Actually does:
        1. Make threading work.
        2. Fix some warnings.
        3. Tidy up the .spec file.
        4. Wrap more functions (mostly tree stuff).

-- Elliot
? autom4te.cache
? obj
? t.py
Index: configure.in
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/configure.in,v
retrieving revision 1.45
diff -u -b -r1.45 configure.in
--- configure.in        2001/09/30 09:42:28     1.45
+++ configure.in        2001/10/03 15:31:42
@@ -46,7 +46,7 @@
   AC_MSG_RESULT(no)
 fi
 
-AM_PATH_GLIB_2_0(1.3.9,,[AC_MSG_ERROR(maybe you want the gtk-gnome-1-2 
branch?)],gobject)
+AM_PATH_GLIB_2_0(1.3.9,,[AC_MSG_ERROR(maybe you want the gtk-gnome-1-2 
+branch?)],gobject $extra_mods)
 PKG_CHECK_MODULES(PANGO, pango >= 0.20,,[AC_MSG_ERROR(maybe you want the 
gtk-gnome-1-2 branch?)])
 AC_SUBST(PANGO_CFLAGS)
 AC_SUBST(PANGO_LIBS)
Index: gobjectmodule.c
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gobjectmodule.c,v
retrieving revision 1.58
diff -u -b -r1.58 gobjectmodule.c
--- gobjectmodule.c     2001/10/02 18:44:53     1.58
+++ gobjectmodule.c     2001/10/03 15:31:42
@@ -1,4 +1,6 @@
 /* -*- Mode: C; c-basic-offset: 4 -*- */
+#include "config.h"
+
 #define _INSIDE_PYGOBJECT_
 #include "pygobject.h"
 
@@ -10,6 +12,8 @@
 staticforward PyTypeObject PyGObject_Type;
 static void pygobject_dealloc(PyGObject *self);
 static int  pygobject_traverse(PyGObject *self, visitproc visit, void *arg);
+static void pyg_block_threads(void);
+static void pyg_unblock_threads(void);
 
 static void
 object_free(PyObject *op)
@@ -50,7 +54,7 @@
     char buf[80];
     const gchar *name = g_type_name(self->type);
 
-    g_snprintf(buf, sizeof(buf), "<GType %s>",
+    g_snprintf(buf, sizeof(buf), "<GType %s (%u)>",
               name?name:"invalid", self->type);
     return PyString_FromString(buf);
 }
@@ -221,9 +225,9 @@
 {
     PyObject *obj = (PyObject *)user_data;
 
-    /* PyGTK_BLOCK_THREADS */
+    pyg_block_threads();
     Py_DECREF(obj);
-    /* PyGTK_UNBLOCK_THREADS */
+    pyg_unblock_threads();
 }
 
 static void
@@ -487,8 +491,8 @@
     PyGBoxed *self;
     PyTypeObject *tp;
 
-    g_return_if_fail(boxed_type != 0);
-    g_return_if_fail(!copy_boxed || (copy_boxed && own_ref));
+    g_return_val_if_fail(boxed_type != 0, NULL);
+    g_return_val_if_fail(!copy_boxed || (copy_boxed && own_ref), NULL);
 
     if (!boxed) {
        Py_INCREF(Py_None);
@@ -891,15 +895,16 @@
     PyObject *swap_data; /* other object for gtk_signal_connect_object */
 };
 
-/* XXXX - must handle multithreadedness here */
 static void
 pyg_closure_destroy(gpointer data, GClosure *closure)
 {
     PyGClosure *pc = (PyGClosure *)closure;
 
+    pyg_block_threads();
     Py_DECREF(pc->callback);
     Py_XDECREF(pc->extra_args);
     Py_XDECREF(pc->swap_data);
+    pyg_unblock_threads();
 }
 
 /* XXXX - need to handle python thread context stuff */
@@ -915,6 +920,7 @@
     PyObject *params, *ret;
     guint i;
 
+    pyg_block_threads();
     /* construct Python tuple for the parameter values */
     params = PyTuple_New(n_param_values);
     for (i = 0; i < n_param_values; i++) {
@@ -929,7 +935,7 @@
            /* error condition */
            if (!item) {
                Py_DECREF(params);
-               /* XXXX - clean up if threading was used */
+               pyg_unblock_threads();
                return;
            }
            PyTuple_SetItem(params, i, item);
@@ -946,13 +952,13 @@
        /* XXXX - do fatal exceptions thing here */
        PyErr_Print();
        PyErr_Clear();
-       /* XXXX - clean up if threading was used */
+       pyg_unblock_threads();
        return;
     }
     if (return_value)
        pyg_value_from_pyobject(return_value, ret);
     Py_DECREF(ret);
