#import "SFODragDropText.h"
#import <appkit/appkit.h>


@implementation SFODragDropText

- awakeFromNib
{
	NXAtom	supportedTypes[11] = {NXFilenamePboardType,
								NXFileContentsPboardType, 
								NXSoundPboardType,
								NXPostScriptPboardType, 
								NXTIFFPboardType,
								NXColorPboardType,
								NXFontPboardType,
								NXRulerPboardType,
								NXRTFPboardType,
								NXAsciiPboardType,
								NULL};
	[self registerForDraggedTypes:supportedTypes count:10];
	return self;
}


/********************************************/
/* add file contents dragging               */
/********************************************/
	
- (NXDragOperation)draggingUpdated:(id <NXDraggingInfo>)sender
{	
	// Check for self-drags
	if ([sender draggingSource] == self)
		return NX_DragOperationNone;
		
	return [super draggingUpdated:sender];
}


- (int)positionForCell:theCell
{
	int pos,k,N;
	NXRun *curr;
	
	if (theCell == nil) return -1;
	pos=0;
	N = theRuns->chunk.used/sizeof(NXRun);
	curr = theRuns->runs;
	for (k=0; k < N; k++) {
		if (curr->info == theCell) return pos;
		pos += curr->chars;
		curr++;
	}
	return -1;
}

- writeCell:theCell toPasteboard:pboard types:(NXAtom *)types
{
	int        numTypes = 0;
	NXSelPt    start, end;
	int        cellPos;
	NXStream  *memStream;
	Text      *rtfd;
	NXRTFDError errno;
	char       path[MAXPATHLEN+1];
	
	while (types && types[numTypes++]); 
	cellPos = [self positionForCell:theCell];
	if (cellPos == -1)
		return nil;
	
	[pboard declareTypes:types num:numTypes-1 owner:nil];

	start = sp0; end = spN;
	[self setSel:cellPos :cellPos+1];
	memStream = NXOpenMemory(NULL, 0, NX_READWRITE);
	[self writeRTFDSelectionTo:memStream];
	NXSeek(memStream, 0, NX_FROMSTART);
	rtfd = [[Text alloc] init];
	[[NXBundle bundleForClass:[SFODragDropText class]]
		getPath:path forResource:"Empty.rtfd" ofType:NULL];
	[rtfd openRTFDFrom:path];
	[rtfd setMonoFont:NO];
	[rtfd setGraphicsImportEnabled:YES];
	if ([rtfd readRTFDFrom:memStream])
		if (errno = [rtfd saveRTFDTo:"/tmp/nt0815.rtfd"
			removeBackup:NO errorHandler:nil] != NX_RTFDErrorNone)
		{
			NXRunAlertPanel("Save RTFD", "Could not save to file %s; error %i."
				, "Sorry!", NULL, NULL
				, "/tmp/nt0815.rtfd", errno);
		}
	[rtfd free];
	NXCloseMemory(memStream, NX_FREEBUFFER);

	sprintf(path, "/tmp/nt0815.rtfd/%s", [theCell stringValue]);
	[pboard writeType:NXFilenamePboardType data:path length:strlen(path)+1];
	[self setSel:start.cp :end.cp];
	return self;
}

@end


@implementation NXGraphicCell(NetTalkAdditions)

- (NXDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal
{
	return (isLocal ? NX_DragOperationNone : NX_DragOperationCopy);
}

#define mask (NX_LMOUSEUPMASK|NX_LMOUSEDRAGGEDMASK)

- (BOOL)trackMouse:(NXEvent *)theEvent inRect:(const NXRect *)cellFrame ofView:controlView
{
	id         dragPasteboard;
	NXAtom     supportedTypes[] = {NXFilenamePboardType, NULL};
	NXPoint    offset, mLoc;
	NXRect     tracker;
	NXEvent   *nextEvent, saveEvent;
	NXImage   *dragImage;
	char      *filenameChars;
	int        filenameLength;
	BOOL       inside, editableFlag, shouldLoop;
	int        oldMask;
	
	if (![controlView respondsTo:@selector(writeCell:toPasteboard:types:)])
		return NO;
	if (theEvent->data.mouse.click == 2)
	{		
		dragPasteboard = [Pasteboard newName:NXDragPboard];
		[controlView writeCell:self toPasteboard:dragPasteboard
			types:supportedTypes];
		
		[dragPasteboard readType:NXFilenamePboardType
			data:&filenameChars length:&filenameLength];
		[[Application workspace] openFile:filenameChars];
		[dragPasteboard free];
		return YES;
	}
	if (theEvent->type == NX_LMOUSEDOWN)
	{
		oldMask = [[controlView window] addToEventMask:NX_LMOUSEDRAGGEDMASK];
		saveEvent = *theEvent;
		tracker = *cellFrame;
		shouldLoop = YES;
    while (shouldLoop)
		{
			nextEvent = [NXApp getNextEvent:mask];
			mLoc = nextEvent->location;
			[controlView convertPoint:&mLoc fromView:nil];
			inside = [controlView mouse:&mLoc inRect:&tracker];
			if (!inside)
			{
				NXSize  imgSize;
				NXPoint imgLoc;
				editableFlag = [controlView isEditable];
				[controlView setEditable:NO];
				dragPasteboard = [Pasteboard newName:NXDragPboard];
					
				[controlView writeCell:self
					toPasteboard:dragPasteboard
					types:supportedTypes];
				
				[dragPasteboard readType:NXFilenamePboardType
					data:&filenameChars length:&filenameLength];
				dragImage = [[Application workspace] getIconForFile:filenameChars];
				
				[dragImage getSize:&imgSize];
				imgLoc = saveEvent.location;
				[controlView convertPoint:&imgLoc fromView:nil];
				imgLoc.x -= imgSize.width/2;
				imgLoc.y += imgSize.height/2;
				offset.x = nextEvent->location.x - saveEvent.location.x;
				offset.y = nextEvent->location.y - saveEvent.location.y;

				[controlView dragImage:dragImage
					at:&imgLoc offset:&offset
					event:&saveEvent pasteboard:dragPasteboard
					source:self slideBack:YES];
				[dragImage free];
				[controlView setEditable:editableFlag];
				shouldLoop = NO;
			}
			if (nextEvent->type == NX_LMOUSEUP)
				shouldLoop = NO;	// mouse up outside rects.
    }
    [[controlView window] setEventMask:oldMask];
		return YES;
	}
	return NO;
	//[super trackMouse:theEvent inRect:cellFrame ofView:controlView];
}

@end
