{-# LINE 1 "System\\Win32\\NLS.hsc" #-}
{-# LANGUAGE Trustworthy #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  System.Win32.NLS
-- Copyright   :  (c) Alastair Reid, 1997-2003
-- License     :  BSD-style (see the file libraries/base/LICENSE)
--
-- Maintainer  :  Esa Ilari Vuokko <ei@vuokko.info>
-- Stability   :  provisional
-- Portability :  portable
--
-- A collection of FFI declarations for interfacing with Win32.
--
-----------------------------------------------------------------------------

module System.Win32.NLS  (
        module System.Win32.NLS,

        -- defined in System.Win32.Types
        LCID, LANGID, SortID, SubLANGID, PrimaryLANGID,
        mAKELCID, lANGIDFROMLCID, sORTIDFROMLCID,
        mAKELANGID, pRIMARYLANGID, sUBLANGID
        ) where

import System.Win32.String (withTStringBufferLen)
import System.Win32.Types
import System.Win32.Utils (trySized)


{-# LINE 32 "System\\Win32\\NLS.hsc" #-}
import Control.Monad (when)
import Data.IORef (modifyIORef, newIORef, readIORef)
import Foreign
import Foreign.C
import Text.Printf (printf)

#include "windows_cconv.h"

-- Somewhere, WINVER and _WIN32_WINNT are being defined as less than 0x0600 -
-- that is, before Windows Vista. Support for Windows XP was dropped in
-- GHC 8.0.1 of May 2016. This forces them to be at least 0x0600.

{-# LINE 47 "System\\Win32\\NLS.hsc" #-}

{-# LINE 51 "System\\Win32\\NLS.hsc" #-}








type NLS_FUNCTION = DWORD

lOCALE_SYSTEM_DEFAULT  :: LCID
lOCALE_SYSTEM_DEFAULT  =  2048
lOCALE_USER_DEFAULT    :: LCID
lOCALE_USER_DEFAULT    =  1024
lOCALE_NEUTRAL         :: LCID
lOCALE_NEUTRAL         =  0

{-# LINE 66 "System\\Win32\\NLS.hsc" #-}

foreign import WINDOWS_CCONV unsafe "windows.h ConvertDefaultLocale"
  convertDefaultLocale :: LCID -> IO LCID

-- ToDo: various enum functions.

type CodePage = UINT

cP_ACP        :: CodePage
cP_ACP        =  0
cP_MACCP      :: CodePage
cP_MACCP      =  2
cP_OEMCP      :: CodePage
cP_OEMCP      =  1

{-# LINE 79 "System\\Win32\\NLS.hsc" #-}

foreign import WINDOWS_CCONV unsafe "windows.h GetACP"
  getACP :: IO CodePage

foreign import WINDOWS_CCONV unsafe "windows.h SetThreadLocale"
  setThreadLocale :: LCID -> IO ()

type LCTYPE = UINT

-- The following locale information constants are excluded from the `enum` list
-- below, for the reason indicated:
-- LOCALE_IDIALINGCODE -- Introduced in Windows 10 but not supported. Synonym
                       -- for LOCALE_ICOUNTRY.
-- LOCALE_INEGATIVEPERCENT -- Introduced in Windows 7 but not supported.
-- LOCALE_IPOSITIVEPERCENT -- Introduced in Windows 7 but not supported.
-- LOCALE_IREADINGLAYOUT -- Introduced in Windows 7 but not supported.
-- LOCALE_SAM -- Introduced by Windows 10 but not supported. Synonyn for
              -- LOCALE_S1159.
-- LOCALE_SENGLISHDISPLAYNAME -- Introduced in Windows 7 but not supported.
-- LOCALE_SIETFLANGUAGE -- Not supported (deprecated from Windows Vista).
-- LOCALE_SNATIVEDISPLAYNAME -- Introduced in Windows 7 but not supported.
-- LOCALE_SNATIVELANGUAGENAME -- Introduced in Windows 7 but not supported.
-- LOCALE_SPERCENT -- Introduced in Windows 7 but not supported.
-- LOCALE_SPM -- Introduced in Windows 10 but not supported. Synonym for
              -- LOCALE_S2359.
-- LOCALE_SSHORTESTAM -- Not supported.
-- LOCALE_SSHORTESTPM -- Not supported.
-- LOCALE_SSHORTTIME -- Introduced in Windows 7 but not supported.

-- The following locale information constant is included in the list below, but
-- note:
-- LOCALE_IINTLCURRDIGITS -- Not supported by Windows 10, use
                          -- LOCALE_ICURRDIGITS.

lOCALE_FONTSIGNATURE  :: LCTYPE
lOCALE_FONTSIGNATURE  =  88
lOCALE_ICALENDARTYPE  :: LCTYPE
lOCALE_ICALENDARTYPE  =  4105
lOCALE_ICENTURY       :: LCTYPE
lOCALE_ICENTURY       =  36
lOCALE_ICOUNTRY       :: LCTYPE
lOCALE_ICOUNTRY       =  5
lOCALE_ICURRDIGITS    :: LCTYPE
lOCALE_ICURRDIGITS    =  25
lOCALE_ICURRENCY      :: LCTYPE
lOCALE_ICURRENCY      =  27
lOCALE_IDATE          :: LCTYPE
lOCALE_IDATE          =  33
lOCALE_IDAYLZERO      :: LCTYPE
lOCALE_IDAYLZERO      =  38
lOCALE_IDEFAULTANSICODEPAGE  :: LCTYPE
lOCALE_IDEFAULTANSICODEPAGE  =  4100
lOCALE_IDEFAULTCODEPAGE  :: LCTYPE
lOCALE_IDEFAULTCODEPAGE  =  11
lOCALE_IDEFAULTCOUNTRY  :: LCTYPE
lOCALE_IDEFAULTCOUNTRY  =  10
lOCALE_IDEFAULTEBCDICCODEPAGE  :: LCTYPE
lOCALE_IDEFAULTEBCDICCODEPAGE  =  4114
lOCALE_IDEFAULTLANGUAGE  :: LCTYPE
lOCALE_IDEFAULTLANGUAGE  =  9
lOCALE_IDEFAULTMACCODEPAGE  :: LCTYPE
lOCALE_IDEFAULTMACCODEPAGE  =  4113
lOCALE_IDIGITS        :: LCTYPE
lOCALE_IDIGITS        =  17
lOCALE_IDIGITSUBSTITUTION  :: LCTYPE
lOCALE_IDIGITSUBSTITUTION  =  4116
lOCALE_IFIRSTDAYOFWEEK  :: LCTYPE
lOCALE_IFIRSTDAYOFWEEK  =  4108
lOCALE_IFIRSTWEEKOFYEAR  :: LCTYPE
lOCALE_IFIRSTWEEKOFYEAR  =  4109
lOCALE_IGEOID         :: LCTYPE
lOCALE_IGEOID         =  91
lOCALE_IINTLCURRDIGITS  :: LCTYPE
lOCALE_IINTLCURRDIGITS  =  26
lOCALE_ILANGUAGE      :: LCTYPE
lOCALE_ILANGUAGE      =  1
lOCALE_ILDATE         :: LCTYPE
lOCALE_ILDATE         =  34
lOCALE_ILZERO         :: LCTYPE
lOCALE_ILZERO         =  18
lOCALE_IMEASURE       :: LCTYPE
lOCALE_IMEASURE       =  13
lOCALE_IMONLZERO      :: LCTYPE
lOCALE_IMONLZERO      =  39
lOCALE_INEGCURR       :: LCTYPE
lOCALE_INEGCURR       =  28
lOCALE_INEGNUMBER     :: LCTYPE
lOCALE_INEGNUMBER     =  4112
lOCALE_INEGSEPBYSPACE  :: LCTYPE
lOCALE_INEGSEPBYSPACE  =  87
lOCALE_INEGSIGNPOSN    :: LCTYPE
lOCALE_INEGSIGNPOSN    =  83
lOCALE_INEGSYMPRECEDES  :: LCTYPE
lOCALE_INEGSYMPRECEDES  =  86
lOCALE_IOPTIONALCALENDAR  :: LCTYPE
lOCALE_IOPTIONALCALENDAR  =  4107
lOCALE_PAPERSIZE      :: LCTYPE
lOCALE_PAPERSIZE      =  4106
lOCALE_IPOSSEPBYSPACE  :: LCTYPE
lOCALE_IPOSSEPBYSPACE  =  85
lOCALE_IPOSSIGNPOSN   :: LCTYPE
lOCALE_IPOSSIGNPOSN   =  82
lOCALE_IPSSYMPRECEDES  :: LCTYPE
lOCALE_IPSSYMPRECEDES  =  84
lOCALE_ITIME          :: LCTYPE
lOCALE_ITIME          =  35
lOCALE_ITIMEMARKPOSN  :: LCTYPE
lOCALE_ITIMEMARKPOSN  =  4101
lOCALE_ITLZERO        :: LCTYPE
lOCALE_ITLZERO        =  37
lOCALE_RETURN_NUMBER  :: LCTYPE
lOCALE_RETURN_NUMBER  =  536870912
lOCALE_S1159          :: LCTYPE
lOCALE_S1159          =  40
lOCALE_S2359          :: LCTYPE
lOCALE_S2359          =  41
lOCALE_SABBREVCTRYNAME  :: LCTYPE
lOCALE_SABBREVCTRYNAME  =  7
lOCALE_SABBREVDAYNAME1  :: LCTYPE
lOCALE_SABBREVDAYNAME1  =  49
lOCALE_SABBREVDAYNAME2  :: LCTYPE
lOCALE_SABBREVDAYNAME2  =  50
lOCALE_SABBREVDAYNAME3  :: LCTYPE
lOCALE_SABBREVDAYNAME3  =  51
lOCALE_SABBREVDAYNAME4  :: LCTYPE
lOCALE_SABBREVDAYNAME4  =  52
lOCALE_SABBREVDAYNAME5  :: LCTYPE
lOCALE_SABBREVDAYNAME5  =  53
lOCALE_SABBREVDAYNAME6  :: LCTYPE
lOCALE_SABBREVDAYNAME6  =  54
lOCALE_SABBREVDAYNAME7  :: LCTYPE
lOCALE_SABBREVDAYNAME7  =  55
lOCALE_SABBREVLANGNAME  :: LCTYPE
lOCALE_SABBREVLANGNAME  =  3
lOCALE_SABBREVMONTHNAME1  :: LCTYPE
lOCALE_SABBREVMONTHNAME1  =  68
lOCALE_SABBREVMONTHNAME2  :: LCTYPE
lOCALE_SABBREVMONTHNAME2  =  69
lOCALE_SABBREVMONTHNAME3  :: LCTYPE
lOCALE_SABBREVMONTHNAME3  =  70
lOCALE_SABBREVMONTHNAME4  :: LCTYPE
lOCALE_SABBREVMONTHNAME4  =  71
lOCALE_SABBREVMONTHNAME5  :: LCTYPE
lOCALE_SABBREVMONTHNAME5  =  72
lOCALE_SABBREVMONTHNAME6  :: LCTYPE
lOCALE_SABBREVMONTHNAME6  =  73
lOCALE_SABBREVMONTHNAME7  :: LCTYPE
lOCALE_SABBREVMONTHNAME7  =  74
lOCALE_SABBREVMONTHNAME8  :: LCTYPE
lOCALE_SABBREVMONTHNAME8  =  75
lOCALE_SABBREVMONTHNAME9  :: LCTYPE
lOCALE_SABBREVMONTHNAME9  =  76
lOCALE_SABBREVMONTHNAME10  :: LCTYPE
lOCALE_SABBREVMONTHNAME10  =  77
lOCALE_SABBREVMONTHNAME11  :: LCTYPE
lOCALE_SABBREVMONTHNAME11  =  78
lOCALE_SABBREVMONTHNAME12  :: LCTYPE
lOCALE_SABBREVMONTHNAME12  =  79
lOCALE_SABBREVMONTHNAME13  :: LCTYPE
lOCALE_SABBREVMONTHNAME13  =  4111
lOCALE_SCONSOLEFALLBACKNAME  :: LCTYPE
lOCALE_SCONSOLEFALLBACKNAME  =  110
lOCALE_SCURRENCY      :: LCTYPE
lOCALE_SCURRENCY      =  20
lOCALE_SDATE          :: LCTYPE
lOCALE_SDATE          =  29
lOCALE_SDAYNAME1      :: LCTYPE
lOCALE_SDAYNAME1      =  42
lOCALE_SDAYNAME2      :: LCTYPE
lOCALE_SDAYNAME2      =  43
lOCALE_SDAYNAME3      :: LCTYPE
lOCALE_SDAYNAME3      =  44
lOCALE_SDAYNAME4      :: LCTYPE
lOCALE_SDAYNAME4      =  45
lOCALE_SDAYNAME5      :: LCTYPE
lOCALE_SDAYNAME5      =  46
lOCALE_SDAYNAME6      :: LCTYPE
lOCALE_SDAYNAME6      =  47
lOCALE_SDAYNAME7      :: LCTYPE
lOCALE_SDAYNAME7      =  48
lOCALE_SDECIMAL       :: LCTYPE
lOCALE_SDECIMAL       =  14
lOCALE_SDURATION      :: LCTYPE
lOCALE_SDURATION      =  93
lOCALE_SENGCURRNAME   :: LCTYPE
lOCALE_SENGCURRNAME   =  4103
lOCALE_SENGLISHCOUNTRYNAME  :: LCTYPE
lOCALE_SENGLISHCOUNTRYNAME  =  4098
lOCALE_SENGLISHLANGUAGENAME  :: LCTYPE
lOCALE_SENGLISHLANGUAGENAME  =  4097
lOCALE_SGROUPING      :: LCTYPE
lOCALE_SGROUPING      =  16
lOCALE_SINTLSYMBOL    :: LCTYPE
lOCALE_SINTLSYMBOL    =  21
lOCALE_SISO3166CTRYNAME  :: LCTYPE
lOCALE_SISO3166CTRYNAME  =  90
lOCALE_SISO3166CTRYNAME2  :: LCTYPE
lOCALE_SISO3166CTRYNAME2  =  104
lOCALE_SISO639LANGNAME  :: LCTYPE
lOCALE_SISO639LANGNAME  =  89
lOCALE_SISO639LANGNAME2  :: LCTYPE
lOCALE_SISO639LANGNAME2  =  103
lOCALE_SKEYBOARDSTOINSTALL  :: LCTYPE
lOCALE_SKEYBOARDSTOINSTALL  =  94
lOCALE_SLIST          :: LCTYPE
lOCALE_SLIST          =  12
lOCALE_SLONGDATE      :: LCTYPE
lOCALE_SLONGDATE      =  32
lOCALE_SMONDECIMALSEP  :: LCTYPE
lOCALE_SMONDECIMALSEP  =  22
lOCALE_SMONGROUPING   :: LCTYPE
lOCALE_SMONGROUPING   =  24
lOCALE_SMONTHNAME1    :: LCTYPE
lOCALE_SMONTHNAME1    =  56
lOCALE_SMONTHNAME2    :: LCTYPE
lOCALE_SMONTHNAME2    =  57
lOCALE_SMONTHNAME3    :: LCTYPE
lOCALE_SMONTHNAME3    =  58
lOCALE_SMONTHNAME4    :: LCTYPE
lOCALE_SMONTHNAME4    =  59
lOCALE_SMONTHNAME5    :: LCTYPE
lOCALE_SMONTHNAME5    =  60
lOCALE_SMONTHNAME6    :: LCTYPE
lOCALE_SMONTHNAME6    =  61
lOCALE_SMONTHNAME7    :: LCTYPE
lOCALE_SMONTHNAME7    =  62
lOCALE_SMONTHNAME8    :: LCTYPE
lOCALE_SMONTHNAME8    =  63
lOCALE_SMONTHNAME9    :: LCTYPE
lOCALE_SMONTHNAME9    =  64
lOCALE_SMONTHNAME10   :: LCTYPE
lOCALE_SMONTHNAME10   =  65
lOCALE_SMONTHNAME11   :: LCTYPE
lOCALE_SMONTHNAME11   =  66
lOCALE_SMONTHNAME12   :: LCTYPE
lOCALE_SMONTHNAME12   =  67
lOCALE_SMONTHNAME13   :: LCTYPE
lOCALE_SMONTHNAME13   =  4110
lOCALE_SMONTHOUSANDSEP  :: LCTYPE
lOCALE_SMONTHOUSANDSEP  =  23
lOCALE_SNAME          :: LCTYPE
lOCALE_SNAME          =  92
lOCALE_SNAN           :: LCTYPE
lOCALE_SNAN           =  105
lOCALE_SNATIVECOUNTRYNAME  :: LCTYPE
lOCALE_SNATIVECOUNTRYNAME  =  8
lOCALE_SNATIVECURRNAME  :: LCTYPE
lOCALE_SNATIVECURRNAME  =  4104
lOCALE_SNATIVEDIGITS  :: LCTYPE
lOCALE_SNATIVEDIGITS  =  19
lOCALE_SNEGATIVESIGN  :: LCTYPE
lOCALE_SNEGATIVESIGN  =  81
lOCALE_SNEGINFINITY   :: LCTYPE
lOCALE_SNEGINFINITY   =  107
lOCALE_SPARENT        :: LCTYPE
lOCALE_SPARENT        =  109
lOCALE_SPOSINFINITY   :: LCTYPE
lOCALE_SPOSINFINITY   =  106
lOCALE_SPOSITIVESIGN  :: LCTYPE
lOCALE_SPOSITIVESIGN  =  80
lOCALE_SSCRIPTS       :: LCTYPE
lOCALE_SSCRIPTS       =  108
lOCALE_SSHORTDATE     :: LCTYPE
lOCALE_SSHORTDATE     =  31
lOCALE_SSHORTESTDAYNAME1  :: LCTYPE
lOCALE_SSHORTESTDAYNAME1  =  96
lOCALE_SSHORTESTDAYNAME2  :: LCTYPE
lOCALE_SSHORTESTDAYNAME2  =  97
lOCALE_SSHORTESTDAYNAME3  :: LCTYPE
lOCALE_SSHORTESTDAYNAME3  =  98
lOCALE_SSHORTESTDAYNAME4  :: LCTYPE
lOCALE_SSHORTESTDAYNAME4  =  99
lOCALE_SSHORTESTDAYNAME5  :: LCTYPE
lOCALE_SSHORTESTDAYNAME5  =  100
lOCALE_SSHORTESTDAYNAME6  :: LCTYPE
lOCALE_SSHORTESTDAYNAME6  =  101
lOCALE_SSHORTESTDAYNAME7  :: LCTYPE
lOCALE_SSHORTESTDAYNAME7  =  102
lOCALE_SSORTNAME      :: LCTYPE
lOCALE_SSORTNAME      =  4115
lOCALE_STHOUSAND      :: LCTYPE
lOCALE_STHOUSAND      =  15
lOCALE_STIME          :: LCTYPE
lOCALE_STIME          =  30
lOCALE_STIMEFORMAT    :: LCTYPE
lOCALE_STIMEFORMAT    =  4099
lOCALE_SYEARMONTH     :: LCTYPE
lOCALE_SYEARMONTH     =  4102

{-# LINE 242 "System\\Win32\\NLS.hsc" #-}

-- |Type representing locale data
data LCData
  -- | Data in the form of a Unicode string.
  = LCTextualData !String
  -- | Data in the form of a number. See 'lOCAL_RETURN_NUMBER' and @LOCAL_I*@
  -- locate information constants.
  | LCNumericData !DWORD
  -- | Data in the fomr of a 'LOCALESIGNATURE'. See 'lOCAL_FONTSIGNATURE' locale
  -- information constant.
  | LCSignatureData !LOCALESIGNATURE
  deriving (Eq, Show)

data LOCALESIGNATURE = LOCALESIGNATURE
  { lsUsb :: !UnicodeSubsetBitfield
  , lsCsbDefault :: !DDWORD
  , lsCsbSupported :: !DDWORD
  } deriving (Eq, Show)

instance Storable LOCALESIGNATURE where
  sizeOf = const (32)
{-# LINE 263 "System\\Win32\\NLS.hsc" #-}
  alignment _ = 4
{-# LINE 264 "System\\Win32\\NLS.hsc" #-}
  peek buf = do
    lsUsb'          <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) buf
{-# LINE 266 "System\\Win32\\NLS.hsc" #-}
    lsCsbDefault'   <- ((\hsc_ptr -> peekByteOff hsc_ptr 16)) buf
{-# LINE 267 "System\\Win32\\NLS.hsc" #-}
    lsCsbSupported' <- ((\hsc_ptr -> peekByteOff hsc_ptr 24)) buf
{-# LINE 268 "System\\Win32\\NLS.hsc" #-}
    return $ LOCALESIGNATURE lsUsb' lsCsbDefault' lsCsbSupported'
  poke buf info = do
    ((\hsc_ptr -> pokeByteOff hsc_ptr 0)) buf (lsUsb info)
{-# LINE 271 "System\\Win32\\NLS.hsc" #-}
    ((\hsc_ptr -> pokeByteOff hsc_ptr 16)) buf (lsCsbDefault info)
{-# LINE 272 "System\\Win32\\NLS.hsc" #-}
    ((\hsc_ptr -> pokeByteOff hsc_ptr 24)) buf (lsCsbSupported info)
{-# LINE 273 "System\\Win32\\NLS.hsc" #-}

-- | Type representing 128-bit Unicode subset bitfields, as the @base@ package
-- does include a module exporting a 128-bit unsigned integer type.
data UnicodeSubsetBitfield = UnicodeSubsetBitfield
  { usbLow :: !DDWORD
  , usbHigh :: !DDWORD
  } deriving (Eq, Show)

instance Storable UnicodeSubsetBitfield where
  sizeOf _ = 2 * sizeOf (undefined :: DDWORD)
  alignment _ = alignment (undefined :: DWORD)
  peek buf = do
    usbLow'  <- (peekByteOff buf 0 :: IO DDWORD)
    usbHigh' <- (peekByteOff buf (sizeOf (undefined :: DDWORD)) :: IO DDWORD)
    return $ UnicodeSubsetBitfield usbLow' usbHigh'
  poke buf info = do
    pokeByteOff buf 0 (usbLow info)
    pokeByteOff buf (sizeOf (undefined :: DDWORD)) (usbHigh info)

getLocaleInfoEx :: Maybe String -> LCTYPE -> IO LCData
getLocaleInfoEx locale ty
  | ty == lOCALE_FONTSIGNATURE =
      getLocaleInfoEx' LCSignatureData localSigCharCount

  | ty .&. lOCALE_RETURN_NUMBER /= 0 =
      getLocaleInfoEx' LCNumericData dWORDCharCount

  | otherwise = maybeWith withTString locale $ \c_locale ->
      LCTextualData <$> trySized cFuncName (c_GetLocaleInfoEx c_locale ty)
 where
  cFuncName = "GetLocaleInfoEx"
  -- See https://docs.microsoft.com/en-us/windows/win32/api/winnls/nf-winnls-getlocaleinfoex
  localSigCharCount = ((32)) `div` ((2))
{-# LINE 306 "System\\Win32\\NLS.hsc" #-}
  dWORDCharCount = ((4)) `div` ((2))
{-# LINE 307 "System\\Win32\\NLS.hsc" #-}

  getLocaleInfoEx' constructor bufSize = maybeWith withTString locale $
    \c_locale -> do
      value <- alloca $ \buf -> do
        _ <- failIfZero cFuncName
          $ c_GetLocaleInfoEx c_locale ty (castPtr buf) bufSize
        peek buf
      return $ constructor value

foreign import WINDOWS_CCONV unsafe "windows.h GetLocaleInfoEx"
  c_GetLocaleInfoEx :: LPCWSTR -> LCTYPE -> LPWSTR -> CInt -> IO CInt

setLocaleInfo :: LCID -> LCTYPE -> String -> IO ()
setLocaleInfo locale ty info =
  withTString info $ \ c_info ->
  failIfFalse_ "SetLocaleInfo" $ c_SetLocaleInfo locale ty c_info
foreign import WINDOWS_CCONV unsafe "windows.h SetLocaleInfoW"
  c_SetLocaleInfo :: LCID -> LCTYPE -> LPCTSTR -> IO Bool

type LCMapFlags = DWORD

lCMAP_BYTEREV               :: LCMapFlags
lCMAP_BYTEREV               =  2048
lCMAP_FULLWIDTH             :: LCMapFlags
lCMAP_FULLWIDTH             =  8388608
lCMAP_HALFWIDTH             :: LCMapFlags
lCMAP_HALFWIDTH             =  4194304
lCMAP_HIRAGANA              :: LCMapFlags
lCMAP_HIRAGANA              =  1048576
lCMAP_KATAKANA              :: LCMapFlags
lCMAP_KATAKANA              =  2097152
lCMAP_LINGUISTIC_CASING     :: LCMapFlags
lCMAP_LINGUISTIC_CASING     =  16777216
lCMAP_LOWERCASE             :: LCMapFlags
lCMAP_LOWERCASE             =  256
lCMAP_SIMPLIFIED_CHINESE    :: LCMapFlags
lCMAP_SIMPLIFIED_CHINESE    =  33554432
lCMAP_SORTKEY               :: LCMapFlags
lCMAP_SORTKEY               =  1024
lCMAP_TRADITIONAL_CHINESE   :: LCMapFlags
lCMAP_TRADITIONAL_CHINESE   =  67108864
lCMAP_UPPERCASE             :: LCMapFlags
lCMAP_UPPERCASE             =  512
lINGUISTIC_IGNORECASE       :: LCMapFlags
lINGUISTIC_IGNORECASE       =  16
lINGUISTIC_IGNOREDIACRITIC  :: LCMapFlags
lINGUISTIC_IGNOREDIACRITIC  =  32
nORM_IGNORECASE             :: LCMapFlags
nORM_IGNORECASE             =  1
nORM_IGNORENONSPACE         :: LCMapFlags
nORM_IGNORENONSPACE         =  2
nORM_IGNOREKANATYPE         :: LCMapFlags
nORM_IGNOREKANATYPE         =  65536
nORM_IGNORESYMBOLS          :: LCMapFlags
nORM_IGNORESYMBOLS          =  4
nORM_IGNOREWIDTH            :: LCMapFlags
nORM_IGNOREWIDTH            =  131072
nORM_LINGUISTIC_CASING      :: LCMapFlags
nORM_LINGUISTIC_CASING      =  134217728
sORT_STRINGSORT             :: LCMapFlags
sORT_STRINGSORT             =  4096

{-# LINE 350 "System\\Win32\\NLS.hsc" #-}

data NLSVERSIONINFOEX = NLSVERSIONINFOEX
  { dwNLSVersionInfoSize :: DWORD
  , dwNLSVersion :: DWORD
  , dwDefinedVersion :: DWORD
  , dwEffectiveId :: DWORD
  , guidCustomVersion :: GUID
  } deriving (Eq, Show)

instance Storable NLSVERSIONINFOEX where
  sizeOf = const (32)
{-# LINE 361 "System\\Win32\\NLS.hsc" #-}
  alignment _ = 4
{-# LINE 362 "System\\Win32\\NLS.hsc" #-}
  peek buf = do
    dwNLSVersionInfoSize' <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) buf
{-# LINE 364 "System\\Win32\\NLS.hsc" #-}
    dwNLSVersion' <- ((\hsc_ptr -> peekByteOff hsc_ptr 4)) buf
{-# LINE 365 "System\\Win32\\NLS.hsc" #-}
    dwDefinedVersion' <- ((\hsc_ptr -> peekByteOff hsc_ptr 8)) buf
{-# LINE 366 "System\\Win32\\NLS.hsc" #-}
    dwEffectiveId' <- ((\hsc_ptr -> peekByteOff hsc_ptr 12)) buf
{-# LINE 367 "System\\Win32\\NLS.hsc" #-}
    guidCustomVersion' <- ((\hsc_ptr -> peekByteOff hsc_ptr 16)) buf
{-# LINE 368 "System\\Win32\\NLS.hsc" #-}
    return $ NLSVERSIONINFOEX dwNLSVersionInfoSize' dwNLSVersion'
               dwDefinedVersion' dwEffectiveId' guidCustomVersion'
  poke buf info = do
    ((\hsc_ptr -> pokeByteOff hsc_ptr 0)) buf
{-# LINE 372 "System\\Win32\\NLS.hsc" #-}
      (dwNLSVersionInfoSize info)
    ((\hsc_ptr -> pokeByteOff hsc_ptr 4)) buf (dwNLSVersion info)
{-# LINE 374 "System\\Win32\\NLS.hsc" #-}
    ((\hsc_ptr -> pokeByteOff hsc_ptr 8)) buf (dwDefinedVersion info)
{-# LINE 375 "System\\Win32\\NLS.hsc" #-}
    ((\hsc_ptr -> pokeByteOff hsc_ptr 12)) buf (dwEffectiveId info)
{-# LINE 376 "System\\Win32\\NLS.hsc" #-}
    ((\hsc_ptr -> pokeByteOff hsc_ptr 16)) buf (guidCustomVersion info)
{-# LINE 377 "System\\Win32\\NLS.hsc" #-}

-- Based on the `UnpackedUUID` type of package `uuid-types`.
data GUID = GUID
  !Word32
  !Word16
  !Word16
  !Word8
  !Word8
  !Word8
  !Word8
  !Word8
  !Word8
  !Word8
  !Word8
  deriving (Eq)

instance Show GUID where
  show (GUID data1 data2 data3 b1 b2 b3 b4 b5 b6 b7 b8) =
    printf "{%.8x-%.4x-%.4x-%.2x%2x-%.2x%.2x%.2x%.2x%.2x%.2x}" data1 data2 data3 b1 b2 b3 b4 b5 b6 b7 b8

instance Storable GUID where
  sizeOf _ = 16
  alignment _ = 4
  peekByteOff p off = GUID
    <$> peekByteOff p off
    <*> peekByteOff p (off + 4)
    <*> peekByteOff p (off + 6)
    <*> peekByteOff p (off + 8)
    <*> peekByteOff p (off + 9)
    <*> peekByteOff p (off + 10)
    <*> peekByteOff p (off + 11)
    <*> peekByteOff p (off + 12)
    <*> peekByteOff p (off + 13)
    <*> peekByteOff p (off + 14)
    <*> peekByteOff p (off + 15)
  pokeByteOff p off (GUID data1 data2 data3 b1 b2 b3 b4 b5 b6 b7 b8) = do
    pokeByteOff p off data1
    pokeByteOff p (off + 4) data2
    pokeByteOff p (off + 6) data3
    pokeByteOff p (off + 8) b1
    pokeByteOff p (off + 9) b2
    pokeByteOff p (off + 10) b3
    pokeByteOff p (off + 11) b4
    pokeByteOff p (off + 12) b5
    pokeByteOff p (off + 13) b6
    pokeByteOff p (off + 14) b7
    pokeByteOff p (off + 15) b8

getNLSVersionEx :: Maybe String -> IO NLSVERSIONINFOEX
getNLSVersionEx locale = maybeWith withTString locale $ \c_locale ->
  with defaultVersionInfo $ \c_versionInfo -> do
    failIfFalse_ "GetNLSVersionEx" $
      c_GetNLSVersionEx function c_locale c_versionInfo
    peek c_versionInfo
 where
  function = 1
{-# LINE 433 "System\\Win32\\NLS.hsc" #-}
  defaultVersionInfo = NLSVERSIONINFOEX
    { dwNLSVersionInfoSize = (32)
{-# LINE 435 "System\\Win32\\NLS.hsc" #-}
    , dwNLSVersion = 0
    , dwDefinedVersion = 0
    , dwEffectiveId = 0
    , guidCustomVersion = GUID 0 0 0 0 0 0 0 0 0 0 0
    }
foreign import WINDOWS_CCONV unsafe "windows.h GetNLSVersionEx"
  c_GetNLSVersionEx :: NLS_FUNCTION
                    -> LPCWSTR
                    -> Ptr NLSVERSIONINFOEX
                    -> IO Bool

lCMapStringEx :: Maybe String
              -> LCMapFlags
              -> String
              -> NLSVERSIONINFOEX
              -> IO String
lCMapStringEx locale flags src versionInfo =
  maybeWith withTString locale $ \c_locale ->
    withTStringLen src $ \(c_src, src_len) ->
      with versionInfo $ \c_versionInfo -> do
        let c_src_len = fromIntegral src_len
            c_func s l = c_LCMapStringEx c_locale
                                         flags
                                         c_src c_src_len
                                         s l
                                         c_versionInfo
                                         nullPtr -- Reserved, must be NULL
                                         0 -- Reserved, must be 0
        trySized "LCMapStringEx" c_func
foreign import WINDOWS_CCONV unsafe "windows.h LCMapStringEx"
  c_LCMapStringEx :: LPCWSTR
                  -> LCMapFlags
                  -> LPCWSTR
                  -> CInt
                  -> LPWSTR
                  -> CInt
                  -> Ptr NLSVERSIONINFOEX
                  -> LPVOID
                  -> LPARAM
                  -> IO CInt

lCMapString :: LCID -> LCMapFlags -> String -> Int -> IO String
lCMapString locale flags src dest_size =
  withTStringLen src $ \ (c_src, src_len) ->
  allocaArray dest_size $ \ c_dest -> do
  _ <- failIfZero "LCMapString" $
    c_LCMapString locale flags c_src src_len c_dest dest_size
  peekTString c_dest
foreign import WINDOWS_CCONV unsafe "windows.h LCMapStringW"
  c_LCMapString :: LCID -> LCMapFlags -> LPCTSTR -> Int -> LPCTSTR -> Int -> IO Int

type LocaleTestFlags = DWORD

lCID_INSTALLED        :: LocaleTestFlags
lCID_INSTALLED        =  1
lCID_SUPPORTED        :: LocaleTestFlags
lCID_SUPPORTED        =  2

{-# LINE 492 "System\\Win32\\NLS.hsc" #-}

isValidLocaleName :: Maybe String -> IO Bool
isValidLocaleName lpLocaleName =
  maybeWith withTString lpLocaleName c_IsValidLocaleName
foreign import WINDOWS_CCONV unsafe "windows.h IsValidLocaleName"
  c_IsValidLocaleName :: LPCWSTR -> IO Bool

foreign import WINDOWS_CCONV unsafe "windows.h IsValidLocale"
  isValidLocale :: LCID -> LocaleTestFlags -> IO Bool

type EnumLocalesFlag = DWORD

-- The following locale enumeration flag constants are excluded from the `enum`
-- list below, for the reason indicated:
-- LOCALE_NEUTRALDATA -- Introduced in Windows 7 but not supported.

lOCALE_ALL              :: EnumLocalesFlag
lOCALE_ALL              =  0
lOCALE_ALTERNATE_SORTS  :: EnumLocalesFlag
lOCALE_ALTERNATE_SORTS  =  4
lOCALE_REPLACEMENT      :: EnumLocalesFlag
lOCALE_REPLACEMENT      =  8
lOCALE_SUPPLEMENTAL     :: EnumLocalesFlag
lOCALE_SUPPLEMENTAL     =  2
lOCALE_WINDOWS          :: EnumLocalesFlag
lOCALE_WINDOWS          =  1

{-# LINE 515 "System\\Win32\\NLS.hsc" #-}

type LOCALE_ENUMPROCEX = LPWSTR -> EnumLocalesFlag -> LPARAM -> IO BOOL
foreign import WINDOWS_CCONV "wrapper"
  mkLOCALE_ENUMPROCEX :: LOCALE_ENUMPROCEX -> IO (FunPtr LOCALE_ENUMPROCEX)

enumSystemLocalesEx :: LOCALE_ENUMPROCEX -> EnumLocalesFlag -> LPARAM -> IO ()
enumSystemLocalesEx callback dwFlags lParam = do
  c_callback <- mkLOCALE_ENUMPROCEX callback
  failIfFalse_ "EnumSystemLocalesEx" $
    c_EnumSystemLocalesEx c_callback dwFlags lParam nullPtr
  freeHaskellFunPtr c_callback
foreign import WINDOWS_CCONV safe "windows.h EnumSystemLocalesEx"
  c_EnumSystemLocalesEx :: (FunPtr LOCALE_ENUMPROCEX)
                        -> DWORD
                        -> LPARAM
                        -> LPVOID
                        -> IO Bool

enumSystemLocalesEx' :: EnumLocalesFlag
                     -> Maybe Bool
                     -- ^ Maybe include (or exclude) replacement locales?
                     -> IO [String]
enumSystemLocalesEx' dwFlags mIsReplacement = do
  store <- newIORef []
  let localeEnumProcEx c_locale arg2 _ = do
        locale <- peekTString c_locale
        case mIsReplacement of
          Nothing -> modifyIORef store (locale:)
          Just isReplacement ->
            when (isReplacement == (arg2 .&. lOCALE_REPLACEMENT /= 0)) $
              modifyIORef store (locale:)
        return True
  enumSystemLocalesEx localeEnumProcEx dwFlags 0
  reverse <$> readIORef store

foreign import WINDOWS_CCONV unsafe "windows.h IsValidCodePage"
  isValidCodePage :: CodePage -> IO Bool

foreign import WINDOWS_CCONV unsafe "windows.h GetUserDefaultLCID"
  getUserDefaultLCID :: LCID

foreign import WINDOWS_CCONV unsafe "windows.h GetUserDefaultLangID"
  getUserDefaultLangID :: LANGID

-- #define LOCALE_NAME_INVARIANT L""
lOCALE_NAME_INVARIANT :: Maybe String
lOCALE_NAME_INVARIANT = Just ""

 -- #define LOCALE_NAME_SYSTEM_DEFAULT L"!x-sys-default-locale"
lOCALE_NAME_SYSTEM_DEFAULT :: Maybe String
lOCALE_NAME_SYSTEM_DEFAULT = Just "!x-sys-default-locale"

 -- #define LOCALE_NAME_USER_DEFAULT NULL
lOCALE_NAME_USER_DEFAULT :: Maybe String
lOCALE_NAME_USER_DEFAULT = Nothing

getUserDefaultLocaleName :: IO String
getUserDefaultLocaleName =
  getDefaultLocaleName "GetUserDefaultLocaleName" c_GetUserDefaultLocaleName
foreign import WINDOWS_CCONV unsafe "windows.h GetUserDefaultLocaleName"
  c_GetUserDefaultLocaleName :: LPWSTR -> CInt -> IO CInt

lOCALE_NAME_MAX_LENGTH  :: CInt
lOCALE_NAME_MAX_LENGTH  =  85

{-# LINE 580 "System\\Win32\\NLS.hsc" #-}

-- |Helper function for use with 'c_GetUserDefaultLocaleName' or
-- 'c_GetSystemDefaultLocaleName'. See 'getUserDefaultLocaleName' and
-- 'getSystemUserDefaultLocaleName'.
getDefaultLocaleName :: String -> (LPWSTR -> CInt -> IO CInt) -> IO String
getDefaultLocaleName cDefaultLocaleFuncName cDefaultLocaleFunc =
  withTStringBufferLen maxLength $ \(buf, len) -> do
    let c_len = fromIntegral len
    c_len' <- failIfZero cDefaultLocaleFuncName $
      cDefaultLocaleFunc buf c_len
    let len' = fromIntegral c_len'
    peekTStringLen (buf, len' - 1) -- Drop final null character
 where
  maxLength = fromIntegral lOCALE_NAME_MAX_LENGTH

foreign import WINDOWS_CCONV unsafe "windows.h GetThreadLocale"
  getThreadLocale :: IO LCID

foreign import WINDOWS_CCONV unsafe "windows.h GetSystemDefaultLCID"
  getSystemDefaultLCID :: LCID

foreign import WINDOWS_CCONV unsafe "windows.h GetSystemDefaultLangID"
  getSystemDefaultLangID :: LANGID

getSystemDefaultLocaleName :: IO String
getSystemDefaultLocaleName =
  getDefaultLocaleName "GetSystemDefaultLocaleName" c_GetSystemDefaultLocaleName
foreign import WINDOWS_CCONV unsafe "windows.h GetSystemDefaultLocaleName"
  c_GetSystemDefaultLocaleName :: LPWSTR -> CInt -> IO CInt

foreign import WINDOWS_CCONV unsafe "windows.h GetOEMCP"
  getOEMCP :: CodePage

lANG_NEUTRAL          :: PrimaryLANGID
lANG_NEUTRAL          =  0
lANG_BULGARIAN        :: PrimaryLANGID
lANG_BULGARIAN        =  2
lANG_CHINESE          :: PrimaryLANGID
lANG_CHINESE          =  4
lANG_CZECH            :: PrimaryLANGID
lANG_CZECH            =  5
lANG_DANISH           :: PrimaryLANGID
lANG_DANISH           =  6
lANG_GERMAN           :: PrimaryLANGID
lANG_GERMAN           =  7
lANG_GREEK            :: PrimaryLANGID
lANG_GREEK            =  8
lANG_ENGLISH          :: PrimaryLANGID
lANG_ENGLISH          =  9
lANG_SPANISH          :: PrimaryLANGID
lANG_SPANISH          =  10
lANG_FINNISH          :: PrimaryLANGID
lANG_FINNISH          =  11
lANG_FRENCH           :: PrimaryLANGID
lANG_FRENCH           =  12
lANG_HUNGARIAN        :: PrimaryLANGID
lANG_HUNGARIAN        =  14
lANG_ICELANDIC        :: PrimaryLANGID
lANG_ICELANDIC        =  15
lANG_ITALIAN          :: PrimaryLANGID
lANG_ITALIAN          =  16
lANG_JAPANESE         :: PrimaryLANGID
lANG_JAPANESE         =  17
lANG_KOREAN           :: PrimaryLANGID
lANG_KOREAN           =  18
lANG_DUTCH            :: PrimaryLANGID
lANG_DUTCH            =  19
lANG_NORWEGIAN        :: PrimaryLANGID
lANG_NORWEGIAN        =  20
lANG_POLISH           :: PrimaryLANGID
lANG_POLISH           =  21
lANG_PORTUGUESE       :: PrimaryLANGID
lANG_PORTUGUESE       =  22
lANG_ROMANIAN         :: PrimaryLANGID
lANG_ROMANIAN         =  24
lANG_RUSSIAN          :: PrimaryLANGID
lANG_RUSSIAN          =  25
lANG_CROATIAN         :: PrimaryLANGID
lANG_CROATIAN         =  26
lANG_SLOVAK           :: PrimaryLANGID
lANG_SLOVAK           =  27
lANG_SWEDISH          :: PrimaryLANGID
lANG_SWEDISH          =  29
lANG_TURKISH          :: PrimaryLANGID
lANG_TURKISH          =  31
lANG_SLOVENIAN        :: PrimaryLANGID
lANG_SLOVENIAN        =  36
lANG_ARABIC           :: PrimaryLANGID
lANG_ARABIC           =  1
lANG_CATALAN          :: PrimaryLANGID
lANG_CATALAN          =  3
lANG_HEBREW           :: PrimaryLANGID
lANG_HEBREW           =  13
lANG_SERBIAN          :: PrimaryLANGID
lANG_SERBIAN          =  26
lANG_ALBANIAN         :: PrimaryLANGID
lANG_ALBANIAN         =  28
lANG_THAI             :: PrimaryLANGID
lANG_THAI             =  30
lANG_URDU             :: PrimaryLANGID
lANG_URDU             =  32
lANG_INDONESIAN       :: PrimaryLANGID
lANG_INDONESIAN       =  33
lANG_BELARUSIAN       :: PrimaryLANGID
lANG_BELARUSIAN       =  35
lANG_ESTONIAN         :: PrimaryLANGID
lANG_ESTONIAN         =  37
lANG_LATVIAN          :: PrimaryLANGID
lANG_LATVIAN          =  38
lANG_LITHUANIAN       :: PrimaryLANGID
lANG_LITHUANIAN       =  39
lANG_FARSI            :: PrimaryLANGID
lANG_FARSI            =  41
lANG_VIETNAMESE       :: PrimaryLANGID
lANG_VIETNAMESE       =  42
lANG_ARMENIAN         :: PrimaryLANGID
lANG_ARMENIAN         =  43
lANG_AZERI            :: PrimaryLANGID
lANG_AZERI            =  44
lANG_BASQUE           :: PrimaryLANGID
lANG_BASQUE           =  45
lANG_MACEDONIAN       :: PrimaryLANGID
lANG_MACEDONIAN       =  47
lANG_AFRIKAANS        :: PrimaryLANGID
lANG_AFRIKAANS        =  54
lANG_GEORGIAN         :: PrimaryLANGID
lANG_GEORGIAN         =  55
lANG_FAEROESE         :: PrimaryLANGID
lANG_FAEROESE         =  56
lANG_HINDI            :: PrimaryLANGID
lANG_HINDI            =  57
lANG_MALAY            :: PrimaryLANGID
lANG_MALAY            =  62
lANG_KAZAK            :: PrimaryLANGID
lANG_KAZAK            =  63
lANG_SWAHILI          :: PrimaryLANGID
lANG_SWAHILI          =  65
lANG_UZBEK            :: PrimaryLANGID
lANG_UZBEK            =  67
lANG_TATAR            :: PrimaryLANGID
lANG_TATAR            =  68
lANG_BENGALI          :: PrimaryLANGID
lANG_BENGALI          =  69
lANG_PUNJABI          :: PrimaryLANGID
lANG_PUNJABI          =  70
lANG_GUJARATI         :: PrimaryLANGID
lANG_GUJARATI         =  71
lANG_ORIYA            :: PrimaryLANGID
lANG_ORIYA            =  72
lANG_TAMIL            :: PrimaryLANGID
lANG_TAMIL            =  73
lANG_TELUGU           :: PrimaryLANGID
lANG_TELUGU           =  74
lANG_KANNADA          :: PrimaryLANGID
lANG_KANNADA          =  75
lANG_MALAYALAM        :: PrimaryLANGID
lANG_MALAYALAM        =  76
lANG_ASSAMESE         :: PrimaryLANGID
lANG_ASSAMESE         =  77
lANG_MARATHI          :: PrimaryLANGID
lANG_MARATHI          =  78
lANG_SANSKRIT         :: PrimaryLANGID
lANG_SANSKRIT         =  79
lANG_KONKANI          :: PrimaryLANGID
lANG_KONKANI          =  87
lANG_MANIPURI         :: PrimaryLANGID
lANG_MANIPURI         =  88
lANG_SINDHI           :: PrimaryLANGID
lANG_SINDHI           =  89
lANG_KASHMIRI         :: PrimaryLANGID
lANG_KASHMIRI         =  96
lANG_NEPALI           :: PrimaryLANGID
lANG_NEPALI           =  97

{-# LINE 685 "System\\Win32\\NLS.hsc" #-}

sORT_DEFAULT          :: SortID
sORT_DEFAULT          =  0
sORT_JAPANESE_XJIS    :: SortID
sORT_JAPANESE_XJIS    =  0
sORT_JAPANESE_UNICODE  :: SortID
sORT_JAPANESE_UNICODE  =  1
sORT_CHINESE_BIG5     :: SortID
sORT_CHINESE_BIG5     =  0
sORT_CHINESE_UNICODE  :: SortID
sORT_CHINESE_UNICODE  =  1
sORT_KOREAN_KSC       :: SortID
sORT_KOREAN_KSC       =  0
sORT_KOREAN_UNICODE   :: SortID
sORT_KOREAN_UNICODE   =  1

{-# LINE 695 "System\\Win32\\NLS.hsc" #-}

sUBLANG_NEUTRAL                       :: SubLANGID
sUBLANG_NEUTRAL                       =  0
sUBLANG_DEFAULT                       :: SubLANGID
sUBLANG_DEFAULT                       =  1
sUBLANG_SYS_DEFAULT                   :: SubLANGID
sUBLANG_SYS_DEFAULT                   =  2
sUBLANG_CHINESE_TRADITIONAL           :: SubLANGID
sUBLANG_CHINESE_TRADITIONAL           =  1
sUBLANG_CHINESE_SIMPLIFIED            :: SubLANGID
sUBLANG_CHINESE_SIMPLIFIED            =  2
sUBLANG_CHINESE_HONGKONG              :: SubLANGID
sUBLANG_CHINESE_HONGKONG              =  3
sUBLANG_CHINESE_SINGAPORE             :: SubLANGID
sUBLANG_CHINESE_SINGAPORE             =  4
sUBLANG_DUTCH                         :: SubLANGID
sUBLANG_DUTCH                         =  1
sUBLANG_DUTCH_BELGIAN                 :: SubLANGID
sUBLANG_DUTCH_BELGIAN                 =  2
sUBLANG_ENGLISH_US                    :: SubLANGID
sUBLANG_ENGLISH_US                    =  1
sUBLANG_ENGLISH_UK                    :: SubLANGID
sUBLANG_ENGLISH_UK                    =  2
sUBLANG_ENGLISH_AUS                   :: SubLANGID
sUBLANG_ENGLISH_AUS                   =  3
sUBLANG_ENGLISH_CAN                   :: SubLANGID
sUBLANG_ENGLISH_CAN                   =  4
sUBLANG_ENGLISH_NZ                    :: SubLANGID
sUBLANG_ENGLISH_NZ                    =  5
sUBLANG_ENGLISH_EIRE                  :: SubLANGID
sUBLANG_ENGLISH_EIRE                  =  6
sUBLANG_FRENCH                        :: SubLANGID
sUBLANG_FRENCH                        =  1
sUBLANG_FRENCH_BELGIAN                :: SubLANGID
sUBLANG_FRENCH_BELGIAN                =  2
sUBLANG_FRENCH_CANADIAN               :: SubLANGID
sUBLANG_FRENCH_CANADIAN               =  3
sUBLANG_FRENCH_SWISS                  :: SubLANGID
sUBLANG_FRENCH_SWISS                  =  4
sUBLANG_GERMAN                        :: SubLANGID
sUBLANG_GERMAN                        =  1
sUBLANG_GERMAN_SWISS                  :: SubLANGID
sUBLANG_GERMAN_SWISS                  =  2
sUBLANG_GERMAN_AUSTRIAN               :: SubLANGID
sUBLANG_GERMAN_AUSTRIAN               =  3
sUBLANG_ITALIAN                       :: SubLANGID
sUBLANG_ITALIAN                       =  1
sUBLANG_ITALIAN_SWISS                 :: SubLANGID
sUBLANG_ITALIAN_SWISS                 =  2
sUBLANG_NORWEGIAN_BOKMAL              :: SubLANGID
sUBLANG_NORWEGIAN_BOKMAL              =  1
sUBLANG_NORWEGIAN_NYNORSK             :: SubLANGID
sUBLANG_NORWEGIAN_NYNORSK             =  2
sUBLANG_PORTUGUESE                    :: SubLANGID
sUBLANG_PORTUGUESE                    =  2
sUBLANG_PORTUGUESE_BRAZILIAN          :: SubLANGID
sUBLANG_PORTUGUESE_BRAZILIAN          =  1
sUBLANG_SPANISH                       :: SubLANGID
sUBLANG_SPANISH                       =  1
sUBLANG_SPANISH_MEXICAN               :: SubLANGID
sUBLANG_SPANISH_MEXICAN               =  2
sUBLANG_SPANISH_MODERN                :: SubLANGID
sUBLANG_SPANISH_MODERN                =  3
sUBLANG_ARABIC_SAUDI_ARABIA           :: SubLANGID
sUBLANG_ARABIC_SAUDI_ARABIA           =  1
sUBLANG_ARABIC_IRAQ                   :: SubLANGID
sUBLANG_ARABIC_IRAQ                   =  2
sUBLANG_ARABIC_EGYPT                  :: SubLANGID
sUBLANG_ARABIC_EGYPT                  =  3
sUBLANG_ARABIC_LIBYA                  :: SubLANGID
sUBLANG_ARABIC_LIBYA                  =  4
sUBLANG_ARABIC_ALGERIA                :: SubLANGID
sUBLANG_ARABIC_ALGERIA                =  5
sUBLANG_ARABIC_MOROCCO                :: SubLANGID
sUBLANG_ARABIC_MOROCCO                =  6
sUBLANG_ARABIC_TUNISIA                :: SubLANGID
sUBLANG_ARABIC_TUNISIA                =  7
sUBLANG_ARABIC_OMAN                   :: SubLANGID
sUBLANG_ARABIC_OMAN                   =  8
sUBLANG_ARABIC_YEMEN                  :: SubLANGID
sUBLANG_ARABIC_YEMEN                  =  9
sUBLANG_ARABIC_SYRIA                  :: SubLANGID
sUBLANG_ARABIC_SYRIA                  =  10
sUBLANG_ARABIC_JORDAN                 :: SubLANGID
sUBLANG_ARABIC_JORDAN                 =  11
sUBLANG_ARABIC_LEBANON                :: SubLANGID
sUBLANG_ARABIC_LEBANON                =  12
sUBLANG_ARABIC_KUWAIT                 :: SubLANGID
sUBLANG_ARABIC_KUWAIT                 =  13
sUBLANG_ARABIC_UAE                    :: SubLANGID
sUBLANG_ARABIC_UAE                    =  14
sUBLANG_ARABIC_BAHRAIN                :: SubLANGID
sUBLANG_ARABIC_BAHRAIN                =  15
sUBLANG_ARABIC_QATAR                  :: SubLANGID
sUBLANG_ARABIC_QATAR                  =  16
sUBLANG_AZERI_CYRILLIC                :: SubLANGID
sUBLANG_AZERI_CYRILLIC                =  2
sUBLANG_AZERI_LATIN                   :: SubLANGID
sUBLANG_AZERI_LATIN                   =  1
sUBLANG_CHINESE_MACAU                 :: SubLANGID
sUBLANG_CHINESE_MACAU                 =  5
sUBLANG_ENGLISH_SOUTH_AFRICA          :: SubLANGID
sUBLANG_ENGLISH_SOUTH_AFRICA          =  7
sUBLANG_ENGLISH_JAMAICA               :: SubLANGID
sUBLANG_ENGLISH_JAMAICA               =  8
sUBLANG_ENGLISH_CARIBBEAN             :: SubLANGID
sUBLANG_ENGLISH_CARIBBEAN             =  9
sUBLANG_ENGLISH_BELIZE                :: SubLANGID
sUBLANG_ENGLISH_BELIZE                =  10
sUBLANG_ENGLISH_TRINIDAD              :: SubLANGID
sUBLANG_ENGLISH_TRINIDAD              =  11
sUBLANG_ENGLISH_PHILIPPINES           :: SubLANGID
sUBLANG_ENGLISH_PHILIPPINES           =  13
sUBLANG_ENGLISH_ZIMBABWE              :: SubLANGID
sUBLANG_ENGLISH_ZIMBABWE              =  12
sUBLANG_FRENCH_LUXEMBOURG             :: SubLANGID
sUBLANG_FRENCH_LUXEMBOURG             =  5
sUBLANG_FRENCH_MONACO                 :: SubLANGID
sUBLANG_FRENCH_MONACO                 =  6
sUBLANG_GERMAN_LUXEMBOURG             :: SubLANGID
sUBLANG_GERMAN_LUXEMBOURG             =  4
sUBLANG_GERMAN_LIECHTENSTEIN          :: SubLANGID
sUBLANG_GERMAN_LIECHTENSTEIN          =  5
sUBLANG_KASHMIRI_INDIA                :: SubLANGID
sUBLANG_KASHMIRI_INDIA                =  2
sUBLANG_KOREAN                        :: SubLANGID
sUBLANG_KOREAN                        =  1
sUBLANG_LITHUANIAN                    :: SubLANGID
sUBLANG_LITHUANIAN                    =  1
sUBLANG_MALAY_MALAYSIA                :: SubLANGID
sUBLANG_MALAY_MALAYSIA                =  1
sUBLANG_MALAY_BRUNEI_DARUSSALAM       :: SubLANGID
sUBLANG_MALAY_BRUNEI_DARUSSALAM       =  2
sUBLANG_NEPALI_INDIA                  :: SubLANGID
sUBLANG_NEPALI_INDIA                  =  2
sUBLANG_SERBIAN_LATIN                 :: SubLANGID
sUBLANG_SERBIAN_LATIN                 =  2
sUBLANG_SERBIAN_CYRILLIC              :: SubLANGID
sUBLANG_SERBIAN_CYRILLIC              =  3
sUBLANG_SPANISH_GUATEMALA             :: SubLANGID
sUBLANG_SPANISH_GUATEMALA             =  4
sUBLANG_SPANISH_COSTA_RICA            :: SubLANGID
sUBLANG_SPANISH_COSTA_RICA            =  5
sUBLANG_SPANISH_PANAMA                :: SubLANGID
sUBLANG_SPANISH_PANAMA                =  6
sUBLANG_SPANISH_DOMINICAN_REPUBLIC    :: SubLANGID
sUBLANG_SPANISH_DOMINICAN_REPUBLIC    =  7
sUBLANG_SPANISH_VENEZUELA             :: SubLANGID
sUBLANG_SPANISH_VENEZUELA             =  8
sUBLANG_SPANISH_COLOMBIA              :: SubLANGID
sUBLANG_SPANISH_COLOMBIA              =  9
sUBLANG_SPANISH_PERU                  :: SubLANGID
sUBLANG_SPANISH_PERU                  =  10
sUBLANG_SPANISH_ARGENTINA             :: SubLANGID
sUBLANG_SPANISH_ARGENTINA             =  11
sUBLANG_SPANISH_ECUADOR               :: SubLANGID
sUBLANG_SPANISH_ECUADOR               =  12
sUBLANG_SPANISH_CHILE                 :: SubLANGID
sUBLANG_SPANISH_CHILE                 =  13
sUBLANG_SPANISH_URUGUAY               :: SubLANGID
sUBLANG_SPANISH_URUGUAY               =  14
sUBLANG_SPANISH_PARAGUAY              :: SubLANGID
sUBLANG_SPANISH_PARAGUAY              =  15
sUBLANG_SPANISH_BOLIVIA               :: SubLANGID
sUBLANG_SPANISH_BOLIVIA               =  16
sUBLANG_SPANISH_EL_SALVADOR           :: SubLANGID
sUBLANG_SPANISH_EL_SALVADOR           =  17
sUBLANG_SPANISH_HONDURAS              :: SubLANGID
sUBLANG_SPANISH_HONDURAS              =  18
sUBLANG_SPANISH_NICARAGUA             :: SubLANGID
sUBLANG_SPANISH_NICARAGUA             =  19
sUBLANG_SPANISH_PUERTO_RICO           :: SubLANGID
sUBLANG_SPANISH_PUERTO_RICO           =  20
sUBLANG_SWEDISH                       :: SubLANGID
sUBLANG_SWEDISH                       =  1
sUBLANG_SWEDISH_FINLAND               :: SubLANGID
sUBLANG_SWEDISH_FINLAND               =  2
sUBLANG_URDU_PAKISTAN                 :: SubLANGID
sUBLANG_URDU_PAKISTAN                 =  1
sUBLANG_URDU_INDIA                    :: SubLANGID
sUBLANG_URDU_INDIA                    =  2
sUBLANG_UZBEK_LATIN                   :: SubLANGID
sUBLANG_UZBEK_LATIN                   =  1
sUBLANG_UZBEK_CYRILLIC                :: SubLANGID
sUBLANG_UZBEK_CYRILLIC                =  2

{-# LINE 790 "System\\Win32\\NLS.hsc" #-}

-- , SUBLANG_LITHUANIAN_CLASSIC (not in mingw-20001111)

-- ----------------------------------------------------------------------------

-- | The `System.IO` input functions (e.g. `getLine`) don't
-- automatically convert to Unicode, so this function is provided to
-- make the conversion from a multibyte string in the given code page
-- to a proper Unicode string.  To get the code page for the console,
-- use `getConsoleCP`.

stringToUnicode :: CodePage -> String -> IO String
stringToUnicode _cp "" = return ""
     -- MultiByteToWideChar doesn't handle empty strings (#1929)
stringToUnicode cp mbstr =
  withCAStringLen mbstr $ \(cstr,len) -> do
    wchars <- failIfZero "MultiByteToWideChar" $ multiByteToWideChar
                cp
                0
                cstr
                (fromIntegral len)
                nullPtr 0
    -- wchars is the length of buffer required
    allocaArray (fromIntegral wchars) $ \cwstr -> do
      wchars' <- failIfZero "MultiByteToWideChar" $ multiByteToWideChar
                cp
                0
                cstr
                (fromIntegral len)
                cwstr wchars
      peekCWStringLen (cwstr,fromIntegral wchars')  -- converts UTF-16 to [Char]

foreign import WINDOWS_CCONV unsafe "MultiByteToWideChar"
  multiByteToWideChar
        :: CodePage
        -> DWORD   -- dwFlags,
        -> LPCSTR  -- lpMultiByteStr
        -> CInt    -- cbMultiByte
        -> LPWSTR  -- lpWideCharStr
        -> CInt    -- cchWideChar
        -> IO CInt