/*
	Copyright (C) 1994 Sean Luke

	COWSIBControlInterface.m
	and COWSControlIB--a category for Controls
	and COWSCellIB--a category for Cells
	Version 1.0
	Sean Luke
	
*/




#import "COWSIBControlInterface.h"
#import "COWSLibraryNode.h"
#import <appkit/Control.h>
#import <appkit/Cell.h>
#import <stdlib.h>

#define COWSIBCONTROLINTERFACE_LARGEBUFFER	255

@implementation COWSIBControlInterface


- _prepareNodes
	{
	if (!output) output=[[COWSStringNode alloc] init];
	if (!default_input) default_input=[[COWSStringNode alloc] init];
	if (!input_1) input_1=[[COWSStringNode alloc] init];
	if (!input_2) input_2=[[COWSStringNode alloc] init];
	if (!input_3) input_3=[[COWSStringNode alloc] init];
	if (!input_4) input_4=[[COWSStringNode alloc] init];
	if (!input_5) input_5=[[COWSStringNode alloc] init];
	if (!input_6) input_6=[[COWSStringNode alloc] init];
	if (!input_7) input_7=[[COWSStringNode alloc] init];
	if (!input_8) input_8=[[COWSStringNode alloc] init];
	return self;
	}

- awake
	{
	[super awake];
	if (use_radio)
		if (COWS_RADIO) [COWS_RADIO add:self];	// connects to radio if no
												// interpreter and radio 
												// exists
	value=[[COWSStringNode alloc] init];
	[self _prepareNodes];
	inited=1;
	return self;
	}

- init
	{
	id returnval=[super init];
	printf("Initing\n");
	if (use_radio)
		if (COWS_RADIO) [COWS_RADIO add:self];	// connects to radio if no
												// interpreter and radio 
												// exists
	value=[[COWSStringNode alloc] init];
	[self _prepareNodes];
	inited=1;
	return returnval;
	}

- free
	{
	return [super free];
	}

- loadLibrary:sender
	{
	id returnval=[super loadLibrary:sender];
	
	if (![sender conformsTo:@protocol(LibraryControl)])
		{
		printf ("IBLibrary error:  Interpreter cannot accept Library Control protocol!\n");
		return NULL;
		}
		
	if (target&&output) [sender addLibraryFunction: [output string]
			selector: @selector(performOutput:)
			target: self];
	interpreter=sender;
			
	return returnval;
	}
	
- setTarget:anObject
	{
	target=anObject;
	return self;
	}

- setAction:(SEL)aSelector
	{
	action=aSelector;
	return self;
	}

- (SEL)action
	{
	return action;
	}

- target
	{
	return target;
	}

- _callInterpreter:sender:(BOOL)include_argument
	// calls interpreter based on sender,
	// passing value as argument if asked for
	{
	id arguments=[[COWSArgumentList alloc] init];
	id temp=[[COWSStringNode alloc] init];
	
	if (!interpreter) 
		{
		[arguments free];
		[temp free];
		return NULL;
		}
		
	if (include_argument) 
		{
		[temp copyValue:value];
		[arguments push:temp];
		}
	else [temp free];

	if (sender==input1)
		[interpreter interpretFunction:[input_1 string] 
			arguments:arguments];
	else if (sender==input2)
		[interpreter interpretFunction:[input_2 string] 
			arguments:arguments];
	else if (sender==input3)
		[interpreter interpretFunction:[input_3 string] 
			arguments:arguments];
	else if (sender==input4)
		[interpreter interpretFunction:[input_4 string] 
			arguments:arguments];
	else if (sender==input5)
		[interpreter interpretFunction:[input_5 string] 
			arguments:arguments];
	else if (sender==input6)
		[interpreter interpretFunction:[input_6 string] 
			arguments:arguments];
	else if (sender==input7)
		[interpreter interpretFunction:[input_7 string] 
			arguments:arguments];
	else if (sender==input8)
		[interpreter interpretFunction:[input_8 string] 
			arguments:arguments];
	else							// default
		{
		[interpreter interpretFunction:[default_input string]
			arguments:arguments];
		}
	[arguments free];
	return self;
	}

- takeDoubleValueFrom:sender
	{
	[value setDoubleVal:[sender doubleValue]];
	return [self _callInterpreter:sender:YES];
	}

- takeFloatValueFrom:sender
	{
	[value setFloatVal:[sender floatValue]];
	return [self _callInterpreter:sender:YES];
	}

- takeIntValueFrom:sender
	{
	[value setIntVal:[sender intValue]];
	return [self _callInterpreter:sender:YES];
	}

- takeStringValueFrom:sender
	{
	const char* x=[sender stringValue];
	if (x) [value setString:x];
	return [self _callInterpreter:sender:YES];
	}
	
