/*
 * Atom table functions
 *
 * Copyright 1993 Alexandre Julliard
 */

/*
 * Current limitations:
 *
 * - This code should work fine when called from the emulation library,
 * but probably not when called from the Windows program.  The reason
 * is that everything is allocated on the current local heap, instead
 * of taking into account the DS register.  Correcting this will also
 * require some changes in the local heap management to bring it closer
 * to Windows.
 *
 * - The code assumes that LocalAlloc() returns a block aligned on a
 * 4-bytes boundary (because of the shifting done in HANDLETOATOM).
 * If this is not the case, the allocation code will have to be changed.
 *
 * - Integer atoms created with MAKEINTATOM are not supported.  This is
 * because they can't generally be differentiated from string constants
 * located below 0x10000 in the emulation library.  If you need
 * integer atoms, use the "#1234" form.
 */

#include <stdlib.h>
#include <string.h>

#include "atom.h"


#define DEFAULT_ATOMTABLE_SIZE    37
#define MIN_STR_ATOM              0xc000

#define ATOMTOHANDLE(atom)        ((HANDLE)(atom) << 2)
#define HANDLETOATOM(handle)      ((ATOM)(0xc000 | ((handle) >> 2)))


static ATOMTABLE * localTable = NULL;
static ATOMTABLE * globalTable = NULL;


/***********************************************************************
 *           ATOM_InitTable
 */
static BOOL ATOM_InitTable( ATOMTABLE ** table, WORD entries )
{
    int i;
    HANDLE handle;
    
    handle = LocalAlloc( LMEM_MOVEABLE, sizeof(ATOMTABLE) +
			 (entries-1) * sizeof(HANDLE) );
    if (!handle) return FALSE;
    *table = (ATOMTABLE *) LocalLock( handle );
    (*table)->size = entries;
    for (i = 0; i < entries; i++) (*table)->entries[i] = 0;
    return TRUE;
    
}


/***********************************************************************
 *           ATOM_Init
 *
 * Global table initialisation.
 */
BOOL ATOM_Init()
{
    return ATOM_InitTable( &globalTable, DEFAULT_ATOMTABLE_SIZE );
}


/***********************************************************************
 *           ATOM_MakePtr
 *
 * Make an ATOMENTRY pointer from a handle (obtained from GetAtomHandle()).
 * Is is assumed that the atom is in the same segment as the table.
 */
static ATOMENTRY * ATOM_MakePtr( ATOMTABLE * table, HANDLE handle )
{
    return (ATOMENTRY *) (((int)table & 0xffff0000) | (int)handle);
}


/***********************************************************************
 *           ATOM_Hash
 */
static WORD ATOM_Hash( WORD entries, LPCSTR str, WORD len )
{
    WORD i, hash = 0;

    for (i = 0; i < len; i++) hash ^= str[i] + i;
    return hash % entries;
}


/***********************************************************************
 *           ATOM_AddAtom
 */
static ATOM ATOM_AddAtom( ATOMTABLE * table, LPCSTR str )
{
    WORD hash;
    HANDLE entry;
    ATOMENTRY * entryPtr;
    int len;
    
    if ((len = strlen( str )) > 255) len = 255;

      /* Check for integer atom */
/*    if (!((int)str & 0xffff0000)) return (ATOM)((int)str & 0xffff); */
    if (str[0] == '#') return atoi( &str[1] );

    hash = ATOM_Hash( table->size, str, len );
    entry = table->entries[hash];
    while (entry)
    {
	entryPtr = ATOM_MakePtr( table, entry );
	if ((entryPtr->length == len) && 
	    (!strncasecmp( entryPtr->str, str, len )))
	{
	    entryPtr->refCount++;
	    return HANDLETOATOM( entry );
	}
	entry = entryPtr->next;
    }
    
    entry = (int)LocalAlloc( LMEM_MOVEABLE, sizeof(ATOMENTRY)+len-1 ) & 0xffff;
    if (!entry) return 0;
    entryPtr = ATOM_MakePtr( table, entry );
    entryPtr->next = table->entries[hash];
    entryPtr->refCount = 1;
    entryPtr->length = len;
    memcpy( entryPtr->str, str, len );
    table->entries[hash] = entry;
    return HANDLETOATOM( entry );
}


/***********************************************************************
 *           ATOM_DeleteAtom
 */
