// AcceptDragText.m
// By Charles G. Fleming, Educational Computing Services, Allegheny College.
// Copyright 1993, Allegheny College.
// You may freely copy, distribute and reuse this code. 
// Allegheny College and the author disclaim any warranty of any kind, 
// expressed or implied, as to its fitness for any particular use.

#import "AcceptDragText.h"
#import "Borders.h"
#import "SaverAndRetriever.h"

@implementation AcceptDragText

- initFrame:(const NXRect *)frameRect text:(const char *)theText 
		alignment:(int)mode
{
	int numTypes = 1;
	const char *pasteboardTypes[2] = {NXFilenamePboardType, NULL};

	[super initFrame:frameRect text:theText alignment:mode];
	
	// Register the dragging types that this view will accept.
	[self registerForDraggedTypes:pasteboardTypes count:numTypes];

	// Get a pasteboard for dragging.
	dragPasteboard = [Pasteboard newName:NXDragPboard];	

	// Create a file retriever to load dragged data files.
	dataFileRetriever = [[FileRetriever allocFromZone:[self zone]] init];
	[dataFileRetriever setDataDelegate:self];	
	return self;
}				

- setOutputWindow:anObject
{
	outputWindow = anObject;
	return self;
}
	
-setInspectorPanel:anObject
{
	inspectorPanel = anObject;
	return self;
}
	
//*****************************************************************************
//*****************************************************************************
// NXDraggingDestination routines. 
// Note that views and windows do not have to implement all of these methods
// since the View and Window classes provide private implemenations for all of
// these methods.
//*****************************************************************************
//*****************************************************************************

// The dragged image has entered the view.
- (NXDragOperation)draggingEntered:sender
{
	NXDragOperation sourceMask;
	NXPoint corner = {21, 57};
	NXRect borderRect;

	// Draw a blace border around the text when a file is dragged into it.
	
	// Set up the NXImage that will display a black border when a file is
	// dragged into the input text.
	[[superview superview] getContentSize:&borderRect.size];
	
	if(blackBorderNXImage)
		[blackBorderNXImage free];
		
	blackBorderNXImage = [[NXImage allocFromZone:[self zone]] 
			initSize:&borderRect.size];
	[blackBorderNXImage lockFocus];
	drawBlackBorder(borderRect.size.width, borderRect.size.height,
			borderRect.size.width-2, borderRect.size.height-1);
	[blackBorderNXImage unlockFocus];

	// Draw the border.	
	[[window contentView] lockFocus];
	[blackBorderNXImage composite:NX_SOVER toPoint:&corner];
	[[window contentView]  unlockFocus];
	[window flushWindow];

	// Ask the drag source for its operation mask.
	sourceMask = [sender draggingSourceOperationMask]; 
	if (sourceMask & NX_DragOperationCopy)
		dragOperation = NX_DragOperationCopy;
	else
		dragOperation = NX_DragOperationNone;
	return dragOperation;
}
	
// While the dragged image remains in the view, we receive this message.
- (NXDragOperation)draggingUpdated:sender
{
	return dragOperation;  
}

// If the dragged image leaves the view, we receive this message.
- draggingExited:sender
{
	// Remove the black border being displayed.
	[[self superview] display];
	return self;
}

// When the dragged image is released, this message is sent.  If we return 
// YES, we will receive the performDragOperation: message.
- (BOOL)prepareForDragOperation:sender
{
	// Remove the black border being displayed.
	[[self superview] display];

	// We do want to accept the dragged image and receive the
	// performDragOperation message.
	return YES;
}

// Do your work here.	
- (BOOL)performDragOperation:sender
{
	BOOL viewAcceptedData = NO, directoryFound = NO;
	int dataLength;
	char *filePath;
	char *tab, *startPath, *remainingPaths, *lastSlash;

	// Get the filename from the pasteboard.
	if([dragPasteboard readType:NXFilenamePboardType data:&filePath
			length:&dataLength])
	{
		[self setText:""];	
		startPath = filePath;
		
		// Count the files.
		tab = filePath;
		
		for(; tab = index(tab, '\t'); tab++)
		{
			remainingPaths = tab+1;
			*tab = '\0';
			
			if(lastSlash = rindex(startPath, '/'))
			{
				strcpy(filename, lastSlash+1);
				*lastSlash = '\0';
				strcpy(directory, startPath);
				startPath = remainingPaths;
			}
			[(FileRetriever *)dataFileRetriever setDirectory:directory];
			[(FileRetriever *)dataFileRetriever setFilename:filename];
			[dataFileRetriever open];
		}			

		if(lastSlash = rindex(startPath, '/'))
		{
			strcpy(filename, lastSlash+1);
			*lastSlash = '\0';
			strcpy(directory, startPath);
			startPath = remainingPaths;
		}
		[(FileRetriever *)dataFileRetriever setDirectory:directory];
		[(FileRetriever *)dataFileRetriever setFilename:filename];
		[dataFileRetriever open];
		
		viewAcceptedData = YES;
	}
	return viewAcceptedData;
}

// Any necessary cleaning can be done here.  This is the last message
// we will be sent.	
- concludeDragOperation:sender
{
	// The application will not be active if files were dragged into the 
	// input text from the Workspace.
	if(![NXApp isActive])
	{
		[NXApp activateSelf:YES];
		if(inspectorPanel)
			if([inspectorPanel isVisible])
				[inspectorPanel orderFront:self];
		[outputWindow orderFront:self];
		[window makeKeyAndOrderFront:self];
			
	}
	return self;
}

// We allow multiple data files to be dragged into the input text.
- (BOOL)readDataFromStream:(NXStream *)stream
{
	char *buffer, *dataString;
	int length, maxLength;
	
	NXGetMemoryBuffer(stream, &buffer, &length, &maxLength);
	
	dataString = (char *)malloc(length+1);
	strncpy(dataString, buffer, length);
	*(dataString+length) = '\0';
	
	[self setSel:textLength :textLength];
	[self replaceSel:dataString];
	[self sizeToFit];
	
	free(dataString);
	return YES;
}	
@end
