-
Notifications
You must be signed in to change notification settings - Fork 156
Description
To ensure that these functions are truly international, at least on Windows, it is needed the use of the LCMapStringEx function (https://learn.microsoft.com/en-us/windows/win32/api/winnls/nf-winnls-lcmapstringex).
Declare Function UCase ( ByRef str As Const WString, ByRef locale As Const WString = LOCALE_NAME_USER_DEFAULT, ByVal dwMapFlags AS DWORD = 0) As WString
For example, the Turkish word "karışıklığı" is uppercased by Free Basic's UCase as "KARıŞıKLıĞı" instead of "KARIŞIKLIĞI", and "KARIŞIKLIĞI" is lowercased by Free Basic's LCase to "karişikliği" instead of "karışıklığı". Notice the "ı", that is not an "i".
In my own code 'm using:
#if _WIN32_WINNT = &h0602
' ========================================================================================
' Returns an uppercased version of a string.
' - pwszStr [in]:
' The string to convert. Cannot have a size of 0.
' - pwszLocaleName [in, optional]:
' Pointer to a locale name or one of these pre-defined values:
' LOCALE_NAME_INVARIANT
' LOCALE_NAME_SYSTEM_DEFAULT
' LOCALE_NAME_USER_DEFAULT
' For a table of language culture names see:
' https://msdn.microsoft.com/es-es/library/ee825488(v=cs.20).aspx
' - dwMapFlags [in, optional]:
' Flag specifying the type of transformation to use during string mapping or the type
' of sort key to generate. This parameter can have the following values
' For a complete list see:
' https://msdn.microsoft.com/en-us/library/windows/desktop/dd318702(v=vs.85).aspx
' Return value:
' The uppercased string.
' ========================================================================================
PRIVATE FUNCTION wstrUCase (BYVAL pwszStr AS WSTRING PTR, _
BYVAL pwszLocaleName AS WSTRING PTR = LOCALE_NAME_USER_DEFAULT, _
BYVAL dwMapFlags AS DWORD = 0) AS DWSTRING
' // Check the vailidy of the passed parameters
IF pwszStr = NULL THEN RETURN ""
IF LEN(*pwszStr) = 0 THEN RETURN ""
DIM dwsOut AS DWSTRING = *pwszStr
' // Make sure that LCMAP_LOWERCASE is not being used
dwMapFlags = dwMapFlags AND (NOT LCMAP_LOWERCASE)
' // Make sure that LCMAP_LINGUISTIC_CASING OR LCMAP_UPPERCASE is being used
dwMapFlags OR= LCMAP_LINGUISTIC_CASING OR LCMAP_UPPERCASE
' // Ususally, the length of the converted string will be the same that the one of
' // the input string, so let's try it
DIM cbLen AS LONG = LCMapStringEx(pwszLocaleName, dwMapFlags, pwszStr, LEN(*pwszStr), _
dwsOut, LEN(dwsOut), NULL, NULL, 0)
' // If the output length is bigger than the input one, request the needed length,
' // make the buffer bigger and try it again
IF cbLen = 0 AND GetLastError = ERROR_INSUFFICIENT_BUFFER THEN
cbLen = LCMapStringEx(pwszLocaleName, dwMapFlags, pwszStr, LEN(*pwszStr), NULL, 0, NULL, NULL, 0)
IF cbLen THEN
dwsOut += WSPACE(cbLen)
cbLen = LCMapStringEx(pwszLocaleName, dwMapFlags, pwszStr, LEN(*pwszStr), _
dwsOut, LEN(dwsOut), NULL, NULL, 0)
END IF
END IF
RETURN dwsOut
END FUNCTION
' ========================================================================================
' ========================================================================================
' Returns a lowercased version of a string.
' - pwszStr [in]:
' The string to convert. Cannot have a size of 0.
' - pwszLocaleName [in, optional]:
' Pointer to a locale name or one of these pre-defined values:
' LOCALE_NAME_INVARIANT
' LOCALE_NAME_SYSTEM_DEFAULT
' LOCALE_NAME_USER_DEFAULT
' For a table of language culture names see:
' https://msdn.microsoft.com/es-es/library/ee825488(v=cs.20).aspx
' - dwMapFlags [in, optional]:
' Flag specifying the type of transformation to use during string mapping or the type
' of sort key to generate. This parameter can have the following values
' For a complete list see:
' https://msdn.microsoft.com/en-us/library/windows/desktop/dd318702(v=vs.85).aspx
' Return value:
' The lowercased string.
' ========================================================================================
PRIVATE FUNCTION wstrLCase (BYVAL pwszStr AS WSTRING PTR, _
BYVAL pwszLocaleName AS WSTRING PTR = LOCALE_NAME_USER_DEFAULT, _
BYVAL dwMapFlags AS DWORD = 0) AS DWSTRING
' // Check the vailidy of the passed parameters
IF pwszStr = NULL THEN RETURN ""
IF LEN(*pwszStr) = 0 THEN RETURN ""
DIM dwsOut AS DWSTRING = *pwszStr
' // Make sure that LCMAP_UPPERCASE is not being used
dwMapFlags = dwMapFlags AND (NOT LCMAP_UPPERCASE)
' // Make sure that LCMAP_LINGUISTIC_CASING OR LCMAP_LOWERCASE is being used
dwMapFlags OR= LCMAP_LINGUISTIC_CASING OR LCMAP_LOWERCASE
' // Ususally, the length of the converted string will be the same that the one of
' // the input string, so let's try it
DIM cbLen AS LONG = LCMapStringEx(pwszLocaleName, dwMapFlags, pwszStr, LEN(*pwszStr), _
dwsOut, LEN(dwsOut), NULL, NULL, 0)
' // If the output length is bigger than the input one, request the needed length,
' // make the buffer bigger and try it again
IF cbLen = 0 AND GetLastError = ERROR_INSUFFICIENT_BUFFER THEN
cbLen = LCMapStringEx(pwszLocaleName, dwMapFlags, pwszStr, LEN(*pwszStr), NULL, 0, NULL, NULL, 0)
IF cbLen THEN
dwsOut += WSPACE(cbLen)
cbLen = LCMapStringEx(pwszLocaleName, dwMapFlags, pwszStr, LEN(*pwszStr), _
dwsOut, LEN(dwsOut), NULL, NULL, 0)
END IF
END IF
RETURN dwsOut
END FUNCTION
' ========================================================================================
#endif
And i call them as
wstrUCase("karışıklığı", "tr-TR")
wstrLCase("KARIŞIKLIĞI", "tr-TR")
Of course, DWSTRING, must be changed to other kind of buffer.
"tr-TR" is the locale for Turkey.
Table of Language Culture Names:
https://learn.microsoft.com/en-us/previous-versions/commerce-server/ee825488(v=cs.20)