/*
 * KW: the definition for a single configuration variable in a
 * Karray.
 *
 * Copyright (c) 1996 David L Parsons
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by David L Parsons (orc@pell.chi.il.us).  My name may not be used
 * to endorse or promote products derived from this software without
 * specific prior written permission.  THIS SOFTWARE IS PROVIDED
 * ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
 * WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * functions provided:
 *
 *	KW(char*)		initialize, assigning value.
 *	KW()			initialize, no value.
 *	KW(int)			initialize, make invalid.
 *	~KW()			goodbye, cruel world.
 *	-- NO COPY CONSTRUCTOR --
 *	changed()		has this KW been modified?
 *	(char*)			value of the KW
 *	value()			value of the KW
 *	reset()			reset the KW to initial conditions
 *	operator =(char*)	assign a value to this KW
 *	operator =(KW&)		copy the value of another KW to this one
 *	operator +=(char*)	append to this KW's value
 *	operator +=(KW*)	append another KW to this KW's value
 *
 *	print(FILE*)		print a dump of the KW to a FILE*
 *
 *	True()			is this ON/TRUE/YES/1 ?
 *	False()			is this OFF/NO/FALSE/0 ?
 */
#ifndef _KW_D
#define _KW_D

extern "C" {
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
}
#include <string.h>

class KW {
private:
    char *_value;
    char *_orig;
    int   _different;
    int   _valid;
public:
    inline KW(char *value) {
			    _valid = 1;
			    if (value) {
				_orig = strdup(value);
				_value = strdup(value);
			    }
			    else
				_orig = _value = (char*)0;
			    _different = 0;
			}
    inline KW() { _orig = _value = (char*)0; _different = 0; _valid = 1; }
    inline KW(int ick) { _orig = _value = (char*)0;
			 _different = _valid = 0;
			 ick = !ick; }

    inline ~KW()	{   if (_value)
				free(_value);
			    if (_orig)
				free(_orig);
		        }

    inline char *value() { return _value; }
    operator char*()	{ return _value; }
    inline int changed() { return _different; }
    inline int changed(int val) { return _different = val; }
    inline int valid()  { return _valid; }

    void reset()	{   if (valid()) {
				if (_value)
				    free(_value);
				if (_orig)
				    _value = strdup(_orig);
				else
				    _value = _orig;
				_different = 0;
			    }
			}

    /* STRING ASSIGNMENT */
    KW& operator =(char *rhs) {
			    if (!valid())
				return *this;
			    if (_value)
				free(_value);
			    if (rhs) {
				_value = strdup(rhs);
				_different = (_orig == (char*)0)
					      || strcmp(_value, _orig);
			    }
			    else {
				_value = 0;
				_different = (_orig != (char*)0);
			    }
			    return *this;
			}
    KW& operator +=(char *rhs) {
			    if (!(valid() && rhs))
				return *this;

			    if (! _value)
				_value = strdup(rhs);
			    else {
				_value = (char*)realloc((void*)_value,
						         strlen(_value)
						         + strlen(rhs) + 1);
				strcat(_value, rhs);
			    }
			    _different = (_orig == (char*)0)
					    || strcmp(_value, _orig);
			    return *this;
			}

    /* COPY OPERATORS */
    inline KW& operator =(KW &rhs) {
			    return valid() ? (*this = rhs.value()) : (*this);
			}
    inline KW& operator +=(KW &rhs) {
			    return valid() ? (*this += rhs.value()) : (*this);
			}
    inline KW& operator =(int rhs) {
			    assert(rhs == 0);
			    return valid() ? (*this = (char*)0) : (*this);
			}
    inline KW& operator +=(int rhs) {
			    assert(rhs == 0);
			    return valid() ? (*this += (char*)0) : (*this);
			}

    inline int print(FILE *out = stdout) {
			    if (!valid())
				fprintf(out, "invalid\n");
			    else if (value())
				fprintf(out, "value is (%s), changed is %d\n",
						value(), changed());
			    else
				fprintf(out, "changed is %d\n", changed());
			    return ferror(out);
			}

    int True() {
	char *p;
	return (valid() && (p=value()) && (strcasecmp(p, "yes") == 0
					       || strcasecmp(p, "on") == 0
					       || strcasecmp(p, "True") == 0));
    }

    int False() {
	char *p;
	return (valid() && (p=value()) && (strcasecmp(p, "False") == 0
						 || strcasecmp(p, "off") == 0
					         || strcasecmp(p, "no") == 0));
    }
};

#endif/*_KW_D*/
