2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/misc/atom.c
5 * PURPOSE: Atom functions
6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
7 modified from WINE [ Onno Hovers, (onno@stack.urc.tue.nl) ]
12 #include <kernel32\atom.h>
13 #include <kernel32\proc.h>
14 #include <kernel32\thread.h>
24 /* system global and local atom tables */
26 static ATOMTABLE GlobalAtomTable
;
28 /* internal functions */
29 ATOM
GLDeleteAtom(ATOMTABLE
*at
, ATOM nAtom
);
30 ATOM
AWGLAddAtom( ATOMTABLE
*at
, const WCHAR
*lpString
);
31 ATOM
AWGLFindAtom(ATOMTABLE
*at
, const WCHAR
*lpString
);
32 UINT
AWGLGetAtomName(ATOMTABLE
*at
,ATOM atom
, WCHAR
*lpString
, int nSize
);
34 static ATOMENTRY
*GetAtomPointer(ATOMTABLE
*,int);
35 static ATOMID
AtomHashString(const WCHAR
*,int *);
37 #define ATOMBASE 0xcc00
39 int unicode2ansi( char *ansi
,const WCHAR
*uni
, int s
);
40 int ansi2unicode( WCHAR
*uni
,const char *ansi
, int s
);
49 return GLDeleteAtom(&GlobalAtomTable
, nAtom
);
59 // nSize should be a prime number
61 if ( nSize
< 4 || nSize
>= 512 ) {
65 if ( (GetCurrentPeb()->LocalAtomTable
).lpDrvData
== NULL
) {
66 (GetCurrentPeb()->LocalAtomTable
).lpDrvData
= HeapAlloc(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,nSize
*sizeof(ATOMENTRY
));
80 return GLDeleteAtom(&GetCurrentPeb()->LocalAtomTable
, nAtom
);
94 UINT BufLen
= strlen(lpString
);
95 WCHAR
*lpBuffer
= (WCHAR
*)HeapAlloc(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,BufLen
*sizeof(WCHAR
));
97 ansi2unicode(lpBuffer
, lpString
,BufLen
);
98 atom
= AWGLAddAtom(&GlobalAtomTable
,lpBuffer
);
99 HeapFree(GetProcessHeap(),0,lpBuffer
);
113 return AWGLAddAtom(&GlobalAtomTable
, lpString
);
124 UINT BufLen
= strlen(lpString
);
125 WCHAR
*lpBuffer
= (WCHAR
*)HeapAlloc(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,BufLen
*sizeof(WCHAR
));
126 ansi2unicode(lpBuffer
, lpString
,BufLen
);
127 a
= AWGLFindAtom(&GlobalAtomTable
, lpBuffer
);
128 HeapFree(GetProcessHeap(),0,lpBuffer
);
136 const WCHAR
*lpString
139 return AWGLFindAtom(&GlobalAtomTable
, lpString
);
153 WCHAR
*lpUnicode
= (WCHAR
*)HeapAlloc(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,nSize
*sizeof(WCHAR
));
154 UINT x
= AWGLGetAtomName(&GlobalAtomTable
,nAtom
, lpUnicode
,nSize
);
155 unicode2ansi(lpBuffer
,lpUnicode
,nSize
);
156 HeapFree(GetProcessHeap(),0,lpUnicode
);
169 return AWGLGetAtomName(&GlobalAtomTable
, nAtom
, lpBuffer
, nSize
);
179 UINT BufLen
= strlen(lpString
);
180 WCHAR
*lpBuffer
= (WCHAR
*)HeapAlloc(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,BufLen
*2);
182 ansi2unicode(lpBuffer
, lpString
,BufLen
);
183 a
= AWGLAddAtom(&GetCurrentPeb()->LocalAtomTable
, lpBuffer
);
184 HeapFree(GetProcessHeap(),0,lpBuffer
);
193 const WCHAR
* lpString
196 return AWGLAddAtom(&GetCurrentPeb()->LocalAtomTable
, lpString
);
208 UINT BufLen
= strlen(lpString
);
209 WCHAR
*lpBuffer
= (WCHAR
*)HeapAlloc(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,BufLen
*2);
211 ansi2unicode(lpBuffer
, lpString
,BufLen
);
212 a
= AWGLFindAtom(&GetCurrentPeb()->LocalAtomTable
, lpBuffer
);
213 HeapFree(GetProcessHeap(),0,lpBuffer
);
221 const WCHAR
* lpString
224 return AWGLFindAtom(&GetCurrentPeb()->LocalAtomTable
, lpString
);
237 LPWSTR lpUnicode
= (WCHAR
*)HeapAlloc(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,nSize
*2);
238 UINT x
= AWGLGetAtomName(&GlobalAtomTable
, nAtom
,lpUnicode
,nSize
);
239 unicode2ansi(lpBuffer
,lpUnicode
,nSize
);
240 HeapFree(GetProcessHeap(),0,lpUnicode
);
253 return AWGLGetAtomName(&GetCurrentPeb()->LocalAtomTable
,nAtom
,lpBuffer
, nSize
);
258 ATOMTABLE
*at
, ATOM nAtom
264 /* a free slot has q == 0 && refcnt == 0 */
265 if((lp
= GetAtomPointer(at
,nAtom
- ATOMBASE
))) {
269 if(lp
->refcnt
== 0) {
270 HeapFree(GetProcessHeap(),0,at
->AtomTable
);
271 at
->AtomTable
= NULL
;
272 HeapFree(GetProcessHeap(),0,at
->AtomData
);
286 ATOMTABLE
*at
, const WCHAR
*lpString
291 LPATOMENTRY lp
,lpfree
;
298 /* if we already have it, bump refcnt */
299 if((atom
= AWGLFindAtom(at
, lpString
))) {
300 lp
= GetAtomPointer(at
,atom
- ATOMBASE
);
301 if(lp
->idsize
) lp
->refcnt
++;
305 /* add to a free slot */
306 q
= AtomHashString(lpString
,&atomlen
);
311 for(index
= 0;(lp
= GetAtomPointer(at
,index
));index
++) {
312 if(lp
->q
== 0 && lp
->refcnt
== 0) {
313 if(lp
->idsize
> atomlen
) {
315 (lpfree
->idsize
> lp
->idsize
)) {
322 /* intatoms do not take space in data, but do get new entries */
323 /* an INTATOM will have length of 0 */
324 if(lpfree
&& atomlen
) {
327 lstrcpynW(&at
->AtomData
[lpfree
->idx
],lpString
,atomlen
);
328 return freeindex
+ ATOMBASE
;
331 /* no space was available, or we have an INTATOM */
332 /* so expand or create the table */
333 if(at
->AtomTable
== 0) {
334 at
->AtomTable
= (ATOMENTRY
*) HeapAlloc(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,sizeof(ATOMENTRY
));
340 at
->AtomTable
= (ATOMENTRY
*) HeapReAlloc(GetProcessHeap(),0,
341 (LPVOID
) at
->AtomTable
,
342 at
->TableSize
* sizeof(ATOMENTRY
));
343 lp
= &at
->AtomTable
[at
->TableSize
- 1];
346 /* set in the entry */
349 lp
->idsize
= atomlen
;
352 /* add an entry if not intatom... */
354 newlen
= at
->DataSize
+ atomlen
;
356 if(at
->AtomData
== 0) {
357 at
->AtomData
= (WCHAR
*) HeapAlloc(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,newlen
*2);
361 at
->AtomData
= (WCHAR
*) HeapReAlloc(GetProcessHeap(),0,at
->AtomData
,newlen
*2);
362 lp
->idx
= at
->DataSize
;
365 lstrcpyW(&at
->AtomData
[lp
->idx
],lpString
);
366 at
->DataSize
= newlen
;
369 return index
+ ATOMBASE
;
383 ATOMTABLE
*at
, const WCHAR
*lpString
395 /* convert string to 'q', and get length */
396 q
= AtomHashString(lpString
,&atomlen
);
398 /* find the q value, note: this could be INTATOM */
399 /* if q matches, then do case insensitive compare*/
400 for(index
= 0;(lp
= GetAtomPointer(at
,index
));index
++) {
402 if(HIWORD(lpString
) == 0)
403 return ATOMBASE
+ index
;
404 if(lstrcmpiW(&at
->AtomData
[lp
->idx
],lpString
) == 0)
405 return ATOMBASE
+ index
;
413 AWGLGetAtomName(ATOMTABLE
*at
, ATOM atom
, WCHAR
*lpString
,int len
)
422 /* return the atom name, or create the INTATOM */
423 if((lp
= GetAtomPointer(at
,atom
- ATOMBASE
))) {
425 atomlen
= lstrlenW(atomstr
= &at
->AtomData
[lp
->idx
]);
427 lstrcpyW(lpString
,atomstr
);
429 lstrcpynW(lpString
,atomstr
,len
-1);
430 lpString
[len
-1] = '\0';
432 return (UINT
)lstrlenW(lpString
);
434 //wsprintf((wchar *)lpString,"#%d",lp->q);
435 return (UINT
)lstrlenW(lpString
);
442 /********************************************************/
443 /* convert alphanumeric string to a 'q' value. */
444 /* 'q' values do not need to be unique, they just limit */
445 /* the search we need to make to find a string */
446 /********************************************************/
449 AtomHashString(const WCHAR
* lp
,int *lplen
)
455 /* if we have an intatom... */
456 if(HIWORD(lp
) == 0) {
457 if(lplen
) *lplen
= 0;
461 /* convert the string to an internal representation */
462 for(p
=(WCHAR
*)lp
,q
=0,len
=0;(p
++,ch
=*p
++);len
++)
463 q
= (q
<<1) + iswlower(ch
)?towupper(ch
):ch
;
465 /* 0 is reserved for empty slots */
469 /* avoid strlen later */
470 /* check out with unicode */
477 /********************************************************/
478 /* convert an atom index into a pointer into an */
479 /* atom table. This validates the pointer is in */
480 /* range, and that the data is accessible */
481 /********************************************************/
484 GetAtomPointer(ATOMTABLE
*at
,int index
)
488 /* if no table, then no pointers */
489 if(at
->AtomTable
== 0)
493 if((index
< 0) || (index
>= at
->TableSize
))
496 /* we have a pointer */
497 lp
= &at
->AtomTable
[index
];
500 /* is the index past stored data, validity check */
501 /* LATER: is the size of the entry within the available space */
502 if(lp
->idx
> at
->DataSize
)
508 int ansi2unicode( WCHAR
*uni
,const char *ansi
, int s
)
513 uni
[i
] = (WCHAR
)ansi
[i
];
517 int unicode2ansi( char *ansi
,const WCHAR
*uni
, int s
)
522 ansi
[i
] = (char)uni
[i
];