summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog77
-rw-r--r--ChangeLog.pre-2-077
-rw-r--r--ChangeLog.pre-2-1077
-rw-r--r--ChangeLog.pre-2-277
-rw-r--r--ChangeLog.pre-2-477
-rw-r--r--ChangeLog.pre-2-677
-rw-r--r--ChangeLog.pre-2-877
-rw-r--r--gdk/Makefile.am3
-rw-r--r--gdk/gdk.c774
-rw-r--r--gdk/gdk.h63
-rw-r--r--gdk/gdkdraw.c60
-rw-r--r--gdk/gdkfont.c106
-rw-r--r--gdk/gdkglobals.c4
-rw-r--r--gdk/gdki18n.h123
-rw-r--r--gdk/gdkprivate.h17
-rw-r--r--gdk/gdktypes.h70
-rw-r--r--gdk/gdkwindow.c7
-rw-r--r--gdk/x11/gdkfont-x11.c106
-rw-r--r--gdk/x11/gdkglobals-x11.c4
-rw-r--r--gdk/x11/gdkmain-x11.c774
-rw-r--r--gdk/x11/gdkwindow-x11.c7
-rw-r--r--gtk/gtkeditable.c58
-rw-r--r--gtk/gtkeditable.h15
-rw-r--r--gtk/gtkentry.c702
-rw-r--r--gtk/gtkentry.h26
-rw-r--r--gtk/gtkmain.c39
-rw-r--r--gtk/gtkprivate.h6
-rw-r--r--gtk/gtkspinbutton.c32
-rw-r--r--gtk/gtktext.c596
-rw-r--r--gtk/gtktext.h19
-rw-r--r--gtk/gtkwidget.c22
-rw-r--r--gtk/testgtk.c24
-rw-r--r--gtk/testgtkrc4
-rw-r--r--tests/testgtk.c24
-rw-r--r--tests/testgtkrc4
35 files changed, 1931 insertions, 2297 deletions
diff --git a/ChangeLog b/ChangeLog
index af8d9629b3..c37d061508 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 \
diff --git a/gdk/gdk.c b/gdk/gdk.c
index f504ea313a..15dcaa3035 100644
--- a/gdk/gdk.c
+++ b/gdk/gdk.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/gdk.h b/gdk/gdk.h
index 4cd435a841..0127077fc2 100644
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -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