DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400 Tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Rational R1000/400 Tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T c

⟦c48c6e40a⟧ TextFile

    Length: 21461 (0x53d5)
    Types: TextFile
    Names: »c_av.c«

Derivation

└─⟦149519bd4⟧ Bits:30000546 8mm tape, Rational 1000, !projects 93-07-13
    └─ ⟦124ff5788⟧ »DATA« 
        └─⟦f2882457c⟧ 
└─⟦a7d1ea751⟧ Bits:30000550 8mm tape, Rational 1000, !users!projects 94_04_11
    └─ ⟦129cab021⟧ »DATA« 
        └─⟦f2882457c⟧ 
└─⟦f64eaa120⟧ Bits:30000752 8mm tape, Rational 1000, !projects 93 02 16
    └─ ⟦6f12a12be⟧ »DATA« 
        └─⟦f2882457c⟧ 
└─⟦2f6cfab89⟧ Bits:30000547 8mm tape, Rational 1000, !projects 94-01-04
    └─ ⟦d65440be7⟧ »DATA« 
        └─⟦f2882457c⟧ 
            └─ ⟦this⟧ »C/c_av.c« 

TextFile

static char rcsid_c_av_c[] = "$Id: c_av.c,v 1.1 91/03/07 15:27:12 md Exp $";

/******************************************************************************
*******************************************************************************
*
*  (c) Copyright 1990, Non Standard Logics S.A.
*  ALL RIGHTS RESERVED
*  
*  	THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
*  AND COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND
*  WITH THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR
*  ANY OTHER COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE
*  AVAILABLE TO ANY OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE
*  SOFTWARE IS HEREBY TRANSFERRED.
*  
*  	THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT
*  NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY 
*  Non Standard Logics S.A. OR ITS THIRD PARTY SUPPLIERS.
*  
*  	Non Standard Logics S.A. AND ITS THIRD PARTY SUPPLIERS,
*  ASSUME NO RESPONSIBILITY FOR THE USE OR INABILITY TO USE ANY OF ITS
*  SOFTWARE .   Non Standard Logics S.A SOFTWARE IS PROVIDED "AS IS"
*  WITHOUT WARRANTY OF ANY KIND, AND OSF EXPRESSLY DISCLAIMS ALL 
*  IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*  
*  (c) Copyright 1990, Non Standard Logics S.A.  Unpublished - all
*  rights reserved under the Copyright laws of France
*  
*  Non Standard Logics S.A.
*  57-59 rue Lhomond,
*  75005 Paris.
*  France.
*  
* XFaceMaker is a registered trademark of Non Standard Logics S.A.
*
*******************************************************************************
******************************************************************************/

#include <stdio.h>

#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>

#undef XtDisplay
#undef XtScreen
#undef XtWindow
#undef XtClass
#undef XtSuperClass
#undef XtIsManaged
#undef XtIsRealized
#undef XtIsSensitive

#ifndef NIL

#define NIL	0
#define Nil(type)	((type) NIL)

typedef int *pointer;

#endif

/*
 *	arrays
 */
typedef struct _ARRAY {
	pointer	UserPtr;
	int 	Min;
	int 	Size;
	pointer	*Data;
} ARRAY;

#define ArrayData(a, type)	((type *) (a)->Data)
#define ArrayIndex(a, i, type)	((type) (a)->Data[i - (a)->Min])
#define CheckArray(a, i)	(i > (a)->Min && i < (a)->Min + (a)->Size)

/*
 *	H-code tables
 */

/*
 *	hash tables (keys are strings)
 */
typedef struct _HASH {
	char	*HName;		/* hash key */
	pointer	 HInfo;		/* info */
	struct	_HASH * HNext;	/* synonyms */
} HASH;

typedef struct _HTABLE {
	int 	(* Hash)();	/* hcoding function */
	char *	(* HCopy)();	/* copy function for the name (can be NIL) */
	void	(* HDel)();	/* delete function for the entries (can be NIL) */
	ARRAY	 * HTable;	/* table : must be zero based */
} HTABLE;

/*
 *	assoc tables (keys are pointers)
 */
