btmux/autom4te.cache/
btmux/doc/.svn/
btmux/event/.svn/
btmux/game/.svn/
btmux/game/bin/.svn/
btmux/game/data/.svn/
btmux/game/logs/.svn/
btmux/game/maps/
btmux/game/maps/.svn/
btmux/game/maps/.svn/prop-base/
btmux/game/maps/.svn/props/
btmux/game/maps/.svn/text-base/
btmux/game/maps/.svn/wcprops/
btmux/game/mechs/
btmux/game/mechs/.svn/
btmux/game/mechs/.svn/prop-base/
btmux/game/mechs/.svn/props/
btmux/game/mechs/.svn/text-base/
btmux/game/mechs/.svn/wcprops/
btmux/game/text/.svn/
btmux/include/.svn/
btmux/misc/
btmux/misc/.svn/
btmux/misc/.svn/prop-base/
btmux/misc/.svn/props/
btmux/misc/.svn/text-base/
btmux/misc/.svn/wcprops/
btmux/python/
btmux/python/.svn/
btmux/python/.svn/prop-base/
btmux/python/.svn/props/
btmux/python/.svn/text-base/
btmux/python/.svn/wcprops/
btmux/src/.svn/prop-base/
btmux/src/.svn/props/
btmux/src/.svn/text-base/
btmux/src/.svn/wcprops/
btmux/src/hcode/.svn/
btmux/src/hcode/btech/
btmux/src/hcode/btech/.svn/
btmux/src/hcode/btech/.svn/prop-base/
btmux/src/hcode/btech/.svn/props/
btmux/src/hcode/btech/.svn/text-base/
btmux/src/hcode/btech/.svn/wcprops/
btmux/src/hcode/include/.svn/
/*
 * vattr.c -- Manages the user-defined attributes. 
 */

/*
 * $Id: vattr.c,v 1.4 2005/08/08 09:43:07 murrayma Exp $ 
 */

#include "copyright.h"
#include "config.h"

#include "copyright.h"
#include "mudconf.h"
#include "vattr.h"
#include "alloc.h"
#include "htab.h"
#include "externs.h"

static void fixcase(char *);
static char *store_string(char *);

/*
 * Allocate space for strings in lumps this big. 
 */

#define STRINGBLOCK 1000

/*
 * Current block we're putting stuff in 
 */

static char *stringblock = (char *) 0;

/*
 * High water mark. 
 */

static int stringblock_hwm = 0;

void vattr_init(void)
{
    hashinit(&mudstate.vattr_name_htab, 256 * HASH_FACTOR);
}

VATTR *vattr_find(name)
char *name;
{
    register VATTR *vp;

    if (!ok_attr_name(name))
	return (NULL);

    vp = (VATTR *) hashfind(name, &mudstate.vattr_name_htab);

    /*
     * vp is NULL or the right thing. It's right, either way. 
     */
    return (vp);
}

VATTR *vattr_alloc(name, flags)
char *name;
int flags;
{
    int number;

    if (((number = mudstate.attr_next++) & 0x7f) == 0)
	number = mudstate.attr_next++;
    anum_extend(number);
    return (vattr_define(name, number, flags));
}

VATTR *vattr_define(name, number, flags)
char *name;
int number, flags;
{
    VATTR *vp;

    /*
     * Be ruthless. 
     */

    if (strlen(name) > VNAME_SIZE)
	name[VNAME_SIZE - 1] = '\0';

    fixcase(name);
    if (!ok_attr_name(name))
	return (NULL);

    if ((vp = vattr_find(name)) != NULL)
	return (vp);

    vp = (VATTR *) malloc(sizeof(VATTR));

    vp->name = store_string(name);
    vp->flags = flags;
    vp->number = number;

    hashadd(vp->name, (int *) vp, &mudstate.vattr_name_htab);

    anum_extend(vp->number);
    anum_set(vp->number, (ATTR *) vp);
    return (vp);
}

void do_dbclean(player, cause, key)
dbref player, cause;
int key;
{
    VATTR *vp;
    dbref i;
    int notfree;

    for (vp = (VATTR *) hash_firstentry(&mudstate.vattr_name_htab);
	vp != NULL;
	vp = (VATTR *) hash_nextentry(&mudstate.vattr_name_htab)) {
	notfree = 0;

	DO_WHOLE_DB(i) {
	    if (atr_get_raw(i, vp->number) != NULL) {
		notfree = 1;
		break;
	    }
	}

	if (!notfree) {
	    anum_set(vp->number, NULL);
	    hashdelete(vp->name, &mudstate.vattr_name_htab);
	    free((char *) vp);
	}
    }
#ifndef STANDALONE
    notify(player, "Database cleared of stale attribute entries.");
#endif
}

void vattr_delete(name)
char *name;
{
    VATTR *vp;
    int number;

    fixcase(name);
    if (!ok_attr_name(name))
	return;

    number = 0;

    vp = (VATTR *) hashfind(name, &mudstate.vattr_name_htab);

    if (vp) {
	number = vp->number;
	anum_set(number, NULL);
	hashdelete(name, &mudstate.vattr_name_htab);
	free((char *) vp);
    }

    return;
}

VATTR *vattr_rename(name, newname)
char *name, *newname;
{
    VATTR *vp;

    fixcase(name);
    if (!ok_attr_name(name))
	return (NULL);

    /*
     * Be ruthless. 
     */

    if (strlen(newname) > VNAME_SIZE)
	newname[VNAME_SIZE - 1] = '\0';

    fixcase(newname);
    if (!ok_attr_name(newname))
	return (NULL);

    vp = (VATTR *) hashfind(name, &mudstate.vattr_name_htab);

    if (vp)
	vp->name = store_string(newname);

    return (vp);
}

VATTR *vattr_first(void)
{
    return (VATTR *) hash_firstentry(&mudstate.vattr_name_htab);
}

VATTR *vattr_next(vp)
VATTR *vp;
{
    if (vp == NULL)
	return (vattr_first());

    return ((VATTR *) hash_nextentry(&mudstate.vattr_name_htab));
}

static void fixcase(name)
char *name;
{
    char *cp = name;

    while (*cp) {
	*cp = ToUpper(*cp);
	cp++;
    }

    return;
}


/*
 * Some goop for efficiently storing strings we expect to
 * keep forever. There is no freeing mechanism.
 */

static char *store_string(str)
char *str;
{
    int len;
    char *ret;

    len = strlen(str);

    /*
     * If we have no block, or there's not enough room left in the * * *
     * current one, get a new one. 
     */

    if (!stringblock || (STRINGBLOCK - stringblock_hwm) < (len + 1)) {
	stringblock = (char *) malloc(STRINGBLOCK);
	if (!stringblock)
	    return ((char *) 0);
	stringblock_hwm = 0;
    }
    ret = stringblock + stringblock_hwm;
    StringCopy(ret, str);
    stringblock_hwm += (len + 1);
    return (ret);
}