* Extended X interface: pixmap objects, colormap objects visual objects,
  image objects, and lots of new methods.
* Added counting of allocations and deallocations of builtin types if
  COUNT_ALLOCS is defined.  Had to move calls to NEWREF down in some
  files.
* Bug fix in sorting lists.
diff --git a/Include/object.h b/Include/object.h
index 2a6b170..ab270f8 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -198,6 +198,13 @@
 	/* More standard operations (at end for binary compatibility) */
 
 	long (*tp_hash) FPROTO((object *));
+#ifdef COUNT_ALLOCS
+	/* these must be last */
+	int tp_alloc;
+	int tp_free;
+	int tp_maxalloc;
+	struct _typeobject *tp_next;
+#endif
 } typeobject;
 
 extern typeobject Typetype; /* The type of type objects */
@@ -253,15 +260,27 @@
 #endif
 
 #ifndef TRACE_REFS
+#ifdef COUNT_ALLOCS
+#define DELREF(op) ((op)->ob_type->tp_free++, (*(op)->ob_type->tp_dealloc)((object *)(op)))
+#else
 #define DELREF(op) (*(op)->ob_type->tp_dealloc)((object *)(op))
+#endif
 #define UNREF(op) /*empty*/
 #endif
 
+#ifdef COUNT_ALLOCS
+extern void inc_count PROTO((typeobject *));
+#endif
+
 #ifdef REF_DEBUG
 extern long ref_total;
 #ifndef TRACE_REFS
+#ifdef COUNT_ALLOCS
+#define NEWREF(op) (inc_count((op)->ob_type), ref_total++, (op)->ob_refcnt = 1)
+#else
 #define NEWREF(op) (ref_total++, (op)->ob_refcnt = 1)
 #endif
+#endif
 #define INCREF(op) (ref_total++, (op)->ob_refcnt++)
 #define DECREF(op) \
 	if (--ref_total, --(op)->ob_refcnt > 0) \
@@ -269,7 +288,11 @@
 	else \
 		DELREF(op)
 #else
+#ifdef COUNT_ALLOCS
+#define NEWREF(op) (inc_count((op)->ob_type), (op)->ob_refcnt = 1)
+#else
 #define NEWREF(op) ((op)->ob_refcnt = 1)
+#endif
 #define INCREF(op) ((op)->ob_refcnt++)
 #define DECREF(op) \
 	if (--(op)->ob_refcnt > 0) \
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index b5a2cfa..93c0735 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -252,10 +252,10 @@
 			return err_nomem();
 		}
 	}
-	NEWREF(op);
 	op->ob_type = &Arraytype;
 	op->ob_size = size;
 	op->ob_descr = descr;
+	NEWREF(op);
 	return (object *) op;
 }
 
diff --git a/Modules/config.c.in b/Modules/config.c.in
index 484381e..f19655f 100644
--- a/Modules/config.c.in
+++ b/Modules/config.c.in
@@ -310,6 +310,9 @@
 #ifdef USE_HTML
 extern void initHTML();
 #endif