typedef struct _ASSOC {
	pointer	AKey;		/* hash key */
	pointer	AInfo;		/* info */
	struct	_ASSOC * ANext;	/* synonyms */
} ASSOC;

typedef struct _ATABLE {
	int 	(* AHash)();	/* hcoding function */
	pointer	(* ACopy)();	/* copy function for the key (can be NIL) */
	void	(* ADel)();	/* delete function for the entries (can be NIL) */
	int	(* ACmp)();	/* compare two keys, return 1 if equals (can be NIL) */
	ARRAY	 * ATable;	/* table : must be zero based */
} ATABLE;

/*
 *	Array management
 */

static ARRAY *
NewArray (nb)
int nb;
{
	register ARRAY *a = (ARRAY *)XtMalloc(sizeof(ARRAY));
	
	if (nb > 0) {
		a -> Data = (pointer *) XtMalloc (nb * sizeof (pointer));
	
		if (! a -> Data) {
			free (a);
			return NIL;
		}
	} else {
		a -> Data = NIL;
		nb = 0;
	}
	
	a -> UserPtr = NIL;
	a -> Min = 0;
	a -> Size = nb;
	return a;
}

static void
NewArraySize (a, min, sz, filler)
ARRAY *a;
int min;
int sz;
pointer filler;
{
	pointer *new;
	register pointer *pnew, *copy;
	register int i, size;
	
	if (sz < 0)
		sz = 0;
	
	if (sz)
		pnew = new = (pointer *) XtMalloc (sz * sizeof (pointer));
	else {
		a->Min = min;
		a->Size = NIL;
		if (a->Data)
			free (a->Data);
		a->Data = NIL;
		return;
	}
	
	/* brand new array */
	if (! a -> Data) {
		a->Min = min;
		a->Size = sz;
		a->Data = new;
		while (sz --)
			*pnew++ = filler;
		return;
	}
	
	size = sz;
	copy = a->Data;
	
	/* if the new array starts before the old one, fill the beginning */
	i = a->Min - min;
	if (i > 0)
		while (i--) {
			*pnew++ = filler;
			size--;
		}
	
	/* if the new array is longer, copy and fill end, else just copy */
	if (size > a->Size) {
		i = a->Size;
		while (i--)
			*pnew++ = *copy++;
		i = size - a->Size;
		while (i--)
			*pnew++ = filler;
	} else {
		i = size;
		while (i--)
			*pnew++ = *copy++;
	}
	
	/* free old data and set new array */
	free (a->Data);
	a->Data = new;
	a->Min = min;
	a->Size = sz;
}

static void
CopyArray (to, from)
ARRAY *to, *from;
{
	register pointer *copy, *orig;
	register int i;
	
	if (to -> Data)
		free (to -> Data);
	
	*to = *from;
	if (to -> Size == 0 || ! to -> Data)
		return;
	copy = to -> Data = (pointer *) XtMalloc (to->Size * sizeof (pointer));
	i = to->Size;
	orig = from->Data;
	while (i--)
		*copy++ = *orig++;
}

static void
FreeArray (a)
ARRAY *a;
{
	if (a -> Data)
		free (a -> Data);
	free (a);
}

static void
ResetArray (a)
ARRAY *a;
{
	register pointer *p;
	register int i;
	
	for (p = a -> Data, i = a->Size; i--; p++)
		*p = NIL;
}

static void
SetArray (a, i, val)
register ARRAY *a;
register int i;
pointer val;
{
	if (i < a->Min)
		return;
	if (i > a->Min + a->Size)
		return;
	a -> Data [i - a -> Min] = val;
}

static pointer
GetArray (a, i)
register ARRAY *a;
register int i;
{
	if (i < a->Min)
		return NIL;
	if (i > a->Min + a->Size)
		return NIL;
	return a -> Data [i - a -> Min];
}

/*
 *	--	ASSOC TABLES 	--
 *			
 *
 *	[mbl]	04/04/89
 *	
 */

