///////////////////////////////////////////////////////////////////////////////
//	FILENAME:	eTURLink.h 
//	SUMMARY:	Implementation of a URL Annotation
//	SUPERCLASS:	eTImage
//	INTERFACE:	None
//	PROTOCOLS:	<Annotation,HTMDSupport,ASCIISupport,LaTeXSupport,Tool,
//				InspectableTarget>
//	AUTHOR:		Rohit Khare
//	COPYRIGHT:	(c) 1994 California Institure of Technology, eText Project
///////////////////////////////////////////////////////////////////////////////
//	IMPLEMENTATION COMMENTS
//		Holds an URLrep and tries to NXPerformService("Open URL").
//		Tries to lookup an icon based on the scheme of the URL if possible
///////////////////////////////////////////////////////////////////////////////
//	HISTORY
//	02/04/95:	Added support to create .uri files; draggability
//  02/04/95:	Modified to support new services (SpiderWoman, Omni .9)
//	10/30/94:	Modified to support <InspectableTarget>
//  07/20/94:	Minimal Creation
///////////////////////////////////////////////////////////////////////////////

#import "eTURLink.h"
#define _eTURLinkVERSION	10

@implementation eTURLink
//	char *URLRep;

- setURL: (const char *) newURL
{	
	URLRep = realloc(URLRep,(strlen(newURL)+1)*sizeof(char));
	strcpy(URLRep, newURL);
	[etDoc touch];
	return self;
}
- (char *) URL {return URLRep;}

+ toolAwake:theApp
{
	char        buf[MAXPATHLEN];
	NXBundle	*bundle;
	id 			icon=nil;

	bundle = [NXBundle bundleForClass:[eTURLink class]];
	// we should register a whole bunch of images here: "Gopher", "News",etc
	if ([bundle getPath:buf forResource:"eTURLinkIcon" ofType:"tiff"] ) {
		icon=[[NXImage alloc] initFromFile:buf];
		[icon setName:"eTURLinkIcon"];
	} else {
		NXLogError("Image not found: eTURLinkIcon");
	}	
	[theApp   registerAnnotation: [eTURLink class] 
							name: "eTURLink"
					RTFDirective: "eTURLink"
					   menuLabel: "HTML/Insert eTURLink"
						 menuKey: '\0'
						menuIcon: (NXImage *) icon];

	[theApp registerType:NXCreateFileContentsPboardType(".uri") for:[eTURLink class]];
	[theApp registerType:URIPboardType for:[eTURLink class]];
	[theApp registerType:OWPboardType for:[eTURLink class]];

	return self;
}

- init
{
#define DEFAULT "http://www.etext.caltech.edu/"
	[super init];
	[self setUsesButtonStyle:NO];
	[self setDraggable:YES];
	[self setImageComponent:[eTImageComponent newImageNamed:"eTURLinkIcon"]];
	URLRep = (char *)malloc((strlen(DEFAULT)+1)*sizeof(char));
	strcpy(URLRep, DEFAULT);
	return self;
}

