diff options
author | Tor Lillqvist <tml@iki.fi> | 2002-01-10 00:53:39 +0000 |
---|---|---|
committer | Tor Lillqvist <tml@src.gnome.org> | 2002-01-10 00:53:39 +0000 |
commit | 1b7cff475571cf24c70c52ec6b3aa859f578b011 (patch) | |
tree | a85b17cb316fbb5908730ca2f07de6bca4745b0a | |
parent | f3f0ad29f101b3701a3e379c7100e6dc90d89740 (diff) | |
download | gtk+-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-- | ChangeLog | 94 | ||||
-rw-r--r-- | ChangeLog.pre-2-0 | 94 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 94 | ||||
-rw-r--r-- | ChangeLog.pre-2-2 | 94 | ||||
-rw-r--r-- | ChangeLog.pre-2-4 | 94 | ||||
-rw-r--r-- | ChangeLog.pre-2-6 | 94 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 94 | ||||
-rw-r--r-- | gdk/win32/gdkdnd-win32.c | 95 | ||||
-rw-r--r-- | gdk/win32/gdkdrawable-win32.c | 4 | ||||
-rw-r--r-- | gdk/win32/gdkevents-win32.c | 125 | ||||
-rw-r--r-- | gdk/win32/gdkfont-win32.c | 8 | ||||
-rw-r--r-- | gdk/win32/gdkglobals-win32.c | 22 | ||||
-rw-r--r-- | gdk/win32/gdkim-win32.c | 112 | ||||
-rw-r--r-- | gdk/win32/gdkmain-win32.c | 16 | ||||
-rw-r--r-- | gdk/win32/gdkprivate-win32.h | 43 | ||||
-rw-r--r-- | gdk/win32/gdkproperty-win32.c | 321 | ||||
-rw-r--r-- | gdk/win32/gdkselection-win32.c | 471 | ||||
-rw-r--r-- | gdk/win32/gdkwindow-win32.c | 9 |
18 files changed, 1457 insertions, 427 deletions
@@ -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 |