Apply the same fixes and improvements as to the gtk-1-3-win32-production

2002-01-10  Tor Lillqvist  <tml@iki.fi>

	Apply the same fixes and improvements as to the
	gtk-1-3-win32-production branch: Bug fixes and cleanup of
	selection and DND functionality. Still doesn't work as well as the
	win32-production branch, though, but getting closer.

	After this, need to add Archaeopteryx Software's OLE2 DND support.

	* gdk/win32/gdkselection-win32.c (gdk_selection_owner_set,
	gdk_selection_send_notify, generate_selection_notify): Don't use
	SendMessage() to generate events for the same app, instead use
	gdk_event_put().

	* gdk/win32/gdkprivate-win32.h
	* gdk/win32/gdkglobals-win32.c
	* gdk/win32/gdkmain-win32.c
	* gdk/win32/gdkevents-win32.c: Thus, remove declaration, definition,
	initialisation and handling of gdk_selection_notify_msg,
	gdk_selection_request_msg and gdk_selection_clear_msg.

	* gdk/win32/gdkselection-win32.c (gdk_text_property_to_text_list,
	gdk_free_text_list, gdk_string_to_compound_text,
	gdk_free_compound_text): Implement trivially, witrh a text_list
	always having a single element, and a compound text always
	consisting of just a single (UTF-8!) string. Let's see how well
	this works.

	* gdk/win32/gdkselection-win32.c (gdk_selection_convert): Fix
	non-ASCII paste from the clipboard: Try getting the same formats
	from the Windows clipboard that gdk_property_change() puts there:
	CF_UNICODETEXT, UTF8_STRING or CF_TEXT+CF_LOCALE.

	* gdk/win32/gdkproperty-win32.c (gdk_property_change): When
	storing text on the clipboard, handle non-ASCII text
	correctly. The logic is as follows:

	If we have only ASCII characters, use CF_TEXT.

	Else, if we are on NT, use CF_UNICODETEXT.

	Else (we are on Win9x), if all the characters are present in the
	code page of some installed locale, use CF_TEXT and also set
	CF_LOCALE to that locale.

	Else (still on Win9x) store as RTF. We use a very simple RTF
	string, just the text, no fonts or other crap, with the non-ASCII
	characters as Unicode \uN keywords. Additionally, also store the
	UTF-8 string as such, under the format "UTF8_STRING", so that GDK
	can also paste from the Clipboard what it has copied there. (Thus
	no need to implement any RTF parser.)

	(find_common_locale): New function, implements the search for a
	locale for case 3 above.

	* gdk/win32/gdkglobals-win32.c: New global variables
	compound_text, text_uri_list, utf8_string, cf_rtf and
	cf_utf8_string.

	* gdk/win32/gdkim-win32.c (_gdk_ucs2_to_utf8): New function,
	converts from a wchar_t string to UTF-8.
	(_gdk_utf8_to_ucs2): Rename from _gdk_win32_nmbstowchar_ts.
	(_gdk_utf8_to_wcs): Rename from gdk_nmbstowchar_ts.

	* gdk/win32/gdkevents-win32.c (build_keypress_event): Use
	_gdk_ucs2_to_utf8().

	* gdk/win32/gdkselection-win32.c: Remove some unnecessary logging.

	* gdk/win32/gdkdnd-win32.c: Plug memory leaks, the
	gdk_drag_context_ref() was called unnecessarily in a couple of
	places, meaning drag contexts were never freed. The same memory
	leaks seem to be present in gdk/linux-fb/gdkselection-fb.c, BTW.

	(gdk_drop_reply): For WIN32_DROPFILES drops, free the temporarily
	stored file list.

	* gdk/win32/gdkselection-win32.c: Clarify the use of the
	sel_prop_table. Now it is used only for storing the GDK_SELECTION
	"properties".

	The file names dropped with WM_DROPFILES -style DND is stored
	temporarily (between the drop and the target picking them up) in a
	separate place.

	Have a separate hash table to map selection atoms to owner
	windows. This used to be quite mixed up.

	(_gdk_dropfiles_store): New function, to store the dropped file
	list for the drop target to possibly fetch, and clear it
	afterwards, from gdk_drop_reply().

	(gdk_selection_owner_get): Much simplified now.
This commit is contained in:
Tor Lillqvist 2002-01-10 00:53:39 +00:00 committed by Tor Lillqvist
parent f3f0ad29f1
commit 1b7cff4755
18 changed files with 1465 additions and 435 deletions

View File

@ -1,3 +1,97 @@
2002-01-10 Tor Lillqvist <tml@iki.fi>
Apply the same fixes and improvements as to the
gtk-1-3-win32-production branch: Bug fixes and cleanup of
selection and DND functionality. Still doesn't work as well as the
win32-production branch, though, but getting closer.
After this, need to add Archaeopteryx Software's OLE2 DND support.
* gdk/win32/gdkselection-win32.c (gdk_selection_owner_set,
gdk_selection_send_notify, generate_selection_notify): Don't use
SendMessage() to generate events for the same app, instead use
gdk_event_put().
* gdk/win32/gdkprivate-win32.h
* gdk/win32/gdkglobals-win32.c
* gdk/win32/gdkmain-win32.c
* gdk/win32/gdkevents-win32.c: Thus, remove declaration, definition,
initialisation and handling of gdk_selection_notify_msg,
gdk_selection_request_msg and gdk_selection_clear_msg.
* gdk/win32/gdkselection-win32.c (gdk_text_property_to_text_list,
gdk_free_text_list, gdk_string_to_compound_text,
gdk_free_compound_text): Implement trivially, witrh a text_list
always having a single element, and a compound text always
consisting of just a single (UTF-8!) string. Let's see how well
this works.
* gdk/win32/gdkselection-win32.c (gdk_selection_convert): Fix
non-ASCII paste from the clipboard: Try getting the same formats
from the Windows clipboard that gdk_property_change() puts there:
CF_UNICODETEXT, UTF8_STRING or CF_TEXT+CF_LOCALE.
* gdk/win32/gdkproperty-win32.c (gdk_property_change): When
storing text on the clipboard, handle non-ASCII text
correctly. The logic is as follows:
If we have only ASCII characters, use CF_TEXT.
Else, if we are on NT, use CF_UNICODETEXT.
Else (we are on Win9x), if all the characters are present in the
code page of some installed locale, use CF_TEXT and also set
CF_LOCALE to that locale.
Else (still on Win9x) store as RTF. We use a very simple RTF
string, just the text, no fonts or other crap, with the non-ASCII
characters as Unicode \uN keywords. Additionally, also store the
UTF-8 string as such, under the format "UTF8_STRING", so that GDK
can also paste from the Clipboard what it has copied there. (Thus
no need to implement any RTF parser.)
(find_common_locale): New function, implements the search for a
locale for case 3 above.
* gdk/win32/gdkglobals-win32.c: New global variables
compound_text, text_uri_list, utf8_string, cf_rtf and
cf_utf8_string.
* gdk/win32/gdkim-win32.c (_gdk_ucs2_to_utf8): New function,
converts from a wchar_t string to UTF-8.
(_gdk_utf8_to_ucs2): Rename from _gdk_win32_nmbstowchar_ts.
(_gdk_utf8_to_wcs): Rename from gdk_nmbstowchar_ts.
* gdk/win32/gdkevents-win32.c (build_keypress_event): Use
_gdk_ucs2_to_utf8().
* gdk/win32/gdkselection-win32.c: Remove some unnecessary logging.
* gdk/win32/gdkdnd-win32.c: Plug memory leaks, the
gdk_drag_context_ref() was called unnecessarily in a couple of
places, meaning drag contexts were never freed. The same memory
leaks seem to be present in gdk/linux-fb/gdkselection-fb.c, BTW.
(gdk_drop_reply): For WIN32_DROPFILES drops, free the temporarily
stored file list.
* gdk/win32/gdkselection-win32.c: Clarify the use of the
sel_prop_table. Now it is used only for storing the GDK_SELECTION
"properties".
The file names dropped with WM_DROPFILES -style DND is stored
temporarily (between the drop and the target picking them up) in a
separate place.
Have a separate hash table to map selection atoms to owner
windows. This used to be quite mixed up.
(_gdk_dropfiles_store): New function, to store the dropped file
list for the drop target to possibly fetch, and clear it
afterwards, from gdk_drop_reply().
(gdk_selection_owner_get): Much simplified now.
2002-01-09 jacob berkman <jacob@ximian.com>
* gtk/gtklayout.c (gtk_layout_style_set): set the background of

View File

@ -1,3 +1,97 @@
2002-01-10 Tor Lillqvist <tml@iki.fi>
Apply the same fixes and improvements as to the
gtk-1-3-win32-production branch: Bug fixes and cleanup of
selection and DND functionality. Still doesn't work as well as the
win32-production branch, though, but getting closer.
After this, need to add Archaeopteryx Software's OLE2 DND support.
* gdk/win32/gdkselection-win32.c (gdk_selection_owner_set,
gdk_selection_send_notify, generate_selection_notify): Don't use
SendMessage() to generate events for the same app, instead use
gdk_event_put().
* gdk/win32/gdkprivate-win32.h
* gdk/win32/gdkglobals-win32.c
* gdk/win32/gdkmain-win32.c
* gdk/win32/gdkevents-win32.c: Thus, remove declaration, definition,
initialisation and handling of gdk_selection_notify_msg,
gdk_selection_request_msg and gdk_selection_clear_msg.
* gdk/win32/gdkselection-win32.c (gdk_text_property_to_text_list,
gdk_free_text_list, gdk_string_to_compound_text,
gdk_free_compound_text): Implement trivially, witrh a text_list
always having a single element, and a compound text always
consisting of just a single (UTF-8!) string. Let's see how well
this works.
* gdk/win32/gdkselection-win32.c (gdk_selection_convert): Fix
non-ASCII paste from the clipboard: Try getting the same formats
from the Windows clipboard that gdk_property_change() puts there:
CF_UNICODETEXT, UTF8_STRING or CF_TEXT+CF_LOCALE.
* gdk/win32/gdkproperty-win32.c (gdk_property_change): When
storing text on the clipboard, handle non-ASCII text
correctly. The logic is as follows:
If we have only ASCII characters, use CF_TEXT.
Else, if we are on NT, use CF_UNICODETEXT.
Else (we are on Win9x), if all the characters are present in the
code page of some installed locale, use CF_TEXT and also set
CF_LOCALE to that locale.
Else (still on Win9x) store as RTF. We use a very simple RTF
string, just the text, no fonts or other crap, with the non-ASCII
characters as Unicode \uN keywords. Additionally, also store the
UTF-8 string as such, under the format "UTF8_STRING", so that GDK
can also paste from the Clipboard what it has copied there. (Thus
no need to implement any RTF parser.)
(find_common_locale): New function, implements the search for a
locale for case 3 above.
* gdk/win32/gdkglobals-win32.c: New global variables
compound_text, text_uri_list, utf8_string, cf_rtf and
cf_utf8_string.
* gdk/win32/gdkim-win32.c (_gdk_ucs2_to_utf8): New function,
converts from a wchar_t string to UTF-8.
(_gdk_utf8_to_ucs2): Rename from _gdk_win32_nmbstowchar_ts.
(_gdk_utf8_to_wcs): Rename from gdk_nmbstowchar_ts.
* gdk/win32/gdkevents-win32.c (build_keypress_event): Use
_gdk_ucs2_to_utf8().
* gdk/win32/gdkselection-win32.c: Remove some unnecessary logging.
* gdk/win32/gdkdnd-win32.c: Plug memory leaks, the
gdk_drag_context_ref() was called unnecessarily in a couple of
places, meaning drag contexts were never freed. The same memory
leaks seem to be present in gdk/linux-fb/gdkselection-fb.c, BTW.
(gdk_drop_reply): For WIN32_DROPFILES drops, free the temporarily
stored file list.
* gdk/win32/gdkselection-win32.c: Clarify the use of the
sel_prop_table. Now it is used only for storing the GDK_SELECTION
"properties".
The file names dropped with WM_DROPFILES -style DND is stored
temporarily (between the drop and the target picking them up) in a
separate place.
Have a separate hash table to map selection atoms to owner
windows. This used to be quite mixed up.
(_gdk_dropfiles_store): New function, to store the dropped file
list for the drop target to possibly fetch, and clear it
afterwards, from gdk_drop_reply().
(gdk_selection_owner_get): Much simplified now.
2002-01-09 jacob berkman <jacob@ximian.com>
* gtk/gtklayout.c (gtk_layout_style_set): set the background of

