Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

#167 UNICODE to CHAR conversion

open
nobody
None
5
2014-03-05
2012-03-12
No

On file "freeglut/src/mswin/freeglut_window_mswin.c", line 100 function "fghWstrFromStr" the following code is wrong, because it not safely converts from UNICODE UTF-16 to the OEM code page ASCII char (it only works for char’s [0; 128] aka [‘NULL’; ‘_’).

You can use these functions to convert safely from UNICODE to ASCII and vice versa:

<--------------------- CODE ------------------------->

// Purpose: Converts an ASCII string to UNICODE
//
// Parameters:
// char *cstrASCII, the C NULL terminated ASCII string to be converted
//
// Return:
// If an error occurred, returns NULL
// else a (wchar_t*) pointer to a NULL terminated C string
// NOTE: You should use "free(retStr)" on the returned buffer, when the string isn't needed
wchar_t* fghWstrFromStr(const char* cstrASCII)
{
// Validate parameters
assert(cstrASCII != NULL);

wchar_t* cstrUNICODE = NULL;
int requiredSize = 0;
int nRet = 0;

# if defined(_WIN32) || defined(_WIN64) || defined(_WIN32_WCE)
// Microsoft Windows
requiredSize = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, cstrASCII, -1, NULL, 0);
# else
// ANSI C/C++
requiredSize = mbstowcs(NULL, cstrASCII, 0);
# endif

if(requiredSize > 0)
{
cstrUNICODE = (wchar_t*)malloc((requiredSize + 1) * sizeof(wchar_t));
if(cstrUNICODE != NULL)
{
cstrUNICODE[requiredSize] = L'\0';
# if defined(_WIN32) || defined(_WIN64) || defined(_WIN32_WCE)
// Microsoft Windows
nRet = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, cstrASCII, -1, cstrUNICODE, requiredSize);
# else
// ANSI C/C++
nRet = mbstowcs(cstrUNICODE, cstrASCII, requiredSize);
# endif

if((nRet == 0) || (nRet > requiredSize))
{
// Error converting string
free((void*)cstrUNICODE);
cstrUNICODE = NULL;
}
}
else
{
// Error allocating memory
cstrUNICODE = NULL;
}
}
else
{
// Error, can't convert
cstrUNICODE = NULL;
}

return cstrUNICODE;
}

// Purpose: Converts an UNICODE string to ASCII
//
// Parameters:
// wchar_t* cstrUNICODE, the C NULL terminated UNICODE string to be converted
//
// Return:
// If an error occurred, returns NULL
// else a (char*) pointer to a NULL terminated C string
// NOTE: You should use "free(retStr)" on the returned buffer, when the string isn't needed
char* fghStrFromWstr (const wchar_t* cstrUNICODE)
{
// Validate parameters
assert(cstrUNICODE != NULL);

char* cstrASCII = NULL;
int requiredSize = 0;
int nRet = 0;

# if defined(_WIN32) || defined(_WIN64) || defined(_WIN32_WCE)
// Microsoft Windows
requiredSize = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_NO_BEST_FIT_CHARS, cstrUNICODE, -1, NULL, 0, NULL, NULL);
# else
// ANSI C/C++
requiredSize = wcstombs(cstrUNICODE, NULL, 0);
# endif

if(requiredSize > 0)
{
cstrASCII = (char*)malloc((requiredSize + 1) * sizeof(char));
if(cstrASCII != NULL)
{
cstrASCII[requiredSize] = '\0';
# if defined(_WIN32) || defined(_WIN64) || defined(_WIN32_WCE)
// Microsoft Windows
nRet = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_NO_BEST_FIT_CHARS, cstrUNICODE, -1, cstrASCII, requiredSize, NULL, NULL);
# else
// ANSI C/C++
nRet = wcstombs(cstrASCII, cstrUNICODE, requiredSize);
# endif

if((nRet == 0) || (nRet > requiredSize))
{
// Error converting string
free((void*)cstrASCII);
cstrASCII = NULL;
}
}
else
{
// Error allocating memory
cstrASCII = NULL;
}
}
else
{
// Error, can't convert
cstrASCII = NULL;
}

return cstrASCII;
}

<--------------------- CODE ------------------------->

Discussion