Lots of little fixes.
- merged CloseCompressor and CloseDecompressor into one function
- keep existing errors in error function (for exceptions raised in the
  Compress or Decompress callback functions)
- remove newline from error string generated by error function
- allocate less memory when compressing multiple frames
- keep existing errors when clCompress or clDecompress fails
- raise an exception when compressed data doesn't fit within
  dataMaxSize bytes
- allocate frameSize bytes for decompression buffer instead of
  dataMaxSize
- use mkvalue more often
- new function QueryParams which will accept CL.AUDIO and CL.VIDEO
  args
- changed some function names
diff --git a/Modules/clmodule.c b/Modules/clmodule.c
index 31f2691..7e72fbd 100644
--- a/Modules/clmodule.c
+++ b/Modules/clmodule.c
@@ -36,6 +36,7 @@
 	int ob_isCompressor;	/* Compressor or Decompressor */
 	CL_CompressorHdl ob_compressorHdl;
 	long ob_dataMaxSize;
+	long ob_frameSize;
 	object *ob_callbackFunc;
 	object *ob_callbackID;
 	object *ob_data; 
@@ -59,25 +60,32 @@
 {
 	va_list ap;
 	char errbuf[BUFSIZ];	/* hopefully big enough */
+	char *p;
 
+	if (err_occurred())	/* don't change existing error */
+		return;
 	error_handler_called = 1;
 	va_start(ap, fmt);
 	vsprintf(errbuf, fmt, ap);
 	va_end(ap);
+	p = &errbuf[strlen(errbuf) - 1]; /* swat the line feed */
+	if (*p == '\n')
+		*p = 0;
 	err_setstr(ClError, errbuf);
 }
 
 static object *
-cl_CloseCompressor(self, args)
+doClose(self, args, close_func)
 	clobject *self;
 	object *args;
