source: trunk/src/comctl32/comctl32undoc.c@ 2126

Last change on this file since 2126 was 2126, checked in by achimha, 26 years ago

WINE 991212 updates - treeview missing

File size: 52.3 KB
Line 
1/* $Id: comctl32undoc.c,v 1.16 1999-12-18 20:56:58 achimha Exp $ */
2/*
3 * Undocumented functions from COMCTL32.DLL
4 *
5 * Copyright (C) 1999 Achim Hasenmueller
6 *
7 * Based on the work of the WINE group (www.winehq.com)
8 *
9 *
10 * Project Odin Software License can be found in LICENSE.TXT
11 *
12 */
13
14/* WINE 991212 level */
15
16/* CB: todo
17 - porting/implementing string functions
18 - DPA_LoadStream
19 - DPA_SaveStream
20*/
21
22#include "comctl32.h"
23#include <memory.h>
24#include <string.h>
25#include <stdlib.h>
26#include <ctype.h>
27
28extern HANDLE COMCTL32_hHeap; /* handle to the private heap */
29
30/**************************************************************************
31 * DPA_Merge [COMCTL32.11]
32 *
33 * PARAMS
34 * hdpa1 [I] handle to a dynamic pointer array
35 * hdpa2 [I] handle to a dynamic pointer array
36 * dwFlags [I] flags
37 * pfnSort [I] pointer to sort function
38 * pfnMerge [I] pointer to merge function
39 * lParam [I] application specific value
40 *
41 * NOTES
42 * No more information available yet!
43 */
44
45BOOL WINAPI
46DPA_Merge (const HDPA hdpa1, const HDPA hdpa2, DWORD dwFlags,
47 PFNDPACOMPARE pfnCompare, PFNDPAMERGE pfnMerge, LPARAM lParam)
48{
49 INT nCount;
50
51#if 0 /* these go with the "incomplete implementation" below */
52 LPVOID pWork1, pWork2;
53 INT nResult;
54 INT nIndex;
55 INT nNewItems;
56#endif
57
58// TRACE (commctrl, "(%p %p %08lx %p %p %08lx): stub!\n",
59// hdpa1, hdpa2, dwFlags, pfnCompare, pfnParam5, lParam);
60
61 if (IsBadWritePtr (hdpa1, sizeof(DPA)))
62 return FALSE;
63
64 if (IsBadWritePtr (hdpa2, sizeof(DPA)))
65 return FALSE;
66
67 if (IsBadCodePtr ((FARPROC)pfnCompare))
68 return FALSE;
69
70 if (IsBadCodePtr ((FARPROC)pfnMerge))
71 return FALSE;
72
73 if (dwFlags & DPAM_SORT) {
74// TRACE("sorting dpa's!\n");
75 if (hdpa1->nItemCount > 0)
76 DPA_Sort (hdpa1, pfnCompare, lParam);
77// TRACE ("dpa 1 sorted!\n");
78 if (hdpa2->nItemCount > 0)
79 DPA_Sort (hdpa2, pfnCompare, lParam);
80// TRACE ("dpa 2 sorted!\n");
81 }
82
83 if (hdpa2->nItemCount < 1)
84 return TRUE;
85
86// TRACE("hdpa1->nItemCount=%d hdpa2->nItemCount=%d\n",
87// hdpa1->nItemCount, hdpa2->nItemCount);
88
89
90 /* preliminary hack - simply append the pointer list hdpa2 to hdpa1*/
91 for (nCount = 0; nCount < hdpa2->nItemCount; nCount++)
92 DPA_InsertPtr (hdpa1, hdpa1->nItemCount + 1, hdpa2->ptrs[nCount]);
93
94#if 0
95 /* incomplete implementation */
96
97 pWork1 = &(hdpa1->ptrs[hdpa1->nItemCount - 1]);
98 pWork2 = &(hdpa2->ptrs[hdpa2->nItemCount - 1]);
99
100 nIndex = hdpa1->nItemCount - 1;
101 nCount = hdpa2->nItemCount - 1;
102
103 do
104 {
105 nResult = (pfnCompare)(pWork1, pWork2, lParam);
106
107 if (nResult == 0)
108 {
109 PVOID ptr;
110
111 ptr = (pfnMerge)(1, pWork1, pWork2, lParam);
112 if (!ptr)
113 return FALSE;
114
115 nCount--;
116 pWork2--;
117 pWork1 = ptr;
118 }
119 else if (nResult < 0)
120 {
121 if (!dwFlags & 8)
122 {
123 PVOID ptr;
124
125 ptr = DPA_DeletePtr (hdpa1, hdpa1->nItemCount - 1);
126
127 (pfnMerge)(2, ptr, NULL, lParam);
128 }
129 }
130 else
131 {
132 if (!dwFlags & 4)
133 {
134 PVOID ptr;
135
136 ptr = (pfnMerge)(3, pWork2, NULL, lParam);
137 if (!ptr)
138 return FALSE;
139 DPA_InsertPtr (hdpa1, nIndex, ptr);
140 }
141 nCount--;
142 pWork2--;
143 }
144
145 nIndex--;
146 pWork1--;
147
148 }
149 while (nCount >= 0);
150#endif
151
152 return TRUE;
153}
154
155
156/**************************************************************************
157 * Alloc [COMCTL32.71]
158 *
159 * Allocates memory block from the dll's private heap
160 *
161 * PARAMS
162 * dwSize [I] size of the allocated memory block
163 *
164 * RETURNS
165 * Success: pointer to allocated memory block
166 * Failure: NULL
167 */
168
169
170LPVOID WINAPI COMCTL32_Alloc (DWORD dwSize)
171{
172 LPVOID lpPtr;
173
174 lpPtr = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
175
176 return lpPtr;
177}
178
179
180/**************************************************************************
181 * ReAlloc [COMCTL32.72]
182 *
183 * Changes the size of an allocated memory block or allocates a memory
184 * block using the dll's private heap.
185 *
186 * PARAMS
187 * lpSrc [I] pointer to memory block which will be resized
188 * dwSize [I] new size of the memory block.
189 *
190 * RETURNS
191 * Success: pointer to the resized memory block
192 * Failure: NULL
193 *
194 * NOTES
195 * If lpSrc is a NULL-pointer, then COMCTL32_ReAlloc allocates a memory
196 * block like COMCTL32_Alloc.
197 */
198
199LPVOID WINAPI COMCTL32_ReAlloc (LPVOID lpSrc, DWORD dwSize)
200{
201 LPVOID lpDest;
202
203 if (lpSrc)
204 lpDest = HeapReAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, lpSrc, dwSize);
205 else
206 lpDest = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
207
208 return lpDest;
209}
210
211
212/**************************************************************************
213 * Free [COMCTL32.73]
214 *
215 * Frees an allocated memory block from the dll's private heap.
216 *
217 * PARAMS
218 * lpMem [I] pointer to memory block which will be freed
219 *
220 * RETURNS
221 * Success: TRUE
222 * Failure: FALSE
223 */
224
225BOOL WINAPI COMCTL32_Free (LPVOID lpMem)
226{
227 return HeapFree (COMCTL32_hHeap, 0, lpMem);
228}
229
230
231/**************************************************************************
232 * GetSize [COMCTL32.74]
233 *
234 * Retrieves the size of the specified memory block from the dll's
235 * private heap.
236 *
237 * PARAMS
238 * lpMem [I] pointer to an allocated memory block
239 *
240 * RETURNS
241 * Success: size of the specified memory block
242 * Failure: 0
243 */
244
245DWORD WINAPI COMCTL32_GetSize (LPVOID lpMem)
246{
247
248 return HeapSize (COMCTL32_hHeap, 0, lpMem);
249}
250
251
252/**************************************************************************
253 * The MRU-API is a set of functions to manipulate MRU(Most Recently Used)
254 * lists.
255 *
256 * Stored in the reg. as a set of values under a single key. Each item in the
257 * list has a value name that is a single char. 'a' - 'z', '{', '|' or '}'.
258 * The order of the list is stored with value name 'MRUList' which is a string
259 * containing the value names (i.e. 'a', 'b', etc.) in the relevant order.
260 */
261
262typedef struct tagCREATEMRULIST
263{
264 DWORD cbSize; /* size of struct */
265 DWORD nMaxItems; /* max no. of items in list */
266 DWORD dwFlags; /* see below */
267 HKEY hKey; /* root reg. key under which list is saved */
268 LPCSTR lpszSubKey; /* reg. subkey */
269 PROC lpfnCompare; /* item compare proc */
270} CREATEMRULIST, *LPCREATEMRULIST;
271
272/* dwFlags */
273#define MRUF_STRING_LIST 0 /* list will contain strings */
274#define MRUF_BINARY_LIST 1 /* list will contain binary data */
275#define MRUF_DELAYED_SAVE 2 /* only save list order to reg. is FreeMRUList */
276
277/* If list is a string list lpfnCompare has the following prototype
278 * int CALLBACK MRUCompareString(LPCSTR s1, LPCSTR s2)
279 * for binary lists the prototype is
280 * int CALLBACK MRUCompareBinary(LPCVOID data1, LPCVOID data2, DWORD cbData)
281 * where cbData is the no. of bytes to compare.
282 * Need to check what return value means identical - 0?
283 */
284
285typedef struct tagMRU
286{
287 DWORD dwParam1; /* some kind of flag */
288 DWORD dwParam2;
289 DWORD dwParam3;
290 HKEY hkeyMRU;
291 LPCSTR lpszSubKey;
292 DWORD dwParam6;
293} MRU, *HMRU;
294
295HANDLE WINAPI
296CreateMRUListLazyA (LPCREATEMRULIST lpcml, DWORD dwParam2,
297 DWORD dwParam3, DWORD dwParam4);
298
299
300/**************************************************************************
301 * CreateMRUListA [COMCTL32.151]
302 *
303 * PARAMS
304 * lpcml [I] ptr to CREATEMRULIST structure.
305 *
306 * RETURNS
307 * Handle to MRU list.
308 */
309HANDLE WINAPI
310CreateMRUListA (LPCREATEMRULIST lpcml)
311{
312 return CreateMRUListLazyA (lpcml, 0, 0, 0);
313}
314
315/**************************************************************************
316 * FreeMRUListA [COMCTL32.152]
317 *
318 * PARAMS
319 * hMRUList [I] Handle to list.
320 *
321 */
322DWORD WINAPI
323FreeMRUListA (HANDLE hMRUList)
324{
325 FIXME("(%08x) empty stub!\n", hMRUList);
326
327#if 0
328 if (!(hmru->dwParam1 & 1001)) {
329 RegSetValueExA (hmru->hKeyMRU, "MRUList", 0, REG_SZ,
330 hmru->lpszMRUString,
331 lstrlenA (hmru->lpszMRUString));
332 }
333
334
335 RegClosKey (hmru->hkeyMRU
336 COMCTL32_Free32 (hmru->lpszMRUString);
337#endif
338
339 return COMCTL32_Free ((LPVOID)hMRUList);
340}
341
342
343/**************************************************************************
344 * AddMRUData [COMCTL32.167]
345 *
346 * Add item to MRU binary list. If item already exists in list them it is
347 * simply moved up to the top of the list and not added again. If list is
348 * full then the least recently used item is removed to make room.
349 *
350 * PARAMS
351 * hList [I] Handle to list.
352 * lpData [I] ptr to data to add.
353 * cbData [I] no. of bytes of data.
354 *
355 * RETURNS
356 * No. corresponding to registry name where value is stored 'a' -> 0 etc.
357 * -1 on error.
358 */
359INT WINAPI
360AddMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData)
361{
362 FIXME("(%08x, %p, %ld) empty stub!\n", hList, lpData, cbData);
363
364 return 0;
365}
366
367/**************************************************************************
368 * AddMRUStringA [COMCTL32.153]
369 *
370 * Add item to MRU string list. If item already exists in list them it is
371 * simply moved up to the top of the list and not added again. If list is
372 * full then the least recently used item is removed to make room.
373 *
374 * PARAMS
375 * hList [I] Handle to list.
376 * lpszString [I] ptr to string to add.
377 *
378 * RETURNS
379 * No. corresponding to registry name where value is stored 'a' -> 0 etc.
380 * -1 on error.
381 */
382INT WINAPI
383AddMRUStringA(HANDLE hList, LPCSTR lpszString)
384{
385 FIXME("(%08x, %s) empty stub!\n", hList, debugstr_a(lpszString));
386
387 return 0;
388}
389
390/**************************************************************************
391 * DelMRUString [COMCTL32.156]
392 *
393 * Removes item from either string or binary list (despite its name)
394 *
395 * PARAMS
396 * hList [I] list handle
397 * nItemPos [I] item position to remove 0 -> MRU
398 *
399 * RETURNS
400 * TRUE is successful, FALSE if nItemPos is out of range.
401 */
402BOOL WINAPI
403DelMRUString(HANDLE hList, INT nItemPos)
404{
405 FIXME("(%08x, %d): stub\n", hList, nItemPos);
406 return TRUE;
407}
408
409/**************************************************************************
410 * FindMRUData [COMCTL32.169]
411 *
412 * Searches binary list for item that matches lpData of length cbData.
413 * Returns position in list order 0 -> MRU and if lpRegNum != NULL then value
414 * corresponding to item's reg. name will be stored in it ('a' -> 0).
415 *
416 * PARAMS
417 * hList [I] list handle
418 * lpData [I] data to find
419 * cbData [I] length of data
420 * lpRegNum [O] position in registry (maybe NULL)
421 *
422 * RETURNS
423 * Position in list 0 -> MRU. -1 if item not found.
424 */
425INT WINAPI
426FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum)
427{
428 FIXME("(%08x, %p, %ld, %p) empty stub!\n",
429 hList, lpData, cbData, lpRegNum);
430
431 return 0;
432}
433
434/**************************************************************************
435 * FindMRUStringA [COMCTL32.155]
436 *
437 * Searches string list for item that matches lpszString.
438 * Returns position in list order 0 -> MRU and if lpRegNum != NULL then value
439 * corresponding to item's reg. name will be stored in it ('a' -> 0).
440 *
441 * PARAMS
442 * hList [I] list handle
443 * lpszString [I] string to find
444 * lpRegNum [O] position in registry (maybe NULL)
445 *
446 * RETURNS
447 * Position in list 0 -> MRU. -1 if item not found.
448 */
449INT WINAPI
450FindMRUStringA (HANDLE hList, LPCSTR lpszString, LPINT lpRegNum)
451{
452 FIXME("(%08x, %s, %p) empty stub!\n", hList, debugstr_a(lpszString),
453 lpRegNum);
454
455 return 0;
456}
457
458HANDLE WINAPI
459CreateMRUListLazyA (LPCREATEMRULIST lpcml, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
460{
461 /* DWORD dwLocal1; *
462 * HKEY hkeyResult; *
463 * DWORD dwLocal3; *
464 * LPVOID lMRU; *
465 * DWORD dwLocal5; *
466 * DWORD dwLocal6; *
467 * DWORD dwLocal7; *
468 * DWORD dwDisposition; */
469
470 /* internal variables */
471 LPVOID ptr;
472
473 FIXME("(%p) empty stub!\n", lpcml);
474
475 if (lpcml == NULL)
476 return 0;
477
478 if (lpcml->cbSize < sizeof(CREATEMRULIST))
479 return 0;
480
481 FIXME("(%lu %lu %lx %lx \"%s\" %p)\n",
482 lpcml->cbSize, lpcml->nMaxItems, lpcml->dwFlags,
483 (DWORD)lpcml->hKey, lpcml->lpszSubKey, lpcml->lpfnCompare);
484
485 /* dummy pointer creation */
486 ptr = COMCTL32_Alloc (32);
487
488 FIXME("-- ret = %p\n", ptr);
489
490 return (HANDLE)ptr;
491}
492
493/**************************************************************************
494 * EnumMRUListA [COMCTL32.154]
495 *
496 * Enumerate item in a list
497 *
498 * PARAMS
499 * hList [I] list handle
500 * nItemPos [I] item position to enumerate
501 * lpBuffer [O] buffer to receive item
502 * nBufferSize [I] size of buffer
503 *
504 * RETURNS
505 * For binary lists specifies how many bytes were copied to buffer, for
506 * string lists specifies full length of string. Enumerating past the end
507 * of list returns -1.
508 * If lpBuffer == NULL or nItemPos is -ve return value is no. of items in
509 * the list.
510 */
511INT WINAPI EnumMRUListA(HANDLE hList, INT nItemPos, LPVOID lpBuffer,
512DWORD nBufferSize)
513{
514 FIXME("(%08x, %d, %p, %ld): stub\n", hList, nItemPos, lpBuffer,
515 nBufferSize);
516 return 0;
517}
518
519
520
521/**************************************************************************
522 * Str_GetPtrA [COMCTL32.233]
523 *
524 * PARAMS
525 * lpSrc [I]
526 * lpDest [O]
527 * nMaxLen [I]
528 *
529 * RETURNS
530 */
531
532INT WINAPI
533Str_GetPtrA (LPCSTR lpSrc, LPSTR lpDest, INT nMaxLen)
534{
535 INT len;
536
537// TRACE (commctrl, "(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
538
539 if (!lpDest && lpSrc)
540 return lstrlenA (lpSrc);
541
542 if (nMaxLen == 0)
543 return 0;
544
545 if (lpSrc == NULL) {
546 lpDest[0] = '\0';
547 return 0;
548 }
549
550 len = lstrlenA (lpSrc);
551 if (len >= nMaxLen)
552 len = nMaxLen - 1;
553
554 RtlMoveMemory (lpDest, lpSrc, len);
555 lpDest[len] = '\0';
556
557 return len;
558}
559
560
561/**************************************************************************
562 * Str_SetPtrA [COMCTL32.234]
563 *
564 * PARAMS
565 * lppDest [O]
566 * lpSrc [I]
567 *
568 * RETURNS
569 */
570
571BOOL WINAPI
572Str_SetPtrA (LPSTR *lppDest, LPCSTR lpSrc)
573{
574// TRACE (commctrl, "(%p %p)\n", lppDest, lpSrc);
575
576 if (lpSrc) {
577 LPSTR ptr = COMCTL32_ReAlloc (*lppDest, lstrlenA (lpSrc) + 1);
578 if (!ptr)
579 return FALSE;
580 lstrcpyA (ptr, lpSrc);
581 *lppDest = ptr;
582 }
583 else {
584 if (*lppDest) {
585 COMCTL32_Free (*lppDest);
586 *lppDest = NULL;
587 }
588 }
589
590 return TRUE;
591}
592
593
594/**************************************************************************
595 * Str_GetPtrW [COMCTL32.235]
596 *
597 * PARAMS
598 * lpSrc [I]
599 * lpDest [O]
600 * nMaxLen [I]
601 *
602 * RETURNS
603 */
604
605INT WINAPI
606Str_GetPtrW (LPCWSTR lpSrc, LPWSTR lpDest, INT nMaxLen)
607{
608 INT len;
609
610// TRACE (commctrl, "(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
611
612 if (!lpDest && lpSrc)
613 return lstrlenW (lpSrc);
614
615 if (nMaxLen == 0)
616 return 0;
617
618 if (lpSrc == NULL) {
619 lpDest[0] = L'\0';
620 return 0;
621 }
622
623 len = lstrlenW (lpSrc);
624 if (len >= nMaxLen)
625 len = nMaxLen - 1;
626
627 RtlMoveMemory (lpDest, lpSrc, len*sizeof(WCHAR));
628 lpDest[len] = L'\0';
629
630 return len;
631}
632
633
634/**************************************************************************
635 * Str_SetPtrW [COMCTL32.236]
636 *
637 * PARAMS
638 * lpDest [O]
639 * lpSrc [I]
640 *
641 * RETURNS
642 */
643
644BOOL WINAPI
645Str_SetPtrW (LPWSTR *lppDest, LPCWSTR lpSrc)
646{
647// TRACE (commctrl, "(%p %p)\n", lppDest, lpSrc);
648
649 if (lpSrc) {
650 INT len = lstrlenW (lpSrc) + 1;
651 LPWSTR ptr = COMCTL32_ReAlloc (*lppDest, len * sizeof(WCHAR));
652 if (!ptr)
653 return FALSE;
654 lstrcpyW (ptr, lpSrc);
655 *lppDest = ptr;
656 }
657 else {
658 if (*lppDest) {
659 COMCTL32_Free (*lppDest);
660 *lppDest = NULL;
661 }
662 }
663
664 return TRUE;
665}
666
667
668/**************************************************************************
669 * The DSA-API is a set of functions to create and manipulate arrays of
670 * fix sized memory blocks. These arrays can store any kind of data
671 * (strings, icons...).
672 */
673
674/**************************************************************************
675 * DSA_Create [COMCTL32.320] Creates a dynamic storage array
676 *
677 * PARAMS
678 * nSize [I] size of the array elements
679 * nGrow [I] number of elements by which the array grows when it is filled
680 *
681 * RETURNS
682 * Success: pointer to a array control structure. use this like a handle.
683 * Failure: NULL
684 */
685
686HDSA WINAPI
687DSA_Create (INT nSize, INT nGrow)
688{
689 HDSA hdsa;
690
691// TRACE (commctrl, "(size=%d grow=%d)\n", nSize, nGrow);
692
693 hdsa = (HDSA)COMCTL32_Alloc (sizeof(DSA));
694 if (hdsa)
695 {
696 hdsa->nItemCount = 0;
697 hdsa->pData = NULL;
698 hdsa->nMaxCount = 0;
699 hdsa->nItemSize = nSize;
700 hdsa->nGrow = MAX(1, nGrow);
701 }
702
703 return hdsa;
704}
705
706
707/**************************************************************************
708 * DSA_Destroy [COMCTL32.321] Destroys a dynamic storage array
709 *
710 * PARAMS
711 * hdsa [I] pointer to the array control structure
712 *
713 * RETURNS
714 * Success: TRUE
715 * Failure: FALSE
716 */
717
718BOOL WINAPI
719DSA_Destroy (const HDSA hdsa)
720{
721// TRACE (commctrl, "(%p)\n", hdsa);
722
723 if (!hdsa)
724 return FALSE;
725
726 if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
727 return FALSE;
728
729 return COMCTL32_Free (hdsa);
730}
731
732
733/**************************************************************************
734 * DSA_GetItem [COMCTL32.322]
735 *
736 * PARAMS
737 * hdsa [I] pointer to the array control structure
738 * nIndex [I] number of the Item to get
739 * pDest [O] destination buffer. Has to be >= dwElementSize.
740 *
741 * RETURNS
742 * Success: TRUE
743 * Failure: FALSE
744 */
745
746BOOL WINAPI
747DSA_GetItem (const HDSA hdsa, INT nIndex, LPVOID pDest)
748{
749 LPVOID pSrc;
750
751// TRACE (commctrl, "(%p %d %p)\n", hdsa, nIndex, pDest);
752
753 if (!hdsa)
754 return FALSE;
755 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
756 return FALSE;
757
758 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
759 memmove (pDest, pSrc, hdsa->nItemSize);
760
761 return TRUE;
762}
763
764
765/**************************************************************************
766 * DSA_GetItemPtr [COMCTL32.323]
767 *
768 * Retrieves a pointer to the specified item.
769 *
770 * PARAMS
771 * hdsa [I] pointer to the array control structure
772 * nIndex [I] index of the desired item
773 *
774 * RETURNS
775 * Success: pointer to an item
776 * Failure: NULL
777 */
778
779LPVOID WINAPI
780DSA_GetItemPtr (const HDSA hdsa, INT nIndex)
781{
782 LPVOID pSrc;
783
784// TRACE (commctrl, "(%p %d)\n", hdsa, nIndex);
785
786 if (!hdsa)
787 return NULL;
788 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
789 return NULL;
790
791 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
792
793// TRACE (commctrl, "-- ret=%p\n", pSrc);
794
795 return pSrc;
796}
797
798
799/**************************************************************************
800 * DSA_SetItem [COMCTL32.325]
801 *
802 * Sets the contents of an item in the array.
803 *
804 * PARAMS
805 * hdsa [I] pointer to the array control structure
806 * nIndex [I] index for the item
807 * pSrc [I] pointer to the new item data
808 *
809 * RETURNS
810 * Success: TRUE
811 * Failure: FALSE
812 */
813
814BOOL WINAPI
815DSA_SetItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
816{
817 INT nSize, nNewItems;
818 LPVOID pDest, lpTemp;
819
820// TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
821
822 if ((!hdsa) || nIndex < 0)
823 return FALSE;
824
825 if (hdsa->nItemCount <= nIndex) {
826 /* within the old array */
827 if (hdsa->nMaxCount > nIndex) {
828 /* within the allocated space, set a new boundary */
829 hdsa->nItemCount = nIndex + 1;
830 }
831 else {
832 /* resize the block of memory */
833 nNewItems =
834 hdsa->nGrow * ((INT)(((nIndex + 1) - 1) / hdsa->nGrow) + 1);
835 nSize = hdsa->nItemSize * nNewItems;
836
837 lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
838 if (!lpTemp)
839 return FALSE;
840
841 hdsa->nMaxCount = nNewItems;
842 hdsa->nItemCount = nIndex + 1;
843 hdsa->pData = lpTemp;
844 }
845 }
846
847 /* put the new entry in */
848 pDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
849// TRACE("-- move dest=%p src=%p size=%d\n",
850// pDest, pSrc, hdsa->nItemSize);
851 memmove (pDest, pSrc, hdsa->nItemSize);
852
853 return TRUE;
854}
855
856
857/**************************************************************************
858 * DSA_InsertItem [COMCTL32.325]
859 *
860 * PARAMS
861 * hdsa [I] pointer to the array control structure
862 * nIndex [I] index for the new item
863 * pSrc [I] pointer to the element
864 *
865 * RETURNS
866 * Success: position of the new item
867 * Failure: -1
868 */
869
870INT WINAPI
871DSA_InsertItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
872{
873 INT nNewItems, nSize, i;
874 LPVOID lpTemp, lpDest;
875 LPDWORD p;
876
877// TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
878
879 if ((!hdsa) || nIndex < 0)
880 return -1;
881
882 for (i = 0; i < hdsa->nItemSize; i += 4) {
883 p = *(DWORD**)((char *) pSrc + i);
884// if (IsBadStringPtrA ((char*)p, 256))
885// TRACE("-- %d=%p\n", i, (DWORD*)p);
886// else
887// TRACE("-- %d=%p [%s]\n", i, p, debugstr_a((char*)p));
888 }
889
890 /* when nIndex > nItemCount then append */
891 if (nIndex >= hdsa->nItemCount)
892 nIndex = hdsa->nItemCount;
893
894 /* do we need to resize ? */
895 if (hdsa->nItemCount >= hdsa->nMaxCount) {
896 nNewItems = hdsa->nMaxCount + hdsa->nGrow;
897 nSize = hdsa->nItemSize * nNewItems;
898
899 lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
900 if (!lpTemp)
901 return -1;
902
903 hdsa->nMaxCount = nNewItems;
904 hdsa->pData = lpTemp;
905 }
906
907 /* do we need to move elements ? */
908 if (nIndex < hdsa->nItemCount) {
909 lpTemp = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
910 lpDest = (char *) lpTemp + hdsa->nItemSize;
911 nSize = (hdsa->nItemCount - nIndex) * hdsa->nItemSize;
912// TRACE("-- move dest=%p src=%p size=%d\n",
913// lpDest, lpTemp, nSize);
914 memmove (lpDest, lpTemp, nSize);
915 }
916
917 /* ok, we can put the new Item in */
918 hdsa->nItemCount++;
919 lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
920// TRACE("-- move dest=%p src=%p size=%d\n",
921// lpDest, pSrc, hdsa->nItemSize);
922 memmove (lpDest, pSrc, hdsa->nItemSize);
923
924 return hdsa->nItemCount;
925}
926
927
928/**************************************************************************
929 * DSA_DeleteItem [COMCTL32.326]
930 *
931 * PARAMS
932 * hdsa [I] pointer to the array control structure
933 * nIndex [I] index for the element to delete
934 *
935 * RETURNS
936 * Success: number of the deleted element
937 * Failure: -1
938 */
939
940INT WINAPI
941DSA_DeleteItem (const HDSA hdsa, INT nIndex)
942{
943 LPVOID lpDest,lpSrc;
944 INT nSize;
945
946// TRACE (commctrl, "(%p %d)\n", hdsa, nIndex);
947
948 if (!hdsa)
949 return -1;
950 if (nIndex < 0 || nIndex >= hdsa->nItemCount)
951 return -1;
952
953 /* do we need to move ? */
954 if (nIndex < hdsa->nItemCount - 1) {
955 lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
956 lpSrc = (char *) lpDest + hdsa->nItemSize;
957 nSize = hdsa->nItemSize * (hdsa->nItemCount - nIndex - 1);
958// TRACE (commctrl, "-- move dest=%p src=%p size=%d\n",
959// lpDest, lpSrc, nSize);
960 memmove (lpDest, lpSrc, nSize);
961 }
962
963 hdsa->nItemCount--;
964
965 /* free memory ? */
966 if ((hdsa->nMaxCount - hdsa->nItemCount) >= hdsa->nGrow) {
967 nSize = MAX(2*hdsa->nGrow,hdsa->nItemSize)*hdsa->nItemCount;
968
969 lpDest = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
970 if (!lpDest)
971 return -1;
972
973 hdsa->nMaxCount = hdsa->nItemCount;
974 hdsa->pData = lpDest;
975 }
976
977 return nIndex;
978}
979
980
981/**************************************************************************
982 * DSA_DeleteAllItems [COMCTL32.326]
983 *
984 * Removes all items and reinitializes the array.
985 *
986 * PARAMS
987 * hdsa [I] pointer to the array control structure
988 *
989 * RETURNS
990 * Success: TRUE
991 * Failure: FALSE
992 */
993
994BOOL WINAPI
995DSA_DeleteAllItems (const HDSA hdsa)
996{
997// TRACE (commctrl, "(%p)\n", hdsa);
998
999 if (!hdsa)
1000 return FALSE;
1001 if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
1002 return FALSE;
1003
1004 hdsa->nItemCount = 0;
1005 hdsa->pData = NULL;
1006 hdsa->nMaxCount = 0;
1007
1008 return TRUE;
1009}
1010
1011
1012/**************************************************************************
1013 * The DPA-API is a set of functions to create and manipulate arrays of
1014 * pointers.
1015 */
1016
1017/**************************************************************************
1018 * DPA_Create [COMCTL32.328] Creates a dynamic pointer array
1019 *
1020 * PARAMS
1021 * nGrow [I] number of items by which the array grows when it is filled
1022 *
1023 * RETURNS
1024 * Success: handle (pointer) to the pointer array.
1025 * Failure: NULL
1026 */
1027
1028HDPA WINAPI
1029DPA_Create (INT nGrow)
1030{
1031 HDPA hdpa;
1032
1033// TRACE (commctrl, "(%d)\n", nGrow);
1034
1035 hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
1036 if (hdpa) {
1037 hdpa->nGrow = MAX(8, nGrow);
1038 hdpa->hHeap = COMCTL32_hHeap;
1039 hdpa->nMaxCount = hdpa->nGrow * 2;
1040 hdpa->ptrs =
1041 (LPVOID*)COMCTL32_Alloc (hdpa->nMaxCount * sizeof(LPVOID));
1042 }
1043
1044// TRACE (commctrl, "-- %p\n", hdpa);
1045
1046 return hdpa;
1047}
1048
1049
1050/**************************************************************************
1051 * DPA_Destroy [COMCTL32.329] Destroys a dynamic pointer array
1052 *
1053 * PARAMS
1054 * hdpa [I] handle (pointer) to the pointer array
1055 *
1056 * RETURNS
1057 * Success: TRUE
1058 * Failure: FALSE
1059 */
1060
1061BOOL WINAPI
1062DPA_Destroy (const HDPA hdpa)
1063{
1064// TRACE (commctrl, "(%p)\n", hdpa);
1065
1066 if (!hdpa)
1067 return FALSE;
1068
1069 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
1070 return FALSE;
1071
1072 return HeapFree (hdpa->hHeap, 0, hdpa);
1073}
1074
1075
1076/**************************************************************************
1077 * DPA_Grow [COMCTL32.330]
1078 *
1079 * Sets the growth amount.
1080 *
1081 * PARAMS
1082 * hdpa [I] handle (pointer) to the existing (source) pointer array
1083 * nGrow [I] number of items, the array grows, when it's too small
1084 *
1085 * RETURNS
1086 * Success: TRUE
1087 * Failure: FALSE
1088 */
1089
1090BOOL WINAPI
1091DPA_Grow (const HDPA hdpa, INT nGrow)
1092{
1093// TRACE (commctrl, "(%p %d)\n", hdpa, nGrow);
1094
1095 if (!hdpa)
1096 return FALSE;
1097
1098 hdpa->nGrow = MAX(8, nGrow);
1099
1100 return TRUE;
1101}
1102
1103
1104/**************************************************************************
1105 * DPA_Clone [COMCTL32.331]
1106 *
1107 * Copies a pointer array to an other one or creates a copy
1108 *
1109 * PARAMS
1110 * hdpa [I] handle (pointer) to the existing (source) pointer array
1111 * hdpaNew [O] handle (pointer) to the destination pointer array
1112 *
1113 * RETURNS
1114 * Success: pointer to the destination pointer array.
1115 * Failure: NULL
1116 *
1117 * NOTES
1118 * - If the 'hdpaNew' is a NULL-Pointer, a copy of the source pointer
1119 * array will be created and it's handle (pointer) is returned.
1120 * - If 'hdpa' is a NULL-Pointer, the original implementation crashes,
1121 * this implementation just returns NULL.
1122 */
1123
1124HDPA WINAPI
1125DPA_Clone (const HDPA hdpa, const HDPA hdpaNew)
1126{
1127 INT nNewItems, nSize;
1128 HDPA hdpaTemp;
1129
1130 if (!hdpa)
1131 return NULL;
1132
1133// TRACE (commctrl, "(%p %p)\n", hdpa, hdpaNew);
1134
1135 if (!hdpaNew) {
1136 /* create a new DPA */
1137 hdpaTemp = (HDPA)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1138 sizeof(DPA));
1139 hdpaTemp->hHeap = hdpa->hHeap;
1140 hdpaTemp->nGrow = hdpa->nGrow;
1141 }
1142 else
1143 hdpaTemp = hdpaNew;
1144
1145 if (hdpaTemp->ptrs) {
1146 /* remove old pointer array */
1147 HeapFree (hdpaTemp->hHeap, 0, hdpaTemp->ptrs);
1148 hdpaTemp->ptrs = NULL;
1149 hdpaTemp->nItemCount = 0;
1150 hdpaTemp->nMaxCount = 0;
1151 }
1152
1153 /* create a new pointer array */
1154 nNewItems = hdpaTemp->nGrow *
1155 ((INT)((hdpa->nItemCount - 1) / hdpaTemp->nGrow) + 1);
1156 nSize = nNewItems * sizeof(LPVOID);
1157 hdpaTemp->ptrs =
1158 (LPVOID*)HeapAlloc (hdpaTemp->hHeap, HEAP_ZERO_MEMORY, nSize);
1159 hdpaTemp->nMaxCount = nNewItems;
1160
1161 /* clone the pointer array */
1162 hdpaTemp->nItemCount = hdpa->nItemCount;
1163 memmove (hdpaTemp->ptrs, hdpa->ptrs,
1164 hdpaTemp->nItemCount * sizeof(LPVOID));
1165
1166 return hdpaTemp;
1167}
1168
1169
1170/**************************************************************************
1171 * DPA_GetPtr [COMCTL32.332]
1172 *
1173 * Retrieves a pointer from a dynamic pointer array
1174 *
1175 * PARAMS
1176 * hdpa [I] handle (pointer) to the pointer array
1177 * nIndex [I] array index of the desired pointer
1178 *
1179 * RETURNS
1180 * Success: pointer
1181 * Failure: NULL
1182 */
1183
1184LPVOID WINAPI
1185DPA_GetPtr (const HDPA hdpa, INT i)
1186{
1187// TRACE (commctrl, "(%p %d)\n", hdpa, i);
1188
1189 if (!hdpa)
1190 return NULL;
1191 if (!hdpa->ptrs)
1192 return NULL;
1193 if ((i < 0) || (i >= hdpa->nItemCount))
1194 return NULL;
1195
1196// TRACE (commctrl, "-- %p\n", hdpa->ptrs[i]);
1197
1198 return hdpa->ptrs[i];
1199}
1200
1201
1202/**************************************************************************
1203 * DPA_GetPtrIndex [COMCTL32.333]
1204 *
1205 * Retrieves the index of the specified pointer
1206 *
1207 * PARAMS
1208 * hdpa [I] handle (pointer) to the pointer array
1209 * p [I] pointer
1210 *
1211 * RETURNS
1212 * Success: index of the specified pointer
1213 * Failure: -1
1214 */
1215
1216INT WINAPI
1217DPA_GetPtrIndex (const HDPA hdpa, LPVOID p)
1218{
1219 INT i;
1220
1221 if (!hdpa->ptrs)
1222 return -1;
1223
1224 for (i = 0; i < hdpa->nItemCount; i++) {
1225 if (hdpa->ptrs[i] == p)
1226 return i;
1227 }
1228
1229 return -1;
1230}
1231
1232
1233/**************************************************************************
1234 * DPA_InsertPtr [COMCTL32.334]
1235 *
1236 * Inserts a pointer into a dynamic pointer array
1237 *
1238 * PARAMS
1239 * hdpa [I] handle (pointer) to the array
1240 * i [I] array index
1241 * p [I] pointer to insert
1242 *
1243 * RETURNS
1244 * Success: index of the inserted pointer
1245 * Failure: -1
1246 */
1247
1248INT WINAPI
1249DPA_InsertPtr (const HDPA hdpa, INT i, LPVOID p)
1250{
1251 INT nNewItems, nSize, nIndex = 0;
1252 LPVOID *lpTemp, *lpDest;
1253
1254// TRACE (commctrl, "(%p %d %p)\n", hdpa, i, p);
1255
1256 if ((!hdpa) || (i < 0))
1257 return -1;
1258
1259 if (!hdpa->ptrs) {
1260 hdpa->ptrs =
1261 (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1262 2 * hdpa->nGrow * sizeof(LPVOID));
1263 if (!hdpa->ptrs)
1264 return -1;
1265 hdpa->nMaxCount = hdpa->nGrow * 2;
1266 nIndex = 0;
1267 }
1268 else {
1269 if (hdpa->nItemCount >= hdpa->nMaxCount) {
1270// TRACE (commctrl, "-- resizing\n");
1271 nNewItems = hdpa->nMaxCount + hdpa->nGrow;
1272 nSize = nNewItems * sizeof(LPVOID);
1273
1274 lpTemp = (LPVOID*)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1275 hdpa->ptrs, nSize);
1276 if (!lpTemp)
1277 return -1;
1278 hdpa->nMaxCount = nNewItems;
1279 hdpa->ptrs = lpTemp;
1280 }
1281
1282 if (i >= hdpa->nItemCount) {
1283 nIndex = hdpa->nItemCount;
1284// TRACE (commctrl, "-- appending at %d\n", nIndex);
1285 }
1286 else {
1287// TRACE (commctrl, "-- inserting at %d\n", i);
1288 lpTemp = hdpa->ptrs + i;
1289 lpDest = lpTemp + 1;
1290 nSize = (hdpa->nItemCount - i) * sizeof(LPVOID);
1291// TRACE (commctrl, "-- move dest=%p src=%p size=%x\n",
1292// lpDest, lpTemp, nSize);
1293 memmove (lpDest, lpTemp, nSize);
1294 nIndex = i;
1295 }
1296 }
1297
1298 /* insert item */
1299 hdpa->nItemCount++;
1300 hdpa->ptrs[nIndex] = p;
1301
1302 return nIndex;
1303}
1304
1305
1306/**************************************************************************
1307 * DPA_SetPtr [COMCTL32.335]
1308 *
1309 * Sets a pointer in the pointer array
1310 *
1311 * PARAMS
1312 * hdpa [I] handle (pointer) to the pointer array
1313 * i [I] index of the pointer that will be set
1314 * p [I] pointer to be set
1315 *
1316 * RETURNS
1317 * Success: TRUE
1318 * Failure: FALSE
1319 */
1320
1321BOOL WINAPI
1322DPA_SetPtr (const HDPA hdpa, INT i, LPVOID p)
1323{
1324 LPVOID *lpTemp;
1325
1326// TRACE (commctrl, "(%p %d %p)\n", hdpa, i, p);
1327
1328 if ((!hdpa) || i < 0)
1329 return FALSE;
1330
1331 if (hdpa->nItemCount <= i) {
1332 /* within the old array */
1333 if (hdpa->nMaxCount > i) {
1334 /* within the allocated space, set a new boundary */
1335 hdpa->nItemCount = i;
1336 }
1337 else {
1338 /* resize the block of memory */
1339 INT nNewItems =
1340 hdpa->nGrow * ((INT)(((i+1) - 1) / hdpa->nGrow) + 1);
1341 INT nSize = nNewItems * sizeof(LPVOID);
1342
1343 lpTemp = (LPVOID*)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1344 hdpa->ptrs, nSize);
1345 if (!lpTemp)
1346 return FALSE;
1347
1348 hdpa->nItemCount = nNewItems;
1349 hdpa->ptrs = lpTemp;
1350 }
1351 }
1352
1353 /* put the new entry in */
1354 hdpa->ptrs[i] = p;
1355
1356 return TRUE;
1357}
1358
1359
1360/**************************************************************************
1361 * DPA_DeletePtr [COMCTL32.336]
1362 *
1363 * Removes a pointer from the pointer array.
1364 *
1365 * PARAMS
1366 * hdpa [I] handle (pointer) to the pointer array
1367 * i [I] index of the pointer that will be deleted
1368 *
1369 * RETURNS
1370 * Success: deleted pointer
1371 * Failure: NULL
1372 */
1373
1374LPVOID WINAPI
1375DPA_DeletePtr (const HDPA hdpa, INT i)
1376{
1377 LPVOID *lpDest, *lpSrc, lpTemp = NULL;
1378 INT nSize;
1379
1380// TRACE (commctrl, "(%p %d)\n", hdpa, i);
1381
1382 if ((!hdpa) || i < 0 || i >= hdpa->nItemCount)
1383 return NULL;
1384
1385 lpTemp = hdpa->ptrs[i];
1386
1387 /* do we need to move ?*/
1388 if (i < hdpa->nItemCount - 1) {
1389 lpDest = hdpa->ptrs + i;
1390 lpSrc = lpDest + 1;
1391 nSize = (hdpa->nItemCount - i - 1) * sizeof(LPVOID);
1392// TRACE (commctrl,"-- move dest=%p src=%p size=%x\n",
1393// lpDest, lpSrc, nSize);
1394 memmove (lpDest, lpSrc, nSize);
1395 }
1396
1397 hdpa->nItemCount --;
1398
1399 /* free memory ?*/
1400 if ((hdpa->nMaxCount - hdpa->nItemCount) >= hdpa->nGrow) {
1401 INT nNewItems = MAX(hdpa->nGrow*2,hdpa->nItemCount);
1402
1403 nSize = nNewItems * sizeof(LPVOID);
1404 lpDest = (LPVOID)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1405 hdpa->ptrs, nSize);
1406 if (!lpDest)
1407 return NULL;
1408
1409 hdpa->nMaxCount = nNewItems;
1410 hdpa->ptrs = (LPVOID*)lpDest;
1411 }
1412
1413 return lpTemp;
1414}
1415
1416
1417/**************************************************************************
1418 * DPA_DeleteAllPtrs [COMCTL32.337]
1419 *
1420 * Removes all pointers and reinitializes the array.
1421 *
1422 * PARAMS
1423 * hdpa [I] handle (pointer) to the pointer array
1424 *
1425 * RETURNS
1426 * Success: TRUE
1427 * Failure: FALSE
1428 */
1429
1430BOOL WINAPI
1431DPA_DeleteAllPtrs (const HDPA hdpa)
1432{
1433// TRACE (commctrl, "(%p)\n", hdpa);
1434
1435 if (!hdpa)
1436 return FALSE;
1437
1438 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
1439 return FALSE;
1440
1441 hdpa->nItemCount = 0;
1442 hdpa->nMaxCount = hdpa->nGrow * 2;
1443 hdpa->ptrs = (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1444 hdpa->nMaxCount * sizeof(LPVOID));
1445
1446 return TRUE;
1447}
1448
1449
1450/**************************************************************************
1451 * DPA_QuickSort [Internal]
1452 *
1453 * Ordinary quicksort (used by DPA_Sort).
1454 *
1455 * PARAMS
1456 * lpPtrs [I] pointer to the pointer array
1457 * l [I] index of the "left border" of the partition
1458 * r [I] index of the "right border" of the partition
1459 * pfnCompare [I] pointer to the compare function
1460 * lParam [I] user defined value (3rd parameter in compare function)
1461 *
1462 * RETURNS
1463 * NONE
1464 */
1465
1466static VOID
1467DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r,
1468 PFNDPACOMPARE pfnCompare, LPARAM lParam)
1469{
1470 LPVOID t, v;
1471 INT i, j;
1472
1473// TRACE (commctrl, "l=%i r=%i\n", l, r);
1474
1475 i = l;
1476 j = r;
1477 v = lpPtrs[(int)(l+r)/2];
1478 do {
1479 while ((pfnCompare)(lpPtrs[i], v, lParam) < 0) i++;
1480 while ((pfnCompare)(lpPtrs[j], v, lParam) > 0) j--;
1481 if (i <= j)
1482 {
1483 t = lpPtrs[i];
1484 lpPtrs[i++] = lpPtrs[j];
1485 lpPtrs[j--] = t;
1486 }
1487 } while (i <= j);
1488 if (l < j) DPA_QuickSort (lpPtrs, l, j, pfnCompare, lParam);
1489 if (i < r) DPA_QuickSort (lpPtrs, i, r, pfnCompare, lParam);
1490}
1491
1492
1493/**************************************************************************
1494 * DPA_Sort [COMCTL32.338]
1495 *
1496 * Sorts a pointer array using a user defined compare function
1497 *
1498 * PARAMS
1499 * hdpa [I] handle (pointer) to the pointer array
1500 * pfnCompare [I] pointer to the compare function
1501 * lParam [I] user defined value (3rd parameter of compare function)
1502 *
1503 * RETURNS
1504 * Success: TRUE
1505 * Failure: FALSE
1506 */
1507
1508BOOL WINAPI
1509DPA_Sort (const HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam)
1510{
1511 if (!hdpa || !pfnCompare)
1512 return FALSE;
1513
1514// TRACE (commctrl, "(%p %p 0x%lx)\n", hdpa, pfnCompare, lParam);
1515
1516 if ((hdpa->nItemCount > 1) && (hdpa->ptrs))
1517 DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1,
1518 pfnCompare, lParam);
1519
1520 return TRUE;
1521}
1522
1523
1524/**************************************************************************
1525 * DPA_Search [COMCTL32.339]
1526 *
1527 * Searches a pointer array for a specified pointer
1528 *
1529 * PARAMS
1530 * hdpa [I] handle (pointer) to the pointer array
1531 * pFind [I] pointer to search for
1532 * nStart [I] start index
1533 * pfnCompare [I] pointer to the compare function
1534 * lParam [I] user defined value (3rd parameter of compare function)
1535 * uOptions [I] search options
1536 *
1537 * RETURNS
1538 * Success: index of the pointer in the array.
1539 * Failure: -1
1540 *
1541 * NOTES
1542 * Binary search taken from R.Sedgewick "Algorithms in C"!
1543 * Function is NOT tested!
1544 * If something goes wrong, blame HIM not ME! (Eric Kohl)
1545 */
1546
1547INT WINAPI
1548DPA_Search (const HDPA hdpa, LPVOID pFind, INT nStart,
1549 PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions)
1550{
1551 if (!hdpa || !pfnCompare || !pFind)
1552 return -1;
1553
1554// TRACE (commctrl, "(%p %p %d %p 0x%08lx 0x%08x)\n",
1555// hdpa, pFind, nStart, pfnCompare, lParam, uOptions);
1556
1557 if (uOptions & DPAS_SORTED) {
1558 /* array is sorted --> use binary search */
1559 INT l, r, x, n;
1560 LPVOID *lpPtr;
1561
1562// TRACE (commctrl, "binary search\n");
1563
1564 l = (nStart == -1) ? 0 : nStart;
1565 r = hdpa->nItemCount - 1;
1566 lpPtr = hdpa->ptrs;
1567 while (r >= l) {
1568 x = (l + r) / 2;
1569 n = (pfnCompare)(pFind, lpPtr[x], lParam);
1570 if (n < 0)
1571 r = x - 1;
1572 else
1573 l = x + 1;
1574 if (n == 0) {
1575// TRACE (commctrl, "-- ret=%d\n", n);
1576 return n;
1577 }
1578 }
1579
1580 if (uOptions & DPAS_INSERTBEFORE) {
1581// TRACE (commctrl, "-- ret=%d\n", r);
1582 return r;
1583 }
1584
1585 if (uOptions & DPAS_INSERTAFTER) {
1586// TRACE (commctrl, "-- ret=%d\n", l);
1587 return l;
1588 }
1589 }
1590 else {
1591 /* array is not sorted --> use linear search */
1592 LPVOID *lpPtr;
1593 INT nIndex;
1594
1595// TRACE (commctrl, "linear search\n");
1596
1597 nIndex = (nStart == -1)? 0 : nStart;
1598 lpPtr = hdpa->ptrs;
1599 for (; nIndex < hdpa->nItemCount; nIndex++) {
1600 if ((pfnCompare)(pFind, lpPtr[nIndex], lParam) == 0) {
1601// TRACE (commctrl, "-- ret=%d\n", nIndex);
1602 return nIndex;
1603 }
1604 }
1605 }
1606
1607// TRACE (commctrl, "-- not found: ret=-1\n");
1608 return -1;
1609}
1610
1611
1612/**************************************************************************
1613 * DPA_CreateEx [COMCTL32.340]
1614 *
1615 * Creates a dynamic pointer array using the specified size and heap.
1616 *
1617 * PARAMS
1618 * nGrow [I] number of items by which the array grows when it is filled
1619 * hHeap [I] handle to the heap where the array is stored
1620 *
1621 * RETURNS
1622 * Success: handle (pointer) to the pointer array.
1623 * Failure: NULL
1624 */
1625
1626HDPA WINAPI
1627DPA_CreateEx (INT nGrow, HANDLE hHeap)
1628{
1629 HDPA hdpa;
1630
1631// TRACE (commctrl, "(%d 0x%x)\n", nGrow, hHeap);
1632
1633 if (hHeap)
1634 hdpa = (HDPA)HeapAlloc (hHeap, HEAP_ZERO_MEMORY, sizeof(DPA));
1635 else
1636 hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
1637
1638 if (hdpa) {
1639 hdpa->nGrow = MIN(8, nGrow);
1640 hdpa->hHeap = hHeap ? hHeap : COMCTL32_hHeap;
1641 hdpa->nMaxCount = hdpa->nGrow * 2;
1642 hdpa->ptrs =
1643 (LPVOID*)HeapAlloc (hHeap, HEAP_ZERO_MEMORY,
1644 hdpa->nMaxCount * sizeof(LPVOID));
1645 }
1646
1647// TRACE (commctrl, "-- %p\n", hdpa);
1648
1649 return hdpa;
1650}
1651
1652/**************************************************************************
1653 * Notification functions
1654 */
1655
1656typedef struct tagNOTIFYDATA
1657{
1658 HWND hwndFrom;
1659 HWND hwndTo;
1660 DWORD dwParam3;
1661 DWORD dwParam4;
1662 DWORD dwParam5;
1663 DWORD dwParam6;
1664} NOTIFYDATA, *LPNOTIFYDATA;
1665
1666
1667/**************************************************************************
1668 * DoNotify [Internal]
1669 */
1670
1671static LRESULT
1672DoNotify (LPNOTIFYDATA lpNotify, UINT uCode, LPNMHDR lpHdr)
1673{
1674 NMHDR nmhdr;
1675 LPNMHDR lpNmh = NULL;
1676 UINT idFrom = 0;
1677
1678// TRACE (commctrl, "(0x%04x 0x%04x %d %p 0x%08lx)\n",
1679// lpNotify->hwndFrom, lpNotify->hwndTo, uCode, lpHdr,
1680// lpNotify->dwParam5);
1681
1682 if (!lpNotify->hwndTo)
1683 return 0;
1684
1685 if (lpNotify->hwndFrom == -1) {
1686 lpNmh = lpHdr;
1687 idFrom = lpHdr->idFrom;
1688 }
1689 else {
1690 if (lpNotify->hwndFrom) {
1691 HWND hwndParent = GetParent (lpNotify->hwndFrom);
1692 if (hwndParent) {
1693 hwndParent = GetWindow (lpNotify->hwndFrom, GW_OWNER);
1694 if (hwndParent)
1695 idFrom = GetDlgCtrlID (lpNotify->hwndFrom);
1696 }
1697 }
1698
1699 lpNmh = (lpHdr) ? lpHdr : &nmhdr;
1700
1701 lpNmh->hwndFrom = lpNotify->hwndFrom;
1702 lpNmh->idFrom = idFrom;
1703 lpNmh->code = uCode;
1704 }
1705
1706 return SendMessageA (lpNotify->hwndTo, WM_NOTIFY, idFrom, (LPARAM)lpNmh);
1707}
1708
1709
1710/**************************************************************************
1711 * SendNotify [COMCTL32.341]
1712 *
1713 * PARAMS
1714 * hwndFrom [I]
1715 * hwndTo [I]
1716 * uCode [I]
1717 * lpHdr [I]
1718 *
1719 * RETURNS
1720 * Success: return value from notification
1721 * Failure: 0
1722 */
1723
1724LRESULT WINAPI
1725COMCTL32_SendNotify (HWND hwndFrom, HWND hwndTo,
1726 UINT uCode, LPNMHDR lpHdr)
1727{
1728 NOTIFYDATA notify;
1729
1730// TRACE (commctrl, "(0x%04x 0x%04x %d %p)\n",
1731// hwndFrom, hwndTo, uCode, lpHdr);
1732
1733 notify.hwndFrom = hwndFrom;
1734 notify.hwndTo = hwndTo;
1735 notify.dwParam5 = 0;
1736 notify.dwParam6 = 0;
1737
1738 return DoNotify (&notify, uCode, lpHdr);
1739}
1740
1741
1742/**************************************************************************
1743 * SendNotifyEx [COMCTL32.342]
1744 *
1745 * PARAMS
1746 * hwndFrom [I]
1747 * hwndTo [I]
1748 * uCode [I]
1749 * lpHdr [I]
1750 * dwParam5 [I]
1751 *
1752 * RETURNS
1753 * Success: return value from notification
1754 * Failure: 0
1755 */
1756
1757LRESULT WINAPI
1758COMCTL32_SendNotifyEx (HWND hwndTo, HWND hwndFrom, UINT uCode,
1759 LPNMHDR lpHdr, DWORD dwParam5)
1760{
1761 NOTIFYDATA notify;
1762 HWND hwndNotify;
1763
1764// TRACE (commctrl, "(0x%04x 0x%04x %d %p 0x%08lx)\n",
1765// hwndFrom, hwndTo, uCode, lpHdr, dwParam5);
1766
1767 hwndNotify = hwndTo;
1768 if (!hwndTo) {
1769 if (IsWindow (hwndFrom)) {
1770 hwndNotify = GetParent (hwndFrom);
1771 if (!hwndNotify)
1772 return 0;
1773 }
1774 }
1775
1776 notify.hwndFrom = hwndFrom;
1777 notify.hwndTo = hwndNotify;
1778 notify.dwParam5 = dwParam5;
1779 notify.dwParam6 = 0;
1780
1781 return DoNotify (&notify, uCode, lpHdr);
1782}
1783
1784
1785/**************************************************************************
1786 * StrChrA [COMCTL32.350]
1787 *
1788 */
1789
1790LPSTR WINAPI
1791COMCTL32_StrChrA (LPCSTR lpString, CHAR cChar)
1792{
1793 return strchr (lpString, cChar);
1794}
1795
1796
1797/**************************************************************************
1798 * StrStrIA [COMCTL32.355]
1799 */
1800
1801LPSTR WINAPI
1802COMCTL32_StrStrIA (LPCSTR lpStr1, LPCSTR lpStr2)
1803{
1804 INT len1, len2, i;
1805 CHAR first;
1806
1807 if (*lpStr2 == 0)
1808 return ((LPSTR)lpStr1);
1809 len1 = 0;
1810 while (lpStr1[len1] != 0) ++len1;
1811 len2 = 0;
1812 while (lpStr2[len2] != 0) ++len2;
1813 if (len2 == 0)
1814 return ((LPSTR)(lpStr1 + len1));
1815 first = tolower (*lpStr2);
1816 while (len1 >= len2) {
1817 if (tolower(*lpStr1) == first) {
1818 for (i = 1; i < len2; ++i)
1819 if (tolower (lpStr1[i]) != tolower(lpStr2[i]))
1820 break;
1821 if (i >= len2)
1822 return ((LPSTR)lpStr1);
1823 }
1824 ++lpStr1; --len1;
1825 }
1826 return (NULL);
1827}
1828
1829
1830/**************************************************************************
1831 * StrToIntA [COMCTL32.357] Converts a string to a signed integer.
1832 */
1833
1834INT WINAPI
1835COMCTL32_StrToIntA (LPSTR lpString)
1836{
1837 return atoi(lpString);
1838}
1839
1840/**************************************************************************
1841 * DPA_EnumCallback [COMCTL32.385]
1842 *
1843 * Enumerates all items in a dynamic pointer array.
1844 *
1845 * PARAMS
1846 * hdpa [I] handle to the dynamic pointer array
1847 * enumProc [I]
1848 * lParam [I]
1849 *
1850 * RETURNS
1851 * none
1852 */
1853
1854
1855VOID WINAPI
1856DPA_EnumCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
1857{
1858 INT i;
1859
1860// TRACE (commctrl, "(%p %p %08lx)\n", hdpa, enumProc, lParam);
1861
1862 if (!hdpa)
1863 return;
1864 if (hdpa->nItemCount <= 0)
1865 return;
1866
1867 for (i = 0; i < hdpa->nItemCount; i++) {
1868 if ((enumProc)(hdpa->ptrs[i], lParam) == 0)
1869 return;
1870 }
1871
1872 return;
1873}
1874
1875
1876/**************************************************************************
1877 * DPA_DestroyCallback [COMCTL32.386]
1878 *
1879 * Enumerates all items in a dynamic pointer array and destroys it.
1880 *
1881 * PARAMS
1882 * hdpa [I] handle to the dynamic pointer array
1883 * enumProc [I]
1884 * lParam [I]
1885 *
1886 * RETURNS
1887 * Success: TRUE
1888 * Failure: FALSE
1889 */
1890
1891BOOL WINAPI
1892DPA_DestroyCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
1893{
1894// TRACE (commctrl, "(%p %p %08lx)\n", hdpa, enumProc, lParam);
1895
1896 DPA_EnumCallback (hdpa, enumProc, lParam);
1897
1898 return DPA_Destroy (hdpa);
1899}
1900
1901
1902/**************************************************************************
1903 * DSA_EnumCallback [COMCTL32.387]
1904 *
1905 * Enumerates all items in a dynamic storage array.
1906 *
1907 * PARAMS
1908 * hdsa [I] handle to the dynamic storage array
1909 * enumProc [I]
1910 * lParam [I]
1911 *
1912 * RETURNS
1913 * none
1914 */
1915
1916VOID WINAPI
1917DSA_EnumCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
1918{
1919 INT i;
1920
1921// TRACE (commctrl, "(%p %p %08lx)\n", hdsa, enumProc, lParam);
1922
1923 if (!hdsa)
1924 return;
1925 if (hdsa->nItemCount <= 0)
1926 return;
1927
1928 for (i = 0; i < hdsa->nItemCount; i++) {
1929 LPVOID lpItem = DSA_GetItemPtr (hdsa, i);
1930 if ((enumProc)(lpItem, lParam) == 0)
1931 return;
1932 }
1933
1934 return;
1935}
1936
1937
1938/**************************************************************************
1939 * DSA_DestroyCallback [COMCTL32.388]
1940 *
1941 * Enumerates all items in a dynamic storage array and destroys it.
1942 *
1943 * PARAMS
1944 * hdsa [I] handle to the dynamic storage array
1945 * enumProc [I]
1946 * lParam [I]
1947 *
1948 * RETURNS
1949 * Success: TRUE
1950 * Failure: FALSE
1951 */
1952
1953BOOL WINAPI
1954DSA_DestroyCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
1955{
1956// TRACE (commctrl, "(%p %p %08lx)\n", hdsa, enumProc, lParam);
1957
1958 DSA_EnumCallback (hdsa, enumProc, lParam);
1959
1960 return DSA_Destroy (hdsa);
1961}
1962
1963/**************************************************************************
1964 * StrCSpnA [COMCTL32.356]
1965 *
1966 */
1967INT WINAPI COMCTL32_StrCSpnA( LPCSTR lpStr, LPCSTR lpSet) {
1968 return strcspn(lpStr, lpSet);
1969}
1970
1971/**************************************************************************
1972 * StrChrW [COMCTL32.358]
1973 *
1974 */
1975LPWSTR WINAPI COMCTL32_StrChrW( LPCWSTR lpStart, WORD wMatch) {
1976 return (unsigned short*)wcschr(lpStart, wMatch);
1977}
1978
1979/**************************************************************************
1980 * StrCmpNA [COMCTL32.352]
1981 *
1982 */
1983INT WINAPI COMCTL32_StrCmpNA( LPCSTR lpStr1, LPCSTR lpStr2, int nChar) {
1984 return strncmp(lpStr1, lpStr2, nChar);
1985}
1986
1987/**************************************************************************
1988 * StrCmpNIA [COMCTL32.353]
1989 *
1990 */
1991INT WINAPI COMCTL32_StrCmpNIA( LPCSTR lpStr1, LPCSTR lpStr2, int nChar) {
1992 //AH: Inline helper function from WINE
1993 int res;
1994 if (!nChar) return 0;
1995 while ((--nChar > 0) && *lpStr1)
1996 if ((res = toupper(*lpStr1++) - toupper(*lpStr2++))) return res;
1997 return toupper(*lpStr1) - toupper(*lpStr2);
1998}
1999
2000/**************************************************************************
2001 * StrCmpNW [COMCTL32.360]
2002 *
2003 */
2004INT WINAPI COMCTL32_StrCmpNW( LPCWSTR lpStr1, LPCWSTR lpStr2, int nChar) {
2005 return wcsncmp(lpStr1, lpStr2, nChar);
2006}
2007
2008/**************************************************************************
2009 * StrCmpNIW [COMCTL32.361]
2010 *
2011 */
2012INT WINAPI COMCTL32_StrCmpNIW( LPCWSTR lpStr1, LPCWSTR lpStr2, int nChar) {
2013// FIXME("(%s, %s, %i): stub\n", debugstr_w(lpStr1), debugstr_w(lpStr2), nChar);
2014 dprintf(("COMCTL32: StrCmpNIW - unimplemented stub\n"));
2015 return 0;
2016}
2017
2018/***********************************************************************
2019 * ChrCmpA
2020 * This fuction returns FALSE if both words match, TRUE otherwise...
2021 */
2022static BOOL ChrCmpA( WORD word1, WORD word2) {
2023 if (LOBYTE(word1) == LOBYTE(word2)) {
2024 if (IsDBCSLeadByte(LOBYTE(word1))) {
2025 return (word1 != word2);
2026 }
2027 return FALSE;
2028 }
2029 return TRUE;
2030}
2031
2032/**************************************************************************
2033 * StrRChrA [COMCTL32.351]
2034 *
2035 */
2036LPSTR WINAPI COMCTL32_StrRChrA( LPCSTR lpStart, LPCSTR lpEnd, WORD wMatch) {
2037 LPCSTR lpGotIt = NULL;
2038
2039 if (!lpEnd) lpEnd = lpStart + strlen(lpStart);
2040
2041 for(; lpStart < lpEnd; lpStart = CharNextA(lpStart))
2042 if (!ChrCmpA( GET_WORD(lpStart), wMatch))
2043 lpGotIt = lpStart;
2044
2045 return ((LPSTR)lpGotIt);
2046
2047 return 0;
2048}
2049
2050/***********************************************************************
2051 * ChrCmpW
2052 * This fuction returns FALSE if both words match, TRUE otherwise...
2053 */
2054static BOOL ChrCmpW( WORD word1, WORD word2) {
2055 return (word1 != word2);
2056}
2057
2058/**************************************************************************
2059 * StrRChrW [COMCTL32.359]
2060 *
2061 */
2062LPWSTR WINAPI COMCTL32_StrRChrW( LPCWSTR lpStart, LPCWSTR lpEnd, WORD wMatch)
2063{
2064 //AH: Inline Wine helper function
2065 LPCWSTR lpGotIt = NULL;
2066
2067 if (!lpEnd) lpEnd = lpStart + lstrlenW(lpStart);
2068
2069 for(; lpStart < lpEnd; lpStart = CharNextW(lpStart))
2070 if (!ChrCmpW( GET_WORD(lpStart), wMatch))
2071 lpGotIt = lpStart;
2072
2073 return (LPWSTR)lpGotIt;
2074}
2075
2076
2077/**************************************************************************
2078 * StrStrA [COMCTL32.354]
2079 *
2080 */
2081LPSTR WINAPI COMCTL32_StrStrA( LPCSTR lpFirst, LPCSTR lpSrch) {
2082 return strstr(lpFirst, lpSrch);
2083}
2084
2085/**************************************************************************
2086 * StrStrW [COMCTL32.362]
2087 *
2088 */
2089LPWSTR WINAPI COMCTL32_StrStrW( LPCWSTR lpFirst, LPCWSTR lpSrch) {
2090 return (unsigned short*)wcsstr(lpFirst, lpSrch);
2091}
2092
2093/**************************************************************************
2094 * StrSpnW [COMCTL32.364]
2095 *
2096 */
2097INT WINAPI COMCTL32_StrSpnW( LPWSTR lpStr, LPWSTR lpSet) {
2098 LPWSTR lpLoop = lpStr;
2099
2100 /* validate ptr */
2101 if ((lpStr == 0) || (lpSet == 0)) return 0;
2102
2103/* while(*lpLoop) { if lpLoop++; } */
2104
2105 for(; (*lpLoop != 0); lpLoop++)
2106 if (wcschr(lpSet, *(WORD*)lpLoop))
2107 return (INT)(lpLoop-lpStr);
2108
2109 return (INT)(lpLoop-lpStr);
2110}
2111
2112/**************************************************************************
2113 * comctl32_410 [COMCTL32.410]
2114 *
2115 * FIXME: What's this supposed to do?
2116 * Parameter 1 is an HWND, you're on your own for the rest.
2117 */
2118
2119BOOL WINAPI comctl32_410( HWND hw, DWORD b, DWORD c, DWORD d) {
2120
2121 FIXME("(%x, %lx, %lx, %lx): stub!\n", hw, b, c, d);
2122
2123 return TRUE;
2124}
2125
2126/**************************************************************************
2127 * comctl32_411 [COMCTL32.411]
2128 *
2129 * FIXME: What's this supposed to do?
2130 * Parameter 1 is an HWND, you're on your own for the rest.
2131 */
2132
2133BOOL WINAPI comctl32_411( HWND hw, DWORD b, DWORD c) {
2134
2135 FIXME("(%x, %lx, %lx): stub!\n", hw, b, c);
2136
2137 return TRUE;
2138}
2139
2140/**************************************************************************
2141 * comctl32_412 [COMCTL32.412]
2142 *
2143 * FIXME: What's this supposed to do?
2144 * Parameter 1 is an HWND, you're on your own for the rest.
2145 */
2146
2147BOOL WINAPI comctl32_412( HWND hwnd, DWORD b, DWORD c)
2148{
2149 FIXME("(%x, %lx, %lx): stub!\n", hwnd, b, c);
2150
2151 if (IsWindow (hwnd) == FALSE)
2152 return FALSE;
2153
2154 if (b == 0)
2155 return FALSE;
2156
2157
2158 return TRUE;
2159}
2160
2161/**************************************************************************
2162 * comctl32_413 [COMCTL32.413]
2163 *
2164 * FIXME: What's this supposed to do?
2165 * Parameter 1 is an HWND, you're on your own for the rest.
2166 */
2167
2168BOOL WINAPI comctl32_413( HWND hw, DWORD b, DWORD c, DWORD d) {
2169
2170 FIXME("(%x, %lx, %lx, %lx): stub!\n", hw, b, c, d);
2171
2172 return TRUE;
2173}
2174
2175/*************************************************************************
2176 * InitMUILanguage [COMCTL32.70]
2177 *
2178 * FIXME: What's this supposed to do? Apparently some i18n thing.
2179 *
2180 */
2181
2182BOOL WINAPI InitMUILanguage( LANGID uiLang) {
2183
2184 FIXME("(%04x): stub!\n", uiLang);
2185
2186 return TRUE;
2187}
Note: See TracBrowser for help on using the repository browser.