Fixed an error and an off-by-one bug in DSA_SetItem(). This
[wine.git] / dlls / comctl32 / comctl32undoc.c
blob25360204e6bb1e3c39673eab212ee13271632603
1 /*
2 * Undocumented functions from COMCTL32.DLL
4 * Copyright 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de>
5 * 1998 Juergen Schmied <j.schmied@metronet.de>
6 * NOTES
7 * All of these functions are UNDOCUMENTED!! And I mean UNDOCUMENTED!!!!
8 * Do NOT rely on names or contents of undocumented structures and types!!!
9 * These functions are used by EXPLORER.EXE, IEXPLORE.EXE and
10 * COMCTL32.DLL (internally).
12 * TODO
13 * - Add more functions.
14 * - Write some documentation.
17 #include <string.h>
18 #include <stdlib.h> /* atoi */
19 #include <ctype.h>
21 #include "winbase.h"
22 #include "commctrl.h"
23 #include "debug.h"
25 DEFAULT_DEBUG_CHANNEL(commctrl)
28 extern HANDLE COMCTL32_hHeap; /* handle to the private heap */
31 * We put some function prototypes here that don't seem to belong in
32 * any header file. When they find their place, we can remove them.
34 extern LPWSTR __cdecl CRTDLL_wcschr(LPCWSTR, WCHAR);
35 extern LPSTR WINAPI lstrrchr(LPCSTR, LPCSTR, WORD);
36 extern LPWSTR WINAPI lstrrchrw(LPCWSTR, LPCWSTR, WORD);
37 extern LPWSTR WINAPI strstrw(LPCWSTR, LPCWSTR);
40 /**************************************************************************
41 * DPA_Merge [COMCTL32.11]
43 * PARAMS
44 * hdpa1 [I] handle to a dynamic pointer array
45 * hdpa2 [I] handle to a dynamic pointer array
46 * dwFlags [I] flags
47 * pfnSort [I] pointer to sort function
48 * dwParam5 [I]
49 * lParam [I] application specific value
51 * NOTES
52 * No more information available yet!
55 BOOL WINAPI
56 DPA_Merge (const HDPA hdpa1, const HDPA hdpa2, DWORD dwFlags,
57 PFNDPACOMPARE pfnCompare, LPVOID pfnParam5, LPARAM lParam)
59 /* LPVOID *pWork1, *pWork2; */
60 INT nCount1, nCount2;
62 TRACE (commctrl, "(%p %p %08lx %p %p %08lx): stub!\n",
63 hdpa1, hdpa2, dwFlags, pfnCompare, pfnParam5, lParam);
65 if (IsBadWritePtr (hdpa1, sizeof(DPA)))
66 return FALSE;
68 if (IsBadWritePtr (hdpa2, sizeof(DPA)))
69 return FALSE;
71 if (IsBadCodePtr ((FARPROC)pfnCompare))
72 return FALSE;
74 if (IsBadCodePtr ((FARPROC)pfnParam5))
75 return FALSE;
77 if (dwFlags & DPAM_SORT) {
78 TRACE (commctrl, "sorting dpa's!\n");
79 DPA_Sort (hdpa1, pfnCompare, lParam);
80 DPA_Sort (hdpa2, pfnCompare, lParam);
83 if (hdpa2->nItemCount <= 0)
84 return TRUE;
86 nCount1 = hdpa1->nItemCount - 1;
88 nCount2 = hdpa2->nItemCount - 1;
90 FIXME (commctrl, "nCount1=%d nCount2=%d\n", nCount1, nCount2);
91 FIXME (commctrl, "semi stub!\n");
92 #if 0
94 do {
97 if (nResult == 0) {
100 else if (nResult > 0) {
103 else {
108 while (nCount2 >= 0);
110 #endif
113 return TRUE;
117 /**************************************************************************
118 * Alloc [COMCTL32.71]
120 * Allocates memory block from the dll's private heap
122 * PARAMS
123 * dwSize [I] size of the allocated memory block
125 * RETURNS
126 * Success: pointer to allocated memory block
127 * Failure: NULL
130 LPVOID WINAPI
131 COMCTL32_Alloc (DWORD dwSize)
133 LPVOID lpPtr;
135 TRACE (commctrl, "(0x%lx)\n", dwSize);
137 lpPtr = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
139 TRACE (commctrl, "-- ret=%p\n", lpPtr);
141 return lpPtr;
145 /**************************************************************************
146 * ReAlloc [COMCTL32.72]
148 * Changes the size of an allocated memory block or allocates a memory
149 * block using the dll's private heap.
151 * PARAMS
152 * lpSrc [I] pointer to memory block which will be resized
153 * dwSize [I] new size of the memory block.
155 * RETURNS
156 * Success: pointer to the resized memory block
157 * Failure: NULL
159 * NOTES
160 * If lpSrc is a NULL-pointer, then COMCTL32_ReAlloc allocates a memory
161 * block like COMCTL32_Alloc.
164 LPVOID WINAPI
165 COMCTL32_ReAlloc (LPVOID lpSrc, DWORD dwSize)
167 LPVOID lpDest;
169 TRACE (commctrl, "(%p 0x%08lx)\n", lpSrc, dwSize);
171 if (lpSrc)
172 lpDest = HeapReAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, lpSrc, dwSize);
173 else
174 lpDest = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
176 TRACE (commctrl, "-- ret=%p\n", lpDest);
178 return lpDest;
182 /**************************************************************************
183 * Free [COMCTL32.73]
185 * Frees an allocated memory block from the dll's private heap.
187 * PARAMS
188 * lpMem [I] pointer to memory block which will be freed
190 * RETURNS
191 * Success: TRUE
192 * Failure: FALSE
195 BOOL WINAPI
196 COMCTL32_Free (LPVOID lpMem)
198 TRACE (commctrl, "(%p)\n", lpMem);
200 return HeapFree (COMCTL32_hHeap, 0, lpMem);
204 /**************************************************************************
205 * GetSize [COMCTL32.74]
207 * Retrieves the size of the specified memory block from the dll's
208 * private heap.
210 * PARAMS
211 * lpMem [I] pointer to an allocated memory block
213 * RETURNS
214 * Success: size of the specified memory block
215 * Failure: 0
218 DWORD WINAPI
219 COMCTL32_GetSize (LPVOID lpMem)
221 TRACE (commctrl, "(%p)\n", lpMem);
223 return HeapSize (COMCTL32_hHeap, 0, lpMem);
227 /**************************************************************************
228 * The MRU-API is a set of functions to manipulate MRU(Most Recently Used)
229 * lists.
234 typedef struct tagMRUINFO
236 DWORD dwParam1;
237 DWORD dwParam2;
238 DWORD dwParam3;
239 HKEY hkeyMain;
240 LPCSTR lpszSubKey;
241 DWORD dwParam6;
242 } MRUINFO, *LPMRUINFO;
245 typedef struct tagMRU
247 DWORD dwParam1; /* some kind of flag */
248 DWORD dwParam2;
249 DWORD dwParam3;
250 HKEY hkeyMRU;
251 LPCSTR lpszSubKey;
252 DWORD dwParam6;
253 } MRU, *HMRU;
255 LPVOID WINAPI
256 CreateMRUListLazyA (LPMRUINFO lpmi, DWORD dwParam2,
257 DWORD dwParam3, DWORD dwParam4);
260 /**************************************************************************
261 * CreateMRUListA [COMCTL32.151]
263 * PARAMS
264 * dwParam
266 * RETURNS
269 LPVOID WINAPI
270 CreateMRUListA (LPMRUINFO lpmi)
272 return CreateMRUListLazyA (lpmi, 0, 0, 0);
276 DWORD WINAPI
277 FreeMRUListA (HMRU hmru)
279 FIXME (commctrl, "(%p) empty stub!\n", hmru);
281 #if 0
282 if (!(hmru->dwParam1 & 1001)) {
283 RegSetValueExA (hmru->hKeyMRU, "MRUList", 0, REG_SZ,
284 hmru->lpszMRUString,
285 lstrlenA (hmru->lpszMRUString));
289 RegClosKey (hmru->hkeyMRU
290 COMCTL32_Free32 (hmru->lpszMRUString);
291 #endif
293 return COMCTL32_Free (hmru);
298 DWORD WINAPI
299 AddMRUData (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
302 FIXME (commctrl, "(%lx %lx %lx) empty stub!\n",
303 dwParam1, dwParam2, dwParam3);
305 return 0;
309 DWORD WINAPI
310 FindMRUData (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
313 FIXME (commctrl, "(%lx %lx %lx %lx) empty stub!\n",
314 dwParam1, dwParam2, dwParam3, dwParam4);
316 return TRUE;
320 LPVOID WINAPI
321 CreateMRUListLazyA (LPMRUINFO lpmi, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
323 /* DWORD dwLocal1; *
324 * HKEY hkeyResult; *
325 * DWORD dwLocal3; *
326 * LPVOID lMRU; *
327 * DWORD dwLocal5; *
328 * DWORD dwLocal6; *
329 * DWORD dwLocal7; *
330 * DWORD dwDisposition; */
332 /* internal variables */
333 LPVOID ptr;
335 FIXME (commctrl, "(%p) empty stub!\n", lpmi);
337 if (lpmi) {
338 FIXME (commctrl, "(%lx %lx %lx %lx \"%s\" %lx)\n",
339 lpmi->dwParam1, lpmi->dwParam2, lpmi->dwParam3,
340 (DWORD)lpmi->hkeyMain, lpmi->lpszSubKey, lpmi->dwParam6);
343 /* dummy pointer creation */
344 ptr = COMCTL32_Alloc (32);
346 FIXME (commctrl, "-- ret = %p\n", ptr);
348 return ptr;
354 /**************************************************************************
355 * Str_GetPtrA [COMCTL32.233]
357 * PARAMS
358 * lpSrc [I]
359 * lpDest [O]
360 * nMaxLen [I]
362 * RETURNS
365 INT WINAPI
366 Str_GetPtrA (LPCSTR lpSrc, LPSTR lpDest, INT nMaxLen)
368 INT len;
370 TRACE (commctrl, "(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
372 if (!lpDest && lpSrc)
373 return lstrlenA (lpSrc);
375 if (nMaxLen == 0)
376 return 0;
378 if (lpSrc == NULL) {
379 lpDest[0] = '\0';
380 return 0;
383 len = lstrlenA (lpSrc);
384 if (len >= nMaxLen)
385 len = nMaxLen - 1;
387 RtlMoveMemory (lpDest, lpSrc, len);
388 lpDest[len] = '\0';
390 return len;
394 /**************************************************************************
395 * Str_SetPtrA [COMCTL32.234]
397 * PARAMS
398 * lppDest [O]
399 * lpSrc [I]
401 * RETURNS
404 BOOL WINAPI
405 Str_SetPtrA (LPSTR *lppDest, LPCSTR lpSrc)
407 TRACE (commctrl, "(%p %p)\n", lppDest, lpSrc);
409 if (lpSrc) {
410 LPSTR ptr = COMCTL32_ReAlloc (*lppDest, lstrlenA (lpSrc) + 1);
411 if (!ptr)
412 return FALSE;
413 lstrcpyA (ptr, lpSrc);
414 *lppDest = ptr;
416 else {
417 if (*lppDest) {
418 COMCTL32_Free (*lppDest);
419 *lppDest = NULL;
423 return TRUE;
427 /**************************************************************************
428 * Str_GetPtrW [COMCTL32.235]
430 * PARAMS
431 * lpSrc [I]
432 * lpDest [O]
433 * nMaxLen [I]
435 * RETURNS
438 INT WINAPI
439 Str_GetPtrW (LPCWSTR lpSrc, LPWSTR lpDest, INT nMaxLen)
441 INT len;
443 TRACE (commctrl, "(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
445 if (!lpDest && lpSrc)
446 return lstrlenW (lpSrc);
448 if (nMaxLen == 0)
449 return 0;
451 if (lpSrc == NULL) {
452 lpDest[0] = L'\0';
453 return 0;
456 len = lstrlenW (lpSrc);
457 if (len >= nMaxLen)
458 len = nMaxLen - 1;
460 RtlMoveMemory (lpDest, lpSrc, len*sizeof(WCHAR));
461 lpDest[len] = L'\0';
463 return len;
467 /**************************************************************************
468 * Str_SetPtrW [COMCTL32.236]
470 * PARAMS
471 * lpDest [O]
472 * lpSrc [I]
474 * RETURNS
477 BOOL WINAPI
478 Str_SetPtrW (LPWSTR *lppDest, LPCWSTR lpSrc)
480 TRACE (commctrl, "(%p %p)\n", lppDest, lpSrc);
482 if (lpSrc) {
483 INT len = lstrlenW (lpSrc) + 1;
484 LPWSTR ptr = COMCTL32_ReAlloc (*lppDest, len * sizeof(WCHAR));
485 if (!ptr)
486 return FALSE;
487 lstrcpyW (ptr, lpSrc);
488 *lppDest = ptr;
490 else {
491 if (*lppDest) {
492 COMCTL32_Free (*lppDest);
493 *lppDest = NULL;
497 return TRUE;
501 /**************************************************************************
502 * The DSA-API is a set of functions to create and manipulate arrays of
503 * fix sized memory blocks. These arrays can store any kind of data
504 * (strings, icons...).
507 /**************************************************************************
508 * DSA_Create [COMCTL32.320] Creates a dynamic storage array
510 * PARAMS
511 * nSize [I] size of the array elements
512 * nGrow [I] number of elements by which the array grows when it is filled
514 * RETURNS
515 * Success: pointer to a array control structure. use this like a handle.
516 * Failure: NULL
519 HDSA WINAPI
520 DSA_Create (INT nSize, INT nGrow)
522 HDSA hdsa;
524 TRACE (commctrl, "(size=%d grow=%d)\n", nSize, nGrow);
526 hdsa = (HDSA)COMCTL32_Alloc (sizeof(DSA));
527 if (hdsa)
529 hdsa->nItemCount = 0;
530 hdsa->pData = NULL;
531 hdsa->nMaxCount = 0;
532 hdsa->nItemSize = nSize;
533 hdsa->nGrow = MAX(1, nGrow);
536 return hdsa;
540 /**************************************************************************
541 * DSA_Destroy [COMCTL32.321] Destroys a dynamic storage array
543 * PARAMS
544 * hdsa [I] pointer to the array control structure
546 * RETURNS
547 * Success: TRUE
548 * Failure: FALSE
551 BOOL WINAPI
552 DSA_Destroy (const HDSA hdsa)
554 TRACE (commctrl, "(%p)\n", hdsa);
556 if (!hdsa)
557 return FALSE;
559 if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
560 return FALSE;
562 return COMCTL32_Free (hdsa);
566 /**************************************************************************
567 * DSA_GetItem [COMCTL32.322]
569 * PARAMS
570 * hdsa [I] pointer to the array control structure
571 * nIndex [I] number of the Item to get
572 * pDest [O] destination buffer. Has to be >= dwElementSize.
574 * RETURNS
575 * Success: TRUE
576 * Failure: FALSE
579 BOOL WINAPI
580 DSA_GetItem (const HDSA hdsa, INT nIndex, LPVOID pDest)
582 LPVOID pSrc;
584 TRACE (commctrl, "(%p %d %p)\n", hdsa, nIndex, pDest);
586 if (!hdsa)
587 return FALSE;
588 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
589 return FALSE;
591 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
592 memmove (pDest, pSrc, hdsa->nItemSize);
594 return TRUE;
598 /**************************************************************************
599 * DSA_GetItemPtr [COMCTL32.323]
601 * Retrieves a pointer to the specified item.
603 * PARAMS
604 * hdsa [I] pointer to the array control structure
605 * nIndex [I] index of the desired item
607 * RETURNS
608 * Success: pointer to an item
609 * Failure: NULL
612 LPVOID WINAPI
613 DSA_GetItemPtr (const HDSA hdsa, INT nIndex)
615 LPVOID pSrc;
617 TRACE (commctrl, "(%p %d)\n", hdsa, nIndex);
619 if (!hdsa)
620 return NULL;
621 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
622 return NULL;
624 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
626 TRACE (commctrl, "-- ret=%p\n", pSrc);
628 return pSrc;
632 /**************************************************************************
633 * DSA_SetItem [COMCTL32.325]
635 * Sets the contents of an item in the array.
637 * PARAMS
638 * hdsa [I] pointer to the array control structure
639 * nIndex [I] index for the item
640 * pSrc [I] pointer to the new item data
642 * RETURNS
643 * Success: TRUE
644 * Failure: FALSE
647 BOOL WINAPI
648 DSA_SetItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
650 INT nSize, nNewItems;
651 LPVOID pDest, lpTemp;
653 TRACE (commctrl, "(%p %d %p)\n", hdsa, nIndex, pSrc);
655 if ((!hdsa) || nIndex < 0)
656 return FALSE;
658 if (hdsa->nItemCount <= nIndex) {
659 /* within the old array */
660 if (hdsa->nMaxCount > nIndex) {
661 /* within the allocated space, set a new boundary */
662 hdsa->nItemCount = nIndex + 1;
664 else {
665 /* resize the block of memory */
666 nNewItems =
667 hdsa->nGrow * ((INT)((nIndex - 1) / hdsa->nGrow) + 1);
668 nSize = hdsa->nItemSize * nNewItems;
670 lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
671 if (!lpTemp)
672 return FALSE;
674 hdsa->nMaxCount = nNewItems;
675 hdsa->nItemCount = nIndex + 1;
676 hdsa->pData = lpTemp;
680 /* put the new entry in */
681 pDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
682 TRACE (commctrl, "-- move dest=%p src=%p size=%d\n",
683 pDest, pSrc, hdsa->nItemSize);
684 memmove (pDest, pSrc, hdsa->nItemSize);
686 return TRUE;
690 /**************************************************************************
691 * DSA_InsertItem [COMCTL32.325]
693 * PARAMS
694 * hdsa [I] pointer to the array control structure
695 * nIndex [I] index for the new item
696 * pSrc [I] pointer to the element
698 * RETURNS
699 * Success: position of the new item
700 * Failure: -1
703 INT WINAPI
704 DSA_InsertItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
706 INT nNewItems, nSize, i;
707 LPVOID lpTemp, lpDest;
708 LPDWORD p;
710 TRACE(commctrl, "(%p %d %p)\n", hdsa, nIndex, pSrc);
712 if ((!hdsa) || nIndex < 0)
713 return -1;
715 for (i = 0; i < hdsa->nItemSize; i += 4) {
716 p = *(DWORD**)((char *) pSrc + i);
717 if (IsBadStringPtrA ((char*)p, 256))
718 TRACE (commctrl, "-- %d=%p\n", i, (DWORD*)p);
719 else
720 TRACE (commctrl, "-- %d=%p [%s]\n", i, p, debugstr_a((char*)p));
723 /* when nIndex > nItemCount then append */
724 if (nIndex >= hdsa->nItemCount)
725 nIndex = hdsa->nItemCount;
727 /* do we need to resize ? */
728 if (hdsa->nItemCount >= hdsa->nMaxCount) {
729 nNewItems = hdsa->nMaxCount + hdsa->nGrow;
730 nSize = hdsa->nItemSize * nNewItems;
732 lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
733 if (!lpTemp)
734 return -1;
736 hdsa->nMaxCount = nNewItems;
737 hdsa->pData = lpTemp;
740 /* do we need to move elements ? */
741 if (nIndex < hdsa->nItemCount) {
742 lpTemp = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
743 lpDest = (char *) lpTemp + hdsa->nItemSize;
744 nSize = (hdsa->nItemCount - nIndex) * hdsa->nItemSize;
745 TRACE (commctrl, "-- move dest=%p src=%p size=%d\n",
746 lpDest, lpTemp, nSize);
747 memmove (lpDest, lpTemp, nSize);
750 /* ok, we can put the new Item in */
751 hdsa->nItemCount++;
752 lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
753 TRACE (commctrl, "-- move dest=%p src=%p size=%d\n",
754 lpDest, pSrc, hdsa->nItemSize);
755 memmove (lpDest, pSrc, hdsa->nItemSize);
757 return hdsa->nItemCount;
761 /**************************************************************************
762 * DSA_DeleteItem [COMCTL32.326]
764 * PARAMS
765 * hdsa [I] pointer to the array control structure
766 * nIndex [I] index for the element to delete
768 * RETURNS
769 * Success: number of the deleted element
770 * Failure: -1
773 INT WINAPI
774 DSA_DeleteItem (const HDSA hdsa, INT nIndex)
776 LPVOID lpDest,lpSrc;
777 INT nSize;
779 TRACE (commctrl, "(%p %d)\n", hdsa, nIndex);
781 if (!hdsa)
782 return -1;
783 if (nIndex < 0 || nIndex >= hdsa->nItemCount)
784 return -1;
786 /* do we need to move ? */
787 if (nIndex < hdsa->nItemCount - 1) {
788 lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
789 lpSrc = (char *) lpDest + hdsa->nItemSize;
790 nSize = hdsa->nItemSize * (hdsa->nItemCount - nIndex - 1);
791 TRACE (commctrl, "-- move dest=%p src=%p size=%d\n",
792 lpDest, lpSrc, nSize);
793 memmove (lpDest, lpSrc, nSize);
796 hdsa->nItemCount--;
798 /* free memory ? */
799 if ((hdsa->nMaxCount - hdsa->nItemCount) >= hdsa->nGrow) {
800 nSize = hdsa->nItemSize * hdsa->nItemCount;
802 lpDest = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
803 if (!lpDest)
804 return -1;
806 hdsa->nMaxCount = hdsa->nItemCount;
807 hdsa->pData = lpDest;
810 return nIndex;
814 /**************************************************************************
815 * DSA_DeleteAllItems [COMCTL32.326]
817 * Removes all items and reinitializes the array.
819 * PARAMS
820 * hdsa [I] pointer to the array control structure
822 * RETURNS
823 * Success: TRUE
824 * Failure: FALSE
827 BOOL WINAPI
828 DSA_DeleteAllItems (const HDSA hdsa)
830 TRACE (commctrl, "(%p)\n", hdsa);
832 if (!hdsa)
833 return FALSE;
834 if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
835 return FALSE;
837 hdsa->nItemCount = 0;
838 hdsa->pData = NULL;
839 hdsa->nMaxCount = 0;
841 return TRUE;
845 /**************************************************************************
846 * The DPA-API is a set of functions to create and manipulate arrays of
847 * pointers.
850 /**************************************************************************
851 * DPA_Create [COMCTL32.328] Creates a dynamic pointer array
853 * PARAMS
854 * nGrow [I] number of items by which the array grows when it is filled
856 * RETURNS
857 * Success: handle (pointer) to the pointer array.
858 * Failure: NULL
861 HDPA WINAPI
862 DPA_Create (INT nGrow)
864 HDPA hdpa;
866 TRACE (commctrl, "(%d)\n", nGrow);
868 hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
869 if (hdpa) {
870 hdpa->nGrow = MAX(8, nGrow);
871 hdpa->hHeap = COMCTL32_hHeap;
872 hdpa->nMaxCount = hdpa->nGrow * 2;
873 hdpa->ptrs =
874 (LPVOID*)COMCTL32_Alloc (hdpa->nMaxCount * sizeof(LPVOID));
877 TRACE (commctrl, "-- %p\n", hdpa);
879 return hdpa;
883 /**************************************************************************
884 * DPA_Destroy [COMCTL32.329] Destroys a dynamic pointer array
886 * PARAMS
887 * hdpa [I] handle (pointer) to the pointer array
889 * RETURNS
890 * Success: TRUE
891 * Failure: FALSE
894 BOOL WINAPI
895 DPA_Destroy (const HDPA hdpa)
897 TRACE (commctrl, "(%p)\n", hdpa);
899 if (!hdpa)
900 return FALSE;
902 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
903 return FALSE;
905 return HeapFree (hdpa->hHeap, 0, hdpa);
909 /**************************************************************************
910 * DPA_Grow [COMCTL32.330]
912 * Sets the growth amount.
914 * PARAMS
915 * hdpa [I] handle (pointer) to the existing (source) pointer array
916 * nGrow [I] number of items, the array grows, when it's too small
918 * RETURNS
919 * Success: TRUE
920 * Failure: FALSE
923 BOOL WINAPI
924 DPA_Grow (const HDPA hdpa, INT nGrow)
926 TRACE (commctrl, "(%p %d)\n", hdpa, nGrow);
928 if (!hdpa)
929 return FALSE;
931 hdpa->nGrow = MAX(8, nGrow);
933 return TRUE;
937 /**************************************************************************
938 * DPA_Clone [COMCTL32.331]
940 * Copies a pointer array to an other one or creates a copy
942 * PARAMS
943 * hdpa [I] handle (pointer) to the existing (source) pointer array
944 * hdpaNew [O] handle (pointer) to the destination pointer array
946 * RETURNS
947 * Success: pointer to the destination pointer array.
948 * Failure: NULL
950 * NOTES
951 * - If the 'hdpaNew' is a NULL-Pointer, a copy of the source pointer
952 * array will be created and it's handle (pointer) is returned.
953 * - If 'hdpa' is a NULL-Pointer, the original implementation crashes,
954 * this implementation just returns NULL.
957 HDPA WINAPI
958 DPA_Clone (const HDPA hdpa, const HDPA hdpaNew)
960 INT nNewItems, nSize;
961 HDPA hdpaTemp;
963 if (!hdpa)
964 return NULL;
966 TRACE (commctrl, "(%p %p)\n", hdpa, hdpaNew);
968 if (!hdpaNew) {
969 /* create a new DPA */
970 hdpaTemp = (HDPA)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
971 sizeof(DPA));
972 hdpaTemp->hHeap = hdpa->hHeap;
973 hdpaTemp->nGrow = hdpa->nGrow;
975 else
976 hdpaTemp = hdpaNew;
978 if (hdpaTemp->ptrs) {
979 /* remove old pointer array */
980 HeapFree (hdpaTemp->hHeap, 0, hdpaTemp->ptrs);
981 hdpaTemp->ptrs = NULL;
982 hdpaTemp->nItemCount = 0;
983 hdpaTemp->nMaxCount = 0;
986 /* create a new pointer array */
987 nNewItems = hdpaTemp->nGrow *
988 ((INT)((hdpa->nItemCount - 1) / hdpaTemp->nGrow) + 1);
989 nSize = nNewItems * sizeof(LPVOID);
990 hdpaTemp->ptrs =
991 (LPVOID*)HeapAlloc (hdpaTemp->hHeap, HEAP_ZERO_MEMORY, nSize);
992 hdpaTemp->nMaxCount = nNewItems;
994 /* clone the pointer array */
995 hdpaTemp->nItemCount = hdpa->nItemCount;
996 memmove (hdpaTemp->ptrs, hdpa->ptrs,
997 hdpaTemp->nItemCount * sizeof(LPVOID));
999 return hdpaTemp;
1003 /**************************************************************************
1004 * DPA_GetPtr [COMCTL32.332]
1006 * Retrieves a pointer from a dynamic pointer array
1008 * PARAMS
1009 * hdpa [I] handle (pointer) to the pointer array
1010 * nIndex [I] array index of the desired pointer
1012 * RETURNS
1013 * Success: pointer
1014 * Failure: NULL
1017 LPVOID WINAPI
1018 DPA_GetPtr (const HDPA hdpa, INT i)
1020 TRACE (commctrl, "(%p %d)\n", hdpa, i);
1022 if (!hdpa)
1023 return NULL;
1024 if (!hdpa->ptrs)
1025 return NULL;
1026 if ((i < 0) || (i >= hdpa->nItemCount))
1027 return NULL;
1029 TRACE (commctrl, "-- %p\n", hdpa->ptrs[i]);
1031 return hdpa->ptrs[i];
1035 /**************************************************************************
1036 * DPA_GetPtrIndex [COMCTL32.333]
1038 * Retrieves the index of the specified pointer
1040 * PARAMS
1041 * hdpa [I] handle (pointer) to the pointer array
1042 * p [I] pointer
1044 * RETURNS
1045 * Success: index of the specified pointer
1046 * Failure: -1
1049 INT WINAPI
1050 DPA_GetPtrIndex (const HDPA hdpa, LPVOID p)
1052 INT i;
1054 if (!hdpa->ptrs)
1055 return -1;
1057 for (i = 0; i < hdpa->nItemCount; i++) {
1058 if (hdpa->ptrs[i] == p)
1059 return i;
1062 return -1;
1066 /**************************************************************************
1067 * DPA_InsertPtr [COMCTL32.334]
1069 * Inserts a pointer into a dynamic pointer array
1071 * PARAMS
1072 * hdpa [I] handle (pointer) to the array
1073 * i [I] array index
1074 * p [I] pointer to insert
1076 * RETURNS
1077 * Success: index of the inserted pointer
1078 * Failure: -1
1081 INT WINAPI
1082 DPA_InsertPtr (const HDPA hdpa, INT i, LPVOID p)
1084 INT nNewItems, nSize, nIndex = 0;
1085 LPVOID *lpTemp, *lpDest;
1087 TRACE (commctrl, "(%p %d %p)\n", hdpa, i, p);
1089 if ((!hdpa) || (i < 0))
1090 return -1;
1092 if (!hdpa->ptrs) {
1093 hdpa->ptrs =
1094 (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1095 2 * hdpa->nGrow * sizeof(LPVOID));
1096 if (!hdpa->ptrs)
1097 return -1;
1098 hdpa->nMaxCount = hdpa->nGrow * 2;
1099 nIndex = 0;
1101 else {
1102 if (hdpa->nItemCount >= hdpa->nMaxCount) {
1103 TRACE (commctrl, "-- resizing\n");
1104 nNewItems = hdpa->nMaxCount + hdpa->nGrow;
1105 nSize = nNewItems * sizeof(LPVOID);
1107 lpTemp = (LPVOID*)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1108 hdpa->ptrs, nSize);
1109 if (!lpTemp)
1110 return -1;
1111 hdpa->nMaxCount = nNewItems;
1112 hdpa->ptrs = lpTemp;
1115 if (i >= hdpa->nItemCount) {
1116 nIndex = hdpa->nItemCount;
1117 TRACE (commctrl, "-- appending at %d\n", nIndex);
1119 else {
1120 TRACE (commctrl, "-- inserting at %d\n", i);
1121 lpTemp = hdpa->ptrs + i;
1122 lpDest = lpTemp + 1;
1123 nSize = (hdpa->nItemCount - i) * sizeof(LPVOID);
1124 TRACE (commctrl, "-- move dest=%p src=%p size=%x\n",
1125 lpDest, lpTemp, nSize);
1126 memmove (lpDest, lpTemp, nSize);
1127 nIndex = i;
1131 /* insert item */
1132 hdpa->nItemCount++;
1133 hdpa->ptrs[nIndex] = p;
1135 return nIndex;
1139 /**************************************************************************
1140 * DPA_SetPtr [COMCTL32.335]
1142 * Sets a pointer in the pointer array
1144 * PARAMS
1145 * hdpa [I] handle (pointer) to the pointer array
1146 * i [I] index of the pointer that will be set
1147 * p [I] pointer to be set
1149 * RETURNS
1150 * Success: TRUE
1151 * Failure: FALSE
1154 BOOL WINAPI
1155 DPA_SetPtr (const HDPA hdpa, INT i, LPVOID p)
1157 LPVOID *lpTemp;
1159 TRACE (commctrl, "(%p %d %p)\n", hdpa, i, p);
1161 if ((!hdpa) || i < 0)
1162 return FALSE;
1164 if (hdpa->nItemCount <= i) {
1165 /* within the old array */
1166 if (hdpa->nMaxCount > i) {
1167 /* within the allocated space, set a new boundary */
1168 hdpa->nItemCount = i;
1170 else {
1171 /* resize the block of memory */
1172 INT nNewItems =
1173 hdpa->nGrow * ((INT)((i - 1) / hdpa->nGrow) + 1);
1174 INT nSize = nNewItems * sizeof(LPVOID);
1176 lpTemp = (LPVOID*)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1177 hdpa->ptrs, nSize);
1178 if (!lpTemp)
1179 return FALSE;
1181 hdpa->nItemCount = nNewItems;
1182 hdpa->ptrs = lpTemp;
1186 /* put the new entry in */
1187 hdpa->ptrs[i] = p;
1189 return TRUE;
1193 /**************************************************************************
1194 * DPA_DeletePtr [COMCTL32.336]
1196 * Removes a pointer from the pointer array.
1198 * PARAMS
1199 * hdpa [I] handle (pointer) to the pointer array
1200 * i [I] index of the pointer that will be deleted
1202 * RETURNS
1203 * Success: deleted pointer
1204 * Failure: NULL
1207 LPVOID WINAPI
1208 DPA_DeletePtr (const HDPA hdpa, INT i)
1210 LPVOID *lpDest, *lpSrc, lpTemp = NULL;
1211 INT nSize;
1213 TRACE (commctrl, "(%p %d)\n", hdpa, i);
1215 if ((!hdpa) || i < 0 || i >= hdpa->nItemCount)
1216 return NULL;
1218 lpTemp = hdpa->ptrs[i];
1220 /* do we need to move ?*/
1221 if (i < hdpa->nItemCount - 1) {
1222 lpDest = hdpa->ptrs + i;
1223 lpSrc = lpDest + 1;
1224 nSize = (hdpa->nItemCount - i - 1) * sizeof(LPVOID);
1225 TRACE (commctrl,"-- move dest=%p src=%p size=%x\n",
1226 lpDest, lpSrc, nSize);
1227 memmove (lpDest, lpSrc, nSize);
1230 hdpa->nItemCount --;
1232 /* free memory ?*/
1233 if ((hdpa->nMaxCount - hdpa->nItemCount) >= hdpa->nGrow) {
1234 INT nNewItems = MIN(hdpa->nGrow * 2, hdpa->nItemCount);
1235 nSize = nNewItems * sizeof(LPVOID);
1236 lpDest = (LPVOID)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1237 hdpa->ptrs, nSize);
1238 if (!lpDest)
1239 return NULL;
1241 hdpa->nMaxCount = nNewItems;
1242 hdpa->ptrs = (LPVOID*)lpDest;
1245 return lpTemp;
1249 /**************************************************************************
1250 * DPA_DeleteAllPtrs [COMCTL32.337]
1252 * Removes all pointers and reinitializes the array.
1254 * PARAMS
1255 * hdpa [I] handle (pointer) to the pointer array
1257 * RETURNS
1258 * Success: TRUE
1259 * Failure: FALSE
1262 BOOL WINAPI
1263 DPA_DeleteAllPtrs (const HDPA hdpa)
1265 TRACE (commctrl, "(%p)\n", hdpa);
1267 if (!hdpa)
1268 return FALSE;
1270 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
1271 return FALSE;
1273 hdpa->nItemCount = 0;
1274 hdpa->nMaxCount = hdpa->nGrow * 2;
1275 hdpa->ptrs = (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1276 hdpa->nMaxCount * sizeof(LPVOID));
1278 return TRUE;
1282 /**************************************************************************
1283 * DPA_QuickSort [Internal]
1285 * Ordinary quicksort (used by DPA_Sort).
1287 * PARAMS
1288 * lpPtrs [I] pointer to the pointer array
1289 * l [I] index of the "left border" of the partition
1290 * r [I] index of the "right border" of the partition
1291 * pfnCompare [I] pointer to the compare function
1292 * lParam [I] user defined value (3rd parameter in compare function)
1294 * RETURNS
1295 * NONE
1298 static VOID
1299 DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r,
1300 PFNDPACOMPARE pfnCompare, LPARAM lParam)
1302 LPVOID t, v;
1303 INT i, j;
1305 TRACE (commctrl, "l=%i r=%i\n", l, r);
1307 i = l;
1308 j = r;
1309 v = lpPtrs[(int)(l+r)/2];
1310 do {
1311 while ((pfnCompare)(lpPtrs[i], v, lParam) > 0) i++;
1312 while ((pfnCompare)(lpPtrs[j], v, lParam) < 0) j--;
1313 if (i <= j)
1315 t = lpPtrs[i];
1316 lpPtrs[i++] = lpPtrs[j];
1317 lpPtrs[j--] = t;
1319 } while (i <= j);
1320 if (l < j) DPA_QuickSort (lpPtrs, l, j, pfnCompare, lParam);
1321 if (i < r) DPA_QuickSort (lpPtrs, i, r, pfnCompare, lParam);
1325 /**************************************************************************
1326 * DPA_Sort [COMCTL32.338]
1328 * Sorts a pointer array using a user defined compare function
1330 * PARAMS
1331 * hdpa [I] handle (pointer) to the pointer array
1332 * pfnCompare [I] pointer to the compare function
1333 * lParam [I] user defined value (3rd parameter of compare function)
1335 * RETURNS
1336 * Success: TRUE
1337 * Failure: FALSE
1340 BOOL WINAPI
1341 DPA_Sort (const HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam)
1343 if (!hdpa || !pfnCompare)
1344 return FALSE;
1346 TRACE (commctrl, "(%p %p 0x%lx)\n", hdpa, pfnCompare, lParam);
1348 if ((hdpa->nItemCount > 1) && (hdpa->ptrs))
1349 DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1,
1350 pfnCompare, lParam);
1352 return TRUE;
1356 /**************************************************************************
1357 * DPA_Search [COMCTL32.339]
1359 * Searches a pointer array for a specified pointer
1361 * PARAMS
1362 * hdpa [I] handle (pointer) to the pointer array
1363 * pFind [I] pointer to search for
1364 * nStart [I] start index
1365 * pfnCompare [I] pointer to the compare function
1366 * lParam [I] user defined value (3rd parameter of compare function)
1367 * uOptions [I] search options
1369 * RETURNS
1370 * Success: index of the pointer in the array.
1371 * Failure: -1
1373 * NOTES
1374 * Binary search taken from R.Sedgewick "Algorithms in C"!
1375 * Function is NOT tested!
1376 * If something goes wrong, blame HIM not ME! (Eric Kohl)
1379 INT WINAPI
1380 DPA_Search (const HDPA hdpa, LPVOID pFind, INT nStart,
1381 PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions)
1383 if (!hdpa || !pfnCompare || !pFind)
1384 return -1;
1386 TRACE (commctrl, "(%p %p %d %p 0x%08lx 0x%08x)\n",
1387 hdpa, pFind, nStart, pfnCompare, lParam, uOptions);
1389 if (uOptions & DPAS_SORTED) {
1390 /* array is sorted --> use binary search */
1391 INT l, r, x, n;
1392 LPVOID *lpPtr;
1394 TRACE (commctrl, "binary search\n");
1396 l = (nStart == -1) ? 0 : nStart;
1397 r = hdpa->nItemCount - 1;
1398 lpPtr = hdpa->ptrs;
1399 while (r >= l) {
1400 x = (l + r) / 2;
1401 n = (pfnCompare)(pFind, lpPtr[x], lParam);
1402 if (n < 0)
1403 r = x - 1;
1404 else
1405 l = x + 1;
1406 if (n == 0) {
1407 TRACE (commctrl, "-- ret=%d\n", n);
1408 return n;
1412 if (uOptions & DPAS_INSERTBEFORE) {
1413 TRACE (commctrl, "-- ret=%d\n", r);
1414 return r;
1417 if (uOptions & DPAS_INSERTAFTER) {
1418 TRACE (commctrl, "-- ret=%d\n", l);
1419 return l;
1422 else {
1423 /* array is not sorted --> use linear search */
1424 LPVOID *lpPtr;
1425 INT nIndex;
1427 TRACE (commctrl, "linear search\n");
1429 nIndex = (nStart == -1)? 0 : nStart;
1430 lpPtr = hdpa->ptrs;
1431 for (; nIndex < hdpa->nItemCount; nIndex++) {
1432 if ((pfnCompare)(pFind, lpPtr[nIndex], lParam) == 0) {
1433 TRACE (commctrl, "-- ret=%d\n", nIndex);
1434 return nIndex;
1439 TRACE (commctrl, "-- not found: ret=-1\n");
1440 return -1;
1444 /**************************************************************************
1445 * DPA_CreateEx [COMCTL32.340]
1447 * Creates a dynamic pointer array using the specified size and heap.
1449 * PARAMS
1450 * nGrow [I] number of items by which the array grows when it is filled
1451 * hHeap [I] handle to the heap where the array is stored
1453 * RETURNS
1454 * Success: handle (pointer) to the pointer array.
1455 * Failure: NULL
1458 HDPA WINAPI
1459 DPA_CreateEx (INT nGrow, HANDLE hHeap)
1461 HDPA hdpa;
1463 TRACE (commctrl, "(%d 0x%x)\n", nGrow, hHeap);
1465 if (hHeap)
1466 hdpa = (HDPA)HeapAlloc (hHeap, HEAP_ZERO_MEMORY, sizeof(DPA));
1467 else
1468 hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
1470 if (hdpa) {
1471 hdpa->nGrow = MIN(8, nGrow);
1472 hdpa->hHeap = hHeap ? hHeap : COMCTL32_hHeap;
1473 hdpa->nMaxCount = hdpa->nGrow * 2;
1474 hdpa->ptrs =
1475 (LPVOID*)HeapAlloc (hHeap, HEAP_ZERO_MEMORY,
1476 hdpa->nMaxCount * sizeof(LPVOID));
1479 TRACE (commctrl, "-- %p\n", hdpa);
1481 return hdpa;
1485 /**************************************************************************
1486 * Notification functions
1489 typedef struct tagNOTIFYDATA
1491 HWND hwndFrom;
1492 HWND hwndTo;
1493 DWORD dwParam3;
1494 DWORD dwParam4;
1495 DWORD dwParam5;
1496 DWORD dwParam6;
1497 } NOTIFYDATA, *LPNOTIFYDATA;
1500 /**************************************************************************
1501 * DoNotify [Internal]
1504 static LRESULT
1505 DoNotify (LPNOTIFYDATA lpNotify, UINT uCode, LPNMHDR lpHdr)
1507 NMHDR nmhdr;
1508 LPNMHDR lpNmh = NULL;
1509 UINT idFrom = 0;
1511 TRACE (commctrl, "(0x%04x 0x%04x %d %p 0x%08lx)\n",
1512 lpNotify->hwndFrom, lpNotify->hwndTo, uCode, lpHdr,
1513 lpNotify->dwParam5);
1515 if (!lpNotify->hwndTo)
1516 return 0;
1518 if (lpNotify->hwndFrom == -1) {
1519 lpNmh = lpHdr;
1520 idFrom = lpHdr->idFrom;
1522 else {
1523 if (lpNotify->hwndFrom) {
1524 HWND hwndParent = GetParent (lpNotify->hwndFrom);
1525 if (hwndParent) {
1526 hwndParent = GetWindow (lpNotify->hwndFrom, GW_OWNER);
1527 if (hwndParent)
1528 idFrom = GetDlgCtrlID (lpNotify->hwndFrom);
1532 lpNmh = (lpHdr) ? lpHdr : &nmhdr;
1534 lpNmh->hwndFrom = lpNotify->hwndFrom;
1535 lpNmh->idFrom = idFrom;
1536 lpNmh->code = uCode;
1539 return SendMessageA (lpNotify->hwndTo, WM_NOTIFY, idFrom, (LPARAM)lpNmh);
1543 /**************************************************************************
1544 * SendNotify [COMCTL32.341]
1546 * PARAMS
1547 * hwndFrom [I]
1548 * hwndTo [I]
1549 * uCode [I]
1550 * lpHdr [I]
1552 * RETURNS
1553 * Success: return value from notification
1554 * Failure: 0
1557 LRESULT WINAPI
1558 COMCTL32_SendNotify (HWND hwndFrom, HWND hwndTo,
1559 UINT uCode, LPNMHDR lpHdr)
1561 NOTIFYDATA notify;
1563 TRACE (commctrl, "(0x%04x 0x%04x %d %p)\n",
1564 hwndFrom, hwndTo, uCode, lpHdr);
1566 notify.hwndFrom = hwndFrom;
1567 notify.hwndTo = hwndTo;
1568 notify.dwParam5 = 0;
1569 notify.dwParam6 = 0;
1571 return DoNotify (&notify, uCode, lpHdr);
1575 /**************************************************************************
1576 * SendNotifyEx [COMCTL32.342]
1578 * PARAMS
1579 * hwndFrom [I]
1580 * hwndTo [I]
1581 * uCode [I]
1582 * lpHdr [I]
1583 * dwParam5 [I]
1585 * RETURNS
1586 * Success: return value from notification
1587 * Failure: 0
1590 LRESULT WINAPI
1591 COMCTL32_SendNotifyEx (HWND hwndTo, HWND hwndFrom, UINT uCode,
1592 LPNMHDR lpHdr, DWORD dwParam5)
1594 NOTIFYDATA notify;
1595 HWND hwndNotify;
1597 TRACE (commctrl, "(0x%04x 0x%04x %d %p 0x%08lx)\n",
1598 hwndFrom, hwndTo, uCode, lpHdr, dwParam5);
1600 hwndNotify = hwndTo;
1601 if (!hwndTo) {
1602 if (IsWindow (hwndFrom)) {
1603 hwndNotify = GetParent (hwndFrom);
1604 if (!hwndNotify)
1605 return 0;
1609 notify.hwndFrom = hwndFrom;
1610 notify.hwndTo = hwndNotify;
1611 notify.dwParam5 = dwParam5;
1612 notify.dwParam6 = 0;
1614 return DoNotify (&notify, uCode, lpHdr);
1618 /**************************************************************************
1619 * StrChrA [COMCTL32.350]
1623 LPSTR WINAPI
1624 COMCTL32_StrChrA (LPCSTR lpString, CHAR cChar)
1626 return strchr (lpString, cChar);
1630 /**************************************************************************
1631 * StrStrIA [COMCTL32.355]
1634 LPSTR WINAPI
1635 COMCTL32_StrStrIA (LPCSTR lpStr1, LPCSTR lpStr2)
1637 INT len1, len2, i;
1638 CHAR first;
1640 if (*lpStr2 == 0)
1641 return ((LPSTR)lpStr1);
1642 len1 = 0;
1643 while (lpStr1[len1] != 0) ++len1;
1644 len2 = 0;
1645 while (lpStr2[len2] != 0) ++len2;
1646 if (len2 == 0)
1647 return ((LPSTR)(lpStr1 + len1));
1648 first = tolower (*lpStr2);
1649 while (len1 >= len2) {
1650 if (tolower(*lpStr1) == first) {
1651 for (i = 1; i < len2; ++i)
1652 if (tolower (lpStr1[i]) != tolower(lpStr2[i]))
1653 break;
1654 if (i >= len2)
1655 return ((LPSTR)lpStr1);
1657 ++lpStr1; --len1;
1659 return (NULL);
1663 /**************************************************************************
1664 * StrToIntA [COMCTL32.357] Converts a string to a signed integer.
1667 INT WINAPI
1668 COMCTL32_StrToIntA (LPSTR lpString)
1670 return atoi(lpString);
1674 /**************************************************************************
1675 * DPA_EnumCallback [COMCTL32.385]
1677 * Enumerates all items in a dynamic pointer array.
1679 * PARAMS
1680 * hdpa [I] handle to the dynamic pointer array
1681 * enumProc [I]
1682 * lParam [I]
1684 * RETURNS
1685 * none
1688 VOID WINAPI
1689 DPA_EnumCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
1691 INT i;
1693 TRACE (commctrl, "(%p %p %08lx)\n", hdpa, enumProc, lParam);
1695 if (!hdpa)
1696 return;
1697 if (hdpa->nItemCount <= 0)
1698 return;
1700 for (i = 0; i < hdpa->nItemCount; i++) {
1701 if ((enumProc)(hdpa->ptrs[i], lParam) == 0)
1702 return;
1705 return;
1709 /**************************************************************************
1710 * DPA_DestroyCallback [COMCTL32.386]
1712 * Enumerates all items in a dynamic pointer array and destroys it.
1714 * PARAMS
1715 * hdpa [I] handle to the dynamic pointer array
1716 * enumProc [I]
1717 * lParam [I]
1719 * RETURNS
1720 * Success: TRUE
1721 * Failure: FALSE
1724 BOOL WINAPI
1725 DPA_DestroyCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
1727 TRACE (commctrl, "(%p %p %08lx)\n", hdpa, enumProc, lParam);
1729 DPA_EnumCallback (hdpa, enumProc, lParam);
1731 return DPA_Destroy (hdpa);
1735 /**************************************************************************
1736 * DSA_EnumCallback [COMCTL32.387]
1738 * Enumerates all items in a dynamic storage array.
1740 * PARAMS
1741 * hdsa [I] handle to the dynamic storage array
1742 * enumProc [I]
1743 * lParam [I]
1745 * RETURNS
1746 * none
1749 VOID WINAPI
1750 DSA_EnumCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
1752 INT i;
1754 TRACE (commctrl, "(%p %p %08lx)\n", hdsa, enumProc, lParam);
1756 if (!hdsa)
1757 return;
1758 if (hdsa->nItemCount <= 0)
1759 return;
1761 for (i = 0; i < hdsa->nItemCount; i++) {
1762 LPVOID lpItem = DSA_GetItemPtr (hdsa, i);
1763 if ((enumProc)(lpItem, lParam) == 0)
1764 return;
1767 return;
1771 /**************************************************************************
1772 * DSA_DestroyCallback [COMCTL32.388]
1774 * Enumerates all items in a dynamic storage array and destroys it.
1776 * PARAMS
1777 * hdsa [I] handle to the dynamic storage array
1778 * enumProc [I]
1779 * lParam [I]
1781 * RETURNS
1782 * Success: TRUE
1783 * Failure: FALSE
1786 BOOL WINAPI
1787 DSA_DestroyCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
1789 TRACE (commctrl, "(%p %p %08lx)\n", hdsa, enumProc, lParam);
1791 DSA_EnumCallback (hdsa, enumProc, lParam);
1793 return DSA_Destroy (hdsa);
1796 /**************************************************************************
1797 * StrCSpnA [COMCTL32.356]
1800 INT WINAPI COMCTL32_StrCSpnA( LPCSTR lpStr, LPCSTR lpSet) {
1801 return strcspn(lpStr, lpSet);
1804 /**************************************************************************
1805 * StrChrW [COMCTL32.358]
1808 LPWSTR WINAPI COMCTL32_StrChrW( LPCWSTR lpStart, WORD wMatch) {
1809 return CRTDLL_wcschr(lpStart, wMatch);
1812 /**************************************************************************
1813 * StrCmpNA [COMCTL32.352]
1816 INT WINAPI COMCTL32_StrCmpNA( LPCSTR lpStr1, LPCSTR lpStr2, int nChar) {
1817 return lstrncmpA(lpStr1, lpStr2, nChar);
1820 /**************************************************************************
1821 * StrCmpNW [COMCTL32.360]
1824 INT WINAPI COMCTL32_StrCmpNW( LPCWSTR lpStr1, LPCWSTR lpStr2, int nChar) {
1825 return lstrncmpW(lpStr1, lpStr2, nChar);
1828 /**************************************************************************
1829 * StrRChrA [COMCTL32.351]
1832 LPSTR WINAPI COMCTL32_StrRChrA( LPCSTR lpStart, LPCSTR lpEnd, WORD wMatch) {
1833 return lstrrchr(lpStart, lpEnd, wMatch);
1836 /**************************************************************************
1837 * StrRChrW [COMCTL32.359]
1840 LPWSTR WINAPI COMCTL32_StrRChrW( LPCWSTR lpStart, LPCWSTR lpEnd, WORD wMatch) {
1841 return lstrrchrw(lpStart, lpEnd, wMatch);
1844 /**************************************************************************
1845 * StrStrA [COMCTL32.354]
1848 LPSTR WINAPI COMCTL32_StrStrA( LPCSTR lpFirst, LPCSTR lpSrch) {
1849 return strstr(lpFirst, lpSrch);
1852 /**************************************************************************
1853 * StrStrW [COMCTL32.362]
1856 LPWSTR WINAPI COMCTL32_StrStrW( LPCWSTR lpFirst, LPCWSTR lpSrch) {
1857 return strstrw(lpFirst, lpSrch);
1860 /**************************************************************************
1861 * StrSpnW [COMCTL32.364]
1864 INT WINAPI COMCTL32_StrSpnW( LPWSTR lpStr, LPWSTR lpSet) {
1865 LPWSTR lpLoop = lpStr;
1867 /* validate ptr */
1868 if ((lpStr == 0) || (lpSet == 0)) return 0;
1870 /* while(*lpLoop) { if lpLoop++; } */
1872 for(; (*lpLoop != 0); lpLoop++)
1873 if( CRTDLL_wcschr(lpSet, *(WORD*)lpLoop))
1874 return (INT)(lpLoop-lpStr);
1876 return (INT)(lpLoop-lpStr);
1879 /*************************************************************************
1880 * DPA_LoadStream [COMCTL32.9]
1882 * NOTE: Ordinal is only accurate for Win98 / IE 4 and later
1885 DWORD WINAPI DPA_LoadStream(HDPA *hDpa, DWORD pfnDpaLoadCallback, DWORD param3, DWORD param4)
1887 FIXME(commctrl, "(%p %lx %lx %lx): partial stub!\n", hDpa, pfnDpaLoadCallback, param3, param4);
1889 *hDpa = DPA_Create(8);
1891 return(0);
1894 /************************************************************************
1895 * DPA_SaveStream [COMCTL32.10]
1897 * NOTE: Ordinal is only accurate for Win98 / IE 4 and later
1900 DWORD WINAPI DPA_SaveStream(DWORD param1, DWORD param2, DWORD param3, DWORD param4)
1902 FIXME(commctrl, "(%lx %lx %lx %lx): stub!\n", param1, param2, param3, param4);
1904 return(0);