static ATOM ATOM_DeleteAtom( ATOMTABLE * table, ATOM atom )
{
    ATOMENTRY * entryPtr;
    HANDLE entry, *prevEntry;
    WORD hash;
    
    if (atom < MIN_STR_ATOM) return 0;  /* Integer atom */

    entry = ATOMTOHANDLE( atom );
    entryPtr = ATOM_MakePtr( table, entry );

      /* Find previous atom */
    hash = ATOM_Hash( table->size, entryPtr->str, entryPtr->length );
    prevEntry = &table->entries[hash];
    while (*prevEntry && *prevEntry != entry)
    {
	ATOMENTRY * prevEntryPtr = ATOM_MakePtr( table, *prevEntry );
	prevEntry = &prevEntryPtr->next;
    }    
    if (!*prevEntry) return atom;

      /* Delete atom */
    if (--entryPtr->refCount == 0)
    {
	*prevEntry = entryPtr->next;	
	LocalFree( entry );
    }    
    return 0;
}


/***********************************************************************
 *           ATOM_FindAtom
 */
static ATOM ATOM_FindAtom( ATOMTABLE * table, LPCSTR str )
{
    WORD hash;
    HANDLE entry;
    int len;
    
    if ((len = strlen( str )) > 255) len = 255;
    
      /* Check for integer atom */
/*    if (!((int)str & 0xffff0000)) return (ATOM)((int)str & 0xffff); */
    if (str[0] == '#') return atoi( &str[1] );

    hash = ATOM_Hash( table->size, str, len );
    entry = table->entries[hash];
    while (entry)
    {
	ATOMENTRY * entryPtr = ATOM_MakePtr( table, entry );
	if ((entryPtr->length == len) && 
	    (!strncasecmp( entryPtr->str, str, len )))
	    return HANDLETOATOM( entry );
	entry = entryPtr->next;
    }
    return 0;
}


/***********************************************************************
 *           ATOM_GetAtomName
 */
static WORD ATOM_GetAtomName( ATOMTABLE * table, ATOM atom,
			      LPSTR buffer, short count )
{
    ATOMENTRY * entryPtr;
    HANDLE entry;
    char * strPtr;
    int len;
    char text[8];
    
    if (!count) return 0;
    if (atom < MIN_STR_ATOM)
    {
	sprintf( text, "#%d", atom );
	len = strlen(text);
	strPtr = text;
    }
    else
    {
	entry = ATOMTOHANDLE( atom );
	entryPtr = ATOM_MakePtr( table, entry );
	len = entryPtr->length;
	strPtr = entryPtr->str;
    }
    if (len >= count) len = count-1;
    memcpy( buffer, strPtr, len );
    buffer[len] = '\0';
    return len;
}


/***********************************************************************
 *           InitAtomTable   (KERNEL.68)
 */
BOOL InitAtomTable( WORD entries )
{
    return ATOM_InitTable( &localTable, entries );
}


/***********************************************************************
 *           GetAtomHandle   (KERNEL.73)
 */
HANDLE GetAtomHandle( ATOM atom )
{
    if (atom < MIN_STR_ATOM) return 0;
    return ATOMTOHANDLE( atom );
}


/***********************************************************************
 *           AddAtom   (KERNEL.70)
 */
ATOM AddAtom( LPCSTR str )
{
    if (!localTable) InitAtomTable( DEFAULT_ATOMTABLE_SIZE );
    return ATOM_AddAtom( localTable, str );
}


/***********************************************************************
 *           DeleteAtom   (KERNEL.71)
 */
ATOM DeleteAtom( ATOM atom )
{
    if (!localTable) InitAtomTable( DEFAULT_ATOMTABLE_SIZE );
    return ATOM_DeleteAtom( localTable, atom );
}


/***********************************************************************
 *           FindAtom   (KERNEL.69)
 */
ATOM FindAtom( LPCSTR str )
{
    if (!localTable) InitAtomTable( DEFAULT_ATOMTABLE_SIZE );
    return ATOM_FindAtom( localTable, str );
}


/***********************************************************************
 *           GetAtomName   (KERNEL.72)
 */
WORD GetAtomName( ATOM atom, LPSTR buffer, short count )
{
    if (!localTable) InitAtomTable( DEFAULT_ATOMTABLE_SIZE );
    return ATOM_GetAtomName( localTable, atom, buffer, count );
}


/***********************************************************************
 *           GlobalAddAtom   (USER.268)
 */
ATOM GlobalAddAtom( LPCSTR str )
{
    return ATOM_AddAtom( globalTable, str );
}


/***********************************************************************
 *           GlobalDeleteAtom   (USER.269)
 */
ATOM GlobalDeleteAtom( ATOM atom )
{
    return ATOM_DeleteAtom( globalTable, atom );
}


/***********************************************************************
 *           GlobalFindAtom   (USER.270)
 */
ATOM GlobalFindAtom( LPCSTR str )
{
    return ATOM_FindAtom( globalTable, str );
}


/***********************************************************************
 *           GlobalGetAtomName   (USER.271)
 */
WORD GlobalGetAtomName( ATOM atom, LPSTR buffer, short count )
{
    return ATOM_GetAtomName( globalTable, atom, buffer, count );
}