-    /* XXXX - clean up if threading was used */
+    pyg_unblock_threads();
 }
 
 static GClosure *
@@ -972,7 +978,7 @@
     }
     if (swap_data) {
        Py_INCREF(swap_data);
-       ((PyGClosure *)closure)->swap_data;
+       ((PyGClosure *)closure)->swap_data = swap_data;
        closure->derivative_flag = TRUE;
     }
     return closure;
@@ -1007,6 +1013,7 @@
 
     g_return_if_fail(invocation_hint != NULL);
 
+    pyg_block_threads();
     /* get the object passed as the first argument to the closure */
     object = g_value_get_object(&param_values[0]);
     g_return_if_fail(object != NULL && G_IS_OBJECT(object));
@@ -1030,6 +1037,7 @@
     if (!method) {
        PyErr_Clear();
        Py_DECREF(object_wrapper);
+       pyg_unblock_threads();
        return;
     }
     Py_DECREF(object_wrapper);
@@ -1042,7 +1050,7 @@
        /* error condition */
        if (!item) {
            Py_DECREF(params);
-           /* XXXX - clean up if threading was used */
+           pyg_unblock_threads();
            return;
        }
        PyTuple_SetItem(params, i - 1, item);
@@ -1053,15 +1061,15 @@
        /* XXXX - do fatal exceptions thing here */
        PyErr_Print();
        PyErr_Clear();
-       /* XXXX - clean up if threading was used */
        Py_DECREF(method);
+       pyg_unblock_threads();
        return;
     }
     Py_DECREF(method);
     if (return_value)
        pyg_value_from_pyobject(return_value, ret);
     Py_DECREF(ret);
-    /* XXXX - clean up if threading was used */
+    pyg_unblock_threads();
 }
 
 static GClosure *
@@ -1106,7 +1114,9 @@
     PyObject_GC_UnTrack((PyObject *)self);
 
     if (self->inst_dict)
+       {
        Py_DECREF(self->inst_dict);
+       }
     self->inst_dict = NULL;
 
     /* the following causes problems with subclassed types */
@@ -1545,7 +1555,9 @@
     }
     if (query.return_type != G_TYPE_NONE)
        g_value_init(&ret, query.return_type);
+    pyg_unblock_threads();
     g_signal_emitv(params, signal_id, detail, &ret);
+    pyg_block_threads();
     for (i = 0; i < query.n_params + 1; i++)
        g_value_unset(&params[i]);
     g_free(params);
@@ -2253,7 +2265,6 @@
     g_type_class_unref(fclass);
 }
 
-
 /* ----------------- gobject module initialisation -------------- */
 
 static struct _PyGObject_Functions functions = {
@@ -2278,8 +2289,55 @@
 
   pyg_enum_add_constants,
   pyg_flags_add_constants,
+  pyg_block_threads,
+  pyg_unblock_threads,
+  NULL, /* gdk_threads_enter */
+  NULL /* gdk_threads_leave */
 };
 
