diff options
37 files changed, 2421 insertions, 605 deletions
@@ -1,3 +1,55 @@ +Mon Aug 24 18:37:15 1998 Owen Taylor <otaylor@redhat.com> + + * gtk/gtktext.c: Reference count the fonts used in + the text widget. + + * gdk/gdk.h gdk/gdkcolor.c: Rename the color allocation + freeing functions to be more consistent, and more + convenient; leave the old names in for backwards compatibility. + + * gdk/gdkcolor.c gdk/gdkprivate.h: Reference count the + allocations in pseudo-color colormaps to greatly reduce + calls to XAllocColor. Keep a per-colormap hashtable to + speed up finding if there is an already-allocated matching + color. + + * gdk/gdkcolor.c: Don't just match read the system colormap + when the colormap is created, but synchronize our copy + with the system colormap periodically. + + * gdk/gdk.c gdk/gdktypes.h gtk/gtkentry.c gtk/gtktext.c: + Change XIM constants names to match GDK conventions + + * gtk/testinput.c: Allow the drawing area to get the focus. + + * gtk/testgtk.c: Change around the Text test to demonstrates + multiple fonts, use more colors. + + * gtk/gtkwidget.c: Improve gtk_widget_get_colormap()/visual() + so they work after a widget is unrealized. + + * gtk/gtktext.[ch]: Remove the requirement that the text + widget be realized before adding text (!) Allocate colors + ourself, instead of requiring the caller allocate them. + Allow changing styles to work properly by keeping track + of the values for a certain property are default or + set explicitely. + + * gtk/gtkmenu.h: Added some comments. + + * gtk/gtkentry.c: Changes to match XIM constants. + + * gtk/gdk.h gdk/gdkwindow.c: Add gdk_drawable_set_data(), + for adding keyed data to drawables. (Uses g_dataset + internally) + + * gdk/gdkpixmap.c: Keep track of the colors we allocate, + when creating an XPM - store them as user data for the GdkPixmap, + so we don't leak colors when we create pixmaps from XPM's. + + Allocate memory for color information in large blocks instead of + as many little pieces. + Mon Aug 24 11:09:32 PDT 1998 Manish Singh <yosh@gimp.org> * gdk/gdkrgb.c: removed some unused variables diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 6cefa1fc32..65f98ce78e 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,55 @@ +Mon Aug 24 18:37:15 1998 Owen Taylor <otaylor@redhat.com> + + * gtk/gtktext.c: Reference count the fonts used in + the text widget. + + * gdk/gdk.h gdk/gdkcolor.c: Rename the color allocation + freeing functions to be more consistent, and more + convenient; leave the old names in for backwards compatibility. + + * gdk/gdkcolor.c gdk/gdkprivate.h: Reference count the + allocations in pseudo-color colormaps to greatly reduce + calls to XAllocColor. Keep a per-colormap hashtable to + speed up finding if there is an already-allocated matching + color. + + * gdk/gdkcolor.c: Don't just match read the system colormap + when the colormap is created, but synchronize our copy + with the system colormap periodically. + + * gdk/gdk.c gdk/gdktypes.h gtk/gtkentry.c gtk/gtktext.c: + Change XIM constants names to match GDK conventions + + * gtk/testinput.c: Allow the drawing area to get the focus. + + * gtk/testgtk.c: Change around the Text test to demonstrates + multiple fonts, use more colors. + + * gtk/gtkwidget.c: Improve gtk_widget_get_colormap()/visual() + so they work after a widget is unrealized. + + * gtk/gtktext.[ch]: Remove the requirement that the text + widget be realized before adding text (!) Allocate colors + ourself, instead of requiring the caller allocate them. + Allow changing styles to work properly by keeping track + of the values for a certain property are default or + set explicitely. + + * gtk/gtkmenu.h: Added some comments. + + * gtk/gtkentry.c: Changes to match XIM constants. + + * gtk/gdk.h gdk/gdkwindow.c: Add gdk_drawable_set_data(), + for adding keyed data to drawables. (Uses g_dataset + internally) + + * gdk/gdkpixmap.c: Keep track of the colors we allocate, + when creating an XPM - store them as user data for the GdkPixmap, + so we don't leak colors when we create pixmaps from XPM's. + + Allocate memory for color information in large blocks instead of + as many little pieces. + Mon Aug 24 11:09:32 PDT 1998 Manish Singh <yosh@gimp.org> * gdk/gdkrgb.c: removed some unused variables diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 6cefa1fc32..65f98ce78e 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,55 @@ +Mon Aug 24 18:37:15 1998 Owen Taylor <otaylor@redhat.com> + + * gtk/gtktext.c: Reference count the fonts used in + the text widget. + + * gdk/gdk.h gdk/gdkcolor.c: Rename the color allocation + freeing functions to be more consistent, and more + convenient; leave the old names in for backwards compatibility. + + * gdk/gdkcolor.c gdk/gdkprivate.h: Reference count the + allocations in pseudo-color colormaps to greatly reduce + calls to XAllocColor. Keep a per-colormap hashtable to + speed up finding if there is an already-allocated matching + color. + + * gdk/gdkcolor.c: Don't just match read the system colormap + when the colormap is created, but synchronize our copy + with the system colormap periodically. + + * gdk/gdk.c gdk/gdktypes.h gtk/gtkentry.c gtk/gtktext.c: + Change XIM constants names to match GDK conventions + + * gtk/testinput.c: Allow the drawing area to get the focus. + + * gtk/testgtk.c: Change around the Text test to demonstrates + multiple fonts, use more colors. + + * gtk/gtkwidget.c: Improve gtk_widget_get_colormap()/visual() + so they work after a widget is unrealized. + + * gtk/gtktext.[ch]: Remove the requirement that the text + widget be realized before adding text (!) Allocate colors + ourself, instead of requiring the caller allocate them. + Allow changing styles to work properly by keeping track + of the values for a certain property are default or + set explicitely. + + * gtk/gtkmenu.h: Added some comments. + + * gtk/gtkentry.c: Changes to match XIM constants. + + * gtk/gdk.h gdk/gdkwindow.c: Add gdk_drawable_set_data(), + for adding keyed data to drawables. (Uses g_dataset + internally) + + * gdk/gdkpixmap.c: Keep track of the colors we allocate, + when creating an XPM - store them as user data for the GdkPixmap, + so we don't leak colors when we create pixmaps from XPM's. + + Allocate memory for color information in large blocks instead of + as many little pieces. + Mon Aug 24 11:09:32 PDT 1998 Manish Singh <yosh@gimp.org> * gdk/gdkrgb.c: removed some unused variables diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 6cefa1fc32..65f98ce78e 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,55 @@ +Mon Aug 24 18:37:15 1998 Owen Taylor <otaylor@redhat.com> + + * gtk/gtktext.c: Reference count the fonts used in + the text widget. + + * gdk/gdk.h gdk/gdkcolor.c: Rename the color allocation + freeing functions to be more consistent, and more + convenient; leave the old names in for backwards compatibility. + + * gdk/gdkcolor.c gdk/gdkprivate.h: Reference count the + allocations in pseudo-color colormaps to greatly reduce + calls to XAllocColor. Keep a per-colormap hashtable to + speed up finding if there is an already-allocated matching + color. + + * gdk/gdkcolor.c: Don't just match read the system colormap + when the colormap is created, but synchronize our copy + with the system colormap periodically. + + * gdk/gdk.c gdk/gdktypes.h gtk/gtkentry.c gtk/gtktext.c: + Change XIM constants names to match GDK conventions + + * gtk/testinput.c: Allow the drawing area to get the focus. + + * gtk/testgtk.c: Change around the Text test to demonstrates + multiple fonts, use more colors. + + * gtk/gtkwidget.c: Improve gtk_widget_get_colormap()/visual() + so they work after a widget is unrealized. + + * gtk/gtktext.[ch]: Remove the requirement that the text + widget be realized before adding text (!) Allocate colors + ourself, instead of requiring the caller allocate them. + Allow changing styles to work properly by keeping track + of the values for a certain property are default or + set explicitely. + + * gtk/gtkmenu.h: Added some comments. + + * gtk/gtkentry.c: Changes to match XIM constants. + + * gtk/gdk.h gdk/gdkwindow.c: Add gdk_drawable_set_data(), + for adding keyed data to drawables. (Uses g_dataset + internally) + + * gdk/gdkpixmap.c: Keep track of the colors we allocate, + when creating an XPM - store them as user data for the GdkPixmap, + so we don't leak colors when we create pixmaps from XPM's. + + Allocate memory for color information in large blocks instead of + as many little pieces. + Mon Aug 24 11:09:32 PDT 1998 Manish Singh <yosh@gimp.org> * gdk/gdkrgb.c: removed some unused variables diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 6cefa1fc32..65f98ce78e 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,55 @@ +Mon Aug 24 18:37:15 1998 Owen Taylor <otaylor@redhat.com> + + * gtk/gtktext.c: Reference count the fonts used in + the text widget. + + * gdk/gdk.h gdk/gdkcolor.c: Rename the color allocation + freeing functions to be more consistent, and more + convenient; leave the old names in for backwards compatibility. + + * gdk/gdkcolor.c gdk/gdkprivate.h: Reference count the + allocations in pseudo-color colormaps to greatly reduce + calls to XAllocColor. Keep a per-colormap hashtable to + speed up finding if there is an already-allocated matching + color. + + * gdk/gdkcolor.c: Don't just match read the system colormap + when the colormap is created, but synchronize our copy + with the system colormap periodically. + + * gdk/gdk.c gdk/gdktypes.h gtk/gtkentry.c gtk/gtktext.c: + Change XIM constants names to match GDK conventions + + * gtk/testinput.c: Allow the drawing area to get the focus. + + * gtk/testgtk.c: Change around the Text test to demonstrates + multiple fonts, use more colors. + + * gtk/gtkwidget.c: Improve gtk_widget_get_colormap()/visual() + so they work after a widget is unrealized. + + * gtk/gtktext.[ch]: Remove the requirement that the text + widget be realized before adding text (!) Allocate colors + ourself, instead of requiring the caller allocate them. + Allow changing styles to work properly by keeping track + of the values for a certain property are default or + set explicitely. + + * gtk/gtkmenu.h: Added some comments. + + * gtk/gtkentry.c: Changes to match XIM constants. + + * gtk/gdk.h gdk/gdkwindow.c: Add gdk_drawable_set_data(), + for adding keyed data to drawables. (Uses g_dataset + internally) + + * gdk/gdkpixmap.c: Keep track of the colors we allocate, + when creating an XPM - store them as user data for the GdkPixmap, + so we don't leak colors when we create pixmaps from XPM's. + + Allocate memory for color information in large blocks instead of + as many little pieces. + Mon Aug 24 11:09:32 PDT 1998 Manish Singh <yosh@gimp.org> * gdk/gdkrgb.c: removed some unused variables diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 6cefa1fc32..65f98ce78e 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,55 @@ +Mon Aug 24 18:37:15 1998 Owen Taylor <otaylor@redhat.com> + + * gtk/gtktext.c: Reference count the fonts used in + the text widget. + + * gdk/gdk.h gdk/gdkcolor.c: Rename the color allocation + freeing functions to be more consistent, and more + convenient; leave the old names in for backwards compatibility. + + * gdk/gdkcolor.c gdk/gdkprivate.h: Reference count the + allocations in pseudo-color colormaps to greatly reduce + calls to XAllocColor. Keep a per-colormap hashtable to + speed up finding if there is an already-allocated matching + color. + + * gdk/gdkcolor.c: Don't just match read the system colormap + when the colormap is created, but synchronize our copy + with the system colormap periodically. + + * gdk/gdk.c gdk/gdktypes.h gtk/gtkentry.c gtk/gtktext.c: + Change XIM constants names to match GDK conventions + + * gtk/testinput.c: Allow the drawing area to get the focus. + + * gtk/testgtk.c: Change around the Text test to demonstrates + multiple fonts, use more colors. + + * gtk/gtkwidget.c: Improve gtk_widget_get_colormap()/visual() + so they work after a widget is unrealized. + + * gtk/gtktext.[ch]: Remove the requirement that the text + widget be realized before adding text (!) Allocate colors + ourself, instead of requiring the caller allocate them. + Allow changing styles to work properly by keeping track + of the values for a certain property are default or + set explicitely. + + * gtk/gtkmenu.h: Added some comments. + + * gtk/gtkentry.c: Changes to match XIM constants. + + * gtk/gdk.h gdk/gdkwindow.c: Add gdk_drawable_set_data(), + for adding keyed data to drawables. (Uses g_dataset + internally) + + * gdk/gdkpixmap.c: Keep track of the colors we allocate, + when creating an XPM - store them as user data for the GdkPixmap, + so we don't leak colors when we create pixmaps from XPM's. + + Allocate memory for color information in large blocks instead of + as many little pieces. + Mon Aug 24 11:09:32 PDT 1998 Manish Singh <yosh@gimp.org> * gdk/gdkrgb.c: removed some unused variables diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 6cefa1fc32..65f98ce78e 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,55 @@ +Mon Aug 24 18:37:15 1998 Owen Taylor <otaylor@redhat.com> + + * gtk/gtktext.c: Reference count the fonts used in + the text widget. + + * gdk/gdk.h gdk/gdkcolor.c: Rename the color allocation + freeing functions to be more consistent, and more + convenient; leave the old names in for backwards compatibility. + + * gdk/gdkcolor.c gdk/gdkprivate.h: Reference count the + allocations in pseudo-color colormaps to greatly reduce + calls to XAllocColor. Keep a per-colormap hashtable to + speed up finding if there is an already-allocated matching + color. + + * gdk/gdkcolor.c: Don't just match read the system colormap + when the colormap is created, but synchronize our copy + with the system colormap periodically. + + * gdk/gdk.c gdk/gdktypes.h gtk/gtkentry.c gtk/gtktext.c: + Change XIM constants names to match GDK conventions + + * gtk/testinput.c: Allow the drawing area to get the focus. + + * gtk/testgtk.c: Change around the Text test to demonstrates + multiple fonts, use more colors. + + * gtk/gtkwidget.c: Improve gtk_widget_get_colormap()/visual() + so they work after a widget is unrealized. + + * gtk/gtktext.[ch]: Remove the requirement that the text + widget be realized before adding text (!) Allocate colors + ourself, instead of requiring the caller allocate them. + Allow changing styles to work properly by keeping track + of the values for a certain property are default or + set explicitely. + + * gtk/gtkmenu.h: Added some comments. + + * gtk/gtkentry.c: Changes to match XIM constants. + + * gtk/gdk.h gdk/gdkwindow.c: Add gdk_drawable_set_data(), + for adding keyed data to drawables. (Uses g_dataset + internally) + + * gdk/gdkpixmap.c: Keep track of the colors we allocate, + when creating an XPM - store them as user data for the GdkPixmap, + so we don't leak colors when we create pixmaps from XPM's. + + Allocate memory for color information in large blocks instead of + as many little pieces. + Mon Aug 24 11:09:32 PDT 1998 Manish Singh <yosh@gimp.org> * gdk/gdkrgb.c: removed some unused variables @@ -271,3 +271,5 @@ Text/Edit widget: [ From: Stefan Jeske <jeske@braunschweig.netsurf.de> ] - "changed" emitted when doing deletes on empty Text widget. + + - Delete IC in editable->unrealize, not editable->finalize?
\ No newline at end of file @@ -446,15 +446,15 @@ gdk_init (int *argc, { (*argv)[i++] = NULL; if (strcmp ("none", (*argv)[i]) == 0) - gdk_im_set_best_style (GdkIMPreeditNone); + gdk_im_set_best_style (GDK_IM_PREEDIT_NONE); else if (strcmp ("nothing", (*argv)[i]) == 0) - gdk_im_set_best_style (GdkIMPreeditNothing); + gdk_im_set_best_style (GDK_IM_PREEDIT_NOTHING); else if (strcmp ("area", (*argv)[i]) == 0) - gdk_im_set_best_style (GdkIMPreeditArea); + gdk_im_set_best_style (GDK_IM_PREEDIT_AREA); else if (strcmp ("position", (*argv)[i]) == 0) - gdk_im_set_best_style (GdkIMPreeditPosition); + gdk_im_set_best_style (GDK_IM_PREEDIT_POSITION); else if (strcmp ("callbacks", (*argv)[i]) == 0) - gdk_im_set_best_style (GdkIMPreeditCallbacks); + gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS); } } else if (strcmp ("--xim-status", (*argv)[i]) == 0) @@ -463,13 +463,13 @@ gdk_init (int *argc, { (*argv)[i++] = NULL; if (strcmp ("none", (*argv)[i]) == 0) - gdk_im_set_best_style (GdkIMStatusNone); + gdk_im_set_best_style (GDK_IM_STATUS_NONE); else if (strcmp ("nothing", (*argv)[i]) == 0) - gdk_im_set_best_style (GdkIMStatusNothing); + gdk_im_set_best_style (GDK_IM_STATUS_NOTHING); else if (strcmp ("area", (*argv)[i]) == 0) - gdk_im_set_best_style (GdkIMStatusArea); + gdk_im_set_best_style (GDK_IM_STATUS_AREA); else if (strcmp ("callbacks", (*argv)[i]) == 0) - gdk_im_set_best_style (GdkIMStatusCallbacks); + gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS); } } #endif @@ -584,10 +584,10 @@ gdk_init (int *argc, xim_using = FALSE; xim_im = NULL; xim_styles = NULL; - if (!(xim_best_allowed_style & GdkIMPreeditMask)) - gdk_im_set_best_style (GdkIMPreeditCallbacks); - if (!(xim_best_allowed_style & GdkIMStatusMask)) - gdk_im_set_best_style (GdkIMStatusCallbacks); + 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; @@ -3570,34 +3570,34 @@ gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2) if (style1 == 0) return style2; if (style2 == 0) return style1; - if ((style1 & (GdkIMPreeditMask | GdkIMStatusMask)) - == (style2 & (GdkIMPreeditMask | GdkIMStatusMask))) + if ((style1 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK)) + == (style2 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK))) return style1; - - s1 = style1 & GdkIMPreeditMask; - s2 = style2 & GdkIMPreeditMask; + + s1 = style1 & GDK_IM_PREEDIT_MASK; + s2 = style2 & GDK_IM_PREEDIT_MASK; u = s1 | s2; if (s1 != s2) { - if (u & GdkIMPreeditCallbacks) - return (s1 == GdkIMPreeditCallbacks)? style1:style2; - else if (u & GdkIMPreeditPosition) - return (s1 == GdkIMPreeditPosition)? style1:style2; - else if (u & GdkIMPreeditArea) - return (s1 == GdkIMPreeditArea)? style1:style2; - else if (u & GdkIMPreeditNothing) - return (s1 == GdkIMPreeditNothing)? style1:style2; + 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 & GdkIMStatusMask; - s2 = style2 & GdkIMStatusMask; + s1 = style1 & GDK_IM_STATUS_MASK; + s2 = style2 & GDK_IM_STATUS_MASK; u = s1 | s2; - if ( u & GdkIMStatusCallbacks) - return (s1 == GdkIMStatusCallbacks)? style1:style2; - else if ( u & GdkIMStatusArea) - return (s1 == GdkIMStatusArea)? style1:style2; - else if ( u & GdkIMStatusNothing) - return (s1 == GdkIMStatusNothing)? style1:style2; - else if ( u & GdkIMStatusNone) - return (s1 == GdkIMStatusNone)? style1:style2; + 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 */ } @@ -3623,39 +3623,39 @@ gdk_im_decide_style (GdkIMStyle supported_style) GdkIMStyle gdk_im_set_best_style (GdkIMStyle style) { - if (style & GdkIMPreeditMask) + if (style & GDK_IM_PREEDIT_MASK) { - xim_best_allowed_style &= ~GdkIMPreeditMask; - - xim_best_allowed_style |= GdkIMPreeditNone; - if (!(style & GdkIMPreeditNone)) + 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 |= GdkIMPreeditNothing; - if (!(style & GdkIMPreeditNothing)) + xim_best_allowed_style |= GDK_IM_PREEDIT_NOTHING; + if (!(style & GDK_IM_PREEDIT_NOTHING)) { - xim_best_allowed_style |= GdkIMPreeditArea; - if (!(style & GdkIMPreeditArea)) + xim_best_allowed_style |= GDK_IM_PREEDIT_AREA; + if (!(style & GDK_IM_PREEDIT_AREA)) { - xim_best_allowed_style |= GdkIMPreeditPosition; - if (!(style & GdkIMPreeditPosition)) - xim_best_allowed_style |= GdkIMPreeditCallbacks; + xim_best_allowed_style |= GDK_IM_PREEDIT_POSITION; + if (!(style & GDK_IM_PREEDIT_POSITION)) + xim_best_allowed_style |= GDK_IM_PREEDIT_CALLBACKS; } } } } - if (style & GdkIMStatusMask) + if (style & GDK_IM_STATUS_MASK) { - xim_best_allowed_style &= ~GdkIMStatusMask; - - xim_best_allowed_style |= GdkIMStatusNone; - if (!(style & GdkIMStatusNone)) + 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 |= GdkIMStatusNothing; - if (!(style & GdkIMStatusNothing)) + xim_best_allowed_style |= GDK_IM_STATUS_NOTHING; + if (!(style & GDK_IM_STATUS_NOTHING)) { - xim_best_allowed_style |= GdkIMStatusArea; - if (!(style & GdkIMStatusArea)) - xim_best_allowed_style |= GdkIMStatusCallbacks; + xim_best_allowed_style |= GDK_IM_STATUS_AREA; + if (!(style & GDK_IM_STATUS_AREA)) + xim_best_allowed_style |= GDK_IM_STATUS_CALLBACKS; } } } @@ -3960,13 +3960,13 @@ gdk_im_end (void) GdkIMStyle gdk_im_decide_style (GdkIMStyle supported_style) { - return GdkIMPreeditNone | GdkIMStatusNone; + return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE; } GdkIMStyle gdk_im_set_best_style (GdkIMStyle style) { - return GdkIMPreeditNone | GdkIMStatusNone; + return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE; } gint @@ -3991,7 +3991,7 @@ gdk_ic_destroy (GdkIC ic) GdkIMStyle gdk_ic_get_style (GdkIC ic) { - return GdkIMPreeditNone | GdkIMStatusNone; + return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE; } void @@ -307,6 +307,11 @@ void gdk_window_set_functions (GdkWindow *window, GdkWMFunction functions); GList * gdk_window_get_toplevels (void); +void gdk_drawable_set_data (GdkDrawable *drawable, + const gchar *key, + gpointer data, + GDestroyNotify destroy_func); + /* Cursors */ @@ -455,6 +460,22 @@ gint gdk_colormap_get_system_size (void); void gdk_colormap_change (GdkColormap *colormap, gint ncolors); + + +gint gdk_colormap_alloc_colors (GdkColormap *colormap, + GdkColor *colors, + gint ncolors, + gboolean writeable, + gboolean best_match, + gboolean *success); +gboolean gdk_colormap_alloc_color (GdkColormap *colormap, + GdkColor *color, + gboolean writeable, + gboolean best_match); +void gdk_colormap_free_colors (GdkColormap *colormap, + GdkColor *colors, + gint ncolors); + void gdk_colors_store (GdkColormap *colormap, GdkColor *colors, gint ncolors); @@ -482,8 +503,10 @@ gint gdk_color_alloc (GdkColormap *colormap, GdkColor *color); gint gdk_color_change (GdkColormap *colormap, GdkColor *color); -gint gdk_color_equal (GdkColor *colora, - GdkColor *colorb); +guint gdk_color_hash (const GdkColor *colora, + const GdkColor *colorb); +gint gdk_color_equal (const GdkColor *colora, + const GdkColor *colorb); /* Fonts @@ -722,22 +745,27 @@ GdkTimeCoord *gdk_input_motion_events (GdkWindow *window, /* International Input Method Support Functions */ -gint gdk_im_ready (void); - -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); +gint gdk_im_ready (void); + +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); /* Color Context */ @@ -857,6 +885,7 @@ guint gdk_keyval_to_lower (guint keyval); gboolean gdk_keyval_is_upper (guint keyval); gboolean gdk_keyval_is_lower (guint keyval); + #include <gdk/gdkrgb.h> #ifdef __cplusplus diff --git a/gdk/gdkcolor.c b/gdk/gdkcolor.c index b17e26a1c5..fa810473e6 100644 --- a/gdk/gdkcolor.c +++ b/gdk/gdkcolor.c @@ -16,6 +16,7 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ +#include <time.h> #include <X11/Xlib.h> #include "gdk.h" #include "gdkprivate.h" @@ -52,8 +53,12 @@ gdk_colormap_new (GdkVisual *visual, private->xdisplay = gdk_display; private->visual = visual; - private->next_color = 0; private->ref_count = 1; + + private->hash = NULL; + private->last_sync_time = 0; + private->info = NULL; + xvisual = ((GdkVisualPrivate*) visual)->xvisual; colormap->size = visual->colormap_size; @@ -63,6 +68,12 @@ gdk_colormap_new (GdkVisual *visual, { case GDK_VISUAL_GRAYSCALE: case GDK_VISUAL_PSEUDO_COLOR: + private->info = g_new0 (GdkColorInfo, colormap->size); + colormap->colors = g_new (GdkColor, colormap->size); + + private->hash = g_hash_table_new (gdk_color_hash, + gdk_color_equal); + private->private_val = private_cmap; private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window, xvisual, (private_cmap) ? (AllocAll) : (AllocNone)); @@ -134,12 +145,15 @@ gdk_colormap_real_destroy (GdkColormap *colormap) GdkColormapPrivate *private = (GdkColormapPrivate*) colormap; g_return_if_fail (colormap != NULL); - - if (private->ref_count > 0) - return; + g_return_if_fail (private->ref_count > 0); gdk_colormap_remove (colormap); XFreeColormap (private->xdisplay, private->xcolormap); + + if (private->hash) + g_hash_table_destroy (private->hash); + + g_free (private->info); g_free (colormap->colors); g_free (colormap); } @@ -165,13 +179,61 @@ gdk_colormap_unref (GdkColormap *cmap) gdk_colormap_real_destroy (cmap); } +#define MIN_SYNC_TIME 2 + +void +gdk_colormap_sync (GdkColormap *colormap, + gboolean force) +{ + time_t current_time; + GdkColormapPrivate *private = (GdkColormapPrivate *)colormap; + XColor *xpalette; + gint nlookup; + gint i; + + g_return_if_fail (colormap != NULL); + + current_time = time (NULL); + if (!force && ((current_time - private->last_sync_time) < MIN_SYNC_TIME)) + return; + + private->last_sync_time = current_time; + + nlookup = 0; + xpalette = g_new (XColor, colormap->size); + + for (i = 0; i < colormap->size; i++) + { + if (private->info[i].ref_count == 0) + { + xpalette[nlookup].pixel = i; + xpalette[nlookup].red = 0; + xpalette[nlookup].green = 0; + xpalette[nlookup].blue = 0; + nlookup++; + } + } + + XQueryColors (gdk_display, private->xcolormap, xpalette, nlookup); + + for (i = 0; i < nlookup; i++) + { + gulong pixel = xpalette[i].pixel; + colormap->colors[pixel].pixel = pixel; + colormap->colors[pixel].red = xpalette[i].red; + colormap->colors[pixel].green = xpalette[i].green; + colormap->colors[pixel].blue = xpalette[i].blue; + } + + g_free (xpalette); +} + + GdkColormap* gdk_colormap_get_system (void) { static GdkColormap *colormap = NULL; GdkColormapPrivate *private; - XColor *xpalette; - gint i; if (!colormap) { @@ -182,37 +244,25 @@ gdk_colormap_get_system (void) private->xcolormap = DefaultColormap (gdk_display, gdk_screen); private->visual = gdk_visual_get_system (); private->private_val = FALSE; - private->next_color = 0; private->ref_count = 1; + private->hash = NULL; + private->last_sync_time = 0; + private->info = NULL; + + colormap->colors = NULL; colormap->size = private->visual->colormap_size; - colormap->colors = g_new (GdkColor, colormap->size); if ((private->visual->type == GDK_VISUAL_GRAYSCALE) || (private->visual->type == GDK_VISUAL_PSEUDO_COLOR)) { - xpalette = g_new (XColor, colormap->size); + private->info = g_new0 (GdkColorInfo, colormap->size); + colormap->colors = g_new (GdkColor, colormap->size); - for (i = 0; i < colormap->size; i++) - { - xpalette[i].pixel = i; - xpalette[i].red = 0; - xpalette[i].green = 0; - xpalette[i].blue = 0; - } - - XQueryColors (gdk_display, private->xcolormap, xpalette, - colormap->size); - - for (i = 0; i < colormap->size; i++) - { - colormap->colors[i].pixel = xpalette[i].pixel; - colormap->colors[i].red = xpalette[i].red; - colormap->colors[i].green = xpalette[i].green; - colormap->colors[i].blue = xpalette[i].blue; - } + private->hash = g_hash_table_new (gdk_color_hash, + gdk_color_equal); - g_free (xpalette); + gdk_colormap_sync (colormap, TRUE); } gdk_colormap_add (colormap); @@ -258,7 +308,6 @@ gdk_colormap_change (GdkColormap *colormap, } XStoreColors (private->xdisplay, private->xcolormap, palette, ncolors); - private->next_color = MAX (private->next_color, ncolors); break; case GDK_VISUAL_DIRECT_COLOR: @@ -339,6 +388,7 @@ gdk_colors_alloc (GdkColormap *colormap, { GdkColormapPrivate *private; gint return_val; + gint i; g_return_val_if_fail (colormap != NULL, 0); @@ -347,23 +397,65 @@ gdk_colors_alloc (GdkColormap *colormap, return_val = XAllocColorCells (private->xdisplay, private->xcolormap, contiguous, planes, nplanes, pixels, npixels); + if (return_val) + { + for (i=0; i<npixels; i++) + { + private->info[pixels[i]].ref_count++; + private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE; + } + } + return return_val; } +/* This is almost identical to gdk_colormap_free_colors. + * Keep them in sync! + */ void gdk_colors_free (GdkColormap *colormap, - gulong *pixels, - gint npixels, + gulong *in_pixels, + gint in_npixels, gulong planes) { GdkColormapPrivate *private; + gulong *pixels; + gint npixels = 0; + gint i; g_return_if_fail (colormap != NULL); + g_return_if_fail (in_pixels != NULL); private = (GdkColormapPrivate*) colormap; - XFreeColors (private->xdisplay, private->xcolormap, - pixels, npixels, planes); + if ((private->visual->type != GDK_VISUAL_PSEUDO_COLOR) && + (private->visual->type != GDK_VISUAL_GRAYSCALE)) + return; + + pixels = g_new (gulong, in_npixels); + + for (i=0; i<in_npixels; i++) + { + gulong pixel = in_pixels[i]; + + if (private->info[pixel].ref_count) + { + private->info[pixel].ref_count--; + + if (private->info[pixel].ref_count == 0) + { + pixels[npixels++] = pixel; + if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE)) + g_hash_table_remove (private->hash, &colormap->colors[in_pixels[i]]); + private->info[pixel].flags = 0; + } + } + } + + if (npixels) + XFreeColors (private->xdisplay, private->xcolormap, + pixels, npixels, planes); + g_free (pixels); } /* @@ -494,19 +586,22 @@ gdk_color_parse (const gchar *spec, return return_val; } -gboolean -gdk_color_alloc (GdkColormap *colormap, - GdkColor *color) +/******************** + * Color allocation * + ********************/ + +/* Try to allocate a single color using XAllocColor. If it succeeds, + * cache the result in our colormap, and store in ret. + */ +static gboolean +gdk_colormap_alloc1 (GdkColormap *colormap, + GdkColor *color, + GdkColor *ret) { GdkColormapPrivate *private; - GdkVisual *visual; XColor xcolor; - gchar *available = NULL; - gboolean return_val; - gint i, index; - g_return_val_if_fail (colormap != NULL, FALSE); - g_return_val_if_fail (color != NULL, FALSE); + private = (GdkColormapPrivate*) colormap; xcolor.red = color->red; xcolor.green = color->green; @@ -514,113 +609,458 @@ gdk_color_alloc (GdkColormap *colormap, xcolor.pixel = color->pixel; xcolor.flags = DoRed | DoGreen | DoBlue; - return_val = FALSE; + if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor)) + { + ret->pixel = xcolor.pixel; + ret->red = xcolor.red; + ret->green = xcolor.green; + ret->blue = xcolor.blue; + + if (ret->pixel < colormap->size) + { + if (private->info[ret->pixel].ref_count) /* got a duplicate */ + { + XFreeColors (private->xdisplay, private->xcolormap, + &ret->pixel, 1, 0); + } + else + { + colormap->colors[ret->pixel] = *color; + private->info[ret->pixel].ref_count = 1; + + g_hash_table_insert (private->hash, + &colormap->colors[ret->pixel], + &colormap->colors[ret->pixel]); + } + } + return TRUE; + } + else + { + return FALSE; + } +} + +static gint +gdk_colormap_alloc_colors_writeable (GdkColormap *colormap, + GdkColor *colors, + gint ncolors, + gboolean writeable, + gboolean best_match, + gboolean *success) +{ + GdkColormapPrivate *private; + gulong *pixels; + Status status; + gint i, index; + private = (GdkColormapPrivate*) colormap; - switch (private->visual->type) + if (private->private_val) { - case GDK_VISUAL_GRAYSCALE: - case GDK_VISUAL_PSEUDO_COLOR: - if (private->private_val) + index = 0; + for (i=0; i<ncolors; i++) { - if (private->next_color >= colormap->size) + while ((index < colormap->size) && (private->info[index].ref_count != 0)) + index++; + + if (index < colormap->size) { - available = g_new (gchar, colormap->size); - for (i = 0; i < colormap->size; i++) - available[i] = TRUE; - - index = gdk_colormap_match_color (colormap, color, available); - if (index != -1) - { - available[index] = FALSE; - *color = colormap->colors[index]; - return_val = TRUE; - } - else - { - return_val = FALSE; - } + colors[i].pixel = index; + success[i] = TRUE; + private->info[index].ref_count++; + private->info[i].flags |= GDK_COLOR_WRITEABLE; } else + break; + } + return i; + } + else + { + pixels = g_new (gulong, ncolors); + /* Allocation of a writeable color cells */ + + status = XAllocColorCells (private->xdisplay, private->xcolormap, + FALSE, NULL, 0, pixels, ncolors); + if (status) + { + for (i=0; i<ncolors; i++) { - xcolor.pixel = colormap->size - 1 -private->next_color; - color->pixel = xcolor.pixel; - private->next_color += 1; + colors[i].pixel = pixels[i]; + private->info[pixels[i]].ref_count++; + private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE; + } + } + + g_free (pixels); - XStoreColor (private->xdisplay, private->xcolormap, &xcolor); - return_val = TRUE; + return status ? ncolors : 0; + } +} + +static gint +gdk_colormap_alloc_colors_private (GdkColormap *colormap, + GdkColor *colors, + gint ncolors, + gboolean writeable, + gboolean best_match, + gboolean *success) +{ + GdkColormapPrivate *private; + gint i, index; + XColor *store = g_new (XColor, ncolors); + gint nstore = 0; + gint nremaining = 0; + + private = (GdkColormapPrivate*) colormap; + index = -1; + + /* First, store the colors we have room for */ + + index = 0; + for (i=0; i<ncolors; i++) + { + if (!success[i]) + { + while ((index < colormap->size) && (private->info[index].ref_count != 0)) + index++; + + if (index < colormap->size) + { + store[nstore].red = colors[i].red; + store[nstore].blue = colors[i].blue; + store[nstore].green = colors[i].green; + store[nstore].pixel = index; + nstore++; + + success[i] = TRUE; + + colors[i].pixel = index; + private->info[index].ref_count++; } + else + nremaining++; } - else + } + + XStoreColors (private->xdisplay, private->xcolormap, store, nstore); + g_free (store); + + if (nremaining > 0 && best_match) + { + /* Get best matches for remaining colors */ + + gchar *available = g_new (gchar, colormap->size); + for (i = 0; i < colormap->size; i++) + available[i] = TRUE; + + for (i=0; i<ncolors; i++) { - while (1) + if (!success[i]) { - if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor)) + index = gdk_colormap_match_color (colormap, + &colors[i], + available); + if (index != -1) { - color->pixel = xcolor.pixel; - color->red = xcolor.red; - color->green = xcolor.green; - color->blue = xcolor.blue; - - if (color->pixel < colormap->size) - colormap->colors[color->pixel] = *color; + colors[i] = colormap->colors[index]; + private->info[index].ref_count++; - return_val = TRUE; - break; + success[i] = TRUE; + nremaining--; } - else - { - if (available == NULL) - { - available = g_new (gchar, colormap->size); - for (i = 0; i < colormap->size; i++) - available[i] = TRUE; - } + } + } + g_free (available); + } + + return (ncolors - nremaining); +} + +static gint +gdk_colormap_alloc_colors_shared (GdkColormap *colormap, + GdkColor *colors, + gint ncolors, + gboolean writeable, + gboolean best_match, + gboolean *success) +{ + GdkColormapPrivate *private; + gint i, index; + gint nremaining = 0; + gint nfailed = 0; + + private = (GdkColormapPrivate*) colormap; + index = -1; + + for (i=0; i<ncolors; i++) + { + if (!success[i]) + { + if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i])) + success[i] = TRUE; + else + nremaining++; + } + } + - index = gdk_colormap_match_color (colormap, color, available); + if (nremaining > 0 && best_match) + { + gchar *available = g_new (gchar, colormap->size); + for (i = 0; i < colormap->size; i++) + available[i] = ((private->info[i].ref_count == 0) || + !(private->info[i].flags && GDK_COLOR_WRITEABLE)); + gdk_colormap_sync (colormap, FALSE); + + while (nremaining > 0) + { + for (i=0; i<ncolors; i++) + { + if (!success[i]) + { + index = gdk_colormap_match_color (colormap, &colors[i], available); if (index != -1) { - available[index] = FALSE; - xcolor.red = colormap->colors[index].red; - xcolor.green = colormap->colors[index].green; - xcolor.blue = colormap->colors[index].blue; + if (private->info[index].ref_count) + { + private->info[index].ref_count++; + colors[i] = colormap->colors[index]; + success[i] = TRUE; + nremaining--; + } + else + { + if (gdk_colormap_alloc1 (colormap, + &colormap->colors[index], + &colors[i])) + { + success[i] = TRUE; + nremaining--; + break; + } + else + { + available[index] = FALSE; + } + } } else { - return_val = FALSE; - break; + nfailed++; + nremaining--; + success[i] = 2; /* flag as permanent failure */ } } } } + g_free (available); + } + + /* Change back the values we flagged as permanent failures */ + if (nfailed > 0) + { + for (i=0; i<ncolors; i++) + if (success[i] == 2) + success[i] = FALSE; + nremaining = nfailed; + } + + return (ncolors - nremaining); +} + +static gint +gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap, + GdkColor *colors, + gint ncolors, + gboolean writeable, + gboolean best_match, + gboolean *success) +{ + GdkColormapPrivate *private; + GdkColor *lookup_color; + gint i; + gint nremaining = 0; + + private = (GdkColormapPrivate*) colormap; + + /* Check for an exact match among previously allocated colors */ + + for (i=0; i<ncolors; i++) + { + if (!success[i]) + { + lookup_color = g_hash_table_lookup (private->hash, &colors[i]); + if (lookup_color) + { + private->info[lookup_color->pixel].ref_count++; + colors[i].pixel = lookup_color->pixel; + success[i] = TRUE; + } + else + nremaining++; + } + } + + /* If that failed, we try to allocate a new color, or approxmiate + * with what we can get if best_match is TRUE. + */ + if (nremaining > 0) + { + if (private->private_val) + return gdk_colormap_alloc_colors_private (colormap, colors, ncolors, writeable, best_match, success); + else + return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success); + } + else + return 0; +} + +gint +gdk_colormap_alloc_colors (GdkColormap *colormap, + GdkColor *colors, + gint ncolors, + gboolean writeable, + gboolean best_match, + gboolean *success) +{ + GdkColormapPrivate *private; + GdkVisual *visual; + gint i; + gint nremaining = 0; + XColor xcolor; + + g_return_val_if_fail (colormap != NULL, FALSE); + g_return_val_if_fail (colors != NULL, FALSE); + + private = (GdkColormapPrivate*) colormap; + + for (i=0; i<ncolors; i++) + { + success[i] = FALSE; + } + + switch (private->visual->type) + { + case GDK_VISUAL_PSEUDO_COLOR: + case GDK_VISUAL_GRAYSCALE: + if (writeable) + return gdk_colormap_alloc_colors_writeable (colormap, colors, ncolors, + writeable, best_match, success); + else + return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors, + writeable, best_match, success); break; case GDK_VISUAL_DIRECT_COLOR: + case GDK_VISUAL_TRUE_COLOR: visual = private->visual; - xcolor.pixel = (((xcolor.red >> (16 - visual->red_prec)) << visual->red_shift) + - ((xcolor.green >> (16 - visual->green_prec)) << visual->green_shift) + - ((xcolor.blue >> (16 - visual->blue_prec)) << visual->blue_shift)); - color->pixel = xcolor.pixel; - return_val = TRUE; + + for (i=0; i<ncolors; i++) + { + colors[i].pixel = (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) + + ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) + + ((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift)); + success[i] = TRUE; + } break; case GDK_VISUAL_STATIC_GRAY: case GDK_VISUAL_STATIC_COLOR: - case GDK_VISUAL_TRUE_COLOR: - if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor)) + for (i=0; i<ncolors; i++) { - color->pixel = xcolor.pixel; - return_val = TRUE; + xcolor.red = colors[i].red; + xcolor.green = colors[i].green; + xcolor.blue = colors[i].blue; + xcolor.pixel = colors[i].pixel; + xcolor.flags = DoRed | DoGreen | DoBlue; + + if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor)) + { + colors[i].pixel = xcolor.pixel; + success[i] = TRUE; + } + else + nremaining++; } - else - return_val = FALSE; break; } + return nremaining; +} - if (available) - g_free (available); - - return return_val; +gboolean +gdk_colormap_alloc_color (GdkColormap *colormap, + GdkColor *color, + gboolean writeable, + gboolean best_match) +{ + gboolean success; + + gdk_colormap_alloc_colors (colormap, color, 1, writeable, best_match, + &success); + + return success; +} + +/* This is almost identical to gdk_colors_free. + * Keep them in sync! + */ +void +gdk_colormap_free_colors (GdkColormap *colormap, + GdkColor *colors, + gint ncolors) +{ + GdkColormapPrivate *private; + gulong *pixels; + gint npixels = 0; + gint i; + + g_return_if_fail (colormap != NULL); + g_return_if_fail (colors != NULL); + + private = (GdkColormapPrivate*) colormap; + + if ((private->visual->type != GDK_VISUAL_PSEUDO_COLOR) && + (private->visual->type != GDK_VISUAL_GRAYSCALE)) + return; + + pixels = g_new (gulong, ncolors); + + for (i=0; i<ncolors; i++) + { + gulong pixel = colors[i].pixel; + + if (private->info[pixel].ref_count) + { + private->info[pixel].ref_count--; + + if (private->info[pixel].ref_count == 0) + { + pixels[npixels++] = pixel; + if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE)) + g_hash_table_remove (private->hash, &colors[i]); + private->info[pixel].flags = 0; + } + } + } + + if (npixels) + XFreeColors (private->xdisplay, private->xcolormap, + pixels, npixels, 0); + + g_free (pixels); +} + +gboolean +gdk_color_alloc (GdkColormap *colormap, + GdkColor *color) +{ + gboolean success; + + gdk_colormap_alloc_colors (colormap, color, 1, FALSE, TRUE, &success); + + return success; } gboolean @@ -645,9 +1085,19 @@ gdk_color_change (GdkColormap *colormap, return TRUE; } +guint +gdk_color_hash (const GdkColor *colora, + const GdkColor *colorb) +{ + return ((colora->red) + + (colora->green << 11) + + (colora->blue << 22) + + (colora->blue >> 6)); +} + gint -gdk_color_equal (GdkColor *colora, - GdkColor *colorb) +gdk_color_equal (const GdkColor *colora, + const GdkColor *colorb) { g_return_val_if_fail (colora != NULL, FALSE); g_return_val_if_fail (colorb != NULL, FALSE); @@ -657,6 +1107,9 @@ gdk_color_equal (GdkColor *colora, (colora->blue == colorb->blue)); } +/* XXX: Do not use this function until it is fixed. An X Colormap + * is useless unless we also have the visual. + */ GdkColormap* gdkx_colormap_get (Colormap xcolormap) { @@ -677,7 +1130,6 @@ gdkx_colormap_get (Colormap xcolormap) private->xcolormap = xcolormap; private->visual = NULL; private->private_val = TRUE; - private->next_color = 0; /* To do the following safely, we would have to have some way of finding * out what the size or visual of the given colormap is. It seems diff --git a/gdk/gdkpixmap.c b/gdk/gdkpixmap.c index 9fdef0ffcc..dfaf4822c9 100644 --- a/gdk/gdkpixmap.c +++ b/gdk/gdkpixmap.c @@ -34,6 +34,13 @@ typedef struct gint transparent; } _GdkPixmapColor; +typedef struct +{ + guint ncolors; + GdkColormap *colormap; + gulong pixels[1]; +} _GdkPixmapInfo; + GdkPixmap* gdk_pixmap_new (GdkWindow *window, gint width, @@ -388,13 +395,6 @@ gdk_pixmap_extract_color (gchar *buffer) return retcol; } -static void -free_color (gpointer key, gpointer value, gpointer user_data) -{ - g_free (key); - g_free (value); -} - enum buffer_op { @@ -403,6 +403,23 @@ enum buffer_op op_body }; + +static void +gdk_xpm_destroy_notify (gpointer data) +{ + _GdkPixmapInfo *info = (_GdkPixmapInfo *)data; + GdkColor color; + int i; + + for (i=0; i<info->ncolors; i++) + { + color.pixel = info->pixels[i]; + gdk_colormap_free_colors (info->colormap, &color, 1); + } + + gdk_colormap_unref (info->colormap); + g_free (info); +} static GdkPixmap * _gdk_pixmap_create_from_xpm (GdkWindow *window, @@ -420,9 +437,12 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, GdkColor tmp_color; gint width, height, num_cols, cpp, n, ns, cnt, xcnt, ycnt, wbytes; gchar *buffer, pixel_str[32]; + gchar *name_buf; _GdkPixmapColor *color = NULL, *fallbackcolor = NULL; + _GdkPixmapColor *colors = NULL; gulong index; - GHashTable *colors = NULL; + GHashTable *color_hash = NULL; + _GdkPixmapInfo *color_info = NULL; if ((window == NULL) && (colormap == NULL)) g_warning ("Creating pixmap from xpm with NULL window and colormap"); @@ -449,14 +469,30 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, return NULL; } - colors = g_hash_table_new (g_str_hash, g_str_equal); + color_hash = g_hash_table_new (g_str_hash, g_str_equal); if (transparent_color == NULL) { gdk_color_white (colormap, &tmp_color); transparent_color = &tmp_color; } - + + /* For pseudo-color and grayscale visuals, we have to remember + * the colors we allocated, so we can free them later. + */ + if ((visual->type == GDK_VISUAL_PSEUDO_COLOR) || + (visual->type == GDK_VISUAL_GRAYSCALE)) + { + color_info = g_malloc (sizeof (_GdkPixmapInfo) + + sizeof(gulong) * (num_cols - 1)); + color_info->ncolors = num_cols; + color_info->colormap = colormap; + gdk_colormap_ref (colormap); + } + + name_buf = g_new (gchar, num_cols * (cpp+1)); + colors = g_new (_GdkPixmapColor, num_cols); + for (cnt = 0; cnt < num_cols; cnt++) { gchar *color_name; @@ -465,8 +501,8 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, if (buffer == NULL) goto error; - color = g_new (_GdkPixmapColor, 1); - color->color_string = g_new (gchar, cpp + 1); + color = &colors[cnt]; + color->color_string = &name_buf [cnt * (cpp + 1)]; strncpy (color->color_string, buffer, cpp); color->color_string[cpp] = 0; buffer += strlen (color->color_string); @@ -486,7 +522,11 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, /* FIXME: The remaining slowness appears to happen in this function. */ gdk_color_alloc (colormap, &color->color); - g_hash_table_insert (colors, color->color_string, color); + + if (color_info) + color_info->pixels[cnt] = color->color.pixel; + + g_hash_table_insert (color_hash, color->color_string, color); if (cnt == 0) fallbackcolor = color; } @@ -531,7 +571,7 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, pixel_str[cpp] = 0; ns = 0; - color = g_hash_table_lookup (colors, pixel_str); + color = g_hash_table_lookup (color_hash, pixel_str); if (!color) /* screwed up XPM file */ color = fallbackcolor; @@ -558,6 +598,10 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, if (image != NULL) { pixmap = gdk_pixmap_new (window, width, height, visual->depth); + + if (color_info) + gdk_drawable_set_data (pixmap, "gdk-xpm", color_info, + gdk_xpm_destroy_notify); gc = gdk_gc_new (pixmap); gdk_gc_set_foreground (gc, transparent_color); @@ -565,13 +609,18 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, gdk_gc_destroy (gc); gdk_image_destroy (image); } + else if (color_info) + gdk_xpm_destroy_notify (color_info); + if (color_hash != NULL) + g_hash_table_destroy (color_hash); + if (colors != NULL) - { - g_hash_table_foreach (colors, free_color, 0); - g_hash_table_destroy (colors); - } - + g_free (colors); + + if (name_buf != NULL) + g_free (name_buf); + return pixmap; } @@ -720,6 +769,7 @@ gdk_pixmap_unref (GdkPixmap *pixmap) { XFreePixmap (private->xdisplay, private->xwindow); gdk_xid_table_remove (private->xwindow); + g_dataset_destroy (private); g_free (private); } } diff --git a/gdk/gdkprivate.h b/gdk/gdkprivate.h index 6e9889c3e4..9ed85a4663 100644 --- a/gdk/gdkprivate.h +++ b/gdk/gdkprivate.h @@ -41,6 +41,7 @@ typedef struct _GdkWindowPrivate GdkPixmapPrivate; typedef struct _GdkImagePrivate GdkImagePrivate; typedef struct _GdkGCPrivate GdkGCPrivate; typedef struct _GdkColormapPrivate GdkColormapPrivate; +typedef struct _GdkColorInfo GdkColorInfo; typedef struct _GdkVisualPrivate GdkVisualPrivate; typedef struct _GdkFontPrivate GdkFontPrivate; typedef struct _GdkCursorPrivate GdkCursorPrivate; @@ -111,6 +112,16 @@ struct _GdkGCPrivate guint ref_count; }; +typedef enum { + GDK_COLOR_WRITEABLE = 1 << 0 +} GdkColorInfoFlags; + +struct _GdkColorInfo +{ + GdkColorInfoFlags flags; + guint ref_count; +}; + struct _GdkColormapPrivate { GdkColormap colormap; @@ -118,7 +129,11 @@ struct _GdkColormapPrivate Display *xdisplay; GdkVisual *visual; gint private_val; - gint next_color; + + GHashTable *hash; + GdkColorInfo *info; + time_t last_sync_time; + guint ref_count; }; diff --git a/gdk/gdktypes.h b/gdk/gdktypes.h index 5ec44c2d4a..67f9fb3533 100644 --- a/gdk/gdktypes.h +++ b/gdk/gdktypes.h @@ -618,15 +618,18 @@ typedef enum typedef enum /*< flags >*/ { - GdkIMPreeditArea = 0x0001L, /*< nick=preedit-area >*/ - GdkIMPreeditCallbacks = 0x0002L, /*< nick=preedit-callbacks >*/ - GdkIMPreeditPosition = 0x0004L, /*< nick=preedit-position >*/ - GdkIMPreeditNothing = 0x0008L, /*< nick=preedit-nothing >*/ - GdkIMPreeditNone = 0x0010L, /*< nick=preedit-none >*/ - GdkIMStatusArea = 0x0100L, /*< nick=status-area >*/ - GdkIMStatusCallbacks = 0x0200L, /*< nick=status-callbacks >*/ - GdkIMStatusNothing = 0x0400L, /*< nick=status-nothing >*/ - GdkIMStatusNone = 0x0800L /*< nick=status-none >*/ + GDK_IM_PREEDIT_AREA = 0x0001, + GDK_IM_PREEDIT_CALLBACKS = 0x0002, + GDK_IM_PREEDIT_POSITION = 0x0004, + GDK_IM_PREEDIT_NOTHING = 0x0008, + GDK_IM_PREEDIT_NONE = 0x0010, + GDK_IM_PREEDIT_MASK = 0x001f, + + GDK_IM_STATUS_AREA = 0x0100, + GDK_IM_STATUS_CALLBACKS = 0x0200, + GDK_IM_STATUS_NOTHING = 0x0400, + GDK_IM_STATUS_NONE = 0x0800, + GDK_IM_STATUS_MASK = 0x0f00 } GdkIMStyle; /* The next two enumeration values current match the @@ -655,15 +658,6 @@ typedef enum GDK_FUNC_CLOSE = 1 << 5 } GdkWMFunction; -#define GdkIMPreeditMask \ - ( GdkIMPreeditArea | GdkIMPreeditCallbacks | \ - GdkIMPreeditPosition | GdkIMPreeditNothing | \ - GdkIMPreeditNone ) - -#define GdkIMStatusMask \ - ( GdkIMStatusArea | GdkIMStatusCallbacks | \ - GdkIMStatusNothing | GdkIMStatusNone ) - typedef void (*GdkInputFunction) (gpointer data, gint source, GdkInputCondition condition); diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index bd4adfaeeb..afbcdc4cc9 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -704,8 +704,10 @@ gdk_window_unref (GdkWindow *window) { if (!private->destroyed) g_warning ("losing last reference to undestroyed window\n"); + g_dataset_destroy (window); g_free (window); } + } void @@ -2076,3 +2078,11 @@ gdk_window_get_toplevels (void) return new_list; } +void +gdk_drawable_set_data (GdkDrawable *drawable, + const gchar *key, + gpointer data, + GDestroyNotify destroy_func) +{ + g_dataset_set_data_full (drawable, key, data, destroy_func); +} diff --git a/gdk/gdkx.h b/gdk/gdkx.h index 2f43fd85fe..fbe655d2ea 100644 --- a/gdk/gdkx.h +++ b/gdk/gdkx.h @@ -39,6 +39,8 @@ GdkVisual* gdkx_visual_get (VisualID xvisualid); +/* XXX: Do not use this function until it is fixed. An X Colormap + * is useless unless we also have the visual. */ GdkColormap* gdkx_colormap_get (Colormap xcolormap); /* Utility function in gdk.c - not sure where it belongs, but it's needed in more than one place, so make it public */ diff --git a/gdk/x11/gdkcolor-x11.c b/gdk/x11/gdkcolor-x11.c index b17e26a1c5..fa810473e6 100644 --- a/gdk/x11/gdkcolor-x11.c +++ b/gdk/x11/gdkcolor-x11.c @@ -16,6 +16,7 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ +#include <time.h> #include <X11/Xlib.h> #include "gdk.h" #include "gdkprivate.h" @@ -52,8 +53,12 @@ gdk_colormap_new (GdkVisual *visual, private->xdisplay = gdk_display; private->visual = visual; - private->next_color = 0; private->ref_count = 1; + + private->hash = NULL; + private->last_sync_time = 0; + private->info = NULL; + xvisual = ((GdkVisualPrivate*) visual)->xvisual; colormap->size = visual->colormap_size; @@ -63,6 +68,12 @@ gdk_colormap_new (GdkVisual *visual, { case GDK_VISUAL_GRAYSCALE: case GDK_VISUAL_PSEUDO_COLOR: + private->info = g_new0 (GdkColorInfo, colormap->size); + colormap->colors = g_new (GdkColor, colormap->size); + + private->hash = g_hash_table_new (gdk_color_hash, + gdk_color_equal); + private->private_val = private_cmap; private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window, xvisual, (private_cmap) ? (AllocAll) : (AllocNone)); @@ -134,12 +145,15 @@ gdk_colormap_real_destroy (GdkColormap *colormap) GdkColormapPrivate *private = (GdkColormapPrivate*) colormap; g_return_if_fail (colormap != NULL); - - if (private->ref_count > 0) - return; + g_return_if_fail (private->ref_count > 0); gdk_colormap_remove (colormap); XFreeColormap (private->xdisplay, private->xcolormap); + + if (private->hash) + g_hash_table_destroy (private->hash); + + g_free (private->info); g_free (colormap->colors); g_free (colormap); } @@ -165,13 +179,61 @@ gdk_colormap_unref (GdkColormap *cmap) gdk_colormap_real_destroy (cmap); } +#define MIN_SYNC_TIME 2 + +void +gdk_colormap_sync (GdkColormap *colormap, + gboolean force) +{ + time_t current_time; + GdkColormapPrivate *private = (GdkColormapPrivate *)colormap; + XColor *xpalette; + gint nlookup; + gint i; + + g_return_if_fail (colormap != NULL); + + current_time = time (NULL); + if (!force && ((current_time - private->last_sync_time) < MIN_SYNC_TIME)) + return; + + private->last_sync_time = current_time; + + nlookup = 0; + xpalette = g_new (XColor, colormap->size); + + for (i = 0; i < colormap->size; i++) + { + if (private->info[i].ref_count == 0) + { + xpalette[nlookup].pixel = i; + xpalette[nlookup].red = 0; + xpalette[nlookup].green = 0; + xpalette[nlookup].blue = 0; + nlookup++; + } + } + + XQueryColors (gdk_display, private->xcolormap, xpalette, nlookup); + + for (i = 0; i < nlookup; i++) + { + gulong pixel = xpalette[i].pixel; + colormap->colors[pixel].pixel = pixel; + colormap->colors[pixel].red = xpalette[i].red; + colormap->colors[pixel].green = xpalette[i].green; + colormap->colors[pixel].blue = xpalette[i].blue; + } + + g_free (xpalette); +} + + GdkColormap* gdk_colormap_get_system (void) { static GdkColormap *colormap = NULL; GdkColormapPrivate *private; - XColor *xpalette; - gint i; if (!colormap) { @@ -182,37 +244,25 @@ gdk_colormap_get_system (void) private->xcolormap = DefaultColormap (gdk_display, gdk_screen); private->visual = gdk_visual_get_system (); private->private_val = FALSE; - private->next_color = 0; private->ref_count = 1; + private->hash = NULL; + private->last_sync_time = 0; + private->info = NULL; + + colormap->colors = NULL; colormap->size = private->visual->colormap_size; - colormap->colors = g_new (GdkColor, colormap->size); if ((private->visual->type == GDK_VISUAL_GRAYSCALE) || (private->visual->type == GDK_VISUAL_PSEUDO_COLOR)) { - xpalette = g_new (XColor, colormap->size); + private->info = g_new0 (GdkColorInfo, colormap->size); + colormap->colors = g_new (GdkColor, colormap->size); - for (i = 0; i < colormap->size; i++) - { - xpalette[i].pixel = i; - xpalette[i].red = 0; - xpalette[i].green = 0; - xpalette[i].blue = 0; - } - - XQueryColors (gdk_display, private->xcolormap, xpalette, - colormap->size); - - for (i = 0; i < colormap->size; i++) - { - colormap->colors[i].pixel = xpalette[i].pixel; - colormap->colors[i].red = xpalette[i].red; - colormap->colors[i].green = xpalette[i].green; - colormap->colors[i].blue = xpalette[i].blue; - } + private->hash = g_hash_table_new (gdk_color_hash, + gdk_color_equal); - g_free (xpalette); + gdk_colormap_sync (colormap, TRUE); } gdk_colormap_add (colormap); @@ -258,7 +308,6 @@ gdk_colormap_change (GdkColormap *colormap, } XStoreColors (private->xdisplay, private->xcolormap, palette, ncolors); - private->next_color = MAX (private->next_color, ncolors); break; case GDK_VISUAL_DIRECT_COLOR: @@ -339,6 +388,7 @@ gdk_colors_alloc (GdkColormap *colormap, { GdkColormapPrivate *private; gint return_val; + gint i; g_return_val_if_fail (colormap != NULL, 0); @@ -347,23 +397,65 @@ gdk_colors_alloc (GdkColormap *colormap, return_val = XAllocColorCells (private->xdisplay, private->xcolormap, contiguous, planes, nplanes, pixels, npixels); + if (return_val) + { + for (i=0; i<npixels; i++) + { + private->info[pixels[i]].ref_count++; + private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE; + } + } + return return_val; } +/* This is almost identical to gdk_colormap_free_colors. + * Keep them in sync! + */ void gdk_colors_free (GdkColormap *colormap, - gulong *pixels, - gint npixels, + gulong *in_pixels, + gint in_npixels, gulong planes) { GdkColormapPrivate *private; + gulong *pixels; + gint npixels = 0; + gint i; g_return_if_fail (colormap != NULL); + g_return_if_fail (in_pixels != NULL); private = (GdkColormapPrivate*) colormap; - XFreeColors (private->xdisplay, private->xcolormap, - pixels, npixels, planes); + if ((private->visual->type != GDK_VISUAL_PSEUDO_COLOR) && + (private->visual->type != GDK_VISUAL_GRAYSCALE)) + return; + + pixels = g_new (gulong, in_npixels); + + for (i=0; i<in_npixels; i++) + { + gulong pixel = in_pixels[i]; + + if (private->info[pixel].ref_count) + { + private->info[pixel].ref_count--; + + if (private->info[pixel].ref_count == 0) + { + pixels[npixels++] = pixel; + if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE)) + g_hash_table_remove (private->hash, &colormap->colors[in_pixels[i]]); + private->info[pixel].flags = 0; + } + } + } + + if (npixels) + XFreeColors (private->xdisplay, private->xcolormap, + pixels, npixels, planes); + g_free (pixels); } /* @@ -494,19 +586,22 @@ gdk_color_parse (const gchar *spec, return return_val; } -gboolean -gdk_color_alloc (GdkColormap *colormap, - GdkColor *color) +/******************** + * Color allocation * + ********************/ + +/* Try to allocate a single color using XAllocColor. If it succeeds, + * cache the result in our colormap, and store in ret. + */ +static gboolean +gdk_colormap_alloc1 (GdkColormap *colormap, + GdkColor *color, + GdkColor *ret) { GdkColormapPrivate *private; - GdkVisual *visual; XColor xcolor; - gchar *available = NULL; - gboolean return_val; - gint i, index; - g_return_val_if_fail (colormap != NULL, FALSE); - g_return_val_if_fail (color != NULL, FALSE); + private = (GdkColormapPrivate*) colormap; xcolor.red = color->red; xcolor.green = color->green; @@ -514,113 +609,458 @@ gdk_color_alloc (GdkColormap *colormap, xcolor.pixel = color->pixel; xcolor.flags = DoRed | DoGreen | DoBlue; - return_val = FALSE; + if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor)) + { + ret->pixel = xcolor.pixel; + ret->red = xcolor.red; + ret->green = xcolor.green; + ret->blue = xcolor.blue; + + if (ret->pixel < colormap->size) + { + if (private->info[ret->pixel].ref_count) /* got a duplicate */ + { + XFreeColors (private->xdisplay, private->xcolormap, + &ret->pixel, 1, 0); + } + else + { + colormap->colors[ret->pixel] = *color; + private->info[ret->pixel].ref_count = 1; + + g_hash_table_insert (private->hash, + &colormap->colors[ret->pixel], + &colormap->colors[ret->pixel]); + } + } + return TRUE; + } + else + { + return FALSE; + } +} + +static gint +gdk_colormap_alloc_colors_writeable (GdkColormap *colormap, + GdkColor *colors, + gint ncolors, + gboolean writeable, + gboolean best_match, + gboolean *success) +{ + GdkColormapPrivate *private; + gulong *pixels; + Status status; + gint i, index; + private = (GdkColormapPrivate*) colormap; - switch (private->visual->type) + if (private->private_val) { - case GDK_VISUAL_GRAYSCALE: - case GDK_VISUAL_PSEUDO_COLOR: - if (private->private_val) + index = 0; + for (i=0; i<ncolors; i++) { - if (private->next_color >= colormap->size) + while ((index < colormap->size) && (private->info[index].ref_count != 0)) + index++; + + if (index < colormap->size) { - available = g_new (gchar, colormap->size); - for (i = 0; i < colormap->size; i++) - available[i] = TRUE; - - index = gdk_colormap_match_color (colormap, color, available); - if (index != -1) - { - available[index] = FALSE; - *color = colormap->colors[index]; - return_val = TRUE; - } - else - { - return_val = FALSE; - } + colors[i].pixel = index; + success[i] = TRUE; + private->info[index].ref_count++; + private->info[i].flags |= GDK_COLOR_WRITEABLE; } else + break; + } + return i; + } + else + { + pixels = g_new (gulong, ncolors); + /* Allocation of a writeable color cells */ + + status = XAllocColorCells (private->xdisplay, private->xcolormap, + FALSE, NULL, 0, pixels, ncolors); + if (status) + { + for (i=0; i<ncolors; i++) { - xcolor.pixel = colormap->size - 1 -private->next_color; - color->pixel = xcolor.pixel; - private->next_color += 1; + colors[i].pixel = pixels[i]; + private->info[pixels[i]].ref_count++; + private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE; + } + } + + g_free (pixels); - XStoreColor (private->xdisplay, private->xcolormap, &xcolor); - return_val = TRUE; + return status ? ncolors : 0; + } +} + +static gint +gdk_colormap_alloc_colors_private (GdkColormap *colormap, + GdkColor *colors, + gint ncolors, + gboolean writeable, + gboolean best_match, + gboolean *success) +{ + GdkColormapPrivate *private; + gint i, index; + XColor *store = g_new (XColor, ncolors); + gint nstore = 0; + gint nremaining = 0; + + private = (GdkColormapPrivate*) colormap; + index = -1; + + /* First, store the colors we have room for */ + + index = 0; + for (i=0; i<ncolors; i++) + { + if (!success[i]) + { + while ((index < colormap->size) && (private->info[index].ref_count != 0)) + index++; + + if (index < colormap->size) + { + store[nstore].red = colors[i].red; + store[nstore].blue = colors[i].blue; + store[nstore].green = colors[i].green; + store[nstore].pixel = index; + nstore++; + + success[i] = TRUE; + + colors[i].pixel = index; + private->info[index].ref_count++; } + else + nremaining++; } - else + } + + XStoreColors (private->xdisplay, private->xcolormap, store, nstore); + g_free (store); + + if (nremaining > 0 && best_match) + { + /* Get best matches for remaining colors */ + + gchar *available = g_new (gchar, colormap->size); + for (i = 0; i < colormap->size; i++) + available[i] = TRUE; + + for (i=0; i<ncolors; i++) { - while (1) + if (!success[i]) { - if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor)) + index = gdk_colormap_match_color (colormap, + &colors[i], + available); + if (index != -1) { - color->pixel = xcolor.pixel; - color->red = xcolor.red; - color->green = xcolor.green; - color->blue = xcolor.blue; - - if (color->pixel < colormap->size) - colormap->colors[color->pixel] = *color; + colors[i] = colormap->colors[index]; + private->info[index].ref_count++; - return_val = TRUE; - break; + success[i] = TRUE; + nremaining--; } - else - { - if (available == NULL) - { - available = g_new (gchar, colormap->size); - for (i = 0; i < colormap->size; i++) - available[i] = TRUE; - } + } + } + g_free (available); + } + + return (ncolors - nremaining); +} + +static gint +gdk_colormap_alloc_colors_shared (GdkColormap *colormap, + GdkColor *colors, + gint ncolors, + gboolean writeable, + gboolean best_match, + gboolean *success) +{ + GdkColormapPrivate *private; + gint i, index; + gint nremaining = 0; + gint nfailed = 0; + + private = (GdkColormapPrivate*) colormap; + index = -1; + + for (i=0; i<ncolors; i++) + { + if (!success[i]) + { + if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i])) + success[i] = TRUE; + else + nremaining++; + } + } + - index = gdk_colormap_match_color (colormap, color, available); + if (nremaining > 0 && best_match) + { + gchar *available = g_new (gchar, colormap->size); + for (i = 0; i < colormap->size; i++) + available[i] = ((private->info[i].ref_count == 0) || + !(private->info[i].flags && GDK_COLOR_WRITEABLE)); + gdk_colormap_sync (colormap, FALSE); + + while (nremaining > 0) + { + for (i=0; i<ncolors; i++) + { + if (!success[i]) + { + index = gdk_colormap_match_color (colormap, &colors[i], available); if (index != -1) { - available[index] = FALSE; - xcolor.red = colormap->colors[index].red; - xcolor.green = colormap->colors[index].green; - xcolor.blue = colormap->colors[index].blue; + if (private->info[index].ref_count) + { + private->info[index].ref_count++; + colors[i] = colormap->colors[index]; + success[i] = TRUE; + nremaining--; + } + else + { + if (gdk_colormap_alloc1 (colormap, + &colormap->colors[index], + &colors[i])) + { + success[i] = TRUE; + nremaining--; + break; + } + else + { + available[index] = FALSE; + } + } } else { - return_val = FALSE; - break; + nfailed++; + nremaining--; + success[i] = 2; /* flag as permanent failure */ } } } } + g_free (available); + } + + /* Change back the values we flagged as permanent failures */ + if (nfailed > 0) + { + for (i=0; i<ncolors; i++) + if (success[i] == 2) + success[i] = FALSE; + nremaining = nfailed; + } + + return (ncolors - nremaining); +} + +static gint +gdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap, + GdkColor *colors, + gint ncolors, + gboolean writeable, + gboolean best_match, + gboolean *success) +{ + GdkColormapPrivate *private; + GdkColor *lookup_color; + gint i; + gint nremaining = 0; + + private = (GdkColormapPrivate*) colormap; + + /* Check for an exact match among previously allocated colors */ + + for (i=0; i<ncolors; i++) + { + if (!success[i]) + { + lookup_color = g_hash_table_lookup (private->hash, &colors[i]); + if (lookup_color) + { + private->info[lookup_color->pixel].ref_count++; + colors[i].pixel = lookup_color->pixel; + success[i] = TRUE; + } + else + nremaining++; + } + } + + /* If that failed, we try to allocate a new color, or approxmiate + * with what we can get if best_match is TRUE. + */ + if (nremaining > 0) + { + if (private->private_val) + return gdk_colormap_alloc_colors_private (colormap, colors, ncolors, writeable, best_match, success); + else + return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success); + } + else + return 0; +} + +gint +gdk_colormap_alloc_colors (GdkColormap *colormap, + GdkColor *colors, + gint ncolors, + gboolean writeable, + gboolean best_match, + gboolean *success) +{ + GdkColormapPrivate *private; + GdkVisual *visual; + gint i; + gint nremaining = 0; + XColor xcolor; + + g_return_val_if_fail (colormap != NULL, FALSE); + g_return_val_if_fail (colors != NULL, FALSE); + + private = (GdkColormapPrivate*) colormap; + + for (i=0; i<ncolors; i++) + { + success[i] = FALSE; + } + + switch (private->visual->type) + { + case GDK_VISUAL_PSEUDO_COLOR: + case GDK_VISUAL_GRAYSCALE: + if (writeable) + return gdk_colormap_alloc_colors_writeable (colormap, colors, ncolors, + writeable, best_match, success); + else + return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors, + writeable, best_match, success); break; case GDK_VISUAL_DIRECT_COLOR: + case GDK_VISUAL_TRUE_COLOR: visual = private->visual; - xcolor.pixel = (((xcolor.red >> (16 - visual->red_prec)) << visual->red_shift) + - ((xcolor.green >> (16 - visual->green_prec)) << visual->green_shift) + - ((xcolor.blue >> (16 - visual->blue_prec)) << visual->blue_shift)); - color->pixel = xcolor.pixel; - return_val = TRUE; + + for (i=0; i<ncolors; i++) + { + colors[i].pixel = (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) + + ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) + + ((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift)); + success[i] = TRUE; + } break; case GDK_VISUAL_STATIC_GRAY: case GDK_VISUAL_STATIC_COLOR: - case GDK_VISUAL_TRUE_COLOR: - if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor)) + for (i=0; i<ncolors; i++) { - color->pixel = xcolor.pixel; - return_val = TRUE; + xcolor.red = colors[i].red; + xcolor.green = colors[i].green; + xcolor.blue = colors[i].blue; + xcolor.pixel = colors[i].pixel; + xcolor.flags = DoRed | DoGreen | DoBlue; + + if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor)) + { + colors[i].pixel = xcolor.pixel; + success[i] = TRUE; + } + else + nremaining++; } - else - return_val = FALSE; break; } + return nremaining; +} - if (available) - g_free (available); - - return return_val; +gboolean +gdk_colormap_alloc_color (GdkColormap *colormap, + GdkColor *color, + gboolean writeable, + gboolean best_match) +{ + gboolean success; + + gdk_colormap_alloc_colors (colormap, color, 1, writeable, best_match, + &success); + + return success; +} + +/* This is almost identical to gdk_colors_free. + * Keep them in sync! + */ +void +gdk_colormap_free_colors (GdkColormap *colormap, + GdkColor *colors, + gint ncolors) +{ + GdkColormapPrivate *private; + gulong *pixels; + gint npixels = 0; + gint i; + + g_return_if_fail (colormap != NULL); + g_return_if_fail (colors != NULL); + + private = (GdkColormapPrivate*) colormap; + + if ((private->visual->type != GDK_VISUAL_PSEUDO_COLOR) && + (private->visual->type != GDK_VISUAL_GRAYSCALE)) + return; + + pixels = g_new (gulong, ncolors); + + for (i=0; i<ncolors; i++) + { + gulong pixel = colors[i].pixel; + + if (private->info[pixel].ref_count) + { + private->info[pixel].ref_count--; + + if (private->info[pixel].ref_count == 0) + { + pixels[npixels++] = pixel; + if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE)) + g_hash_table_remove (private->hash, &colors[i]); + private->info[pixel].flags = 0; + } + } + } + + if (npixels) + XFreeColors (private->xdisplay, private->xcolormap, + pixels, npixels, 0); + + g_free (pixels); +} + +gboolean +gdk_color_alloc (GdkColormap *colormap, + GdkColor *color) +{ + gboolean success; + + gdk_colormap_alloc_colors (colormap, color, 1, FALSE, TRUE, &success); + + return success; } gboolean @@ -645,9 +1085,19 @@ gdk_color_change (GdkColormap *colormap, return TRUE; } +guint +gdk_color_hash (const GdkColor *colora, + const GdkColor *colorb) +{ + return ((colora->red) + + (colora->green << 11) + + (colora->blue << 22) + + (colora->blue >> 6)); +} + gint -gdk_color_equal (GdkColor *colora, - GdkColor *colorb) +gdk_color_equal (const GdkColor *colora, + const GdkColor *colorb) { g_return_val_if_fail (colora != NULL, FALSE); g_return_val_if_fail (colorb != NULL, FALSE); @@ -657,6 +1107,9 @@ gdk_color_equal (GdkColor *colora, (colora->blue == colorb->blue)); } +/* XXX: Do not use this function until it is fixed. An X Colormap + * is useless unless we also have the visual. + */ GdkColormap* gdkx_colormap_get (Colormap xcolormap) { @@ -677,7 +1130,6 @@ gdkx_colormap_get (Colormap xcolormap) private->xcolormap = xcolormap; private->visual = NULL; private->private_val = TRUE; - private->next_color = 0; /* To do the following safely, we would have to have some way of finding * out what the size or visual of the given colormap is. It seems diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c index 5573d10019..1932d7d3bc 100644 --- a/gdk/x11/gdkmain-x11.c +++ b/gdk/x11/gdkmain-x11.c @@ -446,15 +446,15 @@ gdk_init (int *argc, { (*argv)[i++] = NULL; if (strcmp ("none", (*argv)[i]) == 0) - gdk_im_set_best_style (GdkIMPreeditNone); + gdk_im_set_best_style (GDK_IM_PREEDIT_NONE); else if (strcmp ("nothing", (*argv)[i]) == 0) - gdk_im_set_best_style (GdkIMPreeditNothing); + gdk_im_set_best_style (GDK_IM_PREEDIT_NOTHING); else if (strcmp ("area", (*argv)[i]) == 0) - gdk_im_set_best_style (GdkIMPreeditArea); + gdk_im_set_best_style (GDK_IM_PREEDIT_AREA); else if (strcmp ("position", (*argv)[i]) == 0) - gdk_im_set_best_style (GdkIMPreeditPosition); + gdk_im_set_best_style (GDK_IM_PREEDIT_POSITION); else if (strcmp ("callbacks", (*argv)[i]) == 0) - gdk_im_set_best_style (GdkIMPreeditCallbacks); + gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS); } } else if (strcmp ("--xim-status", (*argv)[i]) == 0) @@ -463,13 +463,13 @@ gdk_init (int *argc, { (*argv)[i++] = NULL; if (strcmp ("none", (*argv)[i]) == 0) - gdk_im_set_best_style (GdkIMStatusNone); + gdk_im_set_best_style (GDK_IM_STATUS_NONE); else if (strcmp ("nothing", (*argv)[i]) == 0) - gdk_im_set_best_style (GdkIMStatusNothing); + gdk_im_set_best_style (GDK_IM_STATUS_NOTHING); else if (strcmp ("area", (*argv)[i]) == 0) - gdk_im_set_best_style (GdkIMStatusArea); + gdk_im_set_best_style (GDK_IM_STATUS_AREA); else if (strcmp ("callbacks", (*argv)[i]) == 0) - gdk_im_set_best_style (GdkIMStatusCallbacks); + gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS); } } #endif @@ -584,10 +584,10 @@ gdk_init (int *argc, xim_using = FALSE; xim_im = NULL; xim_styles = NULL; - if (!(xim_best_allowed_style & GdkIMPreeditMask)) - gdk_im_set_best_style (GdkIMPreeditCallbacks); - if (!(xim_best_allowed_style & GdkIMStatusMask)) - gdk_im_set_best_style (GdkIMStatusCallbacks); + 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; @@ -3570,34 +3570,34 @@ gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2) if (style1 == 0) return style2; if (style2 == 0) return style1; - if ((style1 & (GdkIMPreeditMask | GdkIMStatusMask)) - == (style2 & (GdkIMPreeditMask | GdkIMStatusMask))) + if ((style1 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK)) + == (style2 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK))) return style1; - - s1 = style1 & GdkIMPreeditMask; - s2 = style2 & GdkIMPreeditMask; + + s1 = style1 & GDK_IM_PREEDIT_MASK; + s2 = style2 & GDK_IM_PREEDIT_MASK; u = s1 | s2; if (s1 != s2) { - if (u & GdkIMPreeditCallbacks) - return (s1 == GdkIMPreeditCallbacks)? style1:style2; - else if (u & GdkIMPreeditPosition) - return (s1 == GdkIMPreeditPosition)? style1:style2; - else if (u & GdkIMPreeditArea) - return (s1 == GdkIMPreeditArea)? style1:style2; - else if (u & GdkIMPreeditNothing) - return (s1 == GdkIMPreeditNothing)? style1:style2; + 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 & GdkIMStatusMask; - s2 = style2 & GdkIMStatusMask; + s1 = style1 & GDK_IM_STATUS_MASK; + s2 = style2 & GDK_IM_STATUS_MASK; u = s1 | s2; - if ( u & GdkIMStatusCallbacks) - return (s1 == GdkIMStatusCallbacks)? style1:style2; - else if ( u & GdkIMStatusArea) - return (s1 == GdkIMStatusArea)? style1:style2; - else if ( u & GdkIMStatusNothing) - return (s1 == GdkIMStatusNothing)? style1:style2; - else if ( u & GdkIMStatusNone) - return (s1 == GdkIMStatusNone)? style1:style2; + 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 */ } @@ -3623,39 +3623,39 @@ gdk_im_decide_style (GdkIMStyle supported_style) GdkIMStyle gdk_im_set_best_style (GdkIMStyle style) { - if (style & GdkIMPreeditMask) + if (style & GDK_IM_PREEDIT_MASK) { - xim_best_allowed_style &= ~GdkIMPreeditMask; - - xim_best_allowed_style |= GdkIMPreeditNone; - if (!(style & GdkIMPreeditNone)) + 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 |= GdkIMPreeditNothing; - if (!(style & GdkIMPreeditNothing)) + xim_best_allowed_style |= GDK_IM_PREEDIT_NOTHING; + if (!(style & GDK_IM_PREEDIT_NOTHING)) { - xim_best_allowed_style |= GdkIMPreeditArea; - if (!(style & GdkIMPreeditArea)) + xim_best_allowed_style |= GDK_IM_PREEDIT_AREA; + if (!(style & GDK_IM_PREEDIT_AREA)) { - xim_best_allowed_style |= GdkIMPreeditPosition; - if (!(style & GdkIMPreeditPosition)) - xim_best_allowed_style |= GdkIMPreeditCallbacks; + xim_best_allowed_style |= GDK_IM_PREEDIT_POSITION; + if (!(style & GDK_IM_PREEDIT_POSITION)) + xim_best_allowed_style |= GDK_IM_PREEDIT_CALLBACKS; } } } } - if (style & GdkIMStatusMask) + if (style & GDK_IM_STATUS_MASK) { - xim_best_allowed_style &= ~GdkIMStatusMask; - - xim_best_allowed_style |= GdkIMStatusNone; - if (!(style & GdkIMStatusNone)) + 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 |= GdkIMStatusNothing; - if (!(style & GdkIMStatusNothing)) + xim_best_allowed_style |= GDK_IM_STATUS_NOTHING; + if (!(style & GDK_IM_STATUS_NOTHING)) { - xim_best_allowed_style |= GdkIMStatusArea; - if (!(style & GdkIMStatusArea)) - xim_best_allowed_style |= GdkIMStatusCallbacks; + xim_best_allowed_style |= GDK_IM_STATUS_AREA; + if (!(style & GDK_IM_STATUS_AREA)) + xim_best_allowed_style |= GDK_IM_STATUS_CALLBACKS; } } } @@ -3960,13 +3960,13 @@ gdk_im_end (void) GdkIMStyle gdk_im_decide_style (GdkIMStyle supported_style) { - return GdkIMPreeditNone | GdkIMStatusNone; + return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE; } GdkIMStyle gdk_im_set_best_style (GdkIMStyle style) { - return GdkIMPreeditNone | GdkIMStatusNone; + return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE; } gint @@ -3991,7 +3991,7 @@ gdk_ic_destroy (GdkIC ic) GdkIMStyle gdk_ic_get_style (GdkIC ic) { - return GdkIMPreeditNone | GdkIMStatusNone; + return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE; } void diff --git a/gdk/x11/gdkpixmap-x11.c b/gdk/x11/gdkpixmap-x11.c index 9fdef0ffcc..dfaf4822c9 100644 --- a/gdk/x11/gdkpixmap-x11.c +++ b/gdk/x11/gdkpixmap-x11.c @@ -34,6 +34,13 @@ typedef struct gint transparent; } _GdkPixmapColor; +typedef struct +{ + guint ncolors; + GdkColormap *colormap; + gulong pixels[1]; +} _GdkPixmapInfo; + GdkPixmap* gdk_pixmap_new (GdkWindow *window, gint width, @@ -388,13 +395,6 @@ gdk_pixmap_extract_color (gchar *buffer) return retcol; } -static void -free_color (gpointer key, gpointer value, gpointer user_data) -{ - g_free (key); - g_free (value); -} - enum buffer_op { @@ -403,6 +403,23 @@ enum buffer_op op_body }; + +static void +gdk_xpm_destroy_notify (gpointer data) +{ + _GdkPixmapInfo *info = (_GdkPixmapInfo *)data; + GdkColor color; + int i; + + for (i=0; i<info->ncolors; i++) + { + color.pixel = info->pixels[i]; + gdk_colormap_free_colors (info->colormap, &color, 1); + } + + gdk_colormap_unref (info->colormap); + g_free (info); +} static GdkPixmap * _gdk_pixmap_create_from_xpm (GdkWindow *window, @@ -420,9 +437,12 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, GdkColor tmp_color; gint width, height, num_cols, cpp, n, ns, cnt, xcnt, ycnt, wbytes; gchar *buffer, pixel_str[32]; + gchar *name_buf; _GdkPixmapColor *color = NULL, *fallbackcolor = NULL; + _GdkPixmapColor *colors = NULL; gulong index; - GHashTable *colors = NULL; + GHashTable *color_hash = NULL; + _GdkPixmapInfo *color_info = NULL; if ((window == NULL) && (colormap == NULL)) g_warning ("Creating pixmap from xpm with NULL window and colormap"); @@ -449,14 +469,30 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, return NULL; } - colors = g_hash_table_new (g_str_hash, g_str_equal); + color_hash = g_hash_table_new (g_str_hash, g_str_equal); if (transparent_color == NULL) { gdk_color_white (colormap, &tmp_color); transparent_color = &tmp_color; } - + + /* For pseudo-color and grayscale visuals, we have to remember + * the colors we allocated, so we can free them later. + */ + if ((visual->type == GDK_VISUAL_PSEUDO_COLOR) || + (visual->type == GDK_VISUAL_GRAYSCALE)) + { + color_info = g_malloc (sizeof (_GdkPixmapInfo) + + sizeof(gulong) * (num_cols - 1)); + color_info->ncolors = num_cols; + color_info->colormap = colormap; + gdk_colormap_ref (colormap); + } + + name_buf = g_new (gchar, num_cols * (cpp+1)); + colors = g_new (_GdkPixmapColor, num_cols); + for (cnt = 0; cnt < num_cols; cnt++) { gchar *color_name; @@ -465,8 +501,8 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, if (buffer == NULL) goto error; - color = g_new (_GdkPixmapColor, 1); - color->color_string = g_new (gchar, cpp + 1); + color = &colors[cnt]; + color->color_string = &name_buf [cnt * (cpp + 1)]; strncpy (color->color_string, buffer, cpp); color->color_string[cpp] = 0; buffer += strlen (color->color_string); @@ -486,7 +522,11 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, /* FIXME: The remaining slowness appears to happen in this function. */ gdk_color_alloc (colormap, &color->color); - g_hash_table_insert (colors, color->color_string, color); + + if (color_info) + color_info->pixels[cnt] = color->color.pixel; + + g_hash_table_insert (color_hash, color->color_string, color); if (cnt == 0) fallbackcolor = color; } @@ -531,7 +571,7 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, pixel_str[cpp] = 0; ns = 0; - color = g_hash_table_lookup (colors, pixel_str); + color = g_hash_table_lookup (color_hash, pixel_str); if (!color) /* screwed up XPM file */ color = fallbackcolor; @@ -558,6 +598,10 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, if (image != NULL) { pixmap = gdk_pixmap_new (window, width, height, visual->depth); + + if (color_info) + gdk_drawable_set_data (pixmap, "gdk-xpm", color_info, + gdk_xpm_destroy_notify); gc = gdk_gc_new (pixmap); gdk_gc_set_foreground (gc, transparent_color); @@ -565,13 +609,18 @@ _gdk_pixmap_create_from_xpm (GdkWindow *window, gdk_gc_destroy (gc); gdk_image_destroy (image); } + else if (color_info) + gdk_xpm_destroy_notify (color_info); + if (color_hash != NULL) + g_hash_table_destroy (color_hash); + if (colors != NULL) - { - g_hash_table_foreach (colors, free_color, 0); - g_hash_table_destroy (colors); - } - + g_free (colors); + + if (name_buf != NULL) + g_free (name_buf); + return pixmap; } @@ -720,6 +769,7 @@ gdk_pixmap_unref (GdkPixmap *pixmap) { XFreePixmap (private->xdisplay, private->xwindow); gdk_xid_table_remove (private->xwindow); + g_dataset_destroy (private); g_free (private); } } diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index bd4adfaeeb..afbcdc4cc9 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -704,8 +704,10 @@ gdk_window_unref (GdkWindow *window) { if (!private->destroyed) g_warning ("losing last reference to undestroyed window\n"); + g_dataset_destroy (window); g_free (window); } + } void @@ -2076,3 +2078,11 @@ gdk_window_get_toplevels (void) return new_list; } +void +gdk_drawable_set_data (GdkDrawable *drawable, + const gchar *key, + gpointer data, + GDestroyNotify destroy_func) +{ + g_dataset_set_data_full (drawable, key, data, destroy_func); +} diff --git a/gdk/x11/gdkx.h b/gdk/x11/gdkx.h index 2f43fd85fe..fbe655d2ea 100644 --- a/gdk/x11/gdkx.h +++ b/gdk/x11/gdkx.h @@ -39,6 +39,8 @@ GdkVisual* gdkx_visual_get (VisualID xvisualid); +/* XXX: Do not use this function until it is fixed. An X Colormap + * is useless unless we also have the visual. */ GdkColormap* gdkx_colormap_get (Colormap xcolormap); /* Utility function in gdk.c - not sure where it belongs, but it's needed in more than one place, so make it public */ diff --git a/gtk/gtk.defs b/gtk/gtk.defs index 024fcf5d0f..3183345398 100644 --- a/gtk/gtk.defs +++ b/gtk/gtk.defs @@ -416,6 +416,9 @@ ; enumerations from "../gdk/gdkprivate.h" +(define-flags GdkColorInfoFlags + (writeable GDK_COLOR_WRITEABLE)) + (define-flags GdkDebugFlag (misc GDK_DEBUG_MISC) (events GDK_DEBUG_EVENTS) @@ -809,15 +812,17 @@ (cursor GDK_EXTENSION_EVENTS_CURSOR)) (define-flags GdkIMStyle - (preedit-area GdkIMPreeditArea) - (preedit-callbacks GdkIMPreeditCallbacks) - (preedit-position GdkIMPreeditPosition) - (preedit-nothing GdkIMPreeditNothing) - (preedit-none GdkIMPreeditNone) - (status-area GdkIMStatusArea) - (status-callbacks GdkIMStatusCallbacks) - (status-nothing GdkIMStatusNothing) - (status-none GdkIMStatusNone)) + (preedit-area GDK_IM_PREEDIT_AREA) + (preedit-callbacks GDK_IM_PREEDIT_CALLBACKS) + (preedit-position GDK_IM_PREEDIT_POSITION) + (preedit-nothing GDK_IM_PREEDIT_NOTHING) + (preedit-none GDK_IM_PREEDIT_NONE) + (preedit-mask GDK_IM_PREEDIT_MASK) + (status-area GDK_IM_STATUS_AREA) + (status-callbacks GDK_IM_STATUS_CALLBACKS) + (status-nothing GDK_IM_STATUS_NOTHING) + (status-none GDK_IM_STATUS_NONE) + (status-mask GDK_IM_STATUS_MASK)) (define-flags GdkWMDecoration (all GDK_DECOR_ALL) diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c index 613d64239c..5aaaf25a0b 100644 --- a/gtk/gtkentry.c +++ b/gtk/gtkentry.c @@ -587,17 +587,17 @@ gtk_entry_realize (GtkWidget *widget) gint width, height; GdkEventMask mask; GdkIMStyle style; - GdkIMStyle supported_style = GdkIMPreeditNone | GdkIMPreeditNothing | - GdkIMPreeditPosition | - GdkIMStatusNone | GdkIMStatusNothing; + 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 &= ~GdkIMPreeditPosition; + supported_style &= ~GDK_IM_PREEDIT_POSITION; style = gdk_im_decide_style (supported_style); - switch (style & GdkIMPreeditMask) + switch (style & GDK_IM_PREEDIT_MASK) { - case GdkIMPreeditPosition: + case GDK_IM_PREEDIT_POSITION: if (widget->style && widget->style->font->type != GDK_FONT_FONTSET) { g_warning ("over-the-spot style requires fontset"); @@ -768,7 +768,7 @@ gtk_entry_size_allocate (GtkWidget *widget, gtk_entry_adjust_scroll (entry); #ifdef USE_XIM - if (editable->ic && (gdk_ic_get_style (editable->ic) & GdkIMPreeditPosition)) + if (editable->ic && (gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION)) { gint width, height; GdkRectangle rect; @@ -1442,7 +1442,7 @@ gtk_entry_draw_cursor_on_drawable (GtkEntry *entry, GdkDrawable *drawable) gdk_draw_line (drawable, gc, xoffset, 0, xoffset, text_area_height); #ifdef USE_XIM if (gdk_im_ready() && editable->ic && - gdk_ic_get_style (editable->ic) & GdkIMPreeditPosition) + gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION) { GdkPoint spot; diff --git a/gtk/gtkmenu.h b/gtk/gtkmenu.h index 8600627dd0..856eb27887 100644 --- a/gtk/gtkmenu.h +++ b/gtk/gtkmenu.h @@ -73,6 +73,8 @@ struct _GtkMenuClass GtkType gtk_menu_get_type (void); GtkWidget* gtk_menu_new (void); + +/* Wrappers for the Menu Shell operations */ void gtk_menu_append (GtkMenu *menu, GtkWidget *child); void gtk_menu_prepend (GtkMenu *menu, @@ -80,6 +82,8 @@ void gtk_menu_prepend (GtkMenu *menu, void gtk_menu_insert (GtkMenu *menu, GtkWidget *child, gint position); + +/* Display the menu onscreen */ void gtk_menu_popup (GtkMenu *menu, GtkWidget *parent_menu_shell, GtkWidget *parent_menu_item, @@ -87,17 +91,39 @@ void gtk_menu_popup (GtkMenu *menu, gpointer data, guint button, guint32 activate_time); + +/* Position the menu according to it's position function. Called + * from gtkmenuitem.c when a menu-item changes its allocation + */ void gtk_menu_reposition (GtkMenu *menu); + void gtk_menu_popdown (GtkMenu *menu); + +/* Keep track of the last menu item selected. (For the purposes + * of the option menu + */ GtkWidget* gtk_menu_get_active (GtkMenu *menu); void gtk_menu_set_active (GtkMenu *menu, guint index); + void gtk_menu_set_accel_group (GtkMenu *menu, GtkAccelGroup *accel_group); + +/* A reference count is kept for a widget when it is attached to + * a particular widget. This is typically a menu item; it may also + * be a widget with a popup menu - for instance, the Notebook widget. + */ void gtk_menu_attach_to_widget (GtkMenu *menu, GtkWidget *attach_widget, GtkMenuDetachFunc detacher); +void gtk_menu_detach (GtkMenu *menu); + +/* This should be dumped in favor of data set when the menu is popped + * up - that is currently in the ItemFactory code, but should be + * in the Menu code. + */ GtkWidget* gtk_menu_get_attach_widget (GtkMenu *menu); + void gtk_menu_detach (GtkMenu *menu); void gtk_menu_set_tearoff_state (GtkMenu *menu, gboolean torn_off); diff --git a/gtk/gtktext.c b/gtk/gtktext.c index 2cfed81c59..ba0c1e697d 100644 --- a/gtk/gtktext.c +++ b/gtk/gtktext.c @@ -59,11 +59,25 @@ #define MARK_NEXT_LIST_PTR(mark) ((mark)->property->next) #define MARK_OFFSET(mark) ((mark)->offset) #define MARK_PROPERTY_LENGTH(mark) (MARK_CURRENT_PROPERTY(mark)->length) -#define MARK_CURRENT_FONT(mark) (((TextProperty*)(mark)->property->data)->font->gdk_font) -#define MARK_CURRENT_FORE(mark) (&((TextProperty*)(mark)->property->data)->fore_color) -#define MARK_CURRENT_BACK(mark) (&((TextProperty*)(mark)->property->data)->back_color) -#define MARK_CURRENT_TEXT_FONT(m) (((TextProperty*)(m)->property->data)->font) + +#define MARK_CURRENT_FONT(text, mark) \ + ((MARK_CURRENT_PROPERTY(mark)->flags & PROPERTY_FONT) ? \ + MARK_CURRENT_PROPERTY(mark)->font->gdk_font : \ + GTK_WIDGET (text)->style->font) +#define MARK_CURRENT_FORE(text, mark) \ + ((MARK_CURRENT_PROPERTY(mark)->flags & PROPERTY_FOREGROUND) ? \ + &MARK_CURRENT_PROPERTY(mark)->fore_color : \ + &((GtkWidget *)text)->style->text[((GtkWidget *)text)->state]) +#define MARK_CURRENT_BACK(text, mark) \ + ((MARK_CURRENT_PROPERTY(mark)->flags & PROPERTY_BACKGROUND) ? \ + &MARK_CURRENT_PROPERTY(mark)->back_color : \ + &((GtkWidget *)text)->style->base[((GtkWidget *)text)->state]) +#define MARK_CURRENT_TEXT_FONT(text, mark) \ + ((MARK_CURRENT_PROPERTY(mark)->flags & PROPERTY_FONT) ? \ + MARK_CURRENT_PROPERTY(mark)->font : \ + text->current_font) + #define TEXT_LENGTH(t) ((t)->text_end - (t)->gap_size) #define FONT_HEIGHT(f) ((f)->ascent + (f)->descent) #define LINE_HEIGHT(l) ((l).font_ascent + (l).font_descent) @@ -73,7 +87,6 @@ #define LAST_INDEX(t, m) ((m).index == TEXT_LENGTH(t)) #define CACHE_DATA(c) (*(LineParams*)(c)->data) -typedef struct _TextFont TextFont; typedef struct _TextProperty TextProperty; typedef struct _TabStopMark TabStopMark; typedef struct _PrevTabCont PrevTabCont; @@ -96,25 +109,35 @@ struct _SetVerticalScrollData { GtkPropertyMark mark; }; -struct _TextFont +struct _GtkTextFont { /* The actual font. */ GdkFont *gdk_font; - + guint ref_count; + gint16 char_widths[256]; }; +typedef enum { + PROPERTY_FONT = 1 << 0, + PROPERTY_FOREGROUND = 1 << 1, + PROPERTY_BACKGROUND = 1 << 2 +} TextPropertyFlags; + struct _TextProperty { /* Font. */ - TextFont* font; - + GtkTextFont* font; + /* Background Color. */ GdkColor back_color; /* Foreground Color. */ GdkColor fore_color; - + + /* Show which properties are set */ + TextPropertyFlags flags; + /* Length of this property. */ guint length; }; @@ -213,10 +236,24 @@ static gint gtk_text_focus_out (GtkWidget *widget, static void move_gap_to_point (GtkText* text); static void make_forward_space (GtkText* text, guint len); + +/* Property management */ +static GtkTextFont* get_text_font (GdkFont* gfont); +static void text_font_unref (GtkTextFont *text_font); + static void insert_text_property (GtkText* text, GdkFont* font, GdkColor *fore, GdkColor* back, guint len); +static TextProperty* new_text_property (GtkText *text, GdkFont* font, + GdkColor* fore, GdkColor* back, guint length); +static void destroy_text_property (TextProperty *prop); +static void init_properties (GtkText *text); +static void realize_property (GtkText *text, TextProperty *prop); +static void realize_properties (GtkText *text); +static void unrealize_property (GtkText *text, TextProperty *prop); +static void unrealize_properties (GtkText *text); + static void delete_text_property (GtkText* text, guint len); -static void init_properties (GtkText *text); + static guint pixel_height_of (GtkText* text, GList* cache_line); /* Property Movement and Size Computations */ @@ -229,7 +266,6 @@ static GtkPropertyMark find_mark (GtkText* text, guint mark_position); static GtkPropertyMark find_mark_near (GtkText* text, guint mark_position, const GtkPropertyMark* near); static void find_line_containing_point (GtkText* text, guint point, gboolean scroll); -static TextProperty* new_text_property (GdkFont* font, GdkColor* fore, GdkColor* back, guint length); /* Display */ static void compute_lines_pixels (GtkText* text, guint char_count, @@ -551,6 +587,10 @@ gtk_text_init (GtkText *text) text->timer = 0; text->button = 0; + text->current_font = NULL; + + init_properties (text); + GTK_EDITABLE(text)->editable = FALSE; } @@ -745,10 +785,7 @@ gtk_text_insert (GtkText *text, g_return_if_fail (text != NULL); g_return_if_fail (GTK_IS_TEXT (text)); - - /* This must be because we need to have the style set up. */ - g_assert (GTK_WIDGET_REALIZED(text)); - + if (nchars < 0) length = strlen (chars); else @@ -763,11 +800,6 @@ gtk_text_insert (GtkText *text, frozen = TRUE; } - if (fore == NULL) - fore = >K_WIDGET (text)->style->text[GTK_STATE_NORMAL]; - if (back == NULL) - back = >K_WIDGET (text)->style->base[GTK_STATE_NORMAL]; - if (!text->freeze && (text->line_start_cache != NULL)) { find_line_containing_point (text, text->point.index, TRUE); @@ -789,12 +821,8 @@ gtk_text_insert (GtkText *text, text->cursor_mark.index += length; move_gap_to_point (text); - - if (font == NULL) - font = GTK_WIDGET (text)->style->font; - + make_forward_space (text, length); - memcpy (text->text + text->gap_position, chars, length); insert_text_property (text, font, fore, back, length); @@ -1010,9 +1038,11 @@ gtk_text_finalize (GtkObject *object) tmp_list = text->text_properties; while (tmp_list) { - g_mem_chunk_free (text_property_chunk, tmp_list->data); + destroy_text_property (tmp_list->data); tmp_list = tmp_list->next; } + + text_font_unref (text->current_font); g_list_free (text->text_properties); @@ -1096,17 +1126,19 @@ gtk_text_realize (GtkWidget *widget) gint width, height; GdkEventMask mask; GdkIMStyle style; - GdkIMStyle supported_style = GdkIMPreeditNone | GdkIMPreeditNothing | - GdkIMPreeditPosition | - GdkIMStatusNone | GdkIMStatusNothing; + 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 &= ~GdkIMPreeditPosition; + supported_style &= ~GDK_IM_PREEDIT_POSITION; style = gdk_im_decide_style (supported_style); - switch (style & GdkIMPreeditMask) + switch (style & GDK_IM_PREEDIT_MASK) { - case GdkIMPreeditPosition: + case GDK_IM_PREEDIT_POSITION: if (widget->style && widget->style->font->type != GDK_FONT_FONTSET) { g_warning ("over-the-spot style requires fontset"); @@ -1152,11 +1184,11 @@ gtk_text_realize (GtkWidget *widget) } } #endif - - init_properties (text); + realize_properties (text); gdk_window_show (text->text_area); - + init_properties (text); + if (editable->selection_start_pos != editable->selection_end_pos) gtk_editable_claim_selection (editable, TRUE, GDK_CURRENT_TIME); @@ -1182,7 +1214,11 @@ gtk_text_style_set (GtkWidget *widget, if ((widget->allocation.width > 1) || (widget->allocation.height > 1)) recompute_geometry (text); } - + + if (text->current_font) + text_font_unref (text->current_font); + text->current_font = get_text_font (widget->style->font); + if (GTK_WIDGET_DRAWABLE (widget)) gdk_window_clear (widget->window); } @@ -1206,7 +1242,9 @@ gtk_text_unrealize (GtkWidget *widget) gdk_pixmap_unref (text->line_wrap_bitmap); gdk_pixmap_unref (text->line_arrow_bitmap); - + + unrealize_properties (text); + if (GTK_WIDGET_CLASS (parent_class)->unrealize) (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); } @@ -1399,7 +1437,7 @@ gtk_text_size_allocate (GtkWidget *widget, TEXT_BORDER_ROOM) * 2); #ifdef USE_XIM - if (editable->ic && (gdk_ic_get_style (editable->ic) & GdkIMPreeditPosition)) + if (editable->ic && (gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION)) { gint width, height; GdkRectangle rect; @@ -1703,14 +1741,20 @@ gtk_text_insert_text (GtkEditable *editable, gint *position) { GtkText *text = GTK_TEXT (editable); - + GdkFont *font; + GdkColor *fore, *back; + + TextProperty *property; + gtk_text_set_point (text, *position); - gtk_text_insert (text, - MARK_CURRENT_FONT (&text->point), - MARK_CURRENT_FORE (&text->point), - MARK_CURRENT_BACK (&text->point), - new_text, new_text_length); + + property = MARK_CURRENT_PROPERTY (&text->point); + font = property->flags & PROPERTY_FONT ? property->font->gdk_font : NULL; + fore = property->flags & PROPERTY_FOREGROUND ? &property->fore_color : NULL; + back = property->flags & PROPERTY_BACKGROUND ? &property->back_color : NULL; + gtk_text_insert (text, font, fore, back, new_text, new_text_length); + *position = text->point.index; } @@ -2649,31 +2693,38 @@ insert_expose (GtkText* text, guint old_pixels, gint nchars, TEXT_SHOW(text); } +/* Text property functions */ + static guint font_hash (gconstpointer font) { return gdk_font_id ((const GdkFont*) font); } -static TextFont* +static GHashTable *font_cache_table = NULL; + +static GtkTextFont* get_text_font (GdkFont* gfont) { - static GHashTable *font_cache_table = NULL; - TextFont* tf; - gpointer lu; + GtkTextFont* tf; gint i; if (!font_cache_table) font_cache_table = g_hash_table_new (font_hash, (GCompareFunc) gdk_font_equal); - lu = g_hash_table_lookup (font_cache_table, gfont); - - if (lu) - return (TextFont*)lu; - - tf = g_new (TextFont, 1); + tf = g_hash_table_lookup (font_cache_table, gfont); + if (tf) + { + tf->ref_count++; + return tf; + } + + tf = g_new (GtkTextFont, 1); + tf->ref_count = 1; + tf->gdk_font = gfont; + gdk_font_ref (gfont); for(i = 0; i < 256; i += 1) tf->char_widths[i] = gdk_char_width (gfont, (char)i); @@ -2683,16 +2734,115 @@ get_text_font (GdkFont* gfont) return tf; } +static void +text_font_unref (GtkTextFont *text_font) +{ + text_font->ref_count--; + if (text_font->ref_count == 0) + { + g_hash_table_remove (font_cache_table, text_font->gdk_font); + gdk_font_unref (text_font->gdk_font); + g_free (text_font); + } +} + static gint text_properties_equal (TextProperty* prop, GdkFont* font, GdkColor *fore, GdkColor *back) { - return prop->font == get_text_font(font) && - gdk_color_equal(&prop->fore_color, fore) && - gdk_color_equal(&prop->back_color, back); + if (prop->flags & PROPERTY_FONT) + { + gboolean retval; + GtkTextFont *text_font; + + if (!font) + return FALSE; + + text_font = get_text_font (font); + + retval = (prop->font == text_font); + text_font_unref (text_font); + + if (!retval) + return FALSE; + } + else + if (font != NULL) + return FALSE; + + if (prop->flags & PROPERTY_FOREGROUND) + { + if (!fore || !gdk_color_equal (&prop->fore_color, fore)) + return FALSE; + } + else + if (fore != NULL) + return FALSE; + + if (prop->flags & PROPERTY_BACKGROUND) + { + if (!back || !gdk_color_equal (&prop->fore_color, fore)) + return FALSE; + } + else + if (fore != NULL) + return FALSE; + + return TRUE; +} + +static void +realize_property (GtkText *text, TextProperty *prop) +{ + GdkColormap *colormap = gtk_widget_get_colormap (GTK_WIDGET (text)); + + if (prop->flags & PROPERTY_FOREGROUND) + gdk_colormap_alloc_color (colormap, &prop->fore_color, FALSE, FALSE); + + if (prop->flags & PROPERTY_BACKGROUND) + gdk_colormap_alloc_color (colormap, &prop->back_color, FALSE, FALSE); +} + +static void +realize_properties (GtkText *text) +{ + GList *tmp_list = text->text_properties; + + while (tmp_list) + { + realize_property (text, tmp_list->data); + + tmp_list = tmp_list->next; + } +} + +static void +unrealize_property (GtkText *text, TextProperty *prop) +{ + GdkColormap *colormap = gtk_widget_get_colormap (GTK_WIDGET (text)); + + if (prop->flags & PROPERTY_FOREGROUND) + gdk_colormap_free_colors (colormap, &prop->fore_color, 1); + + if (prop->flags & PROPERTY_BACKGROUND) + gdk_colormap_free_colors (colormap, &prop->back_color, 1); +} + +static void +unrealize_properties (GtkText *text) +{ + GList *tmp_list = text->text_properties; + + while (tmp_list) + { + unrealize_property (text, tmp_list->data); + + tmp_list = tmp_list->next; + } } static TextProperty* -new_text_property (GdkFont* font, GdkColor* fore, GdkColor* back, guint length) +new_text_property (GtkText *text, GdkFont *font, GdkColor* fore, + GdkColor* back, guint length) { TextProperty *prop; @@ -2705,16 +2855,45 @@ new_text_property (GdkFont* font, GdkColor* fore, GdkColor* back, guint length) } prop = g_chunk_new(TextProperty, text_property_chunk); + + prop->flags = 0; + if (font) + { + prop->flags |= PROPERTY_FONT; + prop->font = get_text_font (font); + } + else + prop->font = NULL; - prop->font = get_text_font (font); - prop->fore_color = *fore; + if (fore) + { + prop->flags |= PROPERTY_FOREGROUND; + prop->fore_color = *fore; + } + if (back) - prop->back_color = *back; + { + prop->flags |= PROPERTY_BACKGROUND; + prop->back_color = *back; + } + prop->length = length; - + + if (GTK_WIDGET_REALIZED (text)) + realize_property (text, prop); + return prop; } +static void +destroy_text_property (TextProperty *prop) +{ + if (prop->font) + text_font_unref (prop->font); + + g_mem_chunk_free (text_property_chunk, prop); +} + /* Flop the memory between the point and the gap around like a * dead fish. */ static void @@ -2809,10 +2988,33 @@ insert_text_property (GtkText* text, GdkFont* font, (forward_prop->length == 1)) { /* Next property just has last position, take it over */ - forward_prop->font = get_text_font (font); - forward_prop->fore_color = *fore; - forward_prop->back_color = *back; + + if (GTK_WIDGET_REALIZED (text)) + unrealize_property (text, forward_prop); + + forward_prop->flags = 0; + if (font) + { + forward_prop->flags |= PROPERTY_FONT; + forward_prop->font = get_text_font (font); + } + else + forward_prop->font = NULL; + + if (fore) + { + forward_prop->flags |= PROPERTY_FOREGROUND; + forward_prop->fore_color = *fore; + } + if (back) + { + forward_prop->flags |= PROPERTY_BACKGROUND; + forward_prop->back_color = *back; + } forward_prop->length += len; + + if (GTK_WIDGET_REALIZED (text)) + realize_property (text, forward_prop); } else { @@ -2826,9 +3028,9 @@ insert_text_property (GtkText* text, GdkFont* font, if (new_prop->prev) new_prop->prev->next = new_prop; - - new_prop->data = new_text_property (font, fore, back, len); - + + new_prop->data = new_text_property (text, font, fore, back, len); + SET_PROPERTY_MARK (mark, new_prop, 0); } } @@ -2854,7 +3056,7 @@ insert_text_property (GtkText* text, GdkFont* font, forward_prop->length -= 1; new_prop = g_list_alloc(); - new_prop->data = new_text_property (font, fore, back, len+1); + new_prop->data = new_text_property (text, font, fore, back, len+1); new_prop->prev = MARK_LIST_PTR(mark); new_prop->next = NULL; MARK_NEXT_LIST_PTR(mark) = new_prop; @@ -2871,14 +3073,19 @@ insert_text_property (GtkText* text, GdkFont* font, /* Set the new lengths according to where they are split. Construct * two new properties. */ forward_prop->length = MARK_OFFSET(mark); - - new_prop_forward->data = new_text_property(forward_prop->font->gdk_font, - &forward_prop->fore_color, - &forward_prop->back_color, - old_length - forward_prop->length); - - new_prop->data = new_text_property(font, fore, back, len); - + + new_prop_forward->data = + new_text_property(text, + forward_prop->flags & PROPERTY_FONT ? + forward_prop->font->gdk_font : NULL, + forward_prop->flags & PROPERTY_FOREGROUND ? + &forward_prop->fore_color : NULL, + forward_prop->flags & PROPERTY_BACKGROUND ? + &forward_prop->back_color : NULL, + old_length - forward_prop->length); + + new_prop->data = new_text_property(text, font, fore, back, len); + /* Now splice things in. */ MARK_NEXT_LIST_PTR(mark) = new_prop; new_prop->prev = MARK_LIST_PTR(mark); @@ -2942,8 +3149,11 @@ delete_text_property (GtkText* text, guint nchars) MARK_LIST_PTR (&text->point) = g_list_remove_link (tmp, tmp); text->point.offset = 0; - - g_mem_chunk_free (text_property_chunk, prop); + + if (GTK_WIDGET_REALIZED (text)) + unrealize_property (text, prop); + + destroy_text_property (prop); g_list_free_1 (tmp); prop = MARK_CURRENT_PROPERTY (&text->point); @@ -2976,7 +3186,10 @@ delete_text_property (GtkText* text, guint nchars) text->point.offset = MARK_CURRENT_PROPERTY(&text->point)->length - 1; - g_mem_chunk_free (text_property_chunk, prop); + if (GTK_WIDGET_REALIZED (text)) + unrealize_property (text, prop); + + destroy_text_property (prop); g_list_free_1 (tmp); } } @@ -2984,17 +3197,12 @@ delete_text_property (GtkText* text, guint nchars) static void init_properties (GtkText *text) { - GtkWidget *widget = (GtkWidget *)text; - if (!text->text_properties) { text->text_properties = g_list_alloc(); text->text_properties->next = NULL; text->text_properties->prev = NULL; - text->text_properties->data = new_text_property (widget->style->font, - &widget->style->text[GTK_STATE_NORMAL], - &widget->style->base[GTK_STATE_NORMAL], - 1); + text->text_properties->data = new_text_property (text, NULL, NULL, NULL, 1); text->text_properties_end = text->text_properties; SET_PROPERTY_MARK (&text->point, text->text_properties, 0); @@ -3226,8 +3434,8 @@ find_char_width (GtkText* text, const GtkPropertyMark *mark, const TabStopMark * return 0; ch = GTK_TEXT_INDEX (text, mark->index); - char_widths = MARK_CURRENT_TEXT_FONT (mark)->char_widths; - + char_widths = MARK_CURRENT_TEXT_FONT (text, mark)->char_widths; + if (ch == '\t') { return tab_mark->to_next_tab * char_widths[' ']; @@ -3300,22 +3508,22 @@ find_cursor_at_line (GtkText* text, const LineParams* start_line, gint pixel_hei #ifdef USE_XIM if (gdk_im_ready() && editable->ic && - gdk_ic_get_style (editable->ic) & GdkIMPreeditPosition) + 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; - if (MARK_CURRENT_FONT (&mark)->type == GDK_FONT_FONTSET) + if (MARK_CURRENT_FONT (text, &mark)->type == GDK_FONT_FONTSET) gdk_ic_set_attr (editable->ic, "preeditAttributes", - "fontSet", GDK_FONT_XFONT (MARK_CURRENT_FONT (&mark)), + "fontSet", GDK_FONT_XFONT (MARK_CURRENT_FONT (text, &mark)), NULL); gdk_ic_set_attr (editable->ic, "preeditAttributes", "spotLocation", &spot, "lineSpace", LINE_HEIGHT (*start_line), - "foreground", MARK_CURRENT_FORE (&mark)->pixel, - "background", MARK_CURRENT_BACK (&mark)->pixel, + "foreground", MARK_CURRENT_FORE (text, &mark)->pixel, + "background", MARK_CURRENT_BACK (text, &mark)->pixel, NULL); } #endif @@ -4219,8 +4427,8 @@ find_line_params (GtkText* text, g_assert (lp.end.property); ch = GTK_TEXT_INDEX (text, lp.end.index); - font = MARK_CURRENT_FONT (&lp.end); - + font = MARK_CURRENT_FONT (text, &lp.end); + if (ch == LINE_DELIM) { /* Newline doesn't count in computation of line height, even @@ -4253,7 +4461,7 @@ find_line_params (GtkText* text, { /* Here's the tough case, a tab is wrapping. */ gint pixels_avail = max_display_pixels - lp.pixel_width; - gint space_width = MARK_CURRENT_TEXT_FONT(&lp.end)->char_widths[' ']; + gint space_width = MARK_CURRENT_TEXT_FONT(text, &lp.end)->char_widths[' ']; gint spaces_avail = pixels_avail / space_width; if (spaces_avail == 0) @@ -4320,8 +4528,8 @@ find_line_params (GtkText* text, if (LAST_INDEX(text, lp.start)) { /* Special case, empty last line. */ - font = MARK_CURRENT_FONT (&lp.end); - + font = MARK_CURRENT_FONT (text, &lp.end); + lp.font_ascent = font->ascent; lp.font_descent = font->descent; } @@ -4367,11 +4575,11 @@ mark_bg_gc (GtkText* text, const GtkPropertyMark *mark) else return GTK_WIDGET(text)->style->bg_gc[GTK_STATE_ACTIVE]; } - else if (!gdk_color_equal(MARK_CURRENT_BACK (mark), + else if (!gdk_color_equal(MARK_CURRENT_BACK (text, mark), >K_WIDGET(text)->style->base[GTK_STATE_NORMAL])) { - gdk_gc_set_foreground (text->gc, MARK_CURRENT_BACK (mark)); + gdk_gc_set_foreground (text->gc, MARK_CURRENT_BACK (text, mark)); return text->gc; } return NULL; @@ -4463,8 +4671,8 @@ draw_line (GtkText* text, len = MIN (len, selection_start_pos - mark.index); else if (mark.index < selection_end_pos) len = MIN (len, selection_end_pos - mark.index); - - font = MARK_CURRENT_PROPERTY (&mark)->font->gdk_font; + + font = MARK_CURRENT_FONT (text, &mark); if (font->type == GDK_FONT_FONT) { gdk_gc_set_font (text->gc, font); @@ -4506,11 +4714,11 @@ draw_line (GtkText* text, } else { - gdk_gc_set_foreground (text->gc, MARK_CURRENT_FORE (&mark)); + gdk_gc_set_foreground (text->gc, MARK_CURRENT_FORE (text, &mark)); fg_gc = text->gc; } - - gdk_draw_text (text->text_area, MARK_CURRENT_FONT (&mark), + + gdk_draw_text (text->text_area, MARK_CURRENT_FONT (text, &mark), fg_gc, running_offset, pixel_height, @@ -4534,9 +4742,9 @@ draw_line (GtkText* text, gdk_window_get_size (text->text_area, &pixels_remaining, NULL); pixels_remaining -= (LINE_WRAP_ROOM + running_offset); - - space_width = MARK_CURRENT_TEXT_FONT(&mark)->char_widths[' ']; - + + space_width = MARK_CURRENT_TEXT_FONT(text, &mark)->char_widths[' ']; + spaces_avail = pixels_remaining / space_width; spaces_avail = MIN (spaces_avail, tab_mark.to_next_tab); @@ -4550,8 +4758,8 @@ draw_line (GtkText* text, } running_offset += tab_mark.to_next_tab * - MARK_CURRENT_TEXT_FONT(&mark)->char_widths[' ']; - + MARK_CURRENT_TEXT_FONT(text, &mark)->char_widths[' ']; + advance_tab_mark (text, &tab_mark, '\t'); } @@ -4611,7 +4819,8 @@ static void undraw_cursor (GtkText* text, gint absolute) { GtkEditable *editable = (GtkEditable *)text; - + GdkGC *gc; + TDEBUG (("in undraw_cursor\n")); if (absolute) @@ -4624,10 +4833,11 @@ undraw_cursor (GtkText* text, gint absolute) GdkFont* font; g_assert(text->cursor_mark.property); - - font = MARK_CURRENT_FONT(&text->cursor_mark); - - if (GTK_WIDGET (text)->style->bg_pixmap[GTK_STATE_NORMAL]) + + font = MARK_CURRENT_FONT(text, &text->cursor_mark); + gc = mark_bg_gc (text, &text->cursor_mark); + + if (!gc && (GTK_WIDGET (text)->style->bg_pixmap[GTK_STATE_NORMAL])) { GdkRectangle rect; @@ -4640,8 +4850,12 @@ undraw_cursor (GtkText* text, gint absolute) } else { - gdk_gc_set_foreground (text->gc, MARK_CURRENT_BACK (&text->cursor_mark)); - gdk_draw_line (text->text_area, text->gc, text->cursor_pos_x, + if (!gc) + { + gdk_gc_set_foreground (text->gc, MARK_CURRENT_BACK (text, &text->cursor_mark)); + gc = text->gc; + } + gdk_draw_line (text->text_area, gc, text->cursor_pos_x, text->cursor_pos_y - text->cursor_char_offset, text->cursor_pos_x, text->cursor_pos_y - text->cursor_char_offset - font->ascent); } @@ -4650,9 +4864,9 @@ undraw_cursor (GtkText* text, gint absolute) { if (font->type == GDK_FONT_FONT) gdk_gc_set_font (text->gc, font); - - gdk_gc_set_foreground (text->gc, MARK_CURRENT_FORE (&text->cursor_mark)); - + + gdk_gc_set_foreground (text->gc, MARK_CURRENT_FORE (text, &text->cursor_mark)); + gdk_draw_text (text->text_area, font, text->gc, text->cursor_pos_x, @@ -4670,7 +4884,7 @@ drawn_cursor_min (GtkText* text) g_assert(text->cursor_mark.property); - font = MARK_CURRENT_FONT(&text->cursor_mark); + font = MARK_CURRENT_FONT(text, &text->cursor_mark); return text->cursor_pos_y - text->cursor_char_offset - font->ascent; } @@ -4682,7 +4896,7 @@ drawn_cursor_max (GtkText* text) g_assert(text->cursor_mark.property); - font = MARK_CURRENT_FONT(&text->cursor_mark); + font = MARK_CURRENT_FONT(text, &text->cursor_mark); return text->cursor_pos_y - text->cursor_char_offset; } @@ -4705,9 +4919,9 @@ draw_cursor (GtkText* text, gint absolute) GdkFont* font; g_assert (text->cursor_mark.property); - - font = MARK_CURRENT_FONT (&text->cursor_mark); - + + font = MARK_CURRENT_FONT (text, &text->cursor_mark); + gdk_gc_set_foreground (text->gc, >K_WIDGET (text)->style->text[GTK_STATE_NORMAL]); gdk_draw_line (text->text_area, text->gc, text->cursor_pos_x, @@ -5072,8 +5286,20 @@ gtk_text_show_props (GtkText *text, TextProperty *p = (TextProperty*)props->data; proplen += p->length; - - g_message ("[%d,%p,%p,%ld,%ld] ", p->length, p, p->font, p->fore_color.pixel, p->back_color.pixel); + + g_message ("[%d,%p,", p->length, p); + if (p->flags & PROPERTY_FONT) + g_message ("%p,", p->font); + else + g_message ("-,"); + if (p->flags & PROPERTY_FOREGROUND) + g_message ("%ld, ", p->fore_color.pixel); + else + g_message ("-,"); + if (p->flags & PROPERTY_BACKGROUND) + g_message ("%ld] ", p->back_color.pixel); + else + g_message ("-] "); } g_message ("\n"); diff --git a/gtk/gtktext.h b/gtk/gtktext.h index 1de2de945a..27f4689b7e 100644 --- a/gtk/gtktext.h +++ b/gtk/gtktext.h @@ -24,7 +24,6 @@ #include <gtk/gtkadjustment.h> #include <gtk/gtkeditable.h> - #ifdef __cplusplus extern "C" { #pragma } @@ -37,7 +36,7 @@ extern "C" { #define GTK_IS_TEXT(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_TEXT)) #define GTK_IS_TEXT_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_TEXT)) - +typedef struct _GtkTextFont GtkTextFont; typedef struct _GtkPropertyMark GtkPropertyMark; typedef struct _GtkText GtkText; typedef struct _GtkTextClass GtkTextClass; @@ -147,6 +146,8 @@ struct _GtkText GList *tab_stops; gint default_tab_width; + GtkTextFont *current_font; /* Text font for current style */ + /* Timer used for auto-scrolling off ends */ gint timer; diff --git a/gtk/gtktypebuiltins.h b/gtk/gtktypebuiltins.h index d75f7b6c01..d8afc47183 100644 --- a/gtk/gtktypebuiltins.h +++ b/gtk/gtktypebuiltins.h @@ -55,6 +55,7 @@ extern GtkType GTK_TYPE_TOOLBAR_CHILD_TYPE; extern GtkType GTK_TYPE_TREE_VIEW_MODE; extern GtkType GTK_TYPE_FUNDAMENTAL_TYPE; extern GtkType GTK_TYPE_WIDGET_FLAGS; +extern GtkType GTK_TYPE_GDK_COLOR_INFO_FLAGS; extern GtkType GTK_TYPE_GDK_DEBUG_FLAG; extern GtkType GTK_TYPE_GDK_RGB_DITHER; extern GtkType GTK_TYPE_GDK_WINDOW_TYPE; diff --git a/gtk/gtktypebuiltins_evals.c b/gtk/gtktypebuiltins_evals.c index 53d010f897..6bbef5a4b2 100644 --- a/gtk/gtktypebuiltins_evals.c +++ b/gtk/gtktypebuiltins_evals.c @@ -438,6 +438,10 @@ static GtkEnumValue _gtk_widget_flags_values[] = { { GTK_BASIC, "GTK_BASIC", "basic" }, { 0, NULL, NULL } }; +static GtkEnumValue _gdk_color_info_flags_values[] = { + { GDK_COLOR_WRITEABLE, "GDK_COLOR_WRITEABLE", "writeable" }, + { 0, NULL, NULL } +}; static GtkEnumValue _gdk_debug_flag_values[] = { { GDK_DEBUG_MISC, "GDK_DEBUG_MISC", "misc" }, { GDK_DEBUG_EVENTS, "GDK_DEBUG_EVENTS", "events" }, @@ -865,15 +869,17 @@ static GtkEnumValue _gdk_extension_mode_values[] = { { 0, NULL, NULL } }; static GtkEnumValue _gdk_im_style_values[] = { - { GdkIMPreeditArea, "GdkIMPreeditArea", "preedit-area" }, - { GdkIMPreeditCallbacks, "GdkIMPreeditCallbacks", "preedit-callbacks" }, - { GdkIMPreeditPosition, "GdkIMPreeditPosition", "preedit-position" }, - { GdkIMPreeditNothing, "GdkIMPreeditNothing", "preedit-nothing" }, - { GdkIMPreeditNone, "GdkIMPreeditNone", "preedit-none" }, - { GdkIMStatusArea, "GdkIMStatusArea", "status-area" }, - { GdkIMStatusCallbacks, "GdkIMStatusCallbacks", "status-callbacks" }, - { GdkIMStatusNothing, "GdkIMStatusNothing", "status-nothing" }, - { GdkIMStatusNone, "GdkIMStatusNone", "status-none" }, + { GDK_IM_PREEDIT_AREA, "GDK_IM_PREEDIT_AREA", "preedit-area" }, + { GDK_IM_PREEDIT_CALLBACKS, "GDK_IM_PREEDIT_CALLBACKS", "preedit-callbacks" }, + { GDK_IM_PREEDIT_POSITION, "GDK_IM_PREEDIT_POSITION", "preedit-position" }, + { GDK_IM_PREEDIT_NOTHING, "GDK_IM_PREEDIT_NOTHING", "preedit-nothing" }, + { GDK_IM_PREEDIT_NONE, "GDK_IM_PREEDIT_NONE", "preedit-none" }, + { GDK_IM_PREEDIT_MASK, "GDK_IM_PREEDIT_MASK", "preedit-mask" }, + { GDK_IM_STATUS_AREA, "GDK_IM_STATUS_AREA", "status-area" }, + { GDK_IM_STATUS_CALLBACKS, "GDK_IM_STATUS_CALLBACKS", "status-callbacks" }, + { GDK_IM_STATUS_NOTHING, "GDK_IM_STATUS_NOTHING", "status-nothing" }, + { GDK_IM_STATUS_NONE, "GDK_IM_STATUS_NONE", "status-none" }, + { GDK_IM_STATUS_MASK, "GDK_IM_STATUS_MASK", "status-mask" }, { 0, NULL, NULL } }; static GtkEnumValue _gdk_wm_decoration_values[] = { diff --git a/gtk/gtktypebuiltins_ids.c b/gtk/gtktypebuiltins_ids.c index f348794a93..b13f05b46e 100644 --- a/gtk/gtktypebuiltins_ids.c +++ b/gtk/gtktypebuiltins_ids.c @@ -110,6 +110,8 @@ GTK_TYPE_ENUM, _gtk_fundamental_type_values }, { "GtkWidgetFlags", >K_TYPE_WIDGET_FLAGS, GTK_TYPE_FLAGS, _gtk_widget_flags_values }, + { "GdkColorInfoFlags", >K_TYPE_GDK_COLOR_INFO_FLAGS, + GTK_TYPE_FLAGS, _gdk_color_info_flags_values }, { "GdkDebugFlag", >K_TYPE_GDK_DEBUG_FLAG, GTK_TYPE_FLAGS, _gdk_debug_flag_values }, { "GdkRgbDither", >K_TYPE_GDK_RGB_DITHER, diff --git a/gtk/gtktypebuiltins_vars.c b/gtk/gtktypebuiltins_vars.c index 921dfeb271..91b31a50c0 100644 --- a/gtk/gtktypebuiltins_vars.c +++ b/gtk/gtktypebuiltins_vars.c @@ -55,6 +55,7 @@ GtkType GTK_TYPE_TOOLBAR_CHILD_TYPE = 0; GtkType GTK_TYPE_TREE_VIEW_MODE = 0; GtkType GTK_TYPE_FUNDAMENTAL_TYPE = 0; GtkType GTK_TYPE_WIDGET_FLAGS = 0; +GtkType GTK_TYPE_GDK_COLOR_INFO_FLAGS = 0; GtkType GTK_TYPE_GDK_DEBUG_FLAG = 0; GtkType GTK_TYPE_GDK_RGB_DITHER = 0; GtkType GTK_TYPE_GDK_WINDOW_TYPE = 0; diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index eb420ecde4..ef1975664d 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -3087,15 +3087,19 @@ gtk_widget_get_colormap (GtkWidget *widget) g_return_val_if_fail (widget != NULL, NULL); - if (!widget->window) + if (widget->window) { - colormap = gtk_object_get_data (GTK_OBJECT (widget), colormap_key); + colormap = gdk_window_get_colormap (widget->window); + /* If window was destroyed previously, we'll get NULL here */ if (colormap) return colormap; - return gtk_widget_get_default_colormap (); } - return gdk_window_get_colormap (widget->window); + colormap = gtk_object_get_data (GTK_OBJECT (widget), colormap_key); + if (colormap) + return colormap; + + return gtk_widget_get_default_colormap (); } /***************************************** @@ -3113,15 +3117,19 @@ gtk_widget_get_visual (GtkWidget *widget) g_return_val_if_fail (widget != NULL, NULL); - if (!widget->window) + if (widget->window) { - visual = gtk_object_get_data (GTK_OBJECT (widget), visual_key); + visual = gdk_window_get_visual (widget->window); + /* If window was destroyed previously, we'll get NULL here */ if (visual) return visual; - return gtk_widget_get_default_visual (); } - return gdk_window_get_visual (widget->window); + visual = gtk_object_get_data (GTK_OBJECT (widget), visual_key); + if (visual) + return visual; + + return gtk_widget_get_default_visual (); } /***************************************** diff --git a/gtk/testgtk.c b/gtk/testgtk.c index 22cb8990cf..f101c15a7a 100644 --- a/gtk/testgtk.c +++ b/gtk/testgtk.c @@ -1759,6 +1759,8 @@ create_pixmap (void) &style->bg[GTK_STATE_NORMAL], "test.xpm"); pixmapwid = gtk_pixmap_new (pixmap, mask); + gdk_pixmap_unref (pixmap); + gdk_pixmap_unref (mask); label = gtk_label_new ("Pixmap\ntest"); box3 = gtk_hbox_new (FALSE, 0); @@ -5186,13 +5188,43 @@ text_toggle_word_wrap (GtkWidget *checkbutton, GTK_TOGGLE_BUTTON(checkbutton)->active); } +struct { + GdkColor color; + gchar *name; +} text_colors[] = { + { { 0, 0x0000, 0x0000, 0x0000 }, "black" }, + { { 0, 0xFFFF, 0xFFFF, 0xFFFF }, "white" }, + { { 0, 0xFFFF, 0x0000, 0x0000 }, "red" }, + { { 0, 0x0000, 0xFFFF, 0x0000 }, "green" }, + { { 0, 0x0000, 0x0000, 0xFFFF }, "blue" }, + { { 0, 0x0000, 0xFFFF, 0xFFFF }, "cyan" }, + { { 0, 0xFFFF, 0x0000, 0xFFFF }, "magenta" }, + { { 0, 0xFFFF, 0xFFFF, 0x0000 }, "yellow" } +}; + +int ntext_colors = sizeof(text_colors) / sizeof(text_colors[0]); + /* * GtkText */ +void +text_insert_random (GtkWidget *w, GtkText *text) +{ + int i; + char c; + for (i=0; i<10; i++) + { + c = 'A' + rand() % ('Z' - 'A'); + gtk_text_set_point (text, rand() % gtk_text_get_length (text)); + gtk_text_insert (text, NULL, NULL, NULL, &c, 1); + } +} void create_text (void) { + int i, j; + static GtkWidget *window = NULL; GtkWidget *box1; GtkWidget *box2; @@ -5204,6 +5236,7 @@ create_text (void) GtkWidget *hscrollbar; GtkWidget *vscrollbar; GtkWidget *text; + GdkFont *font; FILE *infile; @@ -5259,7 +5292,27 @@ create_text (void) gtk_text_freeze (GTK_TEXT (text)); - gtk_widget_realize (text); + font = gdk_font_load ("-adobe-courier-medium-r-normal--*-120-*-*-*-*-*-*"); + + for (i=0; i<ntext_colors; i++) + { + gtk_text_insert (GTK_TEXT (text), font, NULL, NULL, + text_colors[i].name, -1); + gtk_text_insert (GTK_TEXT (text), font, NULL, NULL, "\t", -1); + + for (j=0; j<ntext_colors; j++) + { + gtk_text_insert (GTK_TEXT (text), font, + &text_colors[j].color, &text_colors[i].color, + "XYZ", -1); + } + gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, "\n", -1); + } + + /* The Text widget will reference count the font, so we + * unreference it here + */ + gdk_font_unref (font); infile = fopen("testgtk.c", "r"); @@ -5281,13 +5334,6 @@ create_text (void) fclose (infile); } - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "And even ", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->bg[GTK_STATE_NORMAL], NULL, - "colored", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "text", -1); - gtk_text_thaw (GTK_TEXT (text)); hbox = gtk_hbutton_box_new (); @@ -5319,6 +5365,13 @@ create_text (void) gtk_widget_show (box2); + button = gtk_button_new_with_label ("insert random"); + gtk_signal_connect (GTK_OBJECT (button), "clicked", + GTK_SIGNAL_FUNC(text_insert_random), + GTK_TEXT (text)); + gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0); + gtk_widget_show (button); + button = gtk_button_new_with_label ("close"); gtk_signal_connect_object (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), diff --git a/gtk/testgtkrc b/gtk/testgtkrc index 3427c0a876..e4e6ba72c7 100644 --- a/gtk/testgtkrc +++ b/gtk/testgtkrc @@ -49,7 +49,7 @@ style "toggle_button" = "button" style "text" { bg_pixmap[NORMAL] = "marble.xpm" - text[NORMAL] = { 0.2, 0.2, 1.0 } + text[NORMAL] = { 1.0, 1.0, 1.0 } fg[NORMAL] = { 1.0, 1.0, 1.0 } base[NORMAL] = { 0.0, 0.0, 0.0 } } diff --git a/gtk/testinput.c b/gtk/testinput.c index d2ea54cd25..ac8ff136a0 100644 --- a/gtk/testinput.c +++ b/gtk/testinput.c @@ -369,6 +369,7 @@ main (int argc, char *argv[]) events for the drawing area */ gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_ALL); + GTK_WIDGET_SET_FLAGS (drawing_area, GTK_CAN_FOCUS); gtk_widget_grab_focus (drawing_area); /* .. And create some buttons */ diff --git a/tests/testgtk.c b/tests/testgtk.c index 22cb8990cf..f101c15a7a 100644 --- a/tests/testgtk.c +++ b/tests/testgtk.c @@ -1759,6 +1759,8 @@ create_pixmap (void) &style->bg[GTK_STATE_NORMAL], "test.xpm"); pixmapwid = gtk_pixmap_new (pixmap, mask); + gdk_pixmap_unref (pixmap); + gdk_pixmap_unref (mask); label = gtk_label_new ("Pixmap\ntest"); box3 = gtk_hbox_new (FALSE, 0); @@ -5186,13 +5188,43 @@ text_toggle_word_wrap (GtkWidget *checkbutton, GTK_TOGGLE_BUTTON(checkbutton)->active); } +struct { + GdkColor color; + gchar *name; +} text_colors[] = { + { { 0, 0x0000, 0x0000, 0x0000 }, "black" }, + { { 0, 0xFFFF, 0xFFFF, 0xFFFF }, "white" }, + { { 0, 0xFFFF, 0x0000, 0x0000 }, "red" }, + { { 0, 0x0000, 0xFFFF, 0x0000 }, "green" }, + { { 0, 0x0000, 0x0000, 0xFFFF }, "blue" }, + { { 0, 0x0000, 0xFFFF, 0xFFFF }, "cyan" }, + { { 0, 0xFFFF, 0x0000, 0xFFFF }, "magenta" }, + { { 0, 0xFFFF, 0xFFFF, 0x0000 }, "yellow" } +}; + +int ntext_colors = sizeof(text_colors) / sizeof(text_colors[0]); + /* * GtkText */ +void +text_insert_random (GtkWidget *w, GtkText *text) +{ + int i; + char c; + for (i=0; i<10; i++) + { + c = 'A' + rand() % ('Z' - 'A'); + gtk_text_set_point (text, rand() % gtk_text_get_length (text)); + gtk_text_insert (text, NULL, NULL, NULL, &c, 1); + } +} void create_text (void) { + int i, j; + static GtkWidget *window = NULL; GtkWidget *box1; GtkWidget *box2; @@ -5204,6 +5236,7 @@ create_text (void) GtkWidget *hscrollbar; GtkWidget *vscrollbar; GtkWidget *text; + GdkFont *font; FILE *infile; @@ -5259,7 +5292,27 @@ create_text (void) gtk_text_freeze (GTK_TEXT (text)); - gtk_widget_realize (text); + font = gdk_font_load ("-adobe-courier-medium-r-normal--*-120-*-*-*-*-*-*"); + + for (i=0; i<ntext_colors; i++) + { + gtk_text_insert (GTK_TEXT (text), font, NULL, NULL, + text_colors[i].name, -1); + gtk_text_insert (GTK_TEXT (text), font, NULL, NULL, "\t", -1); + + for (j=0; j<ntext_colors; j++) + { + gtk_text_insert (GTK_TEXT (text), font, + &text_colors[j].color, &text_colors[i].color, + "XYZ", -1); + } + gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, "\n", -1); + } + + /* The Text widget will reference count the font, so we + * unreference it here + */ + gdk_font_unref (font); infile = fopen("testgtk.c", "r"); @@ -5281,13 +5334,6 @@ create_text (void) fclose (infile); } - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "And even ", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->bg[GTK_STATE_NORMAL], NULL, - "colored", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "text", -1); - gtk_text_thaw (GTK_TEXT (text)); hbox = gtk_hbutton_box_new (); @@ -5319,6 +5365,13 @@ create_text (void) gtk_widget_show (box2); + button = gtk_button_new_with_label ("insert random"); + gtk_signal_connect (GTK_OBJECT (button), "clicked", + GTK_SIGNAL_FUNC(text_insert_random), + GTK_TEXT (text)); + gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0); + gtk_widget_show (button); + button = gtk_button_new_with_label ("close"); gtk_signal_connect_object (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), diff --git a/tests/testgtkrc b/tests/testgtkrc index 3427c0a876..e4e6ba72c7 100644 --- a/tests/testgtkrc +++ b/tests/testgtkrc @@ -49,7 +49,7 @@ style "toggle_button" = "button" style "text" { bg_pixmap[NORMAL] = "marble.xpm" - text[NORMAL] = { 0.2, 0.2, 1.0 } + text[NORMAL] = { 1.0, 1.0, 1.0 } fg[NORMAL] = { 1.0, 1.0, 1.0 } base[NORMAL] = { 0.0, 0.0, 0.0 } } diff --git a/tests/testinput.c b/tests/testinput.c index d2ea54cd25..ac8ff136a0 100644 --- a/tests/testinput.c +++ b/tests/testinput.c @@ -369,6 +369,7 @@ main (int argc, char *argv[]) events for the drawing area */ gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_ALL); + GTK_WIDGET_SET_FLAGS (drawing_area, GTK_CAN_FOCUS); gtk_widget_grab_focus (drawing_area); /* .. And create some buttons */ |