// MORegexPalette.m
//
// by Mike Ferris
// Part of MOKit - MORegexPalette
// Copyright 1993, all rights reserved.

#import "MORegexPalette.h"
#import "MOKit/MORegexFormCell.h"
#import "MOKit/MORegexTextCell.h"
#import <appkit/appkit.h>
#import <objc/objc-runtime.h>

#define CLASS_VERSION	0

#define BUNDLE_TYPE							"bundle"

#define MOSTRING_CLASS_NAME					"MOString"
#define MOREGEXFORMCELL_CLASS_NAME			"MORegexFormCell"
#define MOREGEXTEXTCELL_CLASS_NAME			"MORegexTextCell"
#define MODATEFORMCELL_CLASS_NAME			"MODateFormCell"
#define MODATETEXTCELL_CLASS_NAME			"MODateTextCell"


#define FORM_GENERIC_NAME					"Generic:"
#define FORM_INT_NAME						"Integer:"
#define FORM_FLOAT_NAME						"Float:"
#define FORM_TIME_NAME						"Time:"
#define FORM_DATE_NAME						"Date:"

#define INT_REGEX		"^[ ]*([+-]?[0-9]+)[ ]*$"

#define FLOAT_REGEX		"^[ ]*(([+-]?[0-9]*).?([0-9]*)[eE]?([0-9]*))[ ]*$"

#define TIME_REGEX_1	"^[ ]*(([0]?[0-9]|[1][0-2]):([0-5][0-9])[ ]*([aA][mM]?|[pP][mM]?))[ ]*$"
#define TIME_REGEX_2	"^[ ]*(([0]?[0-9]|[1][0-9]|[2][0-3]):([0-5][0-9])())[ ]*$"


@implementation  MORegexPalette

static id MOStringClass;
static id MORegexFormCellClass;
static id MORegexTextCellClass;
static id MODateFormCellClass;
static id MODateTextCellClass;

+ MO_loadClassBundle:(const char *)className
// Finds the bundle of the same name as the class, grabs it and loads the
// class from it.
{
	char pathBuff[MAXPATHLEN+1];
	
	// Load the bundle
	if (objc_lookUpClass(className) == nil)  {
		// class is not already loaded... load it.
		id classBundle;
		
		// Look for the bundle in the main bundle first, 
		// else try in this classes bundle.
		if (![[NXBundle mainBundle] getPath:pathBuff forResource:className 
					ofType:BUNDLE_TYPE])  {
			if (![[NXBundle bundleForClass:[self class]] getPath:pathBuff 
						forResource:className ofType:BUNDLE_TYPE])  {
				NXLogError("[MORegexPalette loadClassBundle] failed to "
						"find %s class bundle.", className);
				return nil;
			}
		}
		classBundle = [[NXBundle allocFromZone:[self zone]] 
					initForDirectory:pathBuff];
		if (!classBundle)  {
			NXLogError("[MORegexPalette loadClassBundle] failed to "
						"create bundle for class %s.", className);
			return nil;
		}
		if (![classBundle classNamed:className])  {
			NXLogError("[MORegexPalette loadClassBundle] failed to "
						"load %s class from bundle.", className);
			return nil;
		}
	}
	
	return self;
}

+ initialize
// Set the version.
{
	if (self == [MORegexPalette class])  {
		[self setVersion:CLASS_VERSION];

		// Load the MOString class if necessary
		[self MO_loadClassBundle:MOSTRING_CLASS_NAME];
		MOStringClass = 
					objc_lookUpClass(MOSTRING_CLASS_NAME);
		if (!MOStringClass)  {
			NXLogError("[MORegexPalette initialize]: failed to find "
						"MOString class.");
		}
		// Load the MORegexFormCell class if necessary
		[self MO_loadClassBundle:MOREGEXFORMCELL_CLASS_NAME];
		MORegexFormCellClass = 
					objc_lookUpClass(MOREGEXFORMCELL_CLASS_NAME);
		if (!MORegexFormCellClass)  {
			NXLogError("[MORegexPalette initialize]: failed to find "
						"MORegexFormCell class.");
		}
		// Load the MORegexTextCell class if necessary
		[self MO_loadClassBundle:MOREGEXTEXTCELL_CLASS_NAME];
		MORegexTextCellClass = 
					objc_lookUpClass(MOREGEXTEXTCELL_CLASS_NAME);
		if (!MORegexTextCellClass)  {
			NXLogError("[MORegexPalette initialize]: failed to find "
						"MORegexTextCell class.");
		}
		// Load the MODateFormCell class if necessary
		[self MO_loadClassBundle:MODATEFORMCELL_CLASS_NAME];
		MODateFormCellClass = 
					objc_lookUpClass(MODATEFORMCELL_CLASS_NAME);
		if (!MODateFormCellClass)  {
			NXLogError("[MORegexPalette initialize]: failed to find "
						"MODateFormCell class.");
		}
		// Load the MODateTextCell class if necessary
		[self MO_loadClassBundle:MODATETEXTCELL_CLASS_NAME];
		MODateTextCellClass = 
					objc_lookUpClass(MODATETEXTCELL_CLASS_NAME);
		if (!MODateTextCellClass)  {
			NXLogError("[MORegexPalette initialize]: failed to find "
						"MODateTextCell class.");
		}
	}
	return self;
}

