
/* Generated by Interface Builder */

#import <appkit/appkit.h>
#import <streams/streams.h>
#import <math.h>
#import <stdio.h>
#import <stdlib.h>
#import <strings.h>
#import "ImageControl.h"
#import "HelpControl.h"
#import "PictureDocument.h"
#import "GraphicApp.h"
#import "ControlLoader.h"
#import "NXBitmapImageRepControl.h"
#import "DataPanel.h"
#import "Converter.h"
#import "Indexer.h"

char *getwd(char *);

@implementation GraphicApp

	int		curX = 165;
	int		curY = 700;

	char		*errors[] = 	{
							"No error has occured",
							"Unable to open file",
							"Permission denied",
							"Picture information has become corrupt",
							"File truncated",
							"Converter needs window server",
							"Unable to link the correct converter type",
							"Converter returned an unknown error code"
						};

+ new 
{
	id		myListener;
	
	self = [super new];

	// This will alloc me a NXBitmapImageRepControl off of disk.
	images = [[[ControlLoader loadControl: "Bitmap"] alloc] init];
	
	if (!images) {
		willFail = YES;
	}
	
	numWindows = 0;
	
	myListener = [NXApp appListener];
	[myListener setServicesDelegate: self];
		
	return self;
}

- loadNibFile:(const char *)name owner:anObject withNames:(BOOL)flag;
{
	NXBundle		*myBundle;
	char				buffer[MAXPATHLEN + 1];
	char				name2[MAXPATHLEN + 1];

	strcpy(name2, name);
	strrchr(name2,'.')[0] = '\0';
	chdir(appPath);
	myBundle = [NXBundle bundleForClass: [self class]];
	if ([myBundle getPath: buffer forResource: name2 ofType: "nib"]) {
		return [super loadNibFile: buffer owner: anObject withNames: flag];
	}
	return nil;
}

- fail:sender
{
	[self terminate: self];
	return self;
}

- setFailPanel:anObject
{
	failPanel = anObject;
	
	if (willFail) {
		[failPanel makeKeyAndOrderFront: self];
	}
	return self;
}

- handleOpenBitmap: 	(id)newBitmap 
		withName:	(const char *)name 
		ofType:		(const char *)type
{
	picDoc = [PictureDocument newWithName: name 
					at: 				&curX and: &curY
					of: 				newBitmap
					ofType: 			(char *)type];
	[saveMenu setEnabled: YES];
	[saveAsMenu setEnabled: YES];
	[revertToSavedMenu setEnabled: YES];
	[copyMenu setEnabled: YES];
	[printMenu setEnabled: YES];
	numWindows++;

	[picDoc windowDidBecomeMain: self];

	return self;
}

- open:sender
{
	id		openPanel = [OpenPanel new];
	id		image;
	char		**files;
	int		x;
	char		buffer[MAXPATHLEN];

	[openPanel allowMultipleFiles: YES];
	
	if (![images runOpenPanel: openPanel]) return self;
	
	files = (char **)[openPanel filenames];
	chdir((char *)[openPanel directory]);
	
	for (x = 0; files[x]; x++) {
		sprintf(buffer, "%s/%s", [openPanel directory], files[x]);
		if (image = [images openAndReturnImage: buffer]) {
			if ([images errorState] != CONVERT_ERR_NONE) {
				NXRunAlertPanel("Alert",
								errors[[images errorMessage]],
								"Continue", NULL, NULL);
			}
			chdir(appPath);			// This makes sure that dynamically loaded nibs
									// can find all their parts, like tiff's.
			[self 	handleOpenBitmap: 	image 
					withName: 			buffer 
					ofType: 				[images getCurrentFormatName]];
			chdir((char *)[openPanel directory]);  // and reset path back.
		}
		else {
			NXRunAlertPanel("Alert", 
							"Unable to open file: %s\n", 
							"Continue", NULL, NULL, 
							files[x]);
		}
	}
	chdir(appPath);					// This makes sure that dynamically loaded nibs
									// can find all their parts, like tiff's.
	return self;
}

- info:sender
{
	if (!infoPanel) {
		infoPanel = [NXApp loadNibFile:"InfoPanel.nib" owner:self withNames:NO];
		[infoPanel useOptimizedDrawing:YES];
        }
        [infoPanel makeKeyAndOrderFront:self];

	return self;
}

- saveAs:sender
{
	id		savePanel = [SavePanel new];
	char		name[MAXPATHLEN];
	char		buffer[MAXPATHLEN];
	char		path[MAXPATHLEN];

	if (!strncmp([[self mainWindow] title], "Untitled", 8)) {
		strcpy(name, "Untitled.tiff");
		strcpy(path, "~");
	} else { 
		sscanf([[self mainWindow] title], "%s %s %s", name, buffer, path);
	}
	sprintf(buffer, "%s/%s", path, name);

	if ([images runSavePanel: savePanel withFilename: buffer]) {
		if (![images saveImage: [currentDoc getImage] toFile: [savePanel filename]]) {
			sprintf(buffer, "Unable to save file: %s", [savePanel filename]);
			NXRunAlertPanel("Save", buffer, "Continue", NULL, NULL, NULL);
		} else {
			[[self mainWindow] setTitleAsFilename: [savePanel filename]];
		} 
	}

	return self;
}