+
+#ifdef ENABLE_PYGTK_THREADING
+static GStaticPrivate pythreadstate_key = G_STATIC_PRIVATE_INIT;
+static GStaticPrivate counter_key = G_STATIC_PRIVATE_INIT;
+#  define INITIAL_LOCK_COUNT 1
+#endif
+
+static void
+pyg_block_threads(void)
+{
+#ifdef ENABLE_PYGTK_THREADING
+    gint counter = GPOINTER_TO_INT(g_static_private_get(&counter_key));
+    g_assert(functions.block_threads == pyg_block_threads);
+    if (counter == INITIAL_LOCK_COUNT) {
+       PyThreadState *_save;
+       _save = g_static_private_get(&pythreadstate_key);
+       if(functions.gdk_threads_leave)
+           functions.gdk_threads_leave();
+       Py_BLOCK_THREADS;
+    }                                                                     
+    counter--;
+    g_static_private_set(&counter_key, GINT_TO_POINTER(counter), NULL);
+#endif
+}
+
+static void
+pyg_unblock_threads(void)
+{
+#ifdef ENABLE_PYGTK_THREADING
+    gint counter = GPOINTER_TO_INT(g_static_private_get(&counter_key));
+    g_assert(functions.unblock_threads == pyg_unblock_threads);
+    counter++;
+    if (counter == INITIAL_LOCK_COUNT) {
+       PyThreadState *_save;
+       Py_UNBLOCK_THREADS;
+       if(functions.gdk_threads_enter)
+           functions.gdk_threads_enter();
+       g_static_private_set(&pythreadstate_key, _save, NULL);
+    }
+    g_static_private_set(&counter_key, GINT_TO_POINTER(counter), NULL);
+#endif
+}
+
 DL_EXPORT(void)
 initgobject(void)
 {
@@ -2291,6 +2349,12 @@
     m = Py_InitModule("gobject", pygobject_functions);
     d = PyModule_GetDict(m);
 
+    /* initialise gthread if appropriate ... */
+#ifdef ENABLE_PYGTK_THREADING
+    /* it is required that this function be called to enable the thread
+     * safety functions */
+    g_thread_init(NULL);
+#endif
     g_type_init();
 
     PY_TYPE_OBJECT = g_boxed_type_register_static("PyObject",
Index: pango.override
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/pango.override,v
retrieving revision 1.5
diff -u -b -r1.5 pango.override
--- pango.override      2001/09/28 23:43:46     1.5
+++ pango.override      2001/10/03 15:31:42
@@ -1,8 +1,10 @@
 /* -*- Mode: C; c-basic-offset: 4 -*- */
 %%
 headers
+#include "config.h"
 #define NO_IMPORT_PYGOBJECT
 #include <pygobject.h>
+#define PANGO_ENABLE_BACKEND 1
 #include <pango/pango.h>
 
 static PyTypeObject *_PyGObject_Type;
Index: pygobject.h
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/pygobject.h,v
retrieving revision 1.18
diff -u -b -r1.18 pygobject.h
--- pygobject.h 2001/09/28 23:43:46     1.18
+++ pygobject.h 2001/10/03 15:31:42
@@ -61,6 +61,10 @@
                                const gchar *strip_prefix);
     void (* flags_add_constants)(PyObject *module, GType flags_type,
                                 const gchar *strip_prefix);
+    void (* block_threads)(void);
+    void (* unblock_threads)(void);
+    void (* gdk_threads_enter)(void);
+    void (* gdk_threads_leave)(void);
 };
 
 #ifndef _INSIDE_PYGOBJECT_
@@ -89,6 +93,8 @@
 #define pyg_boxed_new              (_PyGObject_API->boxed_new)
 #define pyg_enum_add_constants     (_PyGObject_API->enum_add_constants)
 #define pyg_flags_add_constants    (_PyGObject_API->flags_add_constants)
+#define pyg_block_threads          (_PyGObject_API->block_threads)
+#define pyg_unblock_threads        (_PyGObject_API->unblock_threads)
 
 #define init_pygobject() { \
     PyObject *gobject = PyImport_ImportModule("gobject"); \
Index: pygtk.spec
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/pygtk.spec,v
retrieving revision 1.22
diff -u -b -r1.22 pygtk.spec
--- pygtk.spec  2001/10/02 15:07:13     1.22
+++ pygtk.spec  2001/10/03 15:31:42
@@ -10,8 +10,11 @@
 Source: ftp://ftp.gtk.org/pub/gtk/python/pygtk-%{version}.tar.gz
 BuildRoot: /var/tmp/pygtk-root
 Packager: James Henstridge <[EMAIL PROTECTED]>
-Requires: gtk+ >= 1.3.7
-Requires: python >= 2.0
+Requires: gtk2 >= 1.3.9
+Requires: python2 >= 2.1
+BuildRequires: python2-devel >= 2.1
+BuildRequires: python2 >= 2.1
+BuildRequires: gtk2-devel >= 1.3.9
 
 %description
 PyGTK is an extension module for python that gives you access to the GTK+
@@ -31,7 +34,7 @@
 %package devel
 Summary: files needed to build wrappers for GTK+ addon libraries
 Group: Development/Languages
-Requires: pygtk = %{ver}
+Requires: pygtk = %{version}
 
 %description devel
 This package contains files required to build wrappers for GTK+ addon
@@ -39,10 +42,11 @@
 
 %prep
 %setup
-./configure --prefix=%{_prefix}
 
 %build
-make
+export PYTHON=/usr/bin/python2.1
+%configure
+make %{?_smp_mflags}
 
 %install
 rm -rf $RPM_BUILD_ROOT