View File

@ -1,3 +1,97 @@
2002-01-10 Tor Lillqvist <tml@iki.fi>
Apply the same fixes and improvements as to the
gtk-1-3-win32-production branch: Bug fixes and cleanup of
selection and DND functionality. Still doesn't work as well as the
win32-production branch, though, but getting closer.
After this, need to add Archaeopteryx Software's OLE2 DND support.
* gdk/win32/gdkselection-win32.c (gdk_selection_owner_set,
gdk_selection_send_notify, generate_selection_notify): Don't use
SendMessage() to generate events for the same app, instead use
gdk_event_put().
* gdk/win32/gdkprivate-win32.h
* gdk/win32/gdkglobals-win32.c
* gdk/win32/gdkmain-win32.c
* gdk/win32/gdkevents-win32.c: Thus, remove declaration, definition,
initialisation and handling of gdk_selection_notify_msg,
gdk_selection_request_msg and gdk_selection_clear_msg.
* gdk/win32/gdkselection-win32.c (gdk_text_property_to_text_list,
gdk_free_text_list, gdk_string_to_compound_text,
gdk_free_compound_text): Implement trivially, witrh a text_list
always having a single element, and a compound text always
consisting of just a single (UTF-8!) string. Let's see how well
this works.
* gdk/win32/gdkselection-win32.c (gdk_selection_convert): Fix
non-ASCII paste from the clipboard: Try getting the same formats
from the Windows clipboard that gdk_property_change() puts there:
CF_UNICODETEXT, UTF8_STRING or CF_TEXT+CF_LOCALE.
* gdk/win32/gdkproperty-win32.c (gdk_property_change): When
storing text on the clipboard, handle non-ASCII text
correctly. The logic is as follows:
If we have only ASCII characters, use CF_TEXT.
Else, if we are on NT, use CF_UNICODETEXT.
Else (we are on Win9x), if all the characters are present in the
code page of some installed locale, use CF_TEXT and also set
CF_LOCALE to that locale.
Else (still on Win9x) store as RTF. We use a very simple RTF
string, just the text, no fonts or other crap, with the non-ASCII
characters as Unicode \uN keywords. Additionally, also store the
UTF-8 string as such, under the format "UTF8_STRING", so that GDK
can also paste from the Clipboard what it has copied there. (Thus
no need to implement any RTF parser.)
(find_common_locale): New function, implements the search for a
locale for case 3 above.
* gdk/win32/gdkglobals-win32.c: New global variables
compound_text, text_uri_list, utf8_string, cf_rtf and
cf_utf8_string.
* gdk/win32/gdkim-win32.c (_gdk_ucs2_to_utf8): New function,
converts from a wchar_t string to UTF-8.
(_gdk_utf8_to_ucs2): Rename from _gdk_win32_nmbstowchar_ts.
(_gdk_utf8_to_wcs): Rename from gdk_nmbstowchar_ts.
* gdk/win32/gdkevents-win32.c (build_keypress_event): Use
_gdk_ucs2_to_utf8().
* gdk/win32/gdkselection-win32.c: Remove some unnecessary logging.
* gdk/win32/gdkdnd-win32.c: Plug memory leaks, the
gdk_drag_context_ref() was called unnecessarily in a couple of
places, meaning drag contexts were never freed. The same memory
leaks seem to be present in gdk/linux-fb/gdkselection-fb.c, BTW.
(gdk_drop_reply): For WIN32_DROPFILES drops, free the temporarily
stored file list.
* gdk/win32/gdkselection-win32.c: Clarify the use of the
sel_prop_table. Now it is used only for storing the GDK_SELECTION
"properties".
The file names dropped with WM_DROPFILES -style DND is stored
temporarily (between the drop and the target picking them up) in a
separate place.
Have a separate hash table to map selection atoms to owner
windows. This used to be quite mixed up.
(_gdk_dropfiles_store): New function, to store the dropped file
list for the drop target to possibly fetch, and clear it
afterwards, from gdk_drop_reply().
(gdk_selection_owner_get): Much simplified now.
2002-01-09 jacob berkman <jacob@ximian.com>
* gtk/gtklayout.c (gtk_layout_style_set): set the background of

View File

@ -1,3 +1,97 @@
2002-01-10 Tor Lillqvist <tml@iki.fi>
Apply the same fixes and improvements as to the
gtk-1-3-win32-production branch: Bug fixes and cleanup of
selection and DND functionality. Still doesn't work as well as the
win32-production branch, though, but getting closer.
After this, need to add Archaeopteryx Software's OLE2 DND support.
* gdk/win32/gdkselection-win32.c (gdk_selection_owner_set,
gdk_selection_send_notify, generate_selection_notify): Don't use
SendMessage() to generate events for the same app, instead use
gdk_event_put().
* gdk/win32/gdkprivate-win32.h
* gdk/win32/gdkglobals-win32.c
* gdk/win32/gdkmain-win32.c
* gdk/win32/gdkevents-win32.c: Thus, remove declaration, definition,
initialisation and handling of gdk_selection_notify_msg,
gdk_selection_request_msg and gdk_selection_clear_msg.
* gdk/win32/gdkselection-win32.c (gdk_text_property_to_text_list,
gdk_free_text_list, gdk_string_to_compound_text,
gdk_free_compound_text): Implement trivially, witrh a text_list
always having a single element, and a compound text always
consisting of just a single (UTF-8!) string. Let's see how well
this works.
* gdk/win32/gdkselection-win32.c (gdk_selection_convert): Fix
non-ASCII paste from the clipboard: Try getting the same formats
from the Windows clipboard that gdk_property_change() puts there:
CF_UNICODETEXT, UTF8_STRING or CF_TEXT+CF_LOCALE.
* gdk/win32/gdkproperty-win32.c (gdk_property_change): When
storing text on the clipboard, handle non-ASCII text
correctly. The logic is as follows:
If we have only ASCII characters, use CF_TEXT.
Else, if we are on NT, use CF_UNICODETEXT.
Else (we are on Win9x), if all the characters are present in the
code page of some installed locale, use CF_TEXT and also set
CF_LOCALE to that locale.
Else (still on Win9x) store as RTF. We use a very simple RTF
string, just the text, no fonts or other crap, with the non-ASCII
characters as Unicode \uN keywords. Additionally, also store the
UTF-8 string as such, under the format "UTF8_STRING", so that GDK
can also paste from the Clipboard what it has copied there. (Thus
no need to implement any RTF parser.)
(find_common_locale): New function, implements the search for a
locale for case 3 above.
* gdk/win32/gdkglobals-win32.c: New global variables
compound_text, text_uri_list, utf8_string, cf_rtf and
cf_utf8_string.
* gdk/win32/gdkim-win32.c (_gdk_ucs2_to_utf8): New function,
converts from a wchar_t string to UTF-8.
(_gdk_utf8_to_ucs2): Rename from _gdk_win32_nmbstowchar_ts.
(_gdk_utf8_to_wcs): Rename from gdk_nmbstowchar_ts.
* gdk/win32/gdkevents-win32.c (build_keypress_event): Use
_gdk_ucs2_to_utf8().
* gdk/win32/gdkselection-win32.c: Remove some unnecessary logging.
* gdk/win32/gdkdnd-win32.c: Plug memory leaks, the
gdk_drag_context_ref() was called unnecessarily in a couple of
places, meaning drag contexts were never freed. The same memory
leaks seem to be present in gdk/linux-fb/gdkselection-fb.c, BTW.
(gdk_drop_reply): For WIN32_DROPFILES drops, free the temporarily
stored file list.
* gdk/win32/gdkselection-win32.c: Clarify the use of the
sel_prop_table. Now it is used only for storing the GDK_SELECTION
"properties".
The file names dropped with WM_DROPFILES -style DND is stored
temporarily (between the drop and the target picking them up) in a
separate place.
Have a separate hash table to map selection atoms to owner
windows. This used to be quite mixed up.
(_gdk_dropfiles_store): New function, to store the dropped file
list for the drop target to possibly fetch, and clear it
afterwards, from gdk_drop_reply().
(gdk_selection_owner_get): Much simplified now.
2002-01-09 jacob berkman <jacob@ximian.com>
* gtk/gtklayout.c (gtk_layout_style_set): set the background of

View File

@ -1,3 +1,97 @@
2002-01-10 Tor Lillqvist <tml@iki.fi>
Apply the same fixes and improvements as to the
gtk-1-3-win32-production branch: Bug fixes and cleanup of
selection and DND functionality. Still doesn't work as well as the
win32-production branch, though, but getting closer.
After this, need to add Archaeopteryx Software's OLE2 DND support.
* gdk/win32/gdkselection-win32.c (gdk_selection_owner_set,
gdk_selection_send_notify, generate_selection_notify): Don't use
SendMessage() to generate events for the same app, instead use
gdk_event_put().
* gdk/win32/gdkprivate-win32.h
* gdk/win32/gdkglobals-win32.c
* gdk/win32/gdkmain-win32.c
* gdk/win32/gdkevents-win32.c: Thus, remove declaration, definition,
initialisation and handling of gdk_selection_notify_msg,
gdk_selection_request_msg and gdk_selection_clear_msg.
* gdk/win32/gdkselection-win32.c (gdk_text_property_to_text_list,
gdk_free_text_list, gdk_string_to_compound_text,
gdk_free_compound_text): Implement trivially, witrh a text_list
always having a single element, and a compound text always
consisting of just a single (UTF-8!) string. Let's see how well
this works.
* gdk/win32/gdkselection-win32.c (gdk_selection_convert): Fix
non-ASCII paste from the clipboard: Try getting the same formats
from the Windows clipboard that gdk_property_change() puts there:
CF_UNICODETEXT, UTF8_STRING or CF_TEXT+CF_LOCALE.
* gdk/win32/gdkproperty-win32.c (gdk_property_change): When
storing text on the clipboard, handle non-ASCII text
correctly. The logic is as follows:
If we have only ASCII characters, use CF_TEXT.
Else, if we are on NT, use CF_UNICODETEXT.
Else (we are on Win9x), if all the characters are present in the
code page of some installed locale, use CF_TEXT and also set
CF_LOCALE to that locale.
Else (still on Win9x) store as RTF. We use a very simple RTF
string, just the text, no fonts or other crap, with the non-ASCII
characters as Unicode \uN keywords. Additionally, also store the
UTF-8 string as such, under the format "UTF8_STRING", so that GDK
can also paste from the Clipboard what it has copied there. (Thus
no need to implement any RTF parser.)
(find_common_locale): New function, implements the search for a
locale for case 3 above.
* gdk/win32/gdkglobals-win32.c: New global variables
compound_text, text_uri_list, utf8_string, cf_rtf and
cf_utf8_string.
* gdk/win32/gdkim-win32.c (_gdk_ucs2_to_utf8): New function,
converts from a wchar_t string to UTF-8.
(_gdk_utf8_to_ucs2): Rename from _gdk_win32_nmbstowchar_ts.
(_gdk_utf8_to_wcs): Rename from gdk_nmbstowchar_ts.
* gdk/win32/gdkevents-win32.c (build_keypress_event): Use
_gdk_ucs2_to_utf8().
* gdk/win32/gdkselection-win32.c: Remove some unnecessary logging.
* gdk/win32/gdkdnd-win32.c: Plug memory leaks, the
gdk_drag_context_ref() was called unnecessarily in a couple of
places, meaning drag contexts were never freed. The same memory
leaks seem to be present in gdk/linux-fb/gdkselection-fb.c, BTW.
(gdk_drop_reply): For WIN32_DROPFILES drops, free the temporarily
stored file list.
* gdk/win32/gdkselection-win32.c: Clarify the use of the
sel_prop_table. Now it is used only for storing the GDK_SELECTION
"properties".
The file names dropped with WM_DROPFILES -style DND is stored
temporarily (between the drop and the target picking them up) in a
separate place.
Have a separate hash table to map selection atoms to owner
windows. This used to be quite mixed up.
(_gdk_dropfiles_store): New function, to store the dropped file
list for the drop target to possibly fetch, and clear it
afterwards, from gdk_drop_reply().
(gdk_selection_owner_get): Much simplified now.
2002-01-09 jacob berkman <jacob@ximian.com>
* gtk/gtklayout.c (gtk_layout_style_set): set the background of

