* dcrt0.cc (dll_crt0_1): Use GetCommandLineW and convert to current
codepage. * environ.cc (set_file_api_mode): Always set file api to ANSI if not using the OEM codepage. (codepage_init): Allow "utf8" codepage. * fhandler_clipboard.cc (set_clipboard): Convert clipbuf to void and cast as needed. Always convert input to wide char and write CF_UNICODETEXT to clipboard. (fhandler_dev_clipboard::read): Read CF_UNICODETEXT from clipboard and convert to current codepage if CYGWIN_NATIVE format is not available. * fhandler_console.cc: Drop redundant undef. * smallprint.cc (__small_vsprintf): Convert PWCHAR and UNICODE_STRING to current codepage for printing. * strfuncs.cc: Use PWCHAR throughout. (get_cp): Return CP_UTF8 for utf8_cp codepage setting. (sys_wcstombs): Allow NULL target buffer. (sys_wcstombs_alloc): New function. (sys_mbstowcs_alloc): Ditto. * winsup.h (codepage_type): Add utf8_cp. (HEAP_NOTHEAP): Define. (sys_wcstombs_alloc): Declare. (sys_mbstowcs_alloc): Declare.
This commit is contained in:
parent
8e87af7ed0
commit
1597484cb5
|
@ -1,3 +1,28 @@
|
||||||
|
2008-01-31 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* dcrt0.cc (dll_crt0_1): Use GetCommandLineW and convert to current
|
||||||
|
codepage.
|
||||||
|
* environ.cc (set_file_api_mode): Always set file api to ANSI if not
|
||||||
|
using the OEM codepage.
|
||||||
|
(codepage_init): Allow "utf8" codepage.
|
||||||
|
* fhandler_clipboard.cc (set_clipboard): Convert clipbuf to void and
|
||||||
|
cast as needed. Always convert input to wide char and write
|
||||||
|
CF_UNICODETEXT to clipboard.
|
||||||
|
(fhandler_dev_clipboard::read): Read CF_UNICODETEXT from clipboard and
|
||||||
|
convert to current codepage if CYGWIN_NATIVE format is not available.
|
||||||
|
* fhandler_console.cc: Drop redundant undef.
|
||||||
|
* smallprint.cc (__small_vsprintf): Convert PWCHAR and UNICODE_STRING
|
||||||
|
to current codepage for printing.
|
||||||
|
* strfuncs.cc: Use PWCHAR throughout.
|
||||||
|
(get_cp): Return CP_UTF8 for utf8_cp codepage setting.
|
||||||
|
(sys_wcstombs): Allow NULL target buffer.
|
||||||
|
(sys_wcstombs_alloc): New function.
|
||||||
|
(sys_mbstowcs_alloc): Ditto.
|
||||||
|
* winsup.h (codepage_type): Add utf8_cp.
|
||||||
|
(HEAP_NOTHEAP): Define.
|
||||||
|
(sys_wcstombs_alloc): Declare.
|
||||||
|
(sys_mbstowcs_alloc): Declare.
|
||||||
|
|
||||||
2008-01-31 Corinna Vinschen <corinna@vinschen.de>
|
2008-01-31 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* cygheap.h (struct cwdstuff): Add dir member to store cwd handle.
|
* cygheap.h (struct cwdstuff): Add dir member to store cwd handle.
|
||||||
|
|
|
@ -18,6 +18,7 @@ details. */
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <winnls.h>
|
||||||
#include <wingdi.h>
|
#include <wingdi.h>
|
||||||
#include <winuser.h>
|
#include <winuser.h>
|
||||||
#include "sigproc.h"
|
#include "sigproc.h"
|
||||||
|
@ -855,11 +856,10 @@ dll_crt0_1 (void *)
|
||||||
|
|
||||||
if (!__argc)
|
if (!__argc)
|
||||||
{
|
{
|
||||||
char *line = GetCommandLineA ();
|
PWCHAR wline = GetCommandLineW ();
|
||||||
line = strcpy ((char *) alloca (strlen (line) + 1), line);
|
size_t size = sys_wcstombs (NULL, size, wline);
|
||||||
|
char *line = (char *) alloca (size);
|
||||||
if (current_codepage == oem_cp)
|
sys_wcstombs (line, size, wline);
|
||||||
CharToOemA (line, line);
|
|
||||||
|
|
||||||
/* Scan the command line and build argv. Expand wildcards if not
|
/* Scan the command line and build argv. Expand wildcards if not
|
||||||
called from another cygwin process. */
|
called from another cygwin process. */
|
||||||
|
|
|
@ -506,7 +506,7 @@ set_file_api_mode (codepage_type cp)
|
||||||
SetFileApisToOEM ();
|
SetFileApisToOEM ();
|
||||||
debug_printf ("File APIs set to OEM");
|
debug_printf ("File APIs set to OEM");
|
||||||
}
|
}
|
||||||
else if (cp == ansi_cp)
|
else
|
||||||
{
|
{
|
||||||
SetFileApisToANSI ();
|
SetFileApisToANSI ();
|
||||||
debug_printf ("File APIs set to ANSI");
|
debug_printf ("File APIs set to ANSI");
|
||||||
|
@ -520,17 +520,14 @@ codepage_init (const char *buf)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (strcasematch (buf, "oem"))
|
if (strcasematch (buf, "oem"))
|
||||||
{
|
current_codepage = oem_cp;
|
||||||
current_codepage = oem_cp;
|
|
||||||
set_file_api_mode (current_codepage);
|
|
||||||
}
|
|
||||||
else if (strcasematch (buf, "ansi"))
|
else if (strcasematch (buf, "ansi"))
|
||||||
{
|
current_codepage = ansi_cp;
|
||||||
current_codepage = ansi_cp;
|
else if (strcasematch (buf, "utf8"))
|
||||||
set_file_api_mode (current_codepage);
|
current_codepage = utf8_cp;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
debug_printf ("Wrong codepage name: %s", buf);
|
debug_printf ("Wrong codepage name: %s", buf);
|
||||||
|
set_file_api_mode (current_codepage);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -14,7 +14,9 @@ details. */
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <wchar.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <winnls.h>
|
||||||
#include <wingdi.h>
|
#include <wingdi.h>
|
||||||
#include <winuser.h>
|
#include <winuser.h>
|
||||||
#include "cygerrno.h"
|
#include "cygerrno.h"
|
||||||
|
@ -82,7 +84,7 @@ static int
|
||||||
set_clipboard (const void *buf, size_t len)
|
set_clipboard (const void *buf, size_t len)
|
||||||
{
|
{
|
||||||
HGLOBAL hmem;
|
HGLOBAL hmem;
|
||||||
unsigned char *clipbuf;
|
void *clipbuf;
|
||||||
/* Native CYGWIN format */
|
/* Native CYGWIN format */
|
||||||
OpenClipboard (0);
|
OpenClipboard (0);
|
||||||
hmem = GlobalAlloc (GMEM_MOVEABLE, len + sizeof (size_t));
|
hmem = GlobalAlloc (GMEM_MOVEABLE, len + sizeof (size_t));
|
||||||
|
@ -91,8 +93,8 @@ set_clipboard (const void *buf, size_t len)
|
||||||
system_printf ("Couldn't allocate global buffer for write");
|
system_printf ("Couldn't allocate global buffer for write");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
clipbuf = (unsigned char *) GlobalLock (hmem);
|
clipbuf = GlobalLock (hmem);
|
||||||
memcpy (clipbuf + sizeof (size_t), buf, len);
|
memcpy ((unsigned char *) clipbuf + sizeof (size_t), buf, len);
|
||||||
*(size_t *) (clipbuf) = len;
|
*(size_t *) (clipbuf) = len;
|
||||||
GlobalUnlock (hmem);
|
GlobalUnlock (hmem);
|
||||||
EmptyClipboard ();
|
EmptyClipboard ();
|
||||||
|
@ -118,19 +120,24 @@ set_clipboard (const void *buf, size_t len)
|
||||||
/* CF_TEXT/CF_OEMTEXT for copying to wordpad and the like */
|
/* CF_TEXT/CF_OEMTEXT for copying to wordpad and the like */
|
||||||
|
|
||||||
OpenClipboard (0);
|
OpenClipboard (0);
|
||||||
hmem = GlobalAlloc (GMEM_MOVEABLE, len + 2);
|
|
||||||
|
len = MultiByteToWideChar (get_cp (), 0, (const char *) buf, len, NULL, 0);
|
||||||
|
if (!len)
|
||||||
|
{
|
||||||
|
system_printf ("Invalid string");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
hmem = GlobalAlloc (GMEM_MOVEABLE, (len + 1) * sizeof (WCHAR));
|
||||||
if (!hmem)
|
if (!hmem)
|
||||||
{
|
{
|
||||||
system_printf ("Couldn't allocate global buffer for write");
|
system_printf ("Couldn't allocate global buffer for write");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
clipbuf = (unsigned char *) GlobalLock (hmem);
|
clipbuf = GlobalLock (hmem);
|
||||||
memcpy (clipbuf, buf, len);
|
sys_mbstowcs ((PWCHAR) clipbuf, (const char *) buf, len);
|
||||||
*(clipbuf + len) = '\0';
|
*((PWCHAR) clipbuf + len) = L'\0';
|
||||||
*(clipbuf + len + 1) = '\0';
|
|
||||||
GlobalUnlock (hmem);
|
GlobalUnlock (hmem);
|
||||||
if (!SetClipboardData
|
if (!SetClipboardData (CF_UNICODETEXT, hmem))
|
||||||
((current_codepage == ansi_cp ? CF_TEXT : CF_OEMTEXT), hmem))
|
|
||||||
{
|
{
|
||||||
system_printf ("Couldn't write to the clipboard");
|
system_printf ("Couldn't write to the clipboard");
|
||||||
/* FIXME: return an appriate error code &| set_errno(); */
|
/* FIXME: return an appriate error code &| set_errno(); */
|
||||||
|
@ -196,7 +203,7 @@ fhandler_dev_clipboard::read (void *ptr, size_t& len)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
formatlist[0] = cygnativeformat;
|
formatlist[0] = cygnativeformat;
|
||||||
formatlist[1] = current_codepage == ansi_cp ? CF_TEXT : CF_OEMTEXT;
|
formatlist[1] = CF_UNICODETEXT;
|
||||||
OpenClipboard (0);
|
OpenClipboard (0);
|
||||||
if ((format = GetPriorityClipboardFormat (formatlist, 2)) <= 0)
|
if ((format = GetPriorityClipboardFormat (formatlist, 2)) <= 0)
|
||||||
{
|
{
|
||||||
|
@ -222,16 +229,24 @@ fhandler_dev_clipboard::read (void *ptr, size_t& len)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LPSTR lpstr;
|
int wret;
|
||||||
lpstr = (LPSTR) GlobalLock (hglb);
|
PWCHAR buf;
|
||||||
|
buf = (PWCHAR) GlobalLock (hglb);
|
||||||
ret = ((len > (strlen (lpstr) - pos)) ? (strlen (lpstr) - pos)
|
size_t glen = GlobalSize (hglb) / sizeof (WCHAR) - 1;
|
||||||
: len);
|
|
||||||
|
/* This loop is necessary because the number of bytes returned
|
||||||
memcpy (ptr, lpstr + pos, ret);
|
by WideCharToMultiByte does not indicate the number of wide
|
||||||
//ret = snprintf((char *) ptr, len, "%s", lpstr);//+pos);
|
chars used for it, so we could potentially drop wide chars. */
|
||||||
|
if (glen - pos > len)
|
||||||
|
glen = pos + len;
|
||||||
|
while ((wret = sys_wcstombs (NULL, 0, buf + pos, glen - pos))
|
||||||
|
!= -1
|
||||||
|
&& (size_t) wret > len)
|
||||||
|
--glen;
|
||||||
|
ret = sys_wcstombs ((char *) ptr, len, buf + pos, glen - pos);
|
||||||
|
//ret = snprintf((char *) ptr, len, "%s", buf);//+pos);
|
||||||
pos += ret;
|
pos += ret;
|
||||||
if (pos + len - ret >= strlen (lpstr))
|
if (pos + len - ret >= wcslen (buf))
|
||||||
eof = true;
|
eof = true;
|
||||||
GlobalUnlock (hglb);
|
GlobalUnlock (hglb);
|
||||||
}
|
}
|
||||||
|
|
|
@ -527,7 +527,6 @@ fhandler_console::read (void *pv, size_t& buflen)
|
||||||
else if (res == line_edit_input_done)
|
else if (res == line_edit_input_done)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#undef ich
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (buflen)
|
while (buflen)
|
||||||
|
|
|
@ -195,24 +195,17 @@ __small_vsprintf (char *dst, const char *fmt, va_list ap)
|
||||||
us = va_arg (ap, PUNICODE_STRING);
|
us = va_arg (ap, PUNICODE_STRING);
|
||||||
wfillin:
|
wfillin:
|
||||||
{
|
{
|
||||||
ANSI_STRING as = { 0, 0, NULL };
|
char *tmp;
|
||||||
NTSTATUS status;
|
|
||||||
|
|
||||||
if (current_codepage == ansi_cp)
|
if (!sys_wcstombs_alloc (&tmp, PATH_MAX, us->Buffer,
|
||||||
status = RtlUnicodeStringToAnsiString (&as, us, TRUE);
|
us->Length / sizeof (WCHAR)))
|
||||||
else
|
|
||||||
status = RtlUnicodeStringToOemString (&as, us, TRUE);
|
|
||||||
if (!NT_SUCCESS (status))
|
|
||||||
{
|
{
|
||||||
s = "invalid UNICODE_STRING";
|
s = "invalid UNICODE_STRING";
|
||||||
goto fillin;
|
goto fillin;
|
||||||
}
|
}
|
||||||
for (i = 0; i < as.Length; ++i)
|
for (i = 0; *tmp && i < n; i++)
|
||||||
*dst++ = as.Buffer[i];
|
*dst++ = *tmp++;
|
||||||
if (current_codepage == ansi_cp)
|
free (tmp);
|
||||||
RtlFreeAnsiString (&as);
|
|
||||||
else
|
|
||||||
RtlFreeOemString (&as);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -10,28 +10,44 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||||
details. */
|
details. */
|
||||||
|
|
||||||
#include "winsup.h"
|
#include "winsup.h"
|
||||||
|
#include <stdlib.h>
|
||||||
#include <winbase.h>
|
#include <winbase.h>
|
||||||
#include <winnls.h>
|
#include <winnls.h>
|
||||||
#include <ntdll.h>
|
#include <ntdll.h>
|
||||||
|
#include "cygerrno.h"
|
||||||
|
#include "security.h"
|
||||||
|
#include "path.h"
|
||||||
|
#include "fhandler.h"
|
||||||
|
#include "dtable.h"
|
||||||
|
#include "cygheap.h"
|
||||||
|
|
||||||
codepage_type current_codepage = ansi_cp;
|
codepage_type current_codepage = ansi_cp;
|
||||||
|
|
||||||
UINT
|
UINT
|
||||||
get_cp ()
|
get_cp ()
|
||||||
{
|
{
|
||||||
return current_codepage == ansi_cp ? GetACP() : GetOEMCP();
|
switch (current_codepage)
|
||||||
|
{
|
||||||
|
case oem_cp:
|
||||||
|
return GetOEMCP ();
|
||||||
|
case utf8_cp:
|
||||||
|
return CP_UTF8;
|
||||||
|
case ansi_cp:
|
||||||
|
default:
|
||||||
|
return GetACP ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* tlen is always treated as the maximum buffer size, including the '\0'
|
/* tlen is always treated as the maximum buffer size, including the '\0'
|
||||||
character. sys_wcstombs will always return a 0-terminated result, no
|
character. sys_wcstombs will always return a 0-terminated result, no
|
||||||
matter what. */
|
matter what. */
|
||||||
int __stdcall
|
int __stdcall
|
||||||
sys_wcstombs (char *tgt, int tlen, const WCHAR *src, int slen)
|
sys_wcstombs (char *tgt, int tlen, const PWCHAR src, int slen)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = WideCharToMultiByte (get_cp (), 0, src, slen, tgt, tlen, NULL, NULL);
|
ret = WideCharToMultiByte (get_cp (), 0, src, slen, tgt, tlen, NULL, NULL);
|
||||||
if (ret)
|
if (ret && tgt)
|
||||||
{
|
{
|
||||||
ret = (ret < tlen) ? ret : tlen - 1;
|
ret = (ret < tlen) ? ret : tlen - 1;
|
||||||
tgt[ret] = '\0';
|
tgt[ret] = '\0';
|
||||||
|
@ -39,13 +55,60 @@ sys_wcstombs (char *tgt, int tlen, const WCHAR *src, int slen)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allocate a buffer big enough for the string, always including the
|
||||||
|
terminating '\0'. The buffer pointer is returned in *tgt_p, the return
|
||||||
|
value is the number of bytes written to the buffer, as usual.
|
||||||
|
The "type" argument determines where the resulting buffer is stored.
|
||||||
|
It's either one of the cygheap_types values, or it's "HEAP_NOTHEAP".
|
||||||
|
In the latter case the allocation uses simple calloc. */
|
||||||
int __stdcall
|
int __stdcall
|
||||||
sys_mbstowcs (WCHAR *tgt, const char *src, int len)
|
sys_wcstombs_alloc (char **tgt_p, int type, const PWCHAR src, int slen)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = WideCharToMultiByte (get_cp (), 0, src, slen, NULL, 0,NULL, NULL);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
size_t tlen = (slen == -1 ? ret : ret + 1);
|
||||||
|
|
||||||
|
if (type == HEAP_NOTHEAP)
|
||||||
|
*tgt_p = (char *) calloc (tlen, sizeof (char));
|
||||||
|
else
|
||||||
|
*tgt_p = (char *) ccalloc ((cygheap_types) type, tlen, sizeof (char));
|
||||||
|
if (!*tgt_p)
|
||||||
|
return 0;
|
||||||
|
ret = sys_wcstombs (*tgt_p, tlen, src, slen);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __stdcall
|
||||||
|
sys_mbstowcs (PWCHAR tgt, const char *src, int len)
|
||||||
{
|
{
|
||||||
int res = MultiByteToWideChar (get_cp (), 0, src, -1, tgt, len);
|
int res = MultiByteToWideChar (get_cp (), 0, src, -1, tgt, len);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Same as sys_wcstombs_alloc, just backwards. */
|
||||||
|
int __stdcall
|
||||||
|
sys_mbstowcs_alloc (PWCHAR *tgt_p, int type, const char *src)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = MultiByteToWideChar (get_cp (), 0, src, -1, NULL, 0);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
if (type == HEAP_NOTHEAP)
|
||||||
|
*tgt_p = (PWCHAR) calloc (ret, sizeof (WCHAR));
|
||||||
|
else
|
||||||
|
*tgt_p = (PWCHAR) ccalloc ((cygheap_types) type, ret, sizeof (WCHAR));
|
||||||
|
if (!*tgt_p)
|
||||||
|
return 0;
|
||||||
|
ret = sys_mbstowcs (*tgt_p, src, ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static WCHAR hex_wchars[] = L"0123456789abcdef";
|
static WCHAR hex_wchars[] = L"0123456789abcdef";
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
NTSTATUS NTAPI
|
||||||
|
|
|
@ -110,15 +110,23 @@ extern const char case_folded_upper[];
|
||||||
/* The one function we use from winuser.h most of the time */
|
/* The one function we use from winuser.h most of the time */
|
||||||
extern "C" DWORD WINAPI GetLastError (void);
|
extern "C" DWORD WINAPI GetLastError (void);
|
||||||
|
|
||||||
enum codepage_type {ansi_cp, oem_cp};
|
enum codepage_type {ansi_cp, oem_cp, utf8_cp};
|
||||||
extern codepage_type current_codepage;
|
extern codepage_type current_codepage;
|
||||||
|
|
||||||
UINT get_cp ();
|
UINT get_cp ();
|
||||||
|
|
||||||
int __stdcall sys_wcstombs(char *, int, const WCHAR *, int = -1)
|
/* Used as type by sys_wcstombs_alloc and sys_mbstowcs_alloc. For a
|
||||||
|
description see there. */
|
||||||
|
#define HEAP_NOTHEAP -1
|
||||||
|
|
||||||
|
int __stdcall sys_wcstombs (char *, int, const PWCHAR, int = -1)
|
||||||
|
__attribute__ ((regparm(3)));
|
||||||
|
int __stdcall sys_wcstombs_alloc (char **, int, const PWCHAR, int = -1)
|
||||||
__attribute__ ((regparm(3)));
|
__attribute__ ((regparm(3)));
|
||||||
|
|
||||||
int __stdcall sys_mbstowcs(WCHAR *, const char *, int)
|
int __stdcall sys_mbstowcs (PWCHAR, const char *, int)
|
||||||
|
__attribute__ ((regparm(3)));
|
||||||
|
int __stdcall sys_mbstowcs_alloc (PWCHAR *, int, const char *)
|
||||||
__attribute__ ((regparm(3)));
|
__attribute__ ((regparm(3)));
|
||||||
|
|
||||||
/* Used to check if Cygwin DLL is dynamically loaded. */
|
/* Used to check if Cygwin DLL is dynamically loaded. */
|
||||||
|
|
Loading…
Reference in New Issue