@@ -67,11 +71,11 @@
 %{_prefix}/bin/pygtk-codegen-2.0
 %dir %{_prefix}/include/pygtk
 %{_prefix}/include/pygtk/*.h
-%{_prerix}/lib/pkgconfig/pygtk-2.0.pc
+%{_prefix}/lib/pkgconfig/pygtk-2.0.pc
 %dir %{_prefix}/share/pygtk
-%dir %{_prefix}/share/pygtk/1.2
-%dir %{_prefix}/share/pygtk/1.2/codegen
-%dir %{_prefix}/share/pygtk/1.2/defs
+%dir %{_prefix}/share/pygtk/2.0
+%dir %{_prefix}/share/pygtk/2.0/codegen
+%dir %{_prefix}/share/pygtk/2.0/defs
 %{_prefix}/share/pygtk/2.0/codegen/*
 %{_prefix}/share/pygtk/2.0/defs/pango.defs
 %{_prefix}/share/pygtk/2.0/defs/gdk.defs
Index: codegen/codegen.py
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/codegen/codegen.py,v
retrieving revision 1.29
diff -u -b -r1.29 codegen.py
--- codegen/codegen.py  2001/10/01 16:07:58     1.29
+++ codegen/codegen.py  2001/10/03 15:31:42
@@ -730,6 +730,7 @@
 
 def write_source(parser, overrides, prefix, fp=sys.stdout):
     fp.write('/* -*- Mode: C; c-basic-offset: 4 -*- */\n\n')
+    fp.write('#include "config.h"\n')
     fp.write('#include <Python.h>\n\n\n')
     fp.write(overrides.get_headers())
     fp.write('\n\n')
Index: gtk/gdk.override
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gtk/gdk.override,v
retrieving revision 1.7
diff -u -b -r1.7 gdk.override
--- gtk/gdk.override    2001/10/02 20:03:33     1.7
+++ gtk/gdk.override    2001/10/03 15:31:42
@@ -1,6 +1,7 @@
 /* -*- Mode: C; c-basic-offset: 4 -*- */
 %%
 headers
+#include "config.h"
 #define NO_IMPORT_PYGOBJECT
 #include "pygobject.h"
 #include <gtk/gtk.h>
Index: gtk/gtk.defs
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gtk/gtk.defs,v
retrieving revision 1.64
diff -u -b -r1.64 gtk.defs
--- gtk/gtk.defs        2001/10/02 20:03:29     1.64
+++ gtk/gtk.defs        2001/10/03 15:31:42
@@ -14036,6 +14036,20 @@
   )
 )
 
+(define-method insert_stock
+  (of-object "GtkToolbar")
+  (c-name "gtk_toolbar_insert_stock")
+  (return-type "GtkWidget*")
+  (parameters
+    '("const-char*" "stock_id")
+    '("const-char*" "tooltip_text")
+    '("const-char*" "tooltip_private_text")
+    '("GtkSignalFunc" "callback")
+    '("gpointer" "user_data")
+    '("gint" "position")
+  )
+)
+
 (define-method append_space
   (of-object "GtkToolbar")
   (c-name "gtk_toolbar_append_space")
Index: gtk/gtk.override
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gtk/gtk.override,v
retrieving revision 1.56
diff -u -b -r1.56 gtk.override
--- gtk/gtk.override    2001/10/02 20:03:33     1.56
+++ gtk/gtk.override    2001/10/03 15:31:42
@@ -1,6 +1,7 @@
 /* -*- Mode: C; c-basic-offset: 4 -*- */
 %%
 headers
+#include "config.h"
 #define NO_IMPORT_PYGOBJECT
 #include "pygobject.h"
 #include <gtk/gtk.h>
@@ -1305,6 +1306,45 @@
     }
 }
 %%
