gdk/win32/gdkdrawable-win32.c (gdk_win32_draw_text)

2004-07-07  Tor Lillqvist  <tml@iki.fi>

	* gdk/win32/gdkdrawable-win32.c (gdk_win32_draw_text)
	* gdk/win32/gdkfont-win32.c (gdk_text_extents)
	* gdk/win32/gdkproperty-win32.c (find_common_locale,
	gdk_property_change)
	* gdk/win32/gdkselection-win32.c (gdk_selection_convert): Use
	g_utf8_to_utf16() instead of the removed _gdk_utf8_to_ucs2() (see
	below).

	* gdk/win32/gdkglobals-win32.c
	* gdk/win32/gdkmain-win32.c (_gdk_windowing_init)
	* gdk/win3/gdkprivate-win32.h: Add a variable for the TARGETS
	atom. Initialize it. Declare it. Drop the variable for the
	COMPOUND_TEXT atom.

	* gdk/win32/gdkim-win32.c (gdk_wcstombs): Don't return UTF-8. This
	function is supposed to return the string in the locale's charset
	and encoding. Use g_convert().

	(gdk_mbstowcs): Similarily, don't take an UTF-8 string, but a
	string in the locale's charset. Use g_convert().

	(_gdk_ucs2_to_utf8, _gdk_utf8_to_wcs, _gdk_utf8_to_ucs2):
	Delete. The UCS-2 functions didn't handle surrogates anyway. Use
	GLib's UTF-16 functions instead. Windows uses UTF-16.

	* gdk/win32/gdkprivate-win32.h: Remove declarations of the deleted
	functions mentioned above.

	* gdk/win32/gdkproperty-win32.c (gdk_property_change): Use CF_TEXT
	also if the string is of type STRING, i.e. ISO-8859-1, and the
	current codepage is 1252, and contains no C1 chars. Accept
	also UTF8_STRING.

	* gdk/win32/gdkselection-win32.c (_gdk_selection_property_store):
	Mark as static. When storing STRING data, convert to
	Latin-1. (#140537)
	(gdk_selection_owner_set_for_display): Now that STRING is always
	ISO-8859-1, use UTF8_STRING when sending the selection request
	to ourselves.

	(gdk_selection_convert): Handle also UTF8_STRING. (#140537, John
	Ehresman)

	(gdk_text_property_to_text_list_for_display): Make work more like
	X11 version. Do obey the encoding parameter.

	(gdk_string_to_compound_text_for_display,
	gdk_utf8_to_compound_text_for_display): Don't even pretend
	supporting COMPOUND_TEXT.

	(gdk_utf8_to_string_target): Convert to ISO-8859-1, like on X11.

	(sanitize_utf8): Zero-terminate string.
This commit is contained in:
Tor Lillqvist 2004-07-07 00:10:03 +00:00 committed by Tor Lillqvist
parent d1c69ab84e
commit d8b2f46c18
12 changed files with 528 additions and 594 deletions

View File

@ -1,3 +1,59 @@
2004-07-07 Tor Lillqvist <tml@iki.fi>
* gdk/win32/gdkdrawable-win32.c (gdk_win32_draw_text)
* gdk/win32/gdkfont-win32.c (gdk_text_extents)
* gdk/win32/gdkproperty-win32.c (find_common_locale,
gdk_property_change)
* gdk/win32/gdkselection-win32.c (gdk_selection_convert): Use
g_utf8_to_utf16() instead of the removed _gdk_utf8_to_ucs2() (see
below).
* gdk/win32/gdkglobals-win32.c
* gdk/win32/gdkmain-win32.c (_gdk_windowing_init)
* gdk/win3/gdkprivate-win32.h: Add a variable for the TARGETS
atom. Initialize it. Declare it. Drop the variable for the
COMPOUND_TEXT atom.
* gdk/win32/gdkim-win32.c (gdk_wcstombs): Don't return UTF-8. This
function is supposed to return the string in the locale's charset
and encoding. Use g_convert().
(gdk_mbstowcs): Similarily, don't take an UTF-8 string, but a
string in the locale's charset. Use g_convert().
(_gdk_ucs2_to_utf8, _gdk_utf8_to_wcs, _gdk_utf8_to_ucs2):
Delete. The UCS-2 functions didn't handle surrogates anyway. Use
GLib's UTF-16 functions instead. Windows uses UTF-16.
* gdk/win32/gdkprivate-win32.h: Remove declarations of the deleted
functions mentioned above.
* gdk/win32/gdkproperty-win32.c (gdk_property_change): Use CF_TEXT
also if the string is of type STRING, i.e. ISO-8859-1, and the
current codepage is 1252, and contains no C1 chars. Accept
also UTF8_STRING.
* gdk/win32/gdkselection-win32.c (_gdk_selection_property_store):
Mark as static. When storing STRING data, convert to
Latin-1. (#140537)
(gdk_selection_owner_set_for_display): Now that STRING is always
ISO-8859-1, use UTF8_STRING when sending the selection request
to ourselves.
(gdk_selection_convert): Handle also UTF8_STRING. (#140537, John
Ehresman)
(gdk_text_property_to_text_list_for_display): Make work more like
X11 version. Do obey the encoding parameter.
(gdk_string_to_compound_text_for_display,
gdk_utf8_to_compound_text_for_display): Don't even pretend
supporting COMPOUND_TEXT.
(gdk_utf8_to_string_target): Convert to ISO-8859-1, like on X11.
(sanitize_utf8): Zero-terminate string.
2004-07-06 Matthias Clasen <mclasen@redhat.com>
* gtk/stock-icons/Makefile.am: Add stock_file_16.png,

View File

@ -1,3 +1,59 @@
2004-07-07 Tor Lillqvist <tml@iki.fi>
* gdk/win32/gdkdrawable-win32.c (gdk_win32_draw_text)
* gdk/win32/gdkfont-win32.c (gdk_text_extents)
* gdk/win32/gdkproperty-win32.c (find_common_locale,
gdk_property_change)
* gdk/win32/gdkselection-win32.c (gdk_selection_convert): Use
g_utf8_to_utf16() instead of the removed _gdk_utf8_to_ucs2() (see
below).
* gdk/win32/gdkglobals-win32.c
* gdk/win32/gdkmain-win32.c (_gdk_windowing_init)
* gdk/win3/gdkprivate-win32.h: Add a variable for the TARGETS
atom. Initialize it. Declare it. Drop the variable for the
COMPOUND_TEXT atom.
* gdk/win32/gdkim-win32.c (gdk_wcstombs): Don't return UTF-8. This
function is supposed to return the string in the locale's charset
and encoding. Use g_convert().
(gdk_mbstowcs): Similarily, don't take an UTF-8 string, but a
string in the locale's charset. Use g_convert().
(_gdk_ucs2_to_utf8, _gdk_utf8_to_wcs, _gdk_utf8_to_ucs2):
Delete. The UCS-2 functions didn't handle surrogates anyway. Use
GLib's UTF-16 functions instead. Windows uses UTF-16.
* gdk/win32/gdkprivate-win32.h: Remove declarations of the deleted
functions mentioned above.
* gdk/win32/gdkproperty-win32.c (gdk_property_change): Use CF_TEXT
also if the string is of type STRING, i.e. ISO-8859-1, and the
current codepage is 1252, and contains no C1 chars. Accept
also UTF8_STRING.
* gdk/win32/gdkselection-win32.c (_gdk_selection_property_store):
Mark as static. When storing STRING data, convert to
Latin-1. (#140537)
(gdk_selection_owner_set_for_display): Now that STRING is always
ISO-8859-1, use UTF8_STRING when sending the selection request
to ourselves.
(gdk_selection_convert): Handle also UTF8_STRING. (#140537, John
Ehresman)
(gdk_text_property_to_text_list_for_display): Make work more like
X11 version. Do obey the encoding parameter.
(gdk_string_to_compound_text_for_display,
gdk_utf8_to_compound_text_for_display): Don't even pretend
supporting COMPOUND_TEXT.
(gdk_utf8_to_string_target): Convert to ISO-8859-1, like on X11.
(sanitize_utf8): Zero-terminate string.
2004-07-06 Matthias Clasen <mclasen@redhat.com>
* gtk/stock-icons/Makefile.am: Add stock_file_16.png,

View File

@ -1,3 +1,59 @@
2004-07-07 Tor Lillqvist <tml@iki.fi>
* gdk/win32/gdkdrawable-win32.c (gdk_win32_draw_text)
* gdk/win32/gdkfont-win32.c (gdk_text_extents)
* gdk/win32/gdkproperty-win32.c (find_common_locale,
gdk_property_change)
* gdk/win32/gdkselection-win32.c (gdk_selection_convert): Use
g_utf8_to_utf16() instead of the removed _gdk_utf8_to_ucs2() (see
below).
* gdk/win32/gdkglobals-win32.c
* gdk/win32/gdkmain-win32.c (_gdk_windowing_init)
* gdk/win3/gdkprivate-win32.h: Add a variable for the TARGETS
atom. Initialize it. Declare it. Drop the variable for the
COMPOUND_TEXT atom.
* gdk/win32/gdkim-win32.c (gdk_wcstombs): Don't return UTF-8. This
function is supposed to return the string in the locale's charset
and encoding. Use g_convert().
(gdk_mbstowcs): Similarily, don't take an UTF-8 string, but a
string in the locale's charset. Use g_convert().
(_gdk_ucs2_to_utf8, _gdk_utf8_to_wcs, _gdk_utf8_to_ucs2):
Delete. The UCS-2 functions didn't handle surrogates anyway. Use
GLib's UTF-16 functions instead. Windows uses UTF-16.
* gdk/win32/gdkprivate-win32.h: Remove declarations of the deleted
functions mentioned above.
* gdk/win32/gdkproperty-win32.c (gdk_property_change): Use CF_TEXT
also if the string is of type STRING, i.e. ISO-8859-1, and the
current codepage is 1252, and contains no C1 chars. Accept
also UTF8_STRING.
* gdk/win32/gdkselection-win32.c (_gdk_selection_property_store):
Mark as static. When storing STRING data, convert to
Latin-1. (#140537)
(gdk_selection_owner_set_for_display): Now that STRING is always
ISO-8859-1, use UTF8_STRING when sending the selection request
to ourselves.
(gdk_selection_convert): Handle also UTF8_STRING. (#140537, John
Ehresman)
(gdk_text_property_to_text_list_for_display): Make work more like
X11 version. Do obey the encoding parameter.
(gdk_string_to_compound_text_for_display,
gdk_utf8_to_compound_text_for_display): Don't even pretend
supporting COMPOUND_TEXT.
(gdk_utf8_to_string_target): Convert to ISO-8859-1, like on X11.
(sanitize_utf8): Zero-terminate string.
2004-07-06 Matthias Clasen <mclasen@redhat.com>
* gtk/stock-icons/Makefile.am: Add stock_file_16.png,

View File

@ -1,3 +1,59 @@
2004-07-07 Tor Lillqvist <tml@iki.fi>
* gdk/win32/gdkdrawable-win32.c (gdk_win32_draw_text)
* gdk/win32/gdkfont-win32.c (gdk_text_extents)
* gdk/win32/gdkproperty-win32.c (find_common_locale,
gdk_property_change)
* gdk/win32/gdkselection-win32.c (gdk_selection_convert): Use
g_utf8_to_utf16() instead of the removed _gdk_utf8_to_ucs2() (see
below).
* gdk/win32/gdkglobals-win32.c
* gdk/win32/gdkmain-win32.c (_gdk_windowing_init)
* gdk/win3/gdkprivate-win32.h: Add a variable for the TARGETS
atom. Initialize it. Declare it. Drop the variable for the
COMPOUND_TEXT atom.
* gdk/win32/gdkim-win32.c (gdk_wcstombs): Don't return UTF-8. This
function is supposed to return the string in the locale's charset
and encoding. Use g_convert().
(gdk_mbstowcs): Similarily, don't take an UTF-8 string, but a
string in the locale's charset. Use g_convert().
(_gdk_ucs2_to_utf8, _gdk_utf8_to_wcs, _gdk_utf8_to_ucs2):
Delete. The UCS-2 functions didn't handle surrogates anyway. Use
GLib's UTF-16 functions instead. Windows uses UTF-16.
* gdk/win32/gdkprivate-win32.h: Remove declarations of the deleted
functions mentioned above.
* gdk/win32/gdkproperty-win32.c (gdk_property_change): Use CF_TEXT
also if the string is of type STRING, i.e. ISO-8859-1, and the
current codepage is 1252, and contains no C1 chars. Accept
also UTF8_STRING.
* gdk/win32/gdkselection-win32.c (_gdk_selection_property_store):
Mark as static. When storing STRING data, convert to
Latin-1. (#140537)
(gdk_selection_owner_set_for_display): Now that STRING is always
ISO-8859-1, use UTF8_STRING when sending the selection request
to ourselves.
(gdk_selection_convert): Handle also UTF8_STRING. (#140537, John
Ehresman)
(gdk_text_property_to_text_list_for_display): Make work more like
X11 version. Do obey the encoding parameter.
(gdk_string_to_compound_text_for_display,
gdk_utf8_to_compound_text_for_display): Don't even pretend
supporting COMPOUND_TEXT.
(gdk_utf8_to_string_target): Convert to ISO-8859-1, like on X11.
(sanitize_utf8): Zero-terminate string.
2004-07-06 Matthias Clasen <mclasen@redhat.com>
* gtk/stock-icons/Makefile.am: Add stock_file_16.png,

View File

@ -1032,7 +1032,7 @@ gdk_win32_draw_text (GdkDrawable *drawable,
{
const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_FONT;
wchar_t *wcstr, wc;
gint wlen;
glong wlen;
gdk_draw_text_arg arg;
if (text_length == 0)
@ -1058,15 +1058,11 @@ gdk_win32_draw_text (GdkDrawable *drawable,
}
else
{
wcstr = g_new (wchar_t, text_length);
if ((wlen = _gdk_utf8_to_ucs2 (wcstr, text, text_length, text_length)) == -1)
g_warning ("gdk_win32_draw_text: _gdk_utf8_to_ucs2 failed");
else
_gdk_wchar_text_handle (font, wcstr, wlen, gdk_draw_text_handler, &arg);
wcstr = g_utf8_to_utf16 (text, text_length, NULL, &wlen, NULL);
_gdk_wchar_text_handle (font, wcstr, wlen, gdk_draw_text_handler, &arg);
g_free (wcstr);
}
gdk_win32_hdc_release (drawable, gc, mask);
}

View File

@ -1592,8 +1592,8 @@ gdk_text_extents (GdkFont *font,
gint *descent)
{
gdk_text_size_arg arg;
gint wlen;
wchar_t *wcstr;
glong wlen;
wchar_t *wcstr, wc;
g_return_if_fail (font != NULL);
g_return_if_fail (text != NULL);
@ -1617,22 +1617,18 @@ gdk_text_extents (GdkFont *font,
arg.total.cx = arg.total.cy = 0;
wcstr = g_new (wchar_t, text_length);
if (text_length == 1)
{
wcstr[0] = (guchar) text[0];
_gdk_wchar_text_handle (font, wcstr, 1, gdk_text_size_handler, &arg);
wc = (guchar) text[0];
_gdk_wchar_text_handle (font, &wc, 1, gdk_text_size_handler, &arg);
}
else
{
if ((wlen = _gdk_utf8_to_ucs2 (wcstr, text, text_length, text_length)) == -1)
g_warning ("gdk_text_extents: _gdk_utf8_to_ucs2 failed");
else
_gdk_wchar_text_handle (font, wcstr, wlen, gdk_text_size_handler, &arg);
wcstr = g_utf8_to_utf16 (text, text_length, NULL, &wlen, NULL);
_gdk_wchar_text_handle (font, wcstr, wlen, gdk_text_size_handler, &arg);
g_free (wcstr);
}
g_free (wcstr);
/* XXX This is quite bogus */
if (lbearing)
*lbearing = 0;

View File

@ -51,8 +51,8 @@ WORD _cf_rtf;
WORD _cf_utf8_string;
GdkAtom _utf8_string;
GdkAtom _compound_text;
GdkAtom _text_uri_list;
GdkAtom _targets;
GdkAtom _local_dnd;
GdkAtom _gdk_win32_dropfiles;

View File

@ -1,6 +1,6 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
* Copyright (C) 1998-2002 Tor Lillqvist
* Copyright (C) 1998-2004 Tor Lillqvist
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -58,321 +58,35 @@ gdk_set_locale (void)
return g_win32_getlocale ();
}
/*
* gdk_wcstombs
*
* Returns a multi-byte string converted from the specified array
* of wide characters. The string is newly allocated. The array of
* wide characters must be null-terminated. If the conversion is
* failed, it returns NULL.
*
* On Win32, we always use UTF-8.
*/
gchar *
gdk_wcstombs (const GdkWChar *src)
{
gint len;
const GdkWChar *wcp;
guchar *mbstr, *bp;
gchar *utf8;
gchar *retval;
const gchar *charset;
wcp = src;
len = 0;
while (*wcp)
{
const GdkWChar c = *wcp++;
if (c < 0x80)
len += 1;
else if (c < 0x800)
len += 2;
else if (c < 0x10000)
len += 3;
else if (c < 0x200000)
len += 4;
else if (c < 0x4000000)
len += 5;
else
len += 6;
}
mbstr = g_malloc (len + 1);
wcp = src;
bp = mbstr;
while (*wcp)
{
int first;
GdkWChar c = *wcp++;
if (c < 0x80)
{
first = 0;
len = 1;
}
else if (c < 0x800)
{
first = 0xc0;
len = 2;
}
else if (c < 0x10000)
{
first = 0xe0;
len = 3;
}
else if (c < 0x200000)
{
first = 0xf0;
len = 4;
}
else if (c < 0x4000000)
{
first = 0xf8;
len = 5;
}
else
{
first = 0xfc;
len = 6;
}
/* Woo-hoo! */
switch (len)
{
case 6: bp[5] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
case 5: bp[4] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
case 4: bp[3] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
case 3: bp[2] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
case 2: bp[1] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
case 1: bp[0] = c | first;
}
bp += len;
}
*bp = 0;
return mbstr;
g_get_charset (&charset);
return g_convert (src, -1, charset, "UCS-4LE", NULL, NULL, NULL);
}
/* A vesion that converts from wchar_t strings to UTF-8 */
gchar *
_gdk_ucs2_to_utf8 (const wchar_t *src,
gint src_len)
{
gint len;
const wchar_t *wcp;
guchar *mbstr, *bp;
wcp = src;
len = 0;
while (wcp < src + src_len)
{
const wchar_t c = *wcp++;
if (c < 0x80)
len += 1;
else if (c < 0x800)
len += 2;
else
len += 3;
}
mbstr = g_malloc (len + 1);
wcp = src;
bp = mbstr;
while (wcp < src + src_len)
{
int first;
wchar_t c = *wcp++;
if (c < 0x80)
{
first = 0;
len = 1;
}
else if (c < 0x800)
{
first = 0xc0;
len = 2;
}
else
{
first = 0xe0;
len = 3;
}
/* Woo-hoo! */
switch (len)
{
case 3: bp[2] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
case 2: bp[1] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
case 1: bp[0] = c | first;
}
bp += len;
}
*bp = 0;
return mbstr;
}
/* Convert from UTF-8 to GdkWChar */
gint
_gdk_utf8_to_wcs (GdkWChar *dest,
const gchar *src,
gint src_len,
gint dest_max)
{
guchar *cp, *end;
gint n;
cp = (guchar *) src;
end = cp + src_len;
n = 0;
while (cp != end && dest != dest + dest_max)
{
gint i, mask = 0, len;
guchar c = *cp;
if (c < 0x80)
{
len = 1;
mask = 0x7f;
}
else if ((c & 0xe0) == 0xc0)
{
len = 2;
mask = 0x1f;
}
else if ((c & 0xf0) == 0xe0)
{
len = 3;
mask = 0x0f;
}
else if ((c & 0xf8) == 0xf0)
{
len = 4;
mask = 0x07;
}
else if ((c & 0xfc) == 0xf8)
{
len = 5;
mask = 0x03;
}
else if ((c & 0xfc) == 0xfc)
{
len = 6;
mask = 0x01;
}
else
return -1;
if (cp + len > end)
return -1;
*dest = (cp[0] & mask);
for (i = 1; i < len; i++)
{
if ((cp[i] & 0xc0) != 0x80)
return -1;
*dest <<= 6;
*dest |= (cp[i] & 0x3f);
}
if (*dest == -1)
return -1;
cp += len;
dest++;
n++;
}
if (cp != end)
return -1;
return n;
}
/*
* gdk_mbstowcs
*
* Converts the specified string into GDK wide characters, and,
* returns the number of wide characters written. The string 'src'
* must be null-terminated. If the conversion is failed, it returns
* -1.
*
* On Win32, the string is assumed to be in UTF-8. Also note that
* GdkWChar is 32 bits, while wchar_t, and the wide characters the
* Windows API uses, are 16 bits!
*/
gint
gdk_mbstowcs (GdkWChar *dest,
const gchar *src,
gint dest_max)
{
return _gdk_utf8_to_wcs (dest, src, strlen (src), dest_max);
}
/* A version that converts to a wchar_t string */
gint
_gdk_utf8_to_ucs2 (wchar_t *dest,
const gchar *src,
gint src_len,
gint dest_max)
{
wchar_t *wcp;
guchar *cp, *end;
gint n;
wcp = dest;
cp = (guchar *) src;
end = cp + src_len;
n = 0;
while (cp != end && wcp != dest + dest_max)
{
gint i, mask = 0, len;
guchar c = *cp;
if (c < 0x80)
{
len = 1;
mask = 0x7f;
}
else if ((c & 0xe0) == 0xc0)
{
len = 2;
mask = 0x1f;
}
else if ((c & 0xf0) == 0xe0)
{
len = 3;
mask = 0x0f;
}
else /* Other lengths are not possible with 16-bit wchar_t! */
return -1;
if (cp + len > end)
return -1;
*wcp = (cp[0] & mask);
for (i = 1; i < len; i++)
{
if ((cp[i] & 0xc0) != 0x80)
return -1;
*wcp <<= 6;
*wcp |= (cp[i] & 0x3f);
}
if (*wcp == 0xFFFF)
return -1;
cp += len;
wcp++;
n++;
}
if (cp != end)
return -1;
return n;
gint retval;
gsize nwritten;
gint n_ucs4;
gunichar *ucs4;
const gchar *charset;
g_get_charset (&charset);
ucs4 = g_convert (src, -1, "UCS-4LE", charset, NULL, &nwritten, NULL);
n_ucs4 = nwritten * sizeof (GdkWChar);
retval = MIN (dest_max, n_ucs4);
memmove (dest, ucs4, retval * sizeof (GdkWChar));
g_free (ucs4);
return retval;
}

View File

@ -115,8 +115,8 @@ _gdk_windowing_init (gint *argc,
_cf_utf8_string = RegisterClipboardFormat ("UTF8_STRING");
_utf8_string = gdk_atom_intern ("UTF8_STRING", FALSE);
_compound_text = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
_text_uri_list = gdk_atom_intern ("text/uri-list", FALSE);
_targets = gdk_atom_intern ("TARGETS", FALSE);
_local_dnd = gdk_atom_intern ("LocalDndSelection", FALSE);
_gdk_win32_dropfiles = gdk_atom_intern ("DROPFILES_DND", FALSE);

View File

@ -363,24 +363,10 @@ void _gdk_win32_adjust_client_rect (GdkWindow *window,
void _gdk_win32_get_adjusted_client_rect (GdkWindow *window,
RECT *RECT);
void _gdk_selection_property_store (GdkWindow *owner,
GdkAtom type,
gint format,
guchar *data,
gint length);
void _gdk_selection_property_delete (GdkWindow *);
void _gdk_dropfiles_store (gchar *data);
gint _gdk_utf8_to_ucs2 (wchar_t *dest,
const gchar *src,
gint src_len,
gint dest_max);
gchar *_gdk_ucs2_to_utf8 (const wchar_t *src,
gint src_len);
void _gdk_wchar_text_handle (GdkFont *font,
const wchar_t *wcstr,
int wclen,
@ -491,6 +477,7 @@ extern WORD _cf_utf8_string;
extern GdkAtom _utf8_string;
extern GdkAtom _compound_text;
extern GdkAtom _text_uri_list;
extern GdkAtom _targets;
/* DND selections */
extern GdkAtom _local_dnd;

View File

@ -198,12 +198,10 @@ find_common_locale (const guchar *data,
* bytes for each Unicode char should be enough, Windows code pages
* are either single- or double-byte.
*/
*bufp = g_malloc ((nchars+1) * 2);
wcs = g_new (wchar_t, nchars+1);
*bufp = g_malloc ((nchars+1)*2);
/* Convert to Windows wide chars into temp buf */
_gdk_utf8_to_ucs2 (wcs, data, nelements, nchars);
wcs[nchars] = 0;
wcs = g_utf8_to_utf16 (data, nelements, NULL, NULL, NULL);
/* For each code page that is the default for an installed locale: */
for (i = 0; i < G_N_ELEMENTS (locales); i++)
@ -254,7 +252,8 @@ gdk_property_change (GdkWindow *window,
gchar *prop_name, *type_name;
guchar *ucptr, *buf = NULL;
wchar_t *wcptr;
enum { PLAIN_ASCII, UNICODE_TEXT, SINGLE_LOCALE, RICH_TEXT } method;
glong wclen;
enum { SYSTEM_CODEPAGE, UNICODE_TEXT, SINGLE_LOCALE, RICH_TEXT } method;
gboolean ok = TRUE;
g_return_if_fail (window != NULL);
@ -279,7 +278,8 @@ gdk_property_change (GdkWindow *window,
g_free (type_name)));
if (property == _gdk_selection_property
&& type == GDK_TARGET_STRING
&& ((type == GDK_TARGET_STRING && GetACP () == 1252) ||
type == _utf8_string)
&& format == 8
&& mode == GDK_PROP_MODE_REPLACE)
{
@ -289,22 +289,31 @@ gdk_property_change (GdkWindow *window,
return;
}
/* Check if only ASCII */
for (i = 0; i < nelements; i++)
if (data[i] >= 0200)
break;
if (type == _utf8_string)
{
/* Check if only ASCII */
for (i = 0; i < nelements; i++)
if (data[i] >= 0200)
break;
}
else /* if (type == GDK_TARGET_STRING) */
{
/* Check that no 0200..0240 chars present, as they
* differ between ISO-8859-1 and CP1252.
*/
for (i = 0; i < nelements; i++)
if (data[i] >= 0200 && data[i] < 0240)
break;
}
nchars = g_utf8_strlen (data, nelements);
if (i == nelements)
nchars = nelements;
else
nchars = g_utf8_strlen (data, nelements);
GDK_NOTE (DND, g_print ("...nchars:%d\n", nchars));
if (i == nelements)
{
/* If only ASCII, use CF_TEXT and the data as such. */
method = PLAIN_ASCII;
/* If UTF-8 and only ASCII, or if STRING (ISO-8859-1) and
* system codepage is CP1252, use CF_TEXT and the data as
* such.
*/
method = SYSTEM_CODEPAGE;
size = nelements;
for (i = 0; i < nelements; i++)
if (data[i] == '\n')
@ -314,9 +323,15 @@ gdk_property_change (GdkWindow *window,
}
else if (IS_WIN_NT ())
{
/* On NT, use CF_UNICODETEXT if any non-ASCII char present */
/* On NT, use CF_UNICODETEXT if any non-system codepage char
* present.
*/
method = UNICODE_TEXT;
size = (nchars + 1) * 2;
wcptr = g_utf8_to_utf16 (data, nelements, NULL, &wclen, NULL);
wclen++; /* Terminating 0 */
size = wclen * 2;
GDK_NOTE (DND, g_print ("...as Unicode\n"));
}
else if (find_common_locale (data, nelements, nchars, &lcid, &buf, &size))
@ -347,7 +362,7 @@ gdk_property_change (GdkWindow *window,
rtf = g_string_append_c (rtf, *p);
p++;
}
else if (*p < 0200)
else if (*p < 0200 && *p >= ' ')
{
rtf = g_string_append_c (rtf, *p);
p++;
@ -388,7 +403,7 @@ gdk_property_change (GdkWindow *window,
switch (method)
{
case PLAIN_ASCII:
case SYSTEM_CODEPAGE:
cf = CF_TEXT;
for (i = 0; i < nelements; i++)
{
@ -401,10 +416,8 @@ gdk_property_change (GdkWindow *window,
case UNICODE_TEXT:
cf = CF_UNICODETEXT;
wcptr = (wchar_t *) ucptr;
if (_gdk_utf8_to_ucs2 (wcptr, data, nelements, nchars) == -1)
g_warning ("_gdk_utf8_to_ucs2() failed");
wcptr[nchars] = 0;
memmove (ucptr, wcptr, size);
g_free (wcptr);
break;
case SINGLE_LOCALE:

View File

@ -41,7 +41,7 @@
typedef struct {
guchar *data;
gint length;
gsize length;
gint format;
GdkAtom type;
} GdkSelProp;
@ -62,7 +62,73 @@ _gdk_win32_selection_init (void)
sel_owner_table = g_hash_table_new (NULL, NULL);
}
void
/* The specifications for COMPOUND_TEXT and STRING specify that C0 and
* C1 are not allowed except for \n and \t, however the X conversions
* routines for COMPOUND_TEXT only enforce this in one direction,
* causing cut-and-paste of \r and \r\n separated text to fail.
* This routine strips out all non-allowed C0 and C1 characters
* from the input string and also canonicalizes \r, and \r\n to \n
*/
static gchar *
sanitize_utf8 (const gchar *src,
gint length)
{
GString *result = g_string_sized_new (length + 1);
const gchar *p = src;
const gchar *endp = src + length;
while (p < endp)
{
if (*p == '\r')
{
p++;
if (*p == '\n')
p++;
g_string_append_c (result, '\n');
}
else
{
gunichar ch = g_utf8_get_char (p);
char buf[7];
gint buflen;
if (!((ch < 0x20 && ch != '\t' && ch != '\n') || (ch >= 0x7f && ch < 0xa0)))
{
buflen = g_unichar_to_utf8 (ch, buf);
g_string_append_len (result, buf, buflen);
}
p = g_utf8_next_char (p);
}
}
g_string_append_c (result, '\0');
return g_string_free (result, FALSE);
}
static gchar *
_gdk_utf8_to_string_target_internal (const gchar *str,
gint length)
{
GError *error = NULL;
gchar *tmp_str = sanitize_utf8 (str, length);
gchar *result = g_convert_with_fallback (tmp_str, -1,
"ISO-8859-1", "UTF-8",
NULL, NULL, NULL, &error);
if (!result)
{
g_warning ("Error converting from UTF-8 to STRING: %s",
error->message);
g_error_free (error);
}
g_free (tmp_str);
return result;
}
static void
_gdk_selection_property_store (GdkWindow *owner,
GdkAtom type,
gint format,
@ -78,8 +144,27 @@ _gdk_selection_property_store (GdkWindow *owner,
g_hash_table_remove (sel_prop_table, GDK_WINDOW_HWND (owner));
}
prop = g_new (GdkSelProp, 1);
prop->data = data;
prop->length = length;
if (type == GDK_TARGET_STRING)
{
/* We know that data is UTF-8 */
prop->data = _gdk_utf8_to_string_target_internal (data, length);
g_free (data);
if (!prop->data)
{
g_free (prop);
return;
}
else
prop->length = strlen (prop->data + 1);
}
else
{
prop->data = data;
prop->length = length;
}
prop->format = format;
prop->type = type;
g_hash_table_insert (sel_prop_table, GDK_WINDOW_HWND (owner), prop);
@ -120,7 +205,8 @@ gdk_selection_owner_set_for_display (GdkDisplay *display,
GdkEvent tmp_event;
gchar *sel_name;
g_return_val_if_fail (display == gdk_display_get_default (), FALSE);
g_return_val_if_fail (display == _gdk_display, FALSE);
g_return_val_if_fail (selection != GDK_NONE, FALSE);
GDK_NOTE (DND,
(sel_name = gdk_atom_name (selection),
@ -176,7 +262,7 @@ gdk_selection_owner_set_for_display (GdkDisplay *display,
tmp_event.selection.window = owner;
tmp_event.selection.send_event = FALSE;
tmp_event.selection.selection = selection;
tmp_event.selection.target = GDK_TARGET_STRING;
tmp_event.selection.target = _utf8_string;
tmp_event.selection.property = _gdk_selection_property;
tmp_event.selection.requestor = (guint32) hwnd;
tmp_event.selection.time = time;
@ -194,12 +280,13 @@ gdk_selection_owner_get_for_display (GdkDisplay *display,
GdkWindow *window;
gchar *sel_name;
g_return_val_if_fail (display == gdk_display_get_default (), NULL);
g_return_val_if_fail (display == _gdk_display, NULL);
g_return_val_if_fail (selection != GDK_NONE, NULL);
/* Return NULL for CLIPBOARD, because otherwise cut&paste
* inside the same application doesn't work. We must pretend to gtk
* that we don't have the selection, so that we always fetch it from
* the Windows clipboard. See also comments in
/* Return NULL for CLIPBOARD, because otherwise cut&paste inside the
* same application doesn't work. We must pretend to gtk that we
* don't have the selection, so that we always fetch it from the
* Windows clipboard. See also comments in
* gdk_selection_send_notify().
*/
if (selection == GDK_SELECTION_CLIPBOARD)
@ -247,8 +334,11 @@ gdk_selection_convert (GdkWindow *requestor,
HGLOBAL hdata;
GdkAtom property = _gdk_selection_property;
gchar *sel_name, *tgt_name;
GError *error = NULL;
g_return_if_fail (selection != GDK_NONE);
g_return_if_fail (requestor != NULL);
if (GDK_WINDOW_DESTROYED (requestor))
return;
@ -262,8 +352,7 @@ gdk_selection_convert (GdkWindow *requestor,
g_free (sel_name),
g_free (tgt_name)));
if (selection == GDK_SELECTION_CLIPBOARD &&
target == gdk_atom_intern ("TARGETS", FALSE))
if (selection == GDK_SELECTION_CLIPBOARD && target == _targets)
{
/* He wants to know what formats are on the clipboard. If there
* is some kind of text, tell him so.
@ -276,7 +365,7 @@ gdk_selection_convert (GdkWindow *requestor,
IsClipboardFormatAvailable (CF_TEXT))
{
GdkAtom *data = g_new (GdkAtom, 1);
*data = GDK_TARGET_STRING;
*data = _utf8_string;
_gdk_selection_property_store (requestor, GDK_SELECTION_TYPE_ATOM,
32, (guchar *) data, 1 * sizeof (GdkAtom));
}
@ -286,36 +375,36 @@ gdk_selection_convert (GdkWindow *requestor,
API_CALL (CloseClipboard, ());
}
else if (selection == GDK_SELECTION_CLIPBOARD &&
(target == _compound_text ||
target == GDK_TARGET_STRING))
(target == GDK_TARGET_STRING ||
target == _utf8_string))
{
/* Converting the CLIPBOARD selection means he wants the
* contents of the clipboard. Get the clipboard data,
* and store it for later.
* contents of the clipboard. Get the clipboard data, and store
* it for later.
*/
if (!API_CALL (OpenClipboard, (GDK_WINDOW_HWND (requestor))))
return;
/* Try various formats. First the simplest, CF_UNICODETEXT. */
if ((hdata = GetClipboardData (CF_UNICODETEXT)) != NULL)
if (IS_WIN_NT () && (hdata = GetClipboardData (CF_UNICODETEXT)) != NULL)
{
wchar_t *ptr, *wcs, *p, *q;
guchar *data;
gint length, wclen;
glong length, wclen;
if ((ptr = GlobalLock (hdata)) != NULL)
{
length = GlobalSize (hdata);
GDK_NOTE (DND, g_print ("...CF_UNICODETEXT: %d bytes\n",
GDK_NOTE (DND, g_print ("...CF_UNICODETEXT: %ld bytes\n",
length));
/* Strip out \r */
wcs = g_new (wchar_t, (length + 1) * 2);
wcs = g_new (wchar_t, length / 2 + 1);
p = ptr;
q = wcs;
wclen = 0;
while (*p)
while (p < ptr + length / 2)
{
if (*p != '\r')
{
@ -325,11 +414,16 @@ gdk_selection_convert (GdkWindow *requestor,
p++;
}
data = _gdk_ucs2_to_utf8 (wcs, wclen);
data = g_utf16_to_utf8 (wcs, wclen, NULL, NULL, &error);
g_free (wcs);
_gdk_selection_property_store (requestor, target, 8,
data, strlen (data) + 1);
if (!data)
{
g_error_free (error);
}
else
_gdk_selection_property_store (requestor, target, 8,
data, strlen (data) + 1);
GlobalUnlock (hdata);
}
}
@ -347,7 +441,7 @@ gdk_selection_convert (GdkWindow *requestor,
length, ptr));
_gdk_selection_property_store (requestor, target, 8,
g_strdup (ptr), strlen (ptr) + 1);
g_memdup (ptr, length), length);
GlobalUnlock (hdata);
}
}
@ -361,13 +455,13 @@ gdk_selection_convert (GdkWindow *requestor,
UINT cp = CP_ACP;
wchar_t *wcs, *wcs2, *p, *q;
guchar *ptr, *data;
gint length, wclen;
glong length, wclen, wclen2;
if ((ptr = GlobalLock (hdata)) != NULL)
{
length = GlobalSize (hdata);
GDK_NOTE (DND, g_print ("...CF_TEXT: %d bytes: %.10s\n",
GDK_NOTE (DND, g_print ("...CF_TEXT: %ld bytes: %.10s\n",
length, ptr));
if ((hlcid = GetClipboardData (CF_LOCALE)) != NULL)
@ -385,30 +479,33 @@ gdk_selection_convert (GdkWindow *requestor,
}
wcs = g_new (wchar_t, length + 1);
wclen = MultiByteToWideChar (cp, 0, ptr, -1,
wclen = MultiByteToWideChar (cp, 0, ptr, length,
wcs, length + 1);
/* Strip out \r */
wcs2 = g_new (wchar_t, wclen);
p = wcs;
q = wcs2;
wclen = 0;
while (*p)
wclen2 = 0;
while (p < wcs + wclen)
{
if (*p != '\r')
{
*q++ = *p;
wclen++;
wclen2++;
}
p++;
}
g_free (wcs);
data = _gdk_ucs2_to_utf8 (wcs2, wclen);
data = g_utf16_to_utf8 (wcs2, wclen2, NULL, &length, &error);
g_free (wcs2);
_gdk_selection_property_store (requestor, target, 8,
data, strlen (data) + 1);
if (!data)
g_error_free (error);
else
_gdk_selection_property_store (requestor, target, 8,
data, length + 1);
GlobalUnlock (hdata);
}
}
@ -498,16 +595,16 @@ _gdk_selection_property_delete (GdkWindow *window)
void
gdk_selection_send_notify_for_display (GdkDisplay *display,
guint32 requestor,
GdkAtom selection,
GdkAtom target,
GdkAtom property,
guint32 time)
guint32 requestor,
GdkAtom selection,
GdkAtom target,
GdkAtom property,
guint32 time)
{
GdkEvent tmp_event;
gchar *sel_name, *tgt_name, *prop_name;
g_return_if_fail (display == gdk_display_get_default ());
g_return_if_fail (display == _gdk_display);
GDK_NOTE (DND,
(sel_name = gdk_atom_name (selection),
@ -522,12 +619,13 @@ gdk_selection_send_notify_for_display (GdkDisplay *display,
g_free (tgt_name),
g_free (prop_name)));
/* Send ourselves a selection clear message so that gtk thinks we don't
* have the selection, and will claim it anew when needed, and
/* Send ourselves a selection clear message so that gtk thinks we
* don't have the selection, and will claim it anew when needed, and
* we thus get a chance to store data in the Windows clipboard.
* Otherwise, if a gtkeditable does a copy to CLIPBOARD several times
* only the first one actually gets copied to the Windows clipboard,
* as only the first one causes a call to gdk_property_change().
* Otherwise, if a gtkeditable does a copy to CLIPBOARD several
* times only the first one actually gets copied to the Windows
* clipboard, as only the first one causes a call to
* gdk_property_change().
*
* Hmm, there is something fishy with this. Cut and paste inside the
* same app didn't work, the gtkeditable immediately forgot the
@ -548,19 +646,25 @@ gdk_selection_send_notify_for_display (GdkDisplay *display,
gdk_event_put (&tmp_event);
}
/* Simplistic implementations of text list and compound text functions */
/* It's hard to say whether implementing this actually is of any use
* on the Win32 platform? gtk calls only
* gdk_text_property_to_utf8_list_for_display().
*/
gint
gdk_text_property_to_text_list_for_display (GdkDisplay *display,
gdk_text_property_to_text_list_for_display (GdkDisplay *display,
GdkAtom encoding,
gint format,
const guchar *text,
gint length,
gchar ***list)
{
GError *error = NULL;
gchar *enc_name;
gchar *result;
const gchar *charset;
const gchar *source_charset = NULL;
g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
g_return_val_if_fail (display == _gdk_display, 0);
GDK_NOTE (DND, (enc_name = gdk_atom_name (encoding),
g_print ("gdk_text_property_to_text_list: %s %d %.20s %d\n",
@ -570,8 +674,25 @@ gdk_text_property_to_text_list_for_display (GdkDisplay *display,
if (!list)
return 0;
if (encoding == GDK_TARGET_STRING)
source_charset = "ISO-8859-1";
else if (encoding == _utf8_string)
source_charset = "UTF-8";
else
source_charset = gdk_atom_name (encoding);
g_get_charset (&charset);
result = g_convert (text, length, charset, source_charset,
NULL, NULL, &error);
if (!result)
{
g_error_free (error);
return 0;
}
*list = g_new (gchar *, 1);
**list = g_strdup (text);
**list = result;
return 1;
}
@ -585,47 +706,6 @@ gdk_free_text_list (gchar **list)
g_free (list);
}
gint
gdk_string_to_compound_text_for_display (GdkDisplay *display,
const gchar *str,
GdkAtom *encoding,
gint *format,
guchar **ctext,
gint *length)
{
g_return_val_if_fail (str != NULL, 0);
g_return_val_if_fail (length >= 0, 0);
g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
GDK_NOTE (DND, g_print ("gdk_string_to_compound_text: %.20s\n", str));
if (encoding)
*encoding = _compound_text;
if (format)
*format = 8;
if (ctext)
*ctext = g_strdup (str);
if (length)
*length = strlen (str);
return 0;
}
void
gdk_free_compound_text (guchar *ctext)
{
g_free (ctext);
}
/* These are lifted from gdkselection-x11.c, just to get GTK+ to build.
* These functions probably don't make much sense at all in Windows.
*/
/* FIXME */
static gint
make_list (const gchar *text,
gint length,
@ -705,7 +785,7 @@ gdk_text_property_to_utf8_list_for_display (GdkDisplay *display,
{
g_return_val_if_fail (text != NULL, 0);
g_return_val_if_fail (length >= 0, 0);
g_return_val_if_fail (display == gdk_display_get_default (), 0);
g_return_val_if_fail (display == _gdk_display, 0);
if (encoding == GDK_TARGET_STRING)
{
@ -717,164 +797,88 @@ gdk_text_property_to_utf8_list_for_display (GdkDisplay *display,
}
else
{
gchar **local_list;
gint local_count;
gint i;
const gchar *charset = NULL;
gboolean need_conversion = g_get_charset (&charset);
gint count = 0;
GError *error = NULL;
/* Probably COMPOUND text, we fall back to Xlib routines
*/
local_count = gdk_text_property_to_text_list (encoding,
format,
text,
length,
&local_list);
if (list)
*list = g_new (gchar *, local_count + 1);
for (i=0; i<local_count; i++)
{
/* list contains stuff in our default encoding
*/
if (need_conversion)
{
gchar *utf = g_convert (local_list[i], -1,
"UTF-8", charset,
NULL, NULL, &error);
if (utf)
{
if (list)
(*list)[count++] = utf;
else
g_free (utf);
}
else
{
g_warning ("Error converting to UTF-8 from '%s': %s",
charset, error->message);
g_error_free (error);
error = NULL;
}
}
else
{
if (list)
(*list)[count++] = g_strdup (local_list[i]);
}
}
gdk_free_text_list (local_list);
(*list)[count] = NULL;
g_warning ("gdk_text_property_to_utf8_list_for_display: encoding %s not handled\n", gdk_atom_name (encoding));
return count;
if (list)
*list = NULL;
return 0;
}
}
/* The specifications for COMPOUND_TEXT and STRING specify that C0 and
* C1 are not allowed except for \n and \t, however the X conversions
* routines for COMPOUND_TEXT only enforce this in one direction,
* causing cut-and-paste of \r and \r\n separated text to fail.
* This routine strips out all non-allowed C0 and C1 characters
* from the input string and also canonicalizes \r, and \r\n to \n
*/
static gchar *
sanitize_utf8 (const gchar *src)
gint
gdk_string_to_compound_text_for_display (GdkDisplay *display,
const gchar *str,
GdkAtom *encoding,
gint *format,
guchar **ctext,
gint *length)
{
gint len = strlen (src);
GString *result = g_string_sized_new (len);
const gchar *p = src;
g_return_val_if_fail (str != NULL, 0);
g_return_val_if_fail (length >= 0, 0);
g_return_val_if_fail (display == _gdk_display, 0);
while (*p)
{
if (*p == '\r')
{
p++;
if (*p == '\n')
p++;
GDK_NOTE (DND, g_print ("gdk_string_to_compound_text_for_display: %.20s\n", str));
g_string_append_c (result, '\n');
}
else
{
gunichar ch = g_utf8_get_char (p);
char buf[7];
gint buflen;
if (!((ch < 0x20 && ch != '\t' && ch != '\n') || (ch >= 0x7f && ch < 0xa0)))
{
buflen = g_unichar_to_utf8 (ch, buf);
g_string_append_len (result, buf, buflen);
}
/* Always fail on Win32. No COMPOUND_TEXT support. */
p = g_utf8_next_char (p);
}
}
if (encoding)
*encoding = GDK_NONE;
return g_string_free (result, FALSE);
if (format)
*format = 0;
if (ctext)
*ctext = NULL;
if (length)
*length = 0;
return -1;
}
gchar *
gdk_utf8_to_string_target (const gchar *str)
{
return sanitize_utf8 (str);
return _gdk_utf8_to_string_target_internal (str, strlen (str));
}
gboolean
gdk_utf8_to_compound_text_for_display (GdkDisplay *display,
gdk_utf8_to_compound_text_for_display (GdkDisplay *display,
const gchar *str,
GdkAtom *encoding,
gint *format,
guchar **ctext,
gint *length)
{
gboolean need_conversion;
const gchar *charset;
gchar *locale_str, *tmp_str;
GError *error = NULL;
gboolean result;
g_return_val_if_fail (str != NULL, FALSE);
g_return_val_if_fail (display == gdk_display_get_default (), FALSE);
g_return_val_if_fail (display == _gdk_display, FALSE);
need_conversion = !g_get_charset (&charset);
GDK_NOTE (DND, g_print ("gdk_utf8_to_compound_text_for_display: %.20s\n", str));
tmp_str = sanitize_utf8 (str);
/* Always fail on Win32. No COMPOUND_TEXT support. */
if (need_conversion)
{
locale_str = g_convert_with_fallback (tmp_str, -1,
charset, "UTF-8",
NULL, NULL, NULL, &error);
g_free (tmp_str);
if (encoding)
*encoding = GDK_NONE;
if (!locale_str)
{
g_warning ("Error converting from UTF-8 to '%s': %s",
charset, error->message);
g_error_free (error);
if (encoding)
*encoding = GDK_NONE;
if (format)
*format = GPOINTER_TO_UINT (GDK_ATOM_TO_POINTER (GDK_NONE));
if (ctext)
*ctext = NULL;
if (length)
*length = 0;
return FALSE;
}
}
else
locale_str = tmp_str;
result = gdk_string_to_compound_text (locale_str,
encoding, format, ctext, length);
if (format)
*format = 0;
g_free (locale_str);
if (ctext)
*ctext = NULL;
return result;
if (length)
*length = 0;
return FALSE;
}
void
gdk_free_compound_text (guchar *ctext)
{
/* As we never generate anything claimed to be COMPOUND_TEXT, this
* should never be called. Or if it is called, ctext should be the
* NULL returned for conversions to COMPOUND_TEXT above.
*/
g_return_if_fail (ctext == NULL);
}