//=============================================================================
//
//		Copyright (C) 1995-1997 by Paul S. McCarthy and Eric Sunshine.
//				Written by Paul S. McCarthy and Eric Sunshine.
//							All Rights Reserved.
//
//		This notice may not be removed from this source code.
//
//		This object is included in the MiscKit by permission from the authors
//		and its use is governed by the MiscKit license, found in the file
//		"License.rtf" in the MiscKit disibution.  Please refer to that file
//		for a list of all applicable permissions and resictions.
//
//=============================================================================
//-----------------------------------------------------------------------------
// Defaults.m
//
//		Simplified interface to NeXT defaults system.
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// $Id: Defaults.m,v 1.2 97/02/05 08:13:09 sunshine Exp $
// $Log:		Defaults.m,v $
// Revision 1.2	 97/02/05  08:13:09	 sunshine
// v29: Reordered headers to be in syn with LazyScrollDir.	Fixed whitespace.
// 
// Revision 1.1	 97/01/12  15:20:24	 sunshine
// v28: Defaults manager.
//-----------------------------------------------------------------------------
#import "Defaults.h"
#import <appkit/Application.h>
#import <appkit/Font.h>
#import <defaults/defaults.h>
#import <assert.h>
#import <ctype.h>
#import <limits.h>
#import <string.h>


//-----------------------------------------------------------------------------
// moduleName
//-----------------------------------------------------------------------------
static inline char const* moduleName( void )
	{
	static char const* name = 0;
	if (name == 0)
		name = [NXApp appName];
	return name;
	}



//=============================================================================
// IMPLEMENTATION
//=============================================================================
@implementation Defaults

//-----------------------------------------------------------------------------
// set:str:
//-----------------------------------------------------------------------------
+ (void)set:(char const*)def str:(char const*)s
	{
	assert( def != 0 );
	NXWriteDefault( moduleName(), def, s );
	}


//-----------------------------------------------------------------------------
// getStr:fallback:
//-----------------------------------------------------------------------------
+ (char const*)getStr:(char const*)def fallback:(char const*)fallback
	{
	char const* s;
	assert( def != 0 );
	s = NXGetDefaultValue( moduleName(), def );
	if (s == 0)
		s = fallback;
	return s;
	}


//-----------------------------------------------------------------------------
// set:int:
//-----------------------------------------------------------------------------
+ (void)set:(char const*)def int:(int)i
	{
	char buf[ 32 ];
	sprintf( buf, "%d", i );
	assert( def != 0 );
	NXWriteDefault( moduleName(), def, buf );
	}


//-----------------------------------------------------------------------------
// getInt:fallback:
//-----------------------------------------------------------------------------
+ (int)getInt:(char const*)def fallback:(int)fallback
	{
	int value = fallback;
	char const* s;
	assert( def != 0 );

	if ((s = NXGetDefaultValue( moduleName(), def )) != 0)
		{
		int x;
		if (sscanf( s, "%d", &x ) == 1)
			value = x;
		else
			fprintf( stderr, "%s/%s has a bad integer default value (%s)\n",
								moduleName(), def, s );
		}
	return value;
	}


//-----------------------------------------------------------------------------
// getInt:fallback:min:max:
//-----------------------------------------------------------------------------
+ (int)getInt:(char const*)def fallback:(int)f min:(int)imin max:(int)imax
	{
	int ret;
	assert( imin <= imax );
	ret = [self getInt:def fallback:f];
	if (ret < imin)
		ret = imin;
	else if (ret > imax)
		ret = imax;
	return ret;
	}


//-----------------------------------------------------------------------------
// getInt:fallback:min:
//-----------------------------------------------------------------------------
+ (int)getInt:(char const*)def fallback:(int)fallback min:(int)imin
	{
	return [self getInt:def fallback:fallback min:imin max:INT_MAX];
	}


//-----------------------------------------------------------------------------
// set:float:
//-----------------------------------------------------------------------------
+ (void)set:(char const*)def float:(float)f
	{
	char buf[ 32 ];
	sprintf( buf, "%g", f );
	assert( def != 0 );
	NXWriteDefault( moduleName(), def, buf );
	}


//-----------------------------------------------------------------------------
// getFloat:fallback:
//-----------------------------------------------------------------------------
+ (float)getFloat:(char const*)def fallback:(float)fallback
	{
	float value = fallback;
	char const* s;
	assert( def != 0 );

	if ((s = NXGetDefaultValue( moduleName(), def )) != 0)
		{
		float x;
		if (sscanf( s, "%f", &x ) == 1)
			value = x;
		else
			fprintf( stderr, "%s/%s has a bad float default value (%s)\n",
								moduleName(), def, s );
		}
	return value;
	}


//-----------------------------------------------------------------------------
// set:color:
//-----------------------------------------------------------------------------
+ (void)set:(char const*)def color:(NXColor)c
	{
	char buf[ 64 ];
	sprintf( buf, "%g %g %g",
				NXRedComponent(c), NXGreenComponent(c), NXBlueComponent(c) );
	assert( def != 0 );
	NXWriteDefault( moduleName(), def, buf );
	}


//-----------------------------------------------------------------------------
// getColor:fallback:
//-----------------------------------------------------------------------------
+ (NXColor)getColor:(char const*)def fallback:(NXColor)fallback
	{
	NXColor color = fallback;
	char const* s;
	assert( def != 0 );

	if ((s = NXGetDefaultValue( moduleName(), def )) != 0)
		{
		float r,g,b;
		if (sscanf( s, "%f %f %f", &r, &g, &b ) == 3)
			color = NXConvertRGBToColor( r, g, b );
		else
			fprintf( stderr, "%s/%s has a bad RGB default value (%s)\n",
								moduleName(), def, s );
		}
	return color;
	}