- preferences:sender
{
    return self;
}

- help:sender
{
        if (!helpPanel) {
		helpPanel = [NXApp loadNibFile:"HelpPanel.nib" owner:self withNames:NO];
		[helpPanel useOptimizedDrawing:YES];
	}
	[helpPanel makeKeyAndOrderFront:self];

        return self;
}

- close:sender
{
	if (!(--numWindows)) {
		[saveMenu setEnabled: NO];
		[saveAsMenu setEnabled: NO];
		[revertToSavedMenu setEnabled: NO];
		[copyMenu setEnabled: NO];
		[printMenu setEnabled: NO];
		[dataPanelInstance setWidth: 		0];
		[dataPanelInstance setHeight:		0];
		[dataPanelInstance setBitsPerSample:0];
		[dataPanelInstance setSamplesPerPixel:0];
		[dataPanelInstance setHasAlpha: 	NO];
		[dataPanelInstance setIsPlanar: 		NO];
		[dataPanelInstance setSizeInBytes: 	0];
		[dataPanelInstance setColors: 		0];
		[(DataPanel *)dataPanelInstance setName: "No Picture Loaded"];
		[dataPanelInstance setPicName: 	"No Picture Loaded"];
		currentDoc = nil;
	}
	return self;
}

- save:sender
{
	id		savePanel = [SavePanel new];
	char		name[MAXPATHLEN];
	char		buffer[MAXPATHLEN];
	char		path[MAXPATHLEN];
	char		fullName[MAXPATHLEN];

	if (!strncmp([[self mainWindow] title], "Untitled", 8)) {
		[self saveAs: sender];
		return self;
	} 
	sscanf([[self mainWindow] title], "%s %s %s", name, buffer, path);
	sprintf(fullName, "%s/%s", path, name);
	if (![images saveImage: [currentDoc getImage] toFile: fullName]) {
		sprintf(buffer, "Unable to save file: %s", [savePanel filename]);
		NXRunAlertPanel("Save", buffer, "Continue", NULL, NULL, NULL);
	}

	return self;
}

- copy:sender
{
	id			myPboard = [Pasteboard newName: NXGeneralPboard];
	NXStream	*myStream;
	char			*data;
	int			length, maxLength;

#ifdef DEBUG
	fprintf(stderr, "Asked to copy\n");
#endif
	
	[myPboard declareTypes: &NXTIFFPboardType num:1 owner:self];
	myStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
	[[currentDoc getImage] writeTIFF: myStream];
	NXGetMemoryBuffer(myStream, &data, &length, &maxLength);
	[myPboard writeType: NXTIFFPboardType data: data length: length];
	NXCloseMemory(myStream, NX_FREEBUFFER);

#ifdef DEBUG
	fprintf(stderr, "Copy completed\n");
#endif
	
	return self;
}

- paste:sender
{
	const NXAtom	*type;
	id				myPboard = [Pasteboard newName: NXGeneralPboard];
	char				*data;
	int				length;
	NXStream		*myStream;
	id				newDocument = [NXBitmapImageRep alloc];
	char				buffer[MAXPATHLEN];

#ifdef DEBUG
	fprintf(stderr, "Asked to paste\n");
#endif
	
	for (type = [myPboard types]; *type; type++) {
		if (!strcmp(*type, NXTIFFPboardType)) break;
	}
	
	if (*type) {
		[myPboard readType: NXTIFFPboardType data: &data length:&length];
		myStream = NXOpenMemory(data, length, NX_READONLY);
		
		if ([newDocument initFromStream: myStream]) {
			sprintf(buffer, "~/Untitled%d.tiff", numWindows + 1);
			[self 	handleOpenBitmap: 	newDocument 
					withName: 			buffer
					ofType:				"Pasteboard Image"];
		} else {
			NXRunAlertPanel("Alert", "Unable to paste TIFF", "Continue", NULL, NULL);
		}
		
		NXCloseMemory(myStream, NX_FREEBUFFER);
	} else {
		NXRunAlertPanel("Alert", "Unable to paste TIFF", "Continue", NULL, NULL);
	}
	
	return self;
}

- print:sender
{
	[currentDoc print: sender];

	return self;
}

- data:sender
{
        [dataPanel makeKeyAndOrderFront:self];

	return self;
}

