diff options
author | Havoc Pennington <hp@src.gnome.org> | 2000-06-07 16:31:46 +0000 |
---|---|---|
committer | Havoc Pennington <hp@src.gnome.org> | 2000-06-07 16:31:46 +0000 |
commit | 49f43eb00b1ef7eb3f6c5077fbcc1cdd46a22bf3 (patch) | |
tree | b85ee035f09e17b8b14bd19b8b775d32a8f3cd3f | |
parent | 9787f736c657d956d809f8ad4ef2039f25729eb8 (diff) | |
download | gdk-pixbuf-49f43eb00b1ef7eb3f6c5077fbcc1cdd46a22bf3.tar.gz |
branch to store the gdk-object-merged-with-pango patch
-rw-r--r-- | gdk/gdk.c | 699 | ||||
-rw-r--r-- | gdk/gdkcompat.h | 48 | ||||
-rw-r--r-- | gdk/gdkdraw.c | 471 | ||||
-rw-r--r-- | gdk/gdkgc.c | 357 | ||||
-rw-r--r-- | gdk/gdkpango.c | 374 | ||||
-rw-r--r-- | gdk/x11/gdkcursor-x11.c | 106 | ||||
-rw-r--r-- | gdk/x11/gdkmain-x11.c | 728 | ||||
-rw-r--r-- | gtk/gtksocket.c | 783 | ||||
-rw-r--r-- | gtk/gtkstyle.c | 3819 | ||||
-rw-r--r-- | gtk/gtkwidget.c | 4648 |
10 files changed, 12033 insertions, 0 deletions
diff --git a/gdk/gdk.c b/gdk/gdk.c new file mode 100644 index 000000000..bfb490e09 --- /dev/null +++ b/gdk/gdk.c @@ -0,0 +1,699 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include "config.h" + +#include <string.h> +#include <stdlib.h> + +#include "gdk.h" +#include "gdkinternals.h" + +#ifndef HAVE_XCONVERTCASE +#include "gdkkeysyms.h" +#endif + +typedef struct _GdkPredicate GdkPredicate; +typedef struct _GdkErrorTrap GdkErrorTrap; + +struct _GdkPredicate +{ + GdkEventFunc func; + gpointer data; +}; + +struct _GdkErrorTrap +{ + gint error_warnings; + gint error_code; +}; + +/* + * Private function declarations + */ +static void gdk_exit_func (void); + +GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev, + GdkEvent *event, + gpointer data); + +/* Private variable declarations + */ +static int gdk_initialized = 0; /* 1 if the library is initialized, + * 0 otherwise. + */ + +static GSList *gdk_error_traps = NULL; /* List of error traps */ +static GSList *gdk_error_trap_free_list = NULL; /* Free list */ + +#ifdef G_ENABLE_DEBUG +static const GDebugKey gdk_debug_keys[] = { + {"events", GDK_DEBUG_EVENTS}, + {"misc", GDK_DEBUG_MISC}, + {"dnd", GDK_DEBUG_DND}, + {"color-context", GDK_DEBUG_COLOR_CONTEXT}, + {"xim", GDK_DEBUG_XIM} +}; + +static const int gdk_ndebug_keys = sizeof(gdk_debug_keys)/sizeof(GDebugKey); + +#endif /* G_ENABLE_DEBUG */ + +GdkArgContext * +gdk_arg_context_new (gpointer cb_data) +{ + GdkArgContext *result = g_new (GdkArgContext, 1); + result->tables = g_ptr_array_new (); + result->cb_data = cb_data; + + return result; +} + +void +gdk_arg_context_destroy (GdkArgContext *context) +{ + g_ptr_array_free (context->tables, TRUE); + g_free (context); +} + +void +gdk_arg_context_add_table (GdkArgContext *context, GdkArgDesc *table) +{ + g_ptr_array_add (context->tables, table); +} + +void +gdk_arg_context_parse (GdkArgContext *context, gint *argc, gchar ***argv) +{ + int i, j, k; + + /* Save a copy of the original argc and argv */ + if (argc && argv) + { + for (i = 1; i < *argc; i++) + { + char *arg; + + if (!(*argv)[i][0] == '-' && (*argv)[i][1] == '-') + continue; + + arg = (*argv)[i] + 2; + + /* '--' terminates list of arguments */ + if (arg == 0) + { + (*argv)[i] = NULL; + break; + } + + for (j = 0; j < context->tables->len; j++) + { + GdkArgDesc *table = context->tables->pdata[j]; + for (k = 0; table[k].name; k++) + { + switch (table[k].type) + { + case GDK_ARG_STRING: + case GDK_ARG_CALLBACK: + case GDK_ARG_INT: + { + int len = strlen (table[k].name); + + if (strncmp (arg, table[k].name, len) == 0 && + (arg[len] == '=' || argc[len] == 0)) + { + char *value = NULL; + + (*argv)[i] = NULL; + + if (arg[len] == '=') + value = arg + len + 1; + else if (i < *argc - 1) + { + value = (*argv)[i + 1]; + (*argv)[i+1] = NULL; + i++; + } + else + value = ""; + + switch (table[k].type) + { + case GDK_ARG_STRING: + *(gchar **)table[k].location = g_strdup (value); + break; + case GDK_ARG_INT: + *(gint *)table[k].location = atoi (value); + break; + case GDK_ARG_CALLBACK: + (*table[k].callback)(table[k].name, value, context->cb_data); + break; + default: + ; + } + + goto next_arg; + } + break; + } + case GDK_ARG_BOOL: + case GDK_ARG_NOBOOL: + if (strcmp (arg, table[k].name) == 0) + { + (*argv)[i] = NULL; + + *(gboolean *)table[k].location = (table[k].type == GDK_ARG_BOOL) ? TRUE : FALSE; + goto next_arg; + } + } + } + } + next_arg: + ; + } + + for (i = 1; i < *argc; i++) + { + for (k = i; k < *argc; k++) + if ((*argv)[k] != NULL) + break; + + if (k > i) + { + k -= i; + for (j = i + k; j < *argc; j++) + (*argv)[j-k] = (*argv)[j]; + *argc -= k; + } + } + } +} + +static void +gdk_arg_debug_cb (const char *key, const char *value, gpointer user_data) +{ + gdk_debug_flags |= g_parse_debug_string (value, + (GDebugKey *) gdk_debug_keys, + gdk_ndebug_keys); +} + +static void +gdk_arg_no_debug_cb (const char *key, const char *value, gpointer user_data) +{ + gdk_debug_flags &= ~g_parse_debug_string (value, + (GDebugKey *) gdk_debug_keys, + gdk_ndebug_keys); +} + +static void +gdk_arg_name_cb (const char *key, const char *value, gpointer user_data) +{ + g_set_prgname (value); +} + +static GdkArgDesc gdk_args[] = { + { "name", GDK_ARG_STRING, NULL, gdk_arg_name_cb }, +#ifdef G_ENABLE_DEBUG + { "gdk-debug", GDK_ARG_CALLBACK, NULL, gdk_arg_debug_cb }, + { "gdk-no-debug", GDK_ARG_CALLBACK, NULL, gdk_arg_no_debug_cb }, +#endif /* G_ENABLE_DEBUG */ + { NULL } +}; + +/* + *-------------------------------------------------------------- + * gdk_init_check + * + * Initialize the library for use. + * + * Arguments: + * "argc" is the number of arguments. + * "argv" is an array of strings. + * + * Results: + * "argc" and "argv" are modified to reflect any arguments + * which were not handled. (Such arguments should either + * be handled by the application or dismissed). If initialization + * fails, returns FALSE, otherwise TRUE. + * + * Side effects: + * The library is initialized. + * + *-------------------------------------------------------------- + */ + +gboolean +gdk_init_check (int *argc, + char ***argv) +{ + gchar **argv_orig = NULL; + gint argc_orig = 0; + GdkArgContext *arg_context; + gboolean result; + int i; + + if (gdk_initialized) + return TRUE; + + if (g_thread_supported ()) + gdk_threads_mutex = g_mutex_new (); + + if (argc && argv) + { + argc_orig = *argc; + + argv_orig = g_malloc ((argc_orig + 1) * sizeof (char*)); + for (i = 0; i < argc_orig; i++) + argv_orig[i] = g_strdup ((*argv)[i]); + argv_orig[argc_orig] = NULL; + + if (*argc > 0) + { + gchar *d; + + d = strrchr((*argv)[0], G_DIR_SEPARATOR); + if (d != NULL) + g_set_prgname (d + 1); + else + g_set_prgname ((*argv)[0]); + } + } + + +#ifdef G_ENABLE_DEBUG + { + gchar *debug_string = getenv("GDK_DEBUG"); + if (debug_string != NULL) + gdk_debug_flags = g_parse_debug_string (debug_string, + (GDebugKey *) gdk_debug_keys, + gdk_ndebug_keys); + } +#endif /* G_ENABLE_DEBUG */ + + g_type_init (); + + arg_context = gdk_arg_context_new (NULL); + gdk_arg_context_add_table (arg_context, gdk_args); + gdk_arg_context_add_table (arg_context, _gdk_windowing_args); + gdk_arg_context_parse (arg_context, argc, argv); + gdk_arg_context_destroy (arg_context); + + GDK_NOTE (MISC, g_message ("progname: \"%s\"", g_get_prgname ())); + + g_type_init (); + + result = _gdk_windowing_init_check (argc_orig, argv_orig); + + for (i = 0; i < argc_orig; i++) + g_free(argv_orig[i]); + g_free(argv_orig); + + if (!result) + return FALSE; + + g_atexit (gdk_exit_func); + + gdk_events_init (); + gdk_visual_init (); + gdk_windowing_window_init (); + gdk_windowing_image_init (); + gdk_input_init (); + gdk_dnd_init (); + +#ifdef USE_XIM + gdk_im_open (); +#endif + + gdk_initialized = 1; + + return TRUE; +} + +void +gdk_init (int *argc, char ***argv) +{ + if (!gdk_init_check (argc, argv)) + { + g_warning ("cannot open display: %s", gdk_get_display ()); + exit(1); + } +} + +/* + *-------------------------------------------------------------- + * gdk_exit + * + * Restores the library to an un-itialized state and exits + * the program using the "exit" system call. + * + * Arguments: + * "errorcode" is the error value to pass to "exit". + * + * Results: + * Allocated structures are freed and the program exits + * cleanly. + * + * Side effects: + * + *-------------------------------------------------------------- + */ + +void +gdk_exit (gint errorcode) +{ + /* de-initialisation is done by the gdk_exit_funct(), + no need to do this here (Alex J.) */ + exit (errorcode); +} + +/* + *-------------------------------------------------------------- + * gdk_exit_func + * + * This is the "atexit" function that makes sure the + * library gets a chance to cleanup. + * + * Arguments: + * + * Results: + * + * Side effects: + * The library is un-initialized and the program exits. + * + *-------------------------------------------------------------- + */ + +static void +gdk_exit_func (void) +{ + static gboolean in_gdk_exit_func = FALSE; + + /* This is to avoid an infinite loop if a program segfaults in + an atexit() handler (and yes, it does happen, especially if a program + has trounced over memory too badly for even g_message to work) */ + if (in_gdk_exit_func == TRUE) + return; + in_gdk_exit_func = TRUE; + + if (gdk_initialized) + { +#ifdef USE_XIM + /* cleanup IC */ + gdk_ic_cleanup (); + /* close IM */ + gdk_im_close (); +#endif + gdk_image_exit (); + gdk_input_exit (); + gdk_key_repeat_restore (); + + gdk_windowing_exit (); + + gdk_initialized = 0; + } +} + +/************************************************************* + * gdk_error_trap_push: + * Push an error trap. X errors will be trapped until + * the corresponding gdk_error_pop(), which will return + * the error code, if any. + * arguments: + * + * results: + *************************************************************/ + +void +gdk_error_trap_push (void) +{ + GSList *node; + GdkErrorTrap *trap; + + if (gdk_error_trap_free_list) + { + node = gdk_error_trap_free_list; + gdk_error_trap_free_list = gdk_error_trap_free_list->next; + } + else + { + node = g_slist_alloc (); + node->data = g_new (GdkErrorTrap, 1); + } + + node->next = gdk_error_traps; + gdk_error_traps = node; + + trap = node->data; + trap->error_code = gdk_error_code; + trap->error_warnings = gdk_error_warnings; + + gdk_error_code = 0; + gdk_error_warnings = 0; +} + +/************************************************************* + * gdk_error_trap_pop: + * Pop an error trap added with gdk_error_push() + * arguments: + * + * results: + * 0, if no error occured, otherwise the error code. + *************************************************************/ + +gint +gdk_error_trap_pop (void) +{ + GSList *node; + GdkErrorTrap *trap; + gint result; + + g_return_val_if_fail (gdk_error_traps != NULL, 0); + + node = gdk_error_traps; + gdk_error_traps = gdk_error_traps->next; + + node->next = gdk_error_trap_free_list; + gdk_error_trap_free_list = node; + + result = gdk_error_code; + + trap = node->data; + gdk_error_code = trap->error_code; + gdk_error_warnings = trap->error_warnings; + + return result; +} + +#ifndef HAVE_XCONVERTCASE +/* compatibility function from X11R6.3, since XConvertCase is not + * supplied by X11R5. + */ +void +gdk_keyval_convert_case (guint symbol, + guint *lower, + guint *upper) +{ + guint xlower = symbol; + guint xupper = symbol; + + switch (symbol >> 8) + { +#if defined (GDK_A) && defined (GDK_Ooblique) + case 0: /* Latin 1 */ + if ((symbol >= GDK_A) && (symbol <= GDK_Z)) + xlower += (GDK_a - GDK_A); + else if ((symbol >= GDK_a) && (symbol <= GDK_z)) + xupper -= (GDK_a - GDK_A); + else if ((symbol >= GDK_Agrave) && (symbol <= GDK_Odiaeresis)) + xlower += (GDK_agrave - GDK_Agrave); + else if ((symbol >= GDK_agrave) && (symbol <= GDK_odiaeresis)) + xupper -= (GDK_agrave - GDK_Agrave); + else if ((symbol >= GDK_Ooblique) && (symbol <= GDK_Thorn)) + xlower += (GDK_oslash - GDK_Ooblique); + else if ((symbol >= GDK_oslash) && (symbol <= GDK_thorn)) + xupper -= (GDK_oslash - GDK_Ooblique); + break; +#endif /* LATIN1 */ + +#if defined (GDK_Aogonek) && defined (GDK_tcedilla) + case 1: /* Latin 2 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (symbol == GDK_Aogonek) + xlower = GDK_aogonek; + else if (symbol >= GDK_Lstroke && symbol <= GDK_Sacute) + xlower += (GDK_lstroke - GDK_Lstroke); + else if (symbol >= GDK_Scaron && symbol <= GDK_Zacute) + xlower += (GDK_scaron - GDK_Scaron); + else if (symbol >= GDK_Zcaron && symbol <= GDK_Zabovedot) + xlower += (GDK_zcaron - GDK_Zcaron); + else if (symbol == GDK_aogonek) + xupper = GDK_Aogonek; + else if (symbol >= GDK_lstroke && symbol <= GDK_sacute) + xupper -= (GDK_lstroke - GDK_Lstroke); + else if (symbol >= GDK_scaron && symbol <= GDK_zacute) + xupper -= (GDK_scaron - GDK_Scaron); + else if (symbol >= GDK_zcaron && symbol <= GDK_zabovedot) + xupper -= (GDK_zcaron - GDK_Zcaron); + else if (symbol >= GDK_Racute && symbol <= GDK_Tcedilla) + xlower += (GDK_racute - GDK_Racute); + else if (symbol >= GDK_racute && symbol <= GDK_tcedilla) + xupper -= (GDK_racute - GDK_Racute); + break; +#endif /* LATIN2 */ + +#if defined (GDK_Hstroke) && defined (GDK_Cabovedot) + case 2: /* Latin 3 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (symbol >= GDK_Hstroke && symbol <= GDK_Hcircumflex) + xlower += (GDK_hstroke - GDK_Hstroke); + else if (symbol >= GDK_Gbreve && symbol <= GDK_Jcircumflex) + xlower += (GDK_gbreve - GDK_Gbreve); + else if (symbol >= GDK_hstroke && symbol <= GDK_hcircumflex) + xupper -= (GDK_hstroke - GDK_Hstroke); + else if (symbol >= GDK_gbreve && symbol <= GDK_jcircumflex) + xupper -= (GDK_gbreve - GDK_Gbreve); + else if (symbol >= GDK_Cabovedot && symbol <= GDK_Scircumflex) + xlower += (GDK_cabovedot - GDK_Cabovedot); + else if (symbol >= GDK_cabovedot && symbol <= GDK_scircumflex) + xupper -= (GDK_cabovedot - GDK_Cabovedot); + break; +#endif /* LATIN3 */ + +#if defined (GDK_Rcedilla) && defined (GDK_Amacron) + case 3: /* Latin 4 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (symbol >= GDK_Rcedilla && symbol <= GDK_Tslash) + xlower += (GDK_rcedilla - GDK_Rcedilla); + else if (symbol >= GDK_rcedilla && symbol <= GDK_tslash) + xupper -= (GDK_rcedilla - GDK_Rcedilla); + else if (symbol == GDK_ENG) + xlower = GDK_eng; + else if (symbol == GDK_eng) + xupper = GDK_ENG; + else if (symbol >= GDK_Amacron && symbol <= GDK_Umacron) + xlower += (GDK_amacron - GDK_Amacron); + else if (symbol >= GDK_amacron && symbol <= GDK_umacron) + xupper -= (GDK_amacron - GDK_Amacron); + break; +#endif /* LATIN4 */ + +#if defined (GDK_Serbian_DJE) && defined (GDK_Cyrillic_yu) + case 6: /* Cyrillic */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (symbol >= GDK_Serbian_DJE && symbol <= GDK_Serbian_DZE) + xlower -= (GDK_Serbian_DJE - GDK_Serbian_dje); + else if (symbol >= GDK_Serbian_dje && symbol <= GDK_Serbian_dze) + xupper += (GDK_Serbian_DJE - GDK_Serbian_dje); + else if (symbol >= GDK_Cyrillic_YU && symbol <= GDK_Cyrillic_HARDSIGN) + xlower -= (GDK_Cyrillic_YU - GDK_Cyrillic_yu); + else if (symbol >= GDK_Cyrillic_yu && symbol <= GDK_Cyrillic_hardsign) + xupper += (GDK_Cyrillic_YU - GDK_Cyrillic_yu); + break; +#endif /* CYRILLIC */ + +#if defined (GDK_Greek_ALPHAaccent) && defined (GDK_Greek_finalsmallsigma) + case 7: /* Greek */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (symbol >= GDK_Greek_ALPHAaccent && symbol <= GDK_Greek_OMEGAaccent) + xlower += (GDK_Greek_alphaaccent - GDK_Greek_ALPHAaccent); + else if (symbol >= GDK_Greek_alphaaccent && symbol <= GDK_Greek_omegaaccent && + symbol != GDK_Greek_iotaaccentdieresis && + symbol != GDK_Greek_upsilonaccentdieresis) + xupper -= (GDK_Greek_alphaaccent - GDK_Greek_ALPHAaccent); + else if (symbol >= GDK_Greek_ALPHA && symbol <= GDK_Greek_OMEGA) + xlower += (GDK_Greek_alpha - GDK_Greek_ALPHA); + else if (symbol >= GDK_Greek_alpha && symbol <= GDK_Greek_omega && + symbol != GDK_Greek_finalsmallsigma) + xupper -= (GDK_Greek_alpha - GDK_Greek_ALPHA); + break; +#endif /* GREEK */ + } + + if (lower) + *lower = xlower; + if (upper) + *upper = xupper; +} +#endif + +guint +gdk_keyval_to_upper (guint keyval) +{ + guint result; + + gdk_keyval_convert_case (keyval, NULL, &result); + + return result; +} + +guint +gdk_keyval_to_lower (guint keyval) +{ + guint result; + + gdk_keyval_convert_case (keyval, &result, NULL); + + return result; +} + +gboolean +gdk_keyval_is_upper (guint keyval) +{ + if (keyval) + { + guint upper_val = 0; + + gdk_keyval_convert_case (keyval, NULL, &upper_val); + return upper_val == keyval; + } + return FALSE; +} + +gboolean +gdk_keyval_is_lower (guint keyval) +{ + if (keyval) + { + guint lower_val = 0; + + gdk_keyval_convert_case (keyval, &lower_val, NULL); + return lower_val == keyval; + } + return FALSE; +} + +void +gdk_threads_enter () +{ + GDK_THREADS_ENTER (); +} + +void +gdk_threads_leave () +{ + GDK_THREADS_LEAVE (); +} + diff --git a/gdk/gdkcompat.h b/gdk/gdkcompat.h new file mode 100644 index 000000000..aa499c40e --- /dev/null +++ b/gdk/gdkcompat.h @@ -0,0 +1,48 @@ +#ifndef __GDK_COMPAT_H__ +#define __GDK_COMPAT_H__ + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* use -DGDK_DISABLE_COMPAT_H to compile your code and asure that it + * works with future GTK+ versions as well. + */ +#ifndef GDK_DISABLE_COMPAT_H + +#define gdk_draw_pixmap gdk_draw_drawable +#define gdk_draw_bitmap gdk_draw_drawable + +#define gdk_window_get_size gdk_drawable_get_size +/* We can't really be compatible here, due to GObject */ +/* #define gdk_window_get_type gdk_drawable_get_type */ +#define gdk_window_get_colormap gdk_drawable_get_colormap +#define gdk_window_set_colormap gdk_drawable_set_colormap +#define gdk_window_get_visual gdk_drawable_get_visual + +#define gdk_window_ref gdk_drawable_ref +#define gdk_window_unref gdk_drawable_unref +#define gdk_bitmap_ref gdk_drawable_ref +#define gdk_bitmap_unref gdk_drawable_unref +#define gdk_pixmap_ref gdk_drawable_ref +#define gdk_pixmap_unref gdk_drawable_unref + +#define gdk_window_copy_area(drawable,gc,x,y,source_drawable,source_x,source_y,width,height) \ + gdk_draw_pixmap(drawable,gc,source_drawable,source_x,source_y,x,y,width,height) + +#define gdk_gc_destroy gdk_gc_unref +#define gdk_image_destroy gdk_image_unref +#define gdk_cursor_destroy gdk_cursor_unref + + +#define GDK_WINDOW_PIXMAP GDK_DRAWABLE_PIXMAP + +#endif /* GDK_DISABLE_COMPAT_H */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GDK_COMPAT_H__ */ + diff --git a/gdk/gdkdraw.c b/gdk/gdkdraw.c new file mode 100644 index 000000000..f6c970853 --- /dev/null +++ b/gdk/gdkdraw.c @@ -0,0 +1,471 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include "gdkdrawable.h" +#include "gdkinternals.h" +#include "gdkwindow.h" + +static void gdk_drawable_init (GdkDrawable *drawable); +static void gdk_drawable_class_init (GdkDrawableClass *klass); +static void gdk_drawable_finalize (GObject *object); + +static gpointer parent_class = NULL; + +GType +gdk_drawable_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (GdkDrawableClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gdk_drawable_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GdkDrawable), + 0, /* n_preallocs */ + (GInstanceInitFunc) gdk_drawable_init, + }; + + object_type = g_type_register_static (G_TYPE_OBJECT, + "GdkDrawable", + &object_info); + } + + return object_type; +} + +static void +gdk_drawable_init (GdkDrawable *drawable) +{ + +} + +static void +gdk_drawable_class_init (GdkDrawableClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = gdk_drawable_finalize; +} + +static void +gdk_drawable_finalize (GObject *object) +{ + GdkDrawable *drawable = GDK_DRAWABLE (object); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +/* Manipulation of drawables + */ + +void +gdk_drawable_set_data (GdkDrawable *drawable, + const gchar *key, + gpointer data, + GDestroyNotify destroy_func) +{ + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + + g_object_set_qdata_full (G_OBJECT (drawable), + g_quark_from_string (key), + data, + destroy_func); +} + +gpointer +gdk_drawable_get_data (GdkDrawable *drawable, + const gchar *key) +{ + g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL); + + return g_object_get_qdata (G_OBJECT (drawable), + g_quark_try_string (key)); +} + +void +gdk_drawable_get_size (GdkDrawable *drawable, + gint *width, + gint *height) +{ + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + + GDK_DRAWABLE_GET_CLASS (drawable)->get_size (drawable, width, height); +} + +GdkVisual* +gdk_drawable_get_visual (GdkDrawable *drawable) +{ + g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL); + + return GDK_DRAWABLE_GET_CLASS (drawable)->get_visual (drawable); +} + +gint +gdk_drawable_get_depth (GdkDrawable *drawable) +{ + g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), 0); + + return GDK_DRAWABLE_GET_CLASS (drawable)->get_depth (drawable); +} + +void +gdk_drawable_set_colormap (GdkDrawable *drawable, + GdkColormap *cmap) +{ + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + + GDK_DRAWABLE_GET_CLASS (drawable)->set_colormap (drawable, cmap); +} + +GdkColormap* +gdk_drawable_get_colormap (GdkDrawable *drawable) +{ + g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL); + + return GDK_DRAWABLE_GET_CLASS (drawable)->get_colormap (drawable); +} + +GdkDrawable* +gdk_drawable_ref (GdkDrawable *drawable) +{ + return (GdkDrawable *) g_object_ref (G_OBJECT (drawable)); +} + +void +gdk_drawable_unref (GdkDrawable *drawable) +{ + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + + g_object_unref (G_OBJECT (drawable)); +} + +/* Drawing + */ +void +gdk_draw_point (GdkDrawable *drawable, + GdkGC *gc, + gint x, + gint y) +{ + GdkPoint point; + + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + g_return_if_fail (GDK_IS_GC (gc)); + + point.x = x; + point.y = y; + + GDK_DRAWABLE_GET_CLASS (drawable)->draw_points (drawable, gc, &point, 1); +} + +void +gdk_draw_line (GdkDrawable *drawable, + GdkGC *gc, + gint x1, + gint y1, + gint x2, + gint y2) +{ + GdkSegment segment; + + g_return_if_fail (drawable != NULL); + g_return_if_fail (gc != NULL); + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + g_return_if_fail (GDK_IS_GC (gc)); + + segment.x1 = x1; + segment.y1 = y1; + segment.x2 = x2; + segment.y2 = y2; + GDK_DRAWABLE_GET_CLASS (drawable)->draw_segments (drawable, gc, &segment, 1); +} + +void +gdk_draw_rectangle (GdkDrawable *drawable, + GdkGC *gc, + gint filled, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + g_return_if_fail (GDK_IS_GC (gc)); + + if (width < 0 || height < 0) + { + gint real_width; + gint real_height; + + gdk_drawable_get_size (drawable, &real_width, &real_height); + + if (width < 0) + width = real_width; + if (height < 0) + height = real_height; + } + + GDK_DRAWABLE_GET_CLASS (drawable)->draw_rectangle (drawable, gc, filled, x, y, + width, height); +} + +void +gdk_draw_arc (GdkDrawable *drawable, + GdkGC *gc, + gint filled, + gint x, + gint y, + gint width, + gint height, + gint angle1, + gint angle2) +{ + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + g_return_if_fail (GDK_IS_GC (gc)); + + if (width < 0 || height < 0) + { + gint real_width; + gint real_height; + + gdk_drawable_get_size (drawable, &real_width, &real_height); + + if (width < 0) + width = real_width; + if (height < 0) + height = real_height; + } + + GDK_DRAWABLE_GET_CLASS (drawable)->draw_arc (drawable, gc, filled, + x, y, width, height, angle1, angle2); +} + +void +gdk_draw_polygon (GdkDrawable *drawable, + GdkGC *gc, + gint filled, + GdkPoint *points, + gint npoints) +{ + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + g_return_if_fail (GDK_IS_GC (gc)); + + GDK_DRAWABLE_GET_CLASS (drawable)->draw_polygon (drawable, gc, filled, + points, npoints); +} + +/* gdk_draw_string + * + * Modified by Li-Da Lho to draw 16 bits and Multibyte strings + * + * Interface changed: add "GdkFont *font" to specify font or fontset explicitely + */ +void +gdk_draw_string (GdkDrawable *drawable, + GdkFont *font, + GdkGC *gc, + gint x, + gint y, + const gchar *string) +{ + gdk_draw_text (drawable, font, gc, x, y, string, _gdk_font_strlen (font, string)); +} + +/* gdk_draw_text + * + * Modified by Li-Da Lho to draw 16 bits and Multibyte strings + * + * Interface changed: add "GdkFont *font" to specify font or fontset explicitely + */ +void +gdk_draw_text (GdkDrawable *drawable, + GdkFont *font, + GdkGC *gc, + gint x, + gint y, + const gchar *text, + gint text_length) +{ + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + g_return_if_fail (font != NULL); + g_return_if_fail (GDK_IS_GC (gc)); + g_return_if_fail (text != NULL); + + GDK_DRAWABLE_GET_CLASS (drawable)->draw_text (drawable, font, gc, x, y, text, text_length); +} + +void +gdk_draw_text_wc (GdkDrawable *drawable, + GdkFont *font, + GdkGC *gc, + gint x, + gint y, + const GdkWChar *text, + gint text_length) +{ + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + g_return_if_fail (font != NULL); + g_return_if_fail (GDK_IS_GC (gc)); + g_return_if_fail (text != NULL); + + GDK_DRAWABLE_GET_CLASS (drawable)->draw_text_wc (drawable, font, gc, x, y, text, text_length); +} + +void +gdk_draw_drawable (GdkDrawable *drawable, + GdkGC *gc, + GdkDrawable *src, + gint xsrc, + gint ysrc, + gint xdest, + gint ydest, + gint width, + gint height) +{ + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + g_return_if_fail (src != NULL); + g_return_if_fail (GDK_IS_GC (gc)); + + if (width < 0 || height < 0) + { + gint real_width; + gint real_height; + + gdk_drawable_get_size (drawable, &real_width, &real_height); + + if (width < 0) + width = real_width; + if (height < 0) + height = real_height; + } + + GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable (drawable, gc, src, + xsrc, ysrc, xdest, ydest, + width, height); +} + +void +gdk_draw_image (GdkDrawable *drawable, + GdkGC *gc, + GdkImage *image, + gint xsrc, + gint ysrc, + gint xdest, + gint ydest, + gint width, + gint height) +{ + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + g_return_if_fail (image != NULL); + g_return_if_fail (GDK_IS_GC (gc)); + + if (width == -1) + width = image->width; + if (height == -1) + height = image->height; + + GDK_DRAWABLE_GET_CLASS (drawable)->draw_image (drawable, gc, image, xsrc, ysrc, + xdest, ydest, width, height); +} + +void +gdk_draw_points (GdkDrawable *drawable, + GdkGC *gc, + GdkPoint *points, + gint npoints) +{ + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + g_return_if_fail ((points != NULL) && (npoints > 0)); + g_return_if_fail (GDK_IS_GC (gc)); + g_return_if_fail (npoints >= 0); + + if (npoints == 0) + return; + + GDK_DRAWABLE_GET_CLASS (drawable)->draw_points (drawable, gc, points, npoints); +} + +void +gdk_draw_segments (GdkDrawable *drawable, + GdkGC *gc, + GdkSegment *segs, + gint nsegs) +{ + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + + if (nsegs == 0) + return; + + g_return_if_fail (segs != NULL); + g_return_if_fail (GDK_IS_GC (gc)); + g_return_if_fail (nsegs >= 0); + + GDK_DRAWABLE_GET_CLASS (drawable)->draw_segments (drawable, gc, segs, nsegs); +} + +void +gdk_draw_lines (GdkDrawable *drawable, + GdkGC *gc, + GdkPoint *points, + gint npoints) +{ + + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + g_return_if_fail (points != NULL); + g_return_if_fail (GDK_IS_GC (gc)); + g_return_if_fail (npoints >= 0); + + if (npoints == 0) + return; + + GDK_DRAWABLE_GET_CLASS (drawable)->draw_lines (drawable, gc, points, npoints); +} + +void +gdk_draw_glyphs (GdkDrawable *drawable, + GdkGC *gc, + PangoFont *font, + gint x, + gint y, + PangoGlyphString *glyphs) +{ + + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + g_return_if_fail (GDK_IS_GC (gc)); + + + GDK_DRAWABLE_GET_CLASS (drawable)->draw_glyphs (drawable, gc, font, x, y, glyphs); +} + + diff --git a/gdk/gdkgc.c b/gdk/gdkgc.c new file mode 100644 index 000000000..5ff3a24df --- /dev/null +++ b/gdk/gdkgc.c @@ -0,0 +1,357 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include <string.h> + +#include "gdkgc.h" +#include "gdkprivate.h" + +static void gdk_gc_init (GdkGC *gc); +static void gdk_gc_class_init (GdkGCClass *klass); +static void gdk_gc_finalize (GObject *object); + +static gpointer parent_class = NULL; + +GType +gdk_gc_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (GdkGCClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gdk_gc_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GdkGC), + 0, /* n_preallocs */ + (GInstanceInitFunc) gdk_gc_init, + }; + + object_type = g_type_register_static (G_TYPE_OBJECT, + "GdkGC", + &object_info); + } + + return object_type; +} + +static void +gdk_gc_init (GdkGC *gc) +{ + +} + +static void +gdk_gc_class_init (GdkGCClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = gdk_gc_finalize; +} + +static void +gdk_gc_finalize (GObject *object) +{ + GdkGC *gc = GDK_GC (object); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +GdkGC* +gdk_gc_new (GdkDrawable *drawable) +{ + g_return_val_if_fail (drawable != NULL, NULL); + + if (GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)) + return NULL; + + return gdk_gc_new_with_values (drawable, NULL, 0); +} + +GdkGC* +gdk_gc_new_with_values (GdkDrawable *drawable, + GdkGCValues *values, + GdkGCValuesMask values_mask) +{ + GdkGC *gc; + + g_return_val_if_fail (drawable != NULL, NULL); + + if (GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)) + return NULL; + + gc = GDK_DRAWABLE_GET_CLASS (drawable)->create_gc (drawable, + values, + values_mask); + if (values_mask & GDK_GC_CLIP_X_ORIGIN) + gc->clip_x_origin = values->clip_x_origin; + if (values_mask & GDK_GC_CLIP_Y_ORIGIN) + gc->clip_y_origin = values->clip_y_origin; + if (values_mask & GDK_GC_TS_X_ORIGIN) + gc->ts_x_origin = values->ts_x_origin; + if (values_mask & GDK_GC_TS_Y_ORIGIN) + gc->ts_y_origin = values->ts_y_origin; + + return gc; +} + +GdkGC * +gdk_gc_ref (GdkGC *gc) +{ + return (GdkGC *) g_object_ref (G_OBJECT (gc)); +} + +void +gdk_gc_unref (GdkGC *gc) +{ + g_object_unref (G_OBJECT (gc)); +} + +void +gdk_gc_get_values (GdkGC *gc, + GdkGCValues *values) +{ + g_return_if_fail (GDK_IS_GC (gc)); + g_return_if_fail (values != NULL); + + GDK_GC_GET_CLASS (gc)->get_values (gc, values); +} + +void +gdk_gc_set_values (GdkGC *gc, + GdkGCValues *values, + GdkGCValuesMask values_mask) +{ + g_return_if_fail (GDK_IS_GC (gc)); + g_return_if_fail (values != NULL); + + if (values_mask & GDK_GC_CLIP_X_ORIGIN) + gc->clip_x_origin = values->clip_x_origin; + if (values_mask & GDK_GC_CLIP_Y_ORIGIN) + gc->clip_y_origin = values->clip_y_origin; + if (values_mask & GDK_GC_TS_X_ORIGIN) + gc->ts_x_origin = values->ts_x_origin; + if (values_mask & GDK_GC_TS_Y_ORIGIN) + gc->ts_y_origin = values->ts_y_origin; + + GDK_GC_GET_CLASS (gc)->set_values (gc, values, values_mask); +} + +void +gdk_gc_set_foreground (GdkGC *gc, + GdkColor *color) +{ + GdkGCValues values; + + g_return_if_fail (GDK_IS_GC (gc)); + g_return_if_fail (color != NULL); + + values.foreground = *color; + gdk_gc_set_values (gc, &values, GDK_GC_FOREGROUND); +} + +void +gdk_gc_set_background (GdkGC *gc, + GdkColor *color) +{ + GdkGCValues values; + + g_return_if_fail (GDK_IS_GC (gc)); + g_return_if_fail (color != NULL); + + values.background = *color; + gdk_gc_set_values (gc, &values, GDK_GC_BACKGROUND); +} + +void +gdk_gc_set_font (GdkGC *gc, + GdkFont *font) +{ + GdkGCValues values; + + g_return_if_fail (GDK_IS_GC (gc)); + g_return_if_fail (font != NULL); + + values.font = font; + gdk_gc_set_values (gc, &values, GDK_GC_FONT); +} + +void +gdk_gc_set_function (GdkGC *gc, + GdkFunction function) +{ + GdkGCValues values; + + g_return_if_fail (GDK_IS_GC (gc)); + + values.function = function; + gdk_gc_set_values (gc, &values, GDK_GC_FUNCTION); +} + +void +gdk_gc_set_fill (GdkGC *gc, + GdkFill fill) +{ + GdkGCValues values; + + g_return_if_fail (GDK_IS_GC (gc)); + + values.fill = fill; + gdk_gc_set_values (gc, &values, GDK_GC_FILL); +} + +void +gdk_gc_set_tile (GdkGC *gc, + GdkPixmap *tile) +{ + GdkGCValues values; + + g_return_if_fail (GDK_IS_GC (gc)); + + values.tile = tile; + gdk_gc_set_values (gc, &values, GDK_GC_TILE); +} + +void +gdk_gc_set_stipple (GdkGC *gc, + GdkPixmap *stipple) +{ + GdkGCValues values; + + g_return_if_fail (GDK_IS_GC (gc)); + + values.stipple = stipple; + gdk_gc_set_values (gc, &values, GDK_GC_STIPPLE); +} + +void +gdk_gc_set_ts_origin (GdkGC *gc, + gint x, + gint y) +{ + GdkGCValues values; + + g_return_if_fail (GDK_IS_GC (gc)); + + values.ts_x_origin = x; + values.ts_y_origin = y; + + gdk_gc_set_values (gc, &values, + GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN); +} + +void +gdk_gc_set_clip_origin (GdkGC *gc, + gint x, + gint y) +{ + GdkGCValues values; + + g_return_if_fail (GDK_IS_GC (gc)); + + values.clip_x_origin = x; + values.clip_y_origin = y; + + gdk_gc_set_values (gc, &values, + GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN); +} + +void +gdk_gc_set_clip_mask (GdkGC *gc, + GdkBitmap *mask) +{ + GdkGCValues values; + + g_return_if_fail (GDK_IS_GC (gc)); + + values.clip_mask = mask; + gdk_gc_set_values (gc, &values, GDK_GC_CLIP_MASK); +} + + +void +gdk_gc_set_subwindow (GdkGC *gc, + GdkSubwindowMode mode) +{ + GdkGCValues values; + + g_return_if_fail (GDK_IS_GC (gc)); + + values.subwindow_mode = mode; + gdk_gc_set_values (gc, &values, GDK_GC_SUBWINDOW); +} + +void +gdk_gc_set_exposures (GdkGC *gc, + gboolean exposures) +{ + GdkGCValues values; + + g_return_if_fail (GDK_IS_GC (gc)); + + values.graphics_exposures = exposures; + gdk_gc_set_values (gc, &values, GDK_GC_EXPOSURES); +} + +void +gdk_gc_set_line_attributes (GdkGC *gc, + gint line_width, + GdkLineStyle line_style, + GdkCapStyle cap_style, + GdkJoinStyle join_style) +{ + GdkGCValues values; + + values.line_width = line_width; + values.line_style = line_style; + values.cap_style = cap_style; + values.join_style = join_style; + + gdk_gc_set_values (gc, &values, + GDK_GC_LINE_WIDTH | + GDK_GC_LINE_STYLE | + GDK_GC_CAP_STYLE | + GDK_GC_JOIN_STYLE); +} + +void +gdk_gc_set_dashes (GdkGC *gc, + gint dash_offset, + gint8 dash_list[], + gint n) +{ + g_return_if_fail (GDK_IS_GC (gc)); + g_return_if_fail (dash_list != NULL); + + GDK_GC_GET_CLASS (gc)->set_dashes (gc, dash_offset, dash_list, n); +} diff --git a/gdk/gdkpango.c b/gdk/gdkpango.c new file mode 100644 index 000000000..e3fc1f958 --- /dev/null +++ b/gdk/gdkpango.c @@ -0,0 +1,374 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2000 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "gdkcolor.h" +#include "gdkgc.h" +#include "gdkpango.h" +#include "gdkprivate.h" + +#define GDK_INFO_KEY "gdk-info" + +typedef struct _GdkPangoContextInfo GdkPangoContextInfo; + +struct _GdkPangoContextInfo +{ + GdkColormap *colormap; +}; + +static void gdk_pango_get_item_properties (PangoItem *item, + PangoUnderline *uline, + PangoAttrColor *fg_color, + gboolean *fg_set, + PangoAttrColor *bg_color, + gboolean *bg_set); + +static void +gdk_pango_context_destroy (GdkPangoContextInfo *info) +{ + gdk_colormap_unref (info->colormap); + g_free (info); +} + +static GdkPangoContextInfo * +gdk_pango_context_get_info (PangoContext *context, gboolean create) +{ + GdkPangoContextInfo *info = pango_context_get_data (context, GDK_INFO_KEY); + if (!info && create) + { + info = g_new (GdkPangoContextInfo, 1); + info->colormap = NULL; + + pango_context_set_data (context, GDK_INFO_KEY, + info, (GDestroyNotify)gdk_pango_context_destroy); + } + + return info; +} + +static GdkGC * +gdk_pango_get_gc (PangoContext *context, + PangoAttrColor *fg_color, + GdkGC *base_gc) +{ + GdkPangoContextInfo *info; + GdkColormap *colormap; + GdkColor color; + + g_return_val_if_fail (context != NULL, NULL); + + info = gdk_pango_context_get_info (context, FALSE); + + if (info && info->colormap) + colormap = info->colormap; + else + colormap = gdk_colormap_get_system(); + + /* FIXME. FIXME. FIXME. Only works for true color */ + + color.red = fg_color->red; + color.green = fg_color->green; + color.blue = fg_color->blue; + + if (gdk_colormap_alloc_color (colormap, &color, FALSE, TRUE)) + { + GdkGC *result = gdk_gc_new (gdk_parent_root); + gdk_gc_copy (result, base_gc); + gdk_gc_set_foreground (result, &color); + + return result; + } + else + return gdk_gc_ref (base_gc); +} + +static void +gdk_pango_free_gc (PangoContext *context, + GdkGC *gc) +{ + gdk_gc_unref (gc); +} + +void +gdk_pango_context_set_colormap (PangoContext *context, + GdkColormap *colormap) +{ + GdkPangoContextInfo *info; + + g_return_if_fail (context != NULL); + + info = gdk_pango_context_get_info (context, TRUE); + g_return_if_fail (info != NULL); + + if (info->colormap != colormap) + { + if (info->colormap) + gdk_colormap_unref (info->colormap); + + info->colormap = colormap; + + if (info->colormap) + gdk_colormap_ref (info->colormap); + } +} + + +/** + * gdk_draw_layout_line: + * @drawable: the drawable on which to draw the line + * @gc: base graphics to use + * @x: the x position of start of string (in pixels) + * @y: the y position of baseline (in pixels) + * @line: a #PangoLayoutLine + * + * Render a #PangoLayoutLine onto an GDK drawable + */ +void +gdk_draw_layout_line (GdkDrawable *drawable, + GdkGC *gc, + gint x, + gint y, + PangoLayoutLine *line) +{ + GSList *tmp_list = line->runs; + PangoRectangle overall_rect; + PangoRectangle logical_rect; + PangoRectangle ink_rect; + PangoContext *context; + gint x_off = 0; + + g_return_if_fail (drawable != NULL); + g_return_if_fail (gc != NULL); + g_return_if_fail (line != NULL); + + if (GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)) + return; + + context = pango_layout_get_context (line->layout); + + pango_layout_line_get_extents (line,NULL, &overall_rect); + + while (tmp_list) + { + PangoUnderline uline = PANGO_UNDERLINE_NONE; + PangoLayoutRun *run = tmp_list->data; + PangoAttrColor fg_color, bg_color; + gboolean fg_set, bg_set; + GdkGC *fg_gc; + + tmp_list = tmp_list->next; + + gdk_pango_get_item_properties (run->item, &uline, &fg_color, &fg_set, &bg_color, &bg_set); + + if (fg_set) + fg_gc = gdk_pango_get_gc (context, &fg_color, gc); + else + fg_gc = gc; + + if (uline == PANGO_UNDERLINE_NONE) + pango_glyph_string_extents (run->glyphs, run->item->analysis.font, + NULL, &logical_rect); + else + pango_glyph_string_extents (run->glyphs, run->item->analysis.font, + &ink_rect, &logical_rect); + + if (bg_set) + { + GdkGC *bg_gc = gdk_pango_get_gc (context, &bg_color, gc); + + gdk_draw_rectangle (drawable, bg_gc, TRUE, + x + (x_off + logical_rect.x) / PANGO_SCALE, + y + overall_rect.y / PANGO_SCALE, + logical_rect.width / PANGO_SCALE, + overall_rect.height / PANGO_SCALE); + + gdk_pango_free_gc (context, bg_gc); + } + + gdk_draw_glyphs (drawable, fg_gc, run->item->analysis.font, + x + x_off / PANGO_SCALE, y, run->glyphs); + + switch (uline) + { + case PANGO_UNDERLINE_NONE: + break; + case PANGO_UNDERLINE_DOUBLE: + gdk_draw_line (drawable, fg_gc, + x + (x_off + ink_rect.x) / PANGO_SCALE - 1, y + 4, + x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, y + 4); + /* Fall through */ + case PANGO_UNDERLINE_SINGLE: + gdk_draw_line (drawable, fg_gc, + x + (x_off + ink_rect.x) / PANGO_SCALE - 1, y + 2, + x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, y + 2); + break; + case PANGO_UNDERLINE_LOW: + gdk_draw_line (drawable, fg_gc, + x + (x_off + ink_rect.x) / PANGO_SCALE - 1, y + (ink_rect.y + ink_rect.height) / PANGO_SCALE + 2, + x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, y + (ink_rect.y + ink_rect.height) / PANGO_SCALE + 2); + break; + } + + if (fg_set) + gdk_pango_free_gc (context, fg_gc); + + x_off += logical_rect.width; + } +} + +/** + * gdk_draw_layout: + * @drawable: the drawable on which to draw string + * @gc: base graphics context to use + * @x: the X position of the left of the layout (in pixels) + * @y: the Y position of the top of the layout (in pixels) + * @layout: a #PangoLayout + * + * Render a #PangoLayout onto a GDK drawable + */ +void +gdk_draw_layout (GdkDrawable *drawable, + GdkGC *gc, + int x, + int y, + PangoLayout *layout) +{ + PangoRectangle logical_rect; + GSList *tmp_list; + PangoAlignment align; + gint indent; + gint width; + gint y_offset = 0; + gboolean first = FALSE; + + g_return_if_fail (drawable != NULL); + g_return_if_fail (gc != NULL); + g_return_if_fail (layout != NULL); + + if (GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)) + return; + + g_return_if_fail (layout != NULL); + + indent = pango_layout_get_indent (layout); + width = pango_layout_get_width (layout); + align = pango_layout_get_alignment (layout); + + if (width == -1 && align != PANGO_ALIGN_LEFT) + { + pango_layout_get_extents (layout, NULL, &logical_rect); + width = logical_rect.width; + } + + tmp_list = pango_layout_get_lines (layout); + while (tmp_list) + { + PangoLayoutLine *line = tmp_list->data; + int x_offset; + + pango_layout_line_get_extents (line, NULL, &logical_rect); + + if (width != 1 && align == PANGO_ALIGN_RIGHT) + x_offset = width - logical_rect.width; + else if (width != 1 && align == PANGO_ALIGN_CENTER) + x_offset = (width - logical_rect.width) / 2; + else + x_offset = 0; + + if (first) + { + if (indent > 0) + { + if (align == PANGO_ALIGN_LEFT) + x_offset += indent; + else + x_offset -= indent; + } + + first = FALSE; + } + else + { + if (indent < 0) + { + if (align == PANGO_ALIGN_LEFT) + x_offset -= indent; + else + x_offset += indent; + } + } + + gdk_draw_layout_line (drawable, gc, + x + x_offset / PANGO_SCALE, y + (y_offset - logical_rect.y) / PANGO_SCALE, + line); + + y_offset += logical_rect.height; + tmp_list = tmp_list->next; + } +} + +static void +gdk_pango_get_item_properties (PangoItem *item, + PangoUnderline *uline, + PangoAttrColor *fg_color, + gboolean *fg_set, + PangoAttrColor *bg_color, + gboolean *bg_set) +{ + GSList *tmp_list = item->extra_attrs; + + if (fg_set) + *fg_set = FALSE; + + if (bg_set) + *bg_set = FALSE; + + while (tmp_list) + { + PangoAttribute *attr = tmp_list->data; + + switch (attr->klass->type) + { + case PANGO_ATTR_UNDERLINE: + if (uline) + *uline = ((PangoAttrInt *)attr)->value; + break; + + case PANGO_ATTR_FOREGROUND: + if (fg_color) + *fg_color = *((PangoAttrColor *)attr); + if (fg_set) + *fg_set = TRUE; + + break; + + case PANGO_ATTR_BACKGROUND: + if (bg_color) + *bg_color = *((PangoAttrColor *)attr); + if (bg_set) + *bg_set = TRUE; + + break; + + default: + break; + } + tmp_list = tmp_list->next; + } +} + diff --git a/gdk/x11/gdkcursor-x11.c b/gdk/x11/gdkcursor-x11.c new file mode 100644 index 000000000..1af928968 --- /dev/null +++ b/gdk/x11/gdkcursor-x11.c @@ -0,0 +1,106 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include <X11/Xlib.h> +#include <X11/cursorfont.h> + +#include "gdkx.h" +#include "gdkcursor.h" +#include "gdkpixmap-x11.h" +#include <gdk/gdkpixmap.h> + +GdkCursor* +gdk_cursor_new (GdkCursorType cursor_type) +{ + GdkCursorPrivate *private; + GdkCursor *cursor; + Cursor xcursor; + + xcursor = XCreateFontCursor (gdk_display, cursor_type); + private = g_new (GdkCursorPrivate, 1); + private->xdisplay = gdk_display; + private->xcursor = xcursor; + cursor = (GdkCursor*) private; + cursor->type = cursor_type; + cursor->ref_count = 1; + + return cursor; +} + +GdkCursor* +gdk_cursor_new_from_pixmap (GdkPixmap *source, + GdkPixmap *mask, + GdkColor *fg, + GdkColor *bg, + gint x, + gint y) +{ + GdkCursorPrivate *private; + GdkCursor *cursor; + Pixmap source_pixmap, mask_pixmap; + Cursor xcursor; + XColor xfg, xbg; + + g_return_val_if_fail (GDK_IS_PIXMAP (source), NULL); + g_return_val_if_fail (fg != NULL, NULL); + g_return_val_if_fail (bg != NULL, NULL); + + source_pixmap = GDK_PIXMAP_XID (source); + mask_pixmap = GDK_PIXMAP_XID (mask); + + xfg.pixel = fg->pixel; + xfg.red = fg->red; + xfg.blue = fg->blue; + xfg.green = fg->green; + xbg.pixel = bg->pixel; + xbg.red = bg->red; + xbg.blue = bg->blue; + xbg.green = bg->green; + + xcursor = XCreatePixmapCursor (gdk_display, source_pixmap, mask_pixmap, &xfg, &xbg, x, y); + private = g_new (GdkCursorPrivate, 1); + private->xdisplay = gdk_display; + private->xcursor = xcursor; + cursor = (GdkCursor *) private; + cursor->type = GDK_CURSOR_IS_PIXMAP; + cursor->ref_count = 1; + + return cursor; +} + +void +_gdk_cursor_destroy (GdkCursor *cursor) +{ + GdkCursorPrivate *private; + + g_return_if_fail (cursor != NULL); + g_return_if_fail (cursor->ref_count == 0); + + private = (GdkCursorPrivate *) cursor; + XFreeCursor (private->xdisplay, private->xcursor); + + g_free (private); +} diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c new file mode 100644 index 000000000..65aefdf25 --- /dev/null +++ b/gdk/x11/gdkmain-x11.c @@ -0,0 +1,728 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include "config.h" + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <errno.h> + +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif /* HAVE_SYS_SELECT_H_ */ + +#define XLIB_ILLEGAL_ACCESS +#include <X11/Xatom.h> +#include <X11/Xlib.h> +#include <X11/Xos.h> +#include <X11/Xutil.h> +#include <X11/cursorfont.h> + +#include "gdk.h" + +#include "gdkprivate-x11.h" +#include "gdkinternals.h" +#include "gdkinputprivate.h" + +typedef struct _GdkPredicate GdkPredicate; +typedef struct _GdkErrorTrap GdkErrorTrap; + +struct _GdkPredicate +{ + GdkEventFunc func; + gpointer data; +}; + +struct _GdkErrorTrap +{ + gint error_warnings; + gint error_code; +}; + +/* + * Private function declarations + */ + +#ifndef HAVE_XCONVERTCASE +static void gdkx_XConvertCase (KeySym symbol, + KeySym *lower, + KeySym *upper); +#define XConvertCase gdkx_XConvertCase +#endif + +static int gdk_x_error (Display *display, + XErrorEvent *error); +static int gdk_x_io_error (Display *display); + +/* Private variable declarations + */ +static int gdk_initialized = 0; /* 1 if the library is initialized, + * 0 otherwise. + */ + +static gint autorepeat; +static gboolean gdk_synchronize = FALSE; + +#ifdef G_ENABLE_DEBUG +static const GDebugKey gdk_debug_keys[] = { + {"events", GDK_DEBUG_EVENTS}, + {"misc", GDK_DEBUG_MISC}, + {"dnd", GDK_DEBUG_DND}, + {"color-context", GDK_DEBUG_COLOR_CONTEXT}, + {"xim", GDK_DEBUG_XIM} +}; + +static const int gdk_ndebug_keys = sizeof(gdk_debug_keys)/sizeof(GDebugKey); + +#endif /* G_ENABLE_DEBUG */ + +static void +gdk_arg_xim_preedit_cb (const gchar *arg, const gchar *value, gpointer cb_data) +{ + if (strcmp ("none", value) == 0) + gdk_im_set_best_style (GDK_IM_PREEDIT_NONE); + else if (strcmp ("nothing", value) == 0) + gdk_im_set_best_style (GDK_IM_PREEDIT_NOTHING); + else if (strcmp ("area", value) == 0) + gdk_im_set_best_style (GDK_IM_PREEDIT_AREA); + else if (strcmp ("position", value) == 0) + gdk_im_set_best_style (GDK_IM_PREEDIT_POSITION); + else if (strcmp ("callbacks", value) == 0) + gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS); +} + +static void +gdk_arg_xim_status_cb (const gchar *arg, const gchar *value, gpointer cb_data) +{ + if (strcmp ("none", value) == 0) + gdk_im_set_best_style (GDK_IM_STATUS_NONE); + else if (strcmp ("nothing", value) == 0) + gdk_im_set_best_style (GDK_IM_STATUS_NOTHING); + else if (strcmp ("area", value) == 0) + gdk_im_set_best_style (GDK_IM_STATUS_AREA); + else if (strcmp ("callbacks", value) == 0) + gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS); +} + +GdkArgDesc _gdk_windowing_args[] = { + { "display", GDK_ARG_STRING, &gdk_display_name, (GdkArgFunc)NULL }, + { "sync", GDK_ARG_BOOL, &gdk_synchronize, (GdkArgFunc)NULL }, + { "no-xshm", GDK_ARG_NOBOOL, &gdk_use_xshm, (GdkArgFunc)NULL }, + { "class", GDK_ARG_STRING, &gdk_progclass, (GdkArgFunc)NULL }, + { "gxid-host", GDK_ARG_STRING, &gdk_input_gxid_host, (GdkArgFunc)NULL }, + { "gxid-port", GDK_ARG_INT, &gdk_input_gxid_port, (GdkArgFunc)NULL }, + { "xim-preedit", GDK_ARG_CALLBACK, NULL, gdk_arg_xim_preedit_cb }, + { "xim-status", GDK_ARG_CALLBACK, NULL, gdk_arg_xim_status_cb }, + { NULL } +}; + +gboolean +_gdk_windowing_init_check (int argc, char **argv) +{ + XKeyboardState keyboard_state; + XClassHint *class_hint; + + XSetErrorHandler (gdk_x_error); + XSetIOErrorHandler (gdk_x_io_error); + + gdk_display = XOpenDisplay (gdk_display_name); + if (!gdk_display) + return FALSE; + + if (gdk_synchronize) + XSynchronize (gdk_display, True); + + gdk_screen = DefaultScreen (gdk_display); + gdk_root_window = RootWindow (gdk_display, gdk_screen); + + gdk_leader_window = XCreateSimpleWindow(gdk_display, gdk_root_window, + 10, 10, 10, 10, 0, 0 , 0); + class_hint = XAllocClassHint(); + class_hint->res_name = g_get_prgname (); + if (gdk_progclass == NULL) + { + gdk_progclass = g_strdup (g_get_prgname ()); + gdk_progclass[0] = toupper (gdk_progclass[0]); + } + class_hint->res_class = gdk_progclass; + XmbSetWMProperties (gdk_display, gdk_leader_window, + NULL, NULL, argv, argc, + NULL, NULL, class_hint); + XFree (class_hint); + + gdk_wm_delete_window = XInternAtom (gdk_display, "WM_DELETE_WINDOW", False); + gdk_wm_take_focus = XInternAtom (gdk_display, "WM_TAKE_FOCUS", False); + gdk_wm_protocols = XInternAtom (gdk_display, "WM_PROTOCOLS", False); + gdk_wm_window_protocols[0] = gdk_wm_delete_window; + gdk_wm_window_protocols[1] = gdk_wm_take_focus; + gdk_selection_property = XInternAtom (gdk_display, "GDK_SELECTION", False); + + XGetKeyboardControl (gdk_display, &keyboard_state); + autorepeat = keyboard_state.global_auto_repeat; + + return TRUE; +} + +void +gdk_set_use_xshm (gboolean use_xshm) +{ + gdk_use_xshm = use_xshm; +} + +gboolean +gdk_get_use_xshm (void) +{ + return gdk_use_xshm; +} + +/* + *-------------------------------------------------------------- + * gdk_pointer_grab + * + * Grabs the pointer to a specific window + * + * Arguments: + * "window" is the window which will receive the grab + * "owner_events" specifies whether events will be reported as is, + * or relative to "window" + * "event_mask" masks only interesting events + * "confine_to" limits the cursor movement to the specified window + * "cursor" changes the cursor for the duration of the grab + * "time" specifies the time + * + * Results: + * + * Side effects: + * requires a corresponding call to gdk_pointer_ungrab + * + *-------------------------------------------------------------- + */ + +gint +gdk_pointer_grab (GdkWindow * window, + gboolean owner_events, + GdkEventMask event_mask, + GdkWindow * confine_to, + GdkCursor * cursor, + guint32 time) +{ + gint return_val; + GdkCursorPrivate *cursor_private; + guint xevent_mask; + Window xwindow; + Window xconfine_to; + Cursor xcursor; + int i; + + g_return_val_if_fail (window != NULL, 0); + g_return_val_if_fail (GDK_IS_WINDOW (window), 0); + g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0); + + cursor_private = (GdkCursorPrivate*) cursor; + + xwindow = GDK_WINDOW_XID (window); + + if (!confine_to || GDK_WINDOW_DESTROYED (confine_to)) + xconfine_to = None; + else + xconfine_to = GDK_WINDOW_XID (confine_to); + + if (!cursor) + xcursor = None; + else + xcursor = cursor_private->xcursor; + + + xevent_mask = 0; + for (i = 0; i < gdk_nevent_masks; i++) + { + if (event_mask & (1 << (i + 1))) + xevent_mask |= gdk_event_mask_table[i]; + } + + if (gdk_input_vtable.grab_pointer) + return_val = gdk_input_vtable.grab_pointer (window, + owner_events, + event_mask, + confine_to, + time); + else + return_val = Success; + + if (return_val == Success) + { + if (!GDK_WINDOW_DESTROYED (window)) + return_val = XGrabPointer (GDK_WINDOW_XDISPLAY (window), + xwindow, + owner_events, + xevent_mask, + GrabModeAsync, GrabModeAsync, + xconfine_to, + xcursor, + time); + else + return_val = AlreadyGrabbed; + } + + if (return_val == GrabSuccess) + gdk_xgrab_window = (GdkWindowObject *)window; + + return return_val; +} + +/* + *-------------------------------------------------------------- + * gdk_pointer_ungrab + * + * Releases any pointer grab + * + * Arguments: + * + * Results: + * + * Side effects: + * + *-------------------------------------------------------------- + */ + +void +gdk_pointer_ungrab (guint32 time) +{ + if (gdk_input_vtable.ungrab_pointer) + gdk_input_vtable.ungrab_pointer (time); + + XUngrabPointer (gdk_display, time); + gdk_xgrab_window = NULL; +} + +/* + *-------------------------------------------------------------- + * gdk_pointer_is_grabbed + * + * Tell wether there is an active x pointer grab in effect + * + * Arguments: + * + * Results: + * + * Side effects: + * + *-------------------------------------------------------------- + */ + +gboolean +gdk_pointer_is_grabbed (void) +{ + return gdk_xgrab_window != NULL; +} + +/* + *-------------------------------------------------------------- + * gdk_keyboard_grab + * + * Grabs the keyboard to a specific window + * + * Arguments: + * "window" is the window which will receive the grab + * "owner_events" specifies whether events will be reported as is, + * or relative to "window" + * "time" specifies the time + * + * Results: + * + * Side effects: + * requires a corresponding call to gdk_keyboard_ungrab + * + *-------------------------------------------------------------- + */ + +gint +gdk_keyboard_grab (GdkWindow * window, + gboolean owner_events, + guint32 time) +{ + g_return_val_if_fail (window != NULL, 0); + g_return_val_if_fail (GDK_IS_WINDOW (window), 0); + + if (!GDK_WINDOW_DESTROYED (window)) + return XGrabKeyboard (GDK_WINDOW_XDISPLAY (window), + GDK_WINDOW_XID (window), + owner_events, + GrabModeAsync, GrabModeAsync, + time); + else + return AlreadyGrabbed; +} + +/* + *-------------------------------------------------------------- + * gdk_keyboard_ungrab + * + * Releases any keyboard grab + * + * Arguments: + * + * Results: + * + * Side effects: + * + *-------------------------------------------------------------- + */ + +void +gdk_keyboard_ungrab (guint32 time) +{ + XUngrabKeyboard (gdk_display, time); +} + +/* + *-------------------------------------------------------------- + * gdk_screen_width + * + * Return the width of the screen. + * + * Arguments: + * + * Results: + * + * Side effects: + * + *-------------------------------------------------------------- + */ + +gint +gdk_screen_width (void) +{ + gint return_val; + + return_val = DisplayWidth (gdk_display, gdk_screen); + + return return_val; +} + +/* + *-------------------------------------------------------------- + * gdk_screen_height + * + * Return the height of the screen. + * + * Arguments: + * + * Results: + * + * Side effects: + * + *-------------------------------------------------------------- + */ + +gint +gdk_screen_height (void) +{ + gint return_val; + + return_val = DisplayHeight (gdk_display, gdk_screen); + + return return_val; +} + +/* + *-------------------------------------------------------------- + * gdk_screen_width_mm + * + * Return the width of the screen in millimeters. + * + * Arguments: + * + * Results: + * + * Side effects: + * + *-------------------------------------------------------------- + */ + +gint +gdk_screen_width_mm (void) +{ + gint return_val; + + return_val = DisplayWidthMM (gdk_display, gdk_screen); + + return return_val; +} + +/* + *-------------------------------------------------------------- + * gdk_screen_height + * + * Return the height of the screen in millimeters. + * + * Arguments: + * + * Results: + * + * Side effects: + * + *-------------------------------------------------------------- + */ + +gint +gdk_screen_height_mm (void) +{ + gint return_val; + + return_val = DisplayHeightMM (gdk_display, gdk_screen); + + return return_val; +} + +/* + *-------------------------------------------------------------- + * gdk_set_sm_client_id + * + * Set the SM_CLIENT_ID property on the WM_CLIENT_LEADER window + * so that the window manager can save our state using the + * X11R6 ICCCM session management protocol. A NULL value should + * be set following disconnection from the session manager to + * remove the SM_CLIENT_ID property. + * + * Arguments: + * + * "sm_client_id" specifies the client id assigned to us by the + * session manager or NULL to remove the property. + * + * Results: + * + * Side effects: + * + *-------------------------------------------------------------- + */ + +void +gdk_set_sm_client_id (const gchar* sm_client_id) +{ + if (sm_client_id && strcmp (sm_client_id, "")) + { + XChangeProperty (gdk_display, gdk_leader_window, + gdk_atom_intern ("SM_CLIENT_ID", FALSE), + XA_STRING, 8, PropModeReplace, + sm_client_id, strlen(sm_client_id)); + } + else + XDeleteProperty (gdk_display, gdk_leader_window, + gdk_atom_intern ("SM_CLIENT_ID", FALSE)); +} + +void +gdk_key_repeat_disable (void) +{ + XAutoRepeatOff (gdk_display); +} + +void +gdk_key_repeat_restore (void) +{ + if (autorepeat) + XAutoRepeatOn (gdk_display); + else + XAutoRepeatOff (gdk_display); +} + + +void +gdk_beep (void) +{ + XBell(gdk_display, 0); +} + +void +gdk_windowing_exit (void) +{ + pango_x_shutdown_display (gdk_display); + + XCloseDisplay (gdk_display); +} + +/* + *-------------------------------------------------------------- + * gdk_x_error + * + * The X error handling routine. + * + * Arguments: + * "display" is the X display the error orignated from. + * "error" is the XErrorEvent that we are handling. + * + * Results: + * Either we were expecting some sort of error to occur, + * in which case we set the "gdk_error_code" flag, or this + * error was unexpected, in which case we will print an + * error message and exit. (Since trying to continue will + * most likely simply lead to more errors). + * + * Side effects: + * + *-------------------------------------------------------------- + */ + +static int +gdk_x_error (Display *display, + XErrorEvent *error) +{ + if (error->error_code) + { + if (gdk_error_warnings) + { + char buf[64]; + + XGetErrorText (display, error->error_code, buf, 63); + +#ifdef G_ENABLE_DEBUG + g_error ("%s\n serial %ld error_code %d request_code %d minor_code %d\n", + buf, + error->serial, + error->error_code, + error->request_code, + error->minor_code); +#else /* !G_ENABLE_DEBUG */ + fprintf (stderr, "Gdk-ERROR **: %s\n serial %ld error_code %d request_code %d minor_code %d\n", + buf, + error->serial, + error->error_code, + error->request_code, + error->minor_code); + + exit(1); +#endif /* G_ENABLE_DEBUG */ + } + gdk_error_code = error->error_code; + } + + return 0; +} + +/* + *-------------------------------------------------------------- + * gdk_x_io_error + * + * The X I/O error handling routine. + * + * Arguments: + * "display" is the X display the error orignated from. + * + * Results: + * An X I/O error basically means we lost our connection + * to the X server. There is not much we can do to + * continue, so simply print an error message and exit. + * + * Side effects: + * + *-------------------------------------------------------------- + */ + +static int +gdk_x_io_error (Display *display) +{ + /* This is basically modelled after the code in XLib. We need + * an explicit error handler here, so we can disable our atexit() + * which would otherwise cause a nice segfault. + * We fprintf(stderr, instead of g_warning() because g_warning() + * could possibly be redirected to a dialog + */ + if (errno == EPIPE) + { + fprintf (stderr, "Gdk-ERROR **: X connection to %s broken (explicit kill or server shutdown).\n", gdk_display ? DisplayString (gdk_display) : gdk_get_display()); + } + else + { + fprintf (stderr, "Gdk-ERROR **: Fatal IO error %d (%s) on X server %s.\n", + errno, g_strerror (errno), + gdk_display ? DisplayString (gdk_display) : gdk_get_display()); + } + + /* Disable the atexit shutdown for GDK */ + gdk_initialized = 0; + + exit(1); +} + +gchar * +gdk_get_display (void) +{ + return (gchar *)XDisplayName (gdk_display_name); +} + +gint +gdk_send_xevent (Window window, gboolean propagate, glong event_mask, + XEvent *event_send) +{ + Status result; + gint old_warnings = gdk_error_warnings; + + gdk_error_code = 0; + + gdk_error_warnings = 0; + result = XSendEvent (gdk_display, window, propagate, event_mask, event_send); + XSync (gdk_display, False); + gdk_error_warnings = old_warnings; + + return result && !gdk_error_code; +} + +gchar* +gdk_keyval_name (guint keyval) +{ + return XKeysymToString (keyval); +} + +guint +gdk_keyval_from_name (const gchar *keyval_name) +{ + g_return_val_if_fail (keyval_name != NULL, 0); + + return XStringToKeysym (keyval_name); +} + +#ifdef HAVE_XCONVERTCASE +void +gdk_keyval_convert_case (guint symbol, + guint *lower, + guint *upper) +{ + KeySym xlower = 0; + KeySym xupper = 0; + + if (symbol) + XConvertCase (symbol, &xlower, &xupper); + + if (lower) + *lower = xlower; + if (upper) + *upper = xupper; +} +#endif HAVE_XCONVERTCASE diff --git a/gtk/gtksocket.c b/gtk/gtksocket.c new file mode 100644 index 000000000..34490f97b --- /dev/null +++ b/gtk/gtksocket.c @@ -0,0 +1,783 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* By Owen Taylor <otaylor@gtk.org> 98/4/4 */ + +/* + * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include "gdkconfig.h" + +#if defined (GDK_WINDOWING_X11) +#include "x11/gdkx.h" +#elif defined (GDK_WINDOWING_WIN32) +#include "win32/gdkwin32.h" +#endif + +#include "gdk/gdkkeysyms.h" +#include "gtkwindow.h" +#include "gtksignal.h" +#include "gtksocket.h" +#include "gtkdnd.h" + +#ifdef GDK_WINDOWING_X11 + +/* Forward declararations */ + +static void gtk_socket_class_init (GtkSocketClass *klass); +static void gtk_socket_init (GtkSocket *socket); +static void gtk_socket_realize (GtkWidget *widget); +static void gtk_socket_unrealize (GtkWidget *widget); +static void gtk_socket_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void gtk_socket_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static gint gtk_socket_focus_in_event (GtkWidget *widget, + GdkEventFocus *event); +static void gtk_socket_claim_focus (GtkSocket *socket); +static gint gtk_socket_focus_out_event (GtkWidget *widget, + GdkEventFocus *event); +static void gtk_socket_send_configure_event (GtkSocket *socket); +static gint gtk_socket_focus (GtkContainer *container, + GtkDirectionType direction); +static GdkFilterReturn gtk_socket_filter_func (GdkXEvent *gdk_xevent, + GdkEvent *event, + gpointer data); + +/* From Tk */ +#define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20 + +/* Local data */ + +static GtkWidgetClass *parent_class = NULL; + +GtkType +gtk_socket_get_type (void) +{ + static GtkType socket_type = 0; + + if (!socket_type) + { + static const GTypeInfo socket_info = + { + sizeof (GtkSocketClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gtk_socket_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GtkSocket), + 16, /* n_preallocs */ + (GInstanceInitFunc) gtk_socket_init, + }; + + socket_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkSocket", &socket_info); + } + + return socket_type; +} + +static void +gtk_socket_class_init (GtkSocketClass *class) +{ + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + GtkContainerClass *container_class; + + object_class = (GtkObjectClass*) class; + widget_class = (GtkWidgetClass*) class; + container_class = (GtkContainerClass*) class; + + parent_class = gtk_type_class (GTK_TYPE_CONTAINER); + + widget_class->realize = gtk_socket_realize; + widget_class->unrealize = gtk_socket_unrealize; + widget_class->size_request = gtk_socket_size_request; + widget_class->size_allocate = gtk_socket_size_allocate; + widget_class->focus_in_event = gtk_socket_focus_in_event; + widget_class->focus_out_event = gtk_socket_focus_out_event; + + container_class->focus = gtk_socket_focus; +} + +static void +gtk_socket_init (GtkSocket *socket) +{ + socket->request_width = 0; + socket->request_height = 0; + socket->current_width = 0; + socket->current_height = 0; + + socket->plug_window = NULL; + socket->same_app = FALSE; + socket->focus_in = FALSE; + socket->have_size = FALSE; + socket->need_map = FALSE; +} + +GtkWidget* +gtk_socket_new (void) +{ + GtkSocket *socket; + + socket = gtk_type_new (GTK_TYPE_SOCKET); + + return GTK_WIDGET (socket); +} + +void +gtk_socket_steal (GtkSocket *socket, guint32 id) +{ + GtkWidget *widget; + + widget = GTK_WIDGET (socket); + + socket->plug_window = gdk_window_lookup (id); + + gdk_error_trap_push (); + + if (socket->plug_window && + ((GdkWindowObject *)socket->plug_window)->user_data) + { + /* + GtkWidget *child_widget; + + child_widget = GTK_WIDGET (socket->plug_window->user_data); + */ + + g_warning("Stealing from same app not yet implemented"); + + socket->same_app = TRUE; + } + else + { + socket->plug_window = gdk_window_foreign_new (id); + if (!socket->plug_window) /* was deleted before we could get it */ + { + gdk_error_trap_pop (); + return; + } + + socket->same_app = FALSE; + socket->have_size = FALSE; + + XSelectInput (GDK_DISPLAY (), + GDK_WINDOW_XWINDOW(socket->plug_window), + StructureNotifyMask | PropertyChangeMask); + + gtk_widget_queue_resize (widget); + } + + gdk_window_hide (socket->plug_window); + gdk_window_reparent (socket->plug_window, widget->window, 0, 0); + + gdk_flush (); + gdk_error_trap_pop (); + + socket->need_map = TRUE; +} + +static void +gtk_socket_realize (GtkWidget *widget) +{ + GtkSocket *socket; + GdkWindowAttr attributes; + gint attributes_mask; + XWindowAttributes xattrs; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_SOCKET (widget)); + + socket = GTK_SOCKET (widget); + GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); + + attributes.window_type = GDK_WINDOW_CHILD; + attributes.x = widget->allocation.x; + attributes.y = widget->allocation.y; + attributes.width = widget->allocation.width; + attributes.height = widget->allocation.height; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + attributes.event_mask = GDK_FOCUS_CHANGE_MASK; + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + + widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), + &attributes, attributes_mask); + gdk_window_set_user_data (widget->window, socket); + + widget->style = gtk_style_attach (widget->style, widget->window); + gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); + + XGetWindowAttributes (GDK_DISPLAY (), + GDK_WINDOW_XWINDOW (widget->window), + &xattrs); + + XSelectInput (GDK_DISPLAY (), + GDK_WINDOW_XWINDOW(widget->window), + xattrs.your_event_mask | + SubstructureNotifyMask | SubstructureRedirectMask); + + gdk_window_add_filter (widget->window, gtk_socket_filter_func, widget); + + GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); + + /* We sync here so that we make sure that if the XID for + * our window is passed to another application, SubstructureRedirectMask + * will be set by the time the other app creates its window. + */ + gdk_flush(); +} + +static void +gtk_socket_unrealize (GtkWidget *widget) +{ + GtkSocket *socket; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_SOCKET (widget)); + + socket = GTK_SOCKET (widget); + + if (socket->plug_window) + { + GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket)); + if (toplevel && GTK_IS_WINDOW (toplevel)) + gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel), + GDK_WINDOW_XWINDOW (socket->plug_window)); + } + + if (GTK_WIDGET_CLASS (parent_class)->unrealize) + (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); +} + +static void +gtk_socket_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + GtkSocket *socket; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_SOCKET (widget)); + g_return_if_fail (requisition != NULL); + + socket = GTK_SOCKET (widget); + + if (!socket->have_size && socket->plug_window) + { + XSizeHints hints; + long supplied; + + gdk_error_trap_push (); + + if (XGetWMNormalHints (GDK_DISPLAY(), + GDK_WINDOW_XWINDOW (socket->plug_window), + &hints, &supplied)) + { + /* This is obsolete, according the X docs, but many programs + * still use it */ + if (hints.flags & (PSize | USSize)) + { + socket->request_width = hints.width; + socket->request_height = hints.height; + } + else if (hints.flags & PMinSize) + { + socket->request_width = hints.min_width; + socket->request_height = hints.min_height; + } + else if (hints.flags & PBaseSize) + { + socket->request_width = hints.base_width; + socket->request_height = hints.base_height; + } + } + socket->have_size = TRUE; /* don't check again? */ + + gdk_error_trap_pop (); + } + + requisition->width = MAX (socket->request_width, 1); + requisition->height = MAX (socket->request_height, 1); +} + +static void +gtk_socket_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GtkSocket *socket; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_SOCKET (widget)); + g_return_if_fail (allocation != NULL); + + socket = GTK_SOCKET (widget); + + widget->allocation = *allocation; + if (GTK_WIDGET_REALIZED (widget)) + { + gdk_window_move_resize (widget->window, + allocation->x, allocation->y, + allocation->width, allocation->height); + + if (socket->plug_window) + { + gdk_error_trap_push (); + + if (!socket->need_map && + (allocation->width == socket->current_width) && + (allocation->height == socket->current_height)) + { + gtk_socket_send_configure_event (socket); + GTK_NOTE(PLUGSOCKET, + g_message ("GtkSocket - allocated no change: %d %d", + allocation->width, allocation->height)); + } + else + { + gdk_window_move_resize (socket->plug_window, + 0, 0, + allocation->width, allocation->height); + GTK_NOTE(PLUGSOCKET, + g_message ("GtkSocket - allocated: %d %d", + allocation->width, allocation->height)); + socket->current_width = allocation->width; + socket->current_height = allocation->height; + } + + if (socket->need_map) + { + gdk_window_show (socket->plug_window); + socket->need_map = FALSE; + } + + gdk_flush (); + gdk_error_trap_pop (); + } + } +} + +static gint +gtk_socket_focus_in_event (GtkWidget *widget, GdkEventFocus *event) +{ + GtkSocket *socket; + g_return_val_if_fail (GTK_IS_SOCKET (widget), FALSE); + socket = GTK_SOCKET (widget); + + if (socket->focus_in && socket->plug_window) + { + gdk_error_trap_push (); + XSetInputFocus (GDK_DISPLAY (), + GDK_WINDOW_XWINDOW (socket->plug_window), + RevertToParent, GDK_CURRENT_TIME); + gdk_flush(); + gdk_error_trap_pop (); + } + + return TRUE; +} + +static gint +gtk_socket_focus_out_event (GtkWidget *widget, GdkEventFocus *event) +{ + GtkWidget *toplevel; + GtkSocket *socket; + + g_return_val_if_fail (GTK_IS_SOCKET (widget), FALSE); + socket = GTK_SOCKET (widget); + + toplevel = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW); + + if (toplevel) + { + XSetInputFocus (GDK_DISPLAY (), + GDK_WINDOW_XWINDOW (toplevel->window), + RevertToParent, CurrentTime); /* FIXME? */ + } + + socket->focus_in = FALSE; + + return TRUE; +} + +static void +gtk_socket_claim_focus (GtkSocket *socket) +{ + + socket->focus_in = TRUE; + + /* Oh, the trickery... */ + + GTK_WIDGET_SET_FLAGS (socket, GTK_CAN_FOCUS); + gtk_widget_grab_focus (GTK_WIDGET (socket)); + GTK_WIDGET_UNSET_FLAGS (socket, GTK_CAN_FOCUS); + + /* FIXME: we might grab the focus even if we don't have + * it as an app... (and see _focus_in ()) */ + if (socket->plug_window) + { + gdk_error_trap_push (); + XSetInputFocus (GDK_DISPLAY (), + GDK_WINDOW_XWINDOW (socket->plug_window), + RevertToParent, GDK_CURRENT_TIME); + gdk_flush (); + gdk_error_trap_pop (); + } +} + +static gint +gtk_socket_focus (GtkContainer *container, GtkDirectionType direction) +{ + GtkSocket *socket; + + g_return_val_if_fail (GTK_IS_SOCKET (container), FALSE); + + socket = GTK_SOCKET (container); + + if (!socket->focus_in && socket->plug_window) + { + XEvent xevent; + + gtk_socket_claim_focus (socket); + + xevent.xkey.type = KeyPress; + xevent.xkey.display = GDK_DISPLAY (); + xevent.xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window); + xevent.xkey.root = GDK_ROOT_WINDOW (); /* FIXME */ + xevent.xkey.time = GDK_CURRENT_TIME; /* FIXME */ + /* FIXME, the following might cause big problems for + * non-GTK apps */ + xevent.xkey.x = 0; + xevent.xkey.y = 0; + xevent.xkey.x_root = 0; + xevent.xkey.y_root = 0; + xevent.xkey.state = 0; + xevent.xkey.same_screen = TRUE; /* FIXME ? */ + + switch (direction) + { + case GTK_DIR_UP: + xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Up); + break; + case GTK_DIR_DOWN: + xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Down); + break; + case GTK_DIR_LEFT: + xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Left); + break; + case GTK_DIR_RIGHT: + xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Right); + break; + case GTK_DIR_TAB_FORWARD: + xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Tab); + break; + case GTK_DIR_TAB_BACKWARD: + xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Tab); + xevent.xkey.state = ShiftMask; + break; + } + + + gdk_error_trap_push (); + XSendEvent (gdk_display, + GDK_WINDOW_XWINDOW (socket->plug_window), + False, NoEventMask, &xevent); + gdk_flush(); + gdk_error_trap_pop (); + + return TRUE; + } + else + { + return FALSE; + } +} + +static void +gtk_socket_send_configure_event (GtkSocket *socket) +{ + XEvent event; + + g_return_if_fail (socket->plug_window != NULL); + + event.xconfigure.type = ConfigureNotify; + event.xconfigure.display = gdk_display; + + event.xconfigure.event = GDK_WINDOW_XWINDOW (socket->plug_window); + event.xconfigure.window = GDK_WINDOW_XWINDOW (socket->plug_window); + + event.xconfigure.x = 0; + event.xconfigure.y = 0; + event.xconfigure.width = GTK_WIDGET(socket)->allocation.width; + event.xconfigure.height = GTK_WIDGET(socket)->allocation.height; + + event.xconfigure.border_width = 0; + event.xconfigure.above = None; + event.xconfigure.override_redirect = False; + + gdk_error_trap_push (); + XSendEvent (gdk_display, + GDK_WINDOW_XWINDOW (socket->plug_window), + False, NoEventMask, &event); + gdk_flush (); + gdk_error_trap_pop (); +} + +static void +gtk_socket_add_window (GtkSocket *socket, guint32 xid) +{ + socket->plug_window = gdk_window_lookup (xid); + socket->same_app = TRUE; + + if (!socket->plug_window) + { + GtkWidget *toplevel; + GdkDragProtocol protocol; + + socket->plug_window = gdk_window_foreign_new (xid); + if (!socket->plug_window) /* Already gone */ + return; + + socket->same_app = FALSE; + + gdk_error_trap_push (); + XSelectInput (GDK_DISPLAY (), + GDK_WINDOW_XWINDOW(socket->plug_window), + StructureNotifyMask | PropertyChangeMask); + + if (gdk_drag_get_protocol (xid, &protocol)) + gtk_drag_dest_set_proxy (GTK_WIDGET (socket), socket->plug_window, + protocol, TRUE); + gdk_flush (); + gdk_error_trap_pop (); + + gdk_window_add_filter (socket->plug_window, + gtk_socket_filter_func, socket); + + /* Add a pointer to the socket on our toplevel window */ + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket)); + if (toplevel && GTK_IS_WINDOW (toplevel)) + { + gtk_window_add_embedded_xid (GTK_WINDOW (toplevel), xid); + } + } +} + +static GdkFilterReturn +gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) +{ + GtkSocket *socket; + GtkWidget *widget; + XEvent *xevent; + + GdkFilterReturn return_val; + + socket = GTK_SOCKET (data); + widget = GTK_WIDGET (socket); + xevent = (XEvent *)gdk_xevent; + + return_val = GDK_FILTER_CONTINUE; + + switch (xevent->type) + { + case CreateNotify: + { + XCreateWindowEvent *xcwe = &xevent->xcreatewindow; + + if (!socket->plug_window) + { + gtk_socket_add_window (socket, xcwe->window); + + gdk_error_trap_push (); + gdk_window_move_resize(socket->plug_window, + 0, 0, + widget->allocation.width, + widget->allocation.height); + gdk_flush (); + gdk_error_trap_pop (); + + socket->request_width = xcwe->width; + socket->request_height = xcwe->height; + socket->have_size = TRUE; + + GTK_NOTE(PLUGSOCKET, + g_message ("GtkSocket - window created with size: %d %d", + socket->request_width, + socket->request_height)); + + gtk_widget_queue_resize (widget); + } + + return_val = GDK_FILTER_REMOVE; + + break; + } + + case ConfigureRequest: + { + XConfigureRequestEvent *xcre = &xevent->xconfigurerequest; + + if (!socket->plug_window) + gtk_socket_add_window (socket, xcre->window); + + if (xcre->window == GDK_WINDOW_XWINDOW (socket->plug_window)) + { + if (xcre->value_mask & (CWWidth | CWHeight)) + { + socket->request_width = xcre->width; + socket->request_height = xcre->height; + socket->have_size = TRUE; + + GTK_NOTE(PLUGSOCKET, + g_message ("GtkSocket - configure request: %d %d", + socket->request_width, + socket->request_height)); + + gtk_widget_queue_resize (widget); + } + else if (xcre->value_mask & (CWX | CWY)) + { + gtk_socket_send_configure_event (socket); + } + /* Ignore stacking requests. */ + + return_val = GDK_FILTER_REMOVE; + } + break; + } + + case DestroyNotify: + { + XDestroyWindowEvent *xdwe = &xevent->xdestroywindow; + + if (socket->plug_window && + (xdwe->window == GDK_WINDOW_XWINDOW (socket->plug_window))) + { + GtkWidget *toplevel; + + GTK_NOTE(PLUGSOCKET, + g_message ("GtkSocket - destroy notify")); + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket)); + if (toplevel && GTK_IS_WINDOW (toplevel)) + gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel), xdwe->window); + gdk_window_destroy_notify (socket->plug_window); + gtk_widget_destroy (widget); + + socket->plug_window = NULL; + + return_val = GDK_FILTER_REMOVE; + } + break; + } + + case FocusIn: + if (xevent->xfocus.mode == EMBEDDED_APP_WANTS_FOCUS) + { + gtk_socket_claim_focus (socket); + } + else if (xevent->xfocus.detail == NotifyInferior) + { +#if 0 + GtkWidget *toplevel; + toplevel = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW); + + if (toplevel) + { + XSetInputFocus (GDK_DISPLAY (), + GDK_WINDOW_XWINDOW (toplevel->window), + RevertToParent, CurrentTime); /* FIXME? */ + } +#endif + } + return_val = GDK_FILTER_REMOVE; + break; + case FocusOut: + return_val = GDK_FILTER_REMOVE; + break; + case MapRequest: + if (!socket->plug_window) + gtk_socket_add_window (socket, xevent->xmaprequest.window); + + if (xevent->xmaprequest.window == + GDK_WINDOW_XWINDOW (socket->plug_window)) + { + GTK_NOTE(PLUGSOCKET, + g_message ("GtkSocket - Map Request")); + + gdk_error_trap_push (); + gdk_window_show (socket->plug_window); + gdk_flush (); + gdk_error_trap_pop (); + + return_val = GDK_FILTER_REMOVE; + } + break; + case PropertyNotify: + if (xevent->xproperty.window == + GDK_WINDOW_XWINDOW (socket->plug_window)) + { + GdkDragProtocol protocol; + + if ((xevent->xproperty.atom == gdk_atom_intern ("XdndAware", FALSE)) || + (xevent->xproperty.atom == gdk_atom_intern ("_MOTIF_DRAG_RECEIVER_INFO", FALSE))) + { + gdk_error_trap_push (); + if (gdk_drag_get_protocol (xevent->xproperty.window, &protocol)) + gtk_drag_dest_set_proxy (GTK_WIDGET (socket), + socket->plug_window, + protocol, TRUE); + gdk_flush (); + gdk_error_trap_pop (); + } + return_val = GDK_FILTER_REMOVE; + } + } + + return return_val; +} + +#elif defined (GDK_WINDOWING_WIN32) + +GtkType +gtk_socket_get_type (void) +{ + g_error ("GtkSocket not implemented"); + return 0; +} + +GtkWidget* +gtk_socket_new () +{ + g_error ("GtkSocket not implemented"); + return NULL; +} + +void +gtk_socket_steal (GtkSocket *socket, guint32 id) +{ + g_error ("GtkSocket not implemented"); +} + +#endif /* GDK_WINDOWING */ diff --git a/gtk/gtkstyle.c b/gtk/gtkstyle.c new file mode 100644 index 000000000..bc9014863 --- /dev/null +++ b/gtk/gtkstyle.c @@ -0,0 +1,3819 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include <math.h> +#include <string.h> +#include "gtkgc.h" +#include "gtkrc.h" +#include "gtkstyle.h" +#include "gtkwidget.h" +#include "gtkthemes.h" + + +#define LIGHTNESS_MULT 1.3 +#define DARKNESS_MULT 0.7 + +/* actually glib should do that for us */ +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif /* M_PI */ +#ifndef M_PI_4 +#define M_PI_4 0.78539816339744830962 +#endif /* M_PI_4 */ + +static void gtk_style_construct (GtkStyle *style, + GdkColormap *colormap, + gint depth); + +static void gtk_default_draw_hline (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x1, + gint x2, + gint y); +static void gtk_default_draw_vline (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint y1, + gint y2, + gint x); +static void gtk_default_draw_shadow (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height); +static void gtk_default_draw_shadow (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height); +static void gtk_default_draw_polygon (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + GdkPoint *points, + gint npoints, + gboolean fill); +static void gtk_default_draw_arrow (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + GtkArrowType arrow_type, + gboolean fill, + gint x, + gint y, + gint width, + gint height); +static void gtk_default_draw_diamond (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height); +static void gtk_default_draw_oval (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height); +static void gtk_default_draw_string (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + const gchar *string); +static void gtk_default_draw_box (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height); +static void gtk_default_draw_flat_box (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height); +static void gtk_default_draw_check (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height); +static void gtk_default_draw_option (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height); +static void gtk_default_draw_cross (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height); +static void gtk_default_draw_ramp (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + GtkArrowType arrow_type, + gint x, + gint y, + gint width, + gint height); +static void gtk_default_draw_tab (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height); +static void gtk_default_draw_shadow_gap (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkPositionType gap_side, + gint gap_x, + gint gap_width); +static void gtk_default_draw_box_gap (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkPositionType gap_side, + gint gap_x, + gint gap_width); +static void gtk_default_draw_extension (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkPositionType gap_side); +static void gtk_default_draw_focus (GtkStyle *style, + GdkWindow *window, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height); +static void gtk_default_draw_slider (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkOrientation orientation); +static void gtk_default_draw_handle (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkOrientation orientation); + +static void gtk_style_shade (GdkColor *a, GdkColor *b, gdouble k); +static void rgb_to_hls (gdouble *r, gdouble *g, gdouble *b); +static void hls_to_rgb (gdouble *h, gdouble *l, gdouble *s); + +GdkFont *default_font = NULL; + +static GdkColor gtk_default_normal_fg = { 0, 0, 0, 0 }; +static GdkColor gtk_default_active_fg = { 0, 0, 0, 0 }; +static GdkColor gtk_default_prelight_fg = { 0, 0, 0, 0 }; +static GdkColor gtk_default_selected_fg = { 0, 0xffff, 0xffff, 0xffff }; +static GdkColor gtk_default_insensitive_fg = { 0, 0x7530, 0x7530, 0x7530 }; + +static GdkColor gtk_default_normal_bg = { 0, 0xd6d6, 0xd6d6, 0xd6d6 }; +static GdkColor gtk_default_active_bg = { 0, 0xc350, 0xc350, 0xc350 }; +static GdkColor gtk_default_prelight_bg = { 0, 0xea60, 0xea60, 0xea60 }; +static GdkColor gtk_default_selected_bg = { 0, 0, 0, 0x9c40 }; +static GdkColor gtk_default_insensitive_bg = { 0, 0xd6d6, 0xd6d6, 0xd6d6 }; + +static gpointer parent_class = NULL; + +static void gtk_style_init (GtkStyle *style); +static void gtk_style_class_init (GtkStyleClass *klass); +static void gtk_style_finalize (GObject *object); + +GType +gtk_style_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (GtkStyleClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gtk_style_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GtkStyle), + 0, /* n_preallocs */ + (GInstanceInitFunc) gtk_style_init, + }; + + object_type = g_type_register_static (G_TYPE_OBJECT, + "GtkStyle", + &object_info); + } + + return object_type; +} + +static void +gtk_style_init (GtkStyle *style) +{ + gint i; + + style->font_desc = pango_font_description_from_string ("Sans 10"); + + if (!default_font) + { + default_font = gdk_font_from_description (style->font_desc); + + if (!default_font) + default_font = gdk_font_load ("fixed"); + if (!default_font) + g_error ("Unable to load default font."); + } + + style->font = default_font; + gdk_font_ref (style->font); + + style->attach_count = 0; + style->colormap = NULL; + style->depth = -1; + + style->black.red = 0; + style->black.green = 0; + style->black.blue = 0; + + style->white.red = 65535; + style->white.green = 65535; + style->white.blue = 65535; + + style->black_gc = NULL; + style->white_gc = NULL; + + style->fg[GTK_STATE_NORMAL] = gtk_default_normal_fg; + style->fg[GTK_STATE_ACTIVE] = gtk_default_active_fg; + style->fg[GTK_STATE_PRELIGHT] = gtk_default_prelight_fg; + style->fg[GTK_STATE_SELECTED] = gtk_default_selected_fg; + style->fg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_fg; + + style->bg[GTK_STATE_NORMAL] = gtk_default_normal_bg; + style->bg[GTK_STATE_ACTIVE] = gtk_default_active_bg; + style->bg[GTK_STATE_PRELIGHT] = gtk_default_prelight_bg; + style->bg[GTK_STATE_SELECTED] = gtk_default_selected_bg; + style->bg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_bg; + + for (i = 0; i < 4; i++) + { + style->text[i] = style->fg[i]; + style->base[i] = style->white; + } + + style->base[GTK_STATE_INSENSITIVE] = gtk_default_prelight_bg; + style->text[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_fg; + + for (i = 0; i < 5; i++) + style->bg_pixmap[i] = NULL; + + style->engine = NULL; + style->engine_data = NULL; + + style->rc_style = NULL; + + for (i = 0; i < 5; i++) + { + style->fg_gc[i] = NULL; + style->bg_gc[i] = NULL; + style->light_gc[i] = NULL; + style->dark_gc[i] = NULL; + style->mid_gc[i] = NULL; + style->text_gc[i] = NULL; + style->base_gc[i] = NULL; + } + + style->xthickness = 2; + style->ythickness = 2; +} + +static void +gtk_style_class_init (GtkStyleClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = gtk_style_finalize; + + klass->draw_hline = gtk_default_draw_hline; + klass->draw_vline = gtk_default_draw_vline; + klass->draw_shadow = gtk_default_draw_shadow; + klass->draw_polygon = gtk_default_draw_polygon; + klass->draw_arrow = gtk_default_draw_arrow; + klass->draw_diamond = gtk_default_draw_diamond; + klass->draw_oval = gtk_default_draw_oval; + klass->draw_string = gtk_default_draw_string; + klass->draw_box = gtk_default_draw_box; + klass->draw_flat_box = gtk_default_draw_flat_box; + klass->draw_check = gtk_default_draw_check; + klass->draw_option = gtk_default_draw_option; + klass->draw_cross = gtk_default_draw_cross; + klass->draw_ramp = gtk_default_draw_ramp; + klass->draw_tab = gtk_default_draw_tab; + klass->draw_shadow_gap = gtk_default_draw_shadow_gap; + klass->draw_box_gap = gtk_default_draw_box_gap; + klass->draw_extension = gtk_default_draw_extension; + klass->draw_focus = gtk_default_draw_focus; + klass->draw_slider = gtk_default_draw_slider; + klass->draw_handle = gtk_default_draw_handle; +} + +static void +gtk_style_finalize (GObject *object) +{ + GtkStyle *style = GTK_STYLE (object); + + g_return_if_fail (style->attach_count == 0); + + if (style->styles) + { + if (style->styles->data != style) + g_slist_remove (style->styles, style); + else + { + GSList *tmp_list = style->styles->next; + + while (tmp_list) + { + ((GtkStyle*) tmp_list->data)->styles = style->styles->next; + tmp_list = tmp_list->next; + } + g_slist_free_1 (style->styles); + } + } + + if (style->engine) + { + style->engine->destroy_style (style); + gtk_theme_engine_unref (style->engine); + } + + gdk_font_unref (style->font); + pango_font_description_free (style->font_desc); + + if (style->rc_style) + gtk_rc_style_unref (style->rc_style); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + + +GtkStyle* +gtk_style_copy (GtkStyle *style) +{ + GtkStyle *new_style; + guint i; + + g_return_val_if_fail (style != NULL, NULL); + + new_style = gtk_style_new (); + + for (i = 0; i < 5; i++) + { + new_style->fg[i] = style->fg[i]; + new_style->bg[i] = style->bg[i]; + new_style->text[i] = style->text[i]; + new_style->base[i] = style->base[i]; + + new_style->bg_pixmap[i] = style->bg_pixmap[i]; + } + + gdk_font_unref (new_style->font); + new_style->font = style->font; + gdk_font_ref (new_style->font); + + pango_font_description_free (new_style->font_desc); + new_style->font_desc = pango_font_description_copy (style->font_desc); + + if (style->rc_style) + { + new_style->rc_style = style->rc_style; + gtk_rc_style_ref (style->rc_style); + } + + if (style->engine) + { + new_style->engine = style->engine; + gtk_theme_engine_ref (new_style->engine); + new_style->engine->duplicate_style (new_style, style); + } + + return new_style; +} + +static GtkStyle* +gtk_style_duplicate (GtkStyle *style) +{ + GtkStyle *new_style; + + g_return_val_if_fail (style != NULL, NULL); + + new_style = gtk_style_copy (style); + + style->styles = g_slist_append (style->styles, new_style); + new_style->styles = style->styles; + + return new_style; +} + +GtkStyle* +gtk_style_new (void) +{ + GtkStyle *style; + + style = GTK_STYLE (g_type_create_instance (gtk_style_get_type ())); + + return style; +} + +/************************************************************* + * gtk_style_attach: + * Attach a style to a window; this process allocates the + * colors and creates the GC's for the style - it specializes + * it to a particular visual and colormap. The process + * may involve the creation of a new style if the style + * has already been attached to a window with a different + * style and colormap. + * arguments: + * style: + * window: + * results: + * Either the style parameter, or a newly created style. + * If the style is newly created, the style parameter + * will be dereferenced, and the new style will have + * a reference count belonging to the caller. + * + * FIXME: The sequence - + * create a style => s1 + * attach s1 to v1, c1 => s1 + * attach s1 to v2, c2 => s2 + * detach s1 from v1, c1 + * attach s1 to v2, c2 => s3 + * results in two separate, unlinked styles s2 and s3 which + * are identical and could be shared. To fix this, we would + * want to never remove a style from the list of linked + * styles as long as as it has a reference count. However, the + * disadvantage of doing it this way means that we would need two + * passes through the linked list when attaching (one to check for + * matching styles, one to look for empty unattached styles - but + * it will almost never be longer than 2 elements. + *************************************************************/ + +GtkStyle* +gtk_style_attach (GtkStyle *style, + GdkWindow *window) +{ + GSList *styles; + GtkStyle *new_style = NULL; + GdkColormap *colormap; + gint depth; + + g_return_val_if_fail (style != NULL, NULL); + g_return_val_if_fail (window != NULL, NULL); + + colormap = gdk_window_get_colormap (window); + depth = gdk_window_get_visual (window)->depth; + + if (!style->styles) + style->styles = g_slist_append (NULL, style); + + styles = style->styles; + while (styles) + { + new_style = styles->data; + + if (new_style->attach_count == 0) + { + gtk_style_construct (new_style, colormap, depth); + break; + } + else if (new_style->colormap == colormap && + new_style->depth == depth) + break; + + new_style = NULL; + styles = styles->next; + } + + if (!new_style) + { + new_style = gtk_style_duplicate (style); + gtk_style_construct (new_style, colormap, depth); + } + + /* A style gets a refcount from being attached */ + if (new_style->attach_count == 0) + gtk_style_ref (new_style); + + /* Another refcount belongs to the parent */ + if (style != new_style) + { + gtk_style_unref (style); + gtk_style_ref (new_style); + } + + new_style->attach_count++; + + return new_style; +} + +void +gtk_style_detach (GtkStyle *style) +{ + gint i; + + g_return_if_fail (style != NULL); + + style->attach_count -= 1; + if (style->attach_count == 0) + { + if (style->engine) + style->engine->unrealize_style (style); + + gtk_gc_release (style->black_gc); + gtk_gc_release (style->white_gc); + + for (i = 0; i < 5; i++) + { + gtk_gc_release (style->fg_gc[i]); + gtk_gc_release (style->bg_gc[i]); + gtk_gc_release (style->light_gc[i]); + gtk_gc_release (style->dark_gc[i]); + gtk_gc_release (style->mid_gc[i]); + gtk_gc_release (style->text_gc[i]); + gtk_gc_release (style->base_gc[i]); + } + + gtk_style_unref (style); + } +} + +GtkStyle* +gtk_style_ref (GtkStyle *style) +{ + return (GtkStyle *) g_object_ref (G_OBJECT (style)); +} + +void +gtk_style_unref (GtkStyle *style) +{ + g_object_unref (G_OBJECT (style)); +} + +static void +gtk_style_construct (GtkStyle *style, + GdkColormap *colormap, + gint depth) +{ + GdkGCValues gc_values; + GdkGCValuesMask gc_values_mask; + gint i; + + g_return_if_fail (style != NULL); + + style->colormap = colormap; + style->depth = depth; + + for (i = 0; i < 5; i++) + { + gtk_style_shade (&style->bg[i], &style->light[i], LIGHTNESS_MULT); + gtk_style_shade (&style->bg[i], &style->dark[i], DARKNESS_MULT); + + style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2; + style->mid[i].green = (style->light[i].green + style->dark[i].green) / 2; + style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2; + } + + gdk_color_black (colormap, &style->black); + gdk_color_white (colormap, &style->white); + + gc_values_mask = GDK_GC_FOREGROUND | GDK_GC_FONT; + if (style->font->type == GDK_FONT_FONT) + { + gc_values.font = style->font; + } + else if (style->font->type == GDK_FONT_FONTSET) + { + gc_values.font = default_font; + } + + gc_values.foreground = style->black; + style->black_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask); + + gc_values.foreground = style->white; + style->white_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask); + + for (i = 0; i < 5; i++) + { + if (style->rc_style && style->rc_style->bg_pixmap_name[i]) + style->bg_pixmap[i] = gtk_rc_load_image (style->colormap, + &style->bg[i], + style->rc_style->bg_pixmap_name[i]); + + if (!gdk_color_alloc (colormap, &style->fg[i])) + g_warning ("unable to allocate color: ( %d %d %d )", + style->fg[i].red, style->fg[i].green, style->fg[i].blue); + if (!gdk_color_alloc (colormap, &style->bg[i])) + g_warning ("unable to allocate color: ( %d %d %d )", + style->bg[i].red, style->bg[i].green, style->bg[i].blue); + if (!gdk_color_alloc (colormap, &style->light[i])) + g_warning ("unable to allocate color: ( %d %d %d )", + style->light[i].red, style->light[i].green, style->light[i].blue); + if (!gdk_color_alloc (colormap, &style->dark[i])) + g_warning ("unable to allocate color: ( %d %d %d )", + style->dark[i].red, style->dark[i].green, style->dark[i].blue); + if (!gdk_color_alloc (colormap, &style->mid[i])) + g_warning ("unable to allocate color: ( %d %d %d )", + style->mid[i].red, style->mid[i].green, style->mid[i].blue); + if (!gdk_color_alloc (colormap, &style->text[i])) + g_warning ("unable to allocate color: ( %d %d %d )", + style->text[i].red, style->text[i].green, style->text[i].blue); + if (!gdk_color_alloc (colormap, &style->base[i])) + g_warning ("unable to allocate color: ( %d %d %d )", + style->base[i].red, style->base[i].green, style->base[i].blue); + + gc_values.foreground = style->fg[i]; + style->fg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask); + + gc_values.foreground = style->bg[i]; + style->bg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask); + + gc_values.foreground = style->light[i]; + style->light_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask); + + gc_values.foreground = style->dark[i]; + style->dark_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask); + + gc_values.foreground = style->mid[i]; + style->mid_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask); + + gc_values.foreground = style->text[i]; + style->text_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask); + + gc_values.foreground = style->base[i]; + style->base_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask); + } + + if (style->engine) + style->engine->realize_style (style); +} + +void +gtk_draw_hline (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + gint x1, + gint x2, + gint y) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_hline != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_hline (style, window, state_type, NULL, NULL, NULL, x1, x2, y); +} + + +void +gtk_draw_vline (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + gint y1, + gint y2, + gint x) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_vline != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_vline (style, window, state_type, NULL, NULL, NULL, y1, y2, x); +} + + +void +gtk_draw_shadow (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_shadow (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height); +} + +void +gtk_draw_polygon (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkPoint *points, + gint npoints, + gboolean fill) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_polygon != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_polygon (style, window, state_type, shadow_type, NULL, NULL, NULL, points, npoints, fill); +} + +void +gtk_draw_arrow (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GtkArrowType arrow_type, + gboolean fill, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_arrow != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_arrow (style, window, state_type, shadow_type, NULL, NULL, NULL, arrow_type, fill, x, y, width, height); +} + + +void +gtk_draw_diamond (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_diamond != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_diamond (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height); +} + + +void +gtk_draw_oval (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_oval != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_oval (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height); +} + +void +gtk_draw_string (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + gint x, + gint y, + const gchar *string) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_string != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_string (style, window, state_type, NULL, NULL, NULL, x, y, string); +} + +void +gtk_draw_box (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_box (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height); +} + +void +gtk_draw_flat_box (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_flat_box != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_flat_box (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height); +} + +void +gtk_draw_check (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_check != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_check (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height); +} + +void +gtk_draw_option (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_option != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_option (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height); +} + +void +gtk_draw_cross (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_cross != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_cross (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height); +} + +void +gtk_draw_ramp (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GtkArrowType arrow_type, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_ramp != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_ramp (style, window, state_type, shadow_type, NULL, NULL, NULL, arrow_type, x, y, width, height); +} + +void +gtk_draw_tab (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_tab != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_tab (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height); +} + +void +gtk_draw_shadow_gap (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height, + GtkPositionType gap_side, + gint gap_x, + gint gap_width) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow_gap != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_shadow_gap (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, gap_side, gap_x, gap_width); +} + +void +gtk_draw_box_gap (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height, + GtkPositionType gap_side, + gint gap_x, + gint gap_width) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box_gap != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_box_gap (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, gap_side, gap_x, gap_width); +} + +void +gtk_draw_extension (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height, + GtkPositionType gap_side) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_extension != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_extension (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, gap_side); +} + +void +gtk_draw_focus (GtkStyle *style, + GdkWindow *window, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_focus != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_focus (style, window, NULL, NULL, NULL, x, y, width, height); +} + +void +gtk_draw_slider (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height, + GtkOrientation orientation) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_slider != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_slider (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, orientation); +} + +void +gtk_draw_handle (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + gint x, + gint y, + gint width, + gint height, + GtkOrientation orientation) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_handle != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_handle (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, orientation); +} + +void +gtk_style_set_background (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type) +{ + GdkPixmap *pixmap; + gint parent_relative; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + if (style->engine && style->engine->set_background) + { + style->engine->set_background (style, window, state_type); + + return; + } + + if (style->bg_pixmap[state_type]) + { + if (style->bg_pixmap[state_type] == (GdkPixmap*) GDK_PARENT_RELATIVE) + { + pixmap = NULL; + parent_relative = TRUE; + } + else + { + pixmap = style->bg_pixmap[state_type]; + parent_relative = FALSE; + } + + gdk_window_set_back_pixmap (window, pixmap, parent_relative); + } + else + gdk_window_set_background (window, &style->bg[state_type]); +} + + +/* Default functions */ +void +gtk_style_apply_default_background (GtkStyle *style, + GdkWindow *window, + gboolean set_bg, + GtkStateType state_type, + GdkRectangle *area, + gint x, + gint y, + gint width, + gint height) +{ + GdkRectangle new_rect, old_rect; + + if (area) + { + old_rect.x = x; + old_rect.y = y; + old_rect.width = width; + old_rect.height = height; + + if (!gdk_rectangle_intersect (area, &old_rect, &new_rect)) + return; + } + else + { + new_rect.x = x; + new_rect.y = y; + new_rect.width = width; + new_rect.height = height; + } + + if (!style->bg_pixmap[state_type] || + GDK_IS_PIXMAP (window) || + (!set_bg && style->bg_pixmap[state_type] != (GdkPixmap*) GDK_PARENT_RELATIVE)) + { + GdkGC *gc = style->bg_gc[state_type]; + + if (style->bg_pixmap[state_type]) + { + gdk_gc_set_fill (gc, GDK_TILED); + gdk_gc_set_tile (gc, style->bg_pixmap[state_type]); + } + + gdk_draw_rectangle (window, gc, TRUE, + new_rect.x, new_rect.y, new_rect.width, new_rect.height); + if (style->bg_pixmap[state_type]) + gdk_gc_set_fill (gc, GDK_SOLID); + } + else + { + if (set_bg) + { + if (style->bg_pixmap[state_type] == (GdkPixmap*) GDK_PARENT_RELATIVE) + gdk_window_set_back_pixmap (window, NULL, TRUE); + else + gdk_window_set_back_pixmap (window, style->bg_pixmap[state_type], FALSE); + } + + gdk_window_clear_area (window, + new_rect.x, new_rect.y, + new_rect.width, new_rect.height); + } +} + +static void +gtk_default_draw_hline (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x1, + gint x2, + gint y) +{ + gint thickness_light; + gint thickness_dark; + gint i; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + thickness_light = style->ythickness / 2; + thickness_dark = style->ythickness - thickness_light; + + if (area) + { + gdk_gc_set_clip_rectangle (style->light_gc[state_type], area); + gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area); + } + + if (detail && !strcmp (detail, "label")) + { + if (state_type == GTK_STATE_INSENSITIVE) + gdk_draw_line (window, style->white_gc, x1 + 1, y + 1, x2 + 1, y + 1); + gdk_draw_line (window, style->fg_gc[state_type], x1, y, x2, y); + } + else + { + for (i = 0; i < thickness_dark; i++) + { + gdk_draw_line (window, style->light_gc[state_type], x2 - i - 1, y + i, x2, y + i); + gdk_draw_line (window, style->dark_gc[state_type], x1, y + i, x2 - i - 1, y + i); + } + + y += thickness_dark; + for (i = 0; i < thickness_light; i++) + { + gdk_draw_line (window, style->dark_gc[state_type], x1, y + i, x1 + thickness_light - i - 1, y + i); + gdk_draw_line (window, style->light_gc[state_type], x1 + thickness_light - i - 1, y + i, x2, y + i); + } + } + + if (area) + { + gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL); + gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL); + } +} + + +static void +gtk_default_draw_vline (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint y1, + gint y2, + gint x) +{ + gint thickness_light; + gint thickness_dark; + gint i; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + thickness_light = style->xthickness / 2; + thickness_dark = style->xthickness - thickness_light; + + if (area) + { + gdk_gc_set_clip_rectangle (style->light_gc[state_type], area); + gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area); + } + for (i = 0; i < thickness_dark; i++) + { + gdk_draw_line (window, style->light_gc[state_type], x + i, y2 - i - 1, x + i, y2); + gdk_draw_line (window, style->dark_gc[state_type], x + i, y1, x + i, y2 - i - 1); + } + + x += thickness_dark; + for (i = 0; i < thickness_light; i++) + { + gdk_draw_line (window, style->dark_gc[state_type], x + i, y1, x + i, y1 + thickness_light - i); + gdk_draw_line (window, style->light_gc[state_type], x + i, y1 + thickness_light - i, x + i, y2); + } + if (area) + { + gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL); + gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL); + } +} + + +static void +gtk_default_draw_shadow (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + GdkGC *gc1 = NULL; + GdkGC *gc2 = NULL; + gint thickness_light; + gint thickness_dark; + gint i; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + if ((width == -1) && (height == -1)) + gdk_window_get_size (window, &width, &height); + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + switch (shadow_type) + { + case GTK_SHADOW_NONE: + return; + case GTK_SHADOW_IN: + case GTK_SHADOW_ETCHED_IN: + gc1 = style->light_gc[state_type]; + gc2 = style->dark_gc[state_type]; + break; + case GTK_SHADOW_OUT: + case GTK_SHADOW_ETCHED_OUT: + gc1 = style->dark_gc[state_type]; + gc2 = style->light_gc[state_type]; + break; + } + + if (area) + { + gdk_gc_set_clip_rectangle (gc1, area); + gdk_gc_set_clip_rectangle (gc2, area); + if (shadow_type == GTK_SHADOW_IN || + shadow_type == GTK_SHADOW_OUT) + { + gdk_gc_set_clip_rectangle (style->black_gc, area); + gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area); + } + } + + switch (shadow_type) + { + case GTK_SHADOW_NONE: + break; + + case GTK_SHADOW_IN: + gdk_draw_line (window, gc1, + x, y + height - 1, x + width - 1, y + height - 1); + gdk_draw_line (window, gc1, + x + width - 1, y, x + width - 1, y + height - 1); + + gdk_draw_line (window, style->bg_gc[state_type], + x + 1, y + height - 2, x + width - 2, y + height - 2); + gdk_draw_line (window, style->bg_gc[state_type], + x + width - 2, y + 1, x + width - 2, y + height - 2); + + gdk_draw_line (window, style->black_gc, + x + 1, y + 1, x + width - 2, y + 1); + gdk_draw_line (window, style->black_gc, + x + 1, y + 1, x + 1, y + height - 2); + + gdk_draw_line (window, gc2, + x, y, x + width - 1, y); + gdk_draw_line (window, gc2, + x, y, x, y + height - 1); + break; + + case GTK_SHADOW_OUT: + gdk_draw_line (window, gc1, + x + 1, y + height - 2, x + width - 2, y + height - 2); + gdk_draw_line (window, gc1, + x + width - 2, y + 1, x + width - 2, y + height - 2); + + gdk_draw_line (window, gc2, + x, y, x + width - 1, y); + gdk_draw_line (window, gc2, + x, y, x, y + height - 1); + + gdk_draw_line (window, style->bg_gc[state_type], + x + 1, y + 1, x + width - 2, y + 1); + gdk_draw_line (window, style->bg_gc[state_type], + x + 1, y + 1, x + 1, y + height - 2); + + gdk_draw_line (window, style->black_gc, + x, y + height - 1, x + width - 1, y + height - 1); + gdk_draw_line (window, style->black_gc, + x + width - 1, y, x + width - 1, y + height - 1); + break; + + case GTK_SHADOW_ETCHED_IN: + case GTK_SHADOW_ETCHED_OUT: + thickness_light = 1; + thickness_dark = 1; + + for (i = 0; i < thickness_dark; i++) + { + gdk_draw_line (window, gc1, + x + i, + y + height - i - 1, + x + width - i - 1, + y + height - i - 1); + gdk_draw_line (window, gc1, + x + width - i - 1, + y + i, + x + width - i - 1, + y + height - i - 1); + + gdk_draw_line (window, gc2, + x + i, + y + i, + x + width - i - 2, + y + i); + gdk_draw_line (window, gc2, + x + i, + y + i, + x + i, + y + height - i - 2); + } + + for (i = 0; i < thickness_light; i++) + { + gdk_draw_line (window, gc1, + x + thickness_dark + i, + y + thickness_dark + i, + x + width - thickness_dark - i - 1, + y + thickness_dark + i); + gdk_draw_line (window, gc1, + x + thickness_dark + i, + y + thickness_dark + i, + x + thickness_dark + i, + y + height - thickness_dark - i - 1); + + gdk_draw_line (window, gc2, + x + thickness_dark + i, + y + height - thickness_light - i - 1, + x + width - thickness_light - 1, + y + height - thickness_light - i - 1); + gdk_draw_line (window, gc2, + x + width - thickness_light - i - 1, + y + thickness_dark + i, + x + width - thickness_light - i - 1, + y + height - thickness_light - 1); + } + break; + } + if (area) + { + gdk_gc_set_clip_rectangle (gc1, NULL); + gdk_gc_set_clip_rectangle (gc2, NULL); + if (shadow_type == GTK_SHADOW_IN || + shadow_type == GTK_SHADOW_OUT) + { + gdk_gc_set_clip_rectangle (style->black_gc, NULL); + gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL); + } + } +} + +static void +gtk_default_draw_polygon (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + GdkPoint *points, + gint npoints, + gboolean fill) +{ + static const gdouble pi_over_4 = M_PI_4; + static const gdouble pi_3_over_4 = M_PI_4 * 3; + GdkGC *gc1; + GdkGC *gc2; + GdkGC *gc3; + GdkGC *gc4; + gdouble angle; + gint xadjust; + gint yadjust; + gint i; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + g_return_if_fail (points != NULL); + + switch (shadow_type) + { + case GTK_SHADOW_IN: + gc1 = style->bg_gc[state_type]; + gc2 = style->dark_gc[state_type]; + gc3 = style->light_gc[state_type]; + gc4 = style->black_gc; + break; + case GTK_SHADOW_ETCHED_IN: + gc1 = style->light_gc[state_type]; + gc2 = style->dark_gc[state_type]; + gc3 = style->dark_gc[state_type]; + gc4 = style->light_gc[state_type]; + break; + case GTK_SHADOW_OUT: + gc1 = style->dark_gc[state_type]; + gc2 = style->light_gc[state_type]; + gc3 = style->black_gc; + gc4 = style->bg_gc[state_type]; + break; + case GTK_SHADOW_ETCHED_OUT: + gc1 = style->dark_gc[state_type]; + gc2 = style->light_gc[state_type]; + gc3 = style->light_gc[state_type]; + gc4 = style->dark_gc[state_type]; + break; + default: + return; + } + + if (area) + { + gdk_gc_set_clip_rectangle (gc1, area); + gdk_gc_set_clip_rectangle (gc2, area); + gdk_gc_set_clip_rectangle (gc3, area); + gdk_gc_set_clip_rectangle (gc4, area); + } + + if (fill) + gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, npoints); + + npoints--; + + for (i = 0; i < npoints; i++) + { + if ((points[i].x == points[i+1].x) && + (points[i].y == points[i+1].y)) + { + angle = 0; + } + else + { + angle = atan2 (points[i+1].y - points[i].y, + points[i+1].x - points[i].x); + } + + if ((angle > -pi_3_over_4) && (angle < pi_over_4)) + { + if (angle > -pi_over_4) + { + xadjust = 0; + yadjust = 1; + } + else + { + xadjust = 1; + yadjust = 0; + } + + gdk_draw_line (window, gc1, + points[i].x-xadjust, points[i].y-yadjust, + points[i+1].x-xadjust, points[i+1].y-yadjust); + gdk_draw_line (window, gc3, + points[i].x, points[i].y, + points[i+1].x, points[i+1].y); + } + else + { + if ((angle < -pi_3_over_4) || (angle > pi_3_over_4)) + { + xadjust = 0; + yadjust = 1; + } + else + { + xadjust = 1; + yadjust = 0; + } + + gdk_draw_line (window, gc4, + points[i].x+xadjust, points[i].y+yadjust, + points[i+1].x+xadjust, points[i+1].y+yadjust); + gdk_draw_line (window, gc2, + points[i].x, points[i].y, + points[i+1].x, points[i+1].y); + } + } + + if (area) + { + gdk_gc_set_clip_rectangle (gc1, NULL); + gdk_gc_set_clip_rectangle (gc2, NULL); + gdk_gc_set_clip_rectangle (gc3, NULL); + gdk_gc_set_clip_rectangle (gc4, NULL); + } +} + +static void +gtk_default_draw_arrow (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + GtkArrowType arrow_type, + gboolean fill, + gint x, + gint y, + gint width, + gint height) +{ + GdkGC *gc1; + GdkGC *gc2; + GdkGC *gc3; + GdkGC *gc4; + gint half_width; + gint half_height; + GdkPoint points[3]; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + switch (shadow_type) + { + case GTK_SHADOW_IN: + gc1 = style->bg_gc[state_type]; + gc2 = style->dark_gc[state_type]; + gc3 = style->light_gc[state_type]; + gc4 = style->black_gc; + break; + case GTK_SHADOW_OUT: + gc1 = style->dark_gc[state_type]; + gc2 = style->light_gc[state_type]; + gc3 = style->black_gc; + gc4 = style->bg_gc[state_type]; + break; + case GTK_SHADOW_ETCHED_IN: + gc1 = style->light_gc[state_type]; + gc2 = style->dark_gc[state_type]; + gc3 = NULL; + gc4 = NULL; + break; + case GTK_SHADOW_ETCHED_OUT: + gc1 = style->dark_gc[state_type]; + gc2 = style->light_gc[state_type]; + gc3 = NULL; + gc4 = NULL; + break; + default: + return; + } + + if ((width == -1) && (height == -1)) + gdk_window_get_size (window, &width, &height); + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + half_width = width / 2; + half_height = height / 2; + + if (area) + { + gdk_gc_set_clip_rectangle (gc1, area); + gdk_gc_set_clip_rectangle (gc2, area); + if ((gc3) && (gc4)) + { + gdk_gc_set_clip_rectangle (gc3, area); + gdk_gc_set_clip_rectangle (gc4, area); + } + } + + switch (arrow_type) + { + case GTK_ARROW_UP: + if (fill) + { + points[0].x = x + half_width; + points[0].y = y; + points[1].x = x; + points[1].y = y + height - 1; + points[2].x = x + width - 1; + points[2].y = y + height - 1; + + gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, 3); + } + + switch (shadow_type) + { + case GTK_SHADOW_IN: + case GTK_SHADOW_OUT: + + gdk_draw_line (window, gc1, + x + 1, y + height - 2, + x + width - 2, y + height - 2); + gdk_draw_line (window, gc3, + x + 0, y + height - 1, + x + width - 1, y + height - 1); + + gdk_draw_line (window, gc1, + x + width - 2, y + height - 1, + x + half_width, y + 1); + gdk_draw_line (window, gc3, + x + width - 1, y + height - 1, + x + half_width, y); + + gdk_draw_line (window, gc4, + x + half_width, y + 1, + x + 1, y + height - 1); + gdk_draw_line (window, gc2, + x + half_width, y, + x, y + height - 1); + break; + + case GTK_SHADOW_ETCHED_IN: + case GTK_SHADOW_ETCHED_OUT: + gdk_draw_line (window, gc1, + x + half_width, y + 1, + x + 1, y + height - 1); + gdk_draw_line (window, gc1, + x + 1, y + height - 1, + x + width - 1, y + height - 1); + gdk_draw_line (window, gc1, + x + width - 1, y + height - 1, + x + half_width + 1, y + 1); + + points[0].x = x + half_width; + points[0].y = y; + points[1].x = x; + points[1].y = y + height - 2; + points[2].x = x + width - 2; + points[2].y = y + height - 2; + + gdk_draw_polygon (window, gc2, FALSE, points, 3); + break; + + default: + break; + } + break; + + case GTK_ARROW_DOWN: + if (fill) + { + points[0].x = x + width - 1; + points[0].y = y; + points[1].x = x; + points[1].y = y; + points[2].x = x + half_width; + points[2].y = y + height - 1; + + gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, 3); + } + switch (shadow_type) + { + case GTK_SHADOW_IN: + case GTK_SHADOW_OUT: + gdk_draw_line (window, gc4, + x + width - 2, + y + 1, x + 1, y + 1); + gdk_draw_line (window, gc2, + x + width - 1, y, + x, y); + + gdk_draw_line (window, gc4, + x + 1, y, + x + half_width, y + height - 2); + gdk_draw_line (window, gc2, + x, y, + x + half_width, y + height - 1); + + gdk_draw_line (window, gc1, + x + half_width, y + height - 2, + x + width - 2, y); + gdk_draw_line (window, gc3, + x + half_width, y + height - 1, + x + width - 1, y); + break; + + case GTK_SHADOW_ETCHED_IN: + case GTK_SHADOW_ETCHED_OUT: + gdk_draw_line (window, gc1, + x + width - 1, y + 1, + x + 1, y + 1); + gdk_draw_line (window, gc1, + x + 1, y + 1, + x + half_width + 1, y + height - 1); + gdk_draw_line (window, gc1, + x + half_width + 1, y + height - 2, + x + width - 1, y); + + points[0].x = x + width - 2; + points[0].y = y; + points[1].x = x; + points[1].y = y; + points[2].x = x + half_width; + points[2].y = y + height - 2; + + gdk_draw_polygon (window, gc2, FALSE, points, 3); + break; + + default: + break; + } + break; + case GTK_ARROW_LEFT: + if (fill) + { + points[0].x = x; + points[0].y = y + half_height; + points[1].x = x + width - 1; + points[1].y = y + height - 1; + points[2].x = x + width - 1; + points[2].y = y; + + gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, 3); + } + + switch (shadow_type) + { + case GTK_SHADOW_IN: + case GTK_SHADOW_OUT: + gdk_draw_line (window, gc1, + x + 1, y + half_height, + x + width - 1, y + height - 1); + gdk_draw_line (window, gc3, + x, y + half_height, + x + width - 1, y + height - 1); + + gdk_draw_line (window, gc1, + x + width - 2, y + height - 1, + x + width - 2, y + 1); + gdk_draw_line (window, gc3, + x + width - 1, y + height - 1, + x + width - 1, y); + + gdk_draw_line (window, gc4, + x + width - 1, y + 1, + x + 1, y + half_height); + gdk_draw_line (window, gc2, + x + width - 1, y, + x, y + half_height); + break; + + case GTK_SHADOW_ETCHED_IN: + case GTK_SHADOW_ETCHED_OUT: + gdk_draw_line (window, gc1, + x + width - 1, y + 1, + x + 1, y + half_height); + gdk_draw_line (window, gc1, + x + 1, y + half_height + 1, + x + width - 1, y + height - 1); + gdk_draw_line (window, gc1, + x + width - 1, y + height - 1, + x + width - 1, y + 1); + + points[0].x = x + width - 2; + points[0].y = y; + points[1].x = x; + points[1].y = y + half_height; + points[2].x = x + width - 2; + points[2].y = y + height - 2; + + gdk_draw_polygon (window, gc2, FALSE, points, 3); + break; + + default: + break; + } + break; + case GTK_ARROW_RIGHT: + if (fill) + { + points[0].x = x + width - 1; + points[0].y = y + half_height; + points[1].x = x; + points[1].y = y; + points[2].x = x; + points[2].y = y + height - 1; + + gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, 3); + } + + switch (shadow_type) + { + case GTK_SHADOW_IN: + case GTK_SHADOW_OUT: + gdk_draw_line (window, gc4, + x + width - 1, y + half_height, + x + 1, y + 1); + gdk_draw_line (window, gc2, + x + width - 1, y + half_height, + x, y); + gdk_draw_line (window, gc4, + x + 1, y + 1, + x + 1, y + height - 2); + gdk_draw_line (window, gc2, + x, y, + x, y + height - 1); + + gdk_draw_line (window, gc1, + x + 1, y + height - 2, + x + width - 1, y + half_height); + gdk_draw_line (window, gc3, + x, y + height - 1, + x + width - 1, y + half_height); + break; + + case GTK_SHADOW_ETCHED_IN: + case GTK_SHADOW_ETCHED_OUT: + gdk_draw_line (window, gc1, + x + width - 1, y + half_height + 1, + x + 1, y + 1); + gdk_draw_line (window, gc1, + x + 1, y + 1, + x + 1, y + height - 1); + gdk_draw_line (window, gc1, + x + 1, y + height - 1, + x + width - 1, y + half_height + 1); + + points[0].x = x + width - 2; + points[0].y = y + half_height; + points[1].x = x; + points[1].y = y; + points[2].x = x; + points[2].y = y + height - 1; + + gdk_draw_polygon (window, gc2, FALSE, points, 3); + break; + + default: + break; + } + break; + } + + if (area) + { + gdk_gc_set_clip_rectangle (gc1, NULL); + gdk_gc_set_clip_rectangle (gc2, NULL); + if (gc3) + { + gdk_gc_set_clip_rectangle (gc3, NULL); + gdk_gc_set_clip_rectangle (gc4, NULL); + } + } +} + +static void +gtk_default_draw_diamond (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + gint half_width; + gint half_height; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + if ((width == -1) && (height == -1)) + gdk_window_get_size (window, &width, &height); + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + half_width = width / 2; + half_height = height / 2; + + if (area) + { + gdk_gc_set_clip_rectangle (style->light_gc[state_type], area); + gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area); + gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area); + gdk_gc_set_clip_rectangle (style->black_gc, area); + } + switch (shadow_type) + { + case GTK_SHADOW_IN: + gdk_draw_line (window, style->bg_gc[state_type], + x + 2, y + half_height, + x + half_width, y + height - 2); + gdk_draw_line (window, style->bg_gc[state_type], + x + half_width, y + height - 2, + x + width - 2, y + half_height); + gdk_draw_line (window, style->light_gc[state_type], + x + 1, y + half_height, + x + half_width, y + height - 1); + gdk_draw_line (window, style->light_gc[state_type], + x + half_width, y + height - 1, + x + width - 1, y + half_height); + gdk_draw_line (window, style->light_gc[state_type], + x, y + half_height, + x + half_width, y + height); + gdk_draw_line (window, style->light_gc[state_type], + x + half_width, y + height, + x + width, y + half_height); + + gdk_draw_line (window, style->black_gc, + x + 2, y + half_height, + x + half_width, y + 2); + gdk_draw_line (window, style->black_gc, + x + half_width, y + 2, + x + width - 2, y + half_height); + gdk_draw_line (window, style->dark_gc[state_type], + x + 1, y + half_height, + x + half_width, y + 1); + gdk_draw_line (window, style->dark_gc[state_type], + x + half_width, y + 1, + x + width - 1, y + half_height); + gdk_draw_line (window, style->dark_gc[state_type], + x, y + half_height, + x + half_width, y); + gdk_draw_line (window, style->dark_gc[state_type], + x + half_width, y, + x + width, y + half_height); + break; + case GTK_SHADOW_OUT: + gdk_draw_line (window, style->dark_gc[state_type], + x + 2, y + half_height, + x + half_width, y + height - 2); + gdk_draw_line (window, style->dark_gc[state_type], + x + half_width, y + height - 2, + x + width - 2, y + half_height); + gdk_draw_line (window, style->dark_gc[state_type], + x + 1, y + half_height, + x + half_width, y + height - 1); + gdk_draw_line (window, style->dark_gc[state_type], + x + half_width, y + height - 1, + x + width - 1, y + half_height); + gdk_draw_line (window, style->black_gc, + x, y + half_height, + x + half_width, y + height); + gdk_draw_line (window, style->black_gc, + x + half_width, y + height, + x + width, y + half_height); + + gdk_draw_line (window, style->bg_gc[state_type], + x + 2, y + half_height, + x + half_width, y + 2); + gdk_draw_line (window, style->bg_gc[state_type], + x + half_width, y + 2, + x + width - 2, y + half_height); + gdk_draw_line (window, style->light_gc[state_type], + x + 1, y + half_height, + x + half_width, y + 1); + gdk_draw_line (window, style->light_gc[state_type], + x + half_width, y + 1, + x + width - 1, y + half_height); + gdk_draw_line (window, style->light_gc[state_type], + x, y + half_height, + x + half_width, y); + gdk_draw_line (window, style->light_gc[state_type], + x + half_width, y, + x + width, y + half_height); + break; + default: + break; + } + if (area) + { + gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL); + gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL); + gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL); + gdk_gc_set_clip_rectangle (style->black_gc, NULL); + } +} + +static void +gtk_default_draw_oval (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + g_warning ("gtk_default_draw_oval(): FIXME, this function is currently unimplemented"); +} + +static void +gtk_default_draw_string (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + const gchar *string) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + if (area) + { + gdk_gc_set_clip_rectangle (style->white_gc, area); + gdk_gc_set_clip_rectangle (style->fg_gc[state_type], area); + } + + if (state_type == GTK_STATE_INSENSITIVE) + gdk_draw_string (window, style->font, style->white_gc, x + 1, y + 1, string); + + gdk_draw_string (window, style->font, style->fg_gc[state_type], x, y, string); + + if (area) + { + gdk_gc_set_clip_rectangle (style->white_gc, NULL); + gdk_gc_set_clip_rectangle (style->fg_gc[state_type], NULL); + } +} + +static void +gtk_default_draw_box (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + if (width == -1 && height == -1) + gdk_window_get_size (window, &width, &height); + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + if (!style->bg_pixmap[state_type] || + GDK_IS_PIXMAP (window)) + { + if (area) + gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area); + + gdk_draw_rectangle (window, style->bg_gc[state_type], TRUE, + x, y, width, height); + if (area) + gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL); + } + else + gtk_style_apply_default_background (style, window, + widget && !GTK_WIDGET_NO_WINDOW (widget), + state_type, area, x, y, width, height); + + gtk_paint_shadow (style, window, state_type, shadow_type, area, widget, detail, + x, y, width, height); +} + +static void +gtk_default_draw_flat_box (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + GdkGC *gc1; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + if (width == -1 && height == -1) + gdk_window_get_size (window, &width, &height); + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + if (detail) + { + if (!strcmp ("text", detail) && state_type == GTK_STATE_SELECTED) + gc1 = style->bg_gc[GTK_STATE_SELECTED]; + else if (!strcmp ("viewportbin", detail)) + gc1 = style->bg_gc[GTK_STATE_NORMAL]; + else if (!strcmp ("entry_bg", detail)) + gc1 = style->base_gc[state_type]; + else + gc1 = style->bg_gc[state_type]; + } + else + gc1 = style->bg_gc[state_type]; + + if (!style->bg_pixmap[state_type] || gc1 != style->bg_gc[state_type] || + GDK_IS_PIXMAP (window)) + { + if (area) + gdk_gc_set_clip_rectangle (gc1, area); + + gdk_draw_rectangle (window, gc1, TRUE, + x, y, width, height); + + if (detail && !strcmp ("tooltip", detail)) + gdk_draw_rectangle (window, style->black_gc, FALSE, + x, y, width - 1, height - 1); + + if (area) + gdk_gc_set_clip_rectangle (gc1, NULL); + } + else + gtk_style_apply_default_background (style, window, + widget && !GTK_WIDGET_NO_WINDOW (widget), + state_type, area, x, y, width, height); +} + +static void +gtk_default_draw_check (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + gtk_paint_box (style, window, state_type, shadow_type, area, widget, detail, + x, y, width, height); +} + +static void +gtk_default_draw_option (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + gtk_paint_diamond (style, window, state_type, shadow_type, area, widget, + detail, x, y, width, height); +} + +static void +gtk_default_draw_cross (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + g_warning ("gtk_default_draw_cross(): FIXME, this function is currently unimplemented"); +} + +static void +gtk_default_draw_ramp (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + GtkArrowType arrow_type, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + g_warning ("gtk_default_draw_ramp(): FIXME, this function is currently unimplemented"); +} + +static void +gtk_default_draw_tab (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + gtk_paint_box (style, window, state_type, shadow_type, area, widget, detail, + x, y, width, height); +} + +static void +gtk_default_draw_shadow_gap (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkPositionType gap_side, + gint gap_x, + gint gap_width) +{ + GdkGC *gc1 = NULL; + GdkGC *gc2 = NULL; + GdkGC *gc3 = NULL; + GdkGC *gc4 = NULL; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + if (width == -1 && height == -1) + gdk_window_get_size (window, &width, &height); + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + switch (shadow_type) + { + case GTK_SHADOW_NONE: + return; + case GTK_SHADOW_IN: + gc1 = style->dark_gc[state_type]; + gc2 = style->black_gc; + gc3 = style->bg_gc[state_type]; + gc4 = style->light_gc[state_type]; + break; + case GTK_SHADOW_ETCHED_IN: + gc1 = style->dark_gc[state_type]; + gc2 = style->light_gc[state_type]; + gc3 = style->dark_gc[state_type]; + gc4 = style->light_gc[state_type]; + break; + case GTK_SHADOW_OUT: + gc1 = style->light_gc[state_type]; + gc2 = style->bg_gc[state_type]; + gc3 = style->dark_gc[state_type]; + gc4 = style->black_gc; + break; + case GTK_SHADOW_ETCHED_OUT: + gc1 = style->light_gc[state_type]; + gc2 = style->dark_gc[state_type]; + gc3 = style->light_gc[state_type]; + gc4 = style->dark_gc[state_type]; + break; + } + if (area) + { + gdk_gc_set_clip_rectangle (gc1, area); + gdk_gc_set_clip_rectangle (gc2, area); + gdk_gc_set_clip_rectangle (gc3, area); + gdk_gc_set_clip_rectangle (gc4, area); + } + + switch (shadow_type) + { + case GTK_SHADOW_NONE: + case GTK_SHADOW_IN: + case GTK_SHADOW_OUT: + case GTK_SHADOW_ETCHED_IN: + case GTK_SHADOW_ETCHED_OUT: + switch (gap_side) + { + case GTK_POS_TOP: + gdk_draw_line (window, gc1, + x, y, x, y + height - 1); + gdk_draw_line (window, gc2, + x + 1, y, x + 1, y + height - 2); + + gdk_draw_line (window, gc3, + x + 1, y + height - 2, x + width - 2, y + height - 2); + gdk_draw_line (window, gc3, + x + width - 2, y, x + width - 2, y + height - 2); + gdk_draw_line (window, gc4, + x, y + height - 1, x + width - 1, y + height - 1); + gdk_draw_line (window, gc4, + x + width - 1, y, x + width - 1, y + height - 1); + if (gap_x > 0) + { + gdk_draw_line (window, gc1, + x, y, x + gap_x - 1, y); + gdk_draw_line (window, gc2, + x + 1, y + 1, x + gap_x - 1, y + 1); + gdk_draw_line (window, gc2, + x + gap_x, y, x + gap_x, y); + } + if ((width - (gap_x + gap_width)) > 0) + { + gdk_draw_line (window, gc1, + x + gap_x + gap_width, y, x + width - 2, y); + gdk_draw_line (window, gc2, + x + gap_x + gap_width, y + 1, x + width - 2, y + 1); + gdk_draw_line (window, gc2, + x + gap_x + gap_width - 1, y, x + gap_x + gap_width - 1, y); + } + break; + case GTK_POS_BOTTOM: + gdk_draw_line (window, gc1, + x, y, x + width - 1, y); + gdk_draw_line (window, gc1, + x, y, x, y + height - 1); + gdk_draw_line (window, gc2, + x + 1, y + 1, x + width - 2, y + 1); + gdk_draw_line (window, gc2, + x + 1, y + 1, x + 1, y + height - 1); + + gdk_draw_line (window, gc3, + x + width - 2, y + 1, x + width - 2, y + height - 1); + gdk_draw_line (window, gc4, + x + width - 1, y, x + width - 1, y + height - 1); + if (gap_x > 0) + { + gdk_draw_line (window, gc4, + x, y + height - 1, x + gap_x - 1, y + height - 1); + gdk_draw_line (window, gc3, + x + 1, y + height - 2, x + gap_x - 1, y + height - 2); + gdk_draw_line (window, gc3, + x + gap_x, y + height - 1, x + gap_x, y + height - 1); + } + if ((width - (gap_x + gap_width)) > 0) + { + gdk_draw_line (window, gc4, + x + gap_x + gap_width, y + height - 1, x + width - 2, y + height - 1); + gdk_draw_line (window, gc3, + x + gap_x + gap_width, y + height - 2, x + width - 2, y + height - 2); + gdk_draw_line (window, gc3, + x + gap_x + gap_width - 1, y + height - 1, x + gap_x + gap_width - 1, y + height - 1); + } + break; + case GTK_POS_LEFT: + gdk_draw_line (window, gc1, + x, y, x + width - 1, y); + gdk_draw_line (window, gc2, + x, y + 1, x + width - 2, y + 1); + + gdk_draw_line (window, gc3, + x, y + height - 2, x + width - 2, y + height - 2); + gdk_draw_line (window, gc3, + x + width - 2, y + 1, x + width - 2, y + height - 2); + gdk_draw_line (window, gc4, + x, y + height - 1, x + width - 1, y + height - 1); + gdk_draw_line (window, gc4, + x + width - 1, y, x + width - 1, y + height - 1); + if (gap_x > 0) + { + gdk_draw_line (window, gc1, + x, y, x, y + gap_x - 1); + gdk_draw_line (window, gc2, + x + 1, y + 1, x + 1, y + gap_x - 1); + gdk_draw_line (window, gc2, + x, y + gap_x, x, y + gap_x); + } + if ((width - (gap_x + gap_width)) > 0) + { + gdk_draw_line (window, gc1, + x, y + gap_x + gap_width, x, y + height - 2); + gdk_draw_line (window, gc2, + x + 1, y + gap_x + gap_width, x + 1, y + height - 2); + gdk_draw_line (window, gc2, + x, y + gap_x + gap_width - 1, x, y + gap_x + gap_width - 1); + } + break; + case GTK_POS_RIGHT: + gdk_draw_line (window, gc1, + x, y, x + width - 1, y); + gdk_draw_line (window, gc1, + x, y, x, y + height - 1); + gdk_draw_line (window, gc2, + x + 1, y + 1, x + width - 1, y + 1); + gdk_draw_line (window, gc2, + x + 1, y + 1, x + 1, y + height - 2); + + gdk_draw_line (window, gc3, + x + 1, y + height - 2, x + width - 1, y + height - 2); + gdk_draw_line (window, gc4, + x, y + height - 1, x + width - 1, y + height - 1); + if (gap_x > 0) + { + gdk_draw_line (window, gc4, + x + width - 1, y, x + width - 1, y + gap_x - 1); + gdk_draw_line (window, gc3, + x + width - 2, y + 1, x + width - 2, y + gap_x - 1); + gdk_draw_line (window, gc3, + x + width - 1, y + gap_x, x + width - 1, y + gap_x); + } + if ((width - (gap_x + gap_width)) > 0) + { + gdk_draw_line (window, gc4, + x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2); + gdk_draw_line (window, gc3, + x + width - 2, y + gap_x + gap_width, x + width - 2, y + height - 2); + gdk_draw_line (window, gc3, + x + width - 1, y + gap_x + gap_width - 1, x + width - 1, y + gap_x + gap_width - 1); + } + break; + } + } + + if (area) + { + gdk_gc_set_clip_rectangle (gc1, NULL); + gdk_gc_set_clip_rectangle (gc2, NULL); + gdk_gc_set_clip_rectangle (gc3, NULL); + gdk_gc_set_clip_rectangle (gc4, NULL); + } +} + +static void +gtk_default_draw_box_gap (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkPositionType gap_side, + gint gap_x, + gint gap_width) +{ + GdkGC *gc1 = NULL; + GdkGC *gc2 = NULL; + GdkGC *gc3 = NULL; + GdkGC *gc4 = NULL; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + gtk_style_apply_default_background (style, window, + widget && !GTK_WIDGET_NO_WINDOW (widget), + state_type, area, x, y, width, height); + + if (width == -1 && height == -1) + gdk_window_get_size (window, &width, &height); + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + switch (shadow_type) + { + case GTK_SHADOW_NONE: + return; + case GTK_SHADOW_IN: + gc1 = style->dark_gc[state_type]; + gc2 = style->black_gc; + gc3 = style->bg_gc[state_type]; + gc4 = style->light_gc[state_type]; + break; + case GTK_SHADOW_ETCHED_IN: + gc1 = style->dark_gc[state_type]; + gc2 = style->light_gc[state_type]; + gc3 = style->dark_gc[state_type]; + gc4 = style->light_gc[state_type]; + break; + case GTK_SHADOW_OUT: + gc1 = style->light_gc[state_type]; + gc2 = style->bg_gc[state_type]; + gc3 = style->dark_gc[state_type]; + gc4 = style->black_gc; + break; + case GTK_SHADOW_ETCHED_OUT: + gc1 = style->light_gc[state_type]; + gc2 = style->dark_gc[state_type]; + gc3 = style->light_gc[state_type]; + gc4 = style->dark_gc[state_type]; + break; + } + + if (area) + { + gdk_gc_set_clip_rectangle (gc1, area); + gdk_gc_set_clip_rectangle (gc2, area); + gdk_gc_set_clip_rectangle (gc3, area); + gdk_gc_set_clip_rectangle (gc4, area); + } + + switch (shadow_type) + { + case GTK_SHADOW_NONE: + case GTK_SHADOW_IN: + case GTK_SHADOW_OUT: + case GTK_SHADOW_ETCHED_IN: + case GTK_SHADOW_ETCHED_OUT: + switch (gap_side) + { + case GTK_POS_TOP: + gdk_draw_line (window, gc1, + x, y, x, y + height - 1); + gdk_draw_line (window, gc2, + x + 1, y, x + 1, y + height - 2); + + gdk_draw_line (window, gc3, + x + 1, y + height - 2, x + width - 2, y + height - 2); + gdk_draw_line (window, gc3, + x + width - 2, y, x + width - 2, y + height - 2); + gdk_draw_line (window, gc4, + x, y + height - 1, x + width - 1, y + height - 1); + gdk_draw_line (window, gc4, + x + width - 1, y, x + width - 1, y + height - 1); + if (gap_x > 0) + { + gdk_draw_line (window, gc1, + x, y, x + gap_x - 1, y); + gdk_draw_line (window, gc2, + x + 1, y + 1, x + gap_x - 1, y + 1); + gdk_draw_line (window, gc2, + x + gap_x, y, x + gap_x, y); + } + if ((width - (gap_x + gap_width)) > 0) + { + gdk_draw_line (window, gc1, + x + gap_x + gap_width, y, x + width - 2, y); + gdk_draw_line (window, gc2, + x + gap_x + gap_width, y + 1, x + width - 2, y + 1); + gdk_draw_line (window, gc2, + x + gap_x + gap_width - 1, y, x + gap_x + gap_width - 1, y); + } + break; + case GTK_POS_BOTTOM: + gdk_draw_line (window, gc1, + x, y, x + width - 1, y); + gdk_draw_line (window, gc1, + x, y, x, y + height - 1); + gdk_draw_line (window, gc2, + x + 1, y + 1, x + width - 2, y + 1); + gdk_draw_line (window, gc2, + x + 1, y + 1, x + 1, y + height - 1); + + gdk_draw_line (window, gc3, + x + width - 2, y + 1, x + width - 2, y + height - 1); + gdk_draw_line (window, gc4, + x + width - 1, y, x + width - 1, y + height - 1); + if (gap_x > 0) + { + gdk_draw_line (window, gc4, + x, y + height - 1, x + gap_x - 1, y + height - 1); + gdk_draw_line (window, gc3, + x + 1, y + height - 2, x + gap_x - 1, y + height - 2); + gdk_draw_line (window, gc3, + x + gap_x, y + height - 1, x + gap_x, y + height - 1); + } + if ((width - (gap_x + gap_width)) > 0) + { + gdk_draw_line (window, gc4, + x + gap_x + gap_width, y + height - 1, x + width - 2, y + height - 1); + gdk_draw_line (window, gc3, + x + gap_x + gap_width, y + height - 2, x + width - 2, y + height - 2); + gdk_draw_line (window, gc3, + x + gap_x + gap_width - 1, y + height - 1, x + gap_x + gap_width - 1, y + height - 1); + } + break; + case GTK_POS_LEFT: + gdk_draw_line (window, gc1, + x, y, x + width - 1, y); + gdk_draw_line (window, gc2, + x, y + 1, x + width - 2, y + 1); + + gdk_draw_line (window, gc3, + x, y + height - 2, x + width - 2, y + height - 2); + gdk_draw_line (window, gc3, + x + width - 2, y + 1, x + width - 2, y + height - 2); + gdk_draw_line (window, gc4, + x, y + height - 1, x + width - 1, y + height - 1); + gdk_draw_line (window, gc4, + x + width - 1, y, x + width - 1, y + height - 1); + if (gap_x > 0) + { + gdk_draw_line (window, gc1, + x, y, x, y + gap_x - 1); + gdk_draw_line (window, gc2, + x + 1, y + 1, x + 1, y + gap_x - 1); + gdk_draw_line (window, gc2, + x, y + gap_x, x, y + gap_x); + } + if ((width - (gap_x + gap_width)) > 0) + { + gdk_draw_line (window, gc1, + x, y + gap_x + gap_width, x, y + height - 2); + gdk_draw_line (window, gc2, + x + 1, y + gap_x + gap_width, x + 1, y + height - 2); + gdk_draw_line (window, gc2, + x, y + gap_x + gap_width - 1, x, y + gap_x + gap_width - 1); + } + break; + case GTK_POS_RIGHT: + gdk_draw_line (window, gc1, + x, y, x + width - 1, y); + gdk_draw_line (window, gc1, + x, y, x, y + height - 1); + gdk_draw_line (window, gc2, + x + 1, y + 1, x + width - 1, y + 1); + gdk_draw_line (window, gc2, + x + 1, y + 1, x + 1, y + height - 2); + + gdk_draw_line (window, gc3, + x + 1, y + height - 2, x + width - 1, y + height - 2); + gdk_draw_line (window, gc4, + x, y + height - 1, x + width - 1, y + height - 1); + if (gap_x > 0) + { + gdk_draw_line (window, gc4, + x + width - 1, y, x + width - 1, y + gap_x - 1); + gdk_draw_line (window, gc3, + x + width - 2, y + 1, x + width - 2, y + gap_x - 1); + gdk_draw_line (window, gc3, + x + width - 1, y + gap_x, x + width - 1, y + gap_x); + } + if ((width - (gap_x + gap_width)) > 0) + { + gdk_draw_line (window, gc4, + x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2); + gdk_draw_line (window, gc3, + x + width - 2, y + gap_x + gap_width, x + width - 2, y + height - 2); + gdk_draw_line (window, gc3, + x + width - 1, y + gap_x + gap_width - 1, x + width - 1, y + gap_x + gap_width - 1); + } + break; + } + } + + if (area) + { + gdk_gc_set_clip_rectangle (gc1, NULL); + gdk_gc_set_clip_rectangle (gc2, NULL); + gdk_gc_set_clip_rectangle (gc3, NULL); + gdk_gc_set_clip_rectangle (gc4, NULL); + } +} + +static void +gtk_default_draw_extension (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkPositionType gap_side) +{ + GdkGC *gc1 = NULL; + GdkGC *gc2 = NULL; + GdkGC *gc3 = NULL; + GdkGC *gc4 = NULL; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + gtk_style_apply_default_background (style, window, + widget && !GTK_WIDGET_NO_WINDOW (widget), + GTK_STATE_NORMAL, area, x, y, width, height); + + if (width == -1 && height == -1) + gdk_window_get_size (window, &width, &height); + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + switch (shadow_type) + { + case GTK_SHADOW_NONE: + return; + case GTK_SHADOW_IN: + gc1 = style->dark_gc[state_type]; + gc2 = style->black_gc; + gc3 = style->bg_gc[state_type]; + gc4 = style->light_gc[state_type]; + break; + case GTK_SHADOW_ETCHED_IN: + gc1 = style->dark_gc[state_type]; + gc2 = style->light_gc[state_type]; + gc3 = style->dark_gc[state_type]; + gc4 = style->light_gc[state_type]; + break; + case GTK_SHADOW_OUT: + gc1 = style->light_gc[state_type]; + gc2 = style->bg_gc[state_type]; + gc3 = style->dark_gc[state_type]; + gc4 = style->black_gc; + break; + case GTK_SHADOW_ETCHED_OUT: + gc1 = style->light_gc[state_type]; + gc2 = style->dark_gc[state_type]; + gc3 = style->light_gc[state_type]; + gc4 = style->dark_gc[state_type]; + break; + } + + if (area) + { + gdk_gc_set_clip_rectangle (gc1, area); + gdk_gc_set_clip_rectangle (gc2, area); + gdk_gc_set_clip_rectangle (gc3, area); + gdk_gc_set_clip_rectangle (gc4, area); + } + + switch (shadow_type) + { + case GTK_SHADOW_NONE: + case GTK_SHADOW_IN: + case GTK_SHADOW_OUT: + case GTK_SHADOW_ETCHED_IN: + case GTK_SHADOW_ETCHED_OUT: + switch (gap_side) + { + case GTK_POS_TOP: + gtk_style_apply_default_background (style, window, + widget && !GTK_WIDGET_NO_WINDOW (widget), + state_type, area, + x + style->xthickness, + y, + width - (2 * style->xthickness), + height - (style->ythickness)); + gdk_draw_line (window, gc1, + x, y, x, y + height - 2); + gdk_draw_line (window, gc2, + x + 1, y, x + 1, y + height - 2); + + gdk_draw_line (window, gc3, + x + 2, y + height - 2, x + width - 2, y + height - 2); + gdk_draw_line (window, gc3, + x + width - 2, y, x + width - 2, y + height - 2); + gdk_draw_line (window, gc4, + x + 1, y + height - 1, x + width - 2, y + height - 1); + gdk_draw_line (window, gc4, + x + width - 1, y, x + width - 1, y + height - 2); + break; + case GTK_POS_BOTTOM: + gtk_style_apply_default_background (style, window, + widget && !GTK_WIDGET_NO_WINDOW (widget), + state_type, area, + x + style->xthickness, + y + style->ythickness, + width - (2 * style->xthickness), + height - (style->ythickness)); + gdk_draw_line (window, gc1, + x + 1, y, x + width - 2, y); + gdk_draw_line (window, gc1, + x, y + 1, x, y + height - 1); + gdk_draw_line (window, gc2, + x + 1, y + 1, x + width - 2, y + 1); + gdk_draw_line (window, gc2, + x + 1, y + 1, x + 1, y + height - 1); + + gdk_draw_line (window, gc3, + x + width - 2, y + 2, x + width - 2, y + height - 1); + gdk_draw_line (window, gc4, + x + width - 1, y + 1, x + width - 1, y + height - 1); + break; + case GTK_POS_LEFT: + gtk_style_apply_default_background (style, window, + widget && !GTK_WIDGET_NO_WINDOW (widget), + state_type, area, + x, + y + style->ythickness, + width - (style->xthickness), + height - (2 * style->ythickness)); + gdk_draw_line (window, gc1, + x, y, x + width - 2, y); + gdk_draw_line (window, gc2, + x + 1, y + 1, x + width - 2, y + 1); + + gdk_draw_line (window, gc3, + x, y + height - 2, x + width - 2, y + height - 2); + gdk_draw_line (window, gc3, + x + width - 2, y + 2, x + width - 2, y + height - 2); + gdk_draw_line (window, gc4, + x, y + height - 1, x + width - 2, y + height - 1); + gdk_draw_line (window, gc4, + x + width - 1, y + 1, x + width - 1, y + height - 2); + break; + case GTK_POS_RIGHT: + gtk_style_apply_default_background (style, window, + widget && !GTK_WIDGET_NO_WINDOW (widget), + state_type, area, + x + style->xthickness, + y + style->ythickness, + width - (style->xthickness), + height - (2 * style->ythickness)); + gdk_draw_line (window, gc1, + x + 1, y, x + width - 1, y); + gdk_draw_line (window, gc1, + x, y + 1, x, y + height - 2); + gdk_draw_line (window, gc2, + x + 1, y + 1, x + width - 1, y + 1); + gdk_draw_line (window, gc2, + x + 1, y + 1, x + 1, y + height - 2); + + gdk_draw_line (window, gc3, + x + 2, y + height - 2, x + width - 1, y + height - 2); + gdk_draw_line (window, gc4, + x + 1, y + height - 1, x + width - 1, y + height - 1); + break; + } + } + + if (area) + { + gdk_gc_set_clip_rectangle (gc1, NULL); + gdk_gc_set_clip_rectangle (gc2, NULL); + gdk_gc_set_clip_rectangle (gc3, NULL); + gdk_gc_set_clip_rectangle (gc4, NULL); + } +} + +static void +gtk_default_draw_focus (GtkStyle *style, + GdkWindow *window, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + if (width == -1 && height == -1) + { + gdk_window_get_size (window, &width, &height); + width -= 1; + height -= 1; + } + else if (width == -1) + { + gdk_window_get_size (window, &width, NULL); + width -= 1; + } + else if (height == -1) + { + gdk_window_get_size (window, NULL, &height); + height -= 1; + } + + if (area) + gdk_gc_set_clip_rectangle (style->black_gc, area); + + if (detail && !strcmp (detail, "add-mode")) + { + gdk_gc_set_line_attributes (style->black_gc, 1, GDK_LINE_ON_OFF_DASH, 0, 0); + gdk_gc_set_dashes (style->black_gc, 0, "\4\4", 2); + + gdk_draw_rectangle (window, + style->black_gc, FALSE, + x, y, width, height); + + gdk_gc_set_line_attributes (style->black_gc, 1, GDK_LINE_SOLID, 0, 0); + } + else + { + gdk_draw_rectangle (window, + style->black_gc, FALSE, + x, y, width, height); + } + + if (area) + gdk_gc_set_clip_rectangle (style->black_gc, NULL); +} + +static void +gtk_default_draw_slider (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkOrientation orientation) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + if (width == -1 && height == -1) + gdk_window_get_size (window, &width, &height); + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + gtk_paint_box (style, window, state_type, shadow_type, + area, widget, detail, x, y, width, height); + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + gtk_paint_vline (style, window, state_type, area, widget, detail, + style->ythickness, + height - style->ythickness - 1, width / 2); + else + gtk_paint_hline (style, window, state_type, area, widget, detail, + style->xthickness, + width - style->xthickness - 1, height / 2); +} + +static void +draw_dot (GdkWindow *window, + GdkGC *light_gc, + GdkGC *dark_gc, + gint x, + gint y, + gushort size) +{ + + size = CLAMP (size, 2, 3); + + if (size == 2) + { + gdk_draw_point (window, light_gc, x, y); + gdk_draw_point (window, light_gc, x+1, y+1); + } + else if (size == 3); + { + gdk_draw_point (window, light_gc, x, y); + gdk_draw_point (window, light_gc, x+1, y); + gdk_draw_point (window, light_gc, x, y+1); + gdk_draw_point (window, dark_gc, x+1, y+2); + gdk_draw_point (window, dark_gc, x+2, y+1); + gdk_draw_point (window, dark_gc, x+2, y+2); + } +} + +static void +gtk_default_draw_handle (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkOrientation orientation) +{ + gint xx, yy; + gint xthick, ythick; + GdkGC *light_gc, *dark_gc; + GdkRectangle rect; + GdkRectangle dest; + gint intersect; + + g_return_if_fail (style != NULL); + g_return_if_fail (window != NULL); + + if (width == -1 && height == -1) + gdk_window_get_size (window, &width, &height); + else if (width == -1) + gdk_window_get_size (window, &width, NULL); + else if (height == -1) + gdk_window_get_size (window, NULL, &height); + + gtk_paint_box (style, window, state_type, shadow_type, area, widget, + detail, x, y, width, height); + + + if (!strcmp (detail, "paned")) + { + /* we want to ignore the shadow border in paned widgets */ + xthick = 0; + ythick = 0; + + light_gc = style->light_gc[state_type]; + dark_gc = style->black_gc; + } + else + { + xthick = style->xthickness; + ythick = style->ythickness; + + light_gc = style->light_gc[state_type]; + dark_gc = style->dark_gc[state_type]; + } + + rect.x = x + xthick; + rect.y = y + ythick; + rect.width = width - (xthick * 2); + rect.height = height - (ythick * 2); + + if (area) + intersect = gdk_rectangle_intersect (area, &rect, &dest); + else + { + intersect = TRUE; + dest = rect; + } + + if (!intersect) + return; + + gdk_gc_set_clip_rectangle (light_gc, &dest); + gdk_gc_set_clip_rectangle (dark_gc, &dest); + + if (!strcmp (detail, "paned")) + { + gint window_width; + gint window_height; + + gdk_window_get_size (window, &window_width, &window_height); + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + for (xx = window_width/2 - 15; xx <= window_width/2 + 15; xx += 5) + draw_dot (window, light_gc, dark_gc, xx, window_height/2 - 1, 3); + else + for (yy = window_height/2 - 15; yy <= window_height/2 + 15; yy += 5) + draw_dot (window, light_gc, dark_gc, window_width/2 - 1, yy, 3); + } + else + { + for (yy = y + ythick; yy < (y + height - ythick); yy += 3) + for (xx = x + xthick; xx < (x + width - xthick); xx += 6) + { + draw_dot (window, light_gc, dark_gc, xx, yy, 2); + draw_dot (window, light_gc, dark_gc, xx + 3, yy + 1, 2); + } + } + + gdk_gc_set_clip_rectangle (light_gc, NULL); + gdk_gc_set_clip_rectangle (dark_gc, NULL); +} + +static void +gtk_style_shade (GdkColor *a, + GdkColor *b, + gdouble k) +{ + gdouble red; + gdouble green; + gdouble blue; + + red = (gdouble) a->red / 65535.0; + green = (gdouble) a->green / 65535.0; + blue = (gdouble) a->blue / 65535.0; + + rgb_to_hls (&red, &green, &blue); + + green *= k; + if (green > 1.0) + green = 1.0; + else if (green < 0.0) + green = 0.0; + + blue *= k; + if (blue > 1.0) + blue = 1.0; + else if (blue < 0.0) + blue = 0.0; + + hls_to_rgb (&red, &green, &blue); + + b->red = red * 65535.0; + b->green = green * 65535.0; + b->blue = blue * 65535.0; +} + +static void +rgb_to_hls (gdouble *r, + gdouble *g, + gdouble *b) +{ + gdouble min; + gdouble max; + gdouble red; + gdouble green; + gdouble blue; + gdouble h, l, s; + gdouble delta; + + red = *r; + green = *g; + blue = *b; + + if (red > green) + { + if (red > blue) + max = red; + else + max = blue; + + if (green < blue) + min = green; + else + min = blue; + } + else + { + if (green > blue) + max = green; + else + max = blue; + + if (red < blue) + min = red; + else + min = blue; + } + + l = (max + min) / 2; + s = 0; + h = 0; + + if (max != min) + { + if (l <= 0.5) + s = (max - min) / (max + min); + else + s = (max - min) / (2 - max - min); + + delta = max -min; + if (red == max) + h = (green - blue) / delta; + else if (green == max) + h = 2 + (blue - red) / delta; + else if (blue == max) + h = 4 + (red - green) / delta; + + h *= 60; + if (h < 0.0) + h += 360; + } + + *r = h; + *g = l; + *b = s; +} + +static void +hls_to_rgb (gdouble *h, + gdouble *l, + gdouble *s) +{ + gdouble hue; + gdouble lightness; + gdouble saturation; + gdouble m1, m2; + gdouble r, g, b; + + lightness = *l; + saturation = *s; + + if (lightness <= 0.5) + m2 = lightness * (1 + saturation); + else + m2 = lightness + saturation - lightness * saturation; + m1 = 2 * lightness - m2; + + if (saturation == 0) + { + *h = lightness; + *l = lightness; + *s = lightness; + } + else + { + hue = *h + 120; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + r = m1 + (m2 - m1) * hue / 60; + else if (hue < 180) + r = m2; + else if (hue < 240) + r = m1 + (m2 - m1) * (240 - hue) / 60; + else + r = m1; + + hue = *h; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + g = m1 + (m2 - m1) * hue / 60; + else if (hue < 180) + g = m2; + else if (hue < 240) + g = m1 + (m2 - m1) * (240 - hue) / 60; + else + g = m1; + + hue = *h - 120; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + b = m1 + (m2 - m1) * hue / 60; + else if (hue < 180) + b = m2; + else if (hue < 240) + b = m1 + (m2 - m1) * (240 - hue) / 60; + else + b = m1; + + *h = r; + *l = g; + *s = b; + } +} + +void +gtk_paint_hline (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x1, + gint x2, + gint y) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_hline != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_hline (style, window, state_type, area, widget, detail, x1, x2, y); +} + +void +gtk_paint_vline (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint y1, + gint y2, + gint x) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_vline != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_vline (style, window, state_type, area, widget, detail, y1, y2, x); +} + +void +gtk_paint_shadow (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_shadow (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); +} + +void +gtk_paint_polygon (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + GdkPoint *points, + gint npoints, + gboolean fill) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_polygon (style, window, state_type, shadow_type, area, widget, detail, points, npoints, fill); +} + +void +gtk_paint_arrow (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + GtkArrowType arrow_type, + gboolean fill, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_arrow != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_arrow (style, window, state_type, shadow_type, area, widget, detail, arrow_type, fill, x, y, width, height); +} + +void +gtk_paint_diamond (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_diamond != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_diamond (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); +} + +void +gtk_paint_oval (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_oval != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_oval (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); +} + +void +gtk_paint_string (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + const gchar *string) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_string != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_string (style, window, state_type, area, widget, detail, x, y, string); +} + +void +gtk_paint_box (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_box (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); +} + +void +gtk_paint_flat_box (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_flat_box != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_flat_box (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); +} + +void +gtk_paint_check (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_check != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_check (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); +} + +void +gtk_paint_option (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_option != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_option (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); +} + +void +gtk_paint_cross (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_cross != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_cross (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); +} + +void +gtk_paint_ramp (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + GtkArrowType arrow_type, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_ramp != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_ramp (style, window, state_type, shadow_type, area, widget, detail, arrow_type, x, y, width, height); +} + +void +gtk_paint_tab (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_tab != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_tab (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height); +} + +void +gtk_paint_shadow_gap (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkPositionType gap_side, + gint gap_x, + gint gap_width) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow_gap != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_shadow_gap (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, gap_side, gap_x, gap_width); +} + + +void +gtk_paint_box_gap (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkPositionType gap_side, + gint gap_x, + gint gap_width) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box_gap != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_box_gap (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, gap_side, gap_x, gap_width); +} + +void +gtk_paint_extension (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkPositionType gap_side) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_extension != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_extension (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, gap_side); +} + +void +gtk_paint_focus (GtkStyle *style, + GdkWindow *window, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_focus != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_focus (style, window, area, widget, detail, x, y, width, height); +} + +void +gtk_paint_slider (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkOrientation orientation) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_slider != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_slider (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, orientation); +} + +void +gtk_paint_handle (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkOrientation orientation) +{ + g_return_if_fail (style != NULL); + g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_handle != NULL); + + GTK_STYLE_GET_CLASS (style)->draw_handle (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, orientation); +} diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c new file mode 100644 index 000000000..76dca3565 --- /dev/null +++ b/gtk/gtkwidget.c @@ -0,0 +1,4648 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include <stdarg.h> +#include <string.h> +#include <locale.h> +#include "gtkcontainer.h" +#include "gtkmain.h" +#include "gtkrc.h" +#include "gtkselection.h" +#include "gtksignal.h" +#include "gtkwidget.h" +#include "gtkwindow.h" +#include "gtkbindings.h" +#include "gtkprivate.h" +#include "gdk/gdk.h" +#include "gdk/gdkprivate.h" /* Used in gtk_reset_shapes_recurse to avoid copy */ + + +#define WIDGET_CLASS(w) GTK_WIDGET_GET_CLASS (w) +#define INIT_PATH_SIZE (512) + + +enum { + SHOW, + HIDE, + MAP, + UNMAP, + REALIZE, + UNREALIZE, + DRAW, + DRAW_FOCUS, + DRAW_DEFAULT, + SIZE_REQUEST, + SIZE_ALLOCATE, + STATE_CHANGED, + PARENT_SET, + STYLE_SET, + ADD_ACCELERATOR, + REMOVE_ACCELERATOR, + GRAB_FOCUS, + EVENT, + BUTTON_PRESS_EVENT, + BUTTON_RELEASE_EVENT, + SCROLL_EVENT, + MOTION_NOTIFY_EVENT, + DELETE_EVENT, + DESTROY_EVENT, + EXPOSE_EVENT, + KEY_PRESS_EVENT, + KEY_RELEASE_EVENT, + ENTER_NOTIFY_EVENT, + LEAVE_NOTIFY_EVENT, + CONFIGURE_EVENT, + FOCUS_IN_EVENT, + FOCUS_OUT_EVENT, + MAP_EVENT, + UNMAP_EVENT, + PROPERTY_NOTIFY_EVENT, + SELECTION_CLEAR_EVENT, + SELECTION_REQUEST_EVENT, + SELECTION_NOTIFY_EVENT, + SELECTION_GET, + SELECTION_RECEIVED, + PROXIMITY_IN_EVENT, + PROXIMITY_OUT_EVENT, + DRAG_BEGIN, + DRAG_END, + DRAG_DATA_DELETE, + DRAG_LEAVE, + DRAG_MOTION, + DRAG_DROP, + DRAG_DATA_GET, + DRAG_DATA_RECEIVED, + CLIENT_EVENT, + NO_EXPOSE_EVENT, + VISIBILITY_NOTIFY_EVENT, + DEBUG_MSG, + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_NAME, + ARG_PARENT, + ARG_X, + ARG_Y, + ARG_WIDTH, + ARG_HEIGHT, + ARG_VISIBLE, + ARG_SENSITIVE, + ARG_APP_PAINTABLE, + ARG_CAN_FOCUS, + ARG_HAS_FOCUS, + ARG_CAN_DEFAULT, + ARG_HAS_DEFAULT, + ARG_RECEIVES_DEFAULT, + ARG_COMPOSITE_CHILD, + ARG_STYLE, + ARG_EVENTS, + ARG_EXTENSION_EVENTS +}; + +typedef struct _GtkStateData GtkStateData; + +struct _GtkStateData +{ + GtkStateType state; + guint state_restoration : 1; + guint parent_sensitive : 1; + guint use_forall : 1; +}; + +static void gtk_widget_class_init (GtkWidgetClass *klass); +static void gtk_widget_init (GtkWidget *widget); +static void gtk_widget_set_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); +static void gtk_widget_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); +static void gtk_widget_shutdown (GObject *object); +static void gtk_widget_real_destroy (GtkObject *object); +static void gtk_widget_finalize (GObject *object); +static void gtk_widget_real_show (GtkWidget *widget); +static void gtk_widget_real_hide (GtkWidget *widget); +static void gtk_widget_real_map (GtkWidget *widget); +static void gtk_widget_real_unmap (GtkWidget *widget); +static void gtk_widget_real_realize (GtkWidget *widget); +static void gtk_widget_real_unrealize (GtkWidget *widget); +static void gtk_widget_real_draw (GtkWidget *widget, + GdkRectangle *area); +static void gtk_widget_real_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void gtk_widget_real_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static gint gtk_widget_real_key_press_event (GtkWidget *widget, + GdkEventKey *event); +static gint gtk_widget_real_key_release_event (GtkWidget *widget, + GdkEventKey *event); +static void gtk_widget_style_set (GtkWidget *widget, + GtkStyle *previous_style); +static void gtk_widget_real_grab_focus (GtkWidget *focus_widget); + +static GdkColormap* gtk_widget_peek_colormap (void); +static GdkVisual* gtk_widget_peek_visual (void); +static GtkStyle* gtk_widget_peek_style (void); + +static void gtk_widget_reparent_container_child (GtkWidget *widget, + gpointer client_data); +static void gtk_widget_propagate_state (GtkWidget *widget, + GtkStateData *data); +static void gtk_widget_set_style_internal (GtkWidget *widget, + GtkStyle *style, + gboolean initial_emission); +static void gtk_widget_set_style_recurse (GtkWidget *widget, + gpointer client_data); + +static GtkWidgetAuxInfo* gtk_widget_aux_info_new (void); +static void gtk_widget_aux_info_destroy (GtkWidgetAuxInfo *aux_info); + +static gpointer parent_class = NULL; +static guint widget_signals[LAST_SIGNAL] = { 0 }; + +static GMemChunk *aux_info_mem_chunk = NULL; + +static GdkColormap *default_colormap = NULL; +static GdkVisual *default_visual = NULL; +static GtkStyle *gtk_default_style = NULL; + +static GSList *colormap_stack = NULL; +static GSList *visual_stack = NULL; +static GSList *style_stack = NULL; +static guint composite_child_stack = 0; + +static const gchar *aux_info_key = "gtk-aux-info"; +static guint aux_info_key_id = 0; +static const gchar *event_key = "gtk-event-mask"; +static guint event_key_id = 0; +static const gchar *extension_event_key = "gtk-extension-event-mode"; +static guint extension_event_key_id = 0; +static const gchar *parent_window_key = "gtk-parent-window"; +static guint parent_window_key_id = 0; +static const gchar *saved_default_style_key = "gtk-saved-default-style"; +static guint saved_default_style_key_id = 0; +static const gchar *shape_info_key = "gtk-shape-info"; +static const gchar *colormap_key = "gtk-colormap"; +static const gchar *visual_key = "gtk-visual"; + +static const gchar *rc_style_key = "gtk-rc-style"; +static guint rc_style_key_id = 0; + +static GtkTextDirection gtk_default_direction = GTK_TEXT_DIR_LTR; + +/***************************************** + * gtk_widget_get_type: + * + * arguments: + * + * results: + *****************************************/ + +GtkType +gtk_widget_get_type (void) +{ + static GtkType widget_type = 0; + + if (!widget_type) + { + static const GtkTypeInfo widget_info = + { + "GtkWidget", + sizeof (GtkWidget), + sizeof (GtkWidgetClass), + (GtkClassInitFunc) gtk_widget_class_init, + (GtkObjectInitFunc) gtk_widget_init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + widget_type = gtk_type_unique (GTK_TYPE_OBJECT, &widget_info); + } + + return widget_type; +} + +/***************************************** + * gtk_widget_class_init: + * + * arguments: + * + * results: + *****************************************/ +#include "stdio.h" +static void +gtk_widget_debug_msg (GtkWidget *widget, + const gchar *string) +{ + fprintf (stderr, "Gtk-DEBUG: %s\n", string); +} + +static void +gtk_widget_class_init (GtkWidgetClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); + + parent_class = gtk_type_class (GTK_TYPE_OBJECT); + + gobject_class->shutdown = gtk_widget_shutdown; + gobject_class->finalize = gtk_widget_finalize; + + object_class->set_arg = gtk_widget_set_arg; + object_class->get_arg = gtk_widget_get_arg; + object_class->destroy = gtk_widget_real_destroy; + + klass->activate_signal = 0; + klass->set_scroll_adjustments_signal = 0; + klass->show = gtk_widget_real_show; + klass->show_all = gtk_widget_show; + klass->hide = gtk_widget_real_hide; + klass->hide_all = gtk_widget_hide; + klass->map = gtk_widget_real_map; + klass->unmap = gtk_widget_real_unmap; + klass->realize = gtk_widget_real_realize; + klass->unrealize = gtk_widget_real_unrealize; + klass->draw = gtk_widget_real_draw; + klass->draw_focus = NULL; + klass->size_request = gtk_widget_real_size_request; + klass->size_allocate = gtk_widget_real_size_allocate; + klass->state_changed = NULL; + klass->parent_set = NULL; + klass->style_set = gtk_widget_style_set; + klass->add_accelerator = (void*) gtk_accel_group_handle_add; + klass->remove_accelerator = (void*) gtk_accel_group_handle_remove; + klass->grab_focus = gtk_widget_real_grab_focus; + klass->event = NULL; + klass->button_press_event = NULL; + klass->button_release_event = NULL; + klass->motion_notify_event = NULL; + klass->delete_event = NULL; + klass->destroy_event = NULL; + klass->expose_event = NULL; + klass->key_press_event = gtk_widget_real_key_press_event; + klass->key_release_event = gtk_widget_real_key_release_event; + klass->enter_notify_event = NULL; + klass->leave_notify_event = NULL; + klass->configure_event = NULL; + klass->focus_in_event = NULL; + klass->focus_out_event = NULL; + klass->map_event = NULL; + klass->unmap_event = NULL; + klass->property_notify_event = gtk_selection_property_notify; + klass->selection_clear_event = gtk_selection_clear; + klass->selection_request_event = gtk_selection_request; + klass->selection_notify_event = gtk_selection_notify; + klass->selection_received = NULL; + klass->proximity_in_event = NULL; + klass->proximity_out_event = NULL; + klass->drag_begin = NULL; + klass->drag_end = NULL; + klass->drag_data_delete = NULL; + klass->drag_leave = NULL; + klass->drag_motion = NULL; + klass->drag_drop = NULL; + klass->drag_data_received = NULL; + + klass->no_expose_event = NULL; + + klass->debug_msg = gtk_widget_debug_msg; + + gtk_object_add_arg_type ("GtkWidget::name", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_NAME); + gtk_object_add_arg_type ("GtkWidget::parent", GTK_TYPE_CONTAINER, GTK_ARG_READWRITE, ARG_PARENT); + gtk_object_add_arg_type ("GtkWidget::x", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_X); + gtk_object_add_arg_type ("GtkWidget::y", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_Y); + gtk_object_add_arg_type ("GtkWidget::width", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_WIDTH); + gtk_object_add_arg_type ("GtkWidget::height", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_HEIGHT); + gtk_object_add_arg_type ("GtkWidget::visible", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_VISIBLE); + gtk_object_add_arg_type ("GtkWidget::sensitive", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SENSITIVE); + gtk_object_add_arg_type ("GtkWidget::app_paintable", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_APP_PAINTABLE); + gtk_object_add_arg_type ("GtkWidget::can_focus", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_CAN_FOCUS); + gtk_object_add_arg_type ("GtkWidget::has_focus", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_HAS_FOCUS); + gtk_object_add_arg_type ("GtkWidget::can_default", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_CAN_DEFAULT); + gtk_object_add_arg_type ("GtkWidget::has_default", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_HAS_DEFAULT); + gtk_object_add_arg_type ("GtkWidget::receives_default", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_RECEIVES_DEFAULT); + gtk_object_add_arg_type ("GtkWidget::composite_child", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_COMPOSITE_CHILD); + gtk_object_add_arg_type ("GtkWidget::style", GTK_TYPE_STYLE, GTK_ARG_READWRITE, ARG_STYLE); + gtk_object_add_arg_type ("GtkWidget::events", GTK_TYPE_GDK_EVENT_MASK, GTK_ARG_READWRITE, ARG_EVENTS); + gtk_object_add_arg_type ("GtkWidget::extension_events", GTK_TYPE_GDK_EVENT_MASK, GTK_ARG_READWRITE, ARG_EXTENSION_EVENTS); + + widget_signals[SHOW] = + gtk_signal_new ("show", + GTK_RUN_FIRST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, show), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + widget_signals[HIDE] = + gtk_signal_new ("hide", + GTK_RUN_FIRST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, hide), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + widget_signals[MAP] = + gtk_signal_new ("map", + GTK_RUN_FIRST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, map), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + widget_signals[UNMAP] = + gtk_signal_new ("unmap", + GTK_RUN_FIRST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, unmap), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + widget_signals[REALIZE] = + gtk_signal_new ("realize", + GTK_RUN_FIRST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, realize), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + widget_signals[UNREALIZE] = + gtk_signal_new ("unrealize", + GTK_RUN_FIRST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, unrealize), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + widget_signals[DRAW] = + gtk_signal_new ("draw", + GTK_RUN_FIRST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, draw), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, + GTK_TYPE_POINTER); + widget_signals[DRAW_FOCUS] = + gtk_signal_new ("draw_focus", + GTK_RUN_FIRST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, draw_focus), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + widget_signals[DRAW_DEFAULT] = + gtk_signal_new ("draw_default", + GTK_RUN_FIRST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, draw_default), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + widget_signals[SIZE_REQUEST] = + gtk_signal_new ("size_request", + GTK_RUN_FIRST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, size_request), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, + GTK_TYPE_POINTER); + widget_signals[SIZE_ALLOCATE] = + gtk_signal_new ("size_allocate", + GTK_RUN_FIRST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, size_allocate), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, + GTK_TYPE_POINTER); + widget_signals[STATE_CHANGED] = + gtk_signal_new ("state_changed", + GTK_RUN_FIRST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, state_changed), + gtk_marshal_NONE__UINT, + GTK_TYPE_NONE, 1, + GTK_TYPE_STATE_TYPE); + widget_signals[PARENT_SET] = + gtk_signal_new ("parent_set", + GTK_RUN_FIRST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, parent_set), + gtk_marshal_NONE__OBJECT, + GTK_TYPE_NONE, 1, + GTK_TYPE_OBJECT); + widget_signals[STYLE_SET] = + gtk_signal_new ("style_set", + GTK_RUN_FIRST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, style_set), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, + GTK_TYPE_STYLE); + widget_signals[ADD_ACCELERATOR] = + gtk_accel_group_create_add (GTK_CLASS_TYPE (object_class), GTK_RUN_LAST, + GTK_SIGNAL_OFFSET (GtkWidgetClass, add_accelerator)); + widget_signals[REMOVE_ACCELERATOR] = + gtk_accel_group_create_remove (GTK_CLASS_TYPE (object_class), GTK_RUN_LAST, + GTK_SIGNAL_OFFSET (GtkWidgetClass, remove_accelerator)); + widget_signals[GRAB_FOCUS] = + gtk_signal_new ("grab_focus", + GTK_RUN_LAST | GTK_RUN_ACTION, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, grab_focus), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + widget_signals[EVENT] = + gtk_signal_new ("event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[BUTTON_PRESS_EVENT] = + gtk_signal_new ("button_press_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, button_press_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[BUTTON_RELEASE_EVENT] = + gtk_signal_new ("button_release_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, button_release_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[SCROLL_EVENT] = + gtk_signal_new ("scroll_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, scroll_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[MOTION_NOTIFY_EVENT] = + gtk_signal_new ("motion_notify_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, motion_notify_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[DELETE_EVENT] = + gtk_signal_new ("delete_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, delete_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[DESTROY_EVENT] = + gtk_signal_new ("destroy_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, destroy_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[EXPOSE_EVENT] = + gtk_signal_new ("expose_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, expose_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[KEY_PRESS_EVENT] = + gtk_signal_new ("key_press_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, key_press_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[KEY_RELEASE_EVENT] = + gtk_signal_new ("key_release_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, key_release_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[ENTER_NOTIFY_EVENT] = + gtk_signal_new ("enter_notify_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, enter_notify_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[LEAVE_NOTIFY_EVENT] = + gtk_signal_new ("leave_notify_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, leave_notify_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[CONFIGURE_EVENT] = + gtk_signal_new ("configure_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, configure_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[FOCUS_IN_EVENT] = + gtk_signal_new ("focus_in_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, focus_in_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[FOCUS_OUT_EVENT] = + gtk_signal_new ("focus_out_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, focus_out_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[MAP_EVENT] = + gtk_signal_new ("map_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, map_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[UNMAP_EVENT] = + gtk_signal_new ("unmap_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, unmap_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[PROPERTY_NOTIFY_EVENT] = + gtk_signal_new ("property_notify_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, property_notify_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[SELECTION_CLEAR_EVENT] = + gtk_signal_new ("selection_clear_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, selection_clear_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[SELECTION_REQUEST_EVENT] = + gtk_signal_new ("selection_request_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, selection_request_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[SELECTION_NOTIFY_EVENT] = + gtk_signal_new ("selection_notify_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, selection_notify_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[SELECTION_RECEIVED] = + gtk_signal_new ("selection_received", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, selection_received), + gtk_marshal_NONE__POINTER_UINT, + GTK_TYPE_NONE, 2, + GTK_TYPE_SELECTION_DATA, + GTK_TYPE_UINT); + widget_signals[SELECTION_GET] = + gtk_signal_new ("selection_get", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, selection_get), + gtk_marshal_NONE__POINTER_UINT_UINT, + GTK_TYPE_NONE, 3, + GTK_TYPE_SELECTION_DATA, + GTK_TYPE_UINT, + GTK_TYPE_UINT); + widget_signals[PROXIMITY_IN_EVENT] = + gtk_signal_new ("proximity_in_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, proximity_in_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[PROXIMITY_OUT_EVENT] = + gtk_signal_new ("proximity_out_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, proximity_out_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[DRAG_LEAVE] = + gtk_signal_new ("drag_leave", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, drag_leave), + gtk_marshal_NONE__POINTER_UINT, + GTK_TYPE_NONE, 2, + GDK_TYPE_DRAG_CONTEXT, + GTK_TYPE_UINT); + widget_signals[DRAG_BEGIN] = + gtk_signal_new ("drag_begin", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, drag_begin), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, + GDK_TYPE_DRAG_CONTEXT); + widget_signals[DRAG_END] = + gtk_signal_new ("drag_end", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, drag_end), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, + GDK_TYPE_DRAG_CONTEXT); + widget_signals[DRAG_DATA_DELETE] = + gtk_signal_new ("drag_data_delete", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, drag_data_delete), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, + GDK_TYPE_DRAG_CONTEXT); + widget_signals[DRAG_MOTION] = + gtk_signal_new ("drag_motion", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, drag_motion), + gtk_marshal_BOOL__POINTER_INT_INT_UINT, + GTK_TYPE_BOOL, 4, + GDK_TYPE_DRAG_CONTEXT, + GTK_TYPE_INT, + GTK_TYPE_INT, + GTK_TYPE_UINT); + widget_signals[DRAG_DROP] = + gtk_signal_new ("drag_drop", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, drag_drop), + gtk_marshal_BOOL__POINTER_INT_INT_UINT, + GTK_TYPE_BOOL, 4, + GDK_TYPE_DRAG_CONTEXT, + GTK_TYPE_INT, + GTK_TYPE_INT, + GTK_TYPE_UINT); + widget_signals[DRAG_DATA_GET] = + gtk_signal_new ("drag_data_get", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, drag_data_get), + gtk_marshal_NONE__POINTER_POINTER_UINT_UINT, + GTK_TYPE_NONE, 4, + GDK_TYPE_DRAG_CONTEXT, + GTK_TYPE_SELECTION_DATA, + GTK_TYPE_UINT, + GTK_TYPE_UINT); + widget_signals[DRAG_DATA_RECEIVED] = + gtk_signal_new ("drag_data_received", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, drag_data_received), + gtk_marshal_NONE__POINTER_INT_INT_POINTER_UINT_UINT, + GTK_TYPE_NONE, 6, + GDK_TYPE_DRAG_CONTEXT, + GTK_TYPE_INT, + GTK_TYPE_INT, + GTK_TYPE_SELECTION_DATA, + GTK_TYPE_UINT, + GTK_TYPE_UINT); + widget_signals[VISIBILITY_NOTIFY_EVENT] = + gtk_signal_new ("visibility_notify_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, visibility_notify_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[CLIENT_EVENT] = + gtk_signal_new ("client_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, client_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[NO_EXPOSE_EVENT] = + gtk_signal_new ("no_expose_event", + GTK_RUN_LAST, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, no_expose_event), + gtk_marshal_BOOL__POINTER, + GTK_TYPE_BOOL, 1, + GTK_TYPE_GDK_EVENT); + widget_signals[DEBUG_MSG] = + gtk_signal_new ("debug_msg", + GTK_RUN_LAST | GTK_RUN_ACTION, + GTK_CLASS_TYPE (object_class), + GTK_SIGNAL_OFFSET (GtkWidgetClass, debug_msg), + gtk_marshal_NONE__STRING, + GTK_TYPE_NONE, 1, + GTK_TYPE_STRING); + + gtk_object_class_add_signals (object_class, widget_signals, LAST_SIGNAL); +} + +static void +gtk_widget_set_arg (GtkObject *object, + GtkArg *arg, + guint arg_id) +{ + GtkWidget *widget; + + widget = GTK_WIDGET (object); + + switch (arg_id) + { + guint32 saved_flags; + + case ARG_NAME: + gtk_widget_set_name (widget, GTK_VALUE_STRING (*arg)); + break; + case ARG_PARENT: + gtk_container_add (GTK_CONTAINER (GTK_VALUE_OBJECT (*arg)), widget); + break; + case ARG_X: + gtk_widget_set_uposition (widget, GTK_VALUE_INT (*arg), -2); + break; + case ARG_Y: + gtk_widget_set_uposition (widget, -2, GTK_VALUE_INT (*arg)); + break; + case ARG_WIDTH: + gtk_widget_set_usize (widget, GTK_VALUE_INT (*arg), -2); + break; + case ARG_HEIGHT: + gtk_widget_set_usize (widget, -2, GTK_VALUE_INT (*arg)); + break; + case ARG_VISIBLE: + if (GTK_VALUE_BOOL(*arg)) + gtk_widget_show (widget); + else + gtk_widget_hide (widget); + break; + case ARG_SENSITIVE: + gtk_widget_set_sensitive (widget, GTK_VALUE_BOOL (*arg)); + break; + case ARG_APP_PAINTABLE: + gtk_widget_set_app_paintable (widget, GTK_VALUE_BOOL (*arg)); + break; + case ARG_CAN_FOCUS: + saved_flags = GTK_WIDGET_FLAGS (widget); + if (GTK_VALUE_BOOL (*arg)) + GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS); + else + GTK_WIDGET_UNSET_FLAGS (widget, GTK_CAN_FOCUS); + if (saved_flags != GTK_WIDGET_FLAGS (widget)) + gtk_widget_queue_resize (widget); + break; + case ARG_HAS_FOCUS: + if (GTK_VALUE_BOOL (*arg)) + gtk_widget_grab_focus (widget); + break; + case ARG_CAN_DEFAULT: + saved_flags = GTK_WIDGET_FLAGS (widget); + if (GTK_VALUE_BOOL (*arg)) + GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_DEFAULT); + else + GTK_WIDGET_UNSET_FLAGS (widget, GTK_CAN_DEFAULT); + if (saved_flags != GTK_WIDGET_FLAGS (widget)) + gtk_widget_queue_resize (widget); + break; + case ARG_HAS_DEFAULT: + if (GTK_VALUE_BOOL (*arg)) + gtk_widget_grab_default (widget); + break; + case ARG_RECEIVES_DEFAULT: + if (GTK_VALUE_BOOL (*arg)) + GTK_WIDGET_SET_FLAGS (widget, GTK_RECEIVES_DEFAULT); + else + GTK_WIDGET_UNSET_FLAGS (widget, GTK_RECEIVES_DEFAULT); + break; + case ARG_COMPOSITE_CHILD: + if (GTK_VALUE_BOOL(*arg)) + GTK_WIDGET_SET_FLAGS (widget, GTK_COMPOSITE_CHILD); + else + GTK_WIDGET_UNSET_FLAGS (widget, GTK_COMPOSITE_CHILD); + break; + case ARG_STYLE: + gtk_widget_set_style (widget, (GtkStyle*) GTK_VALUE_BOXED (*arg)); + break; + case ARG_EVENTS: + if (!GTK_WIDGET_REALIZED (widget) && !GTK_WIDGET_NO_WINDOW (widget)) + gtk_widget_set_events (widget, GTK_VALUE_FLAGS (*arg)); + break; + case ARG_EXTENSION_EVENTS: + gtk_widget_set_extension_events (widget, GTK_VALUE_FLAGS (*arg)); + break; + default: + break; + } +} + +/***************************************** + * gtk_widget_get_arg: + * + * arguments: + * + * results: + *****************************************/ + +static void +gtk_widget_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id) +{ + GtkWidget *widget; + + widget = GTK_WIDGET (object); + + switch (arg_id) + { + GtkWidgetAuxInfo *aux_info; + gint *eventp; + GdkExtensionMode *modep; + + case ARG_NAME: + if (widget->name) + GTK_VALUE_STRING (*arg) = g_strdup (widget->name); + else + GTK_VALUE_STRING (*arg) = g_strdup (""); + break; + case ARG_PARENT: + GTK_VALUE_OBJECT (*arg) = (GtkObject*) widget->parent; + break; + case ARG_X: + aux_info = gtk_object_get_data_by_id (GTK_OBJECT (widget), aux_info_key_id); + if (!aux_info) + GTK_VALUE_INT (*arg) = -1; + else + GTK_VALUE_INT (*arg) = aux_info->x; + break; + case ARG_Y: + aux_info = gtk_object_get_data_by_id (GTK_OBJECT (widget), aux_info_key_id); + if (!aux_info) + GTK_VALUE_INT (*arg) = -1; + else + GTK_VALUE_INT (*arg) = aux_info->y; + break; + case ARG_WIDTH: + aux_info = gtk_object_get_data_by_id (GTK_OBJECT (widget), aux_info_key_id); + if (!aux_info) + GTK_VALUE_INT (*arg) = -1; + else + GTK_VALUE_INT (*arg) = aux_info->width; + break; + case ARG_HEIGHT: + aux_info = gtk_object_get_data_by_id (GTK_OBJECT (widget), aux_info_key_id); + if (!aux_info) + GTK_VALUE_INT (*arg) = -1; + else + GTK_VALUE_INT (*arg) = aux_info->height; + break; + case ARG_VISIBLE: + GTK_VALUE_BOOL (*arg) = (GTK_WIDGET_VISIBLE (widget) != FALSE); + break; + case ARG_SENSITIVE: + GTK_VALUE_BOOL (*arg) = (GTK_WIDGET_SENSITIVE (widget) != FALSE); + break; + case ARG_APP_PAINTABLE: + GTK_VALUE_BOOL (*arg) = (GTK_WIDGET_APP_PAINTABLE (widget) != FALSE); + break; + case ARG_CAN_FOCUS: + GTK_VALUE_BOOL (*arg) = (GTK_WIDGET_CAN_FOCUS (widget) != FALSE); + break; + case ARG_HAS_FOCUS: + GTK_VALUE_BOOL (*arg) = (GTK_WIDGET_HAS_FOCUS (widget) != FALSE); + break; + case ARG_CAN_DEFAULT: + GTK_VALUE_BOOL (*arg) = (GTK_WIDGET_CAN_DEFAULT (widget) != FALSE); + break; + case ARG_HAS_DEFAULT: + GTK_VALUE_BOOL (*arg) = (GTK_WIDGET_HAS_DEFAULT (widget) != FALSE); + break; + case ARG_RECEIVES_DEFAULT: + GTK_VALUE_BOOL (*arg) = (GTK_WIDGET_RECEIVES_DEFAULT (widget) != FALSE); + break; + case ARG_COMPOSITE_CHILD: + GTK_VALUE_BOOL (*arg) = (GTK_WIDGET_COMPOSITE_CHILD (widget) != FALSE); + break; + case ARG_STYLE: + GTK_VALUE_BOXED (*arg) = (gpointer) gtk_widget_get_style (widget); + break; + case ARG_EVENTS: + eventp = gtk_object_get_data_by_id (GTK_OBJECT (widget), event_key_id); + if (!eventp) + GTK_VALUE_FLAGS (*arg) = 0; + else + GTK_VALUE_FLAGS (*arg) = *eventp; + break; + case ARG_EXTENSION_EVENTS: + modep = gtk_object_get_data_by_id (GTK_OBJECT (widget), extension_event_key_id); + if (!modep) + GTK_VALUE_FLAGS (*arg) = 0; + else + GTK_VALUE_FLAGS (*arg) = *modep; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +/***************************************** + * gtk_widget_init: + * + * arguments: + * + * results: + *****************************************/ + +static void +gtk_widget_init (GtkWidget *widget) +{ + GdkColormap *colormap; + GdkVisual *visual; + + GTK_PRIVATE_FLAGS (widget) = 0; + widget->state = GTK_STATE_NORMAL; + widget->saved_state = GTK_STATE_NORMAL; + widget->name = NULL; + widget->requisition.width = 0; + widget->requisition.height = 0; + widget->allocation.x = -1; + widget->allocation.y = -1; + widget->allocation.width = 1; + widget->allocation.height = 1; + widget->window = NULL; + widget->parent = NULL; + + GTK_WIDGET_SET_FLAGS (widget, + GTK_SENSITIVE | + GTK_PARENT_SENSITIVE | + (composite_child_stack ? GTK_COMPOSITE_CHILD : 0) | + GTK_DOUBLE_BUFFERED); + + widget->style = gtk_widget_peek_style (); + gtk_style_ref (widget->style); + + colormap = gtk_widget_peek_colormap (); + visual = gtk_widget_peek_visual (); + + if (colormap != gtk_widget_get_default_colormap ()) + gtk_widget_set_colormap (widget, colormap); + + if (visual != gtk_widget_get_default_visual ()) + gtk_widget_set_visual (widget, visual); +} + +/***************************************** + * gtk_widget_new: + * + * arguments: + * + * results: + *****************************************/ + +GtkWidget* +gtk_widget_new (GtkType widget_type, + const gchar *first_arg_name, + ...) +{ + GtkObject *object; + va_list var_args; + GSList *arg_list = NULL; + GSList *info_list = NULL; + gchar *error; + + g_return_val_if_fail (gtk_type_is_a (widget_type, GTK_TYPE_WIDGET), NULL); + + object = gtk_type_new (widget_type); + + va_start (var_args, first_arg_name); + error = gtk_object_args_collect (GTK_OBJECT_TYPE (object), + &arg_list, + &info_list, + first_arg_name, + var_args); + va_end (var_args); + + if (error) + { + g_warning ("gtk_widget_new(): %s", error); + g_free (error); + } + else + { + GSList *slist_arg; + GSList *slist_info; + + slist_arg = arg_list; + slist_info = info_list; + while (slist_arg) + { + gtk_object_arg_set (object, slist_arg->data, slist_info->data); + slist_arg = slist_arg->next; + slist_info = slist_info->next; + } + gtk_args_collect_cleanup (arg_list, info_list); + } + + if (!GTK_OBJECT_CONSTRUCTED (object)) + gtk_object_default_construct (object); + + return GTK_WIDGET (object); +} + +/***************************************** + * gtk_widget_newv: + * + * arguments: + * + * results: + *****************************************/ + +GtkWidget* +gtk_widget_newv (GtkType type, + guint nargs, + GtkArg *args) +{ + g_return_val_if_fail (gtk_type_is_a (type, GTK_TYPE_WIDGET), NULL); + + return GTK_WIDGET (gtk_object_newv (type, nargs, args)); +} + +/***************************************** + * gtk_widget_get: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_get (GtkWidget *widget, + GtkArg *arg) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (arg != NULL); + + gtk_object_getv (GTK_OBJECT (widget), 1, arg); +} + +/***************************************** + * gtk_widget_getv: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_getv (GtkWidget *widget, + guint nargs, + GtkArg *args) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + gtk_object_getv (GTK_OBJECT (widget), nargs, args); +} + +/***************************************** + * gtk_widget_set: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_set (GtkWidget *widget, + const gchar *first_arg_name, + ...) +{ + GtkObject *object; + va_list var_args; + GSList *arg_list = NULL; + GSList *info_list = NULL; + gchar *error; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + object = GTK_OBJECT (widget); + + va_start (var_args, first_arg_name); + error = gtk_object_args_collect (GTK_OBJECT_TYPE (object), + &arg_list, + &info_list, + first_arg_name, + var_args); + va_end (var_args); + + if (error) + { + g_warning ("gtk_widget_set(): %s", error); + g_free (error); + } + else + { + GSList *slist_arg; + GSList *slist_info; + + slist_arg = arg_list; + slist_info = info_list; + while (slist_arg) + { + gtk_object_arg_set (object, slist_arg->data, slist_info->data); + slist_arg = slist_arg->next; + slist_info = slist_info->next; + } + gtk_args_collect_cleanup (arg_list, info_list); + } +} + +/***************************************** + * gtk_widget_setv: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_setv (GtkWidget *widget, + guint nargs, + GtkArg *args) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + gtk_object_setv (GTK_OBJECT (widget), nargs, args); +} + +static inline void +gtk_widget_queue_clear_child (GtkWidget *widget) +{ + GtkWidget *parent; + + parent = widget->parent; + if (parent && GTK_WIDGET_DRAWABLE (parent)) + gtk_widget_queue_clear_area (parent, + widget->allocation.x, + widget->allocation.y, + widget->allocation.width, + widget->allocation.height); +} + +void +gtk_widget_unparent (GtkWidget *widget) +{ + GtkWidget *toplevel; + GtkWidget *old_parent; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + if (widget->parent == NULL) + return; + + /* keep this function in sync with gtk_menu_detach() + */ + + /* unset focused and default children properly, this code + * should eventually move into some gtk_window_unparent_branch() or + * similar function. + */ + + toplevel = gtk_widget_get_toplevel (widget); + if (GTK_CONTAINER (widget->parent)->focus_child == widget) + { + gtk_container_set_focus_child (GTK_CONTAINER (widget->parent), NULL); + + if (GTK_IS_WINDOW (toplevel)) + { + GtkWidget *child; + + child = GTK_WINDOW (toplevel)->focus_widget; + + while (child && child != widget) + child = child->parent; + + if (child == widget) + gtk_window_set_focus (GTK_WINDOW (toplevel), NULL); + } + } + if (GTK_IS_WINDOW (toplevel)) + { + GtkWidget *child; + + child = GTK_WINDOW (toplevel)->default_widget; + + while (child && child != widget) + child = child->parent; + + if (child == widget) + gtk_window_set_default (GTK_WINDOW (toplevel), NULL); + } + + if (GTK_IS_RESIZE_CONTAINER (widget)) + gtk_container_clear_resize_widgets (GTK_CONTAINER (widget)); + + /* Remove the widget and all its children from any ->resize_widgets list + * of all the parents in our branch. This code should move into gtkcontainer.c + * somwhen, since we mess around with ->resize_widgets, which is + * actually not of our business. + * + * Two ways to make this prettier: + * Write a g_slist_conditional_remove (GSList, gboolean (*)(gpointer)) + * Change resize_widgets to a GList + */ + toplevel = widget->parent; + while (toplevel) + { + GSList *slist; + GSList *prev; + + if (!GTK_CONTAINER (toplevel)->resize_widgets) + { + toplevel = toplevel->parent; + continue; + } + + prev = NULL; + slist = GTK_CONTAINER (toplevel)->resize_widgets; + while (slist) + { + GtkWidget *child; + GtkWidget *parent; + GSList *last; + + last = slist; + slist = last->next; + child = last->data; + + parent = child; + while (parent && (parent != widget)) + parent = parent->parent; + + if (parent == widget) + { + GTK_PRIVATE_UNSET_FLAG (child, GTK_RESIZE_NEEDED); + + if (prev) + prev->next = slist; + else + GTK_CONTAINER (toplevel)->resize_widgets = slist; + + g_slist_free_1 (last); + } + else + prev = last; + } + + toplevel = toplevel->parent; + } + + gtk_widget_queue_clear_child (widget); + + /* Reset the width and height here, to force reallocation if we + * get added back to a new parent. This won't work if our new + * allocation is smaller than 1x1 and we actually want a size of 1x1... + * (would 0x0 be OK here?) + */ + widget->allocation.width = 1; + widget->allocation.height = 1; + + if (GTK_WIDGET_REALIZED (widget) && !GTK_WIDGET_IN_REPARENT (widget)) + gtk_widget_unrealize (widget); + + old_parent = widget->parent; + widget->parent = NULL; + gtk_widget_set_parent_window (widget, NULL); + gtk_signal_emit (GTK_OBJECT (widget), widget_signals[PARENT_SET], old_parent); + + gtk_widget_unref (widget); +} + +/***************************************** + * gtk_widget_destroy: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_destroy (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (GTK_OBJECT_CONSTRUCTED (widget)); + + gtk_object_destroy ((GtkObject*) widget); +} + +/***************************************** + * gtk_widget_destroyed: + * Utility function: sets widget_pointer + * to NULL when widget is destroyed. + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_destroyed (GtkWidget *widget, + GtkWidget **widget_pointer) +{ + /* Don't make any assumptions about the + * value of widget! + * Even check widget_pointer. + */ + if (widget_pointer) + *widget_pointer = NULL; +} + +/***************************************** + * gtk_widget_show: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_show (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (!GTK_WIDGET_VISIBLE (widget)) + { + if (!GTK_WIDGET_TOPLEVEL (widget)) + gtk_widget_queue_resize (widget); + gtk_signal_emit (GTK_OBJECT (widget), widget_signals[SHOW]); + } +} + +static void +gtk_widget_real_show (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (!GTK_WIDGET_VISIBLE (widget)) + { + GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE); + + if (widget->parent && + GTK_WIDGET_MAPPED (widget->parent) && + !GTK_WIDGET_MAPPED (widget)) + gtk_widget_map (widget); + } +} + +/************************************************************* + * gtk_widget_show_now: + * Show a widget, and if it is an unmapped toplevel widget + * wait for the map_event before returning + * + * Warning: This routine will call the main loop recursively. + * + * arguments: + * + * results: + *************************************************************/ + +static void +gtk_widget_show_map_callback (GtkWidget *widget, GdkEvent *event, gint *flag) +{ + *flag = TRUE; + gtk_signal_disconnect_by_data (GTK_OBJECT (widget), flag); +} + +void +gtk_widget_show_now (GtkWidget *widget) +{ + gint flag = FALSE; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + /* make sure we will get event */ + if (!GTK_WIDGET_MAPPED (widget) && + GTK_WIDGET_TOPLEVEL (widget)) + { + gtk_widget_show (widget); + + gtk_signal_connect (GTK_OBJECT (widget), "map_event", + GTK_SIGNAL_FUNC (gtk_widget_show_map_callback), + &flag); + + while (!flag) + gtk_main_iteration(); + } + else + gtk_widget_show (widget); +} + +/***************************************** + * gtk_widget_hide: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_hide (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (GTK_WIDGET_VISIBLE (widget)) + { + gtk_widget_ref (widget); + gtk_signal_emit (GTK_OBJECT (widget), widget_signals[HIDE]); + if (!GTK_WIDGET_TOPLEVEL (widget) && !GTK_OBJECT_DESTROYED (widget)) + gtk_widget_queue_resize (widget); + gtk_widget_unref (widget); + } +} + +static void +gtk_widget_real_hide (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (GTK_WIDGET_VISIBLE (widget)) + { + GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE); + + if (GTK_WIDGET_MAPPED (widget)) + gtk_widget_unmap (widget); + } +} + +gint +gtk_widget_hide_on_delete (GtkWidget *widget) +{ + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + + gtk_widget_hide (widget); + + return TRUE; +} + +void +gtk_widget_show_all (GtkWidget *widget) +{ + GtkWidgetClass *class; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + class = GTK_WIDGET_GET_CLASS (widget); + + if (class->show_all) + class->show_all (widget); +} + +void +gtk_widget_hide_all (GtkWidget *widget) +{ + GtkWidgetClass *class; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + class = GTK_WIDGET_GET_CLASS (widget); + + if (class->hide_all) + class->hide_all (widget); +} + +/***************************************** + * gtk_widget_map: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_map (GtkWidget *widget) +{ + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (GTK_WIDGET_VISIBLE (widget) == TRUE); + + if (!GTK_WIDGET_MAPPED (widget)) + { + if (!GTK_WIDGET_REALIZED (widget)) + gtk_widget_realize (widget); + + gtk_signal_emit (GTK_OBJECT (widget), widget_signals[MAP]); + + if (GTK_WIDGET_NO_WINDOW (widget)) + gtk_widget_queue_draw (widget); + } +} + +/***************************************** + * gtk_widget_unmap: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_unmap (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (GTK_WIDGET_MAPPED (widget)) + { + if (GTK_WIDGET_NO_WINDOW (widget)) + gtk_widget_queue_clear_child (widget); + gtk_signal_emit (GTK_OBJECT (widget), widget_signals[UNMAP]); + } +} + +/***************************************** + * gtk_widget_realize: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_realize (GtkWidget *widget) +{ + gint events; + GdkExtensionMode mode; + GtkWidgetShapeInfo *shape_info; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (!GTK_WIDGET_REALIZED (widget)) + { + /* + if (GTK_IS_CONTAINER (widget) && !GTK_WIDGET_NO_WINDOW (widget)) + g_message ("gtk_widget_realize(%s)", gtk_type_name (GTK_WIDGET_TYPE (widget))); + */ + + if (widget->parent && !GTK_WIDGET_REALIZED (widget->parent)) + gtk_widget_realize (widget->parent); + + gtk_widget_ensure_style (widget); + + gtk_signal_emit (GTK_OBJECT (widget), widget_signals[REALIZE]); + + if (GTK_WIDGET_HAS_SHAPE_MASK (widget)) + { + shape_info = gtk_object_get_data (GTK_OBJECT (widget), + shape_info_key); + gdk_window_shape_combine_mask (widget->window, + shape_info->shape_mask, + shape_info->offset_x, + shape_info->offset_y); + } + + if (!GTK_WIDGET_NO_WINDOW (widget)) + { + mode = gtk_widget_get_extension_events (widget); + if (mode != GDK_EXTENSION_EVENTS_NONE) + { + events = gtk_widget_get_events (widget); + gdk_input_set_extension_events (widget->window, events, mode); + } + } + + } +} + +/***************************************** + * gtk_widget_unrealize: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_unrealize (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (GTK_WIDGET_HAS_SHAPE_MASK (widget)) + gtk_widget_shape_combine_mask (widget, NULL, -1, -1); + + if (GTK_WIDGET_REALIZED (widget)) + { + gtk_widget_ref (widget); + gtk_signal_emit (GTK_OBJECT (widget), widget_signals[UNREALIZE]); + GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED | GTK_MAPPED); + gtk_widget_unref (widget); + } +} + +/***************************************** + * Draw queueing. + *****************************************/ + +void +gtk_widget_queue_draw_area (GtkWidget *widget, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + gtk_widget_queue_clear_area (widget, x, y, width, height); +} + +void +gtk_widget_queue_draw (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + gtk_widget_queue_clear (widget); +} + +/* Invalidates the given area (allocation-relative-coordinates) + * in all of the widget's windows + */ +void +gtk_widget_queue_clear_area (GtkWidget *widget, + gint x, + gint y, + gint width, + gint height) +{ + GdkRectangle invalid_rect; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (!(widget->window && gdk_window_is_viewable (widget->window))) + return; + + /* Find the correct widget */ + + if (!GTK_WIDGET_NO_WINDOW (widget)) + { + if (widget->parent) + { + /* Translate widget relative to window-relative */ + + gint wx, wy, wwidth, wheight; + + gdk_window_get_position (widget->window, &wx, &wy); + x -= wx - widget->allocation.x; + y -= wy - widget->allocation.y; + + gdk_window_get_size (widget->window, &wwidth, &wheight); + + if (x + width <= 0 || y + height <= 0 || + x >= wwidth || y >= wheight) + return; + + if (x < 0) + { + width += x; x = 0; + } + if (y < 0) + { + height += y; y = 0; + } + if (x + width > wwidth) + width = wwidth - x; + if (y + height > wheight) + height = wheight - y; + } + } + + invalid_rect.x = x; + invalid_rect.y = y; + invalid_rect.width = width; + invalid_rect.height = height; + + gdk_window_invalidate_rect (widget->window, &invalid_rect, TRUE); +} + +void +gtk_widget_queue_clear (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (widget->allocation.width || widget->allocation.height) + { + if (GTK_WIDGET_NO_WINDOW (widget)) + gtk_widget_queue_clear_area (widget, widget->allocation.x, + widget->allocation.y, + widget->allocation.width, + widget->allocation.height); + else + gtk_widget_queue_clear_area (widget, 0, 0, + widget->allocation.width, + widget->allocation.height); + } +} + +void +gtk_widget_queue_resize (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (GTK_IS_RESIZE_CONTAINER (widget)) + gtk_container_clear_resize_widgets (GTK_CONTAINER (widget)); + + gtk_widget_queue_clear (widget); + + if (widget->parent) + gtk_container_queue_resize (GTK_CONTAINER (widget->parent)); + else if (GTK_WIDGET_TOPLEVEL (widget)) + gtk_container_queue_resize (GTK_CONTAINER (widget)); +} + +/***************************************** + * gtk_widget_draw: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_draw (GtkWidget *widget, + GdkRectangle *area) +{ + GdkRectangle temp_area; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (GTK_WIDGET_DRAWABLE (widget)) + { + if (!area) + { + if (GTK_WIDGET_NO_WINDOW (widget)) + { + temp_area.x = widget->allocation.x; + temp_area.y = widget->allocation.y; + } + else + { + temp_area.x = 0; + temp_area.y = 0; + } + + temp_area.width = widget->allocation.width; + temp_area.height = widget->allocation.height; + area = &temp_area; + } + + if (!GTK_WIDGET_NO_WINDOW (widget) && GTK_WIDGET_DOUBLE_BUFFERED (widget)) + { + GdkRectangle tmp_area = *area; + gint x, y; + + if (!GTK_WIDGET_TOPLEVEL (widget)) + { + gdk_window_get_position (widget->window, &x, &y); + tmp_area.x -= x - widget->allocation.x; + tmp_area.y -= y - widget->allocation.y; + } + + gdk_window_begin_paint_rect (widget->window, &tmp_area); + } + + gtk_signal_emit (GTK_OBJECT (widget), widget_signals[DRAW], area); + + if (!GTK_WIDGET_NO_WINDOW (widget) && GTK_WIDGET_DOUBLE_BUFFERED (widget)) + gdk_window_end_paint (widget->window); + } +} + +/***************************************** + * gtk_widget_draw_focus: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_draw_focus (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + gtk_signal_emit (GTK_OBJECT (widget), widget_signals[DRAW_FOCUS]); +} + +/***************************************** + * gtk_widget_draw_default: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_draw_default (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + gtk_signal_emit (GTK_OBJECT (widget), widget_signals[DRAW_DEFAULT]); +} + +/***************************************** + * gtk_widget_size_request: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + +#ifdef G_ENABLE_DEBUG + if (requisition == &widget->requisition) + g_warning ("gtk_widget_size_request() called on child widget with request equal\n to widget->requisition. gtk_widget_set_usize() may not work properly."); +#endif /* G_ENABLE_DEBUG */ + + gtk_widget_ref (widget); + gtk_widget_ensure_style (widget); + gtk_signal_emit (GTK_OBJECT (widget), widget_signals[SIZE_REQUEST], + &widget->requisition); + + if (requisition) + gtk_widget_get_child_requisition (widget, requisition); + + gtk_widget_unref (widget); +} + +/***************************************** + * gtk_widget_get_requesition: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_get_child_requisition (GtkWidget *widget, + GtkRequisition *requisition) +{ + GtkWidgetAuxInfo *aux_info; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + *requisition = widget->requisition; + + aux_info = gtk_object_get_data_by_id (GTK_OBJECT (widget), aux_info_key_id); + if (aux_info) + { + if (aux_info->width > 0) + requisition->width = aux_info->width; + if (aux_info->height > 0) + requisition->height = aux_info->height; + } +} + +/***************************************** + * gtk_widget_size_allocate: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GtkWidgetAuxInfo *aux_info; + GtkAllocation real_allocation; + gboolean needs_draw = FALSE; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + real_allocation = *allocation; + aux_info = gtk_object_get_data_by_id (GTK_OBJECT (widget), aux_info_key_id); + + if (aux_info) + { + if (aux_info->x != -1) + real_allocation.x = aux_info->x; + if (aux_info->y != -1) + real_allocation.y = aux_info->y; + } + + real_allocation.width = MAX (real_allocation.width, 1); + real_allocation.height = MAX (real_allocation.height, 1); + + if (real_allocation.width < 0 || real_allocation.height < 0) + { + g_warning ("gtk_widget_size_allocate(): attempt to allocate widget with width %d and height %d", + real_allocation.width, + real_allocation.height); + real_allocation.width = 1; + real_allocation.height = 1; + } + + if (GTK_WIDGET_NO_WINDOW (widget)) + { + if (widget->allocation.x != real_allocation.x || + widget->allocation.y != real_allocation.y || + widget->allocation.width != real_allocation.width || + widget->allocation.height != real_allocation.height) + { + gtk_widget_queue_clear_child (widget); + needs_draw = TRUE; + } + } + else if (widget->allocation.width != real_allocation.width || + widget->allocation.height != real_allocation.height) + { + needs_draw = TRUE; + } + + if (GTK_IS_RESIZE_CONTAINER (widget)) + gtk_container_clear_resize_widgets (GTK_CONTAINER (widget)); + + gtk_signal_emit (GTK_OBJECT (widget), widget_signals[SIZE_ALLOCATE], &real_allocation); + + if (needs_draw) + { + gtk_widget_queue_draw (widget); + if (widget->parent && GTK_CONTAINER (widget->parent)->reallocate_redraws) + gtk_widget_queue_draw (widget->parent); + } +} + +static void +gtk_widget_real_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + widget->allocation = *allocation; + + if (GTK_WIDGET_REALIZED (widget) && + !GTK_WIDGET_NO_WINDOW (widget)) + { + gdk_window_move_resize (widget->window, + allocation->x, allocation->y, + allocation->width, allocation->height); + } +} + +static void +gtk_widget_stop_add_accelerator (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + gtk_signal_emit_stop (GTK_OBJECT (widget), widget_signals[ADD_ACCELERATOR]); +} + +static void +gtk_widget_stop_remove_accelerator (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + gtk_signal_emit_stop (GTK_OBJECT (widget), widget_signals[REMOVE_ACCELERATOR]); +} + +void +gtk_widget_lock_accelerators (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (!gtk_widget_accelerators_locked (widget)) + { + gtk_signal_connect (GTK_OBJECT (widget), + "add_accelerator", + GTK_SIGNAL_FUNC (gtk_widget_stop_add_accelerator), + NULL); + gtk_signal_connect (GTK_OBJECT (widget), + "remove_accelerator", + GTK_SIGNAL_FUNC (gtk_widget_stop_remove_accelerator), + NULL); + } +} + +void +gtk_widget_unlock_accelerators (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (gtk_widget_accelerators_locked (widget)) + { + gtk_signal_disconnect_by_func (GTK_OBJECT (widget), + GTK_SIGNAL_FUNC (gtk_widget_stop_add_accelerator), + NULL); + gtk_signal_disconnect_by_func (GTK_OBJECT (widget), + GTK_SIGNAL_FUNC (gtk_widget_stop_remove_accelerator), + NULL); + } +} + +gboolean +gtk_widget_accelerators_locked (GtkWidget *widget) +{ + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + + return gtk_signal_handler_pending_by_func (GTK_OBJECT (widget), + widget_signals[ADD_ACCELERATOR], + TRUE, + GTK_SIGNAL_FUNC (gtk_widget_stop_add_accelerator), + NULL) > 0; +} + +void +gtk_widget_add_accelerator (GtkWidget *widget, + const gchar *accel_signal, + GtkAccelGroup *accel_group, + guint accel_key, + guint accel_mods, + GtkAccelFlags accel_flags) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (accel_group != NULL); + + gtk_accel_group_add (accel_group, + accel_key, + accel_mods, + accel_flags, + (GtkObject*) widget, + accel_signal); +} + +void +gtk_widget_remove_accelerator (GtkWidget *widget, + GtkAccelGroup *accel_group, + guint accel_key, + guint accel_mods) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (accel_group != NULL); + + gtk_accel_group_remove (accel_group, + accel_key, + accel_mods, + (GtkObject*) widget); +} + +void +gtk_widget_remove_accelerators (GtkWidget *widget, + const gchar *accel_signal, + gboolean visible_only) +{ + GSList *slist; + guint signal_id; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (accel_signal != NULL); + + signal_id = gtk_signal_lookup (accel_signal, GTK_OBJECT_TYPE (widget)); + g_return_if_fail (signal_id != 0); + + slist = gtk_accel_group_entries_from_object (GTK_OBJECT (widget)); + while (slist) + { + GtkAccelEntry *ac_entry; + + ac_entry = slist->data; + slist = slist->next; + if (ac_entry->accel_flags & GTK_ACCEL_VISIBLE && + ac_entry->signal_id == signal_id) + gtk_widget_remove_accelerator (GTK_WIDGET (widget), + ac_entry->accel_group, + ac_entry->accelerator_key, + ac_entry->accelerator_mods); + } +} + +guint +gtk_widget_accelerator_signal (GtkWidget *widget, + GtkAccelGroup *accel_group, + guint accel_key, + guint accel_mods) +{ + GtkAccelEntry *ac_entry; + + g_return_val_if_fail (widget != NULL, 0); + g_return_val_if_fail (GTK_IS_WIDGET (widget), 0); + g_return_val_if_fail (accel_group != NULL, 0); + + ac_entry = gtk_accel_group_get_entry (accel_group, accel_key, accel_mods); + + if (ac_entry && ac_entry->object == (GtkObject*) widget) + return ac_entry->signal_id; + return 0; +} + +static gint +gtk_widget_real_key_press_event (GtkWidget *widget, + GdkEventKey *event) +{ + gboolean handled = FALSE; + + g_return_val_if_fail (widget != NULL, handled); + g_return_val_if_fail (GTK_IS_WIDGET (widget), handled); + g_return_val_if_fail (event != NULL, handled); + + if (!handled) + handled = gtk_bindings_activate (GTK_OBJECT (widget), + event->keyval, + event->state); + + return handled; +} + +static gint +gtk_widget_real_key_release_event (GtkWidget *widget, + GdkEventKey *event) +{ + gboolean handled = FALSE; + + g_return_val_if_fail (widget != NULL, handled); + g_return_val_if_fail (GTK_IS_WIDGET (widget), handled); + g_return_val_if_fail (event != NULL, handled); + + if (!handled) + handled = gtk_bindings_activate (GTK_OBJECT (widget), + event->keyval, + event->state | GDK_RELEASE_MASK); + + return handled; +} + +/***************************************** + * gtk_widget_event: + * + * arguments: + * + * results: + *****************************************/ + +gint +gtk_widget_event (GtkWidget *widget, + GdkEvent *event) +{ + gboolean return_val; + gint signal_num; + + g_return_val_if_fail (widget != NULL, TRUE); + g_return_val_if_fail (GTK_IS_WIDGET (widget), TRUE); + + gtk_widget_ref (widget); + return_val = FALSE; + gtk_signal_emit (GTK_OBJECT (widget), widget_signals[EVENT], event, + &return_val); + if (return_val || GTK_OBJECT_DESTROYED (widget)) + goto out; + + switch (event->type) + { + case GDK_NOTHING: + signal_num = -1; + break; + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + signal_num = BUTTON_PRESS_EVENT; + break; + case GDK_SCROLL: + signal_num = SCROLL_EVENT; + break; + case GDK_BUTTON_RELEASE: + signal_num = BUTTON_RELEASE_EVENT; + break; + case GDK_MOTION_NOTIFY: + signal_num = MOTION_NOTIFY_EVENT; + break; + case GDK_DELETE: + signal_num = DELETE_EVENT; + break; + case GDK_DESTROY: + signal_num = DESTROY_EVENT; + break; + case GDK_KEY_PRESS: + signal_num = KEY_PRESS_EVENT; + break; + case GDK_KEY_RELEASE: + signal_num = KEY_RELEASE_EVENT; + break; + case GDK_ENTER_NOTIFY: + signal_num = ENTER_NOTIFY_EVENT; + break; + case GDK_LEAVE_NOTIFY: + signal_num = LEAVE_NOTIFY_EVENT; + break; + case GDK_FOCUS_CHANGE: + if (event->focus_change.in) + signal_num = FOCUS_IN_EVENT; + else + signal_num = FOCUS_OUT_EVENT; + break; + case GDK_CONFIGURE: + signal_num = CONFIGURE_EVENT; + break; + case GDK_MAP: + signal_num = MAP_EVENT; + break; + case GDK_UNMAP: + signal_num = UNMAP_EVENT; + break; + case GDK_PROPERTY_NOTIFY: + signal_num = PROPERTY_NOTIFY_EVENT; + break; + case GDK_SELECTION_CLEAR: + signal_num = SELECTION_CLEAR_EVENT; + break; + case GDK_SELECTION_REQUEST: + signal_num = SELECTION_REQUEST_EVENT; + break; + case GDK_SELECTION_NOTIFY: + signal_num = SELECTION_NOTIFY_EVENT; + break; + case GDK_PROXIMITY_IN: + signal_num = PROXIMITY_IN_EVENT; + break; + case GDK_PROXIMITY_OUT: + signal_num = PROXIMITY_OUT_EVENT; + break; + case GDK_NO_EXPOSE: + signal_num = NO_EXPOSE_EVENT; + break; + case GDK_CLIENT_EVENT: + signal_num = CLIENT_EVENT; + break; + case GDK_EXPOSE: + if (!event->any.window) /* Why is this necessary */ + goto out; + + signal_num = EXPOSE_EVENT; + break; + case GDK_VISIBILITY_NOTIFY: + signal_num = VISIBILITY_NOTIFY_EVENT; + break; + default: + g_warning ("could not determine signal number for event: %d", event->type); + goto out; + } + + if (signal_num != -1) + gtk_signal_emit (GTK_OBJECT (widget), widget_signals[signal_num], event, &return_val); + + return_val |= GTK_OBJECT_DESTROYED (widget); + + out: + gtk_widget_unref (widget); + + return return_val; +} + +/***************************************** + * gtk_widget_activate: + * + * arguments: + * + * results: + *****************************************/ + +gboolean +gtk_widget_activate (GtkWidget *widget) +{ + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + + if (WIDGET_CLASS (widget)->activate_signal) + { + /* FIXME: we should eventually check the signals signature here */ + gtk_signal_emit (GTK_OBJECT (widget), WIDGET_CLASS (widget)->activate_signal); + + return TRUE; + } + else + return FALSE; +} + +gboolean +gtk_widget_set_scroll_adjustments (GtkWidget *widget, + GtkAdjustment *hadjustment, + GtkAdjustment *vadjustment) +{ + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + if (hadjustment) + g_return_val_if_fail (GTK_IS_ADJUSTMENT (hadjustment), FALSE); + if (vadjustment) + g_return_val_if_fail (GTK_IS_ADJUSTMENT (vadjustment), FALSE); + + if (WIDGET_CLASS (widget)->set_scroll_adjustments_signal) + { + /* FIXME: we should eventually check the signals signature here */ + gtk_signal_emit (GTK_OBJECT (widget), + WIDGET_CLASS (widget)->set_scroll_adjustments_signal, + hadjustment, vadjustment); + return TRUE; + } + else + return FALSE; +} + +/***************************************** + * gtk_widget_reparent_container_child: + * assistent function to gtk_widget_reparent + * + * arguments: + * + * results: + *****************************************/ + +static void +gtk_widget_reparent_container_child (GtkWidget *widget, + gpointer client_data) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (client_data != NULL); + + if (GTK_WIDGET_NO_WINDOW (widget)) + { + if (widget->window) + gdk_window_unref (widget->window); + widget->window = (GdkWindow*) client_data; + if (widget->window) + gdk_window_ref (widget->window); + + if (GTK_IS_CONTAINER (widget)) + gtk_container_forall (GTK_CONTAINER (widget), + gtk_widget_reparent_container_child, + client_data); + } + else + gdk_window_reparent (widget->window, + (GdkWindow*) client_data, 0, 0); +} + +/***************************************** + * gtk_widget_reparent: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_reparent (GtkWidget *widget, + GtkWidget *new_parent) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (new_parent != NULL); + g_return_if_fail (GTK_IS_CONTAINER (new_parent)); + g_return_if_fail (widget->parent != NULL); + + if (widget->parent != new_parent) + { + /* First try to see if we can get away without unrealizing + * the widget as we reparent it. if so we set a flag so + * that gtk_widget_unparent doesn't unrealize widget + */ + if (GTK_WIDGET_REALIZED (widget) && GTK_WIDGET_REALIZED (new_parent)) + GTK_PRIVATE_SET_FLAG (widget, GTK_IN_REPARENT); + + gtk_widget_ref (widget); + gtk_container_remove (GTK_CONTAINER (widget->parent), widget); + gtk_container_add (GTK_CONTAINER (new_parent), widget); + gtk_widget_unref (widget); + + if (GTK_WIDGET_IN_REPARENT (widget)) + { + GTK_PRIVATE_UNSET_FLAG (widget, GTK_IN_REPARENT); + + gtk_widget_reparent_container_child (widget, + gtk_widget_get_parent_window (widget)); + } + } +} + +/***************************************** + * gtk_widget_popup: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_popup (GtkWidget *widget, + gint x, + gint y) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (!GTK_WIDGET_VISIBLE (widget)) + { + if (!GTK_WIDGET_REALIZED (widget)) + gtk_widget_realize (widget); + if (!GTK_WIDGET_NO_WINDOW (widget)) + gdk_window_move (widget->window, x, y); + gtk_widget_show (widget); + } +} + +/***************************************** + * gtk_widget_intersect: + * + * arguments: + * + * results: + *****************************************/ + +gint +gtk_widget_intersect (GtkWidget *widget, + GdkRectangle *area, + GdkRectangle *intersection) +{ + GdkRectangle *dest; + GdkRectangle tmp; + gint return_val; + + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + g_return_val_if_fail (area != NULL, FALSE); + + if (intersection) + dest = intersection; + else + dest = &tmp; + + return_val = gdk_rectangle_intersect (&widget->allocation, area, dest); + + if (return_val && intersection && !GTK_WIDGET_NO_WINDOW (widget)) + { + intersection->x -= widget->allocation.x; + intersection->y -= widget->allocation.y; + } + + return return_val; +} + +/***************************************** + * gtk_widget_grab_focus: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_grab_focus (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + gtk_signal_emit (GTK_OBJECT (widget), widget_signals[GRAB_FOCUS]); +} + +static void +reset_focus_recurse (GtkWidget *widget, + gpointer data) +{ + if (GTK_IS_CONTAINER (widget)) + { + GtkContainer *container; + + container = GTK_CONTAINER (widget); + gtk_container_set_focus_child (container, NULL); + + gtk_container_foreach (container, + reset_focus_recurse, + NULL); + } +} + +static void +gtk_widget_real_grab_focus (GtkWidget *focus_widget) +{ + g_return_if_fail (focus_widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (focus_widget)); + + if (GTK_WIDGET_CAN_FOCUS (focus_widget)) + { + GtkWidget *toplevel; + GtkWidget *widget; + + /* clear the current focus setting, break if the current widget + * is the focus widget's parent, since containers above that will + * be set by the next loop. + */ + toplevel = gtk_widget_get_toplevel (focus_widget); + if (GTK_IS_WINDOW (toplevel)) + { + widget = GTK_WINDOW (toplevel)->focus_widget; + + if (widget == focus_widget) + { + /* We call gtk_window_set_focus() here so that the + * toplevel window can request the focus if necessary. + * This is needed when the toplevel is a GtkPlug + */ + if (!GTK_WIDGET_HAS_FOCUS (widget)) + gtk_window_set_focus (GTK_WINDOW (toplevel), focus_widget); + + return; + } + + if (widget) + { + while (widget->parent && widget->parent != focus_widget->parent) + { + widget = widget->parent; + gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL); + } + } + } + else if (toplevel != focus_widget) + { + /* gtk_widget_grab_focus() operates on a tree without window... + * actually, this is very questionable behaviour. + */ + + gtk_container_foreach (GTK_CONTAINER (toplevel), + reset_focus_recurse, + NULL); + } + + /* now propagate the new focus up the widget tree and finally + * set it on the window + */ + widget = focus_widget; + while (widget->parent) + { + gtk_container_set_focus_child (GTK_CONTAINER (widget->parent), widget); + widget = widget->parent; + } + if (GTK_IS_WINDOW (widget)) + gtk_window_set_focus (GTK_WINDOW (widget), focus_widget); + } +} + +/***************************************** + * gtk_widget_grab_default: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_grab_default (GtkWidget *widget) +{ + GtkWidget *window; + GtkType window_type; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (GTK_WIDGET_CAN_DEFAULT (widget)); + + window_type = GTK_TYPE_WINDOW; + window = widget->parent; + + while (window && !gtk_type_is_a (GTK_WIDGET_TYPE (window), window_type)) + window = window->parent; + + if (window && gtk_type_is_a (GTK_WIDGET_TYPE (window), window_type)) + gtk_window_set_default (GTK_WINDOW (window), widget); + else + g_warning("gtk_widget_grab_default() called on a widget not within a GtkWindow"); +} + +/***************************************** + * gtk_widget_set_name: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_set_name (GtkWidget *widget, + const gchar *name) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (widget->name) + g_free (widget->name); + widget->name = g_strdup (name); + + if (GTK_WIDGET_RC_STYLE (widget)) + gtk_widget_set_rc_style (widget); +} + +/***************************************** + * gtk_widget_get_name: + * + * arguments: + * + * results: + *****************************************/ + +gchar* +gtk_widget_get_name (GtkWidget *widget) +{ + g_return_val_if_fail (widget != NULL, NULL); + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + + if (widget->name) + return widget->name; + return gtk_type_name (GTK_WIDGET_TYPE (widget)); +} + +/***************************************** + * gtk_widget_set_state: + * + * arguments: + * widget + * state + * + * results: + *****************************************/ + +void +gtk_widget_set_state (GtkWidget *widget, + GtkStateType state) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (state == GTK_WIDGET_STATE (widget)) + return; + + if (state == GTK_STATE_INSENSITIVE) + gtk_widget_set_sensitive (widget, FALSE); + else + { + GtkStateData data; + + data.state = state; + data.state_restoration = FALSE; + data.use_forall = FALSE; + if (widget->parent) + data.parent_sensitive = (GTK_WIDGET_IS_SENSITIVE (widget->parent) != FALSE); + else + data.parent_sensitive = TRUE; + + gtk_widget_propagate_state (widget, &data); + + if (GTK_WIDGET_DRAWABLE (widget)) + gtk_widget_queue_clear (widget); + } +} + +void +gtk_widget_set_app_paintable (GtkWidget *widget, + gboolean app_paintable) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + app_paintable = (app_paintable != FALSE); + + if (GTK_WIDGET_APP_PAINTABLE (widget) != app_paintable) + { + if (app_paintable) + GTK_WIDGET_SET_FLAGS (widget, GTK_APP_PAINTABLE); + else + GTK_WIDGET_UNSET_FLAGS (widget, GTK_APP_PAINTABLE); + + if (GTK_WIDGET_DRAWABLE (widget)) + gtk_widget_queue_clear (widget); + } +} + +void +gtk_widget_set_double_buffered (GtkWidget *widget, + gboolean double_buffered) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (double_buffered) + GTK_WIDGET_SET_FLAGS (widget, GTK_DOUBLE_BUFFERED); + else + GTK_WIDGET_UNSET_FLAGS (widget, GTK_DOUBLE_BUFFERED); +} + +/***************************************** + * gtk_widget_set_sensitive: + * + * arguments: + * widget + * boolean value for sensitivity + * + * results: + *****************************************/ + +void +gtk_widget_set_sensitive (GtkWidget *widget, + gboolean sensitive) +{ + GtkStateData data; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + sensitive = (sensitive != FALSE); + + if (sensitive == (GTK_WIDGET_SENSITIVE (widget) != FALSE)) + return; + + if (sensitive) + { + GTK_WIDGET_SET_FLAGS (widget, GTK_SENSITIVE); + data.state = GTK_WIDGET_SAVED_STATE (widget); + } + else + { + GTK_WIDGET_UNSET_FLAGS (widget, GTK_SENSITIVE); + data.state = GTK_WIDGET_STATE (widget); + } + data.state_restoration = TRUE; + data.use_forall = TRUE; + + if (widget->parent) + data.parent_sensitive = (GTK_WIDGET_IS_SENSITIVE (widget->parent) != FALSE); + else + data.parent_sensitive = TRUE; + + gtk_widget_propagate_state (widget, &data); + if (GTK_WIDGET_DRAWABLE (widget)) + gtk_widget_queue_clear (widget); +} + +/***************************************** + * gtk_widget_set_parent: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_set_parent (GtkWidget *widget, + GtkWidget *parent) +{ + GtkStateData data; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (widget->parent == NULL); + g_return_if_fail (!GTK_WIDGET_TOPLEVEL (widget)); + g_return_if_fail (parent != NULL); + g_return_if_fail (GTK_IS_WIDGET (parent)); + g_return_if_fail (widget != parent); + + /* keep this function in sync with gtk_menu_attach_to_widget() + */ + + gtk_widget_ref (widget); + gtk_object_sink (GTK_OBJECT (widget)); + widget->parent = parent; + + if (GTK_WIDGET_STATE (parent) != GTK_STATE_NORMAL) + data.state = GTK_WIDGET_STATE (parent); + else + data.state = GTK_WIDGET_STATE (widget); + data.state_restoration = FALSE; + data.parent_sensitive = (GTK_WIDGET_IS_SENSITIVE (parent) != FALSE); + data.use_forall = GTK_WIDGET_IS_SENSITIVE (parent) != GTK_WIDGET_IS_SENSITIVE (widget); + + gtk_widget_propagate_state (widget, &data); + + gtk_widget_set_style_recurse (widget, NULL); + + gtk_signal_emit (GTK_OBJECT (widget), widget_signals[PARENT_SET], NULL); +} + +/***************************************** + * Widget styles + * see docs/styles.txt + *****************************************/ +void +gtk_widget_set_style (GtkWidget *widget, + GtkStyle *style) +{ + GtkStyle *default_style; + gboolean initial_emission; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (style != NULL); + + initial_emission = !GTK_WIDGET_RC_STYLE (widget) && !GTK_WIDGET_USER_STYLE (widget); + + GTK_WIDGET_UNSET_FLAGS (widget, GTK_RC_STYLE); + GTK_PRIVATE_SET_FLAG (widget, GTK_USER_STYLE); + + default_style = gtk_object_get_data_by_id (GTK_OBJECT (widget), saved_default_style_key_id); + if (!default_style) + { + gtk_style_ref (widget->style); + if (!saved_default_style_key_id) + saved_default_style_key_id = g_quark_from_static_string (saved_default_style_key); + gtk_object_set_data_by_id (GTK_OBJECT (widget), saved_default_style_key_id, widget->style); + } + + gtk_widget_set_style_internal (widget, style, initial_emission); +} + +void +gtk_widget_ensure_style (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (!GTK_WIDGET_USER_STYLE (widget) && + !GTK_WIDGET_RC_STYLE (widget)) + gtk_widget_set_rc_style (widget); +} + +void +gtk_widget_set_rc_style (GtkWidget *widget) +{ + GtkStyle *saved_style; + GtkStyle *new_style; + gboolean initial_emission; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + initial_emission = !GTK_WIDGET_RC_STYLE (widget) && !GTK_WIDGET_USER_STYLE (widget); + + GTK_PRIVATE_UNSET_FLAG (widget, GTK_USER_STYLE); + GTK_WIDGET_SET_FLAGS (widget, GTK_RC_STYLE); + + saved_style = gtk_object_get_data_by_id (GTK_OBJECT (widget), saved_default_style_key_id); + new_style = gtk_rc_get_style (widget); + if (new_style) + { + if (!saved_style) + { + gtk_style_ref (widget->style); + if (!saved_default_style_key_id) + saved_default_style_key_id = g_quark_from_static_string (saved_default_style_key); + gtk_object_set_data_by_id (GTK_OBJECT (widget), saved_default_style_key_id, widget->style); + } + gtk_widget_set_style_internal (widget, new_style, initial_emission); + } + else + { + if (saved_style) + { + g_assert (initial_emission == FALSE); /* FIXME: remove this line */ + + gtk_object_remove_data_by_id (GTK_OBJECT (widget), saved_default_style_key_id); + gtk_widget_set_style_internal (widget, saved_style, initial_emission); + gtk_style_unref (saved_style); + } + else + { + if (initial_emission) + gtk_widget_set_style_internal (widget, widget->style, TRUE); + } + } +} + +void +gtk_widget_restore_default_style (GtkWidget *widget) +{ + GtkStyle *default_style; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + GTK_PRIVATE_UNSET_FLAG (widget, GTK_USER_STYLE); + + default_style = gtk_object_get_data_by_id (GTK_OBJECT (widget), saved_default_style_key_id); + if (default_style) + { + gtk_object_remove_data_by_id (GTK_OBJECT (widget), saved_default_style_key_id); + gtk_widget_set_style_internal (widget, default_style, FALSE); + gtk_style_unref (default_style); + } +} + +GtkStyle* +gtk_widget_get_style (GtkWidget *widget) +{ + g_return_val_if_fail (widget != NULL, NULL); + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + + return widget->style; +} + +void +gtk_widget_modify_style (GtkWidget *widget, + GtkRcStyle *style) +{ + GtkRcStyle *old_style; + + if (!rc_style_key_id) + rc_style_key_id = g_quark_from_static_string (rc_style_key); + + old_style = gtk_object_get_data_by_id (GTK_OBJECT (widget), rc_style_key_id); + + if (style != old_style) + { + gtk_rc_style_ref (style); + + gtk_object_set_data_by_id_full (GTK_OBJECT (widget), + rc_style_key_id, + style, + (GtkDestroyNotify)gtk_rc_style_unref); + } + + if (GTK_WIDGET_RC_STYLE (widget)) + gtk_widget_set_rc_style (widget); +} + +static void +gtk_widget_style_set (GtkWidget *widget, + GtkStyle *previous_style) +{ + if (GTK_WIDGET_REALIZED (widget) && + !GTK_WIDGET_NO_WINDOW (widget)) + gtk_style_set_background (widget->style, widget->window, widget->state); +} + +static void +gtk_widget_set_style_internal (GtkWidget *widget, + GtkStyle *style, + gboolean initial_emission) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (style != NULL); + + if (widget->style != style) + { + GtkStyle *previous_style; + + if (GTK_WIDGET_REALIZED (widget)) + { + gtk_widget_reset_shapes (widget); + gtk_style_detach (widget->style); + } + + previous_style = widget->style; + widget->style = style; + gtk_style_ref (widget->style); + + if (GTK_WIDGET_REALIZED (widget)) + widget->style = gtk_style_attach (widget->style, widget->window); + + gtk_signal_emit (GTK_OBJECT (widget), + widget_signals[STYLE_SET], + initial_emission ? NULL : previous_style); + gtk_style_unref (previous_style); + + if (widget->parent && !initial_emission) + { + GtkRequisition old_requisition; + + old_requisition = widget->requisition; + gtk_widget_size_request (widget, NULL); + + if ((old_requisition.width != widget->requisition.width) || + (old_requisition.height != widget->requisition.height)) + gtk_widget_queue_resize (widget); + else if (GTK_WIDGET_DRAWABLE (widget)) + gtk_widget_queue_clear (widget); + } + } + else if (initial_emission) + { + gtk_signal_emit (GTK_OBJECT (widget), + widget_signals[STYLE_SET], + NULL); + } +} + +static void +gtk_widget_set_style_recurse (GtkWidget *widget, + gpointer client_data) +{ + if (GTK_WIDGET_RC_STYLE (widget)) + gtk_widget_set_rc_style (widget); + + if (GTK_IS_CONTAINER (widget)) + gtk_container_forall (GTK_CONTAINER (widget), + gtk_widget_set_style_recurse, + NULL); +} + +void +gtk_widget_reset_rc_styles (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + gtk_widget_set_style_recurse (widget, NULL); +} + +void +gtk_widget_set_default_style (GtkStyle *style) +{ + if (style != gtk_default_style) + { + if (gtk_default_style) + gtk_style_unref (gtk_default_style); + gtk_default_style = style; + if (gtk_default_style) + gtk_style_ref (gtk_default_style); + } +} + +GtkStyle* +gtk_widget_get_default_style (void) +{ + if (!gtk_default_style) + { + gtk_default_style = gtk_style_new (); + gtk_style_ref (gtk_default_style); + } + + return gtk_default_style; +} + +void +gtk_widget_push_style (GtkStyle *style) +{ + g_return_if_fail (style != NULL); + + gtk_style_ref (style); + style_stack = g_slist_prepend (style_stack, style); +} + +static GtkStyle* +gtk_widget_peek_style (void) +{ + if (style_stack) + return (GtkStyle*) style_stack->data; + else + return gtk_widget_get_default_style (); +} + +void +gtk_widget_pop_style (void) +{ + GSList *tmp; + + if (style_stack) + { + tmp = style_stack; + style_stack = style_stack->next; + gtk_style_unref ((GtkStyle*) tmp->data); + g_slist_free_1 (tmp); + } +} + +/** + * gtk_widget_create_pango_context: + * @widget: a #PangoWidget + * + * Create a new pango context with the appropriate colormap, + * font description, and base direction for drawing text for + * this widget. + * + * Return value: the new #PangoContext + **/ +PangoContext * +gtk_widget_create_pango_context (GtkWidget *widget) +{ + PangoContext *context; + char *lang, *p; + + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + + context = gdk_pango_context_get (); + + gdk_pango_context_set_colormap (context, gtk_widget_get_colormap (widget)); + pango_context_set_base_dir (context, + gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ? + PANGO_DIRECTION_LTR : PANGO_DIRECTION_RTL); + pango_context_set_font_description (context, widget->style->font_desc); + + lang = g_strdup (setlocale (LC_CTYPE, NULL)); + p = strchr (lang, '.'); + if (p) + *p = '\0'; + p = strchr (lang, '@'); + if (p) + *p = '\0'; + + pango_context_set_lang (context, lang); + g_free (lang); + + return context; +} + +/** + * gtk_widget_create_pango_layout: + * @widget: a #PangoWidget + * + * Create a new #PangoLayout with the appropriate colormap, + * font description, and base direction for drawing text for + * this widget. + * + * Return value: the new #PangoLayout + **/ +PangoLayout * +gtk_widget_create_pango_layout (GtkWidget *widget) +{ + PangoLayout *layout; + PangoContext *context; + + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + + context = gtk_widget_create_pango_context (widget); + layout = pango_layout_new (context); + pango_context_unref (context); + + return layout; +} + +/************************************************************* + * gtk_widget_set_parent_window: + * Set a non default parent window for widget + * + * arguments: + * widget: + * parent_window + * + * results: + *************************************************************/ + +void +gtk_widget_set_parent_window (GtkWidget *widget, + GdkWindow *parent_window) +{ + GdkWindow *old_parent_window; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + old_parent_window = gtk_object_get_data_by_id (GTK_OBJECT (widget), + parent_window_key_id); + + if (parent_window != old_parent_window) + { + if (!parent_window_key_id) + parent_window_key_id = g_quark_from_static_string (parent_window_key); + gtk_object_set_data_by_id (GTK_OBJECT (widget), parent_window_key_id, + parent_window); + if (old_parent_window) + gdk_window_unref (old_parent_window); + if (parent_window) + gdk_window_ref (parent_window); + } +} + +/************************************************************* + * gtk_widget_get_parent_window: + * Get widget's parent window + * + * arguments: + * widget: + * + * results: + * parent window + *************************************************************/ + +GdkWindow * +gtk_widget_get_parent_window (GtkWidget *widget) +{ + GdkWindow *parent_window; + + g_return_val_if_fail (widget != NULL, NULL); + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + g_return_val_if_fail (widget->parent != NULL, NULL); + + parent_window = gtk_object_get_data_by_id (GTK_OBJECT (widget), + parent_window_key_id); + + return (parent_window != NULL) ? parent_window : widget->parent->window; +} + +/***************************************** + * gtk_widget_set_uposition: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_set_uposition (GtkWidget *widget, + gint x, + gint y) +{ + GtkWidgetAuxInfo *aux_info; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + aux_info = gtk_object_get_data_by_id (GTK_OBJECT (widget), aux_info_key_id); + if (!aux_info) + { + if (!aux_info_key_id) + aux_info_key_id = g_quark_from_static_string (aux_info_key); + aux_info = gtk_widget_aux_info_new (); + gtk_object_set_data_by_id (GTK_OBJECT (widget), aux_info_key_id, aux_info); + } + + /* keep this in sync with gtk_window_compute_reposition() */ + + if (x > -2) + aux_info->x = x; + if (y > -2) + aux_info->y = y; + + if (GTK_IS_WINDOW (widget) && (aux_info->x != -1) && (aux_info->y != -1)) + gtk_window_reposition (GTK_WINDOW (widget), x, y); + + if (GTK_WIDGET_VISIBLE (widget) && widget->parent) + gtk_widget_size_allocate (widget, &widget->allocation); +} + +/***************************************** + * gtk_widget_set_usize: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_set_usize (GtkWidget *widget, + gint width, + gint height) +{ + GtkWidgetAuxInfo *aux_info; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + aux_info = gtk_object_get_data_by_id (GTK_OBJECT (widget), aux_info_key_id); + if (!aux_info) + { + if (!aux_info_key_id) + aux_info_key_id = g_quark_from_static_string (aux_info_key); + aux_info = gtk_widget_aux_info_new (); + gtk_object_set_data_by_id (GTK_OBJECT (widget), aux_info_key_id, aux_info); + } + + if (width > -2) + aux_info->width = width; + if (height > -2) + aux_info->height = height; + + if (GTK_WIDGET_VISIBLE (widget)) + gtk_widget_queue_resize (widget); +} + +/***************************************** + * gtk_widget_set_events: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_set_events (GtkWidget *widget, + gint events) +{ + gint *eventp; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (!GTK_WIDGET_NO_WINDOW (widget)); + g_return_if_fail (!GTK_WIDGET_REALIZED (widget)); + + eventp = gtk_object_get_data_by_id (GTK_OBJECT (widget), event_key_id); + + if (events) + { + if (!eventp) + eventp = g_new (gint, 1); + + *eventp = events; + if (!event_key_id) + event_key_id = g_quark_from_static_string (event_key); + gtk_object_set_data_by_id (GTK_OBJECT (widget), event_key_id, eventp); + } + else if (eventp) + { + g_free (eventp); + gtk_object_remove_data_by_id (GTK_OBJECT (widget), event_key_id); + } +} + +/***************************************** + * gtk_widget_add_events: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_add_events (GtkWidget *widget, + gint events) +{ + gint *eventp; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (!GTK_WIDGET_NO_WINDOW (widget)); + + eventp = gtk_object_get_data_by_id (GTK_OBJECT (widget), event_key_id); + + if (events) + { + if (!eventp) + { + eventp = g_new (gint, 1); + *eventp = 0; + } + + *eventp |= events; + if (!event_key_id) + event_key_id = g_quark_from_static_string (event_key); + gtk_object_set_data_by_id (GTK_OBJECT (widget), event_key_id, eventp); + } + else if (eventp) + { + g_free (eventp); + gtk_object_remove_data_by_id (GTK_OBJECT (widget), event_key_id); + } + + if (GTK_WIDGET_REALIZED (widget)) + { + gdk_window_set_events (widget->window, + gdk_window_get_events (widget->window) | events); + } +} + +/***************************************** + * gtk_widget_set_extension_events: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_set_extension_events (GtkWidget *widget, + GdkExtensionMode mode) +{ + GdkExtensionMode *modep; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + modep = gtk_object_get_data_by_id (GTK_OBJECT (widget), extension_event_key_id); + + if (!modep) + modep = g_new (GdkExtensionMode, 1); + + *modep = mode; + if (!extension_event_key_id) + extension_event_key_id = g_quark_from_static_string (extension_event_key); + gtk_object_set_data_by_id (GTK_OBJECT (widget), extension_event_key_id, modep); +} + +/***************************************** + * gtk_widget_get_toplevel: + * + * arguments: + * + * results: + *****************************************/ + +GtkWidget* +gtk_widget_get_toplevel (GtkWidget *widget) +{ + g_return_val_if_fail (widget != NULL, NULL); + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + + while (widget->parent) + widget = widget->parent; + + return widget; +} + +/***************************************** + * gtk_widget_get_ancestor: + * + * arguments: + * + * results: + *****************************************/ + +GtkWidget* +gtk_widget_get_ancestor (GtkWidget *widget, + GtkType widget_type) +{ + g_return_val_if_fail (widget != NULL, NULL); + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + + while (widget && !gtk_type_is_a (GTK_WIDGET_TYPE (widget), widget_type)) + widget = widget->parent; + + if (!(widget && gtk_type_is_a (GTK_WIDGET_TYPE (widget), widget_type))) + return NULL; + + return widget; +} + +/***************************************** + * gtk_widget_get_colormap: + * + * arguments: + * + * results: + *****************************************/ + +GdkColormap* +gtk_widget_get_colormap (GtkWidget *widget) +{ + GdkColormap *colormap; + + g_return_val_if_fail (widget != NULL, NULL); + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + + if (widget->window) + { + colormap = gdk_window_get_colormap (widget->window); + /* If window was destroyed previously, we'll get NULL here */ + if (colormap) + return colormap; + } + + colormap = gtk_object_get_data (GTK_OBJECT (widget), colormap_key); + if (colormap) + return colormap; + + return gtk_widget_get_default_colormap (); +} + +/***************************************** + * gtk_widget_get_visual: + * + * arguments: + * + * results: + *****************************************/ + +GdkVisual* +gtk_widget_get_visual (GtkWidget *widget) +{ + GdkVisual *visual; + + g_return_val_if_fail (widget != NULL, NULL); + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + + if (widget->window) + { + visual = gdk_window_get_visual (widget->window); + /* If window was destroyed previously, we'll get NULL here */ + if (visual) + return visual; + } + + visual = gtk_object_get_data (GTK_OBJECT (widget), visual_key); + if (visual) + return visual; + + return gtk_widget_get_default_visual (); +} + +/***************************************** + * gtk_widget_set_colormap: + * Set the colormap for the widget to the given + * value. Widget must not have been previously + * realized. This probably should only be used + * from an init() function. + * arguments: + * widget: + * colormap: + * results: + *****************************************/ + +void +gtk_widget_set_colormap (GtkWidget *widget, GdkColormap *colormap) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (!GTK_WIDGET_REALIZED (widget)); + g_return_if_fail (colormap != NULL); + + /* FIXME: reference count the colormap. + */ + + gtk_object_set_data (GTK_OBJECT (widget), + colormap_key, + colormap); +} + +/***************************************** + * gtk_widget_set_visual: + * Set the colormap for the widget to the given + * value. Widget must not have been previously + * realized. This probably should only be used + * from an init() function. + * arguments: + * widget: + * visual: + * results: + *****************************************/ + +void +gtk_widget_set_visual (GtkWidget *widget, GdkVisual *visual) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (!GTK_WIDGET_REALIZED (widget)); + g_return_if_fail (visual != NULL); + + gtk_object_set_data (GTK_OBJECT (widget), + visual_key, + visual); +} + +/***************************************** + * gtk_widget_get_events: + * + * arguments: + * + * results: + *****************************************/ + +gint +gtk_widget_get_events (GtkWidget *widget) +{ + gint *events; + + g_return_val_if_fail (widget != NULL, 0); + g_return_val_if_fail (GTK_IS_WIDGET (widget), 0); + + events = gtk_object_get_data_by_id (GTK_OBJECT (widget), event_key_id); + if (events) + return *events; + + return 0; +} + +/***************************************** + * gtk_widget_get_extension_events: + * + * arguments: + * + * results: + *****************************************/ + +GdkExtensionMode +gtk_widget_get_extension_events (GtkWidget *widget) +{ + GdkExtensionMode *mode; + + g_return_val_if_fail (widget != NULL, 0); + g_return_val_if_fail (GTK_IS_WIDGET (widget), 0); + + mode = gtk_object_get_data_by_id (GTK_OBJECT (widget), extension_event_key_id); + if (mode) + return *mode; + + return 0; +} + +/***************************************** + * gtk_widget_get_pointer: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_get_pointer (GtkWidget *widget, + gint *x, + gint *y) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (x) + *x = -1; + if (y) + *y = -1; + + if (GTK_WIDGET_REALIZED (widget)) + { + gdk_window_get_pointer (widget->window, x, y, NULL); + + if (GTK_WIDGET_NO_WINDOW (widget)) + { + if (x) + *x -= widget->allocation.x; + if (y) + *y -= widget->allocation.y; + } + } +} + +/***************************************** + * gtk_widget_is_ancestor: + * + * arguments: + * + * results: + *****************************************/ + +gint +gtk_widget_is_ancestor (GtkWidget *widget, + GtkWidget *ancestor) +{ + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + g_return_val_if_fail (ancestor != NULL, FALSE); + + while (widget) + { + if (widget->parent == ancestor) + return TRUE; + widget = widget->parent; + } + + return FALSE; +} + +static GQuark quark_composite_name = 0; + +void +gtk_widget_set_composite_name (GtkWidget *widget, + const gchar *name) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (GTK_WIDGET_COMPOSITE_CHILD (widget)); + g_return_if_fail (name != NULL); + + if (!quark_composite_name) + quark_composite_name = g_quark_from_static_string ("gtk-composite-name"); + + gtk_object_set_data_by_id_full (GTK_OBJECT (widget), + quark_composite_name, + g_strdup (name), + g_free); +} + +gchar* +gtk_widget_get_composite_name (GtkWidget *widget) +{ + g_return_val_if_fail (widget != NULL, NULL); + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + + if (GTK_WIDGET_COMPOSITE_CHILD (widget) && widget->parent) + return gtk_container_child_composite_name (GTK_CONTAINER (widget->parent), + widget); + else + return NULL; +} + +void +gtk_widget_push_composite_child (void) +{ + composite_child_stack++; +} + +void +gtk_widget_pop_composite_child (void) +{ + if (composite_child_stack) + composite_child_stack--; +} + +/***************************************** + * gtk_widget_push_colormap: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_push_colormap (GdkColormap *cmap) +{ + g_return_if_fail (cmap != NULL); + + colormap_stack = g_slist_prepend (colormap_stack, cmap); +} + +/***************************************** + * gtk_widget_push_visual: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_push_visual (GdkVisual *visual) +{ + g_return_if_fail (visual != NULL); + + visual_stack = g_slist_prepend (visual_stack, visual); +} + +/***************************************** + * gtk_widget_pop_colormap: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_pop_colormap (void) +{ + GSList *tmp; + + if (colormap_stack) + { + tmp = colormap_stack; + colormap_stack = colormap_stack->next; + g_slist_free_1 (tmp); + } +} + +/***************************************** + * gtk_widget_pop_visual: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_pop_visual (void) +{ + GSList *tmp; + + if (visual_stack) + { + tmp = visual_stack; + visual_stack = visual_stack->next; + g_slist_free_1 (tmp); + } +} + +/***************************************** + * gtk_widget_set_default_colormap: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_set_default_colormap (GdkColormap *colormap) +{ + if (default_colormap != colormap) + { + if (default_colormap) + gdk_colormap_unref (default_colormap); + default_colormap = colormap; + if (default_colormap) + gdk_colormap_ref (default_colormap); + } +} + +/***************************************** + * gtk_widget_set_default_visual: + * + * arguments: + * + * results: + *****************************************/ + +void +gtk_widget_set_default_visual (GdkVisual *visual) +{ + default_visual = visual; +} + +/***************************************** + * gtk_widget_get_default_colormap: + * + * arguments: + * + * results: + *****************************************/ + +GdkColormap* +gtk_widget_get_default_colormap (void) +{ + if (!default_colormap) + default_colormap = gdk_colormap_get_system (); + + return default_colormap; +} + +/***************************************** + * gtk_widget_get_default_visual: + * + * arguments: + * + * results: + *****************************************/ + +GdkVisual* +gtk_widget_get_default_visual (void) +{ + if (!default_visual) + default_visual = gdk_visual_get_system (); + + return default_visual; +} + +/** + * gtk_widget_set_direction: + * @widget: a #GtkWidget + * @dir: the new direction + * + * Set the reading direction on a particular widget. This direction + * controls the primary direction for widgets containing text, + * and also the direction in which the children of a container are + * packed. The ability to set the direction is present in order + * so that correct localization into languages with right-to-left + * reading directions can be done. Generally, applications will + * let the default reading direction present, except for containers + * where the containers are arranged in an order that is explicitely + * visual rather than logical (such as buttons for text justificiation). + * + * If the direction is set to %GTK_TEXT_DIR_NONE, then the value + * set by gtk_widget_set_default_direction() will be used. + **/ +void +gtk_widget_set_direction (GtkWidget *widget, + GtkTextDirection dir) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (dir >= GTK_TEXT_DIR_NONE && dir <= GTK_TEXT_DIR_RTL); + + if (dir == GTK_TEXT_DIR_NONE) + GTK_PRIVATE_UNSET_FLAG (widget, GTK_DIRECTION_SET); + else + { + GTK_PRIVATE_SET_FLAG (widget, GTK_DIRECTION_SET); + if (dir == GTK_TEXT_DIR_LTR) + GTK_PRIVATE_SET_FLAG (widget, GTK_DIRECTION_LTR); + else + GTK_PRIVATE_UNSET_FLAG (widget, GTK_DIRECTION_LTR); + } +} + +/** + * gtk_widget_get_direction: + * @widget: a #GtkWidget + * + * Get the reading direction for a particular widget. See + * gtk_widget_set_direction(). + * + * Return value: the reading direction for the widget. + **/ +GtkTextDirection +gtk_widget_get_direction (GtkWidget *widget) +{ + g_return_val_if_fail (widget != NULL, GTK_TEXT_DIR_LTR); + g_return_val_if_fail (GTK_IS_WIDGET (widget), GTK_TEXT_DIR_LTR); + + if (GTK_WIDGET_DIRECTION_SET (widget)) + return GTK_WIDGET_DIRECTION_LTR (widget) ? GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL; + else + return gtk_default_direction; +} + +/** + * gtk_widget_set_default_direction: + * @dir: the new default direction. This cannot be + * %GTK_TEXT_DIR_NONE. + * + * Set the default reading direction for widgets where the + * direction has not been explicitly set by gtk_widget_set_direction(). + **/ +void +gtk_widget_set_default_direction (GtkTextDirection dir) +{ + g_return_if_fail (dir == GTK_TEXT_DIR_RTL || dir == GTK_TEXT_DIR_LTR); + + gtk_default_direction = dir; +} + +/** + * gtk_widget_get_default_direction: + * + * Return value: the current default direction. See + * gtk_widget_set_direction(). + **/ +GtkTextDirection +gtk_widget_get_default_direction (void) +{ + return gtk_default_direction; +} + +static void +gtk_widget_shutdown (GObject *object) +{ + GtkWidget *widget = GTK_WIDGET (object); + + if (widget->parent) + gtk_container_remove (GTK_CONTAINER (widget->parent), widget); + + GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE); + if (GTK_WIDGET_REALIZED (widget)) + gtk_widget_unrealize (widget); + + G_OBJECT_CLASS (parent_class)->shutdown (object); +} + +static void +gtk_widget_real_destroy (GtkObject *object) +{ + GtkWidget *widget; + GtkStyle *saved_style; + + /* gtk_object_destroy() will already hold a refcount on object + */ + widget = GTK_WIDGET (object); + + gtk_grab_remove (widget); + gtk_selection_remove_all (widget); + + saved_style = gtk_object_get_data_by_id (object, saved_default_style_key_id); + if (saved_style) + { + gtk_style_unref (saved_style); + gtk_object_remove_data_by_id (object, saved_default_style_key_id); + } + + gtk_style_unref (widget->style); + widget->style = gtk_widget_peek_style (); + gtk_style_ref (widget->style); + + GTK_OBJECT_CLASS (parent_class)->destroy (object); +} + +static void +gtk_widget_finalize (GObject *object) +{ + GtkWidget *widget = GTK_WIDGET (object); + GtkWidgetAuxInfo *aux_info; + gint *events; + GdkExtensionMode *mode; + GtkStyle *saved_style; + + gtk_grab_remove (widget); + gtk_selection_remove_all (widget); + + saved_style = gtk_object_get_data_by_id (GTK_OBJECT (widget), saved_default_style_key_id); + if (saved_style) + { + gtk_style_unref (saved_style); + gtk_object_remove_data_by_id (GTK_OBJECT (widget), saved_default_style_key_id); + } + + gtk_style_unref (widget->style); + widget->style = NULL; + + if (widget->name) + g_free (widget->name); + + aux_info = gtk_object_get_data_by_id (GTK_OBJECT (widget), aux_info_key_id); + if (aux_info) + gtk_widget_aux_info_destroy (aux_info); + + events = gtk_object_get_data_by_id (GTK_OBJECT (widget), event_key_id); + if (events) + g_free (events); + + mode = gtk_object_get_data_by_id (GTK_OBJECT (widget), extension_event_key_id); + if (mode) + g_free (mode); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +/***************************************** + * gtk_widget_real_map: + * + * arguments: + * + * results: + *****************************************/ + +static void +gtk_widget_real_map (GtkWidget *widget) +{ + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (GTK_WIDGET_REALIZED (widget) == TRUE); + + if (!GTK_WIDGET_MAPPED (widget)) + { + GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED); + + if (!GTK_WIDGET_NO_WINDOW (widget)) + gdk_window_show (widget->window); + } +} + +/***************************************** + * gtk_widget_real_unmap: + * + * arguments: + * + * results: + *****************************************/ + +static void +gtk_widget_real_unmap (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (GTK_WIDGET_MAPPED (widget)) + { + GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED); + + if (!GTK_WIDGET_NO_WINDOW (widget)) + gdk_window_hide (widget->window); + } +} + +/***************************************** + * gtk_widget_real_realize: + * + * arguments: + * + * results: + *****************************************/ + +static void +gtk_widget_real_realize (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (GTK_WIDGET_NO_WINDOW (widget)); + + GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); + if (widget->parent) + { + widget->window = gtk_widget_get_parent_window (widget); + gdk_window_ref (widget->window); + } + widget->style = gtk_style_attach (widget->style, widget->window); +} + +/***************************************** + * gtk_widget_real_unrealize: + * + * arguments: + * + * results: + *****************************************/ + +static void +gtk_widget_real_unrealize (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + if (GTK_WIDGET_MAPPED (widget)) + gtk_widget_real_unmap (widget); + + GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED); + + /* printf ("unrealizing %s\n", gtk_type_name (GTK_OBJECT (widget)->klass->type)); + */ + + /* We must do unrealize child widget BEFORE container widget. + * gdk_window_destroy() destroys specified xwindow and its sub-xwindows. + * So, unrealizing container widget bofore its children causes the problem + * (for example, gdk_ic_destroy () with destroyed window causes crash. ) + */ + + if (GTK_IS_CONTAINER (widget)) + gtk_container_forall (GTK_CONTAINER (widget), + (GtkCallback) gtk_widget_unrealize, + NULL); + + gtk_style_detach (widget->style); + if (!GTK_WIDGET_NO_WINDOW (widget)) + { + gdk_window_set_user_data (widget->window, NULL); + gdk_window_destroy (widget->window); + widget->window = NULL; + } + else + { + gdk_window_unref (widget->window); + widget->window = NULL; + } + + GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED); +} + +static void +gtk_widget_real_draw (GtkWidget *widget, + GdkRectangle *area) +{ + GdkEventExpose event; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (area != NULL); + + if (GTK_WIDGET_DRAWABLE (widget)) + { + event.type = GDK_EXPOSE; + event.send_event = TRUE; + event.window = widget->window; + event.area = *area; + event.count = 0; + + gdk_window_ref (event.window); + gtk_widget_event (widget, (GdkEvent*) &event); + gdk_window_unref (event.window); + } +} + +static void +gtk_widget_real_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + requisition->width = widget->requisition.width; + requisition->height = widget->requisition.height; +} + +/***************************************** + * gtk_widget_peek_colormap: + * + * arguments: + * + * results: + *****************************************/ + +static GdkColormap* +gtk_widget_peek_colormap (void) +{ + if (colormap_stack) + return (GdkColormap*) colormap_stack->data; + return gtk_widget_get_default_colormap (); +} + +/***************************************** + * gtk_widget_peek_visual: + * + * arguments: + * + * results: + *****************************************/ + +static GdkVisual* +gtk_widget_peek_visual (void) +{ + if (visual_stack) + return (GdkVisual*) visual_stack->data; + return gtk_widget_get_default_visual (); +} + +static void +gtk_widget_propagate_state (GtkWidget *widget, + GtkStateData *data) +{ + guint8 old_state; + + /* don't call this function with state==GTK_STATE_INSENSITIVE, + * parent_sensitive==TRUE on a sensitive widget + */ + + old_state = GTK_WIDGET_STATE (widget); + + if (data->parent_sensitive) + { + GTK_WIDGET_SET_FLAGS (widget, GTK_PARENT_SENSITIVE); + + if (GTK_WIDGET_IS_SENSITIVE (widget)) + { + if (data->state_restoration) + GTK_WIDGET_STATE (widget) = GTK_WIDGET_SAVED_STATE (widget); + else + GTK_WIDGET_STATE (widget) = data->state; + } + else + { + GTK_WIDGET_STATE (widget) = GTK_STATE_INSENSITIVE; + if (!data->state_restoration && + data->state != GTK_STATE_INSENSITIVE) + GTK_WIDGET_SAVED_STATE (widget) = data->state; + } + } + else + { + GTK_WIDGET_UNSET_FLAGS (widget, GTK_PARENT_SENSITIVE); + if (!data->state_restoration) + { + if (data->state != GTK_STATE_INSENSITIVE) + GTK_WIDGET_SAVED_STATE (widget) = data->state; + } + else if (GTK_WIDGET_STATE (widget) != GTK_STATE_INSENSITIVE) + GTK_WIDGET_SAVED_STATE (widget) = GTK_WIDGET_STATE (widget); + GTK_WIDGET_STATE (widget) = GTK_STATE_INSENSITIVE; + } + + if (GTK_WIDGET_HAS_FOCUS (widget) && !GTK_WIDGET_IS_SENSITIVE (widget)) + { + GtkWidget *window; + + window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW); + if (window) + gtk_window_set_focus (GTK_WINDOW (window), NULL); + } + + if (old_state != GTK_WIDGET_STATE (widget)) + { + gtk_widget_ref (widget); + gtk_signal_emit (GTK_OBJECT (widget), widget_signals[STATE_CHANGED], old_state); + + if (GTK_IS_CONTAINER (widget)) + { + data->parent_sensitive = (GTK_WIDGET_IS_SENSITIVE (widget) != FALSE); + data->state = GTK_WIDGET_STATE (widget); + if (data->use_forall) + gtk_container_forall (GTK_CONTAINER (widget), + (GtkCallback) gtk_widget_propagate_state, + data); + else + gtk_container_foreach (GTK_CONTAINER (widget), + (GtkCallback) gtk_widget_propagate_state, + data); + } + gtk_widget_unref (widget); + } +} + +/***************************************** + * gtk_widget_aux_info_new: + * + * arguments: + * + * results: + *****************************************/ + +static GtkWidgetAuxInfo* +gtk_widget_aux_info_new (void) +{ + GtkWidgetAuxInfo *aux_info; + + if (!aux_info_mem_chunk) + aux_info_mem_chunk = g_mem_chunk_new ("widget aux info mem chunk", + sizeof (GtkWidgetAuxInfo), + 1024, G_ALLOC_AND_FREE); + + aux_info = g_chunk_new (GtkWidgetAuxInfo, aux_info_mem_chunk); + + aux_info->x = -1; + aux_info->y = -1; + aux_info->width = 0; + aux_info->height = 0; + + return aux_info; +} + +/***************************************** + * gtk_widget_aux_info_destroy: + * + * arguments: + * + * results: + *****************************************/ + +static void +gtk_widget_aux_info_destroy (GtkWidgetAuxInfo *aux_info) +{ + g_return_if_fail (aux_info != NULL); + + g_mem_chunk_free (aux_info_mem_chunk, aux_info); +} + +static void +gtk_widget_shape_info_destroy (GtkWidgetShapeInfo *info) +{ + gdk_drawable_unref (info->shape_mask); + g_free (info); +} + +/***************************************** + * gtk_widget_shape_combine_mask: + * set a shape for this widgets' gdk window, this allows for + * transparent windows etc., see gdk_window_shape_combine_mask + * for more information + * + * arguments: + * + * results: + *****************************************/ +void +gtk_widget_shape_combine_mask (GtkWidget *widget, + GdkBitmap *shape_mask, + gint offset_x, + gint offset_y) +{ + GtkWidgetShapeInfo* shape_info; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + /* set_shape doesn't work on widgets without gdk window */ + g_return_if_fail (!GTK_WIDGET_NO_WINDOW (widget)); + + if (!shape_mask) + { + GTK_PRIVATE_UNSET_FLAG (widget, GTK_HAS_SHAPE_MASK); + + if (widget->window) + gdk_window_shape_combine_mask (widget->window, NULL, 0, 0); + + gtk_object_remove_data (GTK_OBJECT (widget), shape_info_key); + } + else + { + GTK_PRIVATE_SET_FLAG (widget, GTK_HAS_SHAPE_MASK); + + shape_info = g_new (GtkWidgetShapeInfo, 1); + gtk_object_set_data_full (GTK_OBJECT (widget), shape_info_key, shape_info, + (GDestroyNotify)gtk_widget_shape_info_destroy); + + shape_info->shape_mask = gdk_drawable_ref (shape_mask); + shape_info->offset_x = offset_x; + shape_info->offset_y = offset_y; + + /* set shape if widget has a gdk window allready. + * otherwise the shape is scheduled to be set by gtk_widget_realize. + */ + if (widget->window) + gdk_window_shape_combine_mask (widget->window, shape_mask, + offset_x, offset_y); + } +} + +static void +gtk_reset_shapes_recurse (GtkWidget *widget, + GdkWindow *window) +{ + GdkWindowObject *private; + gpointer data; + GList *list; + + private = (GdkWindowObject*) window; + + gdk_window_get_user_data (window, &data); + if (data != widget) + return; + + gdk_window_shape_combine_mask (window, NULL, 0, 0); + for (list = private->children; list; list = list->next) + gtk_reset_shapes_recurse (widget, list->data); +} + +void +gtk_widget_reset_shapes (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (GTK_WIDGET_REALIZED (widget)); + + if (!GTK_WIDGET_HAS_SHAPE_MASK (widget)) + gtk_reset_shapes_recurse (widget, widget->window); +} + +GtkWidget* +gtk_widget_ref (GtkWidget *widget) +{ + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + + return (GtkWidget*) g_object_ref ((GObject*) widget); +} + +void +gtk_widget_unref (GtkWidget *widget) +{ + g_return_if_fail (GTK_IS_WIDGET (widget)); + + g_object_unref ((GObject*) widget); +} + +void +gtk_widget_path (GtkWidget *widget, + guint *path_length_p, + gchar **path_p, + gchar **path_reversed_p) +{ + static gchar *rev_path = NULL; + static guint path_len = 0; + guint len; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + len = 0; + do + { + gchar *string; + gchar *d, *s; + guint l; + + string = gtk_widget_get_name (widget); + l = strlen (string); + while (path_len <= len + l + 1) + { + path_len += INIT_PATH_SIZE; + rev_path = g_realloc (rev_path, path_len); + } + s = string + l - 1; + d = rev_path + len; + while (s >= string) + *(d++) = *(s--); + len += l; + + widget = widget->parent; + + if (widget) + rev_path[len++] = '.'; + else + rev_path[len++] = 0; + } + while (widget); + + if (path_length_p) + *path_length_p = len - 1; + if (path_reversed_p) + *path_reversed_p = g_strdup (rev_path); + if (path_p) + { + *path_p = g_strdup (rev_path); + g_strreverse (*path_p); + } +} + +void +gtk_widget_class_path (GtkWidget *widget, + guint *path_length_p, + gchar **path_p, + gchar **path_reversed_p) +{ + static gchar *rev_path = NULL; + static guint path_len = 0; + guint len; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + len = 0; + do + { + gchar *string; + gchar *d, *s; + guint l; + + string = gtk_type_name (GTK_WIDGET_TYPE (widget)); + l = strlen (string); + while (path_len <= len + l + 1) + { + path_len += INIT_PATH_SIZE; + rev_path = g_realloc (rev_path, path_len); + } + s = string + l - 1; + d = rev_path + len; + while (s >= string) + *(d++) = *(s--); + len += l; + + widget = widget->parent; + + if (widget) + rev_path[len++] = '.'; + else + rev_path[len++] = 0; + } + while (widget); + + if (path_length_p) + *path_length_p = len - 1; + if (path_reversed_p) + *path_reversed_p = g_strdup (rev_path); + if (path_p) + { + *path_p = g_strdup (rev_path); + g_strreverse (*path_p); + } +} |