+override gtk_tree_selection_selected_foreach
+static PyObject *
+_wrap_gtk_tree_selection_selected_foreach(PyGObject *self, PyObject *args)
+{
+  PyObject *pyfunc, *pyarg = NULL;
+  PyGtkCustomNotify cunote;
+
+  if(!PyArg_ParseTuple(args, "O|O:GtkTreeSelection.selected_foreach", &pyfunc, 
+&pyarg))
+    return NULL;
+
+  cunote.func = pyfunc;
+  cunote.data = pyarg;
+  pygtk_unblock_threads();
+  gtk_tree_selection_selected_foreach(GTK_TREE_SELECTION(self->obj), 
+pygtk_tree_foreach_marshal, &cunote);
+  pygtk_block_threads();
+
+  Py_INCREF(Py_None);
+  return Py_None;
+}
+%%
+override gtk_tree_selection_set_select_function
+static PyObject *
+_wrap_gtk_tree_selection_set_select_function(PyGObject *self, PyObject *args)
+{
+  PyObject *pyfunc, *pyarg = NULL;
+  PyGtkCustomNotify *cunote;
+
+  if(!PyArg_ParseTuple(args, "O|O:GtkTreeSelection.set_select_function", &pyfunc, 
+&pyarg))
+    return NULL;
+
+  cunote = g_new0(PyGtkCustomNotify, 1);
+  Py_XINCREF(cunote->func = pyfunc);
+  Py_XINCREF(cunote->data = pyarg);
+  gtk_tree_selection_set_select_function(GTK_TREE_SELECTION(self->obj), 
+pygtk_tree_selection_marshal, cunote,
+                                        pygtk_custom_destroy_notify);
+  Py_INCREF(Py_None);
+  return Py_None;
+}
+%%
 override gtk_tree_selection_get_selected
 static PyObject *
 _wrap_gtk_tree_selection_get_selected(PyGObject *self, PyObject *args)
@@ -2814,6 +2854,36 @@
     return pygobject_new((GObject *)ret);
 }
 %%
+override gtk_toolbar_insert_stock kwargs
+static PyObject *
+_wrap_gtk_toolbar_insert_stock(PyGObject *self, PyObject *args,
+                              PyObject *kwargs)
+{
+    static char *kwlist[] = { "stock_id", "tooltip_text", "tooltip_private_text",
+                             "callback", "user_data", "position",
+                             NULL };
+    char *stock_id, *tooltip_text, *tooltip_private_text;
+    PyObject *callback, *param;
+    GtkWidget *ret;
+    int position;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                                    "zzzOOi:GtkToolbar.insert_stock", kwlist,
+                                    &stock_id, &tooltip_text,
+                                    &tooltip_private_text,
+                                    &callback, &param, &position))
+       return NULL;
+    ret = gtk_toolbar_insert_stock(GTK_TOOLBAR(self->obj), stock_id, tooltip_text,
+                                 tooltip_private_text, NULL, NULL,
+                                 position);
+    if (ret && PyCallable_Check(callback)) {
+       g_signal_connect_closure(ret, "clicked",
+                                pyg_closure_new(callback, param, NULL),
+                                FALSE);
+    }
+    return pygobject_new((GObject *)ret);
+}
+%%
 override gtk_toolbar_append_element kwargs
 static PyObject *
 _wrap_gtk_toolbar_append_element(PyGObject *self, PyObject *args,
@@ -3828,6 +3898,24 @@
     gtk_object_sink(GTK_OBJECT(self->obj));
     pygobject_register_wrapper((PyObject *)self);
     return 0;
+}
+%%
+override gtk_dialog_run
+
+static PyObject *
+_wrap_gtk_dialog_run(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+    static char *kwlist[] = { NULL };
+    gint retval;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":GtkDialog.run", kwlist))
+        return NULL;
+
+    pyg_unblock_threads();
+    retval = gtk_dialog_run(GTK_DIALOG(self->obj));
+    pyg_block_threads();
+
+    return PyInt_FromLong(retval);
 }
 %%
 override gtk_message_dialog_new kwargs
Index: gtk/gtkgl.override
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gtk/gtkgl.override,v
retrieving revision 1.2
diff -u -b -r1.2 gtkgl.override
--- gtk/gtkgl.override  2000/06/26 14:14:48     1.2
+++ gtk/gtkgl.override  2001/10/03 15:31:42
@@ -1,6 +1,7 @@
 /* -*- Mode: C; c-basic-offset: 4 -*- */
 %%
 headers
+#include "config.h"
 #define NO_IMPORT_PYGTK
 #include "pygtk.h"
 
Index: gtk/gtkmodule.c
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gtk/gtkmodule.c,v
retrieving revision 1.22
diff -u -b -r1.22 gtkmodule.c
--- gtk/gtkmodule.c     2001/09/27 16:22:45     1.22
+++ gtk/gtkmodule.c     2001/10/03 15:31:42
@@ -20,9 +20,6 @@
     VERSION,
     FALSE,
 
-    pygtk_block_threads,
-    pygtk_unblock_threads,
-
     pygtk_destroy_notify,
 
     &PyGdkAtom_Type,  PyGdkAtom_New,