- initFromPboard:thePboard inDoc:theDoc linked:(BOOL) linked
{
	NXAtom foundType;
	NXAtom supportedTypes[4] = {URIPboardType, OWPboardType,
								NXFilenamePboardType,
								NXFileContentsPboardType};

	[super initFromPboard:thePboard inDoc:theDoc linked:linked];
	[imageComponent setDoc:etDoc];
	[self setDescription:"here"];

	// first, we want to check for OW url drag types.
	foundType = [thePboard findAvailableTypeFrom:supportedTypes num:4];

	if (foundType == NXFilenamePboardType) {
		// can we derive a .uri file name? if not, puke
		char	*path;
		int		len;

		[thePboard readType:NXFilenamePboardType data:&path length:&len];
		// we only process _ONE_ filename; this defeats the tab-separation
		if (index(path, '\t')) *index(path, '\t')=0;
		if (rindex(path, '.') && !strcmp(rindex(path, '.'), "."URI_EXT)) {
			NXStream *s;
			
			// OK, we have a .uri path: bring the contents in, and path as title.
			s = NXMapFile(path, NX_READONLY);
			if (s) {
				char *data, *url;
				int len, maxlen;
				
				NXGetMemoryBuffer(s, &data, &len, &maxlen);
				if (!strncmp(data, "URL:",4)) url = data+4;
					else if (!strncmp(data, "<URL:",5)) url = data+5;
					else url = data;
				[self setURL:url];
				NXCloseMemory(s, NX_FREEBUFFER);
			}
			*rindex(path, '.') = '\0';
			[self setDescription:path];
			[self setCaptionMode];
		}
		[thePboard deallocatePasteboardData:path length:len];
	} else if (foundType == NXFileContentsPboardType) {
		NXLogError("Eeek! Unimplemented: FileContentsPboard for eTURLink.");
	} else if (foundType == URIPboardType) {
		// Note that we can't yet handle multiple URLs
		char *data, *url;
		int len, maxlen;
		NXStream *s;
		
		s = [thePboard readTypeToStream:URIPboardType];
		if (s) {
			NXGetMemoryBuffer(s, &data, &len, &maxlen);
			if (!strncmp(data, "URL:",4)) url = data+4;
				else if (!strncmp(data, "<URL:",5)) url = data+5;
				else url = data;
			[self setURL:url];
			NXCloseMemory(s, NX_FREEBUFFER);
		}
		s = [thePboard readTypeToStream:URITitlePboardType];
		if (s) {
			NXGetMemoryBuffer(s, &data, &len, &maxlen);
			[self setDescription:data];
			[self setCaptionMode];
			NXCloseMemory(s, NX_FREEBUFFER);
		}
	} else if (foundType == OWPboardType) {
		// OmniWeb combatibility hemorrage... 
		char *data;
		int len;
		
		[thePboard readType:OWPboardType data:&data length:&len];
		[self setURL:data];
		[self setDescription:data];
		[self setCaptionMode];
		[thePboard deallocatePasteboardData:data length:len];
	} else {
		NXSelPt	begin, end;

		[theText getSel:&begin :&end]; 	// we know the sel exists because
										// etApp checks acceptsAnnotation:
		if (begin.cp != end.cp) {
			char *buf = calloc((end.cp - begin.cp + 1) , sizeof(char));
			[theText getSubstring:buf start:begin.cp length:(end.cp - begin.cp)];
			[self setURL:buf];
			free(buf);
		}
	}
	return self;
}
- readRichText:(NXStream *)stream forView:view 
{
	int i;
	char buf[MAXPATHLEN];
	
	NXScanf(stream, "%d ", &i);
	if (i != _eTURLinkVERSION) {
		// bad version block.
	 NXLogError("eTURLink found unparseable version %d at position %d",
					i, NXTell(stream));
		return nil;
	}
	NXScanf(stream, "%d", &i); NXGetc(stream); //space-eater
	if(i) NXRead(stream,buf,i);
	buf[i]=0;
	[self setURL:buf];
	NXGetc(stream); // trailing space
	[super readRichText:stream forView:view];
	return self;
}

- writeRichText:(NXStream *)stream forView:view
{
	NXPrintf(stream, "%d %d %s ", _eTURLinkVERSION, 
			 strlen(URLRep), URLRep);
	[super writeRichText:stream forView:view];
	return self;
}

- writeASCIIRef:(NXStream *)stream forView:view
{
	NXPrintf(stream, "See %V.\n\t",URLRep);
	[super writeASCIIRef:stream forView:view];
	return self;
}

- writeHTML:(NXStream *)stream forView: view
{
	// always generates an icon -- we _ought_ to provide for an alternate
	// associated label.
	NXPrintf(stream,"<A HREF=\"%s\">", URLRep);
	[super writeHTML:stream forView:view];
	NXPrintf(stream,"</A>");
	return self;
}