/*
 *	--	HCODE 	--
 *			
 *
 *	[mbl]	28/01/1986
 *	
 *	v1.0
 *	v1.1	01/05/87
 *	[mbl]	13/08/87	HNum devient HInfo de type int *
 *				ajoute structure HTable
 *				change arguments fonctions en consequence
 *				htable = tableau de pointeurs au lieu de
 *					 tableau de structures
 *				+ fonctions de hash et de copie de nom
 *				 (avec fns par defaut si 0)
 *				fonctions nouvelles :
 *					enlever des element
 *					rehasher dans une autre table
 *		  			detruire une table
 *	[mbl]	25/10/87	remplace table et taille par un ARRAY
 *				DelHash retourne l'info (et plus le HASH *)
 *	[mbl]	13/11/87	ajoute ForHTable pour enumerer une table
 *	[mbl]	04/04/89	petites modifs pour integration des assoc tables
 */


/*
 *	hasher ...
 */
static HASH**
DoHash (ht, name)
register HTABLE *ht;
register char *name;
{
	register int h = 0;
	
	if (ht -> Hash)
		h = (* ht->Hash) (name, ht -> HTable -> Size);
	else
		while (*name)
			h += *name++;
	
	if (h > ht -> HTable -> Size)
		h %= ht -> HTable -> Size;
	
	return ArrayData (ht -> HTable, HASH *) + h;
}

/*
 *	allouer de la place pour un homonyme
 */
static HASH *
NewHash ()
{
	return (HASH *) XtMalloc (sizeof (HASH));
}

/*
 *	ajouter un element en entry
 */
static HASH *
PutHash (entry, name)
register HASH **entry;
register char *name;
{
	register HASH * h;
	
	h = NewHash ();
	h->HName = name;
	h->HNext = *entry;
	*entry = h;
	return h;
}

/*
 *	chercher un element dans entry
 *	la fonction retourne son adresse, ou NIL s'il n'y est pas
 */
static HASH *
FindHash (entry, name)
register HASH **entry;
register char *name;
{
	register char *p, *q;
	register HASH *h;
	
	/* si l'entree est non vide, chercher dans la liste */
	if (*entry)
		for (h = *entry; h; h = h -> HNext) {
			/* on fait le strcmp a la main : ca va + vite */
			for (p = name, q = h->HName; *p == *q++; p++)
				if (*p == '\0')
					return h;
		}
	
	return NIL;
}

/*
 *	enlever un element
 *	le mettre dans la liste des libres
 *	retourne 1 si trouve, 0 sinon
 */
static int
RemoveHash (ht, entry, name)
HTABLE *ht;
HASH **entry;
char *name;
{
	register char *p, *q;
	register HASH *h, *hp = NIL;
	
	/* si l'entree est non vide, chercher dans la liste */
	if (!*entry)
		return 0;
	
	for (h = *entry; h; h = h -> HNext) {
		/* on fait le strcmp a la main : ca va + vite */
		for (p = name, q = h->HName; *p == *q++; p++)
			if (*p == '\0') {
				/* l'enlever de la liste */
				if (hp)
					hp -> HNext = h -> HNext;
				else
					*entry = h -> HNext;
				
				/* le liberer */
				if (ht -> HDel)
					(* ht->HDel) (h);
				free (h);
				return 1;
			}
		hp = h;
	}
	
	return 0;
}

/*
 *	ajouter un element, sauf s'il existe deja
 *	retourne un pointeur sur ledit element.
 *	found indique s'il a ete ajoute (si non nil)
 */
static HASH *
AddHash (ht, name, found)
register HTABLE *ht;
char *name;
int *found;
{
	HASH **entry;
	HASH *h;
	/* est-il dans la table ? */
	entry = DoHash (ht, name);
	if (h = FindHash (entry, name)) {
		if (found)
			*found = 1;
		return h;
	}
	
	/* fonction de copie du nom ? */
	if (ht -> HCopy)
		name = (* ht->HCopy) (name);
	
	/* do it */
	h = PutHash (entry, name);
	if (found)
		*found = 0;
	return h;
}

/*
 *	rechercher un element
 *	retourne un pointeur sur ledit element, NIL si non trouve
 */
static HASH *
GetHash (ht, name)
HTABLE *ht;
char *name;
{
	HASH **entry;
	
	entry = DoHash (ht, name);
	return FindHash (entry, name);
}