View File

@ -1,3 +1,97 @@
2002-01-10 Tor Lillqvist <tml@iki.fi>
Apply the same fixes and improvements as to the
gtk-1-3-win32-production branch: Bug fixes and cleanup of
selection and DND functionality. Still doesn't work as well as the
win32-production branch, though, but getting closer.
After this, need to add Archaeopteryx Software's OLE2 DND support.
* gdk/win32/gdkselection-win32.c (gdk_selection_owner_set,
gdk_selection_send_notify, generate_selection_notify): Don't use
SendMessage() to generate events for the same app, instead use
gdk_event_put().
* gdk/win32/gdkprivate-win32.h
* gdk/win32/gdkglobals-win32.c
* gdk/win32/gdkmain-win32.c
* gdk/win32/gdkevents-win32.c: Thus, remove declaration, definition,
initialisation and handling of gdk_selection_notify_msg,
gdk_selection_request_msg and gdk_selection_clear_msg.
* gdk/win32/gdkselection-win32.c (gdk_text_property_to_text_list,
gdk_free_text_list, gdk_string_to_compound_text,
gdk_free_compound_text): Implement trivially, witrh a text_list
always having a single element, and a compound text always
consisting of just a single (UTF-8!) string. Let's see how well
this works.
* gdk/win32/gdkselection-win32.c (gdk_selection_convert): Fix
non-ASCII paste from the clipboard: Try getting the same formats
from the Windows clipboard that gdk_property_change() puts there:
CF_UNICODETEXT, UTF8_STRING or CF_TEXT+CF_LOCALE.
* gdk/win32/gdkproperty-win32.c (gdk_property_change): When
storing text on the clipboard, handle non-ASCII text
correctly. The logic is as follows:
If we have only ASCII characters, use CF_TEXT.
Else, if we are on NT, use CF_UNICODETEXT.
Else (we are on Win9x), if all the characters are present in the
code page of some installed locale, use CF_TEXT and also set
CF_LOCALE to that locale.
Else (still on Win9x) store as RTF. We use a very simple RTF
string, just the text, no fonts or other crap, with the non-ASCII
characters as Unicode \uN keywords. Additionally, also store the
UTF-8 string as such, under the format "UTF8_STRING", so that GDK
can also paste from the Clipboard what it has copied there. (Thus
no need to implement any RTF parser.)
(find_common_locale): New function, implements the search for a
locale for case 3 above.
* gdk/win32/gdkglobals-win32.c: New global variables
compound_text, text_uri_list, utf8_string, cf_rtf and
cf_utf8_string.
* gdk/win32/gdkim-win32.c (_gdk_ucs2_to_utf8): New function,
converts from a wchar_t string to UTF-8.
(_gdk_utf8_to_ucs2): Rename from _gdk_win32_nmbstowchar_ts.
(_gdk_utf8_to_wcs): Rename from gdk_nmbstowchar_ts.
* gdk/win32/gdkevents-win32.c (build_keypress_event): Use
_gdk_ucs2_to_utf8().
* gdk/win32/gdkselection-win32.c: Remove some unnecessary logging.
* gdk/win32/gdkdnd-win32.c: Plug memory leaks, the
gdk_drag_context_ref() was called unnecessarily in a couple of
places, meaning drag contexts were never freed. The same memory
leaks seem to be present in gdk/linux-fb/gdkselection-fb.c, BTW.
(gdk_drop_reply): For WIN32_DROPFILES drops, free the temporarily
stored file list.
* gdk/win32/gdkselection-win32.c: Clarify the use of the
sel_prop_table. Now it is used only for storing the GDK_SELECTION
"properties".
The file names dropped with WM_DROPFILES -style DND is stored
temporarily (between the drop and the target picking them up) in a
separate place.
Have a separate hash table to map selection atoms to owner
windows. This used to be quite mixed up.
(_gdk_dropfiles_store): New function, to store the dropped file
list for the drop target to possibly fetch, and clear it
afterwards, from gdk_drop_reply().
(gdk_selection_owner_get): Much simplified now.
2002-01-09 jacob berkman <jacob@ximian.com>
* gtk/gtklayout.c (gtk_layout_style_set): set the background of

View File

@ -1,3 +1,97 @@
2002-01-10 Tor Lillqvist <tml@iki.fi>
Apply the same fixes and improvements as to the
gtk-1-3-win32-production branch: Bug fixes and cleanup of
selection and DND functionality. Still doesn't work as well as the
win32-production branch, though, but getting closer.
After this, need to add Archaeopteryx Software's OLE2 DND support.
* gdk/win32/gdkselection-win32.c (gdk_selection_owner_set,
gdk_selection_send_notify, generate_selection_notify): Don't use
SendMessage() to generate events for the same app, instead use
gdk_event_put().
* gdk/win32/gdkprivate-win32.h
* gdk/win32/gdkglobals-win32.c
* gdk/win32/gdkmain-win32.c
* gdk/win32/gdkevents-win32.c: Thus, remove declaration, definition,
initialisation and handling of gdk_selection_notify_msg,
gdk_selection_request_msg and gdk_selection_clear_msg.
* gdk/win32/gdkselection-win32.c (gdk_text_property_to_text_list,
gdk_free_text_list, gdk_string_to_compound_text,
gdk_free_compound_text): Implement trivially, witrh a text_list
always having a single element, and a compound text always
consisting of just a single (UTF-8!) string. Let's see how well
this works.
* gdk/win32/gdkselection-win32.c (gdk_selection_convert): Fix
non-ASCII paste from the clipboard: Try getting the same formats
from the Windows clipboard that gdk_property_change() puts there:
CF_UNICODETEXT, UTF8_STRING or CF_TEXT+CF_LOCALE.
* gdk/win32/gdkproperty-win32.c (gdk_property_change): When
storing text on the clipboard, handle non-ASCII text
correctly. The logic is as follows:
If we have only ASCII characters, use CF_TEXT.
Else, if we are on NT, use CF_UNICODETEXT.
Else (we are on Win9x), if all the characters are present in the
code page of some installed locale, use CF_TEXT and also set
CF_LOCALE to that locale.
Else (still on Win9x) store as RTF. We use a very simple RTF
string, just the text, no fonts or other crap, with the non-ASCII
characters as Unicode \uN keywords. Additionally, also store the
UTF-8 string as such, under the format "UTF8_STRING", so that GDK
can also paste from the Clipboard what it has copied there. (Thus
no need to implement any RTF parser.)
(find_common_locale): New function, implements the search for a
locale for case 3 above.
* gdk/win32/gdkglobals-win32.c: New global variables
compound_text, text_uri_list, utf8_string, cf_rtf and
cf_utf8_string.
* gdk/win32/gdkim-win32.c (_gdk_ucs2_to_utf8): New function,
converts from a wchar_t string to UTF-8.
(_gdk_utf8_to_ucs2): Rename from _gdk_win32_nmbstowchar_ts.
(_gdk_utf8_to_wcs): Rename from gdk_nmbstowchar_ts.
* gdk/win32/gdkevents-win32.c (build_keypress_event): Use
_gdk_ucs2_to_utf8().
* gdk/win32/gdkselection-win32.c: Remove some unnecessary logging.
* gdk/win32/gdkdnd-win32.c: Plug memory leaks, the
gdk_drag_context_ref() was called unnecessarily in a couple of
places, meaning drag contexts were never freed. The same memory
leaks seem to be present in gdk/linux-fb/gdkselection-fb.c, BTW.
(gdk_drop_reply): For WIN32_DROPFILES drops, free the temporarily
stored file list.
* gdk/win32/gdkselection-win32.c: Clarify the use of the
sel_prop_table. Now it is used only for storing the GDK_SELECTION
"properties".
The file names dropped with WM_DROPFILES -style DND is stored
temporarily (between the drop and the target picking them up) in a
separate place.
Have a separate hash table to map selection atoms to owner
windows. This used to be quite mixed up.
(_gdk_dropfiles_store): New function, to store the dropped file
list for the drop target to possibly fetch, and clear it
afterwards, from gdk_drop_reply().
(gdk_selection_owner_get): Much simplified now.
2002-01-09 jacob berkman <jacob@ximian.com>
* gtk/gtklayout.c (gtk_layout_style_set): set the background of

View File

