[COMCTL32] Install comctl32 v6 and its manifest in first stage
[reactos.git] / dll / win32 / comctl32 / dsa.c
1 /*
2 * Dynamic structure array (DSA) implementation
3 *
4 * Copyright 1998 Eric Kohl
5 * 1998 Juergen Schmied <j.schmied@metronet.de>
6 * 2000 Eric Kohl for CodeWeavers
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 *
22 * NOTES
23 * These functions were involuntarily documented by Microsoft in 2002 as
24 * the outcome of an anti-trust suit brought by various U.S. governments.
25 * As a result the specifications on MSDN are inaccurate, incomplete
26 * and misleading. A much more complete (unofficial) documentation is
27 * available at:
28 *
29 * http://members.ozemail.com.au/~geoffch/samples/win32/shell/comctl32
30 */
31
32 #include "comctl32.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(dsa);
35
36 struct _DSA
37 {
38 INT nItemCount;
39 LPVOID pData;
40 INT nMaxCount;
41 INT nItemSize;
42 INT nGrow;
43 };
44
45 /**************************************************************************
46 * DSA_Create [COMCTL32.320]
47 *
48 * Creates a dynamic storage array
49 *
50 * PARAMS
51 * nSize [I] size of the array elements
52 * nGrow [I] number of elements by which the array grows when it is filled
53 *
54 * RETURNS
55 * Success: pointer to an array control structure. Use this like a handle.
56 * Failure: NULL
57 *
58 * NOTES
59 * The DSA_ functions can be used to create and manipulate arrays of
60 * fixed-size memory blocks. These arrays can store any kind of data
61 * (e.g. strings and icons).
62 */
63 HDSA WINAPI DSA_Create (INT nSize, INT nGrow)
64 {
65 HDSA hdsa;
66
67 TRACE("(size=%d grow=%d)\n", nSize, nGrow);
68
69 hdsa = Alloc (sizeof(*hdsa));
70 if (hdsa)
71 {
72 hdsa->nItemCount = 0;
73 hdsa->pData = NULL;
74 hdsa->nMaxCount = 0;
75 hdsa->nItemSize = nSize;
76 hdsa->nGrow = max(1, nGrow);
77 }
78
79 return hdsa;
80 }
81
82
83 /**************************************************************************
84 * DSA_Destroy [COMCTL32.321]
85 *
86 * Destroys a dynamic storage array
87 *
88 * PARAMS
89 * hdsa [I] pointer to the array control structure
90 *
91 * RETURNS
92 * Success: TRUE
93 * Failure: FALSE
94 */
95 BOOL WINAPI DSA_Destroy (HDSA hdsa)
96 {
97 TRACE("(%p)\n", hdsa);
98
99 if (!hdsa)
100 return FALSE;
101
102 if (hdsa->pData && (!Free (hdsa->pData)))
103 return FALSE;
104
105 return Free (hdsa);
106 }
107
108
109 /**************************************************************************
110 * DSA_GetItem [COMCTL32.322]
111 *
112 * Copies the specified item into a caller-supplied buffer.
113 *
114 * PARAMS
115 * hdsa [I] pointer to the array control structure
116 * nIndex [I] number of the Item to get
117 * pDest [O] destination buffer. Has to be >= dwElementSize.
118 *
119 * RETURNS
120 * Success: TRUE
121 * Failure: FALSE
122 */
123 BOOL WINAPI DSA_GetItem (HDSA hdsa, INT nIndex, LPVOID pDest)
124 {
125 LPVOID pSrc;
126
127 TRACE("(%p %d %p)\n", hdsa, nIndex, pDest);
128
129 if (!hdsa)
130 return FALSE;
131 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
132 return FALSE;
133
134 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
135 memmove (pDest, pSrc, hdsa->nItemSize);
136
137 return TRUE;
138 }
139
140
141 /**************************************************************************
142 * DSA_GetItemPtr [COMCTL32.323]
143 *
144 * Retrieves a pointer to the specified item.
145 *
146 * PARAMS
147 * hdsa [I] pointer to the array control structure
148 * nIndex [I] index of the desired item
149 *
150 * RETURNS
151 * Success: pointer to an item
152 * Failure: NULL
153 */
154 LPVOID WINAPI DSA_GetItemPtr (HDSA hdsa, INT nIndex)
155 {
156 LPVOID pSrc;
157
158 TRACE("(%p %d)\n", hdsa, nIndex);
159
160 if (!hdsa)
161 return NULL;
162 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
163 return NULL;
164
165 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
166
167 TRACE("-- ret=%p\n", pSrc);
168
169 return pSrc;
170 }
171
172
173 /**************************************************************************
174 * DSA_SetItem [COMCTL32.325]
175 *
176 * Sets the contents of an item in the array.
177 *
178 * PARAMS
179 * hdsa [I] pointer to the array control structure
180 * nIndex [I] index for the item
181 * pSrc [I] pointer to the new item data
182 *
183 * RETURNS
184 * Success: TRUE
185 * Failure: FALSE
186 */
187 BOOL WINAPI DSA_SetItem (HDSA hdsa, INT nIndex, LPVOID pSrc)
188 {
189 INT nSize, nNewItems;
190 LPVOID pDest, lpTemp;
191
192 TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
193
194 if ((!hdsa) || nIndex < 0)
195 return FALSE;
196
197 if (hdsa->nItemCount <= nIndex) {
198 /* within the old array */
199 if (hdsa->nMaxCount > nIndex) {
200 /* within the allocated space, set a new boundary */
201 hdsa->nItemCount = nIndex + 1;
202 }
203 else {
204 /* resize the block of memory */
205 nNewItems =
206 hdsa->nGrow * ((((nIndex + 1) - 1) / hdsa->nGrow) + 1);
207 nSize = hdsa->nItemSize * nNewItems;
208
209 lpTemp = ReAlloc (hdsa->pData, nSize);
210 if (!lpTemp)
211 return FALSE;
212
213 hdsa->nMaxCount = nNewItems;
214 hdsa->nItemCount = nIndex + 1;
215 hdsa->pData = lpTemp;
216 }
217 }
218
219 /* put the new entry in */
220 pDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
221 TRACE("-- move dest=%p src=%p size=%d\n",
222 pDest, pSrc, hdsa->nItemSize);
223 memmove (pDest, pSrc, hdsa->nItemSize);
224
225 return TRUE;
226 }
227
228
229 /**************************************************************************
230 * DSA_InsertItem [COMCTL32.324]
231 *
232 * Inserts an item into the array at the specified index.
233 *
234 * PARAMS
235 * hdsa [I] pointer to the array control structure
236 * nIndex [I] index for the new item
237 * pSrc [I] pointer to the element
238 *
239 * RETURNS
240 * Success: position of the new item
241 * Failure: -1
242 */
243 INT WINAPI DSA_InsertItem (HDSA hdsa, INT nIndex, LPVOID pSrc)
244 {
245 INT nNewItems, nSize;
246 LPVOID lpTemp, lpDest;
247
248 TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
249
250 if ((!hdsa) || nIndex < 0)
251 return -1;
252
253 /* when nIndex >= nItemCount then append */
254 if (nIndex >= hdsa->nItemCount)
255 nIndex = hdsa->nItemCount;
256
257 /* do we need to resize ? */
258 if (hdsa->nItemCount >= hdsa->nMaxCount) {
259 nNewItems = hdsa->nMaxCount + hdsa->nGrow;
260 nSize = hdsa->nItemSize * nNewItems;
261
262 if (nSize / hdsa->nItemSize != nNewItems)
263 return -1;
264
265 lpTemp = ReAlloc (hdsa->pData, nSize);
266 if (!lpTemp)
267 return -1;
268
269 hdsa->nMaxCount = nNewItems;
270 hdsa->pData = lpTemp;
271 }
272
273 /* do we need to move elements ? */
274 if (nIndex < hdsa->nItemCount) {
275 lpTemp = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
276 lpDest = (char *) lpTemp + hdsa->nItemSize;
277 nSize = (hdsa->nItemCount - nIndex) * hdsa->nItemSize;
278 TRACE("-- move dest=%p src=%p size=%d\n",
279 lpDest, lpTemp, nSize);
280 memmove (lpDest, lpTemp, nSize);
281 }
282
283 /* ok, we can put the new Item in */
284 hdsa->nItemCount++;
285 lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
286 TRACE("-- move dest=%p src=%p size=%d\n",
287 lpDest, pSrc, hdsa->nItemSize);
288 memmove (lpDest, pSrc, hdsa->nItemSize);
289
290 return nIndex;
291 }
292
293
294 /**************************************************************************
295 * DSA_DeleteItem [COMCTL32.326]
296 *
297 * Deletes the specified item from the array.
298 *
299 * PARAMS
300 * hdsa [I] pointer to the array control structure
301 * nIndex [I] index for the element to delete
302 *
303 * RETURNS
304 * Success: number of the deleted element
305 * Failure: -1
306 */
307 INT WINAPI DSA_DeleteItem (HDSA hdsa, INT nIndex)
308 {
309 LPVOID lpDest,lpSrc;
310 INT nSize;
311
312 TRACE("(%p %d)\n", hdsa, nIndex);
313
314 if (!hdsa)
315 return -1;
316 if (nIndex < 0 || nIndex >= hdsa->nItemCount)
317 return -1;
318
319 /* do we need to move ? */
320 if (nIndex < hdsa->nItemCount - 1) {
321 lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
322 lpSrc = (char *) lpDest + hdsa->nItemSize;
323 nSize = hdsa->nItemSize * (hdsa->nItemCount - nIndex - 1);
324 TRACE("-- move dest=%p src=%p size=%d\n",
325 lpDest, lpSrc, nSize);
326 memmove (lpDest, lpSrc, nSize);
327 }
328
329 hdsa->nItemCount--;
330
331 /* free memory ? */
332 if ((hdsa->nMaxCount - hdsa->nItemCount) >= hdsa->nGrow) {
333 nSize = hdsa->nItemSize * hdsa->nItemCount;
334
335 lpDest = ReAlloc (hdsa->pData, nSize);
336 if (!lpDest)
337 return -1;
338
339 hdsa->nMaxCount = hdsa->nItemCount;
340 hdsa->pData = lpDest;
341 }
342
343 return nIndex;
344 }
345
346
347 /**************************************************************************
348 * DSA_DeleteAllItems [COMCTL32.327]
349 *
350 * Removes all items and reinitializes the array.
351 *
352 * PARAMS
353 * hdsa [I] pointer to the array control structure
354 *
355 * RETURNS
356 * Success: TRUE
357 * Failure: FALSE
358 */
359 BOOL WINAPI DSA_DeleteAllItems (HDSA hdsa)
360 {
361 TRACE("(%p)\n", hdsa);
362
363 if (!hdsa)
364 return FALSE;
365 if (hdsa->pData && (!Free (hdsa->pData)))
366 return FALSE;
367
368 hdsa->nItemCount = 0;
369 hdsa->pData = NULL;
370 hdsa->nMaxCount = 0;
371
372 return TRUE;
373 }
374
375
376 /**************************************************************************
377 * DSA_EnumCallback [COMCTL32.387]
378 *
379 * Enumerates all items in a dynamic storage array.
380 *
381 * PARAMS
382 * hdsa [I] handle to the dynamic storage array
383 * enumProc [I]
384 * lParam [I]
385 *
386 * RETURNS
387 * none
388 */
389 VOID WINAPI DSA_EnumCallback (HDSA hdsa, PFNDSAENUMCALLBACK enumProc,
390 LPVOID lParam)
391 {
392 INT i;
393
394 TRACE("(%p %p %p)\n", hdsa, enumProc, lParam);
395
396 if (!hdsa)
397 return;
398 if (hdsa->nItemCount <= 0)
399 return;
400
401 for (i = 0; i < hdsa->nItemCount; i++) {
402 LPVOID lpItem = DSA_GetItemPtr (hdsa, i);
403 if ((enumProc)(lpItem, lParam) == 0)
404 return;
405 }
406
407 return;
408 }
409
410
411 /**************************************************************************
412 * DSA_DestroyCallback [COMCTL32.388]
413 *
414 * Enumerates all items in a dynamic storage array and destroys it.
415 *
416 * PARAMS
417 * hdsa [I] handle to the dynamic storage array
418 * enumProc [I]
419 * lParam [I]
420 *
421 * RETURNS
422 * none
423 */
424 void WINAPI DSA_DestroyCallback (HDSA hdsa, PFNDSAENUMCALLBACK enumProc,
425 LPVOID lParam)
426 {
427 TRACE("(%p %p %p)\n", hdsa, enumProc, lParam);
428
429 DSA_EnumCallback (hdsa, enumProc, lParam);
430 DSA_Destroy (hdsa);
431 }
432
433 /**************************************************************************
434 * DSA_Clone [COMCTL32.@]
435 *
436 * Creates a copy of a dsa
437 *
438 * PARAMS
439 * hdsa [I] handle to the dynamic storage array
440 *
441 * RETURNS
442 * Cloned dsa
443 */
444 HDSA WINAPI DSA_Clone(HDSA hdsa)
445 {
446 HDSA dest;
447 INT i;
448
449 TRACE("(%p)\n", hdsa);
450
451 if (!hdsa)
452 return NULL;
453
454 dest = DSA_Create (hdsa->nItemSize, hdsa->nGrow);
455 if (!dest)
456 return NULL;
457
458 for (i = 0; i < hdsa->nItemCount; i++) {
459 void *ptr = DSA_GetItemPtr (hdsa, i);
460 if (DSA_InsertItem (dest, DA_LAST, ptr) == -1) {
461 DSA_Destroy (dest);
462 return NULL;
463 }
464 }
465
466 return dest;
467 }
468
469 /**************************************************************************
470 * DSA_GetSize [COMCTL32.@]
471 *
472 * Returns allocated memory size for this array
473 *
474 * PARAMS
475 * hdsa [I] handle to the dynamic storage array
476 *
477 * RETURNS
478 * Size
479 */
480 ULONGLONG WINAPI DSA_GetSize(HDSA hdsa)
481 {
482 TRACE("(%p)\n", hdsa);
483
484 if (!hdsa) return 0;
485
486 return sizeof(*hdsa) + (ULONGLONG)hdsa->nMaxCount*hdsa->nItemSize;
487 }