
#import "AlexandraApp.h"
#import "AMGErrorHandling.subproj/AMGErrorHandling.h"
#import <misckit/misckit.h>
#import <libc.h>
#import "emccodes.h"

//-----------------------------------------------------------
// Category of MiscInfoController 
//-----------------------------------------------------------

@interface MiscInfoController(GetStringTable)

- strings;

@end

@implementation MiscInfoController(GetStringTable)

- strings;
	{
	return strings;
	}
	
@end


@implementation AlexandraApp

//-----------------------------------------------------------
// initialise
//-----------------------------------------------------------

- appDidInit:sender;
	{
	[EMErrorManager new];	
	[self makeScratchDirectory];
	return self;
	}


- terminate:sender;
{
	if ([super terminate:sender] == nil)
	{
		[self removeScratchDirectory];
		return nil;
	}
	return self;
}

	
//-----------------------------------------------------------
// global attributes
//-----------------------------------------------------------

- (const char *)appVersion;
	{
	return [[(MiscInfoController *)infoController strings] valueForKey:"Version"];
	}
	
	
//-----------------------------------------------------------
//	scratch directory
//-----------------------------------------------------------

- (void)_removeDirectory:(const char *)pathName;
{
	DIR				*dirp;
	struct direct	*dp;

	if(chdir(pathName) < 0)
		EM_ERROR(EGENScratchDirInaccessible, pathName, NULL);
    if((dirp = opendir(".")) == NULL)
		EM_ERROR(EGENScratchDirInaccessible, pathName, NULL);
    for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) 
		{
		if((strcmp(dp->d_name, ".") == 0) || (strcmp(dp->d_name, "..") == 0))
			continue;
		if(unlink(dp->d_name) < 0)
			EM_ERROR(EGENScratchDirInaccessible, pathName, NULL);
		}
    closedir(dirp);
	chdir("/tmp");
	if(rmdir(pathName) < 0)
		EM_ERROR(EGENScratchDirInaccessible, pathName, NULL);

}

- (void)_makeDirectory:(const char *)pathName;
{
	int			ret;

	if((ret = mkdir(pathName, 0700)) < 0)
		{
		if(ret == EEXIST)
			{
			[self _removeDirectory:pathName];
			if((ret = mkdir(pathName, 0700)) < 0)
				EM_ERROR(EGENTempDirInaccessible, strerror(errno), NULL);
			}
		else 
			{
			EM_ERROR(EGENTempDirInaccessible, strerror(errno), NULL);
			}
		}
}

- (const char *)scratchDirectoryName;
{
	static char buffer[100];
	
	struct stat		_stat;
	
	sprintf(buffer, "/tmp/Alexandra%06d", getpid());
	if ((stat(buffer, &_stat)) == -1)
	{
		NXLogError("making scratch directory `%s'\n", buffer);
		[self _makeDirectory:buffer];
	}
	
	return buffer;
}

- makeScratchDirectory;
{
	const char	*sdir;

	sdir = [self scratchDirectoryName];
	NXLogError("making scratch directory `%s'\n", sdir);
	[self _makeDirectory:sdir];
	
	return self;
}


- removeScratchDirectory;
{
	const char		*sdir;

	NXLogError("removing scratch directory `%s'\n", sdir);
	sdir = [self scratchDirectoryName];
	[self _removeDirectory:sdir];
	
	return self;
}


//-----------------------------------------------------------
//	AUTORELEASE POOL MANAGEMENT
//-----------------------------------------------------------
#if 1
- (void)_setupAutoreleasePool
{
    autoreleasePool = [[NSAutoreleasePool alloc] init];    
    disableCount = 0;
}


/*
 *  Release the current pool, and create a new one.
 */
- (void)_releasePool
{
	if(disableCount<= 0) {
		[autoreleasePool release];
		autoreleasePool = [[NSAutoreleasePool alloc] init];
	}
}



+ new
{
    id poolApplication;

    poolApplication = [super new];

    [poolApplication _setupAutoreleasePool];

    return poolApplication;
}


/*
 *  Release the current pool before and after every event.
 */
- sendEvent:(NXEvent *)event
{
	[self _releasePool];

	disableCount += 1;
	[super sendEvent:event];
	disableCount -= 1;
	[self _releasePool];

	return self;
}


/*
 *  Need to disable the autorelease pool during modal loops otherwise
 *  objects that are involved in the modal loop will be freed prematurely.
 *  We need to have a "disable count" rather than a boolean flag because
 *  we can have nested modal sessions.
 */
- (int)runModalSession:(NXModalSession *)session
{
	int retVal;

	disableCount++;
	retVal = [super runModalSession:session];
	disableCount--;

	return retVal;
}

- (int)runModalFor:theWindow
{
	int retVal;

	disableCount++;
	retVal = [super runModalFor:theWindow];
	disableCount--;

	return retVal;
}


- (NXEvent *)getNextEvent:(int)mask
{
	NXEvent *event;

//	fprintf(stderr, "[Application getNextEvent:] in\n");
	event = [super getNextEvent:mask];
//	fprintf(stderr, "[Application getNextEvent:] out\n");
	
	return event;
}

#endif
//-----------------------------------------------------------
// THAT'S IT
//-----------------------------------------------------------

@end

	