//-----------------------------------------------------------------------------
// set:bool:
//-----------------------------------------------------------------------------
+ (void)set:(char const*)def bool:(BOOL)b
	{
	assert( def != 0 );
	NXWriteDefault( moduleName(), def, (b ? "Yes" : "No") );
	}


//-----------------------------------------------------------------------------
// getBool:fallback:
//-----------------------------------------------------------------------------
+ (BOOL)getBool:(char const*)def fallback:(BOOL)fallback
	{
	BOOL flag = fallback;
	char const* s;
	assert( def != 0 );

	if ((s = NXGetDefaultValue( moduleName(), def )) != 0)
		{
		char c = toupper( *s );
		if ((c == 'Y') || (c == 'N'))
			flag = (c == 'Y');
		else
			fprintf( stderr, "%s/%s has a bad boolean default value (%s)\n",
								moduleName(), def, s );
		}
	return flag;
	}


//-----------------------------------------------------------------------------
// sizeParam -- caller must free returned value
//-----------------------------------------------------------------------------
static char* sizeParam( char const* def )
	{
	static char const SIZE_STR[] = "Size";
	char* p;
	assert( def != 0 );
	p = (char*)malloc( strlen(def) + sizeof(SIZE_STR) ); // include null
	strcat( strcpy( p, def ), SIZE_STR );
	return p;
	}


//-----------------------------------------------------------------------------
// set:font:
//-----------------------------------------------------------------------------
+ (void)set:(char const*)def font:(Font*)f
	{
	char* p;
	assert( f != 0 );
	assert( def != 0 );
	NXWriteDefault( moduleName(), def, [f name] );
	p = sizeParam( def );
	[self set:p float:[f pointSize]];
	free( p );
	}


//-----------------------------------------------------------------------------
// getFont:fallback:
//-----------------------------------------------------------------------------
+ (Font*)getFont:(char const*)def fallback:(Font*)fallback
	{
	Font* font = fallback;
	char const* name;
	assert( def != 0 );
	assert( fallback != 0 );

	if ((name = NXGetDefaultValue( moduleName(), def )) != 0)
		{
		Font* new_font;
		char* p = sizeParam( def );
		float const size = [self getFloat:p fallback:[fallback pointSize]];

		new_font = [Font newFont:name size:size];
		if (new_font != 0)
			font = new_font;
		else
			fprintf( stderr, "%s/%s has a bad font default value (%s)\n",
								moduleName(), def, p );
		free( p );
		}

	assert( font != 0 );
	return font;
	}


//-----------------------------------------------------------------------------
// set:size:
//-----------------------------------------------------------------------------
+ (void)set:(char const*)def size:(NXSize)s
	{
	char buf[ 64 ];
	sprintf( buf, "%g %g", s.width, s.height );
	assert( def != 0 );
	NXWriteDefault( moduleName(), def, buf );
	}


//-----------------------------------------------------------------------------
// getSize:fallback:
//-----------------------------------------------------------------------------
+ (NXSize)getSize:(char const*)def fallback:(NXSize)fallback
	{
	NXSize size = fallback;
	char const* s;
	assert( def != 0 );

	if ((s = NXGetDefaultValue( moduleName(), def )) != 0)
		{
		NXCoord w,h;
		if (sscanf( s, "%f %f", &w, &h ) == 2)
			{
			size.width = w;
			size.height = h;
			}
		else
			fprintf( stderr, "%s/%s has a bad size default value (%s)\n",
								moduleName(), def, s );
		}
	return size;
	}


//-----------------------------------------------------------------------------
// set:point:
//-----------------------------------------------------------------------------
+ (void)set:(char const*)def point:(NXPoint)p
	{
	char buf[ 64 ];
	sprintf( buf, "%g %g", p.x, p.y );
	assert( def != 0 );
	NXWriteDefault( moduleName(), def, buf );
	}


//-----------------------------------------------------------------------------
// getPoint:fallback:
//-----------------------------------------------------------------------------
+ (NXPoint)getPoint:(char const*)def fallback:(NXPoint)fallback
	{
	NXPoint point = fallback;
	char const* s;
	assert( def != 0 );

	if ((s = NXGetDefaultValue( moduleName(), def )) != 0)
		{
		NXCoord x,y;
		if (sscanf( s, "%f %f", &x, &y ) == 2)
			{
			point.x = x;
			point.y = y;
			}
		else
			fprintf( stderr, "%s/%s has a bad point default value (%s)\n",
								moduleName(), def, s );
		}
	return point;
	}


//-----------------------------------------------------------------------------
// set:rect:
//-----------------------------------------------------------------------------
+ (void)set:(char const*)def rect:(NXRect)r
	{
	char buf[ 128 ];
	sprintf( buf, "%g %g %g %g", r.origin.x, r.origin.y,
								 r.size.width, r.size.height );
	assert( def != 0 );
	NXWriteDefault( moduleName(), def, buf );
	}


//-----------------------------------------------------------------------------
// getRect:fallback:
//-----------------------------------------------------------------------------
+ (NXRect)getRect:(char const*)def fallback:(NXRect)fallback
	{
	NXRect rect = fallback;
	char const* s;
	assert( def != 0 );

	if ((s = NXGetDefaultValue( moduleName(), def )) != 0)
		{
		NXCoord x,y,w,h;
		if (sscanf( s, "%f %f %f %f", &x, &y, &w, &h ) == 4)
			{
			rect.origin.x = x;
			rect.origin.y = y;
			rect.size.width = w;
			rect.size.height = h;
			}
		else
			fprintf( stderr, "%s/%s has a bad rect default value (%s)\n",
								moduleName(), def, s );
		}
	return rect;
	}

@end