- do:sender
	{
	return [self _callInterpreter:sender:NO];
	}

- (const char*) stringValue
	{
	printf ("%s\n",[value string]);
	return [value string];
	}

- (int) intValue
	{
	return [value intVal];
	}

- (float) floatValue
	{
	return [value floatVal];
	}

- (double) doubleValue
	{
	return [value doubleVal];
	}

- setStringValue:(const char*) this
	{
	[value setString:this];
	return self;
	}
	
- setFloatValue:(float) this
	{
	[value setFloatVal:this];
	return self;
	}

- setIntValue:(int) this
	{
	[value setIntVal:this];
	return self;
	}

- setDoubleValue:(double) this
	{
	[value setDoubleVal:this];
	return self;
	}

- performOutput:(COWSArgumentList*)arg_list
	{
	id temp=[[COWSStringNode alloc] init];
	if ([arg_list top]) [value copyValue:[arg_list top]];
	[target perform:action with:self];
	[temp copyValue:value];
	return temp;
	}
	
- read:(NXTypedStream*) stream
	{
	char* o1;
	char* o2;
	char* o3;
	char* o4;
	char* o5;
	char* o6;
	char* o7;
	char* o8;
	char* o9;
	char* o10;
	
	[self _prepareNodes];
	[super read:stream];
	NXReadTypes(stream,"c**********",
		&use_radio,&o1,&o2,&o3,&o4,&o5,&o6,&o7,&o8,&o9,&o10);
	[input_1 setString:o1];
	[input_2 setString:o2];
	[input_3 setString:o3];
	[input_4 setString:o4];
	[input_5 setString:o5];
	[input_6 setString:o6];
	[input_7 setString:o7];
	[input_8 setString:o8];
	[default_input setString:o9];
	[output setString:o10];
	
	if (o1) free(o1);
	if (o2) free(o2);
	if (o3) free(o3);
	if (o4) free(o4);
	if (o5) free(o5);
	if (o6) free(o6);
	if (o7) free(o7);
	if (o8) free(o8);
	if (o9) free(o9);
	if (o10) free(o10);
	
	return self;
	}
	
- write:(NXTypedStream*) stream
	{
	const char* o1;
	const char* o2;
	const char* o3;
	const char* o4;
	const char* o5;
	const char* o6;
	const char* o7;
	const char* o8;
	const char* o9;
	const char* o10;
	
	[self _prepareNodes];
	[super write:stream];

	o1=[input_1 string];
	o2=[input_2 string];
	o3=[input_3 string];
	o4=[input_4 string];
	o5=[input_5 string];
	o6=[input_6 string];
	o7=[input_7 string];
	o8=[input_8 string];
	o9=[default_input string];
	o10=[output string];

	NXWriteTypes(stream,"c**********",
		&use_radio,&o1,&o2,&o3,&o4,&o5,&o6,&o7,&o8,&o9,&o10);
	return self;
	}

@end

@implementation Object (COWSObjectIB)			// defaults which are changed

- returnIntValue:sender
	{
	return self;
	}
	
- returnFloatValue:sender
	{
	return self;
	}

- returnStringValue:sender
	{
	return self;
	}

- returnDoubleValue:sender
	{
	return self;
	}


@end


@implementation Cell (COWSCellIB)

- returnIntValue:sender
	{
	if ([sender respondsTo:@selector(setIntValue:)])
		return [sender setIntValue:[self intValue]];
	return NULL;
	}
	
- returnFloatValue:sender
	{
	if ([sender respondsTo:@selector(setFloatValue:)])
		return [sender setFloatValue:[self floatValue]];
	return NULL;
	}

- returnStringValue:sender
	{
	if ([sender respondsTo:@selector(setStringValue:)])
		return [sender setStringValue:[self stringValue]];
	return NULL;
	}

- returnDoubleValue:sender
	{
	if ([sender respondsTo:@selector(setDoubleValue:)])
		return [sender setDoubleValue:[self doubleValue]];
	return NULL;
	}


@end


@implementation Control (COWSControlIB)

- returnIntValue:sender
	{
	if ([sender respondsTo:@selector(setIntValue:)])
		return [sender setIntValue:[self intValue]];
	return NULL;
	}
	
- returnFloatValue:sender
	{
	if ([sender respondsTo:@selector(setFloatValue:)])
		return [sender setFloatValue:[self floatValue]];
	return NULL;
	}

- returnStringValue:sender
	{
	if ([sender respondsTo:@selector(setStringValue:)])
		return [sender setStringValue:[self stringValue]];
	return NULL;
	}

- returnDoubleValue:sender
	{
	if ([sender respondsTo:@selector(setDoubleValue:)])
		return [sender setDoubleValue:[self doubleValue]];
	return NULL;
	}


@end