+#ifdef USE_XLIB
+extern void initXlib();
+#endif
 /* -- ADDMODULE MARKER 1 -- */
 
 struct {
@@ -485,6 +488,10 @@
 	{"HTML", initHTML},
 #endif
 
+#ifdef USE_XLIB
+       {"Xlib", initXlib},
+#endif
+
 /* -- ADDMODULE MARKER 2 -- */
 
 	{0,		0}		/* Sentinel */
diff --git a/Modules/imageop.c b/Modules/imageop.c
index 40940cb..841ec1b 100644
--- a/Modules/imageop.c
+++ b/Modules/imageop.c
@@ -542,9 +542,15 @@
     for ( i=0; i < nlen; i++ ) {
 	/* Bits in source: aaaaaaaa BBbbbbbb GGGggggg RRRrrrrr */
 	value = *cp++;
+#if 0
 	r = (value >>  5) & 7;
 	g = (value >> 13) & 7;
 	b = (value >> 22) & 3;
+#else
+	r = (int) ((value & 0xff) / 255. * 7. + .5);
+	g = (int) (((value >> 8) & 0xff) / 255. * 7. + .5);
+	b = (int) (((value >> 16) & 0xff) / 255. * 3. + .5);
+#endif
 	nvalue = (r<<5) | (b<<3) | g;
 	*ncp++ = nvalue;
     }
diff --git a/Modules/imgfile.c b/Modules/imgfile.c
index 93f5ef3..e57d6c4 100644
--- a/Modules/imgfile.c
+++ b/Modules/imgfile.c
@@ -43,6 +43,7 @@
 
 static object * ImgfileError; /* Exception we raise for various trouble */
 
+static int top_to_bottom;	/* True if we want top-to-bottom images */
 
 /* The image library does not always call the error hander :-(,
    therefore we have a global variable indicating that it was called.
@@ -86,6 +87,20 @@
     return image;
 }
 
+static object *
+imgfile_ttob(self, args)
+    object *self;
+    object *args;
+{
+    int newval;
+    object *rv;
+    
+    if (!getargs(args, "i", &newval))
+      return NULL;
+    rv = newintobject(top_to_bottom);
+    top_to_bottom = newval;
+    return rv;
+}
 
 static object *
 imgfile_read(self, args)
@@ -100,7 +115,8 @@
     static short rs[8192], gs[8192], bs[8192];
     int x, y;
     IMAGE *image;
-    
+    int yfirst, ylast, ystep;
+
     if ( !getargs(args, "s", &fname) )
       return NULL;
     
@@ -139,7 +155,17 @@
     }
     cdatap = getstringvalue(rv);
     idatap = (long *)cdatap;
-    for ( y=0; y < ysize && !error_called; y++ ) {
+
+    if (top_to_bottom) {
+	yfirst = ysize-1;
+	ylast = -1;
+	ystep = -1;
+    } else {
+	yfirst = 0;
+	ylast = ysize;
+	ystep = 1;
+    }
+    for ( y=yfirst; y != ylast && !error_called; y += ystep ) {
 	if ( zsize == 1 ) {
 	    getrow(image, rs, y, 0);
 	    for(x=0; x<xsize; x++ )
@@ -164,14 +190,17 @@
 
 static IMAGE *glob_image;
 static long *glob_datap;
-static int glob_width, glob_z;
+static int glob_width, glob_z, glob_ysize;
 
 static
 xs_get(buf, y)
     short *buf;
     int y;
 {
-    getrow(glob_image, buf, y, glob_z);
+    if (top_to_bottom)
+      getrow(glob_image, buf, (glob_ysize-1-y), glob_z);
+    else
+      getrow(glob_image, buf, y, glob_z);
 }
 
 static
@@ -221,6 +250,7 @@
     glob_image = image;
     glob_datap = datap;
     glob_width = xnew;
+    glob_ysize = ysize;
     if ( zsize == 1 ) {
 	glob_z = 0;
 	filterzoom(xs_get, xs_put_c, xsize, ysize, xnew, ynew, fmode, blur);
@@ -255,6 +285,7 @@
     double blur;
     int extended;
     int fmode;
+    int yfirst, ylast, ystep;
 
     /*
      ** Parse args. Funny, since arg 4 and 5 are optional
@@ -331,7 +362,16 @@
     if ( extended ) {
 	xscale(image, xsize, ysize, zsize, idatap, xwtd, ywtd, fmode, blur);
     } else {
-	for ( y=0; y < ywtd && !error_called; y++ ) {
+	if (top_to_bottom) {
+	    yfirst = ywtd-1;
+	    ylast = -1;
+	    ystep = -1;
+	} else {
+	    yfirst = 0;
+	    ylast = ywtd;
+	    ystep = 1;
+	}
+	for ( y=yfirst; y != ylast && !error_called; y += ystep ) {
 	    yorig = (int)(y*yfac);
 	    if ( zsize == 1 ) {
 		getrow(image, rs, yorig, 0);
@@ -392,6 +432,8 @@
     short r, g, b;
     long rgb;
     int x, y;
+    int yfirst, ylast, ystep;
+
 
     if ( !getargs(args, "(ss#iii)",
 		  &fname, &cdatap, &len, &xsize, &ysize, &zsize) )
@@ -425,7 +467,16 @@
 
     idatap = (long *)cdatap;
     
-    for( y=0; y<ysize && !error_called; y++ ) {
+    if (top_to_bottom) {
+	yfirst = ysize-1;
+	ylast = -1;
+	ystep = -1;
+    } else {
+	yfirst = 0;
+	ylast = ysize;
+	ystep = 1;
+    }
+    for ( y=yfirst; y != ylast && !error_called; y += ystep ) {
 	if ( zsize == 1 ) {
 	    for( x=0; x<xsize; x++ )
 	      rs[x] = *cdatap++;
@@ -459,6 +510,7 @@
     { "read",		imgfile_read },
     { "readscaled",	imgfile_readscaled, 1},
     { "write",		imgfile_write },
+    { "ttob",		imgfile_ttob },
     { NULL,		NULL } /* Sentinel */
 };
 
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index 9994523..d3a2c77 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -60,9 +60,9 @@
 	register floatobject *op = (floatobject *) malloc(sizeof(floatobject));
 	if (op == NULL)
 		return err_nomem();