+	long (*close_func) PROTO((CL_CompressorHdl));
 {
 	CheckCompressor(self);
 
 	if (!getnoarg(args))
 		return NULL;
 
-	if (clCloseCompressor(self->ob_compressorHdl) == FAILURE) {
+	if ((*close_func)(self->ob_compressorHdl) == FAILURE) {
 		if (!error_handler_called)
 			err_setstr(ClError, "CloseCompressor failed");
 		return NULL;
@@ -90,29 +98,23 @@
 }
 
 static object *
-cl_CloseDecompressor(self, args)
+clm_CloseCompressor(self, args)
 	clobject *self;
 	object *args;
 {
-	CheckCompressor(self);
-
-	if (!getnoarg(args))
-		return NULL;
-
-	if (clCloseDecompressor(self->ob_compressorHdl) == FAILURE) {
-		if (!error_handler_called)
-			err_setstr(ClError, "CloseDecompressor failed");
-		return NULL;
-	}
-
-	self->ob_compressorHdl = NULL;
-
-	INCREF(None);
-	return None;
+	return doClose(self, args, clCloseCompressor);
 }
 
 static object *
-cl_Compress(self, args)
+clm_CloseDecompressor(self, args)
+	clobject *self;
+	object *args;
+{
+	return doClose(self, args, clCloseDecompressor);
+}
+
+static object *
+clm_Compress(self, args)
 	clobject *self;
 	object *args;
 {
@@ -124,31 +126,36 @@
 	if (!getargs(args, "(ii)", &frameIndex, &numberOfFrames))
 		return NULL;
 
-	data = newsizedstringobject(NULL,
-				    numberOfFrames * self->ob_dataMaxSize);
+	dataSize = self->ob_dataMaxSize;
+	data = newsizedstringobject(NULL, dataSize);
 	if (data == NULL)
 		return NULL;
 
-	dataSize = numberOfFrames * self->ob_dataMaxSize;
-
 	error_handler_called = 0;
 	if (clCompress(self->ob_compressorHdl, frameIndex, numberOfFrames,
 		       &dataSize, (void *) getstringvalue(data)) == FAILURE) {
 		DECREF(data);
-		if (!error_handler_called)
+		if (!error_handler_called && !err_occurred())
 			err_setstr(ClError, "compress failed");
 		return NULL;
 	}
 
-	if (dataSize < numberOfFrames * self->ob_dataMaxSize)
+	if (dataSize < self->ob_dataMaxSize)
 		if (resizestring(&data, dataSize))
 			return NULL;
 
+	if (dataSize > self->ob_dataMaxSize) {
+		/* we didn't get all data */
+		DECREF(data);
+		err_setstr(ClError, "buffer too small for compressed image");
+		return NULL;
+	}
+
 	return data;
 }	
 
 static object *
-cl_Decompress(self, args)
+clm_Decompress(self, args)
 	clobject *self;
 	object *args;
 {
@@ -161,7 +168,7 @@
 		return NULL;
 
 	data = newsizedstringobject(NULL,
-				    numberOfFrames * self->ob_dataMaxSize);
+				    numberOfFrames * self->ob_frameSize);
 	if (data == NULL)
 		return NULL;
 
@@ -169,7 +176,7 @@
 	if (clDecompress(self->ob_compressorHdl, frameIndex, numberOfFrames,
 			 (void *) getstringvalue(data)) == FAILURE) {
 		DECREF(data);
-		if (!error_handler_called)
+		if (!error_handler_called && !err_occurred())
 			err_setstr(ClError, "decompress failed");
 		return NULL;
 	}
@@ -178,7 +185,7 @@
 }	
 
 static object *
-cl_GetCompressorInfo(self, args)
+clm_GetCompressorInfo(self, args)
 	clobject *self;
 	object *args;
 {
@@ -202,7 +209,7 @@
 }
 
 static object *
-cl_GetDefault(self, args)
+clm_GetDefault(self, args)
 	clobject *self;
 	object *args;
 {
@@ -222,7 +229,7 @@
 }
 
 static object *
-cl_GetMinMax(self, args)
+clm_GetMinMax(self, args)
 	clobject *self;
 	object *args;
 {
@@ -242,7 +249,7 @@
 }
 
 static object *
-cl_GetName(self, args)
+clm_GetName(self, args)
 	clobject *self;
 	object *args;
 {
@@ -317,21 +324,21 @@
 }
 
 static object *
-cl_GetParams(self, args)
+clm_GetParams(self, args)
 	object *self, *args;
 {
 	return doParams(self, args, clGetParams, 1);
 }
 
 static object *
-cl_SetParams(self, args)
+clm_SetParams(self, args)
 	object *self, *args;
 {
 	return doParams(self, args, clSetParams, 0);
 }
 
 static object *
-cl_QueryParams(self, args)
+clm_QueryParams(self, args)
 	clobject *self;
 	object *args;
 {
@@ -380,27 +387,27 @@
 }
 
 static struct methodlist compressor_methods[] = {
-	{"CloseCompressor",	cl_CloseCompressor},
-	{"Compress",		cl_Compress},
-	{"GetCompressorInfo",	cl_GetCompressorInfo},
-	{"GetDefault",		cl_GetDefault},
-	{"GetMinMax",		cl_GetMinMax},
-	{"GetName",		cl_GetName},
-	{"GetParams",		cl_GetParams},
-	{"QueryParams",		cl_QueryParams},
-	{"SetParams",		cl_SetParams},
+	{"CloseCompressor",	clm_CloseCompressor},
+	{"Compress",		clm_Compress},
+	{"GetCompressorInfo",	clm_GetCompressorInfo},
+	{"GetDefault",		clm_GetDefault},
+	{"GetMinMax",		clm_GetMinMax},
+	{"GetName",		clm_GetName},
+	{"GetParams",		clm_GetParams},
+	{"QueryParams",		clm_QueryParams},
+	{"SetParams",		clm_SetParams},
 	{NULL,			NULL}		/* sentinel */
 };
 
 static struct methodlist decompressor_methods[] = {
-	{"CloseDecompressor",	cl_CloseDecompressor},
-	{"Decompress",		cl_Decompress},
-	{"GetDefault",		cl_GetDefault},
-	{"GetMinMax",		cl_GetMinMax},
-	{"GetName",		cl_GetName},
-	{"GetParams",		cl_GetParams},
-	{"QueryParams",		cl_QueryParams},
-	{"SetParams",		cl_SetParams},
+	{"CloseDecompressor",	clm_CloseDecompressor},
+	{"Decompress",		clm_Decompress},
+	{"GetDefault",		clm_GetDefault},
+	{"GetMinMax",		clm_GetMinMax},
+	{"GetName",		clm_GetName},
+	{"GetParams",		clm_GetParams},
+	{"QueryParams",		clm_QueryParams},
+	{"SetParams",		clm_SetParams},
 	{NULL,			NULL}		/* sentinel */
 };
 
@@ -460,20 +467,11 @@
 	clobject *self = (clobject *) callbackID;
 	object *result;
 
-	args = newtupleobject(3);
+	args = mkvalue("(Oii)", self->ob_callbackID, frameIndex,
+		       numberOfFrames);
 	if (args == NULL)
 		return FAILURE;
 
-	XINCREF(self->ob_callbackID);
-	settupleitem(args, 0, self->ob_callbackID);
-	settupleitem(args, 1, newintobject(frameIndex));
-	settupleitem(args, 2, newintobject(numberOfFrames));
-
-	if (err_occurred()) {
-		XDECREF(self->ob_callbackID);
-		return FAILURE;
-	}
-
 	result = call_object(self->ob_callbackFunc, args);
 	DECREF(args);
 	if (result == NULL)
@@ -503,20 +501,11 @@
 	object *args, *result;
 	clobject *self = (clobject *) callbackID;
 
-	args = newtupleobject(3);
+	args = mkvalue("(Oii)", self->ob_callbackID, frameIndex,
+		       numberOfFrames);
 	if (args == NULL)
 		return FAILURE;
 
-	XINCREF(self->ob_callbackID);
-	settupleitem(args, 0, self->ob_callbackID);
-	settupleitem(args, 1, newintobject(frameIndex));
-	settupleitem(args, 2, newintobject(numberOfFrames));
-
-	if (err_occurred()) {
-		XDECREF(self->ob_callbackID);
-		return FAILURE;
-	}
-
 	result = call_object(self->ob_callbackFunc, args);
 	DECREF(args);
 	if (result == NULL)
@@ -587,6 +576,7 @@
 	INCREF(new->ob_callbackID);
 	new->ob_data = NULL;
 	new->ob_dataMaxSize = compressionFormat.dataMaxSize;
+	new->ob_frameSize = compressionFormat.frameSize;
 
 	return new;
 }