@@ -35,17 +32,12 @@
     PyObject *av;
     int argc, i;
     char **argv;
+    GSList *stock_ids, *cur;
+    char buf[128];
 
     /* initialise gobject */
     init_pygobject();
 
-    /* initialise gthread if appropriate ... */
-#ifdef ENABLE_PYGTK_THREADING
-    /* it is required that this function be called to enable the thread
-     * safety functions */
-    g_thread_init(NULL);
-#endif
-
     /* set the default python encoding to utf-8 */
     PyUnicode_SetDefaultEncoding("utf-8");
 
@@ -83,6 +75,37 @@
     PyDict_SetItemString(d, "_PyGtk_API",
                         PyCObject_FromVoidPtr(&functions, NULL));
 
+    stock_ids = gtk_stock_list_ids();
+    strcpy(buf, "STOCK_");
+    for(cur = stock_ids; cur; cur = stock_ids)
+      {
+       char *ctmp;
+       PyObject *obj;
+       int i;
+
+       ctmp = cur->data;
+       if(strncmp(ctmp, "gtk-", 4))
+         continue;
+       ctmp += 4;
+
+       strcpy(buf + sizeof("STOCK"), ctmp);
+       ctmp = buf + sizeof("STOCK");
+       for(i = 0; ctmp[i]; i++)
+         {
+           if(ctmp[i] == '-')
+             ctmp[i] = '_';
+           else if(ctmp[i] >= 'a' && ctmp[i] <= 'z')
+             ctmp[i] -= 'a'-'A';
+         }
+
+       obj = PyString_FromString(cur->data);
+       PyDict_SetItemString(d, buf, obj);
+       Py_DECREF(obj);
+       g_free(cur->data);
+       stock_ids = cur->next;
+       g_slist_free_1(cur);
+      }
+
     /* namespace all the gdk stuff in gtk.gdk ... */
     m = Py_InitModule("gtk.gdk", pygdk_functions);
     d = PyModule_GetDict(m);
@@ -93,4 +116,6 @@
     if (PyErr_Occurred())
        Py_FatalError("can't initialise module _gtk");
 
+    _PyGObject_API->gdk_threads_enter = gdk_threads_enter;
+    _PyGObject_API->gdk_threads_leave = gdk_threads_leave;
 }
Index: gtk/gtkobject-support.c
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gtk/gtkobject-support.c,v
retrieving revision 1.12
diff -u -b -r1.12 gtkobject-support.c
--- gtk/gtkobject-support.c     2001/06/25 03:27:27     1.12
+++ gtk/gtkobject-support.c     2001/10/03 15:31:42
@@ -5,68 +5,6 @@
 
 #include "pygtk-private.h"
 
-/* ----------------- Thread stuff -------------------- */
-/* The threading hacks are based on ones supplied by Duncan Grisby
- * of AT&T Labs Cambridge.  Since then they have been modified a bit. */
-
-/* The threading code has been enhanced to be a little better with multiple
- * threads accessing GTK+.  Here are some notes on the changes by
- * Paul Fisher:
- *
- * If threading is enabled, we create a recursive version of Python's
- * global interpreter mutex using TSD.  This scheme makes it possible,
- * although rather hackish, for any thread to make a call into PyGTK,
- * as long as the GDK lock is held (that is, Python code is wrapped
- * around a threads_{enter,leave} pair).
- *
- * A viable alternative would be to wrap each and every GTK call, at
- * the Python/C level, with Py_{BEGIN,END}_ALLOW_THREADS.  However,
- * given the nature of Python threading, this option is not
- * particularly appealing.
- */
-
-
-#ifdef ENABLE_PYGTK_THREADING
-static GStaticPrivate pythreadstate_key = G_STATIC_PRIVATE_INIT;
-static GStaticPrivate counter_key = G_STATIC_PRIVATE_INIT;
-
-/* The global Python lock will be grabbed by Python when entering a
- * Python/C function; thus, the initial lock count will always be one.
- */
-#  define INITIAL_LOCK_COUNT 1
-#  define PyGTK_BLOCK_THREADS                                              \
-   {                                                                       \
-     gint counter = GPOINTER_TO_INT(g_static_private_get(&counter_key));   \
-     if (counter == -INITIAL_LOCK_COUNT) {                                 \
-       PyThreadState *_save;                                               \
-       _save = g_static_private_get(&pythreadstate_key);                   \
-       Py_BLOCK_THREADS;                                                   \
-     }                                                                     \
-     counter++;                                                            \
-     g_static_private_set(&counter_key, GINT_TO_POINTER(counter), NULL);   \
-   }
-
-#  define PyGTK_UNBLOCK_THREADS                                            \
-   {                                                                       \
-     gint counter = GPOINTER_TO_INT(g_static_private_get(&counter_key));   \
-     counter--;                                                            \
-     if (counter == -INITIAL_LOCK_COUNT) {                                 \
-       PyThreadState *_save;                                               \
-       Py_UNBLOCK_THREADS;                                                 \
-       g_static_private_set(&pythreadstate_key, _save, NULL);              \
-     }                                                                     \
-     g_static_private_set(&counter_key, GINT_TO_POINTER(counter), NULL);   \
-   }
-
-
-#else /* !WITH_THREADS */
-#  define PyGTK_BLOCK_THREADS
-#  define PyGTK_UNBLOCK_THREADS
-#endif
-
-void pygtk_block_threads(void) { PyGTK_BLOCK_THREADS }
-void pygtk_unblock_threads(void) { PyGTK_UNBLOCK_THREADS }
-
 /* ------------------- object support */
 
 void