- writeLaTeX:(NXStream *)stream forView: view
{
	[super writeLaTeX:stream forView:view];
	NXPrintf(stream,"\n\\footnote{See {\\tt %w}}\n",URLRep);
	return self;
}

- click:(NXEvent*)e
	{ return self;}
- doubleClick:(NXEvent *)e
{
	id	thePB;
	
	thePB = [Pasteboard newUnique];
	[thePB declareTypes:&NXAsciiPboardType num:1 owner:nil];
	[thePB writeType:NXAsciiPboardType data:URLRep length:strlen(URLRep)];
	if (!NXPerformService("Open URL", thePB) &&
		!NXPerformService("OmniWeb/Open URL", thePB) &&
		!NXPerformService("SpiderWoman/Open URL", thePB))
		NXRunAlertPanel("eTURLink","Could not open a "URI_EXT" file (using services): %s.", "OK", NULL, NULL, URLRep);
	return self;
}
- inspect:(NXEvent*)e
	{ [[NXApp inspector] inspect:self];return self;}
- (id <Inspectable>) inspectableDelegate {
	return [[eTURLinkUI new] setAnnotation:self]; }

- setImageComponent:newImageComponent
{
	const char *name;
	
	name = [[newImageComponent theImage] name];
	if (name && !strcmp(name,"eTURLinkIcon"))
		usesButtonStyle = NO;
	else
		usesButtonStyle = YES;
	return [super setImageComponent:newImageComponent];
}

- drag: (Pasteboard *)draggingPboard image: (NXImage **)proxyImage
{
	char	 filename[MAXPATHLEN], filteredTitle[MAXPATHLEN], *title;
	NXAtom	 types[3] = {URIPboardType, NXAsciiPboardType, NXFilenamePboardType};
	NXStream *b;
	int		 i;
	
	// write out .uri file in /tmp
	title = [self description];
	if (title && *title) sprintf(filteredTitle, "%s."URI_EXT, title);
	else sprintf(filteredTitle, "%s."URI_EXT, URLRep);
	
	// filter out /es
	for (i=0; filteredTitle[i]; i++) if (filteredTitle[i] == '/') filteredTitle[i] = '_';
	
	sprintf(filename, "/tmp/%s", filteredTitle);
	
	[draggingPboard declareTypes:types num:3 owner:nil];
	[draggingPboard writeType: NXFilenamePboardType data: filename
					length: strlen(filename)];

	b = NXOpenMemory(NULL, 0, NX_READWRITE);
	NXPrintf(b, "%V", URLRep);
	NXSeek(b, 0, NX_FROMSTART);
	[draggingPboard writeType: NXAsciiPboardType fromStream:b];

	NXSeek(b, 0, NX_FROMSTART);
	if (strncmp(URLRep, "URL:",4)) NXPrintf(b, "URL:%V", URLRep);
	else NXPrintf(b, "%V", URLRep);;
	NXSeek(b, 0, NX_FROMSTART);
	[draggingPboard writeType: URIPboardType fromStream:b];

	NXSeek(b, 0, NX_FROMSTART);
	NXSaveToFile(b, filename);
	NXCloseMemory(b, NX_FREEBUFFER);

	*proxyImage = [NXImage findImageNamed:NXUniqueString("eTURLinkIcon")];
	return self;
}

- addToPboard: pboard
{
	char	 buf[MAXPATHLEN];
	NXStream *b;
	
	b = NXOpenMemory(buf, MAXPATHLEN, NX_READWRITE);
	if (strncmp(URLRep, "URL:",4)) NXPrintf(b, "URL:%V", URLRep);
	else NXPrintf(b, "%V", URLRep);;
	NXSeek(b, 0, NX_FROMSTART);
	[pboard addTypes:&URIPboardType num:1 owner:nil];
	[pboard writeType:URIPboardType fromStream:b];
	NXClose(b);
}

@end