diff options
-rw-r--r-- | ChangeLog | 77 | ||||
-rw-r--r-- | ChangeLog.pre-2-0 | 77 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 77 | ||||
-rw-r--r-- | ChangeLog.pre-2-2 | 77 | ||||
-rw-r--r-- | ChangeLog.pre-2-4 | 77 | ||||
-rw-r--r-- | ChangeLog.pre-2-6 | 77 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 77 | ||||
-rw-r--r-- | gdk/Makefile.am | 3 | ||||
-rw-r--r-- | gdk/gdk.c | 774 | ||||
-rw-r--r-- | gdk/gdk.h | 63 | ||||
-rw-r--r-- | gdk/gdkdraw.c | 60 | ||||
-rw-r--r-- | gdk/gdkfont.c | 106 | ||||
-rw-r--r-- | gdk/gdkglobals.c | 4 | ||||
-rw-r--r-- | gdk/gdki18n.h | 123 | ||||
-rw-r--r-- | gdk/gdkprivate.h | 17 | ||||
-rw-r--r-- | gdk/gdktypes.h | 70 | ||||
-rw-r--r-- | gdk/gdkwindow.c | 7 | ||||
-rw-r--r-- | gdk/x11/gdkfont-x11.c | 106 | ||||
-rw-r--r-- | gdk/x11/gdkglobals-x11.c | 4 | ||||
-rw-r--r-- | gdk/x11/gdkmain-x11.c | 774 | ||||
-rw-r--r-- | gdk/x11/gdkwindow-x11.c | 7 | ||||
-rw-r--r-- | gtk/gtkeditable.c | 58 | ||||
-rw-r--r-- | gtk/gtkeditable.h | 15 | ||||
-rw-r--r-- | gtk/gtkentry.c | 702 | ||||
-rw-r--r-- | gtk/gtkentry.h | 26 | ||||
-rw-r--r-- | gtk/gtkmain.c | 39 | ||||
-rw-r--r-- | gtk/gtkprivate.h | 6 | ||||
-rw-r--r-- | gtk/gtkspinbutton.c | 32 | ||||
-rw-r--r-- | gtk/gtktext.c | 596 | ||||
-rw-r--r-- | gtk/gtktext.h | 19 | ||||
-rw-r--r-- | gtk/gtkwidget.c | 22 | ||||
-rw-r--r-- | gtk/testgtk.c | 24 | ||||
-rw-r--r-- | gtk/testgtkrc | 4 | ||||
-rw-r--r-- | tests/testgtk.c | 24 | ||||
-rw-r--r-- | tests/testgtkrc | 4 |
35 files changed, 1931 insertions, 2297 deletions
@@ -1,3 +1,80 @@ +Mon Dec 7 10:27:09 1998 Owen Taylor <otaylor@redhat.com> + + * gtk/gtkwidget.c: Destroy widgets _after_ propagating unrealize + signals through the widget heirarchy. This is unpleasant, as it + causes more X traffic, but is necessary, because we have to clean + up our Input Contexts before destroying the X windows. + (from matsu-981109-0.patch) + +Mon Dec 7 10:18:18 1998 Owen Taylor <otaylor@redhat.com> + + Applied gtk-a-higuti-981202-0 : + [ a-higuti@math.sci.hokudai.ac.jp (Akira Higuchi) ] + + * gdk/gdk.h gdk/gdk.c + (gdk_mbstowcs): New function. Nearly equals to mbstowcs, but + implemented by a combination of Xlib functions, so + it works even with X_LOCALE. + (gdk_wcstombs): New function. + (g_mbtowc): Removed. No longer needed. + + * gdk/gdk.h gdk/gdkfont.c gdk/gdkdraw.c: + Added _wc() variants to gdk_text_width(), + gdk_char_width(), gdk_draw_text(), + + * gdk/gdki18n.h + (mblen, mbtowc, wctomb, mbstowcs, wcstombs, + wcslen, wcscpy, wcsncpy): + Removed. No longer needed. + (iswalnum): Removed. + (gdk_iswalnum): New macro. + (gdk_iswspace): New macro. + * gdk/gdktype.h + (GdkWChar): New typedef. + + * gtk/gtkentry.h, gtk/gtkentry.c + There are many changes according to the change of the + internal representation of text, from multibyte string + to wide characters. + * gtk/gtkprivate.h, gtk/gtkmain.c + Removed the variable gtk_use_mb and related codes. + * gtk/gtkspinbutton.c + Some changes according to the change of type of entry->text. + * gtk/gtktext.h, gtk/gtktext.c + Changed the internal representation of text. We use GdkWchar + if a fontset is supplied. If not, we use guchar to save + memory. + +Tue Dec 1 15:20:39 1998 Owen Taylor <otaylor@redhat.com> + + * gdk/gdkwindow.c (gdk_window_new): When creating + a window with a specified non-system visual, use + a matching colormap. + +Mon Nov 30 11:50:13 1998 Owen Taylor <otaylor@redhat.com> + + * gdk/gdk.c gdk/gdkim.c gdk/gdkprivate.h gdk/gdk.h + gdk/gdktypes.h gtk/gtkeditable.c gtk/gtkmain.c + gtk/gtkentry.c gtk/gtktext.c: + + Applied matsu-981109-0 + [ matsu@arch.comp.kyutech.ac.jp (Takashi Matsuda) ] + + - Change system of setting input method values + from varargs to a structure, similar to GC's + or window attributes. + + - Various fixes to event handling. + + Also: + + * gdk/gdkim.c: Split of input method stuff into + a separate source file. + + * Remove GdkIM typedef, change everything from + GdkIC to GdkIC * to be consistent with the + rest of GTK. + Wed Dec 9 00:41:41 1998 Owen Taylor <otaylor@redhat.com> * gtk/gtkrc.c (gtk_rc_add_initial_default_files): Allocate diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index af8d9629b3..c37d061508 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,80 @@ +Mon Dec 7 10:27:09 1998 Owen Taylor <otaylor@redhat.com> + + * gtk/gtkwidget.c: Destroy widgets _after_ propagating unrealize + signals through the widget heirarchy. This is unpleasant, as it + causes more X traffic, but is necessary, because we have to clean + up our Input Contexts before destroying the X windows. + (from matsu-981109-0.patch) + +Mon Dec 7 10:18:18 1998 Owen Taylor <otaylor@redhat.com> + + Applied gtk-a-higuti-981202-0 : + [ a-higuti@math.sci.hokudai.ac.jp (Akira Higuchi) ] + + * gdk/gdk.h gdk/gdk.c + (gdk_mbstowcs): New function. Nearly equals to mbstowcs, but + implemented by a combination of Xlib functions, so + it works even with X_LOCALE. + (gdk_wcstombs): New function. + (g_mbtowc): Removed. No longer needed. + + * gdk/gdk.h gdk/gdkfont.c gdk/gdkdraw.c: + Added _wc() variants to gdk_text_width(), + gdk_char_width(), gdk_draw_text(), + + * gdk/gdki18n.h + (mblen, mbtowc, wctomb, mbstowcs, wcstombs, + wcslen, wcscpy, wcsncpy): + Removed. No longer needed. + (iswalnum): Removed. + (gdk_iswalnum): New macro. + (gdk_iswspace): New macro. + * gdk/gdktype.h + (GdkWChar): New typedef. + + * gtk/gtkentry.h, gtk/gtkentry.c + There are many changes according to the change of the + internal representation of text, from multibyte string + to wide characters. + * gtk/gtkprivate.h, gtk/gtkmain.c + Removed the variable gtk_use_mb and related codes. + * gtk/gtkspinbutton.c + Some changes according to the change of type of entry->text. + * gtk/gtktext.h, gtk/gtktext.c + Changed the internal representation of text. We use GdkWchar + if a fontset is supplied. If not, we use guchar to save + memory. + +Tue Dec 1 15:20:39 1998 Owen Taylor <otaylor@redhat.com> + + * gdk/gdkwindow.c (gdk_window_new): When creating + a window with a specified non-system visual, use + a matching colormap. + +Mon Nov 30 11:50:13 1998 Owen Taylor <otaylor@redhat.com> + + * gdk/gdk.c gdk/gdkim.c gdk/gdkprivate.h gdk/gdk.h + gdk/gdktypes.h gtk/gtkeditable.c gtk/gtkmain.c + gtk/gtkentry.c gtk/gtktext.c: + + Applied matsu-981109-0 + [ matsu@arch.comp.kyutech.ac.jp (Takashi Matsuda) ] + + - Change system of setting input method values + from varargs to a structure, similar to GC's + or window attributes. + + - Various fixes to event handling. + + Also: + + * gdk/gdkim.c: Split of input method stuff into + a separate source file. + + * Remove GdkIM typedef, change everything from + GdkIC to GdkIC * to be consistent with the + rest of GTK. + Wed Dec 9 00:41:41 1998 Owen Taylor <otaylor@redhat.com> * gtk/gtkrc.c (gtk_rc_add_initial_default_files): Allocate diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index af8d9629b3..c37d061508 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,80 @@ +Mon Dec 7 10:27:09 1998 Owen Taylor <otaylor@redhat.com> + + * gtk/gtkwidget.c: Destroy widgets _after_ propagating unrealize + signals through the widget heirarchy. This is unpleasant, as it + causes more X traffic, but is necessary, because we have to clean + up our Input Contexts before destroying the X windows. + (from matsu-981109-0.patch) + +Mon Dec 7 10:18:18 1998 Owen Taylor <otaylor@redhat.com> + + Applied gtk-a-higuti-981202-0 : + [ a-higuti@math.sci.hokudai.ac.jp (Akira Higuchi) ] + + * gdk/gdk.h gdk/gdk.c + (gdk_mbstowcs): New function. Nearly equals to mbstowcs, but + implemented by a combination of Xlib functions, so + it works even with X_LOCALE. + (gdk_wcstombs): New function. + (g_mbtowc): Removed. No longer needed. + + * gdk/gdk.h gdk/gdkfont.c gdk/gdkdraw.c: + Added _wc() variants to gdk_text_width(), + gdk_char_width(), gdk_draw_text(), + + * gdk/gdki18n.h + (mblen, mbtowc, wctomb, mbstowcs, wcstombs, + wcslen, wcscpy, wcsncpy): + Removed. No longer needed. + (iswalnum): Removed. + (gdk_iswalnum): New macro. + (gdk_iswspace): New macro. + * gdk/gdktype.h + (GdkWChar): New typedef. + + * gtk/gtkentry.h, gtk/gtkentry.c + There are many changes according to the change of the + internal representation of text, from multibyte string + to wide characters. + * gtk/gtkprivate.h, gtk/gtkmain.c + Removed the variable gtk_use_mb and related codes. + * gtk/gtkspinbutton.c + Some changes according to the change of type of entry->text. + * gtk/gtktext.h, gtk/gtktext.c + Changed the internal representation of text. We use GdkWchar + if a fontset is supplied. If not, we use guchar to save + memory. + +Tue Dec 1 15:20:39 1998 Owen Taylor <otaylor@redhat.com> + + * gdk/gdkwindow.c (gdk_window_new): When creating + a window with a specified non-system visual, use + a matching colormap. + +Mon Nov 30 11:50:13 1998 Owen Taylor <otaylor@redhat.com> + + * gdk/gdk.c gdk/gdkim.c gdk/gdkprivate.h gdk/gdk.h + gdk/gdktypes.h gtk/gtkeditable.c gtk/gtkmain.c + gtk/gtkentry.c gtk/gtktext.c: + + Applied matsu-981109-0 + [ matsu@arch.comp.kyutech.ac.jp (Takashi Matsuda) ] + + - Change system of setting input method values + from varargs to a structure, similar to GC's + or window attributes. + + - Various fixes to event handling. + + Also: + + * gdk/gdkim.c: Split of input method stuff into + a separate source file. + + * Remove GdkIM typedef, change everything from + GdkIC to GdkIC * to be consistent with the + rest of GTK. + Wed Dec 9 00:41:41 1998 Owen Taylor <otaylor@redhat.com> * gtk/gtkrc.c (gtk_rc_add_initial_default_files): Allocate diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index af8d9629b3..c37d061508 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,80 @@ +Mon Dec 7 10:27:09 1998 Owen Taylor <otaylor@redhat.com> + + * gtk/gtkwidget.c: Destroy widgets _after_ propagating unrealize + signals through the widget heirarchy. This is unpleasant, as it + causes more X traffic, but is necessary, because we have to clean + up our Input Contexts before destroying the X windows. + (from matsu-981109-0.patch) + +Mon Dec 7 10:18:18 1998 Owen Taylor <otaylor@redhat.com> + + Applied gtk-a-higuti-981202-0 : + [ a-higuti@math.sci.hokudai.ac.jp (Akira Higuchi) ] + + * gdk/gdk.h gdk/gdk.c + (gdk_mbstowcs): New function. Nearly equals to mbstowcs, but + implemented by a combination of Xlib functions, so + it works even with X_LOCALE. + (gdk_wcstombs): New function. + (g_mbtowc): Removed. No longer needed. + + * gdk/gdk.h gdk/gdkfont.c gdk/gdkdraw.c: + Added _wc() variants to gdk_text_width(), + gdk_char_width(), gdk_draw_text(), + + * gdk/gdki18n.h + (mblen, mbtowc, wctomb, mbstowcs, wcstombs, + wcslen, wcscpy, wcsncpy): + Removed. No longer needed. + (iswalnum): Removed. + (gdk_iswalnum): New macro. + (gdk_iswspace): New macro. + * gdk/gdktype.h + (GdkWChar): New typedef. + + * gtk/gtkentry.h, gtk/gtkentry.c + There are many changes according to the change of the + internal representation of text, from multibyte string + to wide characters. + * gtk/gtkprivate.h, gtk/gtkmain.c + Removed the variable gtk_use_mb and related codes. + * gtk/gtkspinbutton.c + Some changes according to the change of type of entry->text. + * gtk/gtktext.h, gtk/gtktext.c + Changed the internal representation of text. We use GdkWchar + if a fontset is supplied. If not, we use guchar to save + memory. + +Tue Dec 1 15:20:39 1998 Owen Taylor <otaylor@redhat.com> + + * gdk/gdkwindow.c (gdk_window_new): When creating + a window with a specified non-system visual, use + a matching colormap. + +Mon Nov 30 11:50:13 1998 Owen Taylor <otaylor@redhat.com> + + * gdk/gdk.c gdk/gdkim.c gdk/gdkprivate.h gdk/gdk.h + gdk/gdktypes.h gtk/gtkeditable.c gtk/gtkmain.c + gtk/gtkentry.c gtk/gtktext.c: + + Applied matsu-981109-0 + [ matsu@arch.comp.kyutech.ac.jp (Takashi Matsuda) ] + + - Change system of setting input method values + from varargs to a structure, similar to GC's + or window attributes. + + - Various fixes to event handling. + + Also: + + * gdk/gdkim.c: Split of input method stuff into + a separate source file. + + * Remove GdkIM typedef, change everything from + GdkIC to GdkIC * to be consistent with the + rest of GTK. + Wed Dec 9 00:41:41 1998 Owen Taylor <otaylor@redhat.com> * gtk/gtkrc.c (gtk_rc_add_initial_default_files): Allocate diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index af8d9629b3..c37d061508 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,80 @@ +Mon Dec 7 10:27:09 1998 Owen Taylor <otaylor@redhat.com> + + * gtk/gtkwidget.c: Destroy widgets _after_ propagating unrealize + signals through the widget heirarchy. This is unpleasant, as it + causes more X traffic, but is necessary, because we have to clean + up our Input Contexts before destroying the X windows. + (from matsu-981109-0.patch) + +Mon Dec 7 10:18:18 1998 Owen Taylor <otaylor@redhat.com> + + Applied gtk-a-higuti-981202-0 : + [ a-higuti@math.sci.hokudai.ac.jp (Akira Higuchi) ] + + * gdk/gdk.h gdk/gdk.c + (gdk_mbstowcs): New function. Nearly equals to mbstowcs, but + implemented by a combination of Xlib functions, so + it works even with X_LOCALE. + (gdk_wcstombs): New function. + (g_mbtowc): Removed. No longer needed. + + * gdk/gdk.h gdk/gdkfont.c gdk/gdkdraw.c: + Added _wc() variants to gdk_text_width(), + gdk_char_width(), gdk_draw_text(), + + * gdk/gdki18n.h + (mblen, mbtowc, wctomb, mbstowcs, wcstombs, + wcslen, wcscpy, wcsncpy): + Removed. No longer needed. + (iswalnum): Removed. + (gdk_iswalnum): New macro. + (gdk_iswspace): New macro. + * gdk/gdktype.h + (GdkWChar): New typedef. + + * gtk/gtkentry.h, gtk/gtkentry.c + There are many changes according to the change of the + internal representation of text, from multibyte string + to wide characters. + * gtk/gtkprivate.h, gtk/gtkmain.c + Removed the variable gtk_use_mb and related codes. + * gtk/gtkspinbutton.c + Some changes according to the change of type of entry->text. + * gtk/gtktext.h, gtk/gtktext.c + Changed the internal representation of text. We use GdkWchar + if a fontset is supplied. If not, we use guchar to save + memory. + +Tue Dec 1 15:20:39 1998 Owen Taylor <otaylor@redhat.com> + + * gdk/gdkwindow.c (gdk_window_new): When creating + a window with a specified non-system visual, use + a matching colormap. + +Mon Nov 30 11:50:13 1998 Owen Taylor <otaylor@redhat.com> + + * gdk/gdk.c gdk/gdkim.c gdk/gdkprivate.h gdk/gdk.h + gdk/gdktypes.h gtk/gtkeditable.c gtk/gtkmain.c + gtk/gtkentry.c gtk/gtktext.c: + + Applied matsu-981109-0 + [ matsu@arch.comp.kyutech.ac.jp (Takashi Matsuda) ] + + - Change system of setting input method values + from varargs to a structure, similar to GC's + or window attributes. + + - Various fixes to event handling. + + Also: + + * gdk/gdkim.c: Split of input method stuff into + a separate source file. + + * Remove GdkIM typedef, change everything from + GdkIC to GdkIC * to be consistent with the + rest of GTK. + Wed Dec 9 00:41:41 1998 Owen Taylor <otaylor@redhat.com> * gtk/gtkrc.c (gtk_rc_add_initial_default_files): Allocate diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index af8d9629b3..c37d061508 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,80 @@ +Mon Dec 7 10:27:09 1998 Owen Taylor <otaylor@redhat.com> + + * gtk/gtkwidget.c: Destroy widgets _after_ propagating unrealize + signals through the widget heirarchy. This is unpleasant, as it + causes more X traffic, but is necessary, because we have to clean + up our Input Contexts before destroying the X windows. + (from matsu-981109-0.patch) + +Mon Dec 7 10:18:18 1998 Owen Taylor <otaylor@redhat.com> + + Applied gtk-a-higuti-981202-0 : + [ a-higuti@math.sci.hokudai.ac.jp (Akira Higuchi) ] + + * gdk/gdk.h gdk/gdk.c + (gdk_mbstowcs): New function. Nearly equals to mbstowcs, but + implemented by a combination of Xlib functions, so + it works even with X_LOCALE. + (gdk_wcstombs): New function. + (g_mbtowc): Removed. No longer needed. + + * gdk/gdk.h gdk/gdkfont.c gdk/gdkdraw.c: + Added _wc() variants to gdk_text_width(), + gdk_char_width(), gdk_draw_text(), + + * gdk/gdki18n.h + (mblen, mbtowc, wctomb, mbstowcs, wcstombs, + wcslen, wcscpy, wcsncpy): + Removed. No longer needed. + (iswalnum): Removed. + (gdk_iswalnum): New macro. + (gdk_iswspace): New macro. + * gdk/gdktype.h + (GdkWChar): New typedef. + + * gtk/gtkentry.h, gtk/gtkentry.c + There are many changes according to the change of the + internal representation of text, from multibyte string + to wide characters. + * gtk/gtkprivate.h, gtk/gtkmain.c + Removed the variable gtk_use_mb and related codes. + * gtk/gtkspinbutton.c + Some changes according to the change of type of entry->text. + * gtk/gtktext.h, gtk/gtktext.c + Changed the internal representation of text. We use GdkWchar + if a fontset is supplied. If not, we use guchar to save + memory. + +Tue Dec 1 15:20:39 1998 Owen Taylor <otaylor@redhat.com> + + * gdk/gdkwindow.c (gdk_window_new): When creating + a window with a specified non-system visual, use + a matching colormap. + +Mon Nov 30 11:50:13 1998 Owen Taylor <otaylor@redhat.com> + + * gdk/gdk.c gdk/gdkim.c gdk/gdkprivate.h gdk/gdk.h + gdk/gdktypes.h gtk/gtkeditable.c gtk/gtkmain.c + gtk/gtkentry.c gtk/gtktext.c: + + Applied matsu-981109-0 + [ matsu@arch.comp.kyutech.ac.jp (Takashi Matsuda) ] + + - Change system of setting input method values + from varargs to a structure, similar to GC's + or window attributes. + + - Various fixes to event handling. + + Also: + + * gdk/gdkim.c: Split of input method stuff into + a separate source file. + + * Remove GdkIM typedef, change everything from + GdkIC to GdkIC * to be consistent with the + rest of GTK. + Wed Dec 9 00:41:41 1998 Owen Taylor <otaylor@redhat.com> * gtk/gtkrc.c (gtk_rc_add_initial_default_files): Allocate diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index af8d9629b3..c37d061508 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,80 @@ +Mon Dec 7 10:27:09 1998 Owen Taylor <otaylor@redhat.com> + + * gtk/gtkwidget.c: Destroy widgets _after_ propagating unrealize + signals through the widget heirarchy. This is unpleasant, as it + causes more X traffic, but is necessary, because we have to clean + up our Input Contexts before destroying the X windows. + (from matsu-981109-0.patch) + +Mon Dec 7 10:18:18 1998 Owen Taylor <otaylor@redhat.com> + + Applied gtk-a-higuti-981202-0 : + [ a-higuti@math.sci.hokudai.ac.jp (Akira Higuchi) ] + + * gdk/gdk.h gdk/gdk.c + (gdk_mbstowcs): New function. Nearly equals to mbstowcs, but + implemented by a combination of Xlib functions, so + it works even with X_LOCALE. + (gdk_wcstombs): New function. + (g_mbtowc): Removed. No longer needed. + + * gdk/gdk.h gdk/gdkfont.c gdk/gdkdraw.c: + Added _wc() variants to gdk_text_width(), + gdk_char_width(), gdk_draw_text(), + + * gdk/gdki18n.h + (mblen, mbtowc, wctomb, mbstowcs, wcstombs, + wcslen, wcscpy, wcsncpy): + Removed. No longer needed. + (iswalnum): Removed. + (gdk_iswalnum): New macro. + (gdk_iswspace): New macro. + * gdk/gdktype.h + (GdkWChar): New typedef. + + * gtk/gtkentry.h, gtk/gtkentry.c + There are many changes according to the change of the + internal representation of text, from multibyte string + to wide characters. + * gtk/gtkprivate.h, gtk/gtkmain.c + Removed the variable gtk_use_mb and related codes. + * gtk/gtkspinbutton.c + Some changes according to the change of type of entry->text. + * gtk/gtktext.h, gtk/gtktext.c + Changed the internal representation of text. We use GdkWchar + if a fontset is supplied. If not, we use guchar to save + memory. + +Tue Dec 1 15:20:39 1998 Owen Taylor <otaylor@redhat.com> + + * gdk/gdkwindow.c (gdk_window_new): When creating + a window with a specified non-system visual, use + a matching colormap. + +Mon Nov 30 11:50:13 1998 Owen Taylor <otaylor@redhat.com> + + * gdk/gdk.c gdk/gdkim.c gdk/gdkprivate.h gdk/gdk.h + gdk/gdktypes.h gtk/gtkeditable.c gtk/gtkmain.c + gtk/gtkentry.c gtk/gtktext.c: + + Applied matsu-981109-0 + [ matsu@arch.comp.kyutech.ac.jp (Takashi Matsuda) ] + + - Change system of setting input method values + from varargs to a structure, similar to GC's + or window attributes. + + - Various fixes to event handling. + + Also: + + * gdk/gdkim.c: Split of input method stuff into + a separate source file. + + * Remove GdkIM typedef, change everything from + GdkIC to GdkIC * to be consistent with the + rest of GTK. + Wed Dec 9 00:41:41 1998 Owen Taylor <otaylor@redhat.com> * gtk/gtkrc.c (gtk_rc_add_initial_default_files): Allocate diff --git a/gdk/Makefile.am b/gdk/Makefile.am index ec4f78af9a..2766b3781a 100644 --- a/gdk/Makefile.am +++ b/gdk/Makefile.am @@ -24,6 +24,7 @@ libgdk_la_SOURCES = \ gdkfont.c \ gdkgc.c \ gdkglobals.c \ + gdkim.c \ gdkimage.c \ gdkinput.c \ gdkinput.h \ @@ -53,7 +54,7 @@ gdkinclude_HEADERS = \ gdk.h \ gdkcursors.h \ gdkrgb.h \ - gdki18n.h \ + gdki18n.h \ gdkkeysyms.h \ gdkprivate.h \ gdktypes.h \ @@ -28,9 +28,6 @@ #include <stdlib.h> #include <string.h> #include <limits.h> -#ifdef USE_XIM -#include <stdarg.h> -#endif #ifdef HAVE_SYS_SELECT_H #include <sys/select.h> @@ -42,16 +39,13 @@ #include <X11/Xos.h> #include <X11/Xutil.h> #include <X11/Xmu/WinUtil.h> -#ifdef USE_XIM -#include <X11/Xresource.h> -#endif #include <X11/cursorfont.h> #include "gdk.h" #include "gdkprivate.h" #include "gdkinput.h" +#include "gdki18n.h" #include "gdkx.h" #include "gdkkeysyms.h" -#include "gdki18n.h" #ifndef X_GETTIMEOFDAY #define X_GETTIMEOFDAY(tv) gettimeofday (tv, NULL) @@ -139,21 +133,6 @@ static int gdk_x_error (Display *display, static int gdk_x_io_error (Display *display); static RETSIGTYPE gdk_signal (int signum); - -#ifdef USE_XIM -static guint gdk_im_va_count (va_list list); -static XVaNestedList gdk_im_va_to_nested (va_list list, - guint count); - -static GdkIM gdk_im_get (void); -static gint gdk_im_open (XrmDatabase db, - gchar* res_name, - gchar* rec_class); -static void gdk_im_close (void); -static void gdk_ic_cleanup (void); - -#endif /* USE_XIM */ - GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev, GdkEvent *event, gpointer data); @@ -212,17 +191,6 @@ static GdkWindowPrivate *xgrab_window = NULL; /* Window that currently holds static GList *client_filters; /* Filters for client messages */ -#ifdef USE_XIM -static gint xim_using; /* using XIM Protocol if TRUE */ -static GdkIM xim_im; /* global IM */ -static XIMStyles* xim_styles; /* im supports these styles */ -static XIMStyle xim_best_allowed_style; -static GdkICPrivate *xim_ic; /* currently using IC */ -static GdkWindow* xim_window; /* currently using Widow */ -static GList* xim_ic_list; - -#endif - static GList *putback_events = NULL; static gulong base_id; @@ -570,18 +538,7 @@ gdk_init (int *argc, gdk_wm_protocols_filter, NULL); #ifdef USE_XIM - /* initialize XIM Protocol variables */ - xim_using = FALSE; - xim_im = NULL; - xim_styles = NULL; - if (!(xim_best_allowed_style & GDK_IM_PREEDIT_MASK)) - gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS); - if (!(xim_best_allowed_style & GDK_IM_STATUS_MASK)) - gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS); - xim_ic = NULL; - xim_window = (GdkWindow*)NULL; - - gdk_im_open (NULL, NULL, NULL); + gdk_im_open (); #endif gdk_initialized = 1; @@ -1005,16 +962,22 @@ gdk_event_get (void) * has occurred. Read it. */ #ifdef USE_XIM - gint filter_status; - if (xim_using && xim_window) - do - { /* don't dispatch events used by IM */ - XNextEvent (gdk_display, &xevent); - filter_status = XFilterEvent (&xevent, - GDK_WINDOW_XWINDOW (xim_window)); - } while (filter_status == True); - else - XNextEvent (gdk_display, &xevent); + Window w = None; + + XNextEvent (gdk_display, &xevent); + if (gdk_xim_window) + switch (xevent.type) + { + case KeyPress: + case KeyRelease: + case ButtonPress: + case ButtonRelease: + w = GDK_WINDOW_XWINDOW (gdk_xim_window); + break; + } + + if (XFilterEvent (&xevent, w)) + return NULL; #else XNextEvent (gdk_display, &xevent); #endif @@ -2067,13 +2030,6 @@ gdk_event_translate (GdkEvent *event, if (window != NULL) gdk_window_ref (window); -#ifdef USE_XIM - else if (XFilterEvent(xevent, None)) /* for xlib XIM handling */ - return FALSE; -#endif - else - GDK_NOTE (EVENTS, - g_message ("Got event for unknown window: %#lx\n", xevent->xany.window)); event->any.window = window; event->any.send_event = xevent->xany.send_event; @@ -2088,17 +2044,46 @@ gdk_event_translate (GdkEvent *event, /* Check for filters for this window */ GdkFilterReturn result; + +#ifdef USE_XIM + if (window == NULL && + xevent->type == KeyPress && + gdk_xim_window && + !((GdkWindowPrivate *) gdk_xim_window)->destroyed) + { + /* + * If user presses a key in Preedit or Status window, keypress event + * is sometimes sent to these windows. These windows are not managed + * by GDK, so we redirect KeyPress event to gdk_xim_window. + * + * If someone want to use the window whitch is not managed by GDK + * and want to get KeyPress event, he/she must register the filter + * function to gdk_default_filters to intercept the event. + */ + + window = gdk_xim_window; + window_private = (GdkWindowPrivate *) window; + gdk_window_ref (window); + event->any.window = window; + + GDK_NOTE (XIM, + g_message ("KeyPress event is redirected to gdk_xim_window: %#lx", + xevent->xany.window)); + } +#endif /* USE_XIM */ + result = gdk_event_apply_filters (xevent, event, window_private ?window_private->filters :gdk_default_filters); if (result != GDK_FILTER_CONTINUE) - { - return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE; - } + return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE; } + if (window == NULL) + g_message ("Got event for unknown window: %#lx\n", xevent->xany.window); + /* We do a "manual" conversion of the XEvent to a * GdkEvent. The structures are mostly the same so * the conversion is fairly straightforward. We also @@ -2121,12 +2106,12 @@ gdk_event_translate (GdkEvent *event, } keysym = GDK_VoidSymbol; - if (xim_using == TRUE && xim_ic) + if (gdk_xim_ic && gdk_xim_ic->xic) { Status status; /* Clear keyval. Depending on status, may not be set */ - charcount = XmbLookupString(xim_ic->xic, + charcount = XmbLookupString(gdk_xim_ic->xic, &xevent->xkey, buf, buf_len-1, &keysym, &status); if (status == XBufferOverflow) @@ -2139,7 +2124,7 @@ gdk_event_translate (GdkEvent *event, buf_len *= 2; buf = (gchar *) g_realloc (buf, buf_len); - charcount = XmbLookupString (xim_ic->xic, + charcount = XmbLookupString (gdk_xim_ic->xic, &xevent->xkey, buf, buf_len-1, &keysym, &status); } @@ -2520,6 +2505,13 @@ gdk_event_translate (GdkEvent *event, (xevent->xany.type == FocusIn) ? "in" : "out", xevent->xfocus.window - base_id)); + /* gdk_keyboard_grab() causes following events. These events confuse + * the XIM focus, so ignore them. + */ + if (xevent->xfocus.mode == NotifyGrab || + xevent->xfocus.mode == NotifyUngrab) + break; + event->focus_change.type = GDK_FOCUS_CHANGE; event->focus_change.window = window; event->focus_change.in = (xevent->xany.type == FocusIn); @@ -3186,652 +3178,6 @@ gdk_signal (int sig_num) #endif /* !G_ENABLE_DEBUG */ } -#ifdef USE_XIM - -/* The following routines duplicate functionality in Xlib to - * translate from varargs to X's internal opaque XVaNestedList. - * - * If all vendors have stuck close to the reference implementation, - * then we should hopefully be OK. - */ - -/* This needs to match XIMArg as defined in Xlcint.h exactly */ - -typedef struct { - gchar *name; - gpointer value; -} GdkImArg; - -/************************************************************* - * gdk_im_va_count: - * Counts the number of name/value pairs in the vararg list - * - * arguments: - * - * results: - *************************************************************/ - -static guint -gdk_im_va_count (va_list list) -{ - gint count = 0; - gchar *name; - - name = va_arg (list, gchar *); - while (name) - { - count++; - (void)va_arg (list, gpointer); - name = va_arg (list, gchar *); - } - - return count; -} - -/************************************************************* - * gdk_im_va_to_nested: - * Given a varargs list and the result of gdk_im_va_count, - * create a XVaNestedList. - * - * arguments: - * - * results: - *************************************************************/ - -static XVaNestedList -gdk_im_va_to_nested (va_list list, guint count) -{ - GdkImArg *result; - GdkImArg *arg; - - gchar *name; - - if (count == 0) - return NULL; - - result = g_new (GdkImArg, count+1); - arg = result; - - name = va_arg (list, gchar *); - while (name) - { - arg->name = name; - arg->value = va_arg (list, gpointer); - arg++; - name = va_arg (list, gchar *); - } - - arg->name = NULL; - - return (XVaNestedList)result; -} - -/* - *-------------------------------------------------------------- - * gdk_im_begin - * - * Begin using input method with XIM Protocol(X11R6 standard) - * - * Arguments: - * "ic" is the "Input Context" which is created by gtk_ic_new. - * The input area is specified with "window". - * - * Results: - * The gdk's event handling routine is switched to XIM based routine. - * XIM based routine uses XFilterEvent to get rid of events used by IM, - * and uses XmbLookupString instead of XLookupString. - * - * Side effects: - * - *-------------------------------------------------------------- - */ - -void -gdk_im_begin (GdkIC ic, GdkWindow* window) -{ - GdkICPrivate *private; - Window xwin; - - g_return_if_fail (ic != NULL); - g_return_if_fail (window); - - private = (GdkICPrivate *) ic; - - xim_using = TRUE; - xim_ic = private; - xim_window = window; - if (gdk_im_ready()) - { - XGetICValues (private->xic, XNFocusWindow, &xwin, NULL); - if (xwin != GDK_WINDOW_XWINDOW(window)) - XSetICValues (private->xic, XNFocusWindow, - GDK_WINDOW_XWINDOW(window), NULL); - if (private != xim_ic) - XSetICFocus (private->xic); - } -} - -/* - *-------------------------------------------------------------- - * gdk_im_end - * - * End using input method with XIM Protocol(X11R6 standard) - * - * Arguments: - * - * Results: - * The gdk's event handling routine is switched to normal routine. - * User should call this function before ic and window will be destroyed. - * - * Side effects: - * - *-------------------------------------------------------------- - */ - -void -gdk_im_end (void) -{ - xim_using = FALSE; - xim_ic = NULL; - xim_window = NULL; -} - -static GdkIM -gdk_im_get (void) -{ - return xim_im; -} - -static GdkIMStyle -gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2) -{ - GdkIMStyle s1, s2, u; - - if (style1 == 0) return style2; - if (style2 == 0) return style1; - if ((style1 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK)) - == (style2 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK))) - return style1; - - s1 = style1 & GDK_IM_PREEDIT_MASK; - s2 = style2 & GDK_IM_PREEDIT_MASK; - u = s1 | s2; - if (s1 != s2) { - if (u & GDK_IM_PREEDIT_CALLBACKS) - return (s1 == GDK_IM_PREEDIT_CALLBACKS)? style1:style2; - else if (u & GDK_IM_PREEDIT_POSITION) - return (s1 == GDK_IM_PREEDIT_POSITION)? style1:style2; - else if (u & GDK_IM_PREEDIT_AREA) - return (s1 == GDK_IM_PREEDIT_AREA)? style1:style2; - else if (u & GDK_IM_PREEDIT_NOTHING) - return (s1 == GDK_IM_PREEDIT_NOTHING)? style1:style2; - } else { - s1 = style1 & GDK_IM_STATUS_MASK; - s2 = style2 & GDK_IM_STATUS_MASK; - u = s1 | s2; - if ( u & GDK_IM_STATUS_CALLBACKS) - return (s1 == GDK_IM_STATUS_CALLBACKS)? style1:style2; - else if ( u & GDK_IM_STATUS_AREA) - return (s1 == GDK_IM_STATUS_AREA)? style1:style2; - else if ( u & GDK_IM_STATUS_NOTHING) - return (s1 == GDK_IM_STATUS_NOTHING)? style1:style2; - else if ( u & GDK_IM_STATUS_NONE) - return (s1 == GDK_IM_STATUS_NONE)? style1:style2; - } - return 0; /* Get rid of stupid warning */ -} - -GdkIMStyle -gdk_im_decide_style (GdkIMStyle supported_style) -{ - gint i; - GdkIMStyle style, tmp; - - g_return_val_if_fail (xim_styles != NULL, 0); - - style = 0; - for (i=0; i<xim_styles->count_styles; i++) - { - tmp = xim_styles->supported_styles[i]; - if (tmp == (tmp & supported_style & xim_best_allowed_style)) - style = gdk_im_choose_better_style (style, tmp); - } - return style; -} - -GdkIMStyle -gdk_im_set_best_style (GdkIMStyle style) -{ - if (style & GDK_IM_PREEDIT_MASK) - { - xim_best_allowed_style &= ~GDK_IM_PREEDIT_MASK; - - xim_best_allowed_style |= GDK_IM_PREEDIT_NONE; - if (!(style & GDK_IM_PREEDIT_NONE)) - { - xim_best_allowed_style |= GDK_IM_PREEDIT_NOTHING; - if (!(style & GDK_IM_PREEDIT_NOTHING)) - { - xim_best_allowed_style |= GDK_IM_PREEDIT_AREA; - if (!(style & GDK_IM_PREEDIT_AREA)) - { - xim_best_allowed_style |= GDK_IM_PREEDIT_POSITION; - if (!(style & GDK_IM_PREEDIT_POSITION)) - xim_best_allowed_style |= GDK_IM_PREEDIT_CALLBACKS; - } - } - } - } - if (style & GDK_IM_STATUS_MASK) - { - xim_best_allowed_style &= ~GDK_IM_STATUS_MASK; - - xim_best_allowed_style |= GDK_IM_STATUS_NONE; - if (!(style & GDK_IM_STATUS_NONE)) - { - xim_best_allowed_style |= GDK_IM_STATUS_NOTHING; - if (!(style & GDK_IM_STATUS_NOTHING)) - { - xim_best_allowed_style |= GDK_IM_STATUS_AREA; - if (!(style & GDK_IM_STATUS_AREA)) - xim_best_allowed_style |= GDK_IM_STATUS_CALLBACKS; - } - } - } - - return xim_best_allowed_style; -} - -static gint -gdk_im_open (XrmDatabase db, gchar* res_name, gchar* res_class) -{ - xim_im = XOpenIM (GDK_DISPLAY(), db, res_name, res_class); - if (xim_im == NULL) - { - GDK_NOTE (XIM, g_warning ("Unable to open open IM.")); - return FALSE; - } - XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL); - - return TRUE; -} - -static void -gdk_im_close (void) -{ - if (xim_im) - { - XCloseIM (xim_im); - xim_im = NULL; - } - if (xim_styles) - { - XFree (xim_styles); - xim_styles = NULL; - } -} - -gint -gdk_im_ready (void) -{ - return (xim_im != NULL); -} - -GdkIC -gdk_ic_new (GdkWindow* client_window, - GdkWindow* focus_window, - GdkIMStyle style, ...) -{ - va_list list; - GdkICPrivate *private; - XVaNestedList preedit_attr = NULL; - guint count; - - g_return_val_if_fail (client_window != NULL, NULL); - g_return_val_if_fail (focus_window != NULL, NULL); - g_return_val_if_fail (gdk_im_ready(), NULL); - - private = g_new (GdkICPrivate, 1); - - va_start (list, style); - count = gdk_im_va_count (list); - va_end (list); - - va_start (list, style); - preedit_attr = gdk_im_va_to_nested (list, count); - va_end (list); - - private->style = gdk_im_decide_style (style); - if (private->style != style) - { - g_warning ("can not create input context with specified input style."); - g_free (private); - return NULL; - } - - private->xic = XCreateIC(gdk_im_get (), - XNInputStyle, style, - XNClientWindow, GDK_WINDOW_XWINDOW (client_window), - XNFocusWindow, GDK_WINDOW_XWINDOW (focus_window), - preedit_attr? XNPreeditAttributes : NULL, preedit_attr, - NULL); - - g_free (preedit_attr); - - if (!private->xic) - { - g_free (private); - return NULL; - } - - xim_ic_list = g_list_append (xim_ic_list, private); - return private; -} - -void -gdk_ic_destroy (GdkIC ic) -{ - GdkICPrivate *private; - - g_return_if_fail (ic != NULL); - - private = (GdkICPrivate *) ic; - - if (xim_ic == private) - gdk_im_end (); - - XDestroyIC (private->xic); - xim_ic_list = g_list_remove (xim_ic_list, private); - g_free (private); -} - -GdkIMStyle -gdk_ic_get_style (GdkIC ic) -{ - GdkICPrivate *private; - - g_return_val_if_fail (ic != NULL, 0); - - private = (GdkICPrivate *) ic; - - return private->style; -} - -void -gdk_ic_set_values (GdkIC ic, ...) -{ - va_list list; - XVaNestedList args; - GdkICPrivate *private; - guint count; - - g_return_if_fail (ic != NULL); - - private = (GdkICPrivate *) ic; - - va_start (list, ic); - count = gdk_im_va_count (list); - va_end (list); - - va_start (list, ic); - args = gdk_im_va_to_nested (list, count); - va_end (list); - - XSetICValues (private->xic, XNVaNestedList, args, NULL); - - g_free (args); -} - -void -gdk_ic_get_values (GdkIC ic, ...) -{ - va_list list; - XVaNestedList args; - GdkICPrivate *private; - guint count; - - g_return_if_fail (ic != NULL); - - private = (GdkICPrivate *) ic; - - va_start (list, ic); - count = gdk_im_va_count (list); - va_end (list); - - va_start (list, ic); - args = gdk_im_va_to_nested (list, count); - va_end (list); - - XGetICValues (private->xic, XNVaNestedList, args, NULL); - - g_free (args); -} - -void -gdk_ic_set_attr (GdkIC ic, const char *target, ...) -{ - va_list list; - XVaNestedList attr; - GdkICPrivate *private; - guint count; - - g_return_if_fail (ic != NULL); - g_return_if_fail (target != NULL); - - private = (GdkICPrivate *) ic; - - va_start (list, target); - count = gdk_im_va_count (list); - va_end (list); - - va_start (list, target); - attr = gdk_im_va_to_nested (list, count); - va_end (list); - - XSetICValues (private->xic, target, attr, NULL); - - g_free (attr); -} - -void -gdk_ic_get_attr (GdkIC ic, const char *target, ...) -{ - va_list list; - XVaNestedList attr; - GdkICPrivate *private; - guint count; - - g_return_if_fail (ic != NULL); - g_return_if_fail (target != NULL); - - private = (GdkICPrivate *) ic; - - va_start (list, target); - count = gdk_im_va_count (list); - va_end (list); - - va_start (list, target); - attr = gdk_im_va_to_nested (list, count); - va_end (list); - - XGetICValues (private->xic, target, attr, NULL); - - g_free (attr); -} - -GdkEventMask -gdk_ic_get_events (GdkIC ic) -{ - GdkEventMask mask; - glong xmask; - glong bit; - GdkICPrivate *private; - gint i; - - /* From gdkwindow.c */ - extern int nevent_masks; - extern int event_mask_table[]; - - g_return_val_if_fail (ic != NULL, 0); - - private = (GdkICPrivate *) ic; - - if (XGetICValues (private->xic, XNFilterEvents, &xmask, NULL) != NULL) - { - GDK_NOTE (XIM, g_warning ("Call to XGetICValues: %s failed", XNFilterEvents)); - return 0; - } - - mask = 0; - for (i=0, bit=2; i < nevent_masks; i++, bit <<= 1) - if (xmask & event_mask_table [i]) - { - mask |= bit; - xmask &= ~ event_mask_table [i]; - } - - if (xmask) - g_warning ("ic requires events not supported by the application (%#04lx)", xmask); - - return mask; -} - -static void -gdk_ic_cleanup (void) -{ - GList* node; - gint destroyed; - GdkICPrivate *private; - - destroyed = 0; - for (node = xim_ic_list; node != NULL; node = node->next) - { - if (node->data) - { - private = (GdkICPrivate *) (node->data); - XDestroyIC (private->xic); - g_free (private); - destroyed++; - } - } -#ifdef G_ENABLE_DEBUG - if ((gdk_debug_flags & GDK_DEBUG_XIM) && destroyed > 0) - { - g_warning ("Cleaned up %i IC(s)\n", destroyed); - } -#endif /* G_ENABLE_DEBUG */ - g_list_free(xim_ic_list); - xim_ic_list = NULL; -} - -#else /* !USE_XIM */ - -void -gdk_im_begin (GdkIC ic, GdkWindow* window) -{ -} - -void -gdk_im_end (void) -{ -} - -GdkIMStyle -gdk_im_decide_style (GdkIMStyle supported_style) -{ - return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE; -} - -GdkIMStyle -gdk_im_set_best_style (GdkIMStyle style) -{ - return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE; -} - -gint -gdk_im_ready (void) -{ - return FALSE; -} - -GdkIC -gdk_ic_new (GdkWindow* client_window, - GdkWindow* focus_window, - GdkIMStyle style, ...) -{ - return NULL; -} - -void -gdk_ic_destroy (GdkIC ic) -{ -} - -GdkIMStyle -gdk_ic_get_style (GdkIC ic) -{ - return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE; -} - -void -gdk_ic_set_values (GdkIC ic, ...) -{ -} - -void -gdk_ic_get_values (GdkIC ic, ...) -{ -} - -void -gdk_ic_set_attr (GdkIC ic, const char *target, ...) -{ -} - -void -gdk_ic_get_attr (GdkIC ic, const char *target, ...) -{ -} - -GdkEventMask -gdk_ic_get_events (GdkIC ic) -{ - return 0; -} - -#endif /* USE_XIM */ - -#ifdef X_LOCALE - -gint -_g_mbtowc (wchar_t *wstr, const char *str, size_t len) -{ - static wchar_t wcs[MB_CUR_MAX + 1]; - static gchar mbs[MB_CUR_MAX + 1]; - - wcs[0] = (wchar_t) NULL; - mbs[0] = '\0'; - - /* The last argument isn't a mistake. The X locale code trims - * the input string to the length of the output string! - */ - len = _Xmbstowcs (wcs, str, (len<MB_CUR_MAX)? len:MB_CUR_MAX); - if (len < 1) - return len; - else if (wcs[0] == (wchar_t) NULL) - return -1; - - len = _Xwctomb (mbs, wcs[0]); - if (mbs[0] == '\0') - return -1; - if (wstr) - *wstr = wcs[0]; - - return len; -} - -#endif /* X_LOCALE */ - /* Sends a ClientMessage to all toplevel client windows */ gboolean gdk_event_send_client_message (GdkEvent *event, guint32 xid) @@ -22,7 +22,6 @@ #include <gdk/gdktypes.h> - #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -571,8 +570,13 @@ gint gdk_string_width (GdkFont *font, gint gdk_text_width (GdkFont *font, const gchar *text, gint text_length); +gint gdk_text_width_wc (GdkFont *font, + const GdkWChar *text, + gint text_length); gint gdk_char_width (GdkFont *font, gchar character); +gint gdk_char_width_wc (GdkFont *font, + GdkWChar character); gint gdk_string_measure (GdkFont *font, const gchar *string); gint gdk_text_measure (GdkFont *font, @@ -642,14 +646,21 @@ void gdk_draw_string (GdkDrawable *drawable, GdkGC *gc, gint x, gint y, - const gchar *string); + const gchar *string); void gdk_draw_text (GdkDrawable *drawable, GdkFont *font, GdkGC *gc, gint x, gint y, - const gchar *text, + const gchar *text, gint text_length); +void gdk_draw_text_wc (GdkDrawable *drawable, + GdkFont *font, + GdkGC *gc, + gint x, + gint y, + const GdkWChar *text, + gint text_length); void gdk_draw_pixmap (GdkDrawable *drawable, GdkGC *gc, GdkDrawable *src, @@ -798,25 +809,35 @@ GdkTimeCoord *gdk_input_motion_events (GdkWindow *window, gint gdk_im_ready (void); -void gdk_im_begin (GdkIC ic, - GdkWindow* window); +void gdk_im_begin (GdkIC *ic, + GdkWindow *window); void gdk_im_end (void); -GdkIMStyle gdk_im_decide_style (GdkIMStyle supported_style); -GdkIMStyle gdk_im_set_best_style (GdkIMStyle best_allowed_style); -GdkIC gdk_ic_new (GdkWindow* client_window, - GdkWindow* focus_window, - GdkIMStyle style, ...); -void gdk_ic_destroy (GdkIC ic); -GdkIMStyle gdk_ic_get_style (GdkIC ic); -void gdk_ic_set_values (GdkIC ic, - ...); -void gdk_ic_get_values (GdkIC ic, - ...); -void gdk_ic_set_attr (GdkIC ic, - const char *target, ...); -void gdk_ic_get_attr (GdkIC ic, - const char *target, ...); -GdkEventMask gdk_ic_get_events (GdkIC ic); +GdkIMStyle gdk_im_decide_style (GdkIMStyle supported_style); +GdkIMStyle gdk_im_set_best_style (GdkIMStyle best_allowed_style); + +GdkIC* gdk_ic_new (GdkICAttr *attr, + GdkICAttributesType mask); +void gdk_ic_destroy (GdkIC *ic); +GdkIMStyle gdk_ic_get_style (GdkIC *ic); +GdkEventMask gdk_ic_get_events (GdkIC *ic); + +GdkICAttr* gdk_ic_attr_new (void); +void gdk_ic_attr_destroy (GdkICAttr *attr); + +GdkICAttributesType gdk_ic_set_attr (GdkIC *ic, + GdkICAttr *attr, + GdkICAttributesType mask); +GdkICAttributesType gdk_ic_get_attr (GdkIC *ic, + GdkICAttr *attr, + GdkICAttributesType mask); + +/* Conversion functions between wide char and multibyte strings. + */ +gchar *gdk_wcstombs (const GdkWChar *src); +gint gdk_mbstowcs (GdkWChar *dest, + const gchar *src, + gint dest_max); + /* Color Context */ diff --git a/gdk/gdkdraw.c b/gdk/gdkdraw.c index 2725367c16..2d61d5dc4a 100644 --- a/gdk/gdkdraw.c +++ b/gdk/gdkdraw.c @@ -294,6 +294,66 @@ gdk_draw_text (GdkDrawable *drawable, } void +gdk_draw_text_wc (GdkDrawable *drawable, + GdkFont *font, + GdkGC *gc, + gint x, + gint y, + const GdkWChar *text, + gint text_length) +{ + GdkWindowPrivate *drawable_private; + GdkFontPrivate *font_private; + GdkGCPrivate *gc_private; + + g_return_if_fail (drawable != NULL); + g_return_if_fail (font != NULL); + g_return_if_fail (gc != NULL); + g_return_if_fail (text != NULL); + + drawable_private = (GdkWindowPrivate*) drawable; + if (drawable_private->destroyed) + return; + gc_private = (GdkGCPrivate*) gc; + font_private = (GdkFontPrivate*) font; + + if (font->type == GDK_FONT_FONT) + { + XFontStruct *xfont = (XFontStruct *) font_private->xfont; + gchar *text_8bit; + gint i; + XSetFont(drawable_private->xdisplay, gc_private->xgc, xfont->fid); + text_8bit = g_new (gchar, text_length); + for (i=0; i<text_length; i++) text_8bit[i] = text[i]; + XDrawString (drawable_private->xdisplay, drawable_private->xwindow, + gc_private->xgc, x, y, text_8bit, text_length); + g_free (text_8bit); + } + else if (font->type == GDK_FONT_FONTSET) + { + if (sizeof(GdkWChar) == sizeof(wchar_t)) + { + XwcDrawString (drawable_private->xdisplay, drawable_private->xwindow, + (XFontSet) font_private->xfont, + gc_private->xgc, x, y, (wchar_t *)text, text_length); + } + else + { + wchar_t *text_wchar; + gint i; + text_wchar = g_new (wchar_t, text_length); + for (i=0; i<text_length; i++) text_wchar[i] = text[i]; + XwcDrawString (drawable_private->xdisplay, drawable_private->xwindow, + (XFontSet) font_private->xfont, + gc_private->xgc, x, y, text_wchar, text_length); + g_free (text_wchar); + } + } + else + g_error("undefined font type\n"); +} + +void gdk_draw_pixmap (GdkDrawable *drawable, GdkGC *gc, GdkPixmap *src, diff --git a/gdk/gdkfont.c b/gdk/gdkfont.c index cc1274a0d6..0308fa8e0d 100644 --- a/gdk/gdkfont.c +++ b/gdk/gdkfont.c @@ -271,6 +271,62 @@ gdk_text_width (GdkFont *font, return width; } +gint +gdk_text_width_wc (GdkFont *font, + const GdkWChar *text, + gint text_length) +{ + GdkFontPrivate *private; + gint width; + XFontStruct *xfont; + XFontSet fontset; + + g_return_val_if_fail (font != NULL, -1); + g_return_val_if_fail (text != NULL, -1); + + private = (GdkFontPrivate*) font; + + switch (font->type) + { + case GDK_FONT_FONT: + xfont = (XFontStruct *) private->xfont; + if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0)) + { + gchar *text_8bit; + gint i; + text_8bit = g_new (gchar, text_length); + for (i=0; i<text_length; i++) text_8bit[i] = text[i]; + width = XTextWidth (xfont, text_8bit, text_length); + g_free (text_8bit); + } + else + { + width = 0; + } + break; + case GDK_FONT_FONTSET: + if (sizeof(GdkWChar) == sizeof(wchar_t)) + { + fontset = (XFontSet) private->xfont; + width = XwcTextEscapement (fontset, (wchar_t *)text, text_length); + } + else + { + wchar_t *text_wchar; + gint i; + fontset = (XFontSet) private->xfont; + text_wchar = g_new(wchar_t, text_length); + for (i=0; i<text_length; i++) text_wchar[i] = text[i]; + width = XwcTextEscapement (fontset, text_wchar, text_length); + g_free (text_wchar); + } + break; + default: + width = 0; + } + return width; +} + /* Problem: What if a character is a 16 bits character ?? */ gint gdk_char_width (GdkFont *font, @@ -319,6 +375,56 @@ gdk_char_width (GdkFont *font, } gint +gdk_char_width_wc (GdkFont *font, + GdkWChar character) +{ + GdkFontPrivate *private; + XCharStruct *chars; + gint width; + guint ch = character & 0xff; /* get rid of sign-extension */ + XFontStruct *xfont; + XFontSet fontset; + + g_return_val_if_fail (font != NULL, -1); + + private = (GdkFontPrivate*) font; + + switch (font->type) + { + case GDK_FONT_FONT: + /* only 8 bits characters are considered here */ + xfont = (XFontStruct *) private->xfont; + if ((xfont->min_byte1 == 0) && + (xfont->max_byte1 == 0) && + (ch >= xfont->min_char_or_byte2) && + (ch <= xfont->max_char_or_byte2)) + { + chars = xfont->per_char; + if (chars) + width = chars[ch - xfont->min_char_or_byte2].width; + else + width = xfont->min_bounds.width; + } + else + { + char ch2 = character; + width = XTextWidth (xfont, &ch2, 1); + } + break; + case GDK_FONT_FONTSET: + fontset = (XFontSet) private->xfont; + { + wchar_t char_wc = character; + width = XwcTextEscapement (fontset, &char_wc, 1) ; + } + break; + default: + width = 0; + } + return width; +} + +gint gdk_string_measure (GdkFont *font, const gchar *string) { diff --git a/gdk/gdkglobals.c b/gdk/gdkglobals.c index 5736a1a80d..eeebb51491 100644 --- a/gdk/gdkglobals.c +++ b/gdk/gdkglobals.c @@ -62,4 +62,8 @@ gint gdk_threads_pipe[2]; gboolean gdk_select_waiting = FALSE; #endif +#ifdef USE_XIM +GdkICPrivate *gdk_xim_ic; /* currently using IC */ +GdkWindow *gdk_xim_window; /* currently using Window */ +#endif diff --git a/gdk/gdki18n.h b/gdk/gdki18n.h index f2bf8553df..c7dba9e702 100644 --- a/gdk/gdki18n.h +++ b/gdk/gdki18n.h @@ -28,124 +28,6 @@ #include <stdlib.h> -#ifdef X_LOCALE - -#include <X11/Xfuncproto.h> -#include <X11/Xosdefs.h> - -#ifdef __cplusplus -extern "C" { -#endif - -_XFUNCPROTOBEGIN -extern int _Xmblen ( -#if NeedFunctionPrototypes - const char *s, size_t n -#endif - -); -_XFUNCPROTOEND - -_XFUNCPROTOBEGIN -extern int _Xmbtowc ( -#if NeedFunctionPrototypes - wchar_t *wstr, const char *str, size_t len -#endif -); -_XFUNCPROTOEND - -_XFUNCPROTOBEGIN -extern int _Xwctomb ( -#if NeedFunctionPrototypes - char *str, wchar_t wc -#endif -); -_XFUNCPROTOEND - -_XFUNCPROTOBEGIN -extern size_t _Xmbstowcs ( -#if NeedFunctionPrototypes - wchar_t *wstr, const char *str, size_t len -#endif -); -_XFUNCPROTOEND - -_XFUNCPROTOBEGIN -extern size_t _Xwcstombs ( -#if NeedFunctionPrototypes - char *str, const wchar_t *wstr, size_t len -#endif -); -_XFUNCPROTOEND - -_XFUNCPROTOBEGIN -extern size_t _Xwcslen ( -#if NeedFunctionPrototypes - const wchar_t *wstr -#endif -); -_XFUNCPROTOEND - -_XFUNCPROTOBEGIN -extern wchar_t* _Xwcscpy ( -#if NeedFunctionPrototypes - wchar_t *wstr1, const wchar_t *wstr2 -#endif -); -_XFUNCPROTOEND - -_XFUNCPROTOBEGIN -extern wchar_t* _Xwcsncpy ( -#if NeedFunctionPrototypes - wchar_t *wstr1, const wchar_t *wstr2, size_t len -#endif -); -_XFUNCPROTOEND - -_XFUNCPROTOBEGIN -extern int _Xwcscmp ( -#if NeedFunctionPrototypes - const wchar_t *wstr1, const wchar_t *wstr2 -#endif -); -_XFUNCPROTOEND - -_XFUNCPROTOBEGIN -extern int _Xwcsncmp ( -#if NeedFunctionPrototypes - const wchar_t *wstr1, const wchar_t *wstr2, size_t len -#endif -); -_XFUNCPROTOEND - -/* - * mblen, mbtowc, and mbstowcs of the locale "ja_JP.eucJP" are buggy. - */ - -#ifdef MB_CUR_MAX -# undef MB_CUR_MAX -#endif -#define MB_CUR_MAX 4 -extern int _g_mbtowc (wchar_t *wstr, const char *str, size_t len); - -/* #define mblen _Xmblen */ -/* #define mbtowc _Xmbtowc */ -#define mblen(a,b) _g_mbtowc ((wchar_t *)(NULL), (a), (b)) -#define mbtowc(a,b,c) _g_mbtowc ((a),(b),(c)) - -#define wctomb(a,b) _Xwctomb ((a),(b)) -#define mbstowcs(a,b,c) _Xmbstowcs ((a),(b),(c)) -#define wcstombs(a,b,c) _Xwcstombs ((a),(b),(c)) -#define wcslen(a) _Xwcslen ((a)) -#define wcscpy(a,b) _Xwcscpy ((a),(b)) -#define wcsncpy(a,b,c) _Xwcsncpy ((a),(b),(c)) - -#ifdef __cplusplus -} -#endif - -#endif /* X_LOCALE */ - #if !defined(G_HAVE_BROKEN_WCTYPE) && (defined(G_HAVE_WCTYPE_H) || defined(G_HAVE_WCHAR_H)) && !defined(X_LOCALE) # ifdef G_HAVE_WCTYPE_H # include <wctype.h> @@ -154,8 +36,11 @@ extern int _g_mbtowc (wchar_t *wstr, const char *str, size_t len); # include <wchar.h> # endif # endif +# define gdk_iswalnum(c) iswalnum(c) +# define gdk_iswspace(c) iswspace(c) #else -# define iswalnum(c) ((wchar_t)(c) <= 0xFF && isalnum(c)) +# define gdk_iswalnum(c) ((wchar_t)(c) <= 0xFF && isalnum(c)) +# define gdk_iswspace(c) ((wchar_t)(c) <= 0xFF && isspace(c)) #endif #endif /* __GDK_I18N_H__ */ diff --git a/gdk/gdkprivate.h b/gdk/gdkprivate.h index d7f71cd224..e095853d3f 100644 --- a/gdk/gdkprivate.h +++ b/gdk/gdkprivate.h @@ -186,14 +186,15 @@ struct _GdkClientFilter { #ifdef USE_XIM +typedef struct _GdkICPrivate GdkICPrivate; + struct _GdkICPrivate { XIC xic; - GdkIMStyle style; + GdkICAttr *attr; + GdkICAttributesType mask; }; -typedef struct _GdkICPrivate GdkICPrivate; - #endif /* USE_XIM */ struct _GdkColorContextPrivate @@ -282,6 +283,16 @@ extern gint gdk_threads_pipe[2]; extern gboolean gdk_select_waiting; #endif +#ifdef USE_XIM +/* XIM support */ +gint gdk_im_open (void); +void gdk_im_close (void); +void gdk_ic_cleanup (void); + +extern GdkICPrivate *gdk_xim_ic; /* currently using IC */ +extern GdkWindow *gdk_xim_window; /* currently using Window */ +#endif USE_XIM + /* Debugging support */ #ifdef G_ENABLE_DEBUG diff --git a/gdk/gdktypes.h b/gdk/gdktypes.h index bb38385b84..99befe3cb9 100644 --- a/gdk/gdktypes.h +++ b/gdk/gdktypes.h @@ -89,9 +89,11 @@ typedef struct _GdkRegion GdkRegion; typedef gint (*GdkEventFunc) (GdkEvent *event, gpointer data); -typedef void* GdkIC; -typedef void* GdkIM; +typedef struct _GdkIC GdkIC; +typedef struct _GdkICAttr GdkICAttr; +typedef guint32 GdkWChar; + /* Types of windows. * Root: There is only 1 root window and it is initialized @@ -617,6 +619,45 @@ typedef enum /*< flags >*/ GDK_IM_STATUS_MASK = 0x0f00 } GdkIMStyle; +typedef enum +{ + GDK_IC_STYLE = 1 << 0, + GDK_IC_CLIENT_WINDOW = 1 << 1, + GDK_IC_FOCUS_WINDOW = 1 << 2, + GDK_IC_FILTER_EVENTS = 1 << 3, + GDK_IC_SPOT_LOCATION = 1 << 4, + GDK_IC_LINE_SPACING = 1 << 5, + GDK_IC_CURSOR = 1 << 6, + + GDK_IC_PREEDIT_FONTSET = 1 << 10, + GDK_IC_PREEDIT_AREA = 1 << 11, + GDK_IC_PREEDIT_AREA_NEEDED = 1 << 12, + GDK_IC_PREEDIT_FOREGROUND = 1 << 13, + GDK_IC_PREEDIT_BACKGROUND = 1 << 14, + GDK_IC_PREEDIT_PIXMAP = 1 << 15, + GDK_IC_PREEDIT_COLORMAP = 1 << 16, + + GDK_IC_STATUS_FONTSET = 1 << 21, + GDK_IC_STATUS_AREA = 1 << 22, + GDK_IC_STATUS_AREA_NEEDED = 1 << 23, + GDK_IC_STATUS_FOREGROUND = 1 << 24, + GDK_IC_STATUS_BACKGROUND = 1 << 25, + GDK_IC_STATUS_PIXMAP = 1 << 26, + GDK_IC_STATUS_COLORMAP = 1 << 27, + + GDK_IC_ALL_REQ = GDK_IC_STYLE | + GDK_IC_CLIENT_WINDOW, + + GDK_IC_PREEDIT_AREA_REQ = GDK_IC_PREEDIT_AREA | + GDK_IC_PREEDIT_FONTSET, + GDK_IC_PREEDIT_POSITION_REQ = GDK_IC_PREEDIT_AREA | + GDK_IC_SPOT_LOCATION | + GDK_IC_PREEDIT_FONTSET, + + GDK_IC_STATUS_AREA_REQ = GDK_IC_STATUS_AREA | + GDK_IC_STATUS_FONTSET, +} GdkICAttributesType; + /* The next two enumeration values current match the * Motif constants. If this is changed, the implementation * of gdk_window_set_decorations/gdk_window_set_functions @@ -1182,7 +1223,32 @@ struct _GdkRegion gpointer user_data; }; +struct _GdkICAttr +{ + GdkIMStyle style; + GdkWindow *client_window; + GdkWindow *focus_window; + GdkEventMask filter_events; + GdkPoint spot_location; + gint line_spacing; + GdkCursor *cursor; + GdkFont *preedit_fontset; + GdkRectangle preedit_area; + GdkRectangle preedit_area_needed; + GdkColor preedit_foreground; + GdkColor preedit_background; + GdkPixmap *preedit_pixmap; + GdkColormap *preedit_colormap; + + GdkFont *status_fontset; + GdkRectangle status_area; + GdkRectangle status_area_needed; + GdkColor status_foreground; + GdkColor status_background; + GdkPixmap *status_pixmap; + GdkColormap *status_colormap; +}; #ifdef __cplusplus } diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index efbd713144..72a56d8584 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -323,7 +323,12 @@ gdk_window_new (GdkWindow *parent, if (attributes_mask & GDK_WA_COLORMAP) private->colormap = attributes->colormap; else - private->colormap = gdk_colormap_get_system (); + { + if ((((GdkVisualPrivate*)gdk_visual_get_system())->xvisual) == xvisual) + private->colormap = gdk_colormap_get_system (); + else + private->colormap = gdk_colormap_new (visual, False); + } xattributes.background_pixel = BlackPixel (gdk_display, gdk_screen); xattributes.border_pixel = BlackPixel (gdk_display, gdk_screen); diff --git a/gdk/x11/gdkfont-x11.c b/gdk/x11/gdkfont-x11.c index cc1274a0d6..0308fa8e0d 100644 --- a/gdk/x11/gdkfont-x11.c +++ b/gdk/x11/gdkfont-x11.c @@ -271,6 +271,62 @@ gdk_text_width (GdkFont *font, return width; } +gint +gdk_text_width_wc (GdkFont *font, + const GdkWChar *text, + gint text_length) +{ + GdkFontPrivate *private; + gint width; + XFontStruct *xfont; + XFontSet fontset; + + g_return_val_if_fail (font != NULL, -1); + g_return_val_if_fail (text != NULL, -1); + + private = (GdkFontPrivate*) font; + + switch (font->type) + { + case GDK_FONT_FONT: + xfont = (XFontStruct *) private->xfont; + if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0)) + { + gchar *text_8bit; + gint i; + text_8bit = g_new (gchar, text_length); + for (i=0; i<text_length; i++) text_8bit[i] = text[i]; + width = XTextWidth (xfont, text_8bit, text_length); + g_free (text_8bit); + } + else + { + width = 0; + } + break; + case GDK_FONT_FONTSET: + if (sizeof(GdkWChar) == sizeof(wchar_t)) + { + fontset = (XFontSet) private->xfont; + width = XwcTextEscapement (fontset, (wchar_t *)text, text_length); + } + else + { + wchar_t *text_wchar; + gint i; + fontset = (XFontSet) private->xfont; + text_wchar = g_new(wchar_t, text_length); + for (i=0; i<text_length; i++) text_wchar[i] = text[i]; + width = XwcTextEscapement (fontset, text_wchar, text_length); + g_free (text_wchar); + } + break; + default: + width = 0; + } + return width; +} + /* Problem: What if a character is a 16 bits character ?? */ gint gdk_char_width (GdkFont *font, @@ -319,6 +375,56 @@ gdk_char_width (GdkFont *font, } gint +gdk_char_width_wc (GdkFont *font, + GdkWChar character) +{ + GdkFontPrivate *private; + XCharStruct *chars; + gint width; + guint ch = character & 0xff; /* get rid of sign-extension */ + XFontStruct *xfont; + XFontSet fontset; + + g_return_val_if_fail (font != NULL, -1); + + private = (GdkFontPrivate*) font; + + switch (font->type) + { + case GDK_FONT_FONT: + /* only 8 bits characters are considered here */ + xfont = (XFontStruct *) private->xfont; + if ((xfont->min_byte1 == 0) && + (xfont->max_byte1 == 0) && + (ch >= xfont->min_char_or_byte2) && + (ch <= xfont->max_char_or_byte2)) + { + chars = xfont->per_char; + if (chars) + width = chars[ch - xfont->min_char_or_byte2].width; + else + width = xfont->min_bounds.width; + } + else + { + char ch2 = character; + width = XTextWidth (xfont, &ch2, 1); + } + break; + case GDK_FONT_FONTSET: + fontset = (XFontSet) private->xfont; + { + wchar_t char_wc = character; + width = XwcTextEscapement (fontset, &char_wc, 1) ; + } + break; + default: + width = 0; + } + return width; +} + +gint gdk_string_measure (GdkFont *font, const gchar *string) { diff --git a/gdk/x11/gdkglobals-x11.c b/gdk/x11/gdkglobals-x11.c index 5736a1a80d..eeebb51491 100644 --- a/gdk/x11/gdkglobals-x11.c +++ b/gdk/x11/gdkglobals-x11.c @@ -62,4 +62,8 @@ gint gdk_threads_pipe[2]; gboolean gdk_select_waiting = FALSE; #endif +#ifdef USE_XIM +GdkICPrivate *gdk_xim_ic; /* currently using IC */ +GdkWindow *gdk_xim_window; /* currently using Window */ +#endif diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c index f504ea313a..15dcaa3035 100644 --- a/gdk/x11/gdkmain-x11.c +++ b/gdk/x11/gdkmain-x11.c @@ -28,9 +28,6 @@ #include <stdlib.h> #include <string.h> #include <limits.h> -#ifdef USE_XIM -#include <stdarg.h> -#endif #ifdef HAVE_SYS_SELECT_H #include <sys/select.h> @@ -42,16 +39,13 @@ #include <X11/Xos.h> #include <X11/Xutil.h> #include <X11/Xmu/WinUtil.h> -#ifdef USE_XIM -#include <X11/Xresource.h> -#endif #include <X11/cursorfont.h> #include "gdk.h" #include "gdkprivate.h" #include "gdkinput.h" +#include "gdki18n.h" #include "gdkx.h" #include "gdkkeysyms.h" -#include "gdki18n.h" #ifndef X_GETTIMEOFDAY #define X_GETTIMEOFDAY(tv) gettimeofday (tv, NULL) @@ -139,21 +133,6 @@ static int gdk_x_error (Display *display, static int gdk_x_io_error (Display *display); static RETSIGTYPE gdk_signal (int signum); - -#ifdef USE_XIM -static guint gdk_im_va_count (va_list list); -static XVaNestedList gdk_im_va_to_nested (va_list list, - guint count); - -static GdkIM gdk_im_get (void); -static gint gdk_im_open (XrmDatabase db, - gchar* res_name, - gchar* rec_class); -static void gdk_im_close (void); -static void gdk_ic_cleanup (void); - -#endif /* USE_XIM */ - GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev, GdkEvent *event, gpointer data); @@ -212,17 +191,6 @@ static GdkWindowPrivate *xgrab_window = NULL; /* Window that currently holds static GList *client_filters; /* Filters for client messages */ -#ifdef USE_XIM -static gint xim_using; /* using XIM Protocol if TRUE */ -static GdkIM xim_im; /* global IM */ -static XIMStyles* xim_styles; /* im supports these styles */ -static XIMStyle xim_best_allowed_style; -static GdkICPrivate *xim_ic; /* currently using IC */ -static GdkWindow* xim_window; /* currently using Widow */ -static GList* xim_ic_list; - -#endif - static GList *putback_events = NULL; static gulong base_id; @@ -570,18 +538,7 @@ gdk_init (int *argc, gdk_wm_protocols_filter, NULL); #ifdef USE_XIM - /* initialize XIM Protocol variables */ - xim_using = FALSE; - xim_im = NULL; - xim_styles = NULL; - if (!(xim_best_allowed_style & GDK_IM_PREEDIT_MASK)) - gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS); - if (!(xim_best_allowed_style & GDK_IM_STATUS_MASK)) - gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS); - xim_ic = NULL; - xim_window = (GdkWindow*)NULL; - - gdk_im_open (NULL, NULL, NULL); + gdk_im_open (); #endif gdk_initialized = 1; @@ -1005,16 +962,22 @@ gdk_event_get (void) * has occurred. Read it. */ #ifdef USE_XIM - gint filter_status; - if (xim_using && xim_window) - do - { /* don't dispatch events used by IM */ - XNextEvent (gdk_display, &xevent); - filter_status = XFilterEvent (&xevent, - GDK_WINDOW_XWINDOW (xim_window)); - } while (filter_status == True); - else - XNextEvent (gdk_display, &xevent); + Window w = None; + + XNextEvent (gdk_display, &xevent); + if (gdk_xim_window) + switch (xevent.type) + { + case KeyPress: + case KeyRelease: + case ButtonPress: + case ButtonRelease: + w = GDK_WINDOW_XWINDOW (gdk_xim_window); + break; + } + + if (XFilterEvent (&xevent, w)) + return NULL; #else XNextEvent (gdk_display, &xevent); #endif @@ -2067,13 +2030,6 @@ gdk_event_translate (GdkEvent *event, if (window != NULL) gdk_window_ref (window); -#ifdef USE_XIM - else if (XFilterEvent(xevent, None)) /* for xlib XIM handling */ - return FALSE; -#endif - else - GDK_NOTE (EVENTS, - g_message ("Got event for unknown window: %#lx\n", xevent->xany.window)); event->any.window = window; event->any.send_event = xevent->xany.send_event; @@ -2088,17 +2044,46 @@ gdk_event_translate (GdkEvent *event, /* Check for filters for this window */ GdkFilterReturn result; + +#ifdef USE_XIM + if (window == NULL && + xevent->type == KeyPress && + gdk_xim_window && + !((GdkWindowPrivate *) gdk_xim_window)->destroyed) + { + /* + * If user presses a key in Preedit or Status window, keypress event + * is sometimes sent to these windows. These windows are not managed + * by GDK, so we redirect KeyPress event to gdk_xim_window. + * + * If someone want to use the window whitch is not managed by GDK + * and want to get KeyPress event, he/she must register the filter + * function to gdk_default_filters to intercept the event. + */ + + window = gdk_xim_window; + window_private = (GdkWindowPrivate *) window; + gdk_window_ref (window); + event->any.window = window; + + GDK_NOTE (XIM, + g_message ("KeyPress event is redirected to gdk_xim_window: %#lx", + xevent->xany.window)); + } +#endif /* USE_XIM */ + result = gdk_event_apply_filters (xevent, event, window_private ?window_private->filters :gdk_default_filters); if (result != GDK_FILTER_CONTINUE) - { - return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE; - } + return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE; } + if (window == NULL) + g_message ("Got event for unknown window: %#lx\n", xevent->xany.window); + /* We do a "manual" conversion of the XEvent to a * GdkEvent. The structures are mostly the same so * the conversion is fairly straightforward. We also @@ -2121,12 +2106,12 @@ gdk_event_translate (GdkEvent *event, } keysym = GDK_VoidSymbol; - if (xim_using == TRUE && xim_ic) + if (gdk_xim_ic && gdk_xim_ic->xic) { Status status; /* Clear keyval. Depending on status, may not be set */ - charcount = XmbLookupString(xim_ic->xic, + charcount = XmbLookupString(gdk_xim_ic->xic, &xevent->xkey, buf, buf_len-1, &keysym, &status); if (status == XBufferOverflow) @@ -2139,7 +2124,7 @@ gdk_event_translate (GdkEvent *event, buf_len *= 2; buf = (gchar *) g_realloc (buf, buf_len); - charcount = XmbLookupString (xim_ic->xic, + charcount = XmbLookupString (gdk_xim_ic->xic, &xevent->xkey, buf, buf_len-1, &keysym, &status); } @@ -2520,6 +2505,13 @@ gdk_event_translate (GdkEvent *event, (xevent->xany.type == FocusIn) ? "in" : "out", xevent->xfocus.window - base_id)); + /* gdk_keyboard_grab() causes following events. These events confuse + * the XIM focus, so ignore them. + */ + if (xevent->xfocus.mode == NotifyGrab || + xevent->xfocus.mode == NotifyUngrab) + break; + event->focus_change.type = GDK_FOCUS_CHANGE; event->focus_change.window = window; event->focus_change.in = (xevent->xany.type == FocusIn); @@ -3186,652 +3178,6 @@ gdk_signal (int sig_num) #endif /* !G_ENABLE_DEBUG */ } -#ifdef USE_XIM - -/* The following routines duplicate functionality in Xlib to - * translate from varargs to X's internal opaque XVaNestedList. - * - * If all vendors have stuck close to the reference implementation, - * then we should hopefully be OK. - */ - -/* This needs to match XIMArg as defined in Xlcint.h exactly */ - -typedef struct { - gchar *name; - gpointer value; -} GdkImArg; - -/************************************************************* - * gdk_im_va_count: - * Counts the number of name/value pairs in the vararg list - * - * arguments: - * - * results: - *************************************************************/ - -static guint -gdk_im_va_count (va_list list) -{ - gint count = 0; - gchar *name; - - name = va_arg (list, gchar *); - while (name) - { - count++; - (void)va_arg (list, gpointer); - name = va_arg (list, gchar *); - } - - return count; -} - -/************************************************************* - * gdk_im_va_to_nested: - * Given a varargs list and the result of gdk_im_va_count, - * create a XVaNestedList. - * - * arguments: - * - * results: - *************************************************************/ - -static XVaNestedList -gdk_im_va_to_nested (va_list list, guint count) -{ - GdkImArg *result; - GdkImArg *arg; - - gchar *name; - - if (count == 0) - return NULL; - - result = g_new (GdkImArg, count+1); - arg = result; - - name = va_arg (list, gchar *); - while (name) - { - arg->name = name; - arg->value = va_arg (list, gpointer); - arg++; - name = va_arg (list, gchar *); - } - - arg->name = NULL; - - return (XVaNestedList)result; -} - -/* - *-------------------------------------------------------------- - * gdk_im_begin - * - * Begin using input method with XIM Protocol(X11R6 standard) - * - * Arguments: - * "ic" is the "Input Context" which is created by gtk_ic_new. - * The input area is specified with "window". - * - * Results: - * The gdk's event handling routine is switched to XIM based routine. - * XIM based routine uses XFilterEvent to get rid of events used by IM, - * and uses XmbLookupString instead of XLookupString. - * - * Side effects: - * - *-------------------------------------------------------------- - */ - -void -gdk_im_begin (GdkIC ic, GdkWindow* window) -{ - GdkICPrivate *private; - Window xwin; - - g_return_if_fail (ic != NULL); - g_return_if_fail (window); - - private = (GdkICPrivate *) ic; - - xim_using = TRUE; - xim_ic = private; - xim_window = window; - if (gdk_im_ready()) - { - XGetICValues (private->xic, XNFocusWindow, &xwin, NULL); - if (xwin != GDK_WINDOW_XWINDOW(window)) - XSetICValues (private->xic, XNFocusWindow, - GDK_WINDOW_XWINDOW(window), NULL); - if (private != xim_ic) - XSetICFocus (private->xic); - } -} - -/* - *-------------------------------------------------------------- - * gdk_im_end - * - * End using input method with XIM Protocol(X11R6 standard) - * - * Arguments: - * - * Results: - * The gdk's event handling routine is switched to normal routine. - * User should call this function before ic and window will be destroyed. - * - * Side effects: - * - *-------------------------------------------------------------- - */ - -void -gdk_im_end (void) -{ - xim_using = FALSE; - xim_ic = NULL; - xim_window = NULL; -} - -static GdkIM -gdk_im_get (void) -{ - return xim_im; -} - -static GdkIMStyle -gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2) -{ - GdkIMStyle s1, s2, u; - - if (style1 == 0) return style2; - if (style2 == 0) return style1; - if ((style1 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK)) - == (style2 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK))) - return style1; - - s1 = style1 & GDK_IM_PREEDIT_MASK; - s2 = style2 & GDK_IM_PREEDIT_MASK; - u = s1 | s2; - if (s1 != s2) { - if (u & GDK_IM_PREEDIT_CALLBACKS) - return (s1 == GDK_IM_PREEDIT_CALLBACKS)? style1:style2; - else if (u & GDK_IM_PREEDIT_POSITION) - return (s1 == GDK_IM_PREEDIT_POSITION)? style1:style2; - else if (u & GDK_IM_PREEDIT_AREA) - return (s1 == GDK_IM_PREEDIT_AREA)? style1:style2; - else if (u & GDK_IM_PREEDIT_NOTHING) - return (s1 == GDK_IM_PREEDIT_NOTHING)? style1:style2; - } else { - s1 = style1 & GDK_IM_STATUS_MASK; - s2 = style2 & GDK_IM_STATUS_MASK; - u = s1 | s2; - if ( u & GDK_IM_STATUS_CALLBACKS) - return (s1 == GDK_IM_STATUS_CALLBACKS)? style1:style2; - else if ( u & GDK_IM_STATUS_AREA) - return (s1 == GDK_IM_STATUS_AREA)? style1:style2; - else if ( u & GDK_IM_STATUS_NOTHING) - return (s1 == GDK_IM_STATUS_NOTHING)? style1:style2; - else if ( u & GDK_IM_STATUS_NONE) - return (s1 == GDK_IM_STATUS_NONE)? style1:style2; - } - return 0; /* Get rid of stupid warning */ -} - -GdkIMStyle -gdk_im_decide_style (GdkIMStyle supported_style) -{ - gint i; - GdkIMStyle style, tmp; - - g_return_val_if_fail (xim_styles != NULL, 0); - - style = 0; - for (i=0; i<xim_styles->count_styles; i++) - { - tmp = xim_styles->supported_styles[i]; - if (tmp == (tmp & supported_style & xim_best_allowed_style)) - style = gdk_im_choose_better_style (style, tmp); - } - return style; -} - -GdkIMStyle -gdk_im_set_best_style (GdkIMStyle style) -{ - if (style & GDK_IM_PREEDIT_MASK) - { - xim_best_allowed_style &= ~GDK_IM_PREEDIT_MASK; - - xim_best_allowed_style |= GDK_IM_PREEDIT_NONE; - if (!(style & GDK_IM_PREEDIT_NONE)) - { - xim_best_allowed_style |= GDK_IM_PREEDIT_NOTHING; - if (!(style & GDK_IM_PREEDIT_NOTHING)) - { - xim_best_allowed_style |= GDK_IM_PREEDIT_AREA; - if (!(style & GDK_IM_PREEDIT_AREA)) - { - xim_best_allowed_style |= GDK_IM_PREEDIT_POSITION; - if (!(style & GDK_IM_PREEDIT_POSITION)) - xim_best_allowed_style |= GDK_IM_PREEDIT_CALLBACKS; - } - } - } - } - if (style & GDK_IM_STATUS_MASK) - { - xim_best_allowed_style &= ~GDK_IM_STATUS_MASK; - - xim_best_allowed_style |= GDK_IM_STATUS_NONE; - if (!(style & GDK_IM_STATUS_NONE)) - { - xim_best_allowed_style |= GDK_IM_STATUS_NOTHING; - if (!(style & GDK_IM_STATUS_NOTHING)) - { - xim_best_allowed_style |= GDK_IM_STATUS_AREA; - if (!(style & GDK_IM_STATUS_AREA)) - xim_best_allowed_style |= GDK_IM_STATUS_CALLBACKS; - } - } - } - - return xim_best_allowed_style; -} - -static gint -gdk_im_open (XrmDatabase db, gchar* res_name, gchar* res_class) -{ - xim_im = XOpenIM (GDK_DISPLAY(), db, res_name, res_class); - if (xim_im == NULL) - { - GDK_NOTE (XIM, g_warning ("Unable to open open IM.")); - return FALSE; - } - XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL); - - return TRUE; -} - -static void -gdk_im_close (void) -{ - if (xim_im) - { - XCloseIM (xim_im); - xim_im = NULL; - } - if (xim_styles) - { - XFree (xim_styles); - xim_styles = NULL; - } -} - -gint -gdk_im_ready (void) -{ - return (xim_im != NULL); -} - -GdkIC -gdk_ic_new (GdkWindow* client_window, - GdkWindow* focus_window, - GdkIMStyle style, ...) -{ - va_list list; - GdkICPrivate *private; - XVaNestedList preedit_attr = NULL; - guint count; - - g_return_val_if_fail (client_window != NULL, NULL); - g_return_val_if_fail (focus_window != NULL, NULL); - g_return_val_if_fail (gdk_im_ready(), NULL); - - private = g_new (GdkICPrivate, 1); - - va_start (list, style); - count = gdk_im_va_count (list); - va_end (list); - - va_start (list, style); - preedit_attr = gdk_im_va_to_nested (list, count); - va_end (list); - - private->style = gdk_im_decide_style (style); - if (private->style != style) - { - g_warning ("can not create input context with specified input style."); - g_free (private); - return NULL; - } - - private->xic = XCreateIC(gdk_im_get (), - XNInputStyle, style, - XNClientWindow, GDK_WINDOW_XWINDOW (client_window), - XNFocusWindow, GDK_WINDOW_XWINDOW (focus_window), - preedit_attr? XNPreeditAttributes : NULL, preedit_attr, - NULL); - - g_free (preedit_attr); - - if (!private->xic) - { - g_free (private); - return NULL; - } - - xim_ic_list = g_list_append (xim_ic_list, private); - return private; -} - -void -gdk_ic_destroy (GdkIC ic) -{ - GdkICPrivate *private; - - g_return_if_fail (ic != NULL); - - private = (GdkICPrivate *) ic; - - if (xim_ic == private) - gdk_im_end (); - - XDestroyIC (private->xic); - xim_ic_list = g_list_remove (xim_ic_list, private); - g_free (private); -} - -GdkIMStyle -gdk_ic_get_style (GdkIC ic) -{ - GdkICPrivate *private; - - g_return_val_if_fail (ic != NULL, 0); - - private = (GdkICPrivate *) ic; - - return private->style; -} - -void -gdk_ic_set_values (GdkIC ic, ...) -{ - va_list list; - XVaNestedList args; - GdkICPrivate *private; - guint count; - - g_return_if_fail (ic != NULL); - - private = (GdkICPrivate *) ic; - - va_start (list, ic); - count = gdk_im_va_count (list); - va_end (list); - - va_start (list, ic); - args = gdk_im_va_to_nested (list, count); - va_end (list); - - XSetICValues (private->xic, XNVaNestedList, args, NULL); - - g_free (args); -} - -void -gdk_ic_get_values (GdkIC ic, ...) -{ - va_list list; - XVaNestedList args; - GdkICPrivate *private; - guint count; - - g_return_if_fail (ic != NULL); - - private = (GdkICPrivate *) ic; - - va_start (list, ic); - count = gdk_im_va_count (list); - va_end (list); - - va_start (list, ic); - args = gdk_im_va_to_nested (list, count); - va_end (list); - - XGetICValues (private->xic, XNVaNestedList, args, NULL); - - g_free (args); -} - -void -gdk_ic_set_attr (GdkIC ic, const char *target, ...) -{ - va_list list; - XVaNestedList attr; - GdkICPrivate *private; - guint count; - - g_return_if_fail (ic != NULL); - g_return_if_fail (target != NULL); - - private = (GdkICPrivate *) ic; - - va_start (list, target); - count = gdk_im_va_count (list); - va_end (list); - - va_start (list, target); - attr = gdk_im_va_to_nested (list, count); - va_end (list); - - XSetICValues (private->xic, target, attr, NULL); - - g_free (attr); -} - -void -gdk_ic_get_attr (GdkIC ic, const char *target, ...) -{ - va_list list; - XVaNestedList attr; - GdkICPrivate *private; - guint count; - - g_return_if_fail (ic != NULL); - g_return_if_fail (target != NULL); - - private = (GdkICPrivate *) ic; - - va_start (list, target); - count = gdk_im_va_count (list); - va_end (list); - - va_start (list, target); - attr = gdk_im_va_to_nested (list, count); - va_end (list); - - XGetICValues (private->xic, target, attr, NULL); - - g_free (attr); -} - -GdkEventMask -gdk_ic_get_events (GdkIC ic) -{ - GdkEventMask mask; - glong xmask; - glong bit; - GdkICPrivate *private; - gint i; - - /* From gdkwindow.c */ - extern int nevent_masks; - extern int event_mask_table[]; - - g_return_val_if_fail (ic != NULL, 0); - - private = (GdkICPrivate *) ic; - - if (XGetICValues (private->xic, XNFilterEvents, &xmask, NULL) != NULL) - { - GDK_NOTE (XIM, g_warning ("Call to XGetICValues: %s failed", XNFilterEvents)); - return 0; - } - - mask = 0; - for (i=0, bit=2; i < nevent_masks; i++, bit <<= 1) - if (xmask & event_mask_table [i]) - { - mask |= bit; - xmask &= ~ event_mask_table [i]; - } - - if (xmask) - g_warning ("ic requires events not supported by the application (%#04lx)", xmask); - - return mask; -} - -static void -gdk_ic_cleanup (void) -{ - GList* node; - gint destroyed; - GdkICPrivate *private; - - destroyed = 0; - for (node = xim_ic_list; node != NULL; node = node->next) - { - if (node->data) - { - private = (GdkICPrivate *) (node->data); - XDestroyIC (private->xic); - g_free (private); - destroyed++; - } - } -#ifdef G_ENABLE_DEBUG - if ((gdk_debug_flags & GDK_DEBUG_XIM) && destroyed > 0) - { - g_warning ("Cleaned up %i IC(s)\n", destroyed); - } -#endif /* G_ENABLE_DEBUG */ - g_list_free(xim_ic_list); - xim_ic_list = NULL; -} - -#else /* !USE_XIM */ - -void -gdk_im_begin (GdkIC ic, GdkWindow* window) -{ -} - -void -gdk_im_end (void) -{ -} - -GdkIMStyle -gdk_im_decide_style (GdkIMStyle supported_style) -{ - return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE; -} - -GdkIMStyle -gdk_im_set_best_style (GdkIMStyle style) -{ - return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE; -} - -gint -gdk_im_ready (void) -{ - return FALSE; -} - -GdkIC -gdk_ic_new (GdkWindow* client_window, - GdkWindow* focus_window, - GdkIMStyle style, ...) -{ - return NULL; -} - -void -gdk_ic_destroy (GdkIC ic) -{ -} - -GdkIMStyle -gdk_ic_get_style (GdkIC ic) -{ - return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE; -} - -void -gdk_ic_set_values (GdkIC ic, ...) -{ -} - -void -gdk_ic_get_values (GdkIC ic, ...) -{ -} - -void -gdk_ic_set_attr (GdkIC ic, const char *target, ...) -{ -} - -void -gdk_ic_get_attr (GdkIC ic, const char *target, ...) -{ -} - -GdkEventMask -gdk_ic_get_events (GdkIC ic) -{ - return 0; -} - -#endif /* USE_XIM */ - -#ifdef X_LOCALE - -gint -_g_mbtowc (wchar_t *wstr, const char *str, size_t len) -{ - static wchar_t wcs[MB_CUR_MAX + 1]; - static gchar mbs[MB_CUR_MAX + 1]; - - wcs[0] = (wchar_t) NULL; - mbs[0] = '\0'; - - /* The last argument isn't a mistake. The X locale code trims - * the input string to the length of the output string! - */ - len = _Xmbstowcs (wcs, str, (len<MB_CUR_MAX)? len:MB_CUR_MAX); - if (len < 1) - return len; - else if (wcs[0] == (wchar_t) NULL) - return -1; - - len = _Xwctomb (mbs, wcs[0]); - if (mbs[0] == '\0') - return -1; - if (wstr) - *wstr = wcs[0]; - - return len; -} - -#endif /* X_LOCALE */ - /* Sends a ClientMessage to all toplevel client windows */ gboolean gdk_event_send_client_message (GdkEvent *event, guint32 xid) diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index efbd713144..72a56d8584 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -323,7 +323,12 @@ gdk_window_new (GdkWindow *parent, if (attributes_mask & GDK_WA_COLORMAP) private->colormap = attributes->colormap; else - private->colormap = gdk_colormap_get_system (); + { + if ((((GdkVisualPrivate*)gdk_visual_get_system())->xvisual) == xvisual) + private->colormap = gdk_colormap_get_system (); + else + private->colormap = gdk_colormap_new (visual, False); + } xattributes.background_pixel = BlackPixel (gdk_display, gdk_screen); xattributes.border_pixel = BlackPixel (gdk_display, gdk_screen); diff --git a/gtk/gtkeditable.c b/gtk/gtkeditable.c index 5335274876..5d8248471e 100644 --- a/gtk/gtkeditable.c +++ b/gtk/gtkeditable.c @@ -75,7 +75,6 @@ static void gtk_editable_set_arg (GtkObject *object, static void gtk_editable_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); -static void gtk_editable_finalize (GtkObject *object); static gint gtk_editable_selection_clear (GtkWidget *widget, GdkEventSelection *event); static void gtk_editable_selection_get (GtkWidget *widget, @@ -96,7 +95,7 @@ static void gtk_editable_real_copy_clipboard (GtkEditable *editable); static void gtk_editable_real_paste_clipboard (GtkEditable *editable); static void gtk_editable_real_set_editable (GtkEditable *editable, gboolean is_editable); - + static GtkWidgetClass *parent_class = NULL; static guint editable_signals[LAST_SIGNAL] = { 0 }; @@ -291,7 +290,6 @@ gtk_editable_class_init (GtkEditableClass *class) object_class->set_arg = gtk_editable_set_arg; object_class->get_arg = gtk_editable_get_arg; - object_class->finalize = gtk_editable_finalize; widget_class->selection_clear_event = gtk_editable_selection_clear; widget_class->selection_received = gtk_editable_selection_received; @@ -399,27 +397,6 @@ gtk_editable_init (GtkEditable *editable) targets, n_targets); } -static void -gtk_editable_finalize (GtkObject *object) -{ - GtkEditable *editable; - - g_return_if_fail (object != NULL); - g_return_if_fail (GTK_IS_EDITABLE (object)); - - editable = GTK_EDITABLE (object); - -#ifdef USE_XIM - if (editable->ic) - { - gdk_ic_destroy (editable->ic); - editable->ic = NULL; - } -#endif - - (* GTK_OBJECT_CLASS (parent_class)->finalize) (object); -} - void gtk_editable_insert_text (GtkEditable *editable, const gchar *new_text, @@ -594,7 +571,9 @@ gtk_editable_selection_get (GtkWidget *widget, str = gtk_editable_get_chars(editable, selection_start_pos, selection_end_pos); - length = selection_end_pos - selection_start_pos; + if (!str) + return; /* Refuse */ + length = strlen (str); } else /* CLIPBOARD */ { @@ -938,3 +917,32 @@ gtk_editable_changed (GtkEditable *editable) gtk_signal_emit (GTK_OBJECT (editable), editable_signals[CHANGED]); } + +#if 0 +static void +gtk_editable_parent_set (GtkWidget *widget, + GtkWidget *old_parent, + GtkWidget *editable) +{ + GtkWidget *parent; + + parent = old_parent; + while (parent) + { + gtk_signal_disconnect_by_func (GTK_OBJECT (parent), + GTK_SIGNAL_FUNC (gtk_editable_parent_set), + editable); + parent = parent->parent; + } + + parent = widget->parent; + while (parent) + { + gtk_signal_connect (GTK_OBJECT (parent), "parent_set", + GTK_SIGNAL_FUNC (gtk_editable_parent_set), + editable); + + parent = parent->parent; + } +} +#endif diff --git a/gtk/gtkeditable.h b/gtk/gtkeditable.h index be8c1ef9bd..672d7cb61b 100644 --- a/gtk/gtkeditable.h +++ b/gtk/gtkeditable.h @@ -45,13 +45,14 @@ struct _GtkEditable { GtkWidget widget; - guint current_pos; - - guint selection_start_pos; - guint selection_end_pos; - guint has_selection : 1; - guint editable : 1; - GdkIC ic; + guint current_pos; + + guint selection_start_pos; + guint selection_end_pos; + guint has_selection : 1; + guint editable : 1; + GdkIC *ic; + GdkICAttr *ic_attr; gchar *clipboard_text; }; diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c index 77079d2ae4..76e6d5b7b4 100644 --- a/gtk/gtkentry.c +++ b/gtk/gtkentry.c @@ -18,9 +18,6 @@ */ #include <ctype.h> #include <string.h> -#ifdef USE_XIM -#include "gdk/gdkx.h" -#endif #include "gdk/gdkkeysyms.h" #include "gdk/gdki18n.h" #include "gtkentry.h" @@ -28,7 +25,6 @@ #include "gtkselection.h" #include "gtksignal.h" #include "gtkstyle.h" -#include "gtkprivate.h" #define MIN_ENTRY_WIDTH 150 #define DRAW_TIMEOUT 20 @@ -84,6 +80,9 @@ static void gtk_entry_style_set (GtkWidget *widget, GtkStyle *previous_style); static void gtk_entry_state_changed (GtkWidget *widget, GtkStateType previous_state); +#ifdef USE_XIM +static void gtk_entry_update_ic_attr (GtkWidget *widget); +#endif static void gtk_entry_queue_draw (GtkEntry *entry); static gint gtk_entry_timer (gpointer data); static gint gtk_entry_position (GtkEntry *entry, @@ -143,8 +142,6 @@ static void gtk_entry_set_selection (GtkEditable *editable, gint end); static void gtk_entry_recompute_offsets (GtkEntry *entry); -static gint gtk_entry_find_char (GtkEntry *entry, - gint position); static gint gtk_entry_find_position (GtkEntry *entry, gint position); static void gtk_entry_set_position_from_editable (GtkEditable *editable, @@ -353,9 +350,10 @@ gtk_entry_init (GtkEntry *entry) entry->button = 0; entry->visible = 1; - entry->nchars = 0; - entry->char_pos = NULL; entry->char_offset = NULL; + entry->text_mb = NULL; + entry->text_mb_dirty = TRUE; + entry->use_wchar = FALSE; gtk_entry_grow_text (entry); } @@ -480,14 +478,27 @@ gtk_entry_set_editable(GtkEntry *entry, gchar* gtk_entry_get_text (GtkEntry *entry) { - static char empty_str[2] = ""; - g_return_val_if_fail (entry != NULL, NULL); g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL); + if (!entry->text_mb_dirty) + return entry->text_mb; + + if (entry->text_mb) + g_free(entry->text_mb); + if (!entry->text) - return empty_str; - return entry->text; + { + entry->text_mb = g_new(gchar, 1); + entry->text_mb[0] = 0; + } + else + { + entry->text_mb = gtk_entry_get_chars(GTK_EDITABLE(entry), 0, -1); + } + entry->text_mb_dirty = 0; + + return entry->text_mb; } static void @@ -500,26 +511,22 @@ gtk_entry_finalize (GtkObject *object) entry = GTK_ENTRY (object); -#ifdef USE_XIM - if (GTK_EDITABLE(entry)->ic) - { - gdk_ic_destroy (GTK_EDITABLE(entry)->ic); - GTK_EDITABLE(entry)->ic = NULL; - } -#endif - if (entry->timer) gtk_timeout_remove (entry->timer); entry->text_size = 0; + if (entry->text) g_free (entry->text); - if (entry->char_pos) - g_free (entry->char_pos); if (entry->char_offset) g_free (entry->char_offset); entry->text = NULL; + if (entry->text_mb) + g_free (entry->text_mb); + entry->text_mb = NULL; + + if (entry->backing_pixmap) if (entry->backing_pixmap) gdk_pixmap_unref (entry->backing_pixmap); @@ -581,21 +588,37 @@ gtk_entry_realize (GtkWidget *widget) gdk_window_set_background (entry->text_area, &widget->style->base[GTK_WIDGET_STATE (widget)]); #ifdef USE_XIM - if (gdk_im_ready ()) + if (gdk_im_ready () && (editable->ic_attr = gdk_ic_attr_new ()) != NULL) { - GdkPoint spot; - GdkRectangle rect; gint width, height; GdkEventMask mask; + GdkColormap *colormap; + GdkICAttr *attr = editable->ic_attr; + GdkICAttributesType attrmask = GDK_IC_ALL_REQ; GdkIMStyle style; - GdkIMStyle supported_style = GDK_IM_PREEDIT_NONE | GDK_IM_PREEDIT_NOTHING | - GDK_IM_PREEDIT_POSITION | - GDK_IM_STATUS_NONE | GDK_IM_STATUS_NOTHING; + GdkIMStyle supported_style = GDK_IM_PREEDIT_NONE | + GDK_IM_PREEDIT_NOTHING | + GDK_IM_PREEDIT_POSITION | + GDK_IM_STATUS_NONE | + GDK_IM_STATUS_NOTHING; if (widget->style && widget->style->font->type != GDK_FONT_FONTSET) supported_style &= ~GDK_IM_PREEDIT_POSITION; - style = gdk_im_decide_style (supported_style); + attr->style = style = gdk_im_decide_style (supported_style); + attr->client_window = entry->text_area; + + if ((colormap = gtk_widget_get_colormap (widget)) != + gtk_widget_get_default_colormap ()) + { + attrmask |= GDK_IC_PREEDIT_COLORMAP; + attr->preedit_colormap = colormap; + } + attrmask |= GDK_IC_PREEDIT_FOREGROUND; + attrmask |= GDK_IC_PREEDIT_BACKGROUND; + attr->preedit_foreground = widget->style->fg[GTK_STATE_NORMAL]; + attr->preedit_background = widget->style->base[GTK_STATE_NORMAL]; + switch (style & GDK_IM_PREEDIT_MASK) { case GDK_IM_PREEDIT_POSITION: @@ -604,46 +627,32 @@ gtk_entry_realize (GtkWidget *widget) g_warning ("over-the-spot style requires fontset"); break; } + gdk_window_get_size (entry->text_area, &width, &height); - rect.x = 0; - rect.y = 0; - rect.width = width; - rect.height = height; - spot.x = 0; - spot.y = height; - editable->ic = gdk_ic_new (entry->text_area, entry->text_area, - style, - "spotLocation", &spot, - "area", &rect, - "fontSet", GDK_FONT_XFONT (widget->style->font), - NULL); + + attrmask |= GDK_IC_PREEDIT_POSITION_REQ; + attr->spot_location.x = 0; + attr->spot_location.y = height; + attr->preedit_area.x = 0; + attr->preedit_area.y = 0; + attr->preedit_area.width = width; + attr->preedit_area.height = height; + attr->preedit_fontset = widget->style->font; + break; - default: - editable->ic = gdk_ic_new (entry->text_area, entry->text_area, - style, NULL); } + editable->ic = gdk_ic_new (attr, attrmask); if (editable->ic == NULL) g_warning ("Can't create input context."); else { - GdkColormap *colormap; - mask = gdk_window_get_events (entry->text_area); mask |= gdk_ic_get_events (editable->ic); gdk_window_set_events (entry->text_area, mask); - if ((colormap = gtk_widget_get_colormap (widget)) != - gtk_widget_get_default_colormap ()) - { - gdk_ic_set_attr (editable->ic, "preeditAttributes", - "colorMap", GDK_COLORMAP_XCOLORMAP (colormap), - NULL); - } - gdk_ic_set_attr (editable->ic,"preeditAttributes", - "foreground", widget->style->fg[GTK_STATE_NORMAL].pixel, - "background", widget->style->base[GTK_STATE_NORMAL].pixel, - NULL); + if (GTK_WIDGET_HAS_FOCUS(widget)) + gdk_im_begin (editable->ic, entry->text_area); } } #endif @@ -666,6 +675,19 @@ gtk_entry_unrealize (GtkWidget *widget) entry = GTK_ENTRY (widget); +#ifdef USE_XIM + if (GTK_EDITABLE (widget)->ic) + { + gdk_ic_destroy (GTK_EDITABLE (widget)->ic); + GTK_EDITABLE (widget)->ic = NULL; + } + if (GTK_EDITABLE (widget)->ic_attr) + { + gdk_ic_attr_destroy (GTK_EDITABLE (widget)->ic_attr); + GTK_EDITABLE (widget)->ic_attr = NULL; + } +#endif + if (entry->text_area) { gdk_window_set_user_data (entry->text_area, NULL); @@ -765,17 +787,16 @@ gtk_entry_size_allocate (GtkWidget *widget, entry_adjust_scroll (entry); #ifdef USE_XIM - if (editable->ic && (gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION)) + if (editable->ic && + (gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION)) { gint width, height; - GdkRectangle rect; gdk_window_get_size (entry->text_area, &width, &height); - rect.x = 0; - rect.y = 0; - rect.width = width; - rect.height = height; - gdk_ic_set_attr (editable->ic, "preeditAttributes", "area", &rect, NULL); + editable->ic_attr->preedit_area.width = width; + editable->ic_attr->preedit_area.height = height; + gdk_ic_set_attr (editable->ic, editable->ic_attr, + GDK_IC_PREEDIT_AREA); } #endif } @@ -1236,13 +1257,9 @@ gtk_entry_draw_text (GtkEntry *entry) GtkWidget *widget; GtkEditable *editable; GtkStateType selected_state; - gint start_char; gint start_pos; gint end_pos; - gint end_char; gint start_xoffset; - gint selection_start_char; - gint selection_end_char; gint selection_start_pos; gint selection_end_pos; gint selection_start_xoffset; @@ -1251,8 +1268,8 @@ gtk_entry_draw_text (GtkEntry *entry) gint y; GdkDrawable *drawable; gint use_backing_pixmap; - gchar *stars; - gchar *toprint; + GdkWChar *stars; + GdkWChar *toprint; g_return_if_fail (entry != NULL); g_return_if_fail (GTK_IS_ENTRY (entry)); @@ -1305,12 +1322,10 @@ gtk_entry_draw_text (GtkEntry *entry) y = (height - (widget->style->font->ascent + widget->style->font->descent)) / 2; y += widget->style->font->ascent; - start_char = gtk_entry_find_position (entry, entry->scroll_offset); - start_pos = entry->char_pos[start_char]; - start_xoffset = entry->char_offset[start_char] - entry->scroll_offset; + start_pos = gtk_entry_find_position (entry, entry->scroll_offset); + start_xoffset = entry->char_offset[start_pos] - entry->scroll_offset; - end_char = gtk_entry_find_position (entry, entry->scroll_offset + width); - end_pos = entry->char_pos[end_char]; + end_pos = gtk_entry_find_position (entry, entry->scroll_offset + width); if (end_pos < entry->text_length) end_pos += 1; @@ -1324,13 +1339,10 @@ gtk_entry_draw_text (GtkEntry *entry) selection_start_pos = CLAMP (selection_start_pos, start_pos, end_pos); selection_end_pos = CLAMP (selection_end_pos, start_pos, end_pos); - selection_start_char = gtk_entry_find_char(entry,selection_start_pos); - selection_end_char = gtk_entry_find_char(entry,selection_end_pos); - selection_start_xoffset = - entry->char_offset[selection_start_char] - entry->scroll_offset; + entry->char_offset[selection_start_pos] - entry->scroll_offset; selection_end_xoffset = - entry->char_offset[selection_end_char] -entry->scroll_offset; + entry->char_offset[selection_end_pos] -entry->scroll_offset; /* if entry->visible, print a bunch of stars. If not, print the standard text. */ if (entry->visible) @@ -1341,24 +1353,18 @@ gtk_entry_draw_text (GtkEntry *entry) { gint i; - stars = g_malloc (end_char - start_char); - for (i = 0; i < end_char - start_char; i++) + stars = g_new (GdkWChar, end_pos - start_pos); + for (i = 0; i < end_pos - start_pos; i++) stars[i] = '*'; toprint = stars; - - /* Since '*' is always one byte, work in bytes */ - start_pos = start_char; - selection_start_pos = selection_start_char; - selection_end_pos = selection_end_char; - end_pos = end_char; } if (selection_start_pos > start_pos) - gdk_draw_text (drawable, widget->style->font, - widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - INNER_BORDER + start_xoffset, y, - toprint, - selection_start_pos - start_pos); + gdk_draw_text_wc (drawable, widget->style->font, + widget->style->fg_gc[GTK_WIDGET_STATE (widget)], + INNER_BORDER + start_xoffset, y, + toprint, + selection_start_pos - start_pos); if ((selection_end_pos >= start_pos) && (selection_start_pos < end_pos) && @@ -1371,19 +1377,19 @@ gtk_entry_draw_text (GtkEntry *entry) INNER_BORDER, selection_end_xoffset - selection_start_xoffset, height - 2*INNER_BORDER); - gdk_draw_text (drawable, widget->style->font, - widget->style->fg_gc[selected_state], - INNER_BORDER + selection_start_xoffset, y, - toprint + selection_start_pos - start_pos, - selection_end_pos - selection_start_pos); + gdk_draw_text_wc (drawable, widget->style->font, + widget->style->fg_gc[selected_state], + INNER_BORDER + selection_start_xoffset, y, + toprint + selection_start_pos - start_pos, + selection_end_pos - selection_start_pos); } if (selection_end_pos < end_pos) - gdk_draw_text (drawable, widget->style->font, - widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - INNER_BORDER + selection_end_xoffset, y, - toprint + selection_end_pos - start_pos, - end_pos - selection_end_pos); + gdk_draw_text_wc (drawable, widget->style->font, + widget->style->fg_gc[GTK_WIDGET_STATE (widget)], + INNER_BORDER + selection_end_xoffset, y, + toprint + selection_end_pos - start_pos, + end_pos - selection_end_pos); /* free the space allocated for the stars if it's neccessary. */ if (!entry->visible) g_free (toprint); @@ -1424,7 +1430,7 @@ gtk_entry_draw_cursor_on_drawable (GtkEntry *entry, GdkDrawable *drawable) widget = GTK_WIDGET (entry); editable = GTK_EDITABLE (entry); - xoffset = INNER_BORDER + entry->char_offset[gtk_entry_find_char (entry, editable->current_pos)]; + xoffset = INNER_BORDER + entry->char_offset[editable->current_pos]; xoffset -= entry->scroll_offset; gdk_window_get_size (entry->text_area, NULL, &text_area_height); @@ -1444,14 +1450,16 @@ gtk_entry_draw_cursor_on_drawable (GtkEntry *entry, GdkDrawable *drawable) } #ifdef USE_XIM - if (gdk_im_ready() && editable->ic && - gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION) + if (GTK_WIDGET_HAS_FOCUS(widget) && gdk_im_ready() && editable->ic && + (gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION)) { - GdkPoint spot; + editable->ic_attr->spot_location.x = xoffset; + editable->ic_attr->spot_location.y = + (text_area_height + (widget->style->font->ascent + - widget->style->font->descent) + 1) / 2; - spot.x = xoffset; - spot.y = (text_area_height + (widget->style->font->ascent - widget->style->font->descent) + 1) / 2; - gdk_ic_set_attr (editable->ic, "preeditAttributes", "spotLocation", &spot, NULL); + gdk_ic_set_attr (editable->ic, + editable->ic_attr, GDK_IC_SPOT_LOCATION); } #endif } @@ -1486,7 +1494,7 @@ gtk_entry_find_position (GtkEntry *entry, gint x) { gint start = 0; - gint end = entry->nchars; + gint end = entry->text_length; gint half; if (x <= 0) @@ -1514,7 +1522,7 @@ static gint gtk_entry_position (GtkEntry *entry, gint x) { - return entry->char_pos[gtk_entry_find_position(entry, x)]; + return gtk_entry_find_position(entry, x); } void @@ -1543,13 +1551,13 @@ entry_adjust_scroll (GtkEntry *entry) gdk_window_get_size (entry->text_area, &text_area_width, NULL); /* Display as much text as we can */ - max_offset = MAX(0, entry->char_offset[entry->nchars] - text_area_width); + max_offset = MAX(0, entry->char_offset[entry->text_length] - text_area_width); if (entry->scroll_offset > max_offset) entry->scroll_offset = max_offset; /* And make sure cursor is on screen */ - xoffset = entry->char_offset[gtk_entry_find_char (entry, GTK_EDITABLE(entry)->current_pos)]; + xoffset = entry->char_offset[GTK_EDITABLE(entry)->current_pos]; xoffset -= entry->scroll_offset; if (xoffset < 0) @@ -1574,15 +1582,12 @@ gtk_entry_grow_text (GtkEntry *entry) entry->text_size = 128; else entry->text_size *= 2; - entry->text = g_realloc (entry->text, entry->text_size); - entry->char_pos = g_realloc (entry->char_pos, - entry->text_size * sizeof(guint16)); + entry->text = g_realloc (entry->text, entry->text_size * sizeof(GdkWChar)); entry->char_offset = g_realloc (entry->char_offset, entry->text_size * sizeof(guint)); if (entry->text_length == 0) /* initial allocation */ { - entry->char_pos[0] = 0; entry->char_offset[0] = 0; } @@ -1596,28 +1601,51 @@ gtk_entry_insert_text (GtkEditable *editable, gint new_text_length, gint *position) { - gchar *text; - gint start_char; - gint end_char; + GdkWChar *text; gint start_pos; - gint last_char; gint end_pos; gint last_pos; gint max_length; gint i; - gint insertion_chars; - guint16 *insertion_pos = NULL; /* Quiet the compiler */ + guchar *new_text_nt; + gint insertion_length; + GdkWChar *insertion_text; GtkEntry *entry; + GtkWidget *widget; g_return_if_fail (editable != NULL); g_return_if_fail (GTK_IS_ENTRY (editable)); entry = GTK_ENTRY (editable); + widget = GTK_WIDGET (editable); + + if ((entry->text_length == 0) && (entry->use_wchar == FALSE)) + { + if (!GTK_WIDGET_REALIZED (widget)) + gtk_widget_ensure_style (widget); + if ((widget->style) && (widget->style->font->type == GDK_FONT_FONTSET)) + entry->use_wchar = TRUE; + } if (new_text_length < 0) - new_text_length = strlen (new_text); + { + new_text_nt = (gchar *)new_text; + new_text_length = strlen (new_text); + if (new_text_length <= 0) return; + } + else if (new_text_length == 0) + { + return; + } + else + { + /* make a null-terminated copy of new_text */ + new_text_nt = g_new (gchar, new_text_length + 1); + memcpy (new_text_nt, new_text, new_text_length); + new_text_nt[new_text_length] = 0; + } /* The algorithms here will work as long as, the text size (a * multiple of 2), fits into a guint16 but we specify a shorter @@ -1629,49 +1657,42 @@ gtk_entry_insert_text (GtkEditable *editable, else max_length = MIN (2047, entry->text_max_length); + /* Convert to wide characters */ + insertion_text = g_new (GdkWChar, new_text_length); + if (entry->use_wchar) + insertion_length = gdk_mbstowcs (insertion_text, new_text_nt, + new_text_length); + else + for (insertion_length=0; new_text_nt[insertion_length]; insertion_length++) + insertion_text[insertion_length] = new_text_nt[insertion_length]; + if (new_text_nt != (guchar *)new_text) + g_free (new_text_nt); + /* Make sure we do not exceed the maximum size of the entry. */ - if (new_text_length + entry->text_length > max_length) - new_text_length = max_length - entry->text_length; + if (insertion_length + entry->text_length > max_length) + insertion_length = max_length - entry->text_length; /* Don't insert anything, if there was nothing to insert. */ - if (new_text_length <= 0) - return; - - /* Find the length of the inserted text in characters, chop off - partial/invalid characters */ - if (gtk_use_mb) + if (insertion_length <= 0) { - gint len = 0; - - insertion_pos = g_new (guint16, new_text_length+1); - insertion_chars = 0; - - for (i=0; i<new_text_length; i+=len) - { - len = mblen (&new_text[i], MIN(MB_CUR_MAX,new_text_length-i)); - if (len < 0) - break; - insertion_pos[insertion_chars] = i; - insertion_chars++; - } - insertion_pos[insertion_chars] = i; - - new_text_length = i; + g_free(insertion_text); + return; } - else - insertion_chars = new_text_length; /* Make sure we are inserting at integral character position */ - start_char = gtk_entry_find_char (entry, *position); - start_pos = entry->char_pos[start_char]; + start_pos = *position; + if (start_pos < 0) + start_pos = 0; + else if (start_pos > entry->text_length) + start_pos = entry->text_length; - end_pos = start_pos + new_text_length; - last_pos = new_text_length + entry->text_length; + end_pos = start_pos + insertion_length; + last_pos = insertion_length + entry->text_length; if (editable->selection_start_pos >= *position) - editable->selection_start_pos += new_text_length; + editable->selection_start_pos += insertion_length; if (editable->selection_end_pos >= *position) - editable->selection_end_pos += new_text_length; + editable->selection_end_pos += insertion_length; while (last_pos >= entry->text_size) gtk_entry_grow_text (entry); @@ -1680,33 +1701,8 @@ gtk_entry_insert_text (GtkEditable *editable, for (i = last_pos - 1; i >= end_pos; i--) text[i] = text[i- (end_pos - start_pos)]; for (i = start_pos; i < end_pos; i++) - text[i] = new_text[i - start_pos]; - - if (gtk_use_mb) - { - /* Fix up the character positions */ - - end_char = start_char + insertion_chars; - last_char = entry->nchars + insertion_chars; - - for (i = last_char; i >= end_char; i--) - entry->char_pos[i] - = entry->char_pos[i - insertion_chars] + new_text_length; - - for (i = 1; i < insertion_chars ; i++) - entry->char_pos[start_char+i] = - entry->char_pos[start_char] + insertion_pos[i]; - - g_free (insertion_pos); - } - else - { - end_char = end_pos; - last_char = last_pos; - - for (i = start_char ; i <= last_char ; i++) - entry->char_pos[i] = i; - } + text[i] = insertion_text[i - start_pos]; + g_free (insertion_text); /* Fix up the the character offsets */ @@ -1714,32 +1710,31 @@ gtk_entry_insert_text (GtkEditable *editable, { gint offset = 0; - for (i = last_char; i >= end_char; i--) + for (i = last_pos; i >= end_pos; i--) entry->char_offset[i] - = entry->char_offset[i - insertion_chars]; + = entry->char_offset[i - insertion_length]; - for (i=start_char; i<end_char; i++) + for (i=start_pos; i<end_pos; i++) { - entry->char_offset[i] = entry->char_offset[start_char] + offset; + entry->char_offset[i] = entry->char_offset[start_pos] + offset; if (entry->visible) { - offset += gdk_text_width (GTK_WIDGET (entry)->style->font, - entry->text + entry->char_pos[i], - entry->char_pos[i+1] - entry->char_pos[i]); + offset += gdk_char_width_wc (GTK_WIDGET (entry)->style->font, + entry->text[i]); } else { - offset += gdk_text_width (GTK_WIDGET (entry)->style->font, "*", 1); + offset += gdk_char_width (GTK_WIDGET (entry)->style->font, '*'); } } - for (i = end_char ; i <= last_char ; i++) + for (i = end_pos; i <= last_pos; i++) entry->char_offset[i] += offset; } - entry->text_length += new_text_length; - entry->nchars += insertion_chars; + entry->text_length += insertion_length; *position = end_pos; + entry->text_mb_dirty = 1; gtk_entry_queue_draw (entry); } @@ -1750,64 +1745,30 @@ gtk_entry_recompute_offsets (GtkEntry *entry) gint i; gint offset = 0; - for (i=0; i<entry->nchars; i++) + for (i=0; i<entry->text_length; i++) { entry->char_offset[i] = offset; if (entry->visible) { - offset += gdk_text_width (GTK_WIDGET (entry)->style->font, - entry->text + entry->char_pos[i], - entry->char_pos[i+1] - entry->char_pos[i]); + offset += gdk_char_width_wc (GTK_WIDGET (entry)->style->font, + entry->text[i]); } else { - offset += gdk_text_width (GTK_WIDGET (entry)->style->font, "*", 1); + offset += gdk_char_width (GTK_WIDGET (entry)->style->font, '*'); } } entry->char_offset[i] = offset; } -/* Given a position in the entry, find the character index of the - * last character with position <= the given position - */ -static gint -gtk_entry_find_char (GtkEntry *entry, gint position) -{ - gint start = 0; - gint end = entry->nchars; - gint half; - - if (position >= entry->char_pos[end]) - return end; - if (position < 0) - return 0; - - /* invariant - char_pos[start] <= position < char_pos[end] */ - - while (start != end) - { - half = (start+end)/2; - if (half == start) - return half; - else if (entry->char_pos[half] <= position) - start = half; - else - end = half; - } - - return start; -} - static void gtk_entry_delete_text (GtkEditable *editable, gint start_pos, gint end_pos) { - gchar *text; + GdkWChar *text; gint deletion_length; - gint start_char; - gint end_char; gint i; GtkEntry *entry; @@ -1820,11 +1781,6 @@ gtk_entry_delete_text (GtkEditable *editable, if (end_pos < 0) end_pos = entry->text_length; - start_char = gtk_entry_find_char (entry, start_pos); - end_char = gtk_entry_find_char (entry, end_pos); - start_pos = entry->char_pos[start_char]; - end_pos = entry->char_pos[end_char]; - if (editable->selection_start_pos > start_pos) editable->selection_start_pos -= MIN(end_pos, editable->selection_start_pos) - start_pos; if (editable->selection_end_pos > start_pos) @@ -1841,10 +1797,10 @@ gtk_entry_delete_text (GtkEditable *editable, if (GTK_WIDGET_REALIZED (entry)) { gint deletion_width = - entry->char_offset[end_char] - entry->char_offset[start_char]; + entry->char_offset[end_pos] - entry->char_offset[start_pos]; - for (i = 0 ; i <= entry->nchars - end_char; i++) - entry->char_offset[start_char+i] = entry->char_offset[end_char+i] - deletion_width; + for (i = 0 ; i <= entry->text_length - end_pos; i++) + entry->char_offset[start_pos+i] = entry->char_offset[end_pos+i] - deletion_width; } for (i = end_pos; i < entry->text_length; i++) @@ -1853,15 +1809,11 @@ gtk_entry_delete_text (GtkEditable *editable, for (i = entry->text_length - deletion_length; i < entry->text_length; i++) text[i] = '\0'; - for (i = 0 ; i <= entry->nchars - end_char; i++) - entry->char_pos[start_char+i] = entry->char_pos[end_char+i] - deletion_length; - - entry->nchars -= end_char - start_char; - entry->text_length -= deletion_length; editable->current_pos = start_pos; } + entry->text_mb_dirty = 1; gtk_entry_queue_draw (entry); } @@ -1878,9 +1830,7 @@ gtk_entry_get_chars (GtkEditable *editable, gint start_pos, gint end_pos) { - gchar *retval; GtkEntry *entry; - gchar c; g_return_val_if_fail (editable != NULL, NULL); g_return_val_if_fail (GTK_IS_ENTRY (editable), NULL); @@ -1895,14 +1845,27 @@ gtk_entry_get_chars (GtkEditable *editable, if (start_pos <= end_pos) { - c = entry->text[end_pos]; - entry->text[end_pos] = '\0'; - - retval = g_strdup (&entry->text[start_pos]); - - entry->text[end_pos] = c; - - return retval; + guchar *mbstr; + if (entry->use_wchar) + { + GdkWChar ch; + if (end_pos >= entry->text_size) + gtk_entry_grow_text(entry); + ch = entry->text[end_pos]; + entry->text[end_pos] = 0; + mbstr = gdk_wcstombs (entry->text + start_pos); + entry->text[end_pos] = ch; + return (gchar *)mbstr; + } + else + { + gint i; + mbstr = g_new (gchar, end_pos - start_pos + 1); + for (i=0; i<end_pos-start_pos; i++) + mbstr[i] = entry->text[start_pos + i]; + mbstr[i] = 0; + return (gchar *)mbstr; + } } else return NULL; @@ -1913,47 +1876,16 @@ gtk_entry_move_cursor (GtkEditable *editable, gint x, gint y) { - gint len; - GtkEntry *entry; entry = GTK_ENTRY (editable); /* Horizontal motion */ - if (x > 0) - { - while (x-- != 0) - { - if (gtk_use_mb) - { - if (editable->current_pos < entry->text_length) - { - len = mblen (entry->text+editable->current_pos, MB_CUR_MAX); - editable->current_pos += (len>0)? len:1; - } - if (editable->current_pos > entry->text_length) - editable->current_pos = entry->text_length; - } - else - { - if (editable->current_pos < entry->text_length) - editable->current_pos ++; - } - } - } - else if (x < 0) - { - while (x++ != 0) - { - if (0 < editable->current_pos) - { - if (gtk_use_mb) - editable->current_pos = - entry->char_pos[gtk_entry_find_char (entry, editable->current_pos - 1)]; - else - editable->current_pos--; - } - } - } + if ((gint)editable->current_pos < -x) + editable->current_pos = 0; + else if (editable->current_pos + x > entry->text_length) + editable->current_pos = entry->text_length; + else + editable->current_pos += x; /* Ignore vertical motion */ } @@ -1974,26 +1906,18 @@ static void gtk_entry_move_word (GtkEditable *editable, gint n) { - if (n > 0) - { - while (n-- != 0) - gtk_move_forward_word (GTK_ENTRY (editable)); - } - else if (n < 0) - { - while (n++ != 0) - gtk_move_backward_word (GTK_ENTRY (editable)); - } + while (n-- > 0) + gtk_move_forward_word (GTK_ENTRY (editable)); + while (n++ < 0) + gtk_move_backward_word (GTK_ENTRY (editable)); } static void gtk_move_forward_word (GtkEntry *entry) { GtkEditable *editable; - gchar *text; + GdkWChar *text; gint i; - wchar_t c; - gint len; editable = GTK_EDITABLE (entry); @@ -2002,45 +1926,20 @@ gtk_move_forward_word (GtkEntry *entry) text = entry->text; i = editable->current_pos; - if (gtk_use_mb) + if ((entry->use_wchar) ? (!gdk_iswalnum (text[i])) : (!isalnum (text[i]))) + for (; i < entry->text_length; i++) + { + if ((entry->use_wchar) ? gdk_iswalnum (text[i]) : isalnum (text[i])) + break; + } + + for (; i < entry->text_length; i++) { - len = mbtowc (&c, text+i, MB_CUR_MAX); - if (!iswalnum(c)) - for (; i < entry->text_length; i+=len) - { - len = mbtowc (&c, text+i, MB_CUR_MAX); - if (len < 1 || iswalnum(c)) - break; - } - - for (; i < entry->text_length; i+=len) - { - len = mbtowc (&c, text+i, MB_CUR_MAX); - if (len < 1 || !iswalnum(c)) - break; - } - - editable->current_pos = i; - if (editable->current_pos > entry->text_length) - editable->current_pos = entry->text_length; + if ((entry->use_wchar) ? (!gdk_iswalnum (text[i])) : (!isalnum (text[i]))) + break; } - else - { - if (!isalnum (text[i])) - for (; i < entry->text_length; i++) - { - if (isalnum(text[i])) - break; - } - - for (; i < entry->text_length; i++) - { - if (!isalnum(text[i])) - break; - } - editable->current_pos = i; - } + editable->current_pos = i; } } @@ -2048,70 +1947,34 @@ static void gtk_move_backward_word (GtkEntry *entry) { GtkEditable *editable; - gchar *text; + GdkWChar *text; gint i; - wchar_t c; editable = GTK_EDITABLE (entry); if (entry->text && editable->current_pos > 0) { text = entry->text; - - if (gtk_use_mb) + i = editable->current_pos - 1; + if ((entry->use_wchar) ? (!gdk_iswalnum (text[i])) : (!isalnum (text[i]))) + for (; i >= 0; i--) + { + if ((entry->use_wchar) ? gdk_iswalnum (text[i]) : isalnum (text[i])) + break; + } + for (; i >= 0; i--) { - i = gtk_entry_find_char (entry, editable->current_pos - 1); - - mbtowc (&c, text+entry->char_pos[i], MB_CUR_MAX); - if (!iswalnum(c)) - for (; i >= 0; i--) - { - mbtowc (&c, text+entry->char_pos[i], MB_CUR_MAX); - if (iswalnum(c)) - break; - } - - for (; i >= 0; i--) + if ((entry->use_wchar) ? (!gdk_iswalnum (text[i])) : (!isalnum (text[i]))) { - mbtowc (&c, text+entry->char_pos[i], MB_CUR_MAX); - if (!iswalnum(c)) - { - i++; - break; - } + i++; + break; } - - if (i < 0) - i = 0; - - editable->current_pos = entry->char_pos[i]; } - else - { - i = editable->current_pos - 1; - - if (!isalnum(text[i])) - for (; i >= 0; i--) - { - if (isalnum(text[i])) - break; - } - - for (; i >= 0; i--) - { - if (!isalnum(text[i])) - { - i++; - break; - } - } - if (i < 0) - i = 0; + if (i < 0) + i = 0; - editable->current_pos = i; - } - + editable->current_pos = i; } } @@ -2122,10 +1985,10 @@ gtk_entry_move_to_column (GtkEditable *editable, gint column) entry = GTK_ENTRY (editable); - if (column < 0 || column > entry->nchars) + if (column < 0 || column > entry->text_length) editable->current_pos = entry->text_length; else - editable->current_pos = entry->char_pos[column]; + editable->current_pos = column; } static void @@ -2311,6 +2174,45 @@ gtk_entry_set_max_length (GtkEntry *entry, entry->text_max_length = max; } +#ifdef USE_XIM +static void +gtk_entry_update_ic_attr (GtkWidget *widget) +{ + GtkEditable *editable = (GtkEditable *) widget; + GdkICAttributesType mask = 0; + + gdk_ic_get_attr (editable->ic, editable->ic_attr, + GDK_IC_PREEDIT_FOREGROUND | + GDK_IC_PREEDIT_BACKGROUND | + GDK_IC_PREEDIT_FONTSET); + + if (editable->ic_attr->preedit_foreground.pixel != + widget->style->fg[GTK_STATE_NORMAL].pixel) + { + mask |= GDK_IC_PREEDIT_FOREGROUND; + editable->ic_attr->preedit_foreground + = widget->style->fg[GTK_STATE_NORMAL]; + } + if (editable->ic_attr->preedit_background.pixel != + widget->style->base[GTK_STATE_NORMAL].pixel) + { + mask |= GDK_IC_PREEDIT_BACKGROUND; + editable->ic_attr->preedit_background + = widget->style->base[GTK_STATE_NORMAL]; + } + if ((gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION) && + !gdk_font_equal (editable->ic_attr->preedit_fontset, + widget->style->font)) + { + mask |= GDK_IC_PREEDIT_FONTSET; + editable->ic_attr->preedit_fontset = widget->style->font; + } + + if (mask) + gdk_ic_set_attr (editable->ic, editable->ic_attr, mask); +} +#endif /* USE_XIM */ + static void gtk_entry_style_set (GtkWidget *widget, GtkStyle *previous_style) @@ -2332,6 +2234,10 @@ gtk_entry_style_set (GtkWidget *widget, gdk_window_set_background (widget->window, &widget->style->base[GTK_WIDGET_STATE (widget)]); gdk_window_set_background (entry->text_area, &widget->style->base[GTK_WIDGET_STATE (widget)]); + +#ifdef USE_XIM + gtk_entry_update_ic_attr (widget); +#endif } if (GTK_WIDGET_DRAWABLE (widget)) @@ -2349,6 +2255,10 @@ gtk_entry_state_changed (GtkWidget *widget, { gdk_window_set_background (widget->window, &widget->style->base[GTK_WIDGET_STATE (widget)]); gdk_window_set_background (GTK_ENTRY (widget)->text_area, &widget->style->base[GTK_WIDGET_STATE (widget)]); + +#ifdef USE_XIM + gtk_entry_update_ic_attr (widget); +#endif } if (GTK_WIDGET_DRAWABLE (widget)) diff --git a/gtk/gtkentry.h b/gtk/gtkentry.h index a487c5e56b..c1b6f90652 100644 --- a/gtk/gtkentry.h +++ b/gtk/gtkentry.h @@ -46,26 +46,27 @@ struct _GtkEntry GdkWindow *text_area; GdkPixmap *backing_pixmap; GdkCursor *cursor; - gchar *text; + GdkWChar *text; - guint16 text_size; - guint16 text_length; + guint16 text_size; /* allocated size */ + guint16 text_length; /* length in use */ guint16 text_max_length; gint scroll_offset; guint visible : 1; guint32 timer; guint button; - /* The total number of characters (not bytes) in the entry */ - guint nchars; - - /* The byte offset of each character - * (including the last insertion position) */ - guint16 *char_pos; - /* The x-offset of each character (including the last insertion position) * only valid when the widget is realized */ - gint *char_offset; + gint *char_offset; + + /* Same as 'text', but in multibyte */ + gchar *text_mb; + /* If true, 'text' and 'text_mb' are not coherent */ + guint text_mb_dirty : 1; + /* If true, we use the encoding of wchar_t as the encoding of 'text'. + * Otherwise we use the encoding of multi-byte characters instead. */ + guint use_wchar : 1; }; struct _GtkEntryClass @@ -75,7 +76,7 @@ struct _GtkEntryClass GtkType gtk_entry_get_type (void); GtkWidget* gtk_entry_new (void); -GtkWidget* gtk_entry_new_with_max_length (guint16 max); +GtkWidget* gtk_entry_new_with_max_length (guint16 max); void gtk_entry_set_text (GtkEntry *entry, const gchar *text); void gtk_entry_append_text (GtkEntry *entry, @@ -84,6 +85,7 @@ void gtk_entry_prepend_text (GtkEntry *entry, const gchar *text); void gtk_entry_set_position (GtkEntry *entry, gint position); +/* returns a reference to the text */ gchar* gtk_entry_get_text (GtkEntry *entry); void gtk_entry_select_region (GtkEntry *entry, gint start, diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index 2f3d58b073..cabdf87e7d 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -248,15 +248,12 @@ gtk_check_version (guint required_major, } -gint gtk_use_mb = -1; - void gtk_init (int *argc, char ***argv) { GSList *gtk_modules = NULL; GSList *slist; - gchar *current_locale; gchar *env_string = NULL; if (gtk_initialized) @@ -397,42 +394,6 @@ gtk_init (int *argc, } } - /* Check if there is a good chance the mb functions will handle things - * correctly - set if either mblen("\xc0", MB_CUR_MAX) == 1 in the - * C locale, or we're using X's mb functions. (-DX_LOCALE && locale != C) - */ - - current_locale = setlocale (LC_CTYPE, NULL); - -#ifdef X_LOCALE - if ((strcmp (current_locale, "C")) && (strcmp (current_locale, "POSIX"))) - gtk_use_mb = TRUE; - else -#endif /* X_LOCALE */ - { - /* Detect GNU libc, where mb == UTF8. Not useful unless it's - * really a UTF8 locale. The below still probably will - * screw up on Greek, Cyrillic, etc, encoded as UTF8. - */ - - wchar_t result; - gtk_use_mb = TRUE; - - if ((MB_CUR_MAX == 2) && - (mbstowcs (&result, "\xdd\xa5", 1) > 0) && - result == 0x765) - { - if ((strlen (current_locale) < 4) || - g_strcasecmp (current_locale + strlen(current_locale) - 4, "utf8")) - gtk_use_mb = FALSE; - } - } - - GTK_NOTE (MISC, - g_message ("%s multi-byte string functions.", - gtk_use_mb ? "Using" : "Not using")); - - /* load gtk modules */ gtk_modules = g_slist_reverse (gtk_modules); for (slist = gtk_modules; slist; slist = slist->next) diff --git a/gtk/gtkprivate.h b/gtk/gtkprivate.h index 9ec6863478..a71cd73161 100644 --- a/gtk/gtkprivate.h +++ b/gtk/gtkprivate.h @@ -60,12 +60,6 @@ typedef enum #define GTK_PRIVATE_SET_FLAG(wid,flag) G_STMT_START{ (GTK_PRIVATE_FLAGS (wid) |= (PRIVATE_ ## flag)); }G_STMT_END #define GTK_PRIVATE_UNSET_FLAG(wid,flag) G_STMT_START{ (GTK_PRIVATE_FLAGS (wid) &= ~(PRIVATE_ ## flag)); }G_STMT_END -/* True if there is a good chance the mb functions will handle things - * correctly - set if either mblen("\xc0", MB_CUR_MAX) == 1 in the - * C locale, or were using X's mb functions. (-DX_LOCALE && locale != C) - */ -extern gint gtk_use_mb; - #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/gtk/gtkspinbutton.c b/gtk/gtkspinbutton.c index 1307119235..e806f85704 100644 --- a/gtk/gtkspinbutton.c +++ b/gtk/gtkspinbutton.c @@ -1182,8 +1182,11 @@ gtk_spin_button_insert_text (GtkEditable *editable, gboolean sign; gint dotpos = -1; gint i; - gchar pos_sign; - gchar neg_sign; + GdkWChar pos_sign; + GdkWChar neg_sign; + guint entry_length; + + entry_length = entry->text_length; lc = localeconv (); @@ -1197,16 +1200,27 @@ gtk_spin_button_insert_text (GtkEditable *editable, else pos_sign = '+'; - sign = ((strchr (entry->text, neg_sign) != 0) || - (strchr (entry->text, pos_sign) != 0)); + for (sign=0, i=0; i<entry_length; i++) + if ((entry->text[i] == neg_sign) || + (entry->text[i] == pos_sign)) + { + sign = 1; + break; + } if (sign && !(*position)) return; - dotpos = strchr (entry->text, *(lc->decimal_point)) - entry->text; - + for (dotpos=-1, i=0; i<entry_length; i++) + if (entry->text[i] == *(lc->decimal_point)) + { + dotpos = i; + break; + } + if (dotpos > -1 && *position > dotpos && - spin->digits - entry->text_length + dotpos - new_text_length + 1 < 0) + spin->digits - entry_length + + dotpos - new_text_length + 1 < 0) return; for (i = 0; i < new_text_length; i++) @@ -1220,8 +1234,8 @@ gtk_spin_button_insert_text (GtkEditable *editable, else if (new_text[i] == *(lc->decimal_point)) { if (!spin->digits || dotpos > -1 || - (new_text_length - 1 - i + entry->text_length - *position > - spin->digits)) + (new_text_length - 1 - i + entry_length + - *position > spin->digits)) return; dotpos = *position + i; } diff --git a/gtk/gtktext.c b/gtk/gtktext.c index 18281ccd18..0a993a2fd2 100644 --- a/gtk/gtktext.c +++ b/gtk/gtktext.c @@ -19,9 +19,7 @@ #include <ctype.h> #include <string.h> #include "gdk/gdkkeysyms.h" -#ifdef USE_XIM -#include "gdk/gdkx.h" -#endif +#include "gdk/gdki18n.h" #include "gtkmain.h" #include "gtkselection.h" #include "gtksignal.h" @@ -248,7 +246,7 @@ static gint gtk_text_focus_in (GtkWidget *widget, static gint gtk_text_focus_out (GtkWidget *widget, GdkEventFocus *event); -static void move_gap_to_point (GtkText* text); +static void move_gap (GtkText* text, guint index); static void make_forward_space (GtkText* text, guint len); /* Property management */ @@ -674,9 +672,13 @@ gtk_text_init (GtkText *text) text->line_wrap_bitmap = NULL; text->line_arrow_bitmap = NULL; - text->text = g_new (guchar, INITIAL_BUFFER_SIZE); + text->use_wchar = FALSE; + text->text.ch = g_new (guchar, INITIAL_BUFFER_SIZE); text->text_len = INITIAL_BUFFER_SIZE; - + + text->scratch_buffer.ch = NULL; + text->scratch_buffer_len = 0; + text->freeze_count = 0; if (!params_mem_chunk) @@ -921,6 +923,7 @@ gtk_text_insert (GtkText *text, guint old_height = 0; guint length; guint i; + gint numwcs; g_return_if_fail (text != NULL); g_return_if_fail (GTK_IS_TEXT (text)); @@ -943,37 +946,90 @@ gtk_text_insert (GtkText *text, { find_line_containing_point (text, text->point.index, TRUE); old_height = total_line_height (text, text->current_line, 1); - for (i=0; i<length; i++) - if (chars[i] == '\n') - new_line_count++; } - if (text->point.index < text->first_line_start_index) - text->first_line_start_index += length; - - if (text->point.index < editable->selection_start_pos) - editable->selection_start_pos += length; - if (text->point.index < editable->selection_end_pos) - editable->selection_end_pos += length; - /* We'll reset the cursor later anyways if we aren't frozen */ - if (text->point.index < text->cursor_mark.index) - text->cursor_mark.index += length; - - move_gap_to_point (text); - + if ((TEXT_LENGTH (text) == 0) && (text->use_wchar == FALSE)) + { + GtkWidget *widget; + widget = GTK_WIDGET (text); + gtk_widget_ensure_style (widget); + if ((widget->style) && (widget->style->font->type == GDK_FONT_FONTSET)) + { + text->use_wchar = TRUE; + g_free (text->text.ch); + text->text.wc = g_new (GdkWChar, INITIAL_BUFFER_SIZE); + text->text_len = INITIAL_BUFFER_SIZE; + if (text->scratch_buffer.ch) + g_free (text->scratch_buffer.ch); + text->scratch_buffer.wc = NULL; + text->scratch_buffer_len = 0; + } + } + + move_gap (text, text->point.index); make_forward_space (text, length); - memcpy (text->text + text->gap_position, chars, length); - - insert_text_property (text, font, fore, back, length); - - text->gap_size -= length; - text->gap_position += length; - - advance_mark_n (&text->point, length); + + if (text->use_wchar) + { + char *chars_nt = (char *)chars; + if (nchars > 0) + { + chars_nt = g_new (char, length+1); + memcpy (chars_nt, chars, length); + chars_nt[length] = 0; + } + numwcs = gdk_mbstowcs (text->text.wc + text->gap_position, chars_nt, + length); + if (chars_nt != chars) + g_free(chars_nt); + if (numwcs < 0) + numwcs = 0; + } + else + { + numwcs = length; + memcpy(text->text.ch + text->gap_position, chars, length); + } + + if (!text->freeze_count && (text->line_start_cache != NULL)) + { + if (text->use_wchar) + { + for (i=0; i<numwcs; i++) + if (text->text.wc[text->gap_position + i] == '\n') + new_line_count++; + } + else + { + for (i=0; i<numwcs; i++) + if (text->text.ch[text->gap_position + i] == '\n') + new_line_count++; + } + } + + if (numwcs > 0) + { + insert_text_property (text, font, fore, back, numwcs); + + text->gap_size -= numwcs; + text->gap_position += numwcs; + + if (text->point.index < text->first_line_start_index) + text->first_line_start_index += numwcs; + if (text->point.index < editable->selection_start_pos) + editable->selection_start_pos += numwcs; + if (text->point.index < editable->selection_end_pos) + editable->selection_end_pos += numwcs; + /* We'll reset the cursor later anyways if we aren't frozen */ + if (text->point.index < text->cursor_mark.index) + text->cursor_mark.index += numwcs; - if (!text->freeze_count && text->line_start_cache != NULL) - insert_expose (text, old_height, length, new_line_count); + advance_mark_n (&text->point, numwcs); + if (!text->freeze_count && (text->line_start_cache != NULL)) + insert_expose (text, old_height, numwcs, new_line_count); + } + if (frozen) gtk_text_thaw (text); } @@ -1030,7 +1086,8 @@ gtk_text_forward_delete (GtkText *text, { text->first_line_start_index = text->point.index; while ((text->first_line_start_index > 0) && - (GTK_TEXT_INDEX (text, text->first_line_start_index - 1) != LINE_DELIM)) + (GTK_TEXT_INDEX (text, text->first_line_start_index - 1) + != LINE_DELIM)) text->first_line_start_index -= 1; } @@ -1049,7 +1106,7 @@ gtk_text_forward_delete (GtkText *text, move_mark_n (&text->cursor_mark, -MIN(nchars, text->cursor_mark.index - text->point.index)); - move_gap_to_point (text); + move_gap (text, text->point.index); text->gap_size += nchars; @@ -1086,10 +1143,8 @@ gtk_text_get_chars (GtkEditable *editable, gint end_pos) { GtkText *text; - + gchar *retval; - gchar *p; - guint n, nchars; g_return_val_if_fail (editable != NULL, NULL); g_return_val_if_fail (GTK_IS_TEXT (editable), NULL); @@ -1103,31 +1158,26 @@ gtk_text_get_chars (GtkEditable *editable, (end_pos < start_pos)) return NULL; - nchars = end_pos - start_pos; - - retval = g_new (gchar, nchars+1); - p = retval; - - if (start_pos < text->gap_position) + move_gap (text, TEXT_LENGTH (text)); + make_forward_space (text, 1); + + if (text->use_wchar) { - n = MIN (text->gap_position - start_pos, nchars); - memcpy (p, &text->text[start_pos], n); - p += n; - start_pos += n; - nchars -= n; + GdkWChar ch; + ch = text->text.wc[end_pos]; + text->text.wc[end_pos] = 0; + retval = gdk_wcstombs (text->text.wc + start_pos); + text->text.wc[end_pos] = ch; } - - if (start_pos+nchars >= text->gap_position) + else { - memcpy (p, - text->text + MAX (text->gap_position + text->gap_size, - start_pos + text->gap_size), - nchars); - p += nchars; + guchar ch; + ch = text->text.ch[end_pos]; + text->text.ch[end_pos] = 0; + retval = g_strdup (text->text.ch + start_pos); + text->text.ch[end_pos] = ch; } - - *p = 0; - + return retval; } @@ -1169,7 +1219,10 @@ gtk_text_finalize (GtkObject *object) gtk_object_unref (GTK_OBJECT (text->vadj)); /* Clean up the internal structures */ - g_free (text->text); + if (text->use_wchar) + g_free (text->text.wc); + else + g_free (text->text.ch); free_cache (text); tmp_list = text->text_properties; @@ -1184,8 +1237,16 @@ gtk_text_finalize (GtkObject *object) g_list_free (text->text_properties); - if (text->scratch_buffer) - g_free (text->scratch_buffer); + if (text->use_wchar) + { + if (text->scratch_buffer.wc) + g_free (text->scratch_buffer.wc); + } + else + { + if (text->scratch_buffer.ch) + g_free (text->scratch_buffer.ch); + } g_list_free (text->tab_stops); @@ -1257,12 +1318,13 @@ gtk_text_realize (GtkWidget *widget) gdk_gc_set_foreground (text->gc, &widget->style->text[GTK_STATE_NORMAL]); #ifdef USE_XIM - if (gdk_im_ready ()) + if (gdk_im_ready () && (editable->ic_attr = gdk_ic_attr_new ()) != NULL) { - GdkPoint spot; - GdkRectangle rect; gint width, height; + GdkColormap *colormap; GdkEventMask mask; + GdkICAttr *attr = editable->ic_attr; + GdkICAttributesType attrmask = GDK_IC_ALL_REQ; GdkIMStyle style; GdkIMStyle supported_style = GDK_IM_PREEDIT_NONE | GDK_IM_PREEDIT_NOTHING | @@ -1273,7 +1335,16 @@ gtk_text_realize (GtkWidget *widget) if (widget->style && widget->style->font->type != GDK_FONT_FONTSET) supported_style &= ~GDK_IM_PREEDIT_POSITION; - style = gdk_im_decide_style (supported_style); + attr->style = style = gdk_im_decide_style (supported_style); + attr->client_window = text->text_area; + + if ((colormap = gtk_widget_get_colormap (widget)) != + gtk_widget_get_default_colormap ()) + { + attrmask |= GDK_IC_PREEDIT_COLORMAP; + attr->preedit_colormap = colormap; + } + switch (style & GDK_IM_PREEDIT_MASK) { case GDK_IM_PREEDIT_POSITION: @@ -1282,43 +1353,31 @@ gtk_text_realize (GtkWidget *widget) g_warning ("over-the-spot style requires fontset"); break; } + + attrmask |= GDK_IC_PREEDIT_POSITION_REQ; gdk_window_get_size (text->text_area, &width, &height); - rect.x = 0; - rect.y = 0; - rect.width = width; - rect.height = height; - spot.x = 0; - spot.y = height; + attr->spot_location.x = 0; + attr->spot_location.y = height; + attr->preedit_area.x = 0; + attr->preedit_area.y = 0; + attr->preedit_area.width = width; + attr->preedit_area.height = height; + attr->preedit_fontset = widget->style->font; - editable->ic = gdk_ic_new (text->text_area, text->text_area, - style, - "spotLocation", &spot, - "area", &rect, - "fontSet", GDK_FONT_XFONT (widget->style->font), - NULL); break; - default: - editable->ic = gdk_ic_new (text->text_area, text->text_area, - style, NULL); } + editable->ic = gdk_ic_new (attr, attrmask); if (editable->ic == NULL) g_warning ("Can't create input context."); else { - GdkColormap *colormap; - mask = gdk_window_get_events (text->text_area); mask |= gdk_ic_get_events (editable->ic); gdk_window_set_events (text->text_area, mask); - if ((colormap = gtk_widget_get_colormap (widget)) != - gtk_widget_get_default_colormap ()) - { - gdk_ic_set_attr (editable->ic, "preeditAttributes", - "colorMap", GDK_COLORMAP_XCOLORMAP (colormap), - NULL); - } + if (GTK_WIDGET_HAS_FOCUS (widget)) + gdk_im_begin (editable->ic, text->text_area); } } #endif @@ -1368,7 +1427,20 @@ gtk_text_unrealize (GtkWidget *widget) g_return_if_fail (GTK_IS_TEXT (widget)); text = GTK_TEXT (widget); - + +#ifdef USE_XIM + if (GTK_EDITABLE (widget)->ic) + { + gdk_ic_destroy (GTK_EDITABLE (widget)->ic); + GTK_EDITABLE (widget)->ic = NULL; + } + if (GTK_EDITABLE (widget)->ic_attr) + { + gdk_ic_attr_destroy (GTK_EDITABLE (widget)->ic_attr); + GTK_EDITABLE (widget)->ic_attr = NULL; + } +#endif + gdk_window_set_user_data (text->text_area, NULL); gdk_window_destroy (text->text_area); text->text_area = NULL; @@ -1569,14 +1641,13 @@ gtk_text_size_allocate (GtkWidget *widget, if (editable->ic && (gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION)) { gint width, height; - GdkRectangle rect; gdk_window_get_size (text->text_area, &width, &height); - rect.x = 0; - rect.y = 0; - rect.width = width; - rect.height = height; - gdk_ic_set_attr (editable->ic, "preeditAttributes", "area", &rect, NULL); + editable->ic_attr->preedit_area.width = width; + editable->ic_attr->preedit_area.height = height; + + gdk_ic_set_attr (editable->ic, + editable->ic_attr, GDK_IC_PREEDIT_AREA); } #endif @@ -2095,12 +2166,9 @@ gtk_text_key_press (GtkWidget *widget, { extend_selection = FALSE; - if (event->length == 1) - { - gtk_editable_delete_selection (editable); - position = text->point.index; - gtk_editable_insert_text (editable, &(event->string[0]), 1, &position); - } + gtk_editable_delete_selection (editable); + position = text->point.index; + gtk_editable_insert_text (editable, event->string, event->length, &position); return_val = TRUE; } @@ -3023,27 +3091,37 @@ destroy_text_property (TextProperty *prop) /* Flop the memory between the point and the gap around like a * dead fish. */ static void -move_gap_to_point (GtkText* text) +move_gap (GtkText* text, guint index) { - if (text->gap_position < text->point.index) + if (text->gap_position < index) { - gint diff = text->point.index - text->gap_position; + gint diff = index - text->gap_position; - g_memmove (text->text + text->gap_position, - text->text + text->gap_position + text->gap_size, - diff); + if (text->use_wchar) + g_memmove (text->text.wc + text->gap_position, + text->text.wc + text->gap_position + text->gap_size, + diff*sizeof (GdkWChar)); + else + g_memmove (text->text.ch + text->gap_position, + text->text.ch + text->gap_position + text->gap_size, + diff); - text->gap_position = text->point.index; + text->gap_position = index; } - else if (text->gap_position > text->point.index) + else if (text->gap_position > index) { - gint diff = text->gap_position - text->point.index; + gint diff = text->gap_position - index; - g_memmove (text->text + text->point.index + text->gap_size, - text->text + text->point.index, - diff); + if (text->use_wchar) + g_memmove (text->text.wc + index + text->gap_size, + text->text.wc + index, + diff*sizeof (GdkWChar)); + else + g_memmove (text->text.ch + index + text->gap_size, + text->text.ch + index, + diff); - text->gap_position = text->point.index; + text->gap_position = index; } } @@ -3061,12 +3139,23 @@ make_forward_space (GtkText* text, guint len) while (i <= sum) i <<= 1; - text->text = (guchar*)g_realloc(text->text, i); + if (text->use_wchar) + text->text.wc = (GdkWChar *)g_realloc(text->text.wc, + i*sizeof(GdkWChar)); + else + text->text.ch = (guchar *)g_realloc(text->text.ch, i); + text->text_len = i; } - g_memmove (text->text + text->gap_position + text->gap_size + 2*len, - text->text + text->gap_position + text->gap_size, - text->text_end - (text->gap_position + text->gap_size)); + if (text->use_wchar) + g_memmove (text->text.wc + text->gap_position + text->gap_size + 2*len, + text->text.wc + text->gap_position + text->gap_size, + (text->text_end - (text->gap_position + text->gap_size)) + *sizeof(GdkWChar)); + else + g_memmove (text->text.ch + text->gap_position + text->gap_size + 2*len, + text->text.ch + text->gap_position + text->gap_size, + text->text_end - (text->gap_position + text->gap_size)); text->text_end += len*2; text->gap_size += len*2; @@ -3498,8 +3587,8 @@ find_line_containing_point (GtkText* text, guint point, ( (text->first_cut_pixels == 0) && (CACHE_DATA(text->line_start_cache).start.index > point) ) ) { - scroll_int (text, - SCROLL_PIXELS); g_assert (text->line_start_cache->next); + scroll_int (text, - LINE_HEIGHT(CACHE_DATA(text->line_start_cache->next))); } TEXT_SHOW (text); @@ -3567,7 +3656,7 @@ pixel_height_of (GtkText* text, GList* cache_line) static gint find_char_width (GtkText* text, const GtkPropertyMark *mark, const TabStopMark *tab_mark) { - gchar ch; + GdkWChar ch; gint16* char_widths; if (LAST_INDEX (text, *mark)) @@ -3580,14 +3669,18 @@ find_char_width (GtkText* text, const GtkPropertyMark *mark, const TabStopMark * { return tab_mark->to_next_tab * char_widths[' ']; } + else if (ch < 256) + { + return char_widths[ch]; + } else { - return char_widths[ch & 0xff]; + return gdk_char_width_wc(MARK_CURRENT_TEXT_FONT(text, mark)->gdk_font, ch); } } static void -advance_tab_mark (GtkText* text, TabStopMark* tab_mark, gchar ch) +advance_tab_mark (GtkText* text, TabStopMark* tab_mark, GdkWChar ch) { if (tab_mark->to_next_tab == 1 || ch == '\t') { @@ -3618,7 +3711,7 @@ advance_tab_mark_n (GtkText* text, TabStopMark* tab_mark, gint n) static void find_cursor_at_line (GtkText* text, const LineParams* start_line, gint pixel_height) { - gchar ch; + GdkWChar ch; GtkEditable *editable = (GtkEditable *)text; GtkPropertyMark mark = start_line->start; @@ -3641,30 +3734,32 @@ find_cursor_at_line (GtkText* text, const LineParams* start_line, gint pixel_hei ch = LAST_INDEX (text, mark) ? LINE_DELIM : GTK_TEXT_INDEX (text, mark.index); - if (!isspace(ch)) - text->cursor_char = ch; - else + if ((text->use_wchar) ? gdk_iswspace (ch) : isspace (ch)) text->cursor_char = 0; - + else + text->cursor_char = ch; + #ifdef USE_XIM - if (gdk_im_ready() && editable->ic && - gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION) + if (GTK_WIDGET_HAS_FOCUS(text) && gdk_im_ready() && editable->ic && + (gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION)) { - GdkPoint spot; - - spot.x = text->cursor_pos_x; - spot.y = text->cursor_pos_y - text->cursor_char_offset; + GdkICAttributesType mask = GDK_IC_SPOT_LOCATION | + GDK_IC_PREEDIT_FOREGROUND | + GDK_IC_PREEDIT_BACKGROUND; + + editable->ic_attr->spot_location.x = text->cursor_pos_x; + editable->ic_attr->spot_location.y + = text->cursor_pos_y - text->cursor_char_offset; + editable->ic_attr->preedit_foreground = *MARK_CURRENT_FORE (text, &mark); + editable->ic_attr->preedit_background = *MARK_CURRENT_BACK (text, &mark); + if (MARK_CURRENT_FONT (text, &mark)->type == GDK_FONT_FONTSET) - gdk_ic_set_attr (editable->ic, "preeditAttributes", - "fontSet", GDK_FONT_XFONT (MARK_CURRENT_FONT (text, &mark)), - NULL); + { + mask |= GDK_IC_PREEDIT_FONTSET; + editable->ic_attr->preedit_fontset = MARK_CURRENT_FONT (text, &mark); + } - gdk_ic_set_attr (editable->ic, "preeditAttributes", - "spotLocation", &spot, - "lineSpace", LINE_HEIGHT (*start_line), - "foreground", MARK_CURRENT_FORE (text, &mark)->pixel, - "background", MARK_CURRENT_BACK (text, &mark)->pixel, - NULL); + gdk_ic_set_attr (editable->ic, editable->ic_attr, mask); } #endif } @@ -3700,7 +3795,7 @@ find_mouse_cursor_at_line (GtkText *text, const LineParams* lp, for (;;) { - gchar ch = LAST_INDEX (text, mark) ? + GdkWChar ch = LAST_INDEX (text, mark) ? LINE_DELIM : GTK_TEXT_INDEX (text, mark.index); if (button_x < pixel_width || mark.index == lp->end.index) @@ -3709,10 +3804,10 @@ find_mouse_cursor_at_line (GtkText *text, const LineParams* lp, text->cursor_mark = mark; text->cursor_char_offset = lp->font_descent; - if (!isspace(ch)) - text->cursor_char = ch; - else + if ((text->use_wchar) ? gdk_iswspace (ch) : isspace (ch)) text->cursor_char = 0; + else + text->cursor_char = ch; break; } @@ -3872,7 +3967,8 @@ move_cursor_ver (GtkText *text, int count) } for (i=0; i < text->cursor_virtual_x; i += 1, advance_mark(&mark)) - if (LAST_INDEX(text, mark) || GTK_TEXT_INDEX(text, mark.index) == LINE_DELIM) + if (LAST_INDEX(text, mark) || + GTK_TEXT_INDEX(text, mark.index) == LINE_DELIM) break; undraw_cursor (text, FALSE); @@ -3979,13 +4075,26 @@ gtk_text_move_forward_word (GtkText *text) undraw_cursor (text, FALSE); - while (!LAST_INDEX (text, text->cursor_mark) && - !isalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index))) - advance_mark (&text->cursor_mark); - - while (!LAST_INDEX (text, text->cursor_mark) && - isalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index))) - advance_mark (&text->cursor_mark); + if (text->use_wchar) + { + while (!LAST_INDEX (text, text->cursor_mark) && + !gdk_iswalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index))) + advance_mark (&text->cursor_mark); + + while (!LAST_INDEX (text, text->cursor_mark) && + gdk_iswalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index))) + advance_mark (&text->cursor_mark); + } + else + { + while (!LAST_INDEX (text, text->cursor_mark) && + !isalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index))) + advance_mark (&text->cursor_mark); + + while (!LAST_INDEX (text, text->cursor_mark) && + isalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index))) + advance_mark (&text->cursor_mark); + } find_cursor (text, TRUE); draw_cursor (text, FALSE); @@ -3998,13 +4107,26 @@ gtk_text_move_backward_word (GtkText *text) undraw_cursor (text, FALSE); - while ((text->cursor_mark.index > 0) && - !isalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index-1))) - decrement_mark (&text->cursor_mark); - - while ((text->cursor_mark.index > 0) && - isalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index-1))) - decrement_mark (&text->cursor_mark); + if (text->use_wchar) + { + while ((text->cursor_mark.index > 0) && + !gdk_iswalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index-1))) + decrement_mark (&text->cursor_mark); + + while ((text->cursor_mark.index > 0) && + gdk_iswalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index-1))) + decrement_mark (&text->cursor_mark); + } + else + { + while ((text->cursor_mark.index > 0) && + !isalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index-1))) + decrement_mark (&text->cursor_mark); + + while ((text->cursor_mark.index > 0) && + isalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index-1))) + decrement_mark (&text->cursor_mark); + } find_cursor (text, TRUE); draw_cursor (text, FALSE); @@ -4544,7 +4666,7 @@ find_line_params (GtkText* text, LineParams lp; TabStopMark tab_mark = tab_cont->tab_start; guint max_display_pixels; - gchar ch; + GdkWChar ch; gint ch_width; GdkFont *font; @@ -4626,11 +4748,23 @@ find_line_params (GtkText* text, lp.displayable_chars += 1; - while (!isspace (GTK_TEXT_INDEX (text, lp.end.index)) && - (lp.end.index > lp.start.index)) + if (text->use_wchar) { - decrement_mark (&lp.end); - lp.displayable_chars -= 1; + while (!gdk_iswspace (GTK_TEXT_INDEX (text, lp.end.index)) && + (lp.end.index > lp.start.index)) + { + decrement_mark (&lp.end); + lp.displayable_chars -= 1; + } + } + else + { + while (!isspace(GTK_TEXT_INDEX (text, lp.end.index)) && + (lp.end.index > lp.start.index)) + { + decrement_mark (&lp.end); + lp.displayable_chars -= 1; + } } /* If whole line is one word, revert to char wrapping */ @@ -4689,10 +4823,21 @@ expand_scratch_buffer (GtkText* text, guint len) while (i <= len && i < MIN_GAP_SIZE) i <<= 1; - if (text->scratch_buffer) - text->scratch_buffer = g_new (guchar, i); + if (text->use_wchar) + { + if (text->scratch_buffer.wc) + text->scratch_buffer.wc = g_new (GdkWChar, i); + else + text->scratch_buffer.wc = g_realloc (text->scratch_buffer.wc, + i*sizeof (GdkWChar)); + } else - text->scratch_buffer = g_realloc (text->scratch_buffer, i); + { + if (text->scratch_buffer.ch) + text->scratch_buffer.ch = g_new (guchar, i); + else + text->scratch_buffer.ch = g_realloc (text->scratch_buffer.ch, i); + } text->scratch_buffer_len = i; } @@ -4751,7 +4896,7 @@ draw_line (GtkText* text, gint i; gint len = 0; guint running_offset = lp->tab_cont.pixel_offset; - guchar* buffer; + union { GdkWChar *wc; guchar *ch; } buffer; GdkGC *fg_gc; GtkEditable *editable = GTK_EDITABLE(text); @@ -4772,17 +4917,35 @@ draw_line (GtkText* text, { expand_scratch_buffer (text, chars); - for (i = 0; i < chars; i += 1) - text->scratch_buffer[i] = GTK_TEXT_INDEX(text, mark.index + i); - - buffer = text->scratch_buffer; + if (text->use_wchar) + { + for (i = 0; i < chars; i += 1) + text->scratch_buffer.wc[i] = GTK_TEXT_INDEX(text, mark.index + i); + buffer.wc = text->scratch_buffer.wc; + } + else + { + for (i = 0; i < chars; i += 1) + text->scratch_buffer.ch[i] = GTK_TEXT_INDEX(text, mark.index + i); + buffer.ch = text->scratch_buffer.ch; + } } else { - if (mark.index >= text->gap_position) - buffer = text->text + mark.index + text->gap_size; + if (text->use_wchar) + { + if (mark.index >= text->gap_position) + buffer.wc = text->text.wc + mark.index + text->gap_size; + else + buffer.wc = text->text.wc + mark.index; + } else - buffer = text->text + mark.index; + { + if (mark.index >= text->gap_position) + buffer.ch = text->text.ch + mark.index + text->gap_size; + else + buffer.ch = text->text.ch + mark.index; + } } @@ -4792,19 +4955,42 @@ draw_line (GtkText* text, LINE_HEIGHT (*lp), TRUE); } - for (; chars > 0; chars -= len, buffer += len, len = 0) + while (chars > 0) { - if (buffer[0] != '\t') + len = 0; + if ((text->use_wchar && buffer.wc[0] != '\t') || + (!text->use_wchar && buffer.ch[0] != '\t')) { - guchar* next_tab = memchr (buffer, '\t', chars); + union { GdkWChar *wc; guchar *ch; } next_tab; gint pixel_width; GdkFont *font; - + + next_tab.wc = NULL; + if (text->use_wchar) + for (i=0; i<chars; i++) + { + if (buffer.wc[i] == '\t') + { + next_tab.wc = buffer.wc + i; + break; + } + } + else + next_tab.ch = memchr (buffer.ch, '\t', chars); + len = MIN (MARK_CURRENT_PROPERTY (&mark)->length - mark.offset, chars); - if (next_tab) - len = MIN (len, next_tab - buffer); - + if (text->use_wchar) + { + if (next_tab.wc) + len = MIN (len, next_tab.wc - buffer.wc); + } + else + { + if (next_tab.ch) + len = MIN (len, next_tab.ch - buffer.ch); + } + if (mark.index < selection_start_pos) len = MIN (len, selection_start_pos - mark.index); else if (mark.index < selection_end_pos) @@ -4815,11 +5001,20 @@ draw_line (GtkText* text, { gdk_gc_set_font (text->gc, font); gdk_gc_get_values (text->gc, &gc_values); + if (text->use_wchar) + pixel_width = gdk_text_width_wc (gc_values.font, + buffer.wc, len); + else pixel_width = gdk_text_width (gc_values.font, - (gchar*) buffer, len); + buffer.ch, len); } else - pixel_width = gdk_text_width (font, (gchar*) buffer, len); + { + if (text->use_wchar) + pixel_width = gdk_text_width_wc (font, buffer.wc, len); + else + pixel_width = gdk_text_width (font, buffer.ch, len); + } draw_bg_rect (text, &mark, running_offset, pixel_start_height, pixel_width, LINE_HEIGHT (*lp), TRUE); @@ -4838,12 +5033,20 @@ draw_line (GtkText* text, fg_gc = text->gc; } - gdk_draw_text (text->text_area, MARK_CURRENT_FONT (text, &mark), - fg_gc, - running_offset, - pixel_height, - (gchar*) buffer, - len); + if (text->use_wchar) + gdk_draw_text_wc (text->text_area, MARK_CURRENT_FONT (text, &mark), + fg_gc, + running_offset, + pixel_height, + buffer.wc, + len); + else + gdk_draw_text (text->text_area, MARK_CURRENT_FONT (text, &mark), + fg_gc, + running_offset, + pixel_height, + buffer.ch, + len); running_offset += pixel_width; @@ -4875,6 +5078,11 @@ draw_line (GtkText* text, } advance_mark_n (&mark, len); + if (text->use_wchar) + buffer.wc += len; + else + buffer.ch += len; + chars -= len; } } @@ -4958,7 +5166,7 @@ undraw_cursor (GtkText* text, gint absolute) gdk_gc_set_foreground (text->gc, MARK_CURRENT_FORE (text, &text->cursor_mark)); - gdk_draw_text (text->text_area, font, + gdk_draw_text_wc (text->text_area, font, text->gc, text->cursor_pos_x, text->cursor_pos_y - text->cursor_char_offset, diff --git a/gtk/gtktext.h b/gtk/gtktext.h index 4ba138614b..f8f35af6c7 100644 --- a/gtk/gtktext.h +++ b/gtk/gtktext.h @@ -70,7 +70,7 @@ struct _GtkText /* The text, a single segment of text a'la emacs, with a gap * where insertion occurs. */ - guchar* text; + union { GdkWChar *wc; guchar *ch; } text; /* The allocated length of the text segment. */ guint text_len; /* The gap position, index into address where a char @@ -94,7 +94,7 @@ struct _GtkText /* First visible horizontal pixel. */ guint first_onscreen_hor_pixel; /* First visible vertical pixel. */ - guint first_onscreen_ver_pixel; + guint first_onscreen_ver_pixel; /* FLAGS */ @@ -102,6 +102,9 @@ struct _GtkText * horizontal scrollbar. */ guint line_wrap : 1; guint word_wrap : 1; + /* If a fontset is supplied for the widget, use_wchar become true, + * and we use GdkWchar as the encoding of text. */ + guint use_wchar : 1; /* Frozen, don't do updates. @@@ fixme */ guint freeze_count; @@ -119,7 +122,7 @@ struct _GtkText /* SCRATCH AREA */ - guchar* scratch_buffer; + union { GdkWChar *wc; guchar *ch; } scratch_buffer; guint scratch_buffer_len; /* SCROLLING */ @@ -131,7 +134,7 @@ struct _GtkText gint cursor_pos_x; /* Position of cursor. */ gint cursor_pos_y; /* Baseline of line cursor is drawn on. */ GtkPropertyMark cursor_mark; /* Where it is in the buffer. */ - gchar cursor_char; /* Character to redraw. */ + GdkWChar cursor_char; /* Character to redraw. */ gchar cursor_char_offset; /* Distance from baseline of the font. */ gint cursor_virtual_x; /* Where it would be if it could be. */ gint cursor_drawn_level; /* How many people have undrawn. */ @@ -192,9 +195,11 @@ gint gtk_text_backward_delete (GtkText *text, gint gtk_text_forward_delete (GtkText *text, guint nchars); -#define GTK_TEXT_INDEX(t, index) \ - ((index) < (t)->gap_position ? (t)->text[index] : \ - (t)->text[(index) + (t)->gap_size]) +#define GTK_TEXT_INDEX(t, index) (((t)->use_wchar) \ + ? ((index) < (t)->gap_position ? (t)->text.wc[index] : \ + (t)->text.wc[(index)+(t)->gap_size]) \ + : ((index) < (t)->gap_position ? (t)->text.ch[index] : \ + (t)->text.ch[(index)+(t)->gap_size])) #ifdef __cplusplus } diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index ac9786fd92..9a400079d2 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -4259,14 +4259,25 @@ gtk_widget_real_unrealize (GtkWidget *widget) g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_WIDGET (widget)); - if (GTK_WIDGET_NO_WINDOW (widget) && GTK_WIDGET_MAPPED (widget)) + if (GTK_WIDGET_MAPPED (widget)) gtk_widget_real_unmap (widget); - GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED | GTK_MAPPED); + GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED); /* printf ("unrealizing %s\n", gtk_type_name (GTK_OBJECT(widget)->klass->type)); */ + /* We must do unrealize child widget BEFORE container widget. + * gdk_window_destroy() destroys specified xwindow and it's sub-xwindows. + * So, unrealizing container widget bofore it's children causes the problem + * (for example, gdk_ic_destroy () with destroyed window causes crash. ) + */ + + if (GTK_IS_CONTAINER (widget)) + gtk_container_foreach (GTK_CONTAINER (widget), + (GtkCallback) gtk_widget_unrealize, + NULL); + gtk_style_detach (widget->style); if (!GTK_WIDGET_NO_WINDOW (widget)) { @@ -4280,12 +4291,7 @@ gtk_widget_real_unrealize (GtkWidget *widget) widget->window = NULL; } - /* Unrealize afterwards to improve visual effect */ - - if (GTK_IS_CONTAINER (widget)) - gtk_container_forall (GTK_CONTAINER (widget), - (GtkCallback) gtk_widget_unrealize, - NULL); + GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED); } /***************************************** diff --git a/gtk/testgtk.c b/gtk/testgtk.c index eb4e6ccba3..4a24d8e033 100644 --- a/gtk/testgtk.c +++ b/gtk/testgtk.c @@ -5750,19 +5750,29 @@ create_text (void) if (infile) { - char buffer[1024]; - int nchars; + char *buffer; + int nbytes_read, nbytes_alloc; + nbytes_read = 0; + nbytes_alloc = 1024; + buffer = g_new (char, nbytes_alloc); while (1) { - nchars = fread(buffer, 1, 1024, infile); - gtk_text_insert (GTK_TEXT (text), NULL, NULL, - NULL, buffer, nchars); - - if (nchars < 1024) + int len; + if (nbytes_alloc < nbytes_read + 1024) + { + nbytes_alloc *= 2; + buffer = g_realloc (buffer, nbytes_alloc); + } + len = fread (buffer + nbytes_read, 1, 1024, infile); + nbytes_read += len; + if (len < 1024) break; } + gtk_text_insert (GTK_TEXT (text), NULL, NULL, + NULL, buffer, nbytes_read); + g_free(buffer); fclose (infile); } diff --git a/gtk/testgtkrc b/gtk/testgtkrc index ff0288c651..065b00caca 100644 --- a/gtk/testgtkrc +++ b/gtk/testgtkrc @@ -17,8 +17,8 @@ pixmap_path "." style "defaultfont" { -# fontset = "-adobe-helvetica-medium-r-normal--*-120-*-*-*-*-*-*,*" - font = "-adobe-helvetica-medium-r-normal--*-120-*-*-*-*-*-*,*" + fontset = "-adobe-helvetica-medium-r-normal--*-120-*-*-*-*-*-*,*" +# font = "-adobe-helvetica-medium-r-normal--*-120-*-*-*-*-*-*,*" } # common default diff --git a/tests/testgtk.c b/tests/testgtk.c index eb4e6ccba3..4a24d8e033 100644 --- a/tests/testgtk.c +++ b/tests/testgtk.c @@ -5750,19 +5750,29 @@ create_text (void) if (infile) { - char buffer[1024]; - int nchars; + char *buffer; + int nbytes_read, nbytes_alloc; + nbytes_read = 0; + nbytes_alloc = 1024; + buffer = g_new (char, nbytes_alloc); while (1) { - nchars = fread(buffer, 1, 1024, infile); - gtk_text_insert (GTK_TEXT (text), NULL, NULL, - NULL, buffer, nchars); - - if (nchars < 1024) + int len; + if (nbytes_alloc < nbytes_read + 1024) + { + nbytes_alloc *= 2; + buffer = g_realloc (buffer, nbytes_alloc); + } + len = fread (buffer + nbytes_read, 1, 1024, infile); + nbytes_read += len; + if (len < 1024) break; } + gtk_text_insert (GTK_TEXT (text), NULL, NULL, + NULL, buffer, nbytes_read); + g_free(buffer); fclose (infile); } diff --git a/tests/testgtkrc b/tests/testgtkrc index ff0288c651..065b00caca 100644 --- a/tests/testgtkrc +++ b/tests/testgtkrc @@ -17,8 +17,8 @@ pixmap_path "." style "defaultfont" { -# fontset = "-adobe-helvetica-medium-r-normal--*-120-*-*-*-*-*-*,*" - font = "-adobe-helvetica-medium-r-normal--*-120-*-*-*-*-*-*,*" + fontset = "-adobe-helvetica-medium-r-normal--*-120-*-*-*-*-*-*,*" +# font = "-adobe-helvetica-medium-r-normal--*-120-*-*-*-*-*-*,*" } # common default |