@@ -74,11 +12,22 @@
 {
     PyObject *obj = (PyObject *)user_data;
 
-    PyGTK_BLOCK_THREADS
+    pyg_block_threads();
     Py_DECREF(obj);
-    PyGTK_UNBLOCK_THREADS
+    pyg_unblock_threads();
 }
 
+void
+pygtk_custom_destroy_notify(gpointer user_data)
+{
+  PyGtkCustomNotify *cunote = user_data;
+
+  pyg_block_threads();
+  Py_XDECREF(cunote->func);
+  Py_XDECREF(cunote->data);
+  pyg_unblock_threads();
+  g_free(cunote);
+}
 
 /* used for timeout and idle functions */
 void
@@ -86,7 +35,7 @@
 {
     PyObject *ret;
 
-    PyGTK_BLOCK_THREADS
+    pyg_block_threads();
 
     if (PyTuple_Check(func))
        ret = PyObject_CallObject(PyTuple_GetItem(func, 0),
@@ -101,7 +50,7 @@
            PyErr_Clear();
        }
        *GTK_RETLOC_BOOL(args[0]) = FALSE;
-       PyGTK_UNBLOCK_THREADS
+       pyg_unblock_threads();
            return;
     }
     if (ret == Py_None || (PyInt_Check(ret) && PyInt_AsLong(ret) == 0))
@@ -109,7 +58,7 @@
     else
        *GTK_RETLOC_BOOL(args[0]) = TRUE;
     Py_DECREF(ret);
-    PyGTK_UNBLOCK_THREADS
+    pyg_unblock_threads();
 }
 
 /* callback for input handlers */
@@ -118,7 +67,7 @@
 {
     PyObject *tuple, *ret;
 
-    PyGTK_BLOCK_THREADS
+    pyg_block_threads();
     tuple = Py_BuildValue("(ii)", GTK_VALUE_INT(args[0]),
                          GTK_VALUE_FLAGS(args[1]));
     ret = PyObject_CallObject(func, tuple);
@@ -132,8 +81,67 @@
        }
     } else
        Py_DECREF(ret);
-    PyGTK_UNBLOCK_THREADS
+    pyg_unblock_threads();
+}
+
+void
+pygtk_tree_foreach_marshal(GtkTreeModel *model,
+                          GtkTreePath *path,
+                          GtkTreeIter *iter,
+                          gpointer data)
+{
+  PyGtkCustomNotify *cunote = data;
+  PyObject *pypath, *retobj;
+
+  g_assert(cunote->func);
+
+  pyg_block_threads();
+
+  pypath = pygtk_tree_path_to_pyobject(path);
+  if(cunote->data)
+    retobj = PyEval_CallFunction(cunote->func, "(OO)", pypath, cunote->data);
+  else
+    retobj = PyEval_CallFunction(cunote->func, "(O)", pypath);
+  Py_DECREF(pypath);
+  Py_XDECREF(retobj);
+
+  pyg_unblock_threads();
 }
 
