summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Lillqvist <tml@iki.fi>2002-01-10 00:53:39 +0000
committerTor Lillqvist <tml@src.gnome.org>2002-01-10 00:53:39 +0000
commit1b7cff475571cf24c70c52ec6b3aa859f578b011 (patch)
treea85b17cb316fbb5908730ca2f07de6bca4745b0a
parentf3f0ad29f101b3701a3e379c7100e6dc90d89740 (diff)
downloadgtk+-1b7cff475571cf24c70c52ec6b3aa859f578b011.tar.gz
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.
-rw-r--r--ChangeLog94
-rw-r--r--ChangeLog.pre-2-094
-rw-r--r--ChangeLog.pre-2-1094
-rw-r--r--ChangeLog.pre-2-294
-rw-r--r--ChangeLog.pre-2-494
-rw-r--r--ChangeLog.pre-2-694
-rw-r--r--ChangeLog.pre-2-894
-rw-r--r--gdk/win32/gdkdnd-win32.c95
-rw-r--r--gdk/win32/gdkdrawable-win32.c4
-rw-r--r--gdk/win32/gdkevents-win32.c125
-rw-r--r--gdk/win32/gdkfont-win32.c8
-rw-r--r--gdk/win32/gdkglobals-win32.c22
-rw-r--r--gdk/win32/gdkim-win32.c112
-rw-r--r--gdk/win32/gdkmain-win32.c16
-rw-r--r--gdk/win32/gdkprivate-win32.h43
-rw-r--r--gdk/win32/gdkproperty-win32.c321
-rw-r--r--gdk/win32/gdkselection-win32.c471
-rw-r--r--gdk/win32/gdkwindow-win32.c9
18 files changed, 1457 insertions, 427 deletions
diff --git a/ChangeLog b/ChangeLog
index 66b608339b..5a5f0ef172 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0
index 66b608339b..5a5f0ef172 100644
--- a/ChangeLog.pre-2-0
+++ b/ChangeLog.pre-2-0
@@ -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
diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10
index 66b608339b..5a5f0ef172 100644
--- a/ChangeLog.pre-2-10
+++ b/ChangeLog.pre-2-10
@@ -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
diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2
index 66b608339b..5a5f0ef172 100644
--- a/ChangeLog.pre-2-2
+++ b/ChangeLog.pre-2-2
@@ -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
diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4
index 66b608339b..5a5f0ef172 100644
--- a/ChangeLog.pre-2-4
+++ b/ChangeLog.pre-2-4
@@ -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
diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6
index 66b608339b..5a5f0ef172 100644
--- a/ChangeLog.pre-2-6
+++ b/ChangeLog.pre-2-6
@@ -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
diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8
index 66b608339b..5a5f0ef172 100644
--- a/ChangeLog.pre-2-8
+++ b/ChangeLog.pre-2-8
@@ -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
diff --git a/gdk/win32/gdkdnd-win32.c b/gdk/win32/gdkdnd-win32.c
index 04883fcced..33a13a66ed 100644
--- a/gdk/win32/gdkdnd-win32.c
+++ b/gdk/win32/gdkdnd-win32.c
@@ -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;
}
diff --git a/gdk/win32/gdkdrawable-win32.c b/gdk/win32/gdkdrawable-win32.c
index 4f94df3299..e42b3426c1 100644
--- a/gdk/win32/gdkdrawable-win32.c
+++ b/gdk/win32/gdkdrawable-win32.c
@@ -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);
diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c
index 3c8a0af8a2..0a0bbd0c5b 100644
--- a/gdk/win32/gdkevents-win32.c
+++ b/gdk/win32/gdkevents-win32.c
@@ -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));
diff --git a/gdk/win32/gdkfont-win32.c b/gdk/win32/gdkfont-win32.c
index 264c160b89..c7cde75a2e 100644
--- a/gdk/win32/gdkfont-win32.c
+++ b/gdk/win32/gdkfont-win32.c
@@ -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);
}
diff --git a/gdk/win32/gdkglobals-win32.c b/gdk/win32/gdkglobals-win32.c
index 6deedaf626..6a6a248d0f 100644
--- a/gdk/win32/gdkglobals-win32.c
+++ b/gdk/win32/gdkglobals-win32.c
@@ -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;
diff --git a/gdk/win32/gdkim-win32.c b/gdk/win32/gdkim-win32.c
index 52b70ab68b..40019a2d32 100644
--- a/gdk/win32/gdkim-win32.c
+++ b/gdk/win32/gdkim-win32.c
@@ -151,26 +151,77 @@ gdk_wcstombs (const GdkWChar *src)
return mbstr;
}
+/* 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);
-/*
- * 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!
- */
+ wcp = src;
+ bp = mbstr;
+ while (wcp < src + src_len)
+ {
+ int first;
+ wchar_t c = *wcp++;
-/* First a helper function for not zero-terminated strings */
-static gint
-gdk_nmbstowcs (GdkWChar *dest,
- const gchar *src,
- gint src_len,
- gint dest_max)
+ 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;
diff --git a/gdk/win32/gdkmain-win32.c b/gdk/win32/gdkmain-win32.c
index 73d5461f1b..54e5eedc0e 100644
--- a/gdk/win32/gdkmain-win32.c
+++ b/gdk/win32/gdkmain-win32.c
@@ -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 ();
diff --git a/gdk/win32/gdkprivate-win32.h b/gdk/win32/gdkprivate-win32.h
index a238475172..e8a2f7b7cd 100644
--- a/gdk/win32/gdkprivate-win32.h
+++ b/gdk/win32/gdkprivate-win32.h
@@ -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,26 +446,34 @@ 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;
-extern DWORD windows_version;
-#define IS_WIN_NT() (windows_version < 0x80000000)
+/* GdkAtoms: Targets */
+extern GdkAtom utf8_string;
+extern GdkAtom compound_text;
+extern GdkAtom text_uri_list;
-extern gint gdk_input_ignore_wintab;
+/* 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)
+
+/* 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)
#endif /* __GDK_PRIVATE_WIN32_H__ */
diff --git a/gdk/win32/gdkproperty-win32.c b/gdk/win32/gdkproperty-win32.c
index caaa13cc6f..1609d90ff9 100644
--- a/gdk/win32/gdkproperty-win32.c
+++ b/gdk/win32/gdkproperty-win32.c
@@ -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 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));
+ }
+ 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)))
{
- if (*data == '\n')
- *ptr++ = '\r';
- *ptr++ = *data++;
+ 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 ();
}
- *ptr++ = '\0';
+
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),
diff --git a/gdk/win32/gdkselection-win32.c b/gdk/win32/gdkselection-win32.c
index 1e53eefa2f..c8e6174c8b 100644
--- a/gdk/win32/gdkselection-win32.c
+++ b/gdk/win32/gdkselection-win32.c
@@ -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;
-#else
- /* HB: The above is no longer true with recent changes to get
- * inter-app drag&drop working ...
+ /* 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_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 ());
-
-#endif
+ window = gdk_window_lookup (g_hash_table_lookup (sel_owner_table, selection));
- 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))
+ {
+ /* He wants to know what formats are on the clipboard. If there
+ * is some kind of text, tell him so.
+ */
+ if (!OpenClipboard (GDK_WINDOW_HWND (requestor)))
+ {
+ WIN32_API_FAILED ("OpenClipboard");
+ return;
+ }
+
+ 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.
*/
- 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)
+ /* 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++)
+ _gdk_selection_property_store (requestor, target, 8,
+ data, strlen (data) + 1);
+ GlobalUnlock (hdata);
+ }
+ }
+ 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 == '\0')
- break;
- else if (*p != '\r')
- *datap++ = *p;
+ if (*p != '\r')
+ {
+ *q++ = *p;
+ wclen++;
+ }
p++;
}
- *datap++ = '\0';
- _gdk_selection_property_store (requestor, GDK_TARGET_STRING, 8,
- data, strlen (data) + 1);
+ 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);
}
}
- GDK_NOTE (MISC, g_print ("...CloseClipboard()\n"));
- CloseClipboard ();
-
+ else
+ property = GDK_NONE;
- /* 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)));
+ CloseClipboard ();
}
- 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);
diff --git a/gdk/win32/gdkwindow-win32.c b/gdk/win32/gdkwindow-win32.c
index a7467d3b80..c5562c3df5 100644
--- a/gdk/win32/gdkwindow-win32.c
+++ b/gdk/win32/gdkwindow-win32.c
@@ -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