@ -1,6 +1,6 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1999 Peter Mattis, Spencer Kimball and Josh MacDonald
* Copyright (C) 1998-1999 Tor Lillqvist
* Copyright (C) 1998-2002 Tor Lillqvist
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -87,7 +87,6 @@ static int nformats;
* this is used on both source and destination sides.
*/
struct _GdkDragContextPrivateWin32 {
GdkAtom local_selection;
gint ref_count;
guint16 last_x; /* Coordinates from last event */
@ -192,6 +191,8 @@ gdk_drag_context_ref (GdkDragContext *context)
{
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
GDK_NOTE (DND, g_print ("gdk_drag_context_ref: %p %d\n", context, G_OBJECT(context)->ref_count));
g_object_ref (G_OBJECT (context));
}
@ -200,16 +201,16 @@ gdk_drag_context_unref (GdkDragContext *context)
{
g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
GDK_NOTE (DND, g_print ("gdk_drag_context_unref: %p %d\n", context, G_OBJECT(context)->ref_count));
g_object_unref (G_OBJECT (context));
}
static GdkDragContext *
gdk_drag_context_find (gboolean is_source,
GdkWindow *source,
GdkWindow *dest)
gdk_drag_context_find (gboolean is_source,
GdkWindow *source,
GdkWindow *dest)
{
GList *tmp_list = contexts;
GdkDragContext *context;
GdkDragContextPrivateWin32 *private;
@ -221,7 +222,7 @@ gdk_drag_context_find (gboolean is_source,
if ((!context->is_source == !is_source) &&
((source == NULL) || (context->source_window && (context->source_window == source))) &&
((dest == NULL) || (context->dest_window && (context->dest_window == dest))))
return context;
return context;
tmp_list = tmp_list->next;
}
@ -943,7 +944,6 @@ gdk_dropfiles_filter (GdkXEvent *xev,
{
GdkDragContext *context;
GdkDragContextPrivateWin32 *private;
static GdkAtom text_uri_list_atom = GDK_NONE;
GString *result;
MSG *msg = (MSG *) xev;
HANDLE hdrop;
@ -951,9 +951,6 @@ gdk_dropfiles_filter (GdkXEvent *xev,
gint nfiles, i;
guchar fileName[MAX_PATH], linkedFile[MAX_PATH];
if (text_uri_list_atom == GDK_NONE)
text_uri_list_atom = gdk_atom_intern ("text/uri-list", FALSE);
if (msg->message == WM_DROPFILES)
{
GDK_NOTE (DND, g_print ("WM_DROPFILES: %#x\n", (guint) msg->hwnd));
@ -968,12 +965,11 @@ gdk_dropfiles_filter (GdkXEvent *xev,
gdk_drawable_ref (context->dest_window);
/* WM_DROPFILES drops are always file names */
context->targets =
g_list_append (NULL, GUINT_TO_POINTER (text_uri_list_atom));
g_list_append (NULL, GUINT_TO_POINTER (text_uri_list));
current_dest_drag = context;
event->dnd.type = GDK_DROP_START;
event->dnd.context = current_dest_drag;
gdk_drag_context_ref (current_dest_drag);
hdrop = (HANDLE) msg->wParam;
DragQueryPoint (hdrop, &pt);
@ -1005,8 +1001,8 @@ gdk_dropfiles_filter (GdkXEvent *xev,
}
g_string_append (result, "\015\012");
}
_gdk_selection_property_store (_gdk_parent_root, text_uri_list_atom, 8,
result->str, result->len + 1);
_gdk_dropfiles_store (result->str);
g_string_free (result, FALSE);
DragFinish (hdrop);
@ -1058,8 +1054,8 @@ _gdk_win32_dnd_exit (void)
/* Source side */
static void
local_send_leave (GdkDragContext *context,
guint32 time)
local_send_leave (GdkDragContext *context,
guint32 time)
{
GdkEvent tmp_event;
@ -1070,20 +1066,19 @@ local_send_leave (GdkDragContext *context,
tmp_event.dnd.type = GDK_DRAG_LEAVE;
tmp_event.dnd.window = context->dest_window;
/* Pass ownership of context to the event */
tmp_event.dnd.context = current_dest_drag;
tmp_event.dnd.send_event = FALSE;
tmp_event.dnd.context = current_dest_drag;
tmp_event.dnd.time = GDK_CURRENT_TIME; /* FIXME? */
current_dest_drag = NULL;
gdk_event_put (&tmp_event);
}
}
static void
local_send_enter (GdkDragContext *context,
guint32 time)
local_send_enter (GdkDragContext *context,
guint32 time)
{
GdkEvent tmp_event;
GdkDragContextPrivateWin32 *private;
@ -1091,9 +1086,6 @@ local_send_enter (GdkDragContext *context,
private = GDK_DRAG_CONTEXT_PRIVATE_DATA (context);
if (!private->local_selection)
private->local_selection = gdk_atom_intern ("LocalDndSelection", FALSE);
if (current_dest_drag != NULL)
{
gdk_drag_context_unref (current_dest_drag);
@ -1109,7 +1101,6 @@ local_send_enter (GdkDragContext *context,
new_context->dest_window = context->dest_window;
gdk_window_ref (new_context->dest_window);
new_context->targets = g_list_copy (context->targets);
gdk_window_set_events (new_context->source_window,
@ -1121,24 +1112,19 @@ local_send_enter (GdkDragContext *context,
tmp_event.dnd.window = context->dest_window;
tmp_event.dnd.send_event = FALSE;
tmp_event.dnd.context = new_context;
gdk_drag_context_ref (new_context);
tmp_event.dnd.time = GDK_CURRENT_TIME; /* FIXME? */
current_dest_drag = new_context;
(GDK_DRAG_CONTEXT_PRIVATE_DATA (new_context))->local_selection =
private->local_selection;
gdk_event_put (&tmp_event);
}
static void
local_send_motion (GdkDragContext *context,
gint x_root,
gint y_root,
GdkDragAction action,
guint32 time)
local_send_motion (GdkDragContext *context,
gint x_root,
gint y_root,
GdkDragAction action,
guint32 time)
{
GdkEvent tmp_event;
@ -1150,8 +1136,6 @@ local_send_motion (GdkDragContext *context,
tmp_event.dnd.window = current_dest_drag->dest_window;
tmp_event.dnd.send_event = FALSE;
tmp_event.dnd.context = current_dest_drag;
gdk_drag_context_ref (current_dest_drag);
tmp_event.dnd.time = time;
current_dest_drag->suggested_action = action;
@ -1170,7 +1154,8 @@ local_send_motion (GdkDragContext *context,
}
static void
local_send_drop (GdkDragContext *context, guint32 time)
local_send_drop (GdkDragContext *context,
guint32 time)
{
GdkEvent tmp_event;
@ -1184,10 +1169,7 @@ local_send_drop (GdkDragContext *context, guint32 time)
tmp_event.dnd.type = GDK_DROP_START;
tmp_event.dnd.window = current_dest_drag->dest_window;
tmp_event.dnd.send_event = FALSE;
tmp_event.dnd.context = current_dest_drag;
gdk_drag_context_ref (current_dest_drag);
tmp_event.dnd.time = GDK_CURRENT_TIME;
tmp_event.dnd.x_root = private->last_x;
@ -1314,7 +1296,6 @@ gdk_drag_get_protocol (guint32 xid,
window = gdk_window_lookup (xid);
if (GPOINTER_TO_INT (gdk_drawable_get_data (window, "gdk-dnd-registered")))
{
*protocol = GDK_DRAG_PROTO_LOCAL;
@ -1355,7 +1336,6 @@ gdk_drag_find_window (GdkDragContext *context,
GDK_NOTE (DND, g_print ("gdk_drag_find_window: %#x +%d+%d Protocol: %d\n",
(drag_window ? (guint) GDK_WINDOW_HWND (drag_window) : 0),
x_root, y_root, *protocol));
}
gboolean
@ -1397,7 +1377,6 @@ gdk_drag_motion (GdkDragContext *context,
local_send_enter (context, time);
break;
default:
break;
}
@ -1448,6 +1427,7 @@ gdk_drag_motion (GdkDragContext *context,
case GDK_DRAG_PROTO_NONE:
g_warning ("GDK_DRAG_PROTO_NONE is not valid in gdk_drag_motion()");
break;
default:
break;
}
@ -1478,6 +1458,7 @@ gdk_drag_drop (GdkDragContext *context,
case GDK_DRAG_PROTO_NONE:
g_warning ("GDK_DRAG_PROTO_NONE is not valid in gdk_drag_drop()");
break;
default:
break;
}
@ -1525,8 +1506,6 @@ gdk_drag_status (GdkDragContext *context,
tmp_event.dnd.window = context->source_window;
tmp_event.dnd.send_event = FALSE;
tmp_event.dnd.context = src_context;
gdk_drag_context_ref (src_context);
tmp_event.dnd.time = GDK_CURRENT_TIME; /* FIXME? */
if (action == GDK_ACTION_DEFAULT)
@ -1546,6 +1525,19 @@ gdk_drop_reply (GdkDragContext *context,
g_return_if_fail (context != NULL);
GDK_NOTE (DND, g_print ("gdk_drop_reply\n"));
if (context->dest_window)
{
switch (context->protocol)
{
case GDK_DRAG_PROTO_WIN32_DROPFILES:
_gdk_dropfiles_store (NULL);
break;
default:
break;
}
}
}
void
@ -1572,7 +1564,6 @@ gdk_drop_finish (GdkDragContext *context,
tmp_event.dnd.window = src_context->source_window;
tmp_event.dnd.send_event = FALSE;
tmp_event.dnd.context = src_context;
gdk_drag_context_ref (src_context);
gdk_event_put (&tmp_event);
}
@ -1614,8 +1605,8 @@ gdk_window_register_dnd (GdkWindow *window)
if (GPOINTER_TO_INT (gdk_drawable_get_data (window, "gdk-dnd-registered")))
return;
else
gdk_drawable_set_data (window, "gdk-dnd-registered", GINT_TO_POINTER(TRUE), NULL);
gdk_drawable_set_data (window, "gdk-dnd-registered", GINT_TO_POINTER(TRUE), NULL);
GDK_NOTE (DND, g_print ("gdk_window_register_dnd: %#x\n",
(guint) GDK_WINDOW_HWND (window)));
@ -1668,11 +1659,11 @@ GdkAtom
gdk_drag_get_selection (GdkDragContext *context)
{
if (context->protocol == GDK_DRAG_PROTO_LOCAL)
return (GDK_DRAG_CONTEXT_PRIVATE_DATA (context))->local_selection;
return local_dnd;
else if (context->protocol == GDK_DRAG_PROTO_WIN32_DROPFILES)
return gdk_win32_dropfiles_atom;
return gdk_win32_dropfiles;
else if (context->protocol == GDK_DRAG_PROTO_OLE2)
return gdk_ole2_dnd_atom;
return gdk_ole2_dnd;
else
return GDK_NONE;
}

View File

@ -554,8 +554,8 @@ gdk_win32_draw_text (GdkDrawable *drawable,
else
{
wcstr = g_new (wchar_t, text_length);
if ((wlen = _gdk_win32_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
g_warning ("gdk_win32_draw_text: _gdk_win32_nmbstowchar_ts failed");
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);
g_free (wcstr);

View File

@ -840,9 +840,9 @@ build_keypress_event (GdkWindowImplWin32 *impl,
MSG *msg)
{
HIMC himc;
gint i, bytecount, ucount, ucleft, len;
guchar buf[100], *bp;
wchar_t wbuf[100], *wcp;
gint i, bytecount, ucount;
guchar buf[100];
wchar_t wbuf[100];
event->key.type = GDK_KEY_PRESS;
event->key.time = msg->time;
@ -889,8 +889,7 @@ build_keypress_event (GdkWindowImplWin32 *impl,
*/
ucount = MultiByteToWideChar (impl->charset_info.ciACP,
0, buf, bytecount,
wbuf, sizeof (wbuf) / sizeof (wbuf[0]));
wbuf, G_N_ELEMENTS (wbuf));
}
if (ucount == 0)
event->key.keyval = GDK_VoidSymbol;
@ -911,68 +910,18 @@ build_keypress_event (GdkWindowImplWin32 *impl,
build_key_event_state (event);
/* Build UTF-8 string */
ucleft = ucount;
len = 0;
wcp = wbuf;
while (ucleft-- > 0)
if (ucount == 1 && wbuf[0] < 0200)
{
wchar_t c = *wcp++;
if (c < 0x80)
len += 1;
else if (c < 0x800)
len += 2;
else
len += 3;
event->key.string = g_malloc (2);
event->key.string[0] = wbuf[0];
event->key.string[1] = '\0';
event->key.length = 1;
}
event->key.string = g_malloc (len + 1);
event->key.length = len;
ucleft = ucount;
wcp = wbuf;
bp = event->key.string;
while (ucleft-- > 0)
else
{
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;
}
#if 1
/* 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;
}
#else
for (i = len - 1; i > 0; --i)
{
bp[i] = (c & 0x3f) | 0x80;
c >>= 6;
}
bp[0] = c | first;
#endif
bp += len;
event->key.string = _gdk_ucs2_to_utf8 (wbuf, ucount);
event->key.length = strlen (event->key.string);
}
*bp = 0;
}
static void
@ -1647,55 +1596,7 @@ gdk_event_translate (GdkEvent *event,
/* to translate coordinates to the internal > 16 bit system */
_gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
if (msg->message == gdk_selection_notify_msg)
{
GDK_NOTE (EVENTS, g_print ("gdk_selection_notify_msg: %#lx\n",
(gulong) msg->hwnd));
event->selection.type = GDK_SELECTION_NOTIFY;
event->selection.window = window;
event->selection.selection = GDK_POINTER_TO_ATOM (msg->wParam);
event->selection.target = GDK_POINTER_TO_ATOM (msg->lParam);
event->selection.property = _gdk_selection_property;
event->selection.time = msg->time;
return_val = !GDK_WINDOW_DESTROYED (window);
goto done;
}
else if (msg->message == gdk_selection_request_msg)
{
GDK_NOTE (EVENTS, g_print ("gdk_selection_request_msg: %#lx\n",
(gulong) msg->hwnd));
event->selection.type = GDK_SELECTION_REQUEST;
event->selection.window = window;
event->selection.selection = gdk_clipboard_atom;
event->selection.target = GDK_TARGET_STRING;
event->selection.property = _gdk_selection_property;
event->selection.requestor = (guint32) msg->hwnd;
event->selection.time = msg->time;
return_val = !GDK_WINDOW_DESTROYED (window);
goto done;
}
else if (msg->message == gdk_selection_clear_msg)
{
GDK_NOTE (EVENTS, g_print ("gdk_selection_clear_msg: %#lx\n",
(gulong) msg->hwnd));
event->selection.type = GDK_SELECTION_CLEAR;
event->selection.window = window;
event->selection.selection = GDK_POINTER_TO_ATOM (msg->wParam);
event->selection.target = GDK_POINTER_TO_ATOM (msg->lParam);
event->selection.time = msg->time;
return_val = !GDK_WINDOW_DESTROYED (window);
goto done;
}
else if (msg->message == msh_mousewheel_msg)
if (msg->message == msh_mousewheel_msg)
{
GDK_NOTE (EVENTS, g_print ("MSH_MOUSEWHEEL: %#lx %d\n",
(gulong) msg->hwnd, msg->wParam));

View File

@ -1907,8 +1907,8 @@ gdk_text_size (GdkFont *font,
}
else
{
if ((wlen = _gdk_win32_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
g_warning ("gdk_text_size: _gdk_win32_nmbstowchar_ts failed");
if ((wlen = _gdk_utf8_to_ucs2 (wcstr, text, text_length, text_length)) == -1)
g_warning ("gdk_text_size: _gdk_utf8_to_ucs2 failed");
else
_gdk_wchar_text_handle (font, wcstr, wlen, gdk_text_size_handler, arg);
}
@ -2014,8 +2014,8 @@ gdk_text_extents (GdkFont *font,
}
else
{
if ((wlen = _gdk_win32_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
g_warning ("gdk_text_extents: _gdk_win32_nmbstowchar_ts failed");
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);
}

View File

@ -28,16 +28,24 @@
#include "gdkprivate-win32.h"
HWND gdk_root_window = NULL;
gint gdk_event_func_from_window_proc = FALSE;
HDC gdk_display_hdc;
HINSTANCE gdk_dll_hinstance;
HINSTANCE gdk_app_hmodule;
UINT gdk_selection_notify_msg;
UINT gdk_selection_request_msg;
UINT gdk_selection_clear_msg;
GdkAtom gdk_clipboard_atom;
GdkAtom gdk_win32_dropfiles_atom;
GdkAtom gdk_ole2_dnd_atom;
WORD cf_rtf;
WORD cf_utf8_string;
GdkAtom utf8_string;
GdkAtom compound_text;
GdkAtom text_uri_list;
GdkAtom local_dnd;
GdkAtom gdk_win32_dropfiles;
GdkAtom gdk_ole2_dnd;
GdkAtom _gdk_selection_property;
DWORD windows_version = 0;
gint gdk_input_ignore_wintab = FALSE;
gint gdk_event_func_from_window_proc = FALSE;

View File

@ -151,26 +151,77 @@ gdk_wcstombs (const GdkWChar *src)
return mbstr;
}
/*
* 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!
*/
/* A vesion that converts from wchar_t strings to UTF-8 */
/* First a helper function for not zero-terminated strings */
static gint
gdk_nmbstowcs (GdkWChar *dest,
const gchar *src,
gint src_len,
gint dest_max)
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;
@ -240,22 +291,35 @@ gdk_nmbstowcs (GdkWChar *dest,
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_nmbstowcs (dest, src, strlen (src), dest_max);
return _gdk_utf8_to_wcs (dest, src, strlen (src), dest_max);
}
/* A version that converts to wchar_t wide chars */
/* A version that converts to a wchar_t string */
gint
_gdk_win32_nmbstowchar_ts (wchar_t *dest,
const gchar *src,
gint src_len,
gint dest_max)
_gdk_utf8_to_ucs2 (wchar_t *dest,
const gchar *src,
gint src_len,
gint dest_max)
{
wchar_t *wcp;
guchar *cp, *end;

View File

@ -86,14 +86,18 @@ _gdk_windowing_init_check (int argc,
CoInitialize (NULL);
gdk_selection_request_msg = RegisterWindowMessage ("gdk-selection-request");
gdk_selection_notify_msg = RegisterWindowMessage ("gdk-selection-notify");
gdk_selection_clear_msg = RegisterWindowMessage ("gdk-selection-clear");
cf_rtf = RegisterClipboardFormat ("Rich Text Format");
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);
local_dnd = gdk_atom_intern ("LocalDndSelection", FALSE);
gdk_win32_dropfiles = gdk_atom_intern ("DROPFILES_DND", FALSE);
gdk_ole2_dnd = gdk_atom_intern ("OLE2_DND", FALSE);
_gdk_selection_property = gdk_atom_intern ("GDK_SELECTION", FALSE);
gdk_clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE);
gdk_win32_dropfiles_atom = gdk_atom_intern ("DROPFILES_DND", FALSE);
gdk_ole2_dnd_atom = gdk_atom_intern ("OLE2_DND", FALSE);
_gdk_win32_selection_init ();

View File

@ -374,12 +374,12 @@ GdkImage *_gdk_win32_copy_to_image (GdkDrawable *drawable,
gint width,
gint height);
COLORREF _gdk_win32_colormap_color (GdkColormap *colormap,
gulong pixel);
COLORREF _gdk_win32_colormap_color (GdkColormap *colormap,
gulong pixel);
HRGN BitmapToRegion (HBITMAP hBmp);
HRGN BitmapToRegion (HBITMAP hBmp);
gchar *gdk_font_full_name_get (GdkFont *font);
gchar *gdk_font_full_name_get (GdkFont *font);
void _gdk_selection_property_store (GdkWindow *owner,
GdkAtom type,
@ -389,11 +389,16 @@ void _gdk_selection_property_store (GdkWindow *owner,
void _gdk_selection_property_delete (GdkWindow *);
gint _gdk_win32_nmbstowchar_ts (wchar_t *dest,
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,
@ -441,25 +446,33 @@ void gdk_win32_gdi_failed (const gchar *where,
extern LRESULT CALLBACK _gdk_win32_window_procedure (HWND, UINT, WPARAM, LPARAM);
extern HWND gdk_root_window;
extern gboolean gdk_event_func_from_window_proc;
extern HDC gdk_display_hdc;
extern HINSTANCE gdk_dll_hinstance;
extern HINSTANCE gdk_app_hmodule;
extern UINT gdk_selection_notify_msg;
extern UINT gdk_selection_request_msg;
extern UINT gdk_selection_clear_msg;
extern GdkAtom gdk_clipboard_atom;
extern GdkAtom gdk_win32_dropfiles_atom;
extern GdkAtom gdk_ole2_dnd_atom;
/* Registered clipboard formats */
extern WORD cf_rtf;
extern WORD cf_utf8_string;
/* GdkAtoms: Targets */
extern GdkAtom utf8_string;
extern GdkAtom compound_text;
extern GdkAtom text_uri_list;
/* DND selections */
extern GdkAtom local_dnd;
extern GdkAtom gdk_win32_dropfiles;
extern GdkAtom gdk_ole2_dnd;
extern GdkAtom _gdk_selection_property;
extern DWORD windows_version;
#define IS_WIN_NT() (windows_version < 0x80000000)
extern gint gdk_input_ignore_wintab;
extern GdkAtom _gdk_selection_property;
/* Options */
extern gboolean gdk_input_ignore_wintab;
extern gboolean gdk_event_func_from_window_proc;
#define IMAGE_PRIVATE_DATA(image) ((GdkImagePrivateWin32 *) GDK_IMAGE (image)->windowing_data)

View File

@ -1,5 +1,6 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
* Copyright (C) 1998-2002 Tor Lillqvist
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -25,6 +26,8 @@
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "gdkproperty.h"
#include "gdkselection.h"
@ -34,9 +37,9 @@ GdkAtom
gdk_atom_intern (const gchar *atom_name,
gint only_if_exists)
{
ATOM win32_atom;
GdkAtom retval;
static GHashTable *atom_hash = NULL;
ATOM win32_atom;
if (!atom_hash)
atom_hash = g_hash_table_new (g_str_hash, g_str_equal);
@ -68,17 +71,12 @@ gdk_atom_intern (const gchar *atom_name,
retval = GDK_SELECTION_TYPE_STRING;
else
{
win32_atom = GlobalFindAtom (atom_name);
if (only_if_exists && retval == 0)
win32_atom = 0;
else
win32_atom = GlobalAddAtom (atom_name);
win32_atom = GlobalAddAtom (atom_name);
retval = GUINT_TO_POINTER ((guint) win32_atom);
}
if (retval != GDK_NONE)
g_hash_table_insert (atom_hash,
g_strdup (atom_name),
retval);
g_hash_table_insert (atom_hash,
g_strdup (atom_name),
retval);
}
return retval;
@ -87,8 +85,8 @@ gdk_atom_intern (const gchar *atom_name,
gchar *
gdk_atom_name (GdkAtom atom)
{
gchar name[256];
ATOM win32_atom;
gchar name[256];
if (GDK_SELECTION_PRIMARY == atom) return g_strdup ("PRIMARY");
else if (GDK_SELECTION_SECONDARY == atom) return g_strdup ("SECONDARY");
@ -134,6 +132,108 @@ gdk_property_get (GdkWindow *window,
return FALSE;
}
static gboolean
find_common_locale (const guchar *data,
gint nelements,
gint nchars,
LCID *lcidp,
guchar **bufp,
gint *sizep)
{
static struct {
LCID lcid;
UINT cp;
} locales[] = {
#define ENTRY(lang, sublang) \
{ MAKELCID (MAKELANGID (LANG_##lang, SUBLANG_##sublang), SORT_DEFAULT), 0 }
ENTRY (ENGLISH, DEFAULT),
ENTRY (POLISH, DEFAULT),
ENTRY (CZECH, DEFAULT),
ENTRY (LITHUANIAN, DEFAULT),
ENTRY (RUSSIAN, DEFAULT),
ENTRY (GREEK, DEFAULT),
ENTRY (TURKISH, DEFAULT),
ENTRY (HEBREW, DEFAULT),
ENTRY (ARABIC, DEFAULT),
ENTRY (THAI, DEFAULT),
ENTRY (JAPANESE, DEFAULT),
ENTRY (CHINESE, CHINESE_SIMPLIFIED),
ENTRY (CHINESE, CHINESE_TRADITIONAL),
ENTRY (KOREAN, DEFAULT),
#undef ENTRY
};
static gboolean been_here = FALSE;
gint i;
wchar_t *wcs;
/* For each installed locale: Get the locale's default code page,
* and store the list of locales and code pages.
*/
if (!been_here)
{
been_here = TRUE;
for (i = 0; i < G_N_ELEMENTS (locales); i++)
if (IsValidLocale (locales[i].lcid, LCID_INSTALLED))
{
gchar buf[10];
if (GetLocaleInfo (locales[i].lcid, LOCALE_IDEFAULTANSICODEPAGE,
buf, sizeof (buf)))
{
gchar name[100];
locales[i].cp = atoi (buf);
GDK_NOTE (DND, (GetLocaleInfo (locales[i].lcid,
LOCALE_SENGLANGUAGE,
name, sizeof (name)),
g_print ("locale %#lx: %s: CP%d\n",
(gulong) locales[i].lcid, name,
locales[i].cp)));
}
}
}
/* Allocate bufp big enough to store data in any code page. Two
* 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);
/* Convert to Windows wide chars into temp buf */
_gdk_utf8_to_ucs2 (wcs, data, nelements, nchars);
wcs[nchars] = 0;
/* For each code page that is the default for an installed locale: */
for (i = 0; i < G_N_ELEMENTS (locales); i++)
{
BOOL used_default;
int nbytes;
if (locales[i].cp == 0)
continue;
/* Convert to that code page into bufp */
nbytes = WideCharToMultiByte (locales[i].cp, 0, wcs, -1,
*bufp, (nchars+1)*2,
NULL, &used_default);
if (!used_default)
{
/* This locale is good for the string */
g_free (wcs);
*lcidp = locales[i].lcid;
*sizep = nbytes;
return TRUE;
}
}
g_free (*bufp);
g_free (wcs);
return FALSE;
}
void
gdk_property_change (GdkWindow *window,
GdkAtom property,
@ -143,10 +243,17 @@ gdk_property_change (GdkWindow *window,
const guchar *data,
gint nelements)
{
HGLOBAL hdata;
gint i, length;
HGLOBAL hdata, hlcid, hutf8;
UINT cf = 0;
LCID lcid;
LCID *lcidptr;
GString *rtf = NULL;
gint i, size, nchars;
gchar *prop_name, *type_name;
guchar *ptr;
guchar *ucptr, *buf = NULL;
wchar_t *wcptr;
enum { PLAIN_ASCII, UNICODE_TEXT, SINGLE_LOCALE, RICH_TEXT } method;
gboolean ok = TRUE;
g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
@ -154,7 +261,7 @@ gdk_property_change (GdkWindow *window,
if (GDK_WINDOW_DESTROYED (window))
return;
GDK_NOTE (MISC,
GDK_NOTE (DND,
(prop_name = gdk_atom_name (property),
type_name = gdk_atom_name (type),
g_print ("gdk_property_change: %#x %#x (%s) %#x (%s) %s %d*%d bytes %.10s\n",
@ -174,40 +281,178 @@ gdk_property_change (GdkWindow *window,
&& format == 8
&& mode == GDK_PROP_MODE_REPLACE)
{
length = nelements;
for (i = 0; i < nelements; i++)
if (data[i] == '\n')
length++;
#if 1
GDK_NOTE (MISC, g_print ("...OpenClipboard(%#x)\n",
(guint) GDK_WINDOW_HWND (window)));
if (!OpenClipboard (GDK_WINDOW_HWND (window)))
{
WIN32_API_FAILED ("OpenClipboard");
return;
}
#endif
hdata = GlobalAlloc (GMEM_MOVEABLE|GMEM_DDESHARE, length + 1);
ptr = GlobalLock (hdata);
GDK_NOTE (MISC, g_print ("...hdata=%#x, ptr=%p\n", (guint) hdata, ptr));
/* Check if only ASCII */
for (i = 0; i < nelements; i++)
if (data[i] >= 0200)
break;
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 (*data == '\n')
*ptr++ = '\r';
*ptr++ = *data++;
/* If only ASCII, use CF_TEXT and the data as such. */
method = PLAIN_ASCII;
size = nelements;
for (i = 0; i < nelements; i++)
if (data[i] == '\n')
size++;
size++;
GDK_NOTE (DND, g_print ("...as text: %.40s\n", data));
}
*ptr++ = '\0';
else if (IS_WIN_NT ())
{
/* On NT, use CF_UNICODETEXT if any non-ASCII char present */
method = UNICODE_TEXT;
size = (nchars + 1) * 2;
GDK_NOTE (DND, g_print ("...as Unicode\n"));
}
else if (find_common_locale (data, nelements, nchars, &lcid, &buf, &size))
{
/* On Win9x, if all chars are in the default code page of
* some installed locale, use CF_TEXT and CF_LOCALE.
*/
method = SINGLE_LOCALE;
GDK_NOTE (DND, g_print ("...as text in locale %#lx %d bytes\n",
(gulong) lcid, size));
}
else
{
/* On Win9x, otherwise use RTF */
const guchar *p = data;
method = RICH_TEXT;
rtf = g_string_new ("{\\rtf1\\uc0 ");
while (p < data + nelements)
{
if (*p == '{' ||
*p == '\\' ||
*p == '}')
{
rtf = g_string_append_c (rtf, '\\');
rtf = g_string_append_c (rtf, *p);
p++;
}
else if (*p < 0200)
{
rtf = g_string_append_c (rtf, *p);
p++;
}
else
{
guchar *q;
gint n;
rtf = g_string_append (rtf, "\\uNNNNN ");
rtf->len -= 6; /* five digits and a space */
q = rtf->str + rtf->len;
n = sprintf (q, "%d ", g_utf8_get_char (p));
g_assert (n <= 6);
rtf->len += n;
p = g_utf8_next_char (p);
}
}
rtf = g_string_append (rtf, "}");
size = rtf->len + 1;
GDK_NOTE (DND, g_print ("...as RTF: %.40s\n", rtf->str));
}
if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, size)))
{
WIN32_API_FAILED ("GlobalAlloc");
if (!CloseClipboard ())
WIN32_API_FAILED ("CloseClipboard");
if (buf != NULL)
g_free (buf);
if (rtf != NULL)
g_string_free (rtf, TRUE);
return;
}
ucptr = GlobalLock (hdata);
switch (method)
{
case PLAIN_ASCII:
cf = CF_TEXT;
for (i = 0; i < nelements; i++)
{
if (*data == '\n')
*ucptr++ = '\r';
*ucptr++ = data[i];
}
*ucptr++ = '\0';
break;
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;
break;
case SINGLE_LOCALE:
cf = CF_TEXT;
memmove (ucptr, buf, size);
g_free (buf);
/* Set the CF_LOCALE clipboard data, too */
if (!(hlcid = GlobalAlloc (GMEM_MOVEABLE, sizeof (LCID))))
WIN32_API_FAILED ("GlobalAlloc"), ok = FALSE;
if (ok)
{
lcidptr = GlobalLock (hlcid);
*lcidptr = lcid;
GlobalUnlock (hlcid);
if (!SetClipboardData (CF_LOCALE, hlcid))
WIN32_API_FAILED ("SetClipboardData (CF_LOCALE)"), ok = FALSE;
}
break;
case RICH_TEXT:
cf = cf_rtf;
memmove (ucptr, rtf->str, size);
g_string_free (rtf, TRUE);
/* Set the UTF8_STRING clipboard data, too, for other
* GTK+ apps to use (won't bother reading RTF).
*/
if (!(hutf8 = GlobalAlloc (GMEM_MOVEABLE, nelements)))
WIN32_API_FAILED ("GlobalAlloc");
else
{
guchar *utf8ptr = GlobalLock (hutf8);
memmove (utf8ptr, data, nelements);
GlobalUnlock (hutf8);
if (!SetClipboardData (cf_utf8_string, hutf8))
WIN32_API_FAILED ("SetClipboardData (UTF8_STRING)");
}
break;
default:
g_assert_not_reached ();
}
GlobalUnlock (hdata);
GDK_NOTE (MISC, g_print ("...SetClipboardData(CF_TEXT, %#x)\n",
(guint) hdata));
if (!SetClipboardData(CF_TEXT, hdata))
WIN32_API_FAILED ("SetClipboardData");
#if 1
GDK_NOTE (MISC, g_print ("...CloseClipboard()\n"));
if (ok && !SetClipboardData (cf, hdata))
WIN32_API_FAILED ("SetClipboardData"), ok = FALSE;
if (!CloseClipboard ())
WIN32_API_FAILED ("CloseClipboard");
#endif
}
else
g_warning ("gdk_property_change: General case not implemented");
@ -222,7 +467,7 @@ gdk_property_delete (GdkWindow *window,
g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
GDK_NOTE (MISC,
GDK_NOTE (DND,
(prop_name = gdk_atom_name (property),
g_print ("gdk_property_delete: %#x %#x (%s)\n",
(window ? (guint) GDK_WINDOW_HWND (window) : 0),

View File

@ -1,5 +1,6 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
* Copyright (C) 1998-2002 Tor Lillqvist
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -25,13 +26,15 @@
*/
#include <string.h>
#include <stdlib.h>
#include "gdkproperty.h"
#include "gdkselection.h"
#include "gdkprivate-win32.h"
/* We emulate the GDK_SELECTION window properties by storing
* it's data in a per-window hashtable.
/* We emulate the GDK_SELECTION window properties of windows (as used
* in the X11 backend) by using a hash table from GdkWindows to
* GdkSelProp structs.
*/
typedef struct {
@ -43,11 +46,18 @@ typedef struct {
static GHashTable *sel_prop_table = NULL;
static GdkSelProp *dropfiles_prop = NULL;
/* We store the owner of each selection in this table. Obviously, this only
* is valid intra-app, and in fact it is necessary for the intra-app DND to work.
*/
static GHashTable *sel_owner_table = NULL;
void
_gdk_win32_selection_init (void)
{
if (sel_prop_table == NULL)
sel_prop_table = g_hash_table_new (g_int_hash, g_int_equal);
sel_prop_table = g_hash_table_new (NULL, NULL);
sel_owner_table = g_hash_table_new (NULL, NULL);
}
void
@ -59,18 +69,42 @@ _gdk_selection_property_store (GdkWindow *owner,
{
GdkSelProp *prop;
prop = g_hash_table_lookup (sel_prop_table, &GDK_WINDOW_HWND (owner));
prop = g_hash_table_lookup (sel_prop_table, GDK_WINDOW_HWND (owner));
if (prop != NULL)
{
g_free (prop->data);
g_hash_table_remove (sel_prop_table, &GDK_WINDOW_HWND (owner));
g_hash_table_remove (sel_prop_table, GDK_WINDOW_HWND (owner));
}
prop = g_new (GdkSelProp, 1);
prop->data = data;
prop->length = length;
prop->format = format;
prop->type = type;
g_hash_table_insert (sel_prop_table, &GDK_WINDOW_HWND (owner), prop);
g_hash_table_insert (sel_prop_table, GDK_WINDOW_HWND (owner), prop);
}
void
_gdk_dropfiles_store (gchar *data)
{
if (data != NULL)
{
g_assert (dropfiles_prop == NULL);
dropfiles_prop = g_new (GdkSelProp, 1);
dropfiles_prop->data = data;
dropfiles_prop->length = strlen (data);
dropfiles_prop->format = 8;
dropfiles_prop->type = text_uri_list;
}
else
{
if (dropfiles_prop != NULL)
{
g_free (dropfiles_prop->data);
g_free (dropfiles_prop);
}
dropfiles_prop = NULL;
}
}
gboolean
@ -79,24 +113,27 @@ gdk_selection_owner_set (GdkWindow *owner,
guint32 time,
gboolean send_event)
{
gchar *sel_name;
HWND xwindow;
GdkEvent tmp_event;
gchar *sel_name;
GDK_NOTE (MISC,
GDK_NOTE (DND,
(sel_name = gdk_atom_name (selection),
g_print ("gdk_selection_owner_set: %#x %#x (%s)\n",
(owner ? (guint) GDK_WINDOW_HWND (owner) : 0),
(guint) selection, sel_name),
g_free (sel_name)));
if (selection != gdk_clipboard_atom)
if (selection != GDK_SELECTION_CLIPBOARD)
{
if (!owner)
return FALSE;
_gdk_selection_property_store (owner, selection, 0, 0, 0);
if (owner != NULL)
g_hash_table_insert (sel_owner_table, selection, GDK_WINDOW_HWND (owner));
else
g_hash_table_remove (sel_owner_table, selection);
return TRUE;
}
/* Rest of this function handles the CLIPBOARD selection */
if (owner != NULL)
{
if (GDK_WINDOW_DESTROYED (owner))
@ -107,13 +144,11 @@ gdk_selection_owner_set (GdkWindow *owner,
else
xwindow = NULL;
GDK_NOTE (MISC, g_print ("...OpenClipboard(%#x)\n", (guint) xwindow));
if (!OpenClipboard (xwindow))
{
WIN32_API_FAILED ("OpenClipboard");
return FALSE;
}
GDK_NOTE (MISC, g_print ("...EmptyClipboard()\n"));
if (!EmptyClipboard ())
{
WIN32_API_FAILED ("EmptyClipboard");
@ -125,74 +160,52 @@ gdk_selection_owner_set (GdkWindow *owner,
if (xwindow != NULL)
SetClipboardData (CF_TEXT, NULL);
#endif
GDK_NOTE (MISC, g_print ("...CloseClipboard()\n"));
if (!CloseClipboard ())
{
WIN32_API_FAILED ("CloseClipboard");
return FALSE;
}
if (owner != NULL)
{
/* Send ourselves an ersatz selection request message so that
* gdk_property_change will be called to store the clipboard data.
/* Send ourselves a selection request message so that
* gdk_property_change will be called to store the clipboard
* data.
*/
SendMessage (xwindow, gdk_selection_request_msg,
GPOINTER_TO_UINT (GDK_ATOM_TO_POINTER (selection)), 0);
GDK_NOTE (DND, g_print ("...sending GDK_SELECTION_REQUEST to ourselves\n"));
tmp_event.selection.type = GDK_SELECTION_REQUEST;
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.property = _gdk_selection_property;
tmp_event.selection.requestor = (guint32) xwindow;
tmp_event.selection.time = time;
gdk_event_put (&tmp_event);
}
return TRUE;
}
/* callback for g_hash_table_for_each */
typedef struct {
GdkAtom atom;
GdkNativeWindow hwnd;
} SelectionAndHwnd;
static void
window_from_selection (gpointer key,
gpointer value,
gpointer user_data)
{
GdkSelProp *selprop = (GdkSelProp *)value;
SelectionAndHwnd *sah = (SelectionAndHwnd *) user_data;
if (selprop->type == sah->atom)
sah->hwnd = *(GdkNativeWindow*) key;
}
GdkWindow*
gdk_selection_owner_get (GdkAtom selection)
{
GdkWindow *window;
gchar *sel_name;
#if 0
/* XXX Hmm, gtk selections seem to work best with this. This causes
* gtk to always get the clipboard contents from Windows, and not
* from the editable's own stashed-away copy.
/* 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().
*/
return NULL;
#else
/* HB: The above is no longer true with recent changes to get
* inter-app drag&drop working ...
*/
if (selection != gdk_clipboard_atom)
{
SelectionAndHwnd sah;
sah.atom = selection;
sah.hwnd = 0;
g_hash_table_foreach (sel_prop_table, window_from_selection, &sah);
if (selection == GDK_SELECTION_CLIPBOARD)
return NULL;
window = gdk_win32_handle_table_lookup (sah.hwnd);
}
else
window = gdk_win32_handle_table_lookup ((GdkNativeWindow) GetClipboardOwner ());
window = gdk_window_lookup (g_hash_table_lookup (sel_owner_table, selection));
#endif
GDK_NOTE (MISC,
GDK_NOTE (DND,
(sel_name = gdk_atom_name (selection),
g_print ("gdk_selection_owner_get: %#x (%s) = %#x\n",
(guint) selection, sel_name,
@ -202,6 +215,27 @@ gdk_selection_owner_get (GdkAtom selection)
return window;
}
static void
generate_selection_notify (GdkWindow *requestor,
GdkAtom selection,
GdkAtom target,
GdkAtom property,
guint32 time)
{
GdkEvent tmp_event;
tmp_event.selection.type = GDK_SELECTION_NOTIFY;
tmp_event.selection.window = requestor;
tmp_event.selection.send_event = FALSE;
tmp_event.selection.selection = selection;
tmp_event.selection.target = target;
tmp_event.selection.property = property;
tmp_event.selection.requestor = 0;
tmp_event.selection.time = time;
gdk_event_put (&tmp_event);
}
void
gdk_selection_convert (GdkWindow *requestor,
GdkAtom selection,
@ -209,15 +243,14 @@ gdk_selection_convert (GdkWindow *requestor,
guint32 time)
{
HGLOBAL hdata;
guchar *ptr, *data, *datap, *p;
guint i, length, slength;
GdkAtom property = _gdk_selection_property;
gchar *sel_name, *tgt_name;
g_return_if_fail (requestor != NULL);
if (GDK_WINDOW_DESTROYED (requestor))
return;
GDK_NOTE (MISC,
GDK_NOTE (DND,
(sel_name = gdk_atom_name (selection),
tgt_name = gdk_atom_name (target),
g_print ("gdk_selection_convert: %#x %#x (%s) %#x (%s)\n",
@ -227,96 +260,188 @@ gdk_selection_convert (GdkWindow *requestor,
g_free (sel_name),
g_free (tgt_name)));
if (selection == gdk_clipboard_atom)
if (selection == GDK_SELECTION_CLIPBOARD &&
target == gdk_atom_intern ("TARGETS", FALSE))
{
/* Converting the CLIPBOARD selection means he wants the
* contents of the clipboard. Get the clipboard data,
* and store it for later.
/* He wants to know what formats are on the clipboard. If there
* is some kind of text, tell him so.
*/
GDK_NOTE (MISC, g_print ("...OpenClipboard(%#x)\n",
(guint) GDK_WINDOW_HWND (requestor)));
if (!OpenClipboard (GDK_WINDOW_HWND (requestor)))
{
WIN32_API_FAILED ("OpenClipboard");
return;
}
GDK_NOTE (MISC, g_print ("...GetClipboardData(CF_TEXT)\n"));
if ((hdata = GetClipboardData (CF_TEXT)) != NULL)
if (IsClipboardFormatAvailable (CF_UNICODETEXT) ||
IsClipboardFormatAvailable (cf_utf8_string) ||
IsClipboardFormatAvailable (CF_TEXT))
{
GdkAtom *data = g_new (GdkAtom, 1);
*data = GDK_TARGET_STRING;
_gdk_selection_property_store (requestor, GDK_SELECTION_TYPE_ATOM,
32, data, 1 * sizeof (GdkAtom));
}
else
property = GDK_NONE;
}
else if (selection == GDK_SELECTION_CLIPBOARD &&
(target == compound_text ||
target == GDK_TARGET_STRING))
{
/* Converting the CLIPBOARD selection means he wants the
* contents of the clipboard. Get the clipboard data,
* and store it for later.
*/
if (!OpenClipboard (GDK_WINDOW_HWND (requestor)))
{
WIN32_API_FAILED ("OpenClipboard");
return;
}
/* Try various formats. First the simplest, CF_UNICODETEXT. */
if ((hdata = GetClipboardData (CF_UNICODETEXT)) != NULL)
{
wchar_t *ptr, *wcs, *p, *q;
guchar *data;
gint length, wclen;
if ((ptr = GlobalLock (hdata)) != NULL)
{
length = GlobalSize (hdata);
GDK_NOTE (MISC, g_print ("...got data: %d bytes: %.10s\n",
length, ptr));
slength = 0;
GDK_NOTE (DND, g_print ("...CF_UNICODETEXT: %d bytes\n",
length));
/* Strip out \r */
wcs = g_new (wchar_t, (length + 1) * 2);
p = ptr;
for (i = 0; i < length; i++)
q = wcs;
wclen = 0;
while (*p)
{
if (*p == '\0')
break;
else if (*p != '\r')
slength++;
if (*p != '\r')
{
*q++ = *p;
wclen++;
}
p++;
}
data = _gdk_ucs2_to_utf8 (wcs, wclen);
g_free (wcs);
data = datap = g_malloc (slength + 1);
p = ptr;
for (i = 0; i < length; i++)
{
if (*p == '\0')
break;
else if (*p != '\r')
*datap++ = *p;
p++;
}
*datap++ = '\0';
_gdk_selection_property_store (requestor, GDK_TARGET_STRING, 8,
data, strlen (data) + 1);
_gdk_selection_property_store (requestor, target, 8,
data, strlen (data) + 1);
GlobalUnlock (hdata);
}
}
GDK_NOTE (MISC, g_print ("...CloseClipboard()\n"));
else if ((hdata = GetClipboardData (cf_utf8_string)) != NULL)
{
/* UTF8_STRING is a format we store ourselves when necessary */
guchar *ptr;
gint length;
if ((ptr = GlobalLock (hdata)) != NULL)
{
length = GlobalSize (hdata);
GDK_NOTE (DND, g_print ("...UTF8_STRING: %d bytes: %.10s\n",
length, ptr));
_gdk_selection_property_store (requestor, target, 8,
g_strdup (ptr), strlen (ptr) + 1);
GlobalUnlock (hdata);
}
}
else if ((hdata = GetClipboardData (CF_TEXT)) != NULL)
{
/* We must always assume the data can contain non-ASCII
* in either the current code page, or if there is CF_LOCALE
* data, in that locale's default code page.
*/
HGLOBAL hlcid;
UINT cp = CP_ACP;
wchar_t *wcs, *wcs2, *p, *q;
guchar *ptr, *data;
gint length, wclen;
if ((ptr = GlobalLock (hdata)) != NULL)
{
length = GlobalSize (hdata);
GDK_NOTE (DND, g_print ("...CF_TEXT: %d bytes: %.10s\n",
length, ptr));
if ((hlcid = GetClipboardData (CF_LOCALE)) != NULL)
{
gchar buf[10];
LCID *lcidptr = GlobalLock (hlcid);
if (GetLocaleInfo (*lcidptr, LOCALE_IDEFAULTANSICODEPAGE,
buf, sizeof (buf)))
{
cp = atoi (buf);
GDK_NOTE (DND, g_print ("...CF_LOCALE: %#lx cp:%d\n",
*lcidptr, cp));
}
GlobalUnlock (hlcid);
}
wcs = g_new (wchar_t, length + 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)
{
if (*p != '\r')
{
*q++ = *p;
wclen++;
}
p++;
}
g_free (wcs);
data = _gdk_ucs2_to_utf8 (wcs2, wclen);
g_free (wcs2);
_gdk_selection_property_store (requestor, target, 8,
data, strlen (data) + 1);
GlobalUnlock (hdata);
}
}
else
property = GDK_NONE;
CloseClipboard ();
/* Send ourselves an ersatz selection notify message so that we actually
* fetch the data.
*/
SendMessage (GDK_WINDOW_HWND (requestor), gdk_selection_notify_msg,
GPOINTER_TO_UINT (GDK_ATOM_TO_POINTER (selection)),
GPOINTER_TO_UINT (GDK_ATOM_TO_POINTER (target)));
}
else if (selection == gdk_win32_dropfiles_atom)
else if (selection == gdk_win32_dropfiles)
{
/* This means he wants the names of the dropped files.
* gdk_dropfiles_filter already has stored the text/uri-list
* data, tempoarily on gdk_root_parent's selection "property".
* data temporarily in dropfiles_prop.
*/
GdkSelProp *prop;
prop = g_hash_table_lookup (sel_prop_table,
&GDK_WINDOW_HWND (_gdk_parent_root));
if (prop != NULL)
if (dropfiles_prop != NULL)
{
g_hash_table_remove (sel_prop_table,
&GDK_WINDOW_HWND (_gdk_parent_root));
_gdk_selection_property_store (requestor, prop->type, prop->format,
prop->data, prop->length);
g_free (prop);
SendMessage (GDK_WINDOW_HWND (requestor), gdk_selection_notify_msg,
GPOINTER_TO_UINT (GDK_ATOM_TO_POINTER (selection)),
GPOINTER_TO_UINT (GDK_ATOM_TO_POINTER (target)));
_gdk_selection_property_store
(requestor, selection, dropfiles_prop->format,
dropfiles_prop->data, dropfiles_prop->length);
g_free (dropfiles_prop);
dropfiles_prop = NULL;
}
}
else
{
g_warning ("gdk_selection_convert: General case not implemented");
}
property = GDK_NONE;
/* Generate a selection notify message so that we actually fetch
* the data (if property == _gdk_selection_property) or indicating failure
* (if property == GDK_NONE).
*/
generate_selection_notify (requestor, selection, target, property, time);
}
gint
@ -333,21 +458,24 @@ gdk_selection_property_get (GdkWindow *requestor,
if (GDK_WINDOW_DESTROYED (requestor))
return 0;
GDK_NOTE (MISC, g_print ("gdk_selection_property_get: %#x\n",
GDK_NOTE (DND, g_print ("gdk_selection_property_get: %#x\n",
(guint) GDK_WINDOW_HWND (requestor)));
prop = g_hash_table_lookup (sel_prop_table, &GDK_WINDOW_HWND (requestor));
prop = g_hash_table_lookup (sel_prop_table, GDK_WINDOW_HWND (requestor));
if (prop == NULL)
{
*data = NULL;
return 0;
}
*data = g_malloc (prop->length);
if (prop->length > 0)
memmove (*data, prop->data, prop->length);
if (ret_type)
*ret_type = prop->type;
if (ret_format)
*ret_format = prop->format;
@ -359,14 +487,15 @@ _gdk_selection_property_delete (GdkWindow *window)
{
GdkSelProp *prop;
prop = g_hash_table_lookup (sel_prop_table, &GDK_WINDOW_HWND (window));
GDK_NOTE (DND, g_print ("_gdk_selection_property_delete: %#x\n",
(guint) GDK_WINDOW_HWND (window)));
prop = g_hash_table_lookup (sel_prop_table, GDK_WINDOW_HWND (window));
if (prop != NULL)
{
g_free (prop->data);
g_hash_table_remove (sel_prop_table, &GDK_WINDOW_HWND (window));
g_hash_table_remove (sel_prop_table, GDK_WINDOW_HWND (window));
}
else
g_warning ("huh?");
}
void
@ -376,9 +505,10 @@ gdk_selection_send_notify (guint32 requestor,
GdkAtom property,
guint32 time)
{
GdkEvent tmp_event;
gchar *sel_name, *tgt_name, *prop_name;
GDK_NOTE (MISC,
GDK_NOTE (DND,
(sel_name = gdk_atom_name (selection),
tgt_name = gdk_atom_name (target),
prop_name = gdk_atom_name (property),
@ -394,23 +524,31 @@ gdk_selection_send_notify (guint32 requestor,
/* 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
* Otherwise, if a gtkeditable does a copy to CLIPBOARD several times
* only the first one actually gets copied to the Windows clipboard,
* as only he first one causes a call to gdk_property_change.
* 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
* clipboard contents in gtk_editable_selection_clear as a result of
* this message. OTOH, when I changed gdk_selection_owner_get to
* always return NULL, it works. Sigh.
* clipboard contents in gtk_editable_selection_clear() as a result
* of this message. OTOH, when I changed gdk_selection_owner_get to
* return NULL for CLIPBOARD, it works. Sigh.
*/
SendMessage ((HWND) requestor,
gdk_selection_clear_msg,
GPOINTER_TO_UINT (GDK_ATOM_TO_POINTER (selection)),
GPOINTER_TO_UINT (GDK_ATOM_TO_POINTER (target)));
tmp_event.selection.type = GDK_SELECTION_CLEAR;
tmp_event.selection.window = gdk_window_lookup (requestor);
tmp_event.selection.send_event = FALSE;
tmp_event.selection.selection = selection;
tmp_event.selection.target = 0;
tmp_event.selection.property = 0;
tmp_event.selection.requestor = 0;
tmp_event.selection.time = time;
gdk_event_put (&tmp_event);
}
/* Simplistic implementations of text list and compound text functions */
gint
gdk_text_property_to_text_list (GdkAtom encoding,
gint format,
@ -418,10 +556,20 @@ gdk_text_property_to_text_list (GdkAtom encoding,
gint length,
gchar ***list)
{
GDK_NOTE (MISC,
g_print ("gdk_text_property_to_text_list not implemented\n"));
gchar *enc_name;
GDK_NOTE (DND, (enc_name = gdk_atom_name (encoding),
g_print ("gdk_text_property_to_text_list: %s %d %.20s %d\n",
enc_name, format, text, length),
g_free (enc_name)));
if (!list)
return 0;
*list = g_new (gchar **, 1);
**list = g_strdup (text);
return 0;
return 1;
}
void
@ -429,7 +577,8 @@ gdk_free_text_list (gchar **list)
{
g_return_if_fail (list != NULL);
/* ??? */
g_free (*list);
g_free (list);
}
gint
@ -439,7 +588,19 @@ gdk_string_to_compound_text (const gchar *str,
guchar **ctext,
gint *length)
{
g_warning ("gdk_string_to_compound_text: Not implemented");
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;
}
@ -447,7 +608,7 @@ gdk_string_to_compound_text (const gchar *str,
void
gdk_free_compound_text (guchar *ctext)
{
g_warning ("gdk_free_compound_text: Not implemented");
g_free (ctext);
}
/* These are lifted from gdkselection-x11.c, just to get GTK+ to build.
@ -534,7 +695,7 @@ make_list (const gchar *text,
* @list: location to store the list of strings or %NULL. The
* list should be freed with g_strfreev().
*
* Convert a text property in the giving encoding to
* Converts a text property in the giving encoding to
* a list of UTF-8 strings.
*
* Return value: the number of strings in the resulting
@ -554,7 +715,7 @@ gdk_text_property_to_utf8_list (GdkAtom encoding,
{
return make_list ((gchar *)text, length, TRUE, list);
}
else if (encoding == gdk_atom_intern ("UTF8_STRING", FALSE))
else if (encoding == utf8_string)
{
return make_list ((gchar *)text, length, FALSE, list);
}
@ -563,8 +724,8 @@ gdk_text_property_to_utf8_list (GdkAtom encoding,
gchar **local_list;
gint local_count;
gint i;
gchar *charset = NULL;
gboolean need_conversion= g_get_charset (&charset);
const gchar *charset = NULL;
gboolean need_conversion = g_get_charset (&charset);
gint count = 0;
GError *error = NULL;
@ -663,7 +824,7 @@ sanitize_utf8 (const gchar *src)
* gdk_utf8_to_string_target:
* @str: a UTF-8 string
*
* Convert an UTF-8 string into the best possible representation
* Converts an UTF-8 string into the best possible representation
* as a STRING. The representation of characters not in STRING
* is not specified; it may be as pseudo-escape sequences
* \x{ABCD}, or it may be in some other form of approximation.
@ -675,21 +836,7 @@ sanitize_utf8 (const gchar *src)
gchar *
gdk_utf8_to_string_target (const gchar *str)
{
GError *error = NULL;
gchar *tmp_str = sanitize_utf8 (str);
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;
return sanitize_utf8 (str);
}
/**
@ -701,10 +848,10 @@ gdk_utf8_to_string_target (const gchar *str)
* @length: location to store the length of the data
* stored in @ctext
*
* Convert from UTF-8 to compound text.
* Converts from UTF-8 to compound text.
*
* Return value: %TRUE if the conversion succeeded, otherwise
* false.
* %FALSE.
**/
gboolean
gdk_utf8_to_compound_text (const gchar *str,
@ -714,14 +861,14 @@ gdk_utf8_to_compound_text (const gchar *str,
gint *length)
{
gboolean need_conversion;
gchar *charset;
const gchar *charset;
gchar *locale_str, *tmp_str;
GError *error = NULL;
gboolean result;
g_return_val_if_fail (str != NULL, FALSE);
need_conversion = g_get_charset (&charset);
need_conversion = !g_get_charset (&charset);
tmp_str = sanitize_utf8 (str);

View File

@ -2422,7 +2422,7 @@ gdk_window_stick (GdkWindow *window)
/* "stick" means stick to all desktops _and_ do not scroll with the
* viewport. i.e. glue to the monitor glass in all cases.
*/
g_warning ("gdk_window_stick (0x%X) ???", GDK_WINDOW_HWND (window));
g_warning ("gdk_window_stick (%#x) ???", (guint) GDK_WINDOW_HWND (window));
}
else
{
@ -2443,7 +2443,7 @@ gdk_window_unstick (GdkWindow *window)
if (GDK_WINDOW_IS_MAPPED (window))
{
g_warning ("gdk_window_unstick (0x%X) ???", GDK_WINDOW_HWND (window));
g_warning ("gdk_window_unstick (%#x) ???", (guint) GDK_WINDOW_HWND (window));
}
else
{
@ -2451,7 +2451,6 @@ gdk_window_unstick (GdkWindow *window)
gdk_synthesize_window_state (window,
GDK_WINDOW_STATE_STICKY,
0);
}
}
@ -2555,8 +2554,8 @@ gdk_window_set_type_hint (GdkWindow *window,
* XXX ???
*/
GDK_NOTE (MISC,
g_print ("gdk_window_set_type_hint (0x%0X)\n",
GDK_WINDOW_HWND (window)));
g_print ("gdk_window_set_type_hint (%#x)\n",
(guint) GDK_WINDOW_HWND (window)));
}
void