+gboolean
+pygtk_tree_selection_marshal(GtkTreeSelection  *selection,
+                            GtkTreeModel      *model,
+                            GtkTreePath       *path,
+                            gpointer           data)
+{
+  gboolean retval = FALSE;
+  PyGtkCustomNotify *cunote = data;
+  PyObject *pypath, *retobj;
+
+  g_assert(cunote->func);
+
+  pyg_block_threads();
 
+  pypath = pygtk_tree_path_to_pyobject(path);
+  if(cunote->data)
+    retobj = PyEval_CallFunction(cunote->func, "(OO)", pypath, cunote->data);
+  else
+    retobj = PyEval_CallFunction(cunote->func, "(O)", pypath);
+  Py_DECREF(pypath);
+  if(retobj)
+    {
+      if(retobj == Py_None);
+      else if(PyInt_Check(retobj))
+       retval = PyInt_AsLong(retobj) && TRUE;
+      else if(PyLong_Check(retobj))
+       retval = PyLong_AsLongLong(retobj) && TRUE;
+      else if(PyString_Check(retobj))
+       retval = PyString_GET_SIZE(retobj) && TRUE;
 
+      Py_DECREF(retobj);
+    }
+
+  pyg_unblock_threads();
+
+  return retval;
+}
Index: gtk/libglade.override
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gtk/libglade.override,v
retrieving revision 1.8
diff -u -b -r1.8 libglade.override
--- gtk/libglade.override       2001/09/28 23:43:47     1.8
+++ gtk/libglade.override       2001/10/03 15:31:42
@@ -1,6 +1,7 @@
 /* -*- Mode: C; c-basic-offset: 4 -*- */
 %%
 headers
+#include "config.h"
 #include <pygobject.h>
 #include <glade/glade.h>
 
Index: gtk/pygtk-private.h
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gtk/pygtk-private.h,v
retrieving revision 1.18
diff -u -b -r1.18 pygtk-private.h
--- gtk/pygtk-private.h 2001/09/27 16:22:45     1.18
+++ gtk/pygtk-private.h 2001/10/03 15:31:42
@@ -22,10 +22,6 @@
 /* constructors for PyObject wrappers ... */
 PyObject *PyGdkAtom_New(GdkAtom atom);
 
-/* miscelaneous functions */
-void pygtk_block_threads(void);
-void pygtk_unblock_threads(void);
-
 void pygtk_destroy_notify(gpointer data);
 
 void pygtk_handler_marshal(gpointer a, PyObject *func, int nargs,GtkArg *args);
@@ -36,5 +32,20 @@
 GtkTreePath *pygtk_tree_path_from_pyobject(PyObject *object);
 
 static gboolean PyGtk_FatalExceptions = FALSE;
+
+typedef struct {
+  PyObject *func, *data;
+} PyGtkCustomNotify;
+
+void pygtk_custom_destroy_notify(gpointer user_data);
+
+gboolean pygtk_tree_selection_marshal(GtkTreeSelection  *selection,
+                                     GtkTreeModel      *model,
+                                     GtkTreePath       *path,
+                                     gpointer           data);
+void pygtk_tree_foreach_marshal(GtkTreeModel *model,
+                               GtkTreePath *path,
+                               GtkTreeIter *iter,
+                               gpointer data);
 
 #endif
Index: gtk/pygtk.h
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gtk/pygtk.h,v
retrieving revision 1.20
diff -u -b -r1.20 pygtk.h
--- gtk/pygtk.h 2001/09/28 23:43:47     1.20
+++ gtk/pygtk.h 2001/10/03 15:31:42
@@ -11,9 +11,6 @@
     char *pygtkVersion;
     gboolean fatalExceptions;
 
-    void (* block_threads)(void);
-    void (* unblock_threads)(void);
-
     GtkDestroyNotify destroy_notify;
 
     PyTypeObject *gdkAtom_type;
@@ -30,6 +27,9 @@
 /* routines to get the C object value out of the PyObject wrapper */
 #define PyGdkAtom_Get(v) (((PyGdkAtom_Object *)(v))->atom)
 
+#define pygtk_block_threads pyg_block_threads
+#define pygtk_unblock_threads pyg_unblock_threads
+
 /* this section is dependent on whether we are being included from gtkmodule.c
  * or not.  A similar source level interface should be provided in both
  * instances. */
@@ -53,8 +53,6 @@
 #define PyGdkAtom_New          (_PyGtk_API->gdkAtom_new)
 
 /* miscelaneous other functions */
-#define pygtk_block_threads (_PyGtk_API->block_threads)
-#define pygtk_unblock_threads (_PyGtk_API->unblock_threads)
 #define pygtk_destroy_notify (_PyGtk_API->destroy_notify)
 
 /* some variables */

Reply via email to