// Tabs:3 Indent:3

/*
 * GIFFilter.m, Graphics Interchange Format (GIF) image filter service.
 * Author: Michael McCulloch
 * From example code by: Ali T. Ozer, NeXT Computer, Inc.
 * Written for 3.1, June 15, 1993.
 *
 * You may freely copy, distribute and reuse the code in this example.
 * There is no warranty of any kind, expressed or implied, as to its
 * fitness for any particular use.
 */

#import <appkit/appkit.h>

extern NXBitmapImageRep *convertGIFToTIFF(NXStream *imageStream, float gammaFactor, BOOL showMessage, const char *imageFile);


@interface GIFConverter : Object
{
	float gammaFactor;
	BOOL showMessage;
}

- init;
- convertToTIFF:pb userData:(const char *)userData error:(char **)errorMessage;
@end



@implementation GIFConverter

- init
{
	static const NXDefaultsVector myDefaults = {
		{"gamma", "1.5"},{"GIFterminate", "1"},
		{"showMessages", "1"},{NULL, NULL}
	};
 
	self = [super init];
	NXRegisterDefaults("McFilter", myDefaults);
	gammaFactor = atof(NXGetDefaultValue("McFilter", "gamma"));
	showMessage = (BOOL)atoi(NXGetDefaultValue("McFilter", "showMessages")); 
	
	return self;
}

- convertToTIFF:pasteboard userData:(const char *)userData 
          error:(char **)errorMessage
{
	static NXAtom typesThatCanBeConverted[5] = {NULL, NULL, NULL, NULL, NULL};
	NXAtom typeToBeConverted;
	char fileToBeConverted[MAXPATHLEN+1];
	NXStream *imageStream = NULL;
	u_char *rgb[5];
	const char *gammaDefault;
	const char *messageDefault;

	if(!typesThatCanBeConverted[0]){
		typesThatCanBeConverted[0] = NXCreateFilenamePboardType("gif");
		typesThatCanBeConverted[1] = NXCreateFilenamePboardType("GIF");
		typesThatCanBeConverted[2] = NXCreateFilenamePboardType("giff");
		typesThatCanBeConverted[3] = NXCreateFilenamePboardType("GIFF");
		typesThatCanBeConverted[4] = NULL;
	}

	if(typeToBeConverted = [pasteboard findAvailableTypeFrom:typesThatCanBeConverted num:4]){
		char *data, *separator, *extension;
		int dataLen;
		[pasteboard readType:typeToBeConverted data:&data length:&dataLen];
		if(data && dataLen){
			// Copy the name of the first file in the file list into "path"
			// (Usually there will only be one file, but don't take any chances!)
			int strLen = (separator = index(data, '\t')) ? (separator - data) : dataLen;
			strncpy(fileToBeConverted, data, strLen);
			fileToBeConverted[strLen] = 0;
			// Make sure the file extension is what we want. If not, we punt.
			extension = rindex(fileToBeConverted, '.');
			if(extension && ((strcmp(extension, ".gif") == 0) 
					||  (strcmp(extension, ".GIF") == 0)
					||  (strcmp(extension, ".giff") == 0)
					||  (strcmp(extension, ".GIFF") == 0))){
				imageStream = NXMapFile(fileToBeConverted, NX_READONLY);
			}
		}
		// Deallocate the file name list
		[pasteboard deallocatePasteboardData:data length:dataLen];
	}

	/* go ahead and convert if stream was successfully opened */
	if(imageStream){
		NXBitmapImageRep *tiffImage = nil;
		NXStream *tiffStream = NULL;
		if((gammaDefault = NXUpdateDefault("McFilter","gamma")) != NULL)
			gammaFactor = atof(gammaDefault);
		if((messageDefault = NXUpdateDefault("McFilter", "showMessages")) != NULL)
			showMessage = (BOOL)atoi(messageDefault);

		NX_DURING
			if(tiffImage = convertGIFToTIFF(imageStream,gammaFactor,showMessage,fileToBeConverted)){
				tiffStream = NXOpenMemory (NULL, 0, NX_READWRITE);
				[tiffImage writeTIFF:tiffStream];
				[pasteboard declareTypes:&NXTIFFPboardType num:1 owner:self];
				[pasteboard writeType:NXTIFFPboardType fromStream:tiffStream];
			}
		NX_HANDLER
			NXLogError("Error occurred while converting file %s:",fileToBeConverted);
			NXReportError(&NXLocalHandler);
		NX_ENDHANDLER
  
		if(tiffImage){
			[tiffImage getDataPlanes:rgb];
			if(rgb[0]) free(rgb[0]);
			if(rgb[1]) free(rgb[1]);
			if(rgb[2]) free(rgb[2]);
			[tiffImage free];
		}

		if(tiffStream) NXCloseMemory (tiffStream, NX_FREEBUFFER);
		NXCloseMemory (imageStream, NX_FREEBUFFER);
		imageStream = NULL;
	}
	
	return self;
}

@end


int main(int argc, char **argv)
{
	id listener = [Listener new];
	[listener setServicesDelegate:[GIFConverter new]];
	[listener checkInAs:"GIF Converter"];
	[listener addPort];
	[Listener run];
}

