Release 960414
[wine.git] / ipc / dde_atom.c
blob6d249084824f9076acdc96b6175425757ee413a8
1 /***************************************************************************
2 * Copyright 1995, Technion, Israel Institute of Technology
3 * Electrical Eng, Software Lab.
4 * Author: Michael Veksler.
5 ***************************************************************************
6 * File: dde_atom.c
7 * Purpose : atom functionality for DDE
8 */
9 #ifdef CONFIG_IPC
11 #include <ctype.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include "dde_atom.h"
16 #include "shm_main_blk.h"
17 #include "shm_fragment.h"
18 #include "ldt.h"
19 #include "stddebug.h"
20 #include "debug.h"
22 typedef struct
24 WORD count;
25 BYTE str[1];
26 } AtomData, *AtomData_ptr;
28 #define EMPTY 0 /* empty hash entry */
29 #define DELETED -1 /* deleted hash entry */
30 #define MIN_STR_ATOM 0xfc00
32 /* OFS2AtomData_ptr: extract AtomData_ptr from ofs */
33 #define OFS2AtomData_ptr(ofs) ((AtomData*)((int)&main_block->block+(ofs)))
35 /* OFS2AtomStr: find the string of the atom */
36 #define OFS2AtomStr(ofs) (OFS2AtomData_ptr(atom_ofs)->str)
38 /* offset of an atom according to index */
39 #define ATOM_OFS(idx) (main_block->atoms[idx])
41 /* rot_left: rotate (with wrap-around) */
42 static __inline__ int rot_left(unsigned var,int count)
44 return (var<<count) | (var>> (sizeof(var)-count));
46 /* find the entry in the atom table for this string */
47 static int FindHash(LPCSTR str) /* ignore str case */
49 int i,j;
50 unsigned hash1,hash2;
51 int deleted=-1; /* hash for deleted entry */
52 int atom_ofs;
54 /* get basic hash parameters */
55 for (i= hash1= hash2= 0; str[i] ; i++) {
56 hash1= rot_left(hash1,5) ^ toupper(str[i]);
57 hash2= rot_left(hash2,4) ^ toupper(str[i]);
60 hash1%= DDE_ATOMS;
61 atom_ofs=ATOM_OFS(hash1);
62 switch (atom_ofs) {
63 case EMPTY: /* empty atom entry */
64 return hash1;
65 case DELETED: /* deleted atom entry */
66 deleted=hash1;
67 break;
68 default : /* non empty atom entry */
69 if (lstrcmpi( OFS2AtomStr(atom_ofs) , str) == 0)
70 return hash1; /* found string in atom table */
72 hash2%= DDE_ATOMS-1 ; /* hash2=0..(DDE_ATOMS-2) */
73 hash2++; /* hash2=1..(DDE_ATOMS-1) */
75 /* make jumps in the hash table by hash2 steps */
76 for (i=hash1+hash2 ; ; i+=hash2) {
77 /* i wraps around into j */
78 j=i-DDE_ATOMS;
79 if (j >= 0)
80 i=j; /* i wraps around */
82 if (i==hash1)
83 /* here if covered all hash locations, and got back to beginning */
84 return deleted; /* return first empty entry - if any */
85 atom_ofs=ATOM_OFS(i);
86 switch (atom_ofs) {
87 case EMPTY: /* empty atom entry */
88 return i;
89 case DELETED: /* deleted atom entry */
90 if (deleted < 0)
91 /* consider only the first deleted entry */
92 deleted= i;
93 break;
94 default : /* nonempty atom entry */
95 if (lstrcmpi( OFS2AtomStr(atom_ofs) , str) == 0)
96 return i; /* found string in atom table */
101 void ATOM_GlobalInit(void)
103 int i;
105 for (i=0 ; i < DDE_ATOMS ; i++)
106 ATOM_OFS(i)=EMPTY;
109 /***********************************************************************
110 * DDE_GlobalAddAtom
113 /* important! don't forget to unlock semaphores before return */
114 ATOM DDE_GlobalAddAtom( SEGPTR name )
116 int atom_idx;
117 int atom_ofs;
118 AtomData_ptr ptr;
119 ATOM atom;
120 char *str;
122 /* First check for integer atom */
124 if (!HIWORD(name)) return (ATOM)LOWORD(name);
126 str = (char *)PTR_SEG_TO_LIN( name );
127 if (str[0] == '#')
129 ATOM atom= (ATOM) atoi(&str[1]);
130 return (atom<MIN_STR_ATOM) ? atom : 0;
133 dprintf_atom(stddeb,"GlobalAddAtom(\"%s\")\n",str);
135 DDE_IPC_init(); /* will initialize only if needed */
137 shm_write_wait(main_block->sem);
139 atom_idx=FindHash(str);
140 atom=(ATOM)0;
142 /* use "return" only at the end so semaphore handling is done only once */
143 if (atom_idx>=0) {
144 /* unless table full and item not found */
145 switch (atom_ofs= ATOM_OFS(atom_idx)) {
146 case DELETED:
147 case EMPTY: /* need to allocate new atom */
148 atom_ofs= shm_FragmentAlloc(&main_block->block,
149 strlen(str)+sizeof(AtomData));
150 if (atom_ofs==NIL)
151 break; /* no more memory (atom==0) */
152 ATOM_OFS(atom_idx)=atom_ofs;
153 ptr=OFS2AtomData_ptr(atom_ofs);
154 strcpy(ptr->str,str);
155 ptr->count=1;
156 atom=(ATOM)(atom_idx+MIN_STR_ATOM);
157 break;
158 default : /* has to update existing atom */
159 OFS2AtomData_ptr(atom_ofs)->count++;
160 atom=(ATOM)(atom_idx+MIN_STR_ATOM);
161 } /* end of switch */
162 } /* end of if */
163 shm_write_signal(main_block->sem);
164 return atom;
167 /***********************************************************************
168 * DDE_GlobalDeleteAtom
171 ATOM DDE_GlobalDeleteAtom( ATOM atom )
173 int atom_idx;
174 int atom_ofs;
175 AtomData_ptr atom_ptr;
176 ATOM retval=(ATOM) 0;
178 dprintf_atom(stddeb,"GlobalDeleteAtom(\"%d\")\n",(int)atom);
179 atom_idx=(int)atom - MIN_STR_ATOM;
181 if (atom_idx < 0 )
182 return 0;
184 DDE_IPC_init(); /* will initialize only if needed */
186 shm_write_wait(main_block->sem);
187 /* return used only once from here on -- for semaphore simplicity */
188 switch (atom_ofs=ATOM_OFS(atom_idx)) {
189 case DELETED:
190 case EMPTY:
191 fprintf(stderr,"trying to free unallocated atom %d\n", atom);
192 retval=atom;
193 break;
194 default :
195 atom_ptr=OFS2AtomData_ptr(atom_ofs);
196 if ( --atom_ptr->count == 0) {
197 shm_FragmentFree(&main_block->block,atom_ofs);
198 ATOM_OFS(atom_idx)=DELETED;
202 shm_write_signal(main_block->sem);
203 return retval;
206 /***********************************************************************
207 * DDE_GlobalFindAtom
209 ATOM DDE_GlobalFindAtom( SEGPTR name )
211 int atom_idx;
212 int atom_ofs;
213 char *str;
215 dprintf_atom(stddeb,"GlobalFindAtom(%08lx)\n", name );
217 /* First check for integer atom */
219 if (!HIWORD(name)) return (ATOM)LOWORD(name);
221 str = (char *)PTR_SEG_TO_LIN( name );
222 if (str[0] == '#')
224 ATOM atom= (ATOM) atoi(&str[1]);
225 return (atom<MIN_STR_ATOM) ? atom : 0;
227 dprintf_atom(stddeb,"GlobalFindAtom(\"%s\")\n",str);
229 DDE_IPC_init(); /* will initialize only if needed */
231 shm_read_wait(main_block->sem);
232 atom_idx=FindHash(str);
233 if (atom_idx>=0)
234 atom_ofs=ATOM_OFS(atom_idx); /* is it free ? */
235 else
236 atom_ofs=EMPTY;
237 shm_read_signal(main_block->sem);
239 if (atom_ofs==EMPTY || atom_ofs==DELETED)
240 return 0;
241 else
242 return (ATOM)(atom_idx+MIN_STR_ATOM);
245 /***********************************************************************
246 * DDE_GlobalGetAtomName
248 WORD DDE_GlobalGetAtomName( ATOM atom, LPSTR buffer, short count )
250 int atom_idx, atom_ofs;
251 int size;
252 /* temporary buffer to hold maximum "#65535\0" */
253 char str_num[7];
255 if (count<2) /* no sense to go on */
256 return 0;
257 atom_idx=(int)atom - MIN_STR_ATOM;
259 if (atom_idx < 0) { /* word atom */
260 /* use wine convention... */
261 sprintf(str_num,"#%d%n",(int)atom,&size);
262 if (size+1>count) { /* overflow ? */
263 /* truncate the string */
264 size=count-1;
265 str_num[size]='\0';
267 strcpy(buffer,str_num);
268 return size;
271 DDE_IPC_init(); /* will initialize only if needed */
273 /* string atom */
274 shm_read_wait(main_block->sem);
275 atom_ofs=ATOM_OFS(atom_idx);
276 if (atom_ofs==EMPTY || atom_ofs==DELETED) {
277 fprintf(stderr,"GlobalGetAtomName: illegal atom=%d\n",(int)atom);
278 size=0;
279 } else { /* non empty entry */
280 /* string length will be at most count-1, find actual size */
281 sprintf(buffer,"%.*s%n",count-1, OFS2AtomStr(atom_ofs), &size);
283 shm_read_signal(main_block->sem);
284 return size;
287 #endif /* CONFIG_IPC */