- setAppPath: (char *)path
{
	char		*buffer, *tmp;

	buffer = (char *)malloc(sizeof(char) * (strlen(path) + 1));
	strcpy(buffer, path);
#ifdef DEBUG
	fprintf(stderr, "My Name is %s\n", buffer);
#endif
	if (path[0] == '/') {
		if (tmp = rindex(buffer, '/')) {
			*tmp = '\0';
		}
		strcpy(appPath, buffer);
		strcat(appPath, "/");
	} else {
		getwd(appPath);
		if (tmp = rindex(buffer, '/')) {
			*tmp = '\0';
			strcat(appPath, "/");
			strcat(appPath, buffer);
		}
	}
	free(buffer);
#ifdef DEBUG
	fprintf(stderr, "And my path = %s\n", appPath);
#endif
	return self;
}

- (const char *)appPath
{
	return (const char *)appPath;
}

- loadInspectorPanel:sender
{
#ifdef DEBUG
	fprintf(stderr, "Current Inspector: %p\n", inspectorPanel);
#endif
	if (!inspectorPanel) {
		inspectorPanel = [NXApp loadNibFile:"ToolsInspector.nib" owner:self withNames:NO];
#ifdef DEBUG
		fprintf(stderr, "New Inspector: %p\n", inspectorPanel);
#endif
		[inspectorPanel useOptimizedDrawing:YES];
	}
	[currentDoc windowDidBecomeMain: self];
	[inspectorPanel makeKeyAndOrderFront:self];

	return self;
}

- setDataPanel:anObject;
{
#ifdef DEBUG
	fprintf(stderr, "Setting data panel instance\n");
#endif
	dataPanelInstance = anObject;
	return self;
}

- getDataPanel
{
	return dataPanelInstance;
}

- setConversionPanel:anObject
{
	conversionPanel = anObject;
	return self;
}

- conversionPanel
{
	return conversionPanel;
}

- reportDidBecomeMain: sender
{
	currentDoc = sender;
	
	return self;
}

- setIndexer:anObject
{
#ifdef DEBUG
	fprintf(stderr, "We're setting the indexer\n");
#endif
	indexer = anObject;
	return self;
}

- makeIndex:sender
{
	id		newImage;

        if (!indexer) {
		indexerPanel = [NXApp loadNibFile:"Indexer.nib" owner:self withNames:NO];
		[indexerPanel useOptimizedDrawing:YES];
	}

	newImage = [indexer makeIndex: images];

	[self 	handleOpenBitmap: 	newImage 
			withName: 			"Untitled1.tiff" 
			ofType: 				[images getCurrentFormatName]];

	return self;
}

- currentDoc
{	
	return currentDoc;
}

- imageControl
{
	return images;
}

- (int)app:sender openFile:(const char *)filename type:(const char *)aType
{
	id 		image;

	if (!strcmp(aType, "tools")) return NO;
	else if (!strcmp(aType, "bcvt")) return NO;
	else if (!strcmp(aType, "controls")) return NO;
	
#ifdef DEBUG
	fprintf(stderr, "I open %s %s\n", filename, aType);
#endif
	if (image = [images openAndReturnImage: filename]) {
		if ([images errorState] != CONVERT_ERR_NONE) {
			NXRunAlertPanel("Warning",
							errors[[images errorMessage]],
							"Continue", NULL, NULL);
		}
		[self 	handleOpenBitmap: 	image 
				withName: 			filename 
				ofType: 				[images getCurrentFormatName]];
	}
	else {
		NXRunAlertPanel("Alert", 
						"Unable to open file: %s\n\n%s", 
						"Continue", NULL, NULL, 
						filename, errors[[images errorMessage]]);
		return NO;
	}
	
	return YES;
}

- (int)appAcceptsAnotherFile: sender
{
	return YES;
}

- (int)msgPaste:(int *)flag
{
	[self paste: self];
	*flag = YES;
	
	return 0;
}

- acceptTIFF: (id)pasteboard userData:(const char *)userData error:(char **)msg
{
	const NXAtom	*type;
	char				*data;
	int				length;
	NXStream		*myStream;
	id				newDocument = [NXBitmapImageRep alloc];
	char				buffer[MAXPATHLEN];

	fprintf(stderr, "Asked to paste via service\n");
	
	for (type = [pasteboard types]; *type; type++) {
		if (!strcmp(*type, NXTIFFPboardType)) break;
	}
	
	if (*type) {
		[pasteboard readType: NXTIFFPboardType data: &data length:&length];
		myStream = NXOpenMemory(data, length, NX_READONLY);
		
		if ([newDocument initFromStream: myStream]) {
			sprintf(buffer, "~/Untitled%d.tiff", numWindows + 1);
			[self 	handleOpenBitmap: 	newDocument 
					withName: 			buffer
					ofType:				"Pasteboard Image"];
		} else {
			NXRunAlertPanel("Alert", "Unable to paste TIFF", "Continue", NULL, NULL);
		}
		
		NXCloseMemory(myStream, NX_FREEBUFFER);
	} else {
		NXRunAlertPanel("Alert", "Unable to paste TIFF", "Continue", NULL, NULL);
	}
	
	return self;
}

@end
