Wed Dec 7 14:52:25 1994 Alexandre Julliard (julliard@lamisun.epfl.ch) * [controls/listbox.c] Fixed problems due to new scroll-bar code. * [loader/signal.c] [miscemu/ioports.c] Handle I/O opcodes that use an absolute address. * [objects/text.c] Implemented TabbedTextOut(). Sat Dec 3 18:53:08 1994 Kenneth MacDonald <K.MacDonald@ed.ac.uk> * [objects/metafile.c] Implemented GetMetafile(). Fixed bug in PlayMetaFile() when reading disc based metafile records. Added META_POLYPOLYGON, META_DELETEOBJECT and META_EOF to PlayMetaFileRecord(). Wed Nov 30 06:32:25 1994 Martin von Loewis (martin@cs.csufresno.edu) * [Imakefile] wine.sym: Remove gcc2_compiled and friends * [controls/listbox.c][if1632/relay.c][if1632/relay.c] [loader/resource.c][memory/heap.c][objects/dib.c][windows/dialog.c] Replace #ifdef DEBUG_XXX with if(debugging_xxx){ * [if1632/call.S] CallToLibMain: New function * [if1632/relay.c][include/options.h][misc/main.c] [miscemu/int1a.c][miscemu/int21.c][miscemu/kernel.c] removed Options.relay_debug * [include/heap.h] HEAP_OWNER: Use ds instead of cs:ip * [loader/ne_image.c] LoadNEImage: Remember current exe, handle nodata dlls InitNEDLL: handle nodata dlls, call CallToLibMain * [loader/selector.c] CreateSelectors: Initialize auto_data_sel with 0 * [memory/heap.c] HEAP_CheckHeap: Check prev HEAP_CheckLocalHeaps: new function * [misc/profile] Remember and dump only changed profiles * [tools/makedebug] Introduce debugging_xxx flags Sun Nov 27 23:13:22 MET 1994 <erik@xs4all.nl> * [clipboard.h color.h dc.h dos_fs.h event.h font.h graphics.h if1632.h kernel.h library.h miscemu.h ne_image.h nonclient.h pe_image.h selectors.h wintypes.h] Added. * [*/*] - Commented all 'static char copyright statements', see misc/main.c - moved prototypes to headers files, fixed wrong prototypes. - *please* add a header file for each .c if you need to export things. * [misc/main.c] Added one static string which list the names of the contributors. Fri Nov 25 16:24:27 MET 1994 Dag Asheim (dash@ifi.uio.no) * [Configure] Made the support for multiple languages more automatic. Added a [fonts] section to the wine.conf file. Made the defaults better. Generally cleaned it up. * [rc/sysres_No.rc] [rc/sysres_De.rc] [rc/sysres.c] Norwegian resources and small fixes to the german resources. Wed Nov 23 20:28:59 1994 Martin von Loewis (martin@cs.csufresno.edu) * [debugger/break.c] bark(), toggle_next(), should_continue(): New functions insert_break(): Fixed, adds write access to page before writing wine_bp.next_addr: new structure field * [debugger/dbg.y] Changed symbol's value to be it's value instead of the value pointed to by the symbol. Changed SIGTRAP handling to allow continuation after break point * [misc/shell.c] ShellAbout(): Load resource from memory
373 lines
9.1 KiB
C
373 lines
9.1 KiB
C
/*
|
|
* Atom table functions
|
|
*
|
|
* Copyright 1993 Alexandre Julliard
|
|
*/
|
|
|
|
/*
|
|
* Current limitations:
|
|
*
|
|
* - 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.
|
|
*
|
|
* 13/Feb, miguel
|
|
* Changed the calls to LocalAlloc to LocalAlign. When compiling WINELIB
|
|
* you call a special version of LocalAlloc that would do the alignement.
|
|
* When compiling the emulator we depend on LocalAlloc returning the
|
|
* aligned block. Needed to test the Library.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#include "user.h"
|
|
#include "atom.h"
|
|
#include "prototypes.h"
|
|
#ifndef WINELIB
|
|
#include "heap.h"
|
|
#endif
|
|
|
|
#define DEFAULT_ATOMTABLE_SIZE 37
|
|
#define MIN_STR_ATOM 0xc000
|
|
|
|
#ifdef WINELIB
|
|
#define ATOMTOHANDLE
|
|
#define HANDLETOATOM
|
|
#else
|
|
#define ATOMTOHANDLE(atom) ((HANDLE)(atom) << 2)
|
|
#define HANDLETOATOM(handle) ((ATOM)(0xc000 | ((handle) >> 2)))
|
|
#endif
|
|
|
|
#ifdef WINELIB
|
|
static ATOMTABLE * localTable = NULL;
|
|
#undef LOCALATOMTABLE
|
|
#define LOCALATOMTABLE() &localTable
|
|
#endif
|
|
|
|
static ATOMTABLE * globalTable = NULL;
|
|
|
|
|
|
/***********************************************************************
|
|
* ATOM_InitTable
|
|
*/
|
|
static BOOL ATOM_InitTable( ATOMTABLE ** table, WORD entries )
|
|
{
|
|
int i;
|
|
HANDLE handle;
|
|
|
|
if (table == &globalTable)
|
|
{
|
|
handle = USER_HEAP_ALLOC(LMEM_MOVEABLE, sizeof(ATOMTABLE) +
|
|
(entries-1) * sizeof(HANDLE) );
|
|
if (!handle)
|
|
return FALSE;
|
|
*table = (ATOMTABLE *) USER_HEAP_ADDR( handle );
|
|
}
|
|
else
|
|
{
|
|
handle = (HANDLE) LocalAlign ( 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 )
|
|
{
|
|
#ifdef WINELIB
|
|
return (ATOMENTRY *) LocalLock (handle);
|
|
#else
|
|
return (ATOMENTRY *) (((int)table & 0xffff0000) | (int)handle);
|
|
#endif
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* ATOM_Hash
|
|
*/
|
|
static WORD ATOM_Hash( WORD entries, LPCSTR str, WORD len )
|
|
{
|
|
WORD i, hash = 0;
|
|
|
|
for (i = 0; i < len; i++) hash ^= toupper(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;
|
|
}
|
|
|
|
if (table == globalTable)
|
|
{
|
|
entry = (int) USER_HEAP_ALLOC(LMEM_MOVEABLE,
|
|
sizeof(ATOMENTRY)+len-1 ) & 0xffff;
|
|
}
|
|
else
|
|
{
|
|
entry = (int) LocalAlign(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;
|
|
if (table == globalTable)
|
|
USER_HEAP_FREE(entry);
|
|
else
|
|
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( LOCALATOMTABLE(), 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 (!*LOCALATOMTABLE()) InitAtomTable( DEFAULT_ATOMTABLE_SIZE );
|
|
return ATOM_AddAtom( *LOCALATOMTABLE(), str );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* DeleteAtom (KERNEL.71)
|
|
*/
|
|
ATOM DeleteAtom( ATOM atom )
|
|
{
|
|
if (!*LOCALATOMTABLE()) InitAtomTable( DEFAULT_ATOMTABLE_SIZE );
|
|
return ATOM_DeleteAtom( *LOCALATOMTABLE(), atom );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* FindAtom (KERNEL.69)
|
|
*/
|
|
ATOM FindAtom( LPCSTR str )
|
|
{
|
|
if (!*LOCALATOMTABLE()) return 0;
|
|
/* if (!*LOCALATOMTABLE()) InitAtomTable( DEFAULT_ATOMTABLE_SIZE );*/
|
|
return ATOM_FindAtom( *LOCALATOMTABLE(), str );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* GetAtomName (KERNEL.72)
|
|
*/
|
|
WORD GetAtomName( ATOM atom, LPSTR buffer, short count )
|
|
{
|
|
if (!*LOCALATOMTABLE()) InitAtomTable( DEFAULT_ATOMTABLE_SIZE );
|
|
return ATOM_GetAtomName( *LOCALATOMTABLE(), 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 );
|
|
}
|