/* Copyright (c) 1990, 1992, Scott Hess.  No rights reserved.  No
 * warranty is provided for this software, neither explicit nor
 * implied.  The source and object code for this file may be used
 * and modified as the user sees fit.
 */
#import "StuartSpeaker.h"
#import <appkit/Listener.h>
#import <libc.h>
#import <math.h>
#import <stdio.h>
#import <strings.h>

extern id NXResponsibleDelegate();

@implementation  StuartSpeaker
- init
{
    self=[super init];
    if( self) {
	defaults=[[NXStringTable allocFromZone:[self zone]] init];
    }
    return self;
}
- free
{
    /* Since I was storing static strings in defaults, I don't want
     * them to be freed by the NXStringTable code.
     */
    [defaults empty];
    defaults=[defaults free];
    return [super free];
}
-(int)_stuartNew:(char *)defs activate:(int)flag
{
    return [self selectorRPC:"_stuartNew:activate:" paramTypes:"ci", defs, flag];
}
-(int)_stuartGet:(char **)defs
{
    return [self selectorRPC:"_stuartGet:" paramTypes:"C", defs];
}
static const char *sValue;		// a temp variable.
static char buffer[ 1024];
const char *itoa( int i)
{
    sprintf( buffer, "%d", i);
    return buffer;
}
const char *ftoa( float f)
{
    sprintf( buffer, "%f", f);
    return buffer;
}
const char *btoa( BOOL b)
{
    sprintf( buffer, "%s", b ? "YES" : "NO");
    return buffer;
}
BOOL atob( const char *s)
{
    if( !s) {
	return NO;
    } else if( !*s) {
	return YES;
    } else if( !strcmp( s, "YES")) {
	return YES;
    } else {
	return atoi( s)!=0;
    }
}
-(const char *)default:(const char *)name
{
    return [defaults valueForStringKey:name];
}
-(int)defaultAsInt:(const char *)name
{
    return (sValue=[self default:name]) ? atoi( sValue) : 0;
}
-(float)defaultAsFloat:(const char *)name
{
    return (sValue=[self default:name]) ? atof( sValue) : NAN;
}
-(BOOL)defaultAsBOOL:(const char *)name
{
    return (sValue=[self default:name]) ? atob( sValue) : NO;
}
- default:(const char *)name as:(const char *)value
{
    return [defaults insertKey:(void *)name value:(void *)value];
}
- default:(const char *)name asInt:(int)value
{
    return [self default:name as:itoa( value)];
}
- default:(const char *)name asFloat:(float)value
{
    return [self default:name as:ftoa( value)];
}
- default:(const char *)name asBOOL:(BOOL)value
{
    return [self default:name as:btoa( value)];
}
- removeDefault:(const char *)name
{
    [defaults removeKey:(void *)name];
    return self;
}

-(int)stuartNew
{
    int i=-1;
    NXStream *aStream=NXOpenMemory( NULL, 0, NX_WRITEONLY);
    if( aStream) {
	char *data;
	int len, maxLen;
	BOOL activate=[self defaultAsBOOL:"Activate"];
	[self removeDefault:"Activate"];
	if( [self defaultAsBOOL:"Reverse"]) {
	    if( [self defaultAsBOOL:"ReverseBlack"]) {
		[self default:"BackgroundColor" as:"0 0 0"];
		[self default:"ForegroundColor" as:"1 1 1"];
	    } else {
		[self default:"BackgroundColor" as:"0.666 0.666 0.666"];
	    }
	}
	[defaults writeToStream:aStream];
	NXPutc( aStream, '\0');
	NXGetMemoryBuffer( aStream, &data, &len, &maxLen);
	i=[self _stuartNew:data activate:activate];
	NXCloseMemory( aStream, NX_FREEBUFFER);
    }
    return i;
}
-(int)stuartGet
{
    NXStream *aStream;
    int i, len;
    char *defs;
    i=[self _stuartGet:&defs];
    if( i) {
	return i;
    }
    len=strlen( defs);
    aStream=NXOpenMemory( defs, len, NX_READONLY);
    if( aStream) {
	[defaults readFromStream:aStream];
	NXCloseMemory( aStream, NX_FREEBUFFER);
    }
    return 0;
}
-(int)stuartSend:(int)fd
{
    int ret=0;
    NXStream *aStream=NXOpenFile( fd, NX_READONLY);
    if( aStream) {
	[defaults readFromStream:aStream];
	ret=[self stuartNew];
	NXClose( aStream);
    }
    return ret;
}
-(int)stuartConnectAndNew
{
    int ret=-1;
    port_t stuartPort=NXPortFromName( "Stuart", [self default:"NXHost"]);
    [self removeDefault:"NXHost"];
    if( stuartPort!=PORT_NULL) {
	[self setSendPort:stuartPort];
	ret=[self stuartNew];
    } else {
	fprintf( stderr, "Stuart not running\n");
    }
    return ret;
}
-(int)stuartConnectAndGet
{
    int ret=-1;
    port_t stuartPort=NXPortFromName( "Stuart", [self default:"NXHost"]);
    [self removeDefault:"NXHost"];
    if( stuartPort!=PORT_NULL) {
	[self setSendPort:stuartPort];
	ret=[self stuartGet];
    } else {
	fprintf( stderr, "Stuart not running\n");
    }
    return ret;
}
-(int)stuartConnectAndSend:(int)fd
{
    int ret=-1;
    port_t stuartPort=NXPortFromName( "Stuart", [self default:"NXHost"]);
    [self removeDefault:"NXHost"];
    if( stuartPort!=PORT_NULL) {
	[self setSendPort:stuartPort];
	ret=[self stuartSend:fd];
    } else {
	fprintf( stderr, "Stuart not running\n");
    }
    return ret;
}
@end