-	NEWREF(op);
 	op->ob_type = &Floattype;
 	op->ob_fval = fval;
+	NEWREF(op);
 	return (object *) op;
 }
 
diff --git a/Objects/intobject.c b/Objects/intobject.c
index 3021873..816a411 100644
--- a/Objects/intobject.c
+++ b/Objects/intobject.c
@@ -87,9 +87,9 @@
 	}
 	v = free_list;
 	free_list = *(intobject **)free_list;
-	NEWREF(v);
 	v->ob_type = &Inttype;
 	v->ob_ival = ival;
+	NEWREF(v);
 	return (object *) v;
 }
 
diff --git a/Objects/listobject.c b/Objects/listobject.c
index 38829e2..67a6185 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -58,11 +58,11 @@
 			return err_nomem();
 		}
 	}
-	NEWREF(op);
 	op->ob_type = &Listtype;
 	op->ob_size = size;
 	for (i = 0; i < size; i++)
 		op->ob_item[i] = NULL;
+	NEWREF(op);
 	return (object *) op;
 }
 
@@ -520,7 +520,7 @@
 		return cmpobject(* (object **) v, * (object **) w);
 
 	/* Call the user-supplied comparison function */
-	t = mkvalue("OO", v, w);
+	t = mkvalue("OO", * (object **) v, * (object **) w);
 	if (t == NULL)
 		return 0;
 	res = call_object(cmpfunc, t);
diff --git a/Objects/object.c b/Objects/object.c
index a469797..a20b24d 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -34,6 +34,36 @@
    These are used by the individual routines for object creation.
    Do not call them otherwise, they do not initialize the object! */
 
+#ifdef COUNT_ALLOCS
+static typeobject *type_list;
+
+void
+dump_counts()
+{
+	typeobject *tp;
+
+	for (tp = type_list; tp; tp = tp->tp_next)
+		printf("%s %d %d %d\n", tp->tp_name, tp->tp_alloc, tp->tp_free,
+		       tp->tp_maxalloc);
+}
+
+void
+inc_count(tp)
+	typeobject *tp;
+{
+	if (tp->tp_alloc == 0) {
+		/* first time; hang in linked list */
+		if (tp->tp_next != NULL) /* sanity check */
+			abort();
+		tp->tp_next = type_list;
+		type_list = tp;
+	}
+	tp->tp_alloc++;
+	if (tp->tp_alloc - tp->tp_free > tp->tp_maxalloc)
+		tp->tp_maxalloc = tp->tp_alloc - tp->tp_free;
+}
+#endif
+
 object *
 newobject(tp)
 	typeobject *tp;
@@ -41,8 +71,8 @@
 	object *op = (object *) malloc(tp->tp_basicsize);
 	if (op == NULL)
 		return err_nomem();
-	NEWREF(op);
 	op->ob_type = tp;
+	NEWREF(op);
 	return op;
 }
 
@@ -55,9 +85,9 @@
 		malloc(tp->tp_basicsize + size * tp->tp_itemsize);
 	if (op == NULL)
 		return (varobject *)err_nomem();
-	NEWREF(op);
 	op->ob_type = tp;
 	op->ob_size = size;
+	NEWREF(op);
 	return op;
 }
 
@@ -301,6 +331,9 @@
 	op->_ob_prev = &refchain;
 	refchain._ob_next->_ob_prev = op;
 	refchain._ob_next = op;
+#ifdef COUNT_ALLOCS
+	inc_count(op->ob_type);
+#endif
 }
 
 UNREF(op)
@@ -335,6 +368,9 @@
 	object *op;
 {
 	UNREF(op);
+#ifdef COUNT_ALLOCS
+	op->ob_type->tp_free++;
+#endif
 	(*(op)->ob_type->tp_dealloc)(op);
 	op->ob_type = NULL;
 }
diff --git a/Objects/stringobject.c b/Objects/stringobject.c
index cba8c92..a3043d4 100644
--- a/Objects/stringobject.c
+++ b/Objects/stringobject.c
@@ -35,9 +35,9 @@
 		malloc(sizeof(stringobject) + size * sizeof(char));
 	if (op == NULL)
 		return err_nomem();
-	NEWREF(op);
 	op->ob_type = &Stringtype;
 	op->ob_size = size;
+	NEWREF(op);
 	if (str != NULL)
 		memcpy(op->ob_sval, str, size);
 	op->ob_sval[size] = '\0';
@@ -53,9 +53,9 @@
 		malloc(sizeof(stringobject) + size * sizeof(char));
 	if (op == NULL)
 		return err_nomem();
-	NEWREF(op);
 	op->ob_type = &Stringtype;
 	op->ob_size = size;
+	NEWREF(op);
 	strcpy(op->ob_sval, str);
 	return (object *) op;
 }
@@ -187,9 +187,9 @@
 		malloc(sizeof(stringobject) + size * sizeof(char));
 	if (op == NULL)
 		return err_nomem();
-	NEWREF(op);
 	op->ob_type = &Stringtype;
 	op->ob_size = size;
+	NEWREF(op);
 	memcpy(op->ob_sval, a->ob_sval, (int) a->ob_size);
 	memcpy(op->ob_sval + a->ob_size, b->ob_sval, (int) b->ob_size);
 	op->ob_sval[size] = '\0';
@@ -216,9 +216,9 @@
 		malloc(sizeof(stringobject) + size * sizeof(char));
 	if (op == NULL)
 		return err_nomem();
-	NEWREF(op);
 	op->ob_type = &Stringtype;
 	op->ob_size = size;
+	NEWREF(op);
 	for (i = 0; i < size; i += a->ob_size)
 		memcpy(op->ob_sval+i, a->ob_sval, (int) a->ob_size);
 	op->ob_sval[size] = '\0';
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index faf46d5..fae9386 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -40,11 +40,11 @@
 		malloc(sizeof(tupleobject) + size * sizeof(object *));
 	if (op == NULL)
 		return err_nomem();
-	NEWREF(op);
 	op->ob_type = &Tupletype;
 	op->ob_size = size;
 	for (i = 0; i < size; i++)
 		op->ob_item[i] = NULL;
+	NEWREF(op);
 	return (object *) op;
 }
 
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index d518f24..6661a19 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -417,12 +417,20 @@
 	flushline();
 }
 
+#ifdef COUNT_ALLOCS
+extern void dump_counts PROTO((void));
+#endif
+
 void
 goaway(sts)
 	int sts;
 {
 	cleanup();
 
+#ifdef COUNT_ALLOCS
+	dump_counts();
+#endif
+
 #ifdef USE_THREAD
 
 	/* Other threads may still be active, so skip most of the