- finishInstantiate
// First load up the class bundles, one for each included class.
// Then set up all the palette controls.
{
	id protoCell;
	NXSize size;
		
	// Set up the generic MORegexFormCell
	protoCell = [[MORegexFormCellClass allocFromZone:[self zone]] 
						initTextCell:NULL];
	[genericForm setPrototype:protoCell];
	[genericForm addEntry:FORM_GENERIC_NAME];
	[genericForm sizeToFit];

	// Set up the integer MORegexFormCell
	protoCell = [[MORegexFormCellClass allocFromZone:[self zone]] 
						initTextCell:NULL];
	[protoCell addRegexStr:INT_REGEX];
	[intForm setPrototype:protoCell];
	[intForm addEntry:FORM_INT_NAME];
	[intForm sizeToFit];

	// Set up the float MORegexFormCell
	protoCell = [[MORegexFormCellClass allocFromZone:[self zone]] 
						initTextCell:NULL];
	[protoCell addRegexStr:FLOAT_REGEX];
	[floatForm setPrototype:protoCell];
	[floatForm addEntry:FORM_FLOAT_NAME];
	[floatForm sizeToFit];

	// Set up the time MORegexFormCell
	protoCell = [[MORegexFormCellClass allocFromZone:[self zone]] 
						initTextCell:NULL];
	[protoCell addRegexStr:TIME_REGEX_1];
	[protoCell addRegexStr:TIME_REGEX_2];
	[timeForm setPrototype:protoCell];
	[timeForm addEntry:FORM_TIME_NAME];
	[timeForm sizeToFit];

	// Set up the date MODateFormCell
	protoCell = [[MODateFormCellClass allocFromZone:[self zone]] 
						initTextCell:NULL];
	[dateForm setPrototype:protoCell];
	[dateForm addEntry:FORM_DATE_NAME];
	[dateForm sizeToFit];

	// Set up the generic MORegexTextCell
	protoCell = [[MORegexTextCellClass allocFromZone:[self zone]] 
						initTextCell:NULL];
	[protoCell setBezeled:YES];
	[protoCell setBackgroundGray:NX_WHITE];
	[protoCell setTextGray:NX_BLACK];
	[protoCell setEditable:YES];
	[genericMatrix setPrototype:protoCell];
	size.width = 100; size.height = 21;
	[genericMatrix setCellSize:&size];
	size.width = 4; size.height = 4;
	[genericMatrix setIntercell:&size];
	[genericMatrix renewRows:1 cols:1];
	[genericMatrix sizeToCells];
	
	// Set up the integer MORegexTextCell
	protoCell = [[MORegexTextCellClass allocFromZone:[self zone]] 
						initTextCell:NULL];
	[protoCell setBezeled:YES];
	[protoCell setBackgroundGray:NX_WHITE];
	[protoCell setTextGray:NX_BLACK];
	[protoCell setEditable:YES];
	[protoCell addRegexStr:INT_REGEX];
	[intMatrix setPrototype:protoCell];
	size.width = 100; size.height = 21;
	[intMatrix setCellSize:&size];
	size.width = 4; size.height = 4;
	[intMatrix setIntercell:&size];
	[intMatrix renewRows:1 cols:1];
	[intMatrix sizeToCells];
	
	// Set up the float MORegexTextCell
	protoCell = [[MORegexTextCellClass allocFromZone:[self zone]] 
						initTextCell:NULL];
	[protoCell setBezeled:YES];
	[protoCell setBackgroundGray:NX_WHITE];
	[protoCell setTextGray:NX_BLACK];
	[protoCell setEditable:YES];
	[protoCell addRegexStr:FLOAT_REGEX];
	[floatMatrix setPrototype:protoCell];
	size.width = 100; size.height = 21;
	[floatMatrix setCellSize:&size];
	size.width = 4; size.height = 4;
	[floatMatrix setIntercell:&size];
	[floatMatrix renewRows:1 cols:1];
	[floatMatrix sizeToCells];
	
	// Set up the time MORegexTextCell
	protoCell = [[MORegexTextCellClass allocFromZone:[self zone]] 
						initTextCell:NULL];
	[protoCell setBezeled:YES];
	[protoCell setBackgroundGray:NX_WHITE];
	[protoCell setTextGray:NX_BLACK];
	[protoCell setEditable:YES];
	[protoCell addRegexStr:TIME_REGEX_1];
	[protoCell addRegexStr:TIME_REGEX_2];
	[timeMatrix setPrototype:protoCell];
	size.width = 100; size.height = 21;
	[timeMatrix setCellSize:&size];
	size.width = 4; size.height = 4;
	[timeMatrix setIntercell:&size];
	[timeMatrix renewRows:1 cols:1];
	[timeMatrix sizeToCells];
	
	// Set up the time MORegexTextCell
	protoCell = [[MODateTextCellClass allocFromZone:[self zone]] 
						initTextCell:NULL];
	[protoCell setBezeled:YES];
	[protoCell setBackgroundGray:NX_WHITE];
	[protoCell setTextGray:NX_BLACK];
	[protoCell setEditable:YES];
	[dateMatrix setPrototype:protoCell];
	size.width = 100; size.height = 21;
	[dateMatrix setCellSize:&size];
	size.width = 4; size.height = 4;
	[dateMatrix setIntercell:&size];
	[dateMatrix renewRows:1 cols:1];
	[dateMatrix sizeToCells];
	
	return self;
}

@end
