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

Last change on this file since 2635 was 2635, checked in by cbratschi, 26 years ago

merged with WINE20000130

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