/*
 *	enlever un element
 *	retourne l'info de l'element si trouve
 *	retourne NIL si pas trouve
 */
static int
DelHash (ht, name)
HTABLE *ht;
char *name;
{
	return RemoveHash (ht, DoHash (ht, name), name);
}

/*
 *	rehasher une table
 *	retourne l'ancien tableau
 */
static ARRAY *
ReHash (ht, new)
HTABLE *ht;
ARRAY *new;
{
	register HASH *h, *hp;
	register HASH **entry, **e;
	ARRAY *old;
	int s;
	
	old = ht -> HTable;
	ht -> HTable = new;
	s = old -> Size;
	
	for (entry = ArrayData (old, HASH *); s--; entry++) {
		
		/* rehasher une liste */
		for (h = *entry; h; h = hp) {
			e = DoHash (ht, h -> HName);
			
			/* deplacer l'element */
			hp = h -> HNext;
			h -> HNext = *e;
			*e = h;
		}
		
		*entry = NIL;
	}
	
	return old;
}

/*
 *	detruire une table
 *	f est appellee avant chaque destruction (si non nulle)
 */
static void
DelHTable (ht, f)
HTABLE *ht;
void (*f) ();
{
	register HASH **entry;
	register HASH *h, *hp;
	int s;
	
	s = ht -> HTable -> Size;
	for (entry = ArrayData (ht -> HTable, HASH *); s--; entry++) {
		if (! *entry)
			continue;
		
		/* parcourir la liste */
		for (h = *entry; h;) {
			if (f)
				(*f) (h);
			hp = h;
			h = h -> HNext;
			if (ht -> HDel)
				(* ht->HDel) (hp);
			free (hp);
		}
		
		*entry = NIL;
	}
}

/*
 *	parcourir une table
 *	f est appellee avant pour chaque element
 *	si elle retourne 0 on continue
 *	sinon on s'arrete et on retourne la valeur retournee par la fonction
 */
static int
ForHTable (ht, f, arg)
HTABLE *ht;
int (*f) ();
pointer arg;
{
	register HASH **entry;
	register HASH *h;
	int s, res;
	
	s = ht -> HTable -> Size;
	for (entry = ArrayData (ht -> HTable, HASH *); s--; entry++) {
		if (! *entry)
			continue;
		
		/* parcourir la liste */
		for (h = *entry; h;) {
			res = (*f) (h, arg);
			if (res)
				return res;
			h = h -> HNext;
		}
	}
	
	return 0;
}

/*
 *	hasher ...
 */
static ASSOC**
DoAssoc (at, key)
register ATABLE *at;
register pointer key;
{
	register int h = 0;
	
	if (at -> AHash)
		h = (* at->AHash) (key, at -> ATable -> Size);
	else
		h = (int) key;
	
	if (h > at -> ATable -> Size)
		h %= at -> ATable -> Size;
	
	return ArrayData (at -> ATable, ASSOC *) + h;
}

/*
 *	allouer de la place pour un homonyme
 */
static ASSOC *
NewAssoc ()
{
	return (ASSOC *) XtMalloc (sizeof (ASSOC));
}

/*
 *	ajouter un element en entry
 */
static ASSOC *
PutAssoc (entry, key)
register ASSOC **entry;
register pointer key;
{
	register ASSOC * a;
	
	a = NewAssoc ();
	a->AKey = key;
	a->ANext = *entry;
	*entry = a;
	return a;
}

/*
 *	chercher un element dans entry
 *	la fonction retourne son adresse, ou NIL s'il n'y est pas
 */
static ASSOC *
FindAssoc (at, entry, key)
ATABLE *at;
register ASSOC **entry;
register pointer key;
{
	register ASSOC *a;
	
	/* si l'entree est non vide, chercher dans la liste */
	if (*entry)
		for (a = *entry; a; a = a -> ANext) {
			if (at -> ACmp) {
				if ((* at->ACmp) (a -> AKey, key))
					return a;
			} else
				/* comparaison par defaut : les pointeurs eux-meme */
				if (a -> AKey == key)
					return a;
		}
	
	return NIL;
}

/*
 *	enlever un element
 *	le mettre dans la liste des libres
 *	retourner 1 si trouve, 0 sinon
 */
static int
RemoveAssoc (at, entry, key)
ATABLE *at;
ASSOC **entry;
pointer key;
{
	register ASSOC *a, *ap = NIL;
	
	/* si l'entree est non vide, chercher dans la liste */
	if (!*entry)
		return 0;
	
/*	for (a = *entry; a; a = a -> ANext, ap = a) {*/
	for (a = *entry; a; ap = a, a = a -> ANext) {
			if (at -> ACmp) {
				if (! (* at->ACmp) (a -> AKey, key))
					continue;
			} else
				/* comparaison par defaut : les pointeurs eux-meme */
				if (a -> AKey != key)
					continue;
			
			/* l'enlever de la liste */
			if (ap)
				ap -> ANext = a -> ANext;
			else
				*entry = a -> ANext;
			
			/* le liberer */
			if (at -> ADel)
				(* at->ADel) (a);
			free (a);
			return 1;
	}
	
	return 0;
}

/*
 *	ajouter un element, sauf s'il existe deja
 *	retourne un pointeur sur ledit element.
 *	found indique s'il a ete ajoute (si non nil)
 */
static ASSOC *
AddAssoc (at, key, found)
register ATABLE *at;
pointer key;
int *found;
{
	ASSOC **entry;
	ASSOC *a;
	
	/* est-il dans la table ? */
	entry = DoAssoc (at, key);
	if (a = FindAssoc (at, entry, key)) {
		if (found)
			*found = 1;
		return a;
	}
	
	/* fonction de copie du nom ? */
	if (at -> ACopy)
		key = (* at->ACopy) (key);
	
	/* do it */
	a = PutAssoc (entry, key);
	if (found)
		*found = 0;
	return a;
}

/*
 *	rechercher un element
 *	retourne un pointeur sur ledit element, NIL si non trouve
 */
static ASSOC *
GetAssoc (at, key)
ATABLE *at;
pointer key;
{
	ASSOC **entry;
	
	entry = DoAssoc (at, key);
	return FindAssoc (at, entry, key);
}

/*
 *	enlever un element
 *	retourne l'info de l'element si trouve
 *	retourne NIL si pas trouve
 */
static int
DelAssoc (at, key)
ATABLE *at;
pointer key;
{
	return RemoveAssoc (at, DoAssoc (at, key), key);
}

/*
 *	rehasher une table
 *	retourne l'ancien tableau
 */
static ARRAY *ReAssoc (at, new)
ATABLE *at;
ARRAY *new;
{
	register ASSOC *a, *ap;
	register ASSOC **entry, **e;
	ARRAY *old;
	int s;
	
	old = at -> ATable;
	at -> ATable = new;
	s = old -> Size;
	
	for (entry = ArrayData (old, ASSOC *); s--; entry++) {
		
		/* rehasher une liste */
		for (a = *entry; a; a = ap) {
			e = DoAssoc (at, a -> AKey);
			
			/* deplacer l'element */
			ap = a -> ANext;
			a -> ANext = *e;
			*e = a;
		}
		
		*entry = NIL;
	}
	
	return old;
}

/*
 *	detruire une table
 *	f est appellee avant chaque destruction (si non nulle)
 */
static void DelATable (at, f)
ATABLE *at;
void (*f) ();
{
	register ASSOC **entry;
	register ASSOC *a, *ap;
	int s;
	
	s = at -> ATable -> Size;
	for (entry = ArrayData (at -> ATable, ASSOC *); s--; entry++) {
		if (! *entry)
			continue;
		
		/* parcourir la liste */
		for (a = *entry; a;) {
			if (f)
				(*f) (a);
			ap = a;
			a = a -> ANext;
			if (at -> ADel)
				(* at->ADel) (ap);
			free (ap);
		}
		
		*entry = NIL;
	}
}

/*
 *	parcourir une table
 *	f est appellee avant pour chaque element
 *	si elle retourne 0 on continue
 *	sinon on s'arrete et on retourne la valeur retournee par la fonction
 */
static int ForATable (at, f, arg)
ATABLE *at;
int (*f) ();
pointer arg;
{
	register ASSOC **entry;
	register ASSOC *a;
	int s, res;
	
	s = at -> ATable -> Size;
	for (entry = ArrayData (at -> ATable, ASSOC *); s--; entry++) {
		if (! *entry)
			continue;
		
		/* parcourir la liste */
		for (a = *entry; a;) {
			res = (*f) (a, arg);
			if (res)
				return res;
			a = a -> ANext;
		}
	}
	
	return 0;
}

static ATABLE *_FmNewAssocTable(size)
int size;
{
	ATABLE *ret;
	ret = (ATABLE *)XtMalloc((unsigned)sizeof(ATABLE));
	ret -> AHash = NIL;
	ret -> ACopy = NIL;
	ret -> ADel = NIL;
	ret -> ACmp = NIL;
	ret -> ATable = NewArray(size);
	ResetArray(ret -> ATable);
	return ret;
}

static String NewString(s)
String s;
{
	return XtNewString(s);
}

static void DelString (h)
HASH *h;
{
	(void) free (h->HName);
}

static HTABLE *_FmNewHashTable(size)
int size;
{
	HTABLE *ret;
	ret = (HTABLE *)XtMalloc((unsigned)sizeof(HTABLE));
	ret -> Hash = NIL;
	ret -> HCopy = NewString;
	ret -> HDel = DelString;
	ret -> HTable = NewArray(size);
	ResetArray(ret -> HTable);
	return ret;
}

extern void bzero();

static HTABLE *AvTable = 0;
#define AV_SIZE	128

#ifdef NOVOID
typedef caddr_t _pointer;
#else
typedef void *	_pointer;
#endif

typedef int (*pfun) ();

typedef struct __head {
	struct __av *next;
	struct __av *prev;
	_pointer user_addr;
} _head;

typedef struct __av{
	struct __av *next;
	struct __av *prev;
	char *name;
	pfun setproc;
	pfun getproc;
	Widget widget;
	_head *head;
} _av;

static void Insert(elem, pred)
_av *elem, *pred;
{
	elem -> next = pred -> next;
	pred -> next = elem;
	elem -> prev = pred;
	elem -> next -> prev = elem;
}

static void Remove(elem)
_av *elem;
{
	elem -> prev -> next = elem -> next;
	elem -> next -> prev = elem -> prev;
}

static _head *NewHead(){
	_head *ret;
	ret = (_head *)XtMalloc(sizeof(_head));
	ret -> next = ret -> prev = (_av *)ret;
	ret -> user_addr = 0;
	return ret;
}

static _av* AllocNewAv(name, get, set)
char *name;
pfun get, set;
{
	_av *ret;
	
	ret = (_av *)XtMalloc(sizeof(_av));
	bzero(ret, sizeof(_av));
	ret -> name = XtNewString(name);
	ret -> setproc = set;
	ret -> getproc = get;
	ret -> next = ret -> prev = ret;
	return ret;
}

static void DeleteAvs();

void FmNewAv(name, get, set, widget)
String name;
pfun get, set;
Widget widget;
{
	int found;
	HASH *entry;
	_av *pav;
	_head *head;

	if(AvTable == 0)
		AvTable = _FmNewHashTable(AV_SIZE);
	entry = AddHash (AvTable, name, &found);
	if(found){
		head = (_head *)entry -> HInfo;
	} else {
		head = NewHead();
		entry -> HInfo = (pointer) head;
	}
	pav = AllocNewAv(name, get, set);
	pav -> head = head;
	pav -> widget = widget;
	Insert(pav, head -> prev);
	
	XtAddCallback(widget, XtNdestroyCallback, DeleteAvs, 0);
}

/* Il faut detruire les v.a's quand on detruit
 * le widget...
 */
static int DeleteAv(entry, widget)
HASH *entry;
Widget widget;
{
	_av *av;
	_head *head;
	
	if(!entry || !widget)
		return(0);
	
	head = (_head *)entry -> HInfo;
	
	for(av = head -> next; av != (_av *)head; av = av -> next){
		if(av -> widget == widget){
			Remove(av);
			XtFree(av->name);
			XtFree(av);
			return(0);
		}
	}
}

/* Mettre cette fonction comme DestroyCallback du widget
 * dans NewAv.
 */
static void DeleteAvs(widget)
Widget widget;
{
	ForHTable(AvTable, DeleteAv, widget);
}

int FmAttachAv(name, addr)
String name;
caddr_t addr;
{
	HASH *entry = GetHash(AvTable, name);
	int found;
	_head *head;
	
	if(entry == 0){
		entry = AddHash (AvTable, name, &found);
		head = NewHead();
		head -> user_addr = addr;
		entry -> HInfo = (pointer)head;
		return 0;
	} else {
		head = (_head *)entry -> HInfo;
		head -> user_addr = addr;
		return 1;
	}
}

static int found;

static int
UpdateAv(entry, widget)
HASH *entry;
Widget widget;
{
	_head *head;
	_av *av;

	if(entry == 0)
		return(0);
	head = (_head *)entry -> HInfo;
	for(av = head -> next; av != (_av *)head; av = av -> next){
		if(widget && av -> widget != widget)
			continue;
		found = 1;
		if(av -> getproc)
			av -> getproc(av->widget, 0, head -> user_addr);
	}
	return(0);
}

int FmUpdateNamedAv(name)
String name;
{
	HASH *entry = GetHash(AvTable, name);
	found = 0;
	UpdateAv(entry, 0);
	return(found);
}

int FmUpdateAv(name)
String name;
{
	return(FmUpdateNamedAv(name));
}

int FmUpdateWidgetAv(widget)
Widget widget;
{
	found = 0;
	ForHTable(AvTable, UpdateAv, widget);
	return(found);
}

static int
SetAv(entry, widget)
HASH *entry;
Widget widget;
{
	_head *head;
	_av *av;

	if(entry == 0)
		return(0);
	head = (_head *)entry -> HInfo;
	for(av = head -> next; av != (_av *)head; av = av -> next){
		if(widget && av -> widget != widget)
			continue;
		found = 1;
		if(av -> setproc)
			av -> setproc(av->widget, 0, head -> user_addr);
	}
	return(0);
}

int FmSetNamedAv(name)
String name;
{
	HASH *entry = GetHash(AvTable, name);
	
	found = 0;
	SetAv(entry, 0);
	return(found);
}

int FmSetAv(name)
String name;
{
	return(FmSetNamedAv(name));
}

int FmSetWidgetAv(widget)
Widget widget;
{
	found = 0;
	ForHTable(AvTable, SetAv, widget);
	return(found);
}

#ifdef OLD
int FmSetAv(name)
String name;
{
	HASH *entry = GetHash(AvTable, name);
	_head *head;
	_av *av;

	if(entry == 0)
		return;
	head = (_head *)entry -> HInfo;
	for(av = head -> next; av != (_av *)head; av = av -> next){
		if(av -> setproc){
/*			printf("Set av %s : entry=%x, av=%x, widget=%x, addr=%x\n",
					name, entry, av, av->widget, head->user_addr);
 */
			av -> setproc(av->widget, 0, head -> user_addr);
		}
	}
}
#endif

_pointer FmGetAv(name)
char *name;
{
	HASH *entry = GetHash(AvTable, name);
	_head *head;
	_av *av;

	if(entry == 0)
		return(0);
	head = (_head *)entry -> HInfo;
	
	return(head -> user_addr);
}

/* Nouvel interface.
 */

int FmGetActiveValue(widget, name)
Widget widget;
String name;
{
	HASH *entry;
	
	found = 0;
	if(name){
		entry = GetHash(AvTable, name);
		UpdateAv(entry, widget);
	} else {
		FmUpdateWidgetAv(widget);
	}
	return(found);
}

int FmSetActiveValue(widget, name)
Widget widget;
String name;
{
	HASH *entry;
	
	found = 0;
	if(name){
		entry = GetHash(AvTable, name);
		SetAv(entry, widget);
	} else {
		FmSetWidgetAv(widget);
	}
	return(found);
}

_pointer FmGetActiveValueAddr(name)
char *name;
{
	return(FmGetAv(name));
}