* wincap.h (wincaps::has_always_all_codepages): New element.

* wincap.cc: Implement above element throughout.
	* wchar.h (__sjis_mbtowc): Declare.
	(__eucjp_mbtowc): Ditto.
	(__gbk_mbtowc): Ditto.
	(__kr_mbtowc): Ditto.
	(__big5_mbtowc): Ditto.
	* syscalls.cc (internal_setlocale): Convert to char * function.
	Return parameter by default.  Return NULL if request to use a
	charset can't be satisfied due to missing codepage support in the
	underlying OS.  Fix comment.
	(setlocale): Store original locale.  Restore to original locale if
	internal_setlocale returns NULL.
This commit is contained in:
Corinna Vinschen
2009-07-20 15:44:55 +00:00
parent cb8ee36ae8
commit 20fc2f4936
5 changed files with 71 additions and 6 deletions

View File

@@ -24,6 +24,7 @@ details. */
#define pwrite __FOO_pwrite
#include "winsup.h"
#include "winnls.h"
#include "miscfuncs.h"
#include <sys/stat.h>
#include <sys/vfs.h> /* needed for statfs */
@@ -36,6 +37,7 @@ details. */
#include <sys/uio.h>
#include <ctype.h>
#include <locale.h>
#include <wchar.h>
#include <unistd.h>
#include <sys/wait.h>
#include <rpc.h>
@@ -4031,32 +4033,61 @@ unlinkat (int dirfd, const char *pathname, int flags)
return (flags & AT_REMOVEDIR) ? rmdir (path) : unlink (path);
}
static void
internal_setlocale ()
static char *
internal_setlocale (char *ret)
{
if (*cygheap->locale.charset == 'A')
if (*__locale_charset () == 'A')
{
cygheap->locale.mbtowc = __utf8_mbtowc;
cygheap->locale.wctomb = __utf8_wctomb;
}
else
{
if (!wincap.has_always_all_codepages ())
{
/* Prior to Windows Vista, many codepages are not installed by
default, or can be deinstalled. The following codepages require
that the respective conversion tables are installed into the OS.
So we check if they are installed and if not, setlocale should
fail. */
CPINFO cpi;
UINT cp = 0;
if (__mbtowc == __sjis_mbtowc)
cp = 932;
else if (__mbtowc == __eucjp_mbtowc)
cp = 20932;
else if (__mbtowc == __gbk_mbtowc)
cp = 963;
else if (__mbtowc == __kr_mbtowc)
cp = 949;
else if (__mbtowc == __big5_mbtowc)
cp = 950;
if (cp && !GetCPInfo (cp, &cpi)
&& GetLastError () == ERROR_INVALID_PARAMETER)
return NULL;
}
cygheap->locale.mbtowc = __mbtowc;
cygheap->locale.wctomb = __wctomb;
}
strcpy (cygheap->locale.charset, __locale_charset ());
/* Each setlocale potentially changes the multibyte representation
of the CWD. Therefore we have to rest the CWD's posix path and
of the CWD. Therefore we have to reset the CWD's posix path and
reevaluate the next time it's used. */
/* FIXME: Other buffered paths might be affected as well. */
cygheap->cwd.reset_posix ();
return ret;
}
extern "C" char *
setlocale (int category, const char *locale)
{
char old[(LC_MESSAGES + 1) * (ENCODING_LEN + 1/*"/"*/ + 1)];
if (locale && (category == LC_ALL || category == LC_CTYPE)
&& !wincap.has_always_all_codepages ())
stpcpy (old, _setlocale_r (_REENT, category, NULL));
char *ret = _setlocale_r (_REENT, category, locale);
if (ret && locale && (category == LC_ALL || category == LC_CTYPE))
internal_setlocale ();
if (ret && locale && (category == LC_ALL || category == LC_CTYPE)
&& !(ret = internal_setlocale (ret)))
_setlocale_r (_REENT, category, old);
return ret;
}