#import "Briefcase.h"
#import "BriefDoc.h"
#import "PrefDelegate.h"
#import <appkit/appkit.h>

@implementation Briefcase:MultApp

/* Canon Information Systems is not responsible for anything anyone does with this   */
/* code, nor are they responsible for the correctness of this code.  Basically, this */
/* has very little to do with the company I work for, and you can't blame them.      */

/* This file is best read in a window as wide as this comment, and with tab settings */
/* of 4 spaces and indent setting of 4 spaces (at least, that's what I use).		 */

/* You are welcome to do as you would with this file under the following conditions. */
/* First, I accept no blame for anything that goes wrong no matter how you use it,   */
/* no matter how catastrophic, not even if it stems from a bug in my code.			 */
/* Second, please keep my notices on it when/if you distribute it.					 */
/* Third, if you discover any bugs or have any comments, PLEASE TELL ME!  Code won't */
/* get better without people picking it apart and giving the writer feedback.        */
/* Fourth, if you modify it, please keep a notice that your version is based on mine */
/* in the source files (and keep the notice that mine is based on four other pieces  */
/* of code :<).  Thanks, and have fun.  - Subrata Sircar, ssircar@canon.com			 */

/* This class is an instance of the application delegate class.		*/
/* It handles the drag and drop functions, and the communication	*/
/* with the Workspace.												*/

/* Version 1.0b		Apr-19-92		Third Public Release	*/

#define MY_VERSION		100

/* Public Methods */

- (int)delay
{
    return timeDelay;
}

- setDelay:(int)value;
{
	timeDelay = value;
	return self;
}


/* Target/Action Methods */

- addFile:sender
/*
 * Called by pressing Add File... in the Document menu.
 */
{
	char tempBuf[8192];
	char fileBuf[MAXPATHLEN+1];
    const char *directory;
    const char *const *files;
    static const char *const myType[1] = {NULL};
    id openpanel = [[OpenPanel new] allowMultipleFiles:YES];

    sprintf(tempBuf,"");
	directory = [[self currentDocument] directory];
    if (directory && (*directory == '/')) [openpanel setDirectory:directory];
    if ([openpanel runModalForTypes:myType]) {
		files = [openpanel filenames];
		directory = [openpanel directory];
		while (files && *files) {
	/* Get pathnames and add them to the current Document */
			sprintf(fileBuf,"%s/%s\n",directory,*files);
			strcat(tempBuf,fileBuf);
			files++;
		}
		[[self currentDocument] addFiles:tempBuf];
    }

    return self;
}


/* Automatic update methods */

- (BOOL)validateCommand:menuCell
{
    if ([super validateCommand:menuCell]) {
		if ([menuCell action] == @selector(addFile:)) return [self currentDocument] ? YES : NO;
		else return YES;
	} else return NO;
}


/* Application Delegate Methods */

- appWillInit:sender
{
	char temp[MAXPATHLEN+1];
	/* check and load appropriate defaults */
	
	[super appWillInit:self];
	[[self class] setDocClass:[BriefDoc class]];
	[[self class] setVersion:MY_VERSION];
	
	if (!NXGetDefaultValue([NXApp appName],LocalString("TimeDelay"))) sprintf(temp,"1000");
	else sprintf(temp,NXGetDefaultValue([NXApp appName],LocalString("TimeDelay")));
	sscanf(temp,"%d",&timeDelay);

    return self;
}

- appWillTerminate:sender
/*
 * Overridden to be sure all documents get an opportunity to be saved
 * before exiting the program.  Save the defaults too.
 */
{
	char temp[100];

	sprintf(temp,"%d",timeDelay);
	NXWriteDefault([NXApp appName],LocalString("TimeDelay"),temp);
	return [super appWillTerminate:self];
}
    

/* WARNING!  Hack alert!!  */
/* When an application is inactive, the main window has no meaning.  Apparently it */
/* also doesn't become active until after the appDidBecomeActive: message is sent. */
/* Hence, I queue up a delayed message such that timeDelay milliseconds after the  */
/* application activates, it updates its main window and adds the files then.      */

static char myBuf[MAX_STRING_ARRAY];

- pleaseUpdate:sender
{
	/* Update the drag/drop files and clear the buffer */
	[[self currentDocument] addFiles:myBuf];
	*myBuf = '\0';
	return self;
}
	
- appDidBecomeActive:sender
{
	return [self perform:@selector(pleaseUpdate:) with:self afterDelay:timeDelay cancelPrevious:YES];
}


/* Listener/Speaker remote methods */

// IconDragging Stuff, oh boy, oh boy!
static char **filePath = NULL;
static int files = 0;
 
- (int)iconEntered:(int)windowNum at:(double)x :(double)y
    iconWindow:(int)iconWindowNum iconX:(double)iconX iconY:(double)iconY
    iconWidth:(double)iconWidth iconHeight:(double)iconHeight
    pathList:(const char *)pathList
{
	char *stringPos, *tempPtr;
	char tempBuf[MAXPATHLEN+1];
	int count = 0;
	
	if (filePath) {
		freeList(filePath);
		filePath = NULL;
	}
	stringPos = tempPtr = (char *)pathList;
	files = 0;
	    
	/* This code just parses the pathList for the filenames and explictly */
	/* null-terminates them after copying into a buffer.  It appends that */
	/* buffer to the dynamically-allocated filelist which keeps track of it */

	/* the number of tabs + 1 equals the number of files dragged in */
	while (stringPos = index(stringPos, '\t')) {
		count = (int)(stringPos-tempPtr);
		strncpy(tempBuf,tempPtr,count);
		*(tempBuf+count) = '\0';
		filePath = addFile(tempBuf,filePath,files,MyZone);
		files++;
		stringPos++;
		tempPtr=stringPos;
    }
	strncpy(tempBuf,tempPtr,strlen(tempPtr));
	*(tempBuf+strlen(tempPtr)) = '\0';
	filePath = addFile(tempBuf,filePath,files,MyZone);
	files++;

    return 0;
}

- (int)iconExitedAt:(double)x :(double)y
// Erase those files someone waved through our icon
{
	freeList(filePath);
	filePath = NULL;
	files = 0;
	return 0;
}

- (int)iconReleasedAt:(double)x :(double)y ok:(int *)flag
// Add the fileList to the buffer which will be added upon activation
{
	char tempBuf[MAXPATHLEN+1];
	
	/* accept the icon */
    *flag = 1;
   
	while (files--) {
		if (*(filePath[files])) {
			sprintf(tempBuf,"%s\n",filePath[files]);
			strcat(myBuf,tempBuf);
		} else {
			strcat(myBuf,"/\n");	// Someone waved the hard disk in
		}		
	}
	
    return 0;
}

@end