@@ -645,6 +635,7 @@
 	XINCREF(new->ob_callbackID);
 	new->ob_data = NULL;
 	new->ob_dataMaxSize = compressionFormat.dataMaxSize;
+	new->ob_frameSize = compressionFormat.frameSize;
 
 	return new;
 }
@@ -669,10 +660,56 @@
 	return newintobject(paramID);
 }
 
+static object *
+cl_QueryParams(self, args)
+	object *self, *args;
+{
+	long handle, *PVbuffer, bufferlength;
+	object *list;
+	int i;
+
+	if (!getargs(args, "i", &handle))
+		return NULL;
+
+	error_handler_called = 0;
+	bufferlength = clQueryParams((CL_CompressorHdl) handle, 0, 0);
+	if (error_handler_called)
+		return NULL;
+
+	PVbuffer = NEW(long, bufferlength);
+	if (PVbuffer == NULL)
+		return err_nomem();
+
+	bufferlength = clQueryParams((CL_CompressorHdl) handle, PVbuffer,
+				     bufferlength);
+	if (error_handler_called) {
+		DEL(PVbuffer);
+		return NULL;
+	}
+
+	list = newlistobject(bufferlength);
+	if (list == NULL) {
+		DEL(PVbuffer);
+		return NULL;
+	}
+
+	for (i = 0; i < bufferlength; i++) {
+		if (i & 1)
+			setlistitem(list, i, newintobject(PVbuffer[i]));
+		else
+			setlistitem(list, i, newstringobject((char *) PVbuffer[i]));
+	}
+
+	DEL(PVbuffer);
+
+	return list;
+}
+
 static struct methodlist cl_methods[] = {
 	{"AddParam",		cl_AddParam},
 	{"OpenCompressor",	cl_OpenCompressor},
 	{"OpenDecompressor",	cl_OpenDecompressor},
+	{"QueryParams",		cl_QueryParams},
 	{NULL,			NULL} /* Sentinel */
 };