xref: /reactos/dll/win32/comctl32/dpa.c (revision b3fb8555)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * Dynamic pointer array (DPA) implementation
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * Copyright 1998 Eric Kohl
5c2c66affSColin Finck  *           1998 Juergen Schmied <j.schmied@metronet.de>
6c2c66affSColin Finck  *           2000 Eric Kohl for CodeWeavers
7c2c66affSColin Finck  *
8c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
9c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
10c2c66affSColin Finck  * License as published by the Free Software Foundation; either
11c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
12c2c66affSColin Finck  *
13c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
14c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16c2c66affSColin Finck  * Lesser General Public License for more details.
17c2c66affSColin Finck  *
18c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
19c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
20c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21c2c66affSColin Finck  *
22c2c66affSColin Finck  * NOTES
23c2c66affSColin Finck  *     These functions were involuntarily documented by Microsoft in 2002 as
24c2c66affSColin Finck  *     the outcome of an anti-trust suit brought by various U.S. governments.
25c2c66affSColin Finck  *     As a result the specifications on MSDN are inaccurate, incomplete
26c2c66affSColin Finck  *     and misleading. A much more complete (unofficial) documentation is
27c2c66affSColin Finck  *     available at:
28c2c66affSColin Finck  *
29c2c66affSColin Finck  *     http://members.ozemail.com.au/~geoffch/samples/win32/shell/comctl32
30c2c66affSColin Finck  */
31c2c66affSColin Finck 
32*b3fb8555SGiannis Adamopoulos #define COBJMACROS
33*b3fb8555SGiannis Adamopoulos 
34*b3fb8555SGiannis Adamopoulos #include <stdarg.h>
35*b3fb8555SGiannis Adamopoulos #include <limits.h>
36*b3fb8555SGiannis Adamopoulos 
37*b3fb8555SGiannis Adamopoulos #include "windef.h"
38*b3fb8555SGiannis Adamopoulos #include "winbase.h"
39*b3fb8555SGiannis Adamopoulos #include "winuser.h"
40*b3fb8555SGiannis Adamopoulos #include "commctrl.h"
41*b3fb8555SGiannis Adamopoulos #include "objbase.h"
42*b3fb8555SGiannis Adamopoulos 
43c2c66affSColin Finck #include "comctl32.h"
44*b3fb8555SGiannis Adamopoulos #include "wine/debug.h"
45c2c66affSColin Finck 
46c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(dpa);
47c2c66affSColin Finck 
48c2c66affSColin Finck typedef struct _DPA
49c2c66affSColin Finck {
50c2c66affSColin Finck     INT    nItemCount;
51c2c66affSColin Finck     LPVOID   *ptrs;
52c2c66affSColin Finck     HANDLE hHeap;
53c2c66affSColin Finck     INT    nGrow;
54c2c66affSColin Finck     INT    nMaxCount;
55c2c66affSColin Finck } DPA;
56c2c66affSColin Finck 
57c2c66affSColin Finck typedef struct _STREAMDATA
58c2c66affSColin Finck {
59c2c66affSColin Finck     DWORD dwSize;
60c2c66affSColin Finck     DWORD dwData2;
61c2c66affSColin Finck     DWORD dwItems;
62c2c66affSColin Finck } STREAMDATA, *PSTREAMDATA;
63c2c66affSColin Finck 
64c2c66affSColin Finck /**************************************************************************
65c2c66affSColin Finck  * DPA_LoadStream [COMCTL32.9]
66c2c66affSColin Finck  *
67c2c66affSColin Finck  * Loads a dynamic pointer array from a stream
68c2c66affSColin Finck  *
69c2c66affSColin Finck  * PARAMS
70c2c66affSColin Finck  *     phDpa    [O] pointer to a handle to a dynamic pointer array
71c2c66affSColin Finck  *     loadProc [I] pointer to a callback function
72c2c66affSColin Finck  *     pStream  [I] pointer to a stream
73c2c66affSColin Finck  *     pData    [I] pointer to callback data
74c2c66affSColin Finck  *
75c2c66affSColin Finck  * RETURNS
76c2c66affSColin Finck  *     Success: S_OK, S_FALSE - partial success
77c2c66affSColin Finck  *     Failure: HRESULT error code
78c2c66affSColin Finck  *
79c2c66affSColin Finck  * NOTES
80c2c66affSColin Finck  *     No more information available yet!
81c2c66affSColin Finck  */
DPA_LoadStream(HDPA * phDpa,PFNDPASTREAM loadProc,IStream * pStream,LPVOID pData)82c2c66affSColin Finck HRESULT WINAPI DPA_LoadStream (HDPA *phDpa, PFNDPASTREAM loadProc,
83c2c66affSColin Finck                                IStream *pStream, LPVOID pData)
84c2c66affSColin Finck {
85c2c66affSColin Finck     HRESULT errCode;
86c2c66affSColin Finck     LARGE_INTEGER position;
87c2c66affSColin Finck     ULARGE_INTEGER initial_pos;
88c2c66affSColin Finck     STREAMDATA  streamData;
89c2c66affSColin Finck     DPASTREAMINFO streamInfo;
90c2c66affSColin Finck     ULONG ulRead;
91c2c66affSColin Finck     HDPA hDpa;
92c2c66affSColin Finck     PVOID *ptr;
93c2c66affSColin Finck 
94c2c66affSColin Finck     TRACE ("phDpa=%p loadProc=%p pStream=%p pData=%p\n",
95c2c66affSColin Finck            phDpa, loadProc, pStream, pData);
96c2c66affSColin Finck 
97c2c66affSColin Finck     if (!phDpa || !loadProc || !pStream)
98c2c66affSColin Finck         return E_INVALIDARG;
99c2c66affSColin Finck 
100c2c66affSColin Finck     *phDpa = NULL;
101c2c66affSColin Finck 
102c2c66affSColin Finck     position.QuadPart = 0;
103c2c66affSColin Finck 
104c2c66affSColin Finck     errCode = IStream_Seek (pStream, position, STREAM_SEEK_CUR, &initial_pos);
105c2c66affSColin Finck     if (errCode != S_OK)
106c2c66affSColin Finck         return errCode;
107c2c66affSColin Finck 
108c2c66affSColin Finck     memset(&streamData, 0, sizeof(STREAMDATA));
109c2c66affSColin Finck     errCode = IStream_Read (pStream, &streamData, sizeof(STREAMDATA), &ulRead);
110c2c66affSColin Finck     if (errCode != S_OK)
111c2c66affSColin Finck         return errCode;
112c2c66affSColin Finck 
113c2c66affSColin Finck     TRACE ("dwSize=%u dwData2=%u dwItems=%u\n",
114c2c66affSColin Finck            streamData.dwSize, streamData.dwData2, streamData.dwItems);
115c2c66affSColin Finck 
116c2c66affSColin Finck     if (ulRead < sizeof(STREAMDATA) ||
117c2c66affSColin Finck         streamData.dwSize < sizeof(STREAMDATA) || streamData.dwData2 != 1) {
118c2c66affSColin Finck         /* back to initial position */
119c2c66affSColin Finck         position.QuadPart = initial_pos.QuadPart;
120c2c66affSColin Finck         IStream_Seek (pStream, position, STREAM_SEEK_SET, NULL);
121c2c66affSColin Finck         return E_FAIL;
122c2c66affSColin Finck     }
123c2c66affSColin Finck 
124c2c66affSColin Finck     if (streamData.dwItems > (UINT_MAX / 2 / sizeof(VOID*))) /* 536870911 */
125c2c66affSColin Finck         return E_OUTOFMEMORY;
126c2c66affSColin Finck 
127c2c66affSColin Finck     /* create the dpa */
128c2c66affSColin Finck     hDpa = DPA_Create (streamData.dwItems);
129c2c66affSColin Finck     if (!hDpa)
130c2c66affSColin Finck         return E_OUTOFMEMORY;
131c2c66affSColin Finck 
132c2c66affSColin Finck     if (!DPA_Grow (hDpa, streamData.dwItems)) {
133c2c66affSColin Finck         DPA_Destroy (hDpa);
134c2c66affSColin Finck         return E_OUTOFMEMORY;
135c2c66affSColin Finck     }
136c2c66affSColin Finck 
137c2c66affSColin Finck     /* load data from the stream into the dpa */
138c2c66affSColin Finck     ptr = hDpa->ptrs;
139c2c66affSColin Finck     for (streamInfo.iPos = 0; streamInfo.iPos < streamData.dwItems; streamInfo.iPos++) {
140c2c66affSColin Finck         errCode = (loadProc)(&streamInfo, pStream, pData);
141c2c66affSColin Finck         if (errCode != S_OK) {
142c2c66affSColin Finck             errCode = S_FALSE;
143c2c66affSColin Finck             break;
144c2c66affSColin Finck         }
145c2c66affSColin Finck 
146c2c66affSColin Finck         *ptr = streamInfo.pvItem;
147c2c66affSColin Finck         ptr++;
148c2c66affSColin Finck     }
149c2c66affSColin Finck 
150c2c66affSColin Finck     /* set the number of items */
151c2c66affSColin Finck     hDpa->nItemCount = streamInfo.iPos;
152c2c66affSColin Finck 
153c2c66affSColin Finck     /* store the handle to the dpa */
154c2c66affSColin Finck     *phDpa = hDpa;
155c2c66affSColin Finck     TRACE ("new hDpa=%p, errorcode=%x\n", hDpa, errCode);
156c2c66affSColin Finck 
157c2c66affSColin Finck     return errCode;
158c2c66affSColin Finck }
159c2c66affSColin Finck 
160c2c66affSColin Finck 
161c2c66affSColin Finck /**************************************************************************
162c2c66affSColin Finck  * DPA_SaveStream [COMCTL32.10]
163c2c66affSColin Finck  *
164c2c66affSColin Finck  * Saves a dynamic pointer array to a stream
165c2c66affSColin Finck  *
166c2c66affSColin Finck  * PARAMS
167c2c66affSColin Finck  *     hDpa     [I] handle to a dynamic pointer array
168c2c66affSColin Finck  *     saveProc [I] pointer to a callback function
169c2c66affSColin Finck  *     pStream  [I] pointer to a stream
170c2c66affSColin Finck  *     pData    [I] pointer to callback data
171c2c66affSColin Finck  *
172c2c66affSColin Finck  * RETURNS
173c2c66affSColin Finck  *     Success: S_OK, S_FALSE - partial success
174c2c66affSColin Finck  *     Failure: HRESULT error code
175c2c66affSColin Finck  *
176c2c66affSColin Finck  * NOTES
177c2c66affSColin Finck  *     No more information available yet!
178c2c66affSColin Finck  */
DPA_SaveStream(HDPA hDpa,PFNDPASTREAM saveProc,IStream * pStream,LPVOID pData)179c2c66affSColin Finck HRESULT WINAPI DPA_SaveStream (HDPA hDpa, PFNDPASTREAM saveProc,
180c2c66affSColin Finck                                IStream *pStream, LPVOID pData)
181c2c66affSColin Finck {
182c2c66affSColin Finck     LARGE_INTEGER position;
183c2c66affSColin Finck     ULARGE_INTEGER initial_pos, curr_pos;
184c2c66affSColin Finck     STREAMDATA  streamData;
185c2c66affSColin Finck     DPASTREAMINFO streamInfo;
186c2c66affSColin Finck     HRESULT hr;
187c2c66affSColin Finck     PVOID *ptr;
188c2c66affSColin Finck 
189c2c66affSColin Finck     TRACE ("hDpa=%p saveProc=%p pStream=%p pData=%p\n",
190c2c66affSColin Finck             hDpa, saveProc, pStream, pData);
191c2c66affSColin Finck 
192c2c66affSColin Finck     if (!hDpa || !saveProc || !pStream) return E_INVALIDARG;
193c2c66affSColin Finck 
194c2c66affSColin Finck     /* save initial position to write header after completion */
195c2c66affSColin Finck     position.QuadPart = 0;
196c2c66affSColin Finck     hr = IStream_Seek (pStream, position, STREAM_SEEK_CUR, &initial_pos);
197c2c66affSColin Finck     if (hr != S_OK)
198c2c66affSColin Finck         return hr;
199c2c66affSColin Finck 
200c2c66affSColin Finck     /* write empty header */
201c2c66affSColin Finck     streamData.dwSize  = sizeof(streamData);
202c2c66affSColin Finck     streamData.dwData2 = 1;
203c2c66affSColin Finck     streamData.dwItems = 0;
204c2c66affSColin Finck 
205c2c66affSColin Finck     hr = IStream_Write (pStream, &streamData, sizeof(streamData), NULL);
206c2c66affSColin Finck     if (hr != S_OK) {
207c2c66affSColin Finck         position.QuadPart = initial_pos.QuadPart;
208c2c66affSColin Finck         IStream_Seek (pStream, position, STREAM_SEEK_SET, NULL);
209c2c66affSColin Finck         return hr;
210c2c66affSColin Finck     }
211c2c66affSColin Finck 
212c2c66affSColin Finck     /* no items - we're done */
213c2c66affSColin Finck     if (hDpa->nItemCount == 0) return S_OK;
214c2c66affSColin Finck 
215c2c66affSColin Finck     ptr = hDpa->ptrs;
216c2c66affSColin Finck     for (streamInfo.iPos = 0; streamInfo.iPos < hDpa->nItemCount; streamInfo.iPos++) {
217c2c66affSColin Finck         streamInfo.pvItem = *ptr;
218c2c66affSColin Finck         hr = (saveProc)(&streamInfo, pStream, pData);
219c2c66affSColin Finck         if (hr != S_OK) {
220c2c66affSColin Finck             hr = S_FALSE;
221c2c66affSColin Finck             break;
222c2c66affSColin Finck         }
223c2c66affSColin Finck         ptr++;
224c2c66affSColin Finck     }
225c2c66affSColin Finck 
226c2c66affSColin Finck     /* write updated header */
227c2c66affSColin Finck     position.QuadPart = 0;
228c2c66affSColin Finck     IStream_Seek (pStream, position, STREAM_SEEK_CUR, &curr_pos);
229c2c66affSColin Finck 
230c2c66affSColin Finck     streamData.dwSize  = curr_pos.QuadPart - initial_pos.QuadPart;
231c2c66affSColin Finck     streamData.dwData2 = 1;
232c2c66affSColin Finck     streamData.dwItems = streamInfo.iPos;
233c2c66affSColin Finck 
234c2c66affSColin Finck     position.QuadPart = initial_pos.QuadPart;
235c2c66affSColin Finck     IStream_Seek (pStream, position, STREAM_SEEK_SET, NULL);
236c2c66affSColin Finck     IStream_Write (pStream, &streamData, sizeof(streamData), NULL);
237c2c66affSColin Finck 
238c2c66affSColin Finck     position.QuadPart = curr_pos.QuadPart;
239c2c66affSColin Finck     IStream_Seek (pStream, position, STREAM_SEEK_SET, NULL);
240c2c66affSColin Finck 
241c2c66affSColin Finck     return hr;
242c2c66affSColin Finck }
243c2c66affSColin Finck 
244c2c66affSColin Finck 
245c2c66affSColin Finck /**************************************************************************
246c2c66affSColin Finck  * DPA_Merge [COMCTL32.11]
247c2c66affSColin Finck  *
248c2c66affSColin Finck  * Merge two dynamic pointers arrays.
249c2c66affSColin Finck  *
250c2c66affSColin Finck  * PARAMS
251c2c66affSColin Finck  *     hdpa1       [I] handle to a dynamic pointer array
252c2c66affSColin Finck  *     hdpa2       [I] handle to a dynamic pointer array
253c2c66affSColin Finck  *     dwFlags     [I] flags
254c2c66affSColin Finck  *     pfnCompare  [I] pointer to sort function
255c2c66affSColin Finck  *     pfnMerge    [I] pointer to merge function
256c2c66affSColin Finck  *     lParam      [I] application specific value
257c2c66affSColin Finck  *
258c2c66affSColin Finck  * RETURNS
259c2c66affSColin Finck  *     Success: TRUE
260c2c66affSColin Finck  *     Failure: FALSE
261c2c66affSColin Finck  *
262c2c66affSColin Finck  * NOTES
263c2c66affSColin Finck  *     No more information available yet!
264c2c66affSColin Finck  */
DPA_Merge(HDPA hdpa1,HDPA hdpa2,DWORD dwFlags,PFNDPACOMPARE pfnCompare,PFNDPAMERGE pfnMerge,LPARAM lParam)265c2c66affSColin Finck BOOL WINAPI DPA_Merge (HDPA hdpa1, HDPA hdpa2, DWORD dwFlags,
266c2c66affSColin Finck                        PFNDPACOMPARE pfnCompare, PFNDPAMERGE pfnMerge,
267c2c66affSColin Finck                        LPARAM lParam)
268c2c66affSColin Finck {
269c2c66affSColin Finck     INT nCount;
270c2c66affSColin Finck     LPVOID *pWork1, *pWork2;
271c2c66affSColin Finck     INT nResult, i;
272c2c66affSColin Finck     INT nIndex;
273c2c66affSColin Finck 
274c2c66affSColin Finck     TRACE("(%p %p %08x %p %p %08lx)\n",
275c2c66affSColin Finck            hdpa1, hdpa2, dwFlags, pfnCompare, pfnMerge, lParam);
276c2c66affSColin Finck 
277c2c66affSColin Finck     if (IsBadWritePtr (hdpa1, sizeof(*hdpa1)))
278c2c66affSColin Finck         return FALSE;
279c2c66affSColin Finck 
280c2c66affSColin Finck     if (IsBadWritePtr (hdpa2, sizeof(*hdpa2)))
281c2c66affSColin Finck         return FALSE;
282c2c66affSColin Finck 
283c2c66affSColin Finck     if (IsBadCodePtr ((FARPROC)pfnCompare))
284c2c66affSColin Finck         return FALSE;
285c2c66affSColin Finck 
286c2c66affSColin Finck     if (IsBadCodePtr ((FARPROC)pfnMerge))
287c2c66affSColin Finck         return FALSE;
288c2c66affSColin Finck 
289c2c66affSColin Finck     if (!(dwFlags & DPAM_SORTED)) {
290c2c66affSColin Finck         TRACE("sorting dpa's.\n");
291c2c66affSColin Finck         if (hdpa1->nItemCount > 0)
292c2c66affSColin Finck         DPA_Sort (hdpa1, pfnCompare, lParam);
293c2c66affSColin Finck         TRACE ("dpa 1 sorted.\n");
294c2c66affSColin Finck         if (hdpa2->nItemCount > 0)
295c2c66affSColin Finck         DPA_Sort (hdpa2, pfnCompare, lParam);
296c2c66affSColin Finck         TRACE ("dpa 2 sorted.\n");
297c2c66affSColin Finck     }
298c2c66affSColin Finck 
299c2c66affSColin Finck     if (hdpa2->nItemCount < 1)
300c2c66affSColin Finck         return TRUE;
301c2c66affSColin Finck 
302c2c66affSColin Finck     TRACE("hdpa1->nItemCount=%d hdpa2->nItemCount=%d\n",
303c2c66affSColin Finck            hdpa1->nItemCount, hdpa2->nItemCount);
304c2c66affSColin Finck 
305c2c66affSColin Finck 
306c2c66affSColin Finck     nIndex = hdpa1->nItemCount - 1;
307c2c66affSColin Finck     nCount = hdpa2->nItemCount - 1;
308c2c66affSColin Finck 
309c2c66affSColin Finck     do
310c2c66affSColin Finck     {
311c2c66affSColin Finck         pWork1 = &hdpa1->ptrs[nIndex];
312c2c66affSColin Finck         pWork2 = &hdpa2->ptrs[nCount];
313c2c66affSColin Finck 
314c2c66affSColin Finck         if (nIndex < 0) {
315c2c66affSColin Finck             if ((nCount >= 0) && (dwFlags & DPAM_UNION)) {
316c2c66affSColin Finck                 /* Now insert the remaining new items into DPA 1 */
317c2c66affSColin Finck                 TRACE("%d items to be inserted at start of DPA 1\n",
318c2c66affSColin Finck                       nCount+1);
319c2c66affSColin Finck                 for (i=nCount; i>=0; i--) {
320c2c66affSColin Finck                     PVOID ptr;
321c2c66affSColin Finck 
322c2c66affSColin Finck                     ptr = (pfnMerge)(DPAMM_INSERT, *pWork2, NULL, lParam);
323c2c66affSColin Finck                     if (!ptr)
324c2c66affSColin Finck                         return FALSE;
325c2c66affSColin Finck                     DPA_InsertPtr (hdpa1, 0, ptr);
326c2c66affSColin Finck                     pWork2--;
327c2c66affSColin Finck                 }
328c2c66affSColin Finck             }
329c2c66affSColin Finck             break;
330c2c66affSColin Finck         }
331c2c66affSColin Finck         nResult = (pfnCompare)(*pWork1, *pWork2, lParam);
332c2c66affSColin Finck         TRACE("compare result=%d, dpa1.cnt=%d, dpa2.cnt=%d\n",
333c2c66affSColin Finck               nResult, nIndex, nCount);
334c2c66affSColin Finck 
335c2c66affSColin Finck         if (nResult == 0)
336c2c66affSColin Finck         {
337c2c66affSColin Finck             PVOID ptr;
338c2c66affSColin Finck 
339c2c66affSColin Finck             ptr = (pfnMerge)(DPAMM_MERGE, *pWork1, *pWork2, lParam);
340c2c66affSColin Finck             if (!ptr)
341c2c66affSColin Finck                 return FALSE;
342c2c66affSColin Finck 
343c2c66affSColin Finck             nCount--;
344c2c66affSColin Finck             *pWork1 = ptr;
345c2c66affSColin Finck             nIndex--;
346c2c66affSColin Finck         }
347c2c66affSColin Finck         else if (nResult > 0)
348c2c66affSColin Finck         {
349c2c66affSColin Finck             /* item in DPA 1 missing from DPA 2 */
350c2c66affSColin Finck             if (dwFlags & DPAM_INTERSECT)
351c2c66affSColin Finck             {
352c2c66affSColin Finck                 /* Now delete the extra item in DPA1 */
353c2c66affSColin Finck                 PVOID ptr;
354c2c66affSColin Finck 
355c2c66affSColin Finck                 ptr = DPA_DeletePtr (hdpa1, nIndex);
356c2c66affSColin Finck 
357c2c66affSColin Finck                 (pfnMerge)(DPAMM_DELETE, ptr, NULL, lParam);
358c2c66affSColin Finck             }
359c2c66affSColin Finck             nIndex--;
360c2c66affSColin Finck         }
361c2c66affSColin Finck         else
362c2c66affSColin Finck         {
363c2c66affSColin Finck             /* new item in DPA 2 */
364c2c66affSColin Finck             if (dwFlags & DPAM_UNION)
365c2c66affSColin Finck             {
366c2c66affSColin Finck                 /* Now insert the new item in DPA 1 */
367c2c66affSColin Finck                 PVOID ptr;
368c2c66affSColin Finck 
369c2c66affSColin Finck                 ptr = (pfnMerge)(DPAMM_INSERT, *pWork2, NULL, lParam);
370c2c66affSColin Finck                 if (!ptr)
371c2c66affSColin Finck                     return FALSE;
372c2c66affSColin Finck                 DPA_InsertPtr (hdpa1, nIndex+1, ptr);
373c2c66affSColin Finck             }
374c2c66affSColin Finck             nCount--;
375c2c66affSColin Finck         }
376c2c66affSColin Finck 
377c2c66affSColin Finck     }
378c2c66affSColin Finck     while (nCount >= 0);
379c2c66affSColin Finck 
380c2c66affSColin Finck     return TRUE;
381c2c66affSColin Finck }
382c2c66affSColin Finck 
383c2c66affSColin Finck 
384c2c66affSColin Finck /**************************************************************************
385c2c66affSColin Finck  * DPA_Destroy [COMCTL32.329]
386c2c66affSColin Finck  *
387c2c66affSColin Finck  * Destroys a dynamic pointer array
388c2c66affSColin Finck  *
389c2c66affSColin Finck  * PARAMS
390c2c66affSColin Finck  *     hdpa [I] handle (pointer) to the pointer array
391c2c66affSColin Finck  *
392c2c66affSColin Finck  * RETURNS
393c2c66affSColin Finck  *     Success: TRUE
394c2c66affSColin Finck  *     Failure: FALSE
395c2c66affSColin Finck  */
DPA_Destroy(HDPA hdpa)396c2c66affSColin Finck BOOL WINAPI DPA_Destroy (HDPA hdpa)
397c2c66affSColin Finck {
398c2c66affSColin Finck     TRACE("(%p)\n", hdpa);
399c2c66affSColin Finck 
400c2c66affSColin Finck     if (!hdpa)
401c2c66affSColin Finck         return FALSE;
402c2c66affSColin Finck 
403c2c66affSColin Finck     if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
404c2c66affSColin Finck         return FALSE;
405c2c66affSColin Finck 
406c2c66affSColin Finck     return HeapFree (hdpa->hHeap, 0, hdpa);
407c2c66affSColin Finck }
408c2c66affSColin Finck 
409c2c66affSColin Finck 
410c2c66affSColin Finck /**************************************************************************
411c2c66affSColin Finck  * DPA_Grow [COMCTL32.330]
412c2c66affSColin Finck  *
413c2c66affSColin Finck  * Sets the growth amount.
414c2c66affSColin Finck  *
415c2c66affSColin Finck  * PARAMS
416c2c66affSColin Finck  *     hdpa  [I] handle (pointer) to the existing (source) pointer array
417c2c66affSColin Finck  *     nGrow [I] number of items by which the array grows when it's too small
418c2c66affSColin Finck  *
419c2c66affSColin Finck  * RETURNS
420c2c66affSColin Finck  *     Success: TRUE
421c2c66affSColin Finck  *     Failure: FALSE
422c2c66affSColin Finck  */
DPA_Grow(HDPA hdpa,INT nGrow)423c2c66affSColin Finck BOOL WINAPI DPA_Grow (HDPA hdpa, INT nGrow)
424c2c66affSColin Finck {
425c2c66affSColin Finck     INT items;
426c2c66affSColin Finck     TRACE("(%p %d)\n", hdpa, nGrow);
427c2c66affSColin Finck 
428c2c66affSColin Finck     if (!hdpa)
429c2c66affSColin Finck         return FALSE;
430c2c66affSColin Finck 
431c2c66affSColin Finck     nGrow = max( 8, nGrow );
432c2c66affSColin Finck     items = nGrow * (((hdpa->nMaxCount - 1) / nGrow) + 1);
433c2c66affSColin Finck     if (items > hdpa->nMaxCount)
434c2c66affSColin Finck     {
435c2c66affSColin Finck         void *ptr;
436c2c66affSColin Finck 
437c2c66affSColin Finck         if (hdpa->ptrs)
438c2c66affSColin Finck             ptr = HeapReAlloc( hdpa->hHeap, HEAP_ZERO_MEMORY, hdpa->ptrs, items * sizeof(LPVOID) );
439c2c66affSColin Finck         else
440c2c66affSColin Finck             ptr = HeapAlloc( hdpa->hHeap, HEAP_ZERO_MEMORY, items * sizeof(LPVOID) );
441c2c66affSColin Finck         if (!ptr) return FALSE;
442c2c66affSColin Finck         hdpa->nMaxCount = items;
443c2c66affSColin Finck         hdpa->ptrs = ptr;
444c2c66affSColin Finck     }
445c2c66affSColin Finck     hdpa->nGrow = nGrow;
446c2c66affSColin Finck 
447c2c66affSColin Finck     return TRUE;
448c2c66affSColin Finck }
449c2c66affSColin Finck 
450c2c66affSColin Finck 
451c2c66affSColin Finck /**************************************************************************
452c2c66affSColin Finck  * DPA_Clone [COMCTL32.331]
453c2c66affSColin Finck  *
454c2c66affSColin Finck  * Copies a pointer array to another one or creates a copy
455c2c66affSColin Finck  *
456c2c66affSColin Finck  * PARAMS
457c2c66affSColin Finck  *     hdpa    [I] handle (pointer) to the existing (source) pointer array
458c2c66affSColin Finck  *     hdpaNew [O] handle (pointer) to the destination pointer array
459c2c66affSColin Finck  *
460c2c66affSColin Finck  * RETURNS
461c2c66affSColin Finck  *     Success: pointer to the destination pointer array.
462c2c66affSColin Finck  *     Failure: NULL
463c2c66affSColin Finck  *
464c2c66affSColin Finck  * NOTES
465c2c66affSColin Finck  *     - If the 'hdpaNew' is a NULL-Pointer, a copy of the source pointer
466c2c66affSColin Finck  *       array will be created and its handle (pointer) is returned.
467c2c66affSColin Finck  *     - If 'hdpa' is a NULL-Pointer, the original implementation crashes,
468c2c66affSColin Finck  *       this implementation just returns NULL.
469c2c66affSColin Finck  */
DPA_Clone(const HDPA hdpa,HDPA hdpaNew)470c2c66affSColin Finck HDPA WINAPI DPA_Clone (const HDPA hdpa, HDPA hdpaNew)
471c2c66affSColin Finck {
472c2c66affSColin Finck     INT nNewItems, nSize;
473c2c66affSColin Finck     HDPA hdpaTemp;
474c2c66affSColin Finck 
475c2c66affSColin Finck     if (!hdpa)
476c2c66affSColin Finck         return NULL;
477c2c66affSColin Finck 
478c2c66affSColin Finck     TRACE("(%p %p)\n", hdpa, hdpaNew);
479c2c66affSColin Finck 
480c2c66affSColin Finck     if (!hdpaNew) {
481c2c66affSColin Finck         /* create a new DPA */
482c2c66affSColin Finck         hdpaTemp = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
483c2c66affSColin Finck                                     sizeof(*hdpaTemp));
484c2c66affSColin Finck         hdpaTemp->hHeap = hdpa->hHeap;
485c2c66affSColin Finck         hdpaTemp->nGrow = hdpa->nGrow;
486c2c66affSColin Finck     }
487c2c66affSColin Finck     else
488c2c66affSColin Finck         hdpaTemp = hdpaNew;
489c2c66affSColin Finck 
490c2c66affSColin Finck     if (hdpaTemp->ptrs) {
491c2c66affSColin Finck         /* remove old pointer array */
492c2c66affSColin Finck         HeapFree (hdpaTemp->hHeap, 0, hdpaTemp->ptrs);
493c2c66affSColin Finck         hdpaTemp->ptrs = NULL;
494c2c66affSColin Finck         hdpaTemp->nItemCount = 0;
495c2c66affSColin Finck         hdpaTemp->nMaxCount = 0;
496c2c66affSColin Finck     }
497c2c66affSColin Finck 
498c2c66affSColin Finck     /* create a new pointer array */
499c2c66affSColin Finck     nNewItems = hdpaTemp->nGrow *
500c2c66affSColin Finck                 (((hdpa->nItemCount - 1) / hdpaTemp->nGrow) + 1);
501c2c66affSColin Finck     nSize = nNewItems * sizeof(LPVOID);
502c2c66affSColin Finck     hdpaTemp->ptrs = HeapAlloc (hdpaTemp->hHeap, HEAP_ZERO_MEMORY, nSize);
503c2c66affSColin Finck     hdpaTemp->nMaxCount = nNewItems;
504c2c66affSColin Finck 
505c2c66affSColin Finck     /* clone the pointer array */
506c2c66affSColin Finck     hdpaTemp->nItemCount = hdpa->nItemCount;
507c2c66affSColin Finck     memmove (hdpaTemp->ptrs, hdpa->ptrs,
508c2c66affSColin Finck              hdpaTemp->nItemCount * sizeof(LPVOID));
509c2c66affSColin Finck 
510c2c66affSColin Finck     return hdpaTemp;
511c2c66affSColin Finck }
512c2c66affSColin Finck 
513c2c66affSColin Finck 
514c2c66affSColin Finck /**************************************************************************
515c2c66affSColin Finck  * DPA_GetPtr [COMCTL32.332]
516c2c66affSColin Finck  *
517c2c66affSColin Finck  * Retrieves a pointer from a dynamic pointer array
518c2c66affSColin Finck  *
519c2c66affSColin Finck  * PARAMS
520c2c66affSColin Finck  *     hdpa   [I] handle (pointer) to the pointer array
521c2c66affSColin Finck  *     nIndex [I] array index of the desired pointer
522c2c66affSColin Finck  *
523c2c66affSColin Finck  * RETURNS
524c2c66affSColin Finck  *     Success: pointer
525c2c66affSColin Finck  *     Failure: NULL
526c2c66affSColin Finck  */
DPA_GetPtr(HDPA hdpa,INT nIndex)527c2c66affSColin Finck LPVOID WINAPI DPA_GetPtr (HDPA hdpa, INT nIndex)
528c2c66affSColin Finck {
529c2c66affSColin Finck     TRACE("(%p %d)\n", hdpa, nIndex);
530c2c66affSColin Finck 
531c2c66affSColin Finck     if (!hdpa)
532c2c66affSColin Finck         return NULL;
533c2c66affSColin Finck     if (!hdpa->ptrs) {
534c2c66affSColin Finck         WARN("no pointer array.\n");
535c2c66affSColin Finck         return NULL;
536c2c66affSColin Finck     }
537c2c66affSColin Finck     if ((nIndex < 0) || (nIndex >= hdpa->nItemCount)) {
538c2c66affSColin Finck         WARN("not enough pointers in array (%d vs %d).\n",nIndex,hdpa->nItemCount);
539c2c66affSColin Finck         return NULL;
540c2c66affSColin Finck     }
541c2c66affSColin Finck 
542c2c66affSColin Finck     TRACE("-- %p\n", hdpa->ptrs[nIndex]);
543c2c66affSColin Finck 
544c2c66affSColin Finck     return hdpa->ptrs[nIndex];
545c2c66affSColin Finck }
546c2c66affSColin Finck 
547c2c66affSColin Finck 
548c2c66affSColin Finck /**************************************************************************
549c2c66affSColin Finck  * DPA_GetPtrIndex [COMCTL32.333]
550c2c66affSColin Finck  *
551c2c66affSColin Finck  * Retrieves the index of the specified pointer
552c2c66affSColin Finck  *
553c2c66affSColin Finck  * PARAMS
554c2c66affSColin Finck  *     hdpa   [I] handle (pointer) to the pointer array
555c2c66affSColin Finck  *     p      [I] pointer
556c2c66affSColin Finck  *
557c2c66affSColin Finck  * RETURNS
558c2c66affSColin Finck  *     Success: index of the specified pointer
559c2c66affSColin Finck  *     Failure: -1
560c2c66affSColin Finck  */
DPA_GetPtrIndex(HDPA hdpa,LPCVOID p)561c2c66affSColin Finck INT WINAPI DPA_GetPtrIndex (HDPA hdpa, LPCVOID p)
562c2c66affSColin Finck {
563c2c66affSColin Finck     INT i;
564c2c66affSColin Finck 
565c2c66affSColin Finck     if (!hdpa || !hdpa->ptrs)
566c2c66affSColin Finck         return -1;
567c2c66affSColin Finck 
568c2c66affSColin Finck     for (i = 0; i < hdpa->nItemCount; i++) {
569c2c66affSColin Finck         if (hdpa->ptrs[i] == p)
570c2c66affSColin Finck             return i;
571c2c66affSColin Finck     }
572c2c66affSColin Finck 
573c2c66affSColin Finck     return -1;
574c2c66affSColin Finck }
575c2c66affSColin Finck 
576c2c66affSColin Finck 
577c2c66affSColin Finck /**************************************************************************
578c2c66affSColin Finck  * DPA_InsertPtr [COMCTL32.334]
579c2c66affSColin Finck  *
580c2c66affSColin Finck  * Inserts a pointer into a dynamic pointer array
581c2c66affSColin Finck  *
582c2c66affSColin Finck  * PARAMS
583c2c66affSColin Finck  *     hdpa [I] handle (pointer) to the array
584c2c66affSColin Finck  *     i    [I] array index
585c2c66affSColin Finck  *     p    [I] pointer to insert
586c2c66affSColin Finck  *
587c2c66affSColin Finck  * RETURNS
588c2c66affSColin Finck  *     Success: index of the inserted pointer
589c2c66affSColin Finck  *     Failure: -1
590c2c66affSColin Finck  */
DPA_InsertPtr(HDPA hdpa,INT i,LPVOID p)591c2c66affSColin Finck INT WINAPI DPA_InsertPtr (HDPA hdpa, INT i, LPVOID p)
592c2c66affSColin Finck {
593c2c66affSColin Finck     TRACE("(%p %d %p)\n", hdpa, i, p);
594c2c66affSColin Finck 
595c2c66affSColin Finck     if (!hdpa || i < 0) return -1;
596c2c66affSColin Finck 
597c2c66affSColin Finck     /* append item if index is out of bounds */
598c2c66affSColin Finck     i = min(hdpa->nItemCount, i);
599c2c66affSColin Finck 
600c2c66affSColin Finck     /* create empty spot at the end */
601c2c66affSColin Finck     if (!DPA_SetPtr(hdpa, hdpa->nItemCount, 0)) return -1;
602c2c66affSColin Finck 
603c2c66affSColin Finck     if (i != hdpa->nItemCount - 1)
604c2c66affSColin Finck         memmove (hdpa->ptrs + i + 1, hdpa->ptrs + i,
605c2c66affSColin Finck                  (hdpa->nItemCount - i - 1) * sizeof(LPVOID));
606c2c66affSColin Finck 
607c2c66affSColin Finck     hdpa->ptrs[i] = p;
608c2c66affSColin Finck     return i;
609c2c66affSColin Finck }
610c2c66affSColin Finck 
611c2c66affSColin Finck 
612c2c66affSColin Finck /**************************************************************************
613c2c66affSColin Finck  * DPA_SetPtr [COMCTL32.335]
614c2c66affSColin Finck  *
615c2c66affSColin Finck  * Sets a pointer in the pointer array
616c2c66affSColin Finck  *
617c2c66affSColin Finck  * PARAMS
618c2c66affSColin Finck  *     hdpa [I] handle (pointer) to the pointer array
619c2c66affSColin Finck  *     i    [I] index of the pointer that will be set
620c2c66affSColin Finck  *     p    [I] pointer to be set
621c2c66affSColin Finck  *
622c2c66affSColin Finck  * RETURNS
623c2c66affSColin Finck  *     Success: TRUE
624c2c66affSColin Finck  *     Failure: FALSE
625c2c66affSColin Finck  */
DPA_SetPtr(HDPA hdpa,INT i,LPVOID p)626c2c66affSColin Finck BOOL WINAPI DPA_SetPtr (HDPA hdpa, INT i, LPVOID p)
627c2c66affSColin Finck {
628c2c66affSColin Finck     LPVOID *lpTemp;
629c2c66affSColin Finck 
630c2c66affSColin Finck     TRACE("(%p %d %p)\n", hdpa, i, p);
631c2c66affSColin Finck 
632c2c66affSColin Finck     if (!hdpa || i < 0)
633c2c66affSColin Finck         return FALSE;
634c2c66affSColin Finck 
635c2c66affSColin Finck     if (hdpa->nItemCount <= i) {
636c2c66affSColin Finck         /* within the old array */
637c2c66affSColin Finck         if (hdpa->nMaxCount <= i) {
638c2c66affSColin Finck             /* resize the block of memory */
639c2c66affSColin Finck             INT nNewItems =
640c2c66affSColin Finck                 hdpa->nGrow * ((((i+1) - 1) / hdpa->nGrow) + 1);
641c2c66affSColin Finck             INT nSize = nNewItems * sizeof(LPVOID);
642c2c66affSColin Finck 
643c2c66affSColin Finck             if (hdpa->ptrs)
644c2c66affSColin Finck                 lpTemp = HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, hdpa->ptrs, nSize);
645c2c66affSColin Finck             else
646c2c66affSColin Finck                 lpTemp = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, nSize);
647c2c66affSColin Finck 
648c2c66affSColin Finck             if (!lpTemp)
649c2c66affSColin Finck                 return FALSE;
650c2c66affSColin Finck 
651c2c66affSColin Finck             hdpa->nMaxCount = nNewItems;
652c2c66affSColin Finck             hdpa->ptrs = lpTemp;
653c2c66affSColin Finck         }
654c2c66affSColin Finck         hdpa->nItemCount = i+1;
655c2c66affSColin Finck     }
656c2c66affSColin Finck 
657c2c66affSColin Finck     /* put the new entry in */
658c2c66affSColin Finck     hdpa->ptrs[i] = p;
659c2c66affSColin Finck 
660c2c66affSColin Finck     return TRUE;
661c2c66affSColin Finck }
662c2c66affSColin Finck 
663c2c66affSColin Finck 
664c2c66affSColin Finck /**************************************************************************
665c2c66affSColin Finck  * DPA_DeletePtr [COMCTL32.336]
666c2c66affSColin Finck  *
667c2c66affSColin Finck  * Removes a pointer from the pointer array.
668c2c66affSColin Finck  *
669c2c66affSColin Finck  * PARAMS
670c2c66affSColin Finck  *     hdpa [I] handle (pointer) to the pointer array
671c2c66affSColin Finck  *     i    [I] index of the pointer that will be deleted
672c2c66affSColin Finck  *
673c2c66affSColin Finck  * RETURNS
674c2c66affSColin Finck  *     Success: deleted pointer
675c2c66affSColin Finck  *     Failure: NULL
676c2c66affSColin Finck  */
DPA_DeletePtr(HDPA hdpa,INT i)677c2c66affSColin Finck LPVOID WINAPI DPA_DeletePtr (HDPA hdpa, INT i)
678c2c66affSColin Finck {
679c2c66affSColin Finck     LPVOID *lpDest, *lpSrc, lpTemp = NULL;
680c2c66affSColin Finck     INT  nSize;
681c2c66affSColin Finck 
682c2c66affSColin Finck     TRACE("(%p %d)\n", hdpa, i);
683c2c66affSColin Finck 
684c2c66affSColin Finck     if ((!hdpa) || i < 0 || i >= hdpa->nItemCount)
685c2c66affSColin Finck         return NULL;
686c2c66affSColin Finck 
687c2c66affSColin Finck     lpTemp = hdpa->ptrs[i];
688c2c66affSColin Finck 
689c2c66affSColin Finck     /* do we need to move ?*/
690c2c66affSColin Finck     if (i < hdpa->nItemCount - 1) {
691c2c66affSColin Finck         lpDest = hdpa->ptrs + i;
692c2c66affSColin Finck         lpSrc = lpDest + 1;
693c2c66affSColin Finck         nSize = (hdpa->nItemCount - i - 1) * sizeof(LPVOID);
694c2c66affSColin Finck         TRACE("-- move dest=%p src=%p size=%x\n",
695c2c66affSColin Finck                lpDest, lpSrc, nSize);
696c2c66affSColin Finck         memmove (lpDest, lpSrc, nSize);
697c2c66affSColin Finck     }
698c2c66affSColin Finck 
699c2c66affSColin Finck     hdpa->nItemCount --;
700c2c66affSColin Finck 
701c2c66affSColin Finck     /* free memory ?*/
702c2c66affSColin Finck     if ((hdpa->nMaxCount - hdpa->nItemCount) >= hdpa->nGrow) {
703c2c66affSColin Finck         INT nNewItems = max(hdpa->nGrow * 2, hdpa->nItemCount);
704c2c66affSColin Finck         nSize = nNewItems * sizeof(LPVOID);
705c2c66affSColin Finck         lpDest = HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
706c2c66affSColin Finck                                       hdpa->ptrs, nSize);
707c2c66affSColin Finck         if (!lpDest)
708c2c66affSColin Finck             return NULL;
709c2c66affSColin Finck 
710c2c66affSColin Finck         hdpa->nMaxCount = nNewItems;
711c2c66affSColin Finck         hdpa->ptrs = lpDest;
712c2c66affSColin Finck     }
713c2c66affSColin Finck 
714c2c66affSColin Finck     return lpTemp;
715c2c66affSColin Finck }
716c2c66affSColin Finck 
717c2c66affSColin Finck 
718c2c66affSColin Finck /**************************************************************************
719c2c66affSColin Finck  * DPA_DeleteAllPtrs [COMCTL32.337]
720c2c66affSColin Finck  *
721c2c66affSColin Finck  * Removes all pointers and reinitializes the array.
722c2c66affSColin Finck  *
723c2c66affSColin Finck  * PARAMS
724c2c66affSColin Finck  *     hdpa [I] handle (pointer) to the pointer array
725c2c66affSColin Finck  *
726c2c66affSColin Finck  * RETURNS
727c2c66affSColin Finck  *     Success: TRUE
728c2c66affSColin Finck  *     Failure: FALSE
729c2c66affSColin Finck  */
DPA_DeleteAllPtrs(HDPA hdpa)730c2c66affSColin Finck BOOL WINAPI DPA_DeleteAllPtrs (HDPA hdpa)
731c2c66affSColin Finck {
732c2c66affSColin Finck     TRACE("(%p)\n", hdpa);
733c2c66affSColin Finck 
734c2c66affSColin Finck     if (!hdpa)
735c2c66affSColin Finck         return FALSE;
736c2c66affSColin Finck 
737c2c66affSColin Finck     if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
738c2c66affSColin Finck         return FALSE;
739c2c66affSColin Finck 
740c2c66affSColin Finck     hdpa->nItemCount = 0;
741c2c66affSColin Finck     hdpa->nMaxCount = hdpa->nGrow * 2;
742c2c66affSColin Finck     hdpa->ptrs = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
743c2c66affSColin Finck                                      hdpa->nMaxCount * sizeof(LPVOID));
744c2c66affSColin Finck 
745c2c66affSColin Finck     return TRUE;
746c2c66affSColin Finck }
747c2c66affSColin Finck 
748c2c66affSColin Finck 
749c2c66affSColin Finck /**************************************************************************
750c2c66affSColin Finck  * DPA_QuickSort [Internal]
751c2c66affSColin Finck  *
752c2c66affSColin Finck  * Ordinary quicksort (used by DPA_Sort).
753c2c66affSColin Finck  *
754c2c66affSColin Finck  * PARAMS
755c2c66affSColin Finck  *     lpPtrs     [I] pointer to the pointer array
756c2c66affSColin Finck  *     l          [I] index of the "left border" of the partition
757c2c66affSColin Finck  *     r          [I] index of the "right border" of the partition
758c2c66affSColin Finck  *     pfnCompare [I] pointer to the compare function
759c2c66affSColin Finck  *     lParam     [I] user defined value (3rd parameter in compare function)
760c2c66affSColin Finck  *
761c2c66affSColin Finck  * RETURNS
762c2c66affSColin Finck  *     NONE
763c2c66affSColin Finck  */
DPA_QuickSort(LPVOID * lpPtrs,INT l,INT r,PFNDPACOMPARE pfnCompare,LPARAM lParam)764c2c66affSColin Finck static VOID DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r,
765c2c66affSColin Finck                            PFNDPACOMPARE pfnCompare, LPARAM lParam)
766c2c66affSColin Finck {
767c2c66affSColin Finck     INT m;
768c2c66affSColin Finck     LPVOID t;
769c2c66affSColin Finck 
770c2c66affSColin Finck     TRACE("l=%i r=%i\n", l, r);
771c2c66affSColin Finck 
772c2c66affSColin Finck     if (l==r)    /* one element is always sorted */
773c2c66affSColin Finck         return;
774c2c66affSColin Finck     if (r<l)     /* oops, got it in the wrong order */
775c2c66affSColin Finck         {
776c2c66affSColin Finck         DPA_QuickSort(lpPtrs, r, l, pfnCompare, lParam);
777c2c66affSColin Finck         return;
778c2c66affSColin Finck         }
779c2c66affSColin Finck     m = (l+r)/2; /* divide by two */
780c2c66affSColin Finck     DPA_QuickSort(lpPtrs, l, m, pfnCompare, lParam);
781c2c66affSColin Finck     DPA_QuickSort(lpPtrs, m+1, r, pfnCompare, lParam);
782c2c66affSColin Finck 
783c2c66affSColin Finck     /* join the two sides */
784c2c66affSColin Finck     while( (l<=m) && (m<r) )
785c2c66affSColin Finck     {
786c2c66affSColin Finck         if(pfnCompare(lpPtrs[l],lpPtrs[m+1],lParam)>0)
787c2c66affSColin Finck         {
788c2c66affSColin Finck             t = lpPtrs[m+1];
789c2c66affSColin Finck             memmove(&lpPtrs[l+1],&lpPtrs[l],(m-l+1)*sizeof(lpPtrs[l]));
790c2c66affSColin Finck             lpPtrs[l] = t;
791c2c66affSColin Finck 
792c2c66affSColin Finck             m++;
793c2c66affSColin Finck         }
794c2c66affSColin Finck         l++;
795c2c66affSColin Finck     }
796c2c66affSColin Finck }
797c2c66affSColin Finck 
798c2c66affSColin Finck 
799c2c66affSColin Finck /**************************************************************************
800c2c66affSColin Finck  * DPA_Sort [COMCTL32.338]
801c2c66affSColin Finck  *
802c2c66affSColin Finck  * Sorts a pointer array using a user defined compare function
803c2c66affSColin Finck  *
804c2c66affSColin Finck  * PARAMS
805c2c66affSColin Finck  *     hdpa       [I] handle (pointer) to the pointer array
806c2c66affSColin Finck  *     pfnCompare [I] pointer to the compare function
807c2c66affSColin Finck  *     lParam     [I] user defined value (3rd parameter of compare function)
808c2c66affSColin Finck  *
809c2c66affSColin Finck  * RETURNS
810c2c66affSColin Finck  *     Success: TRUE
811c2c66affSColin Finck  *     Failure: FALSE
812c2c66affSColin Finck  */
DPA_Sort(HDPA hdpa,PFNDPACOMPARE pfnCompare,LPARAM lParam)813c2c66affSColin Finck BOOL WINAPI DPA_Sort (HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam)
814c2c66affSColin Finck {
815c2c66affSColin Finck     if (!hdpa || !pfnCompare)
816c2c66affSColin Finck         return FALSE;
817c2c66affSColin Finck 
818c2c66affSColin Finck     TRACE("(%p %p 0x%lx)\n", hdpa, pfnCompare, lParam);
819c2c66affSColin Finck 
820c2c66affSColin Finck     if ((hdpa->nItemCount > 1) && (hdpa->ptrs))
821c2c66affSColin Finck         DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1,
822c2c66affSColin Finck                        pfnCompare, lParam);
823c2c66affSColin Finck 
824c2c66affSColin Finck     return TRUE;
825c2c66affSColin Finck }
826c2c66affSColin Finck 
827c2c66affSColin Finck 
828c2c66affSColin Finck /**************************************************************************
829c2c66affSColin Finck  * DPA_Search [COMCTL32.339]
830c2c66affSColin Finck  *
831c2c66affSColin Finck  * Searches a pointer array for a specified pointer
832c2c66affSColin Finck  *
833c2c66affSColin Finck  * PARAMS
834c2c66affSColin Finck  *     hdpa       [I] handle (pointer) to the pointer array
835c2c66affSColin Finck  *     pFind      [I] pointer to search for
836c2c66affSColin Finck  *     nStart     [I] start index
837c2c66affSColin Finck  *     pfnCompare [I] pointer to the compare function
838c2c66affSColin Finck  *     lParam     [I] user defined value (3rd parameter of compare function)
839c2c66affSColin Finck  *     uOptions   [I] search options
840c2c66affSColin Finck  *
841c2c66affSColin Finck  * RETURNS
842c2c66affSColin Finck  *     Success: index of the pointer in the array.
843c2c66affSColin Finck  *     Failure: -1
844c2c66affSColin Finck  */
DPA_Search(HDPA hdpa,LPVOID pFind,INT nStart,PFNDPACOMPARE pfnCompare,LPARAM lParam,UINT uOptions)845c2c66affSColin Finck INT WINAPI DPA_Search (HDPA hdpa, LPVOID pFind, INT nStart,
846c2c66affSColin Finck                        PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions)
847c2c66affSColin Finck {
848c2c66affSColin Finck     if (!hdpa || !pfnCompare || !pFind)
849c2c66affSColin Finck         return -1;
850c2c66affSColin Finck 
851c2c66affSColin Finck     TRACE("(%p %p %d %p 0x%08lx 0x%08x)\n",
852c2c66affSColin Finck            hdpa, pFind, nStart, pfnCompare, lParam, uOptions);
853c2c66affSColin Finck 
854c2c66affSColin Finck     if (uOptions & DPAS_SORTED) {
855c2c66affSColin Finck         /* array is sorted --> use binary search */
856c2c66affSColin Finck         INT l, r, x, n;
857c2c66affSColin Finck         LPVOID *lpPtr;
858c2c66affSColin Finck 
859c2c66affSColin Finck         /* for binary search ignore start index */
860c2c66affSColin Finck         l = 0;
861c2c66affSColin Finck         r = hdpa->nItemCount - 1;
862c2c66affSColin Finck         lpPtr = hdpa->ptrs;
863c2c66affSColin Finck         while (r >= l) {
864c2c66affSColin Finck             x = (l + r) / 2;
865c2c66affSColin Finck             n = (pfnCompare)(pFind, lpPtr[x], lParam);
866c2c66affSColin Finck             if (n == 0)
867c2c66affSColin Finck                 return x;
868c2c66affSColin Finck             else if (n < 0)
869c2c66affSColin Finck                 r = x - 1;
870c2c66affSColin Finck             else /* (n > 0) */
871c2c66affSColin Finck                 l = x + 1;
872c2c66affSColin Finck         }
873c2c66affSColin Finck         if (uOptions & (DPAS_INSERTBEFORE|DPAS_INSERTAFTER)) return l;
874c2c66affSColin Finck     }
875c2c66affSColin Finck     else {
876c2c66affSColin Finck         /* array is not sorted --> use linear search */
877c2c66affSColin Finck         LPVOID *lpPtr;
878c2c66affSColin Finck         INT  nIndex;
879c2c66affSColin Finck 
880c2c66affSColin Finck         nIndex = (nStart == -1)? 0 : nStart;
881c2c66affSColin Finck         lpPtr = hdpa->ptrs;
882c2c66affSColin Finck         for (; nIndex < hdpa->nItemCount; nIndex++) {
883c2c66affSColin Finck             if ((pfnCompare)(pFind, lpPtr[nIndex], lParam) == 0)
884c2c66affSColin Finck                 return nIndex;
885c2c66affSColin Finck         }
886c2c66affSColin Finck     }
887c2c66affSColin Finck 
888c2c66affSColin Finck     return -1;
889c2c66affSColin Finck }
890c2c66affSColin Finck 
891c2c66affSColin Finck 
892c2c66affSColin Finck /**************************************************************************
893c2c66affSColin Finck  * DPA_CreateEx [COMCTL32.340]
894c2c66affSColin Finck  *
895c2c66affSColin Finck  * Creates a dynamic pointer array using the specified size and heap.
896c2c66affSColin Finck  *
897c2c66affSColin Finck  * PARAMS
898c2c66affSColin Finck  *     nGrow [I] number of items by which the array grows when it is filled
899c2c66affSColin Finck  *     hHeap [I] handle to the heap where the array is stored
900c2c66affSColin Finck  *
901c2c66affSColin Finck  * RETURNS
902c2c66affSColin Finck  *     Success: handle (pointer) to the pointer array.
903c2c66affSColin Finck  *     Failure: NULL
904c2c66affSColin Finck  *
905c2c66affSColin Finck  * NOTES
906c2c66affSColin Finck  *     The DPA_ functions can be used to create and manipulate arrays of
907c2c66affSColin Finck  *     pointers.
908c2c66affSColin Finck  */
DPA_CreateEx(INT nGrow,HANDLE hHeap)909c2c66affSColin Finck HDPA WINAPI DPA_CreateEx (INT nGrow, HANDLE hHeap)
910c2c66affSColin Finck {
911c2c66affSColin Finck     HDPA hdpa;
912c2c66affSColin Finck 
913c2c66affSColin Finck     TRACE("(%d %p)\n", nGrow, hHeap);
914c2c66affSColin Finck 
915c2c66affSColin Finck     if (hHeap)
916c2c66affSColin Finck         hdpa = HeapAlloc (hHeap, HEAP_ZERO_MEMORY, sizeof(*hdpa));
917c2c66affSColin Finck     else
918c2c66affSColin Finck         hdpa = Alloc (sizeof(*hdpa));
919c2c66affSColin Finck 
920c2c66affSColin Finck     if (hdpa) {
921c2c66affSColin Finck         hdpa->nGrow = max(8, nGrow);
922c2c66affSColin Finck         hdpa->hHeap = hHeap ? hHeap : GetProcessHeap();
923c2c66affSColin Finck         hdpa->nMaxCount = hdpa->nGrow * 2;
924c2c66affSColin Finck         hdpa->ptrs = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
925c2c66affSColin Finck                                 hdpa->nMaxCount * sizeof(LPVOID));
926c2c66affSColin Finck     }
927c2c66affSColin Finck 
928c2c66affSColin Finck     TRACE("-- %p\n", hdpa);
929c2c66affSColin Finck 
930c2c66affSColin Finck     return hdpa;
931c2c66affSColin Finck }
932c2c66affSColin Finck 
933c2c66affSColin Finck 
934c2c66affSColin Finck /**************************************************************************
935c2c66affSColin Finck  * DPA_Create [COMCTL32.328]
936c2c66affSColin Finck  *
937c2c66affSColin Finck  * Creates a dynamic pointer array.
938c2c66affSColin Finck  *
939c2c66affSColin Finck  * PARAMS
940c2c66affSColin Finck  *     nGrow [I] number of items by which the array grows when it is filled
941c2c66affSColin Finck  *
942c2c66affSColin Finck  * RETURNS
943c2c66affSColin Finck  *     Success: handle (pointer) to the pointer array.
944c2c66affSColin Finck  *     Failure: NULL
945c2c66affSColin Finck  *
946c2c66affSColin Finck  * NOTES
947c2c66affSColin Finck  *     The DPA_ functions can be used to create and manipulate arrays of
948c2c66affSColin Finck  *     pointers.
949c2c66affSColin Finck  */
DPA_Create(INT nGrow)950c2c66affSColin Finck HDPA WINAPI DPA_Create (INT nGrow)
951c2c66affSColin Finck {
952c2c66affSColin Finck     return DPA_CreateEx( nGrow, 0 );
953c2c66affSColin Finck }
954c2c66affSColin Finck 
955c2c66affSColin Finck 
956c2c66affSColin Finck /**************************************************************************
957c2c66affSColin Finck  * DPA_EnumCallback [COMCTL32.385]
958c2c66affSColin Finck  *
959c2c66affSColin Finck  * Enumerates all items in a dynamic pointer array.
960c2c66affSColin Finck  *
961c2c66affSColin Finck  * PARAMS
962c2c66affSColin Finck  *     hdpa     [I] handle to the dynamic pointer array
963c2c66affSColin Finck  *     enumProc [I]
964c2c66affSColin Finck  *     lParam   [I]
965c2c66affSColin Finck  *
966c2c66affSColin Finck  * RETURNS
967c2c66affSColin Finck  *     none
968c2c66affSColin Finck  */
DPA_EnumCallback(HDPA hdpa,PFNDPAENUMCALLBACK enumProc,LPVOID lParam)969c2c66affSColin Finck VOID WINAPI DPA_EnumCallback (HDPA hdpa, PFNDPAENUMCALLBACK enumProc,
970c2c66affSColin Finck                               LPVOID lParam)
971c2c66affSColin Finck {
972c2c66affSColin Finck     INT i;
973c2c66affSColin Finck 
974c2c66affSColin Finck     TRACE("(%p %p %p)\n", hdpa, enumProc, lParam);
975c2c66affSColin Finck 
976c2c66affSColin Finck     if (!hdpa)
977c2c66affSColin Finck         return;
978c2c66affSColin Finck     if (hdpa->nItemCount <= 0)
979c2c66affSColin Finck         return;
980c2c66affSColin Finck 
981c2c66affSColin Finck     for (i = 0; i < hdpa->nItemCount; i++) {
982c2c66affSColin Finck         if ((enumProc)(hdpa->ptrs[i], lParam) == 0)
983c2c66affSColin Finck             return;
984c2c66affSColin Finck     }
985c2c66affSColin Finck 
986c2c66affSColin Finck     return;
987c2c66affSColin Finck }
988c2c66affSColin Finck 
989c2c66affSColin Finck 
990c2c66affSColin Finck /**************************************************************************
991c2c66affSColin Finck  * DPA_DestroyCallback [COMCTL32.386]
992c2c66affSColin Finck  *
993c2c66affSColin Finck  * Enumerates all items in a dynamic pointer array and destroys it.
994c2c66affSColin Finck  *
995c2c66affSColin Finck  * PARAMS
996c2c66affSColin Finck  *     hdpa     [I] handle to the dynamic pointer array
997c2c66affSColin Finck  *     enumProc [I]
998c2c66affSColin Finck  *     lParam   [I]
999c2c66affSColin Finck  *
1000c2c66affSColin Finck  * RETURNS
1001c2c66affSColin Finck  *     none
1002c2c66affSColin Finck  */
DPA_DestroyCallback(HDPA hdpa,PFNDPAENUMCALLBACK enumProc,LPVOID lParam)1003c2c66affSColin Finck void WINAPI DPA_DestroyCallback (HDPA hdpa, PFNDPAENUMCALLBACK enumProc,
1004c2c66affSColin Finck                                  LPVOID lParam)
1005c2c66affSColin Finck {
1006c2c66affSColin Finck     TRACE("(%p %p %p)\n", hdpa, enumProc, lParam);
1007c2c66affSColin Finck 
1008c2c66affSColin Finck     DPA_EnumCallback (hdpa, enumProc, lParam);
1009c2c66affSColin Finck     DPA_Destroy (hdpa);
1010c2c66affSColin Finck }
1011c2c66affSColin Finck 
1012c2c66affSColin Finck /**************************************************************************
1013c2c66affSColin Finck  * DPA_GetSize [COMCTL32.@]
1014c2c66affSColin Finck  *
1015c2c66affSColin Finck  * Returns all array allocated memory size
1016c2c66affSColin Finck  *
1017c2c66affSColin Finck  * PARAMS
1018c2c66affSColin Finck  *     hdpa     [I] handle to the dynamic pointer array
1019c2c66affSColin Finck  *
1020c2c66affSColin Finck  * RETURNS
1021c2c66affSColin Finck  *     Size in bytes
1022c2c66affSColin Finck  */
DPA_GetSize(HDPA hdpa)1023c2c66affSColin Finck ULONGLONG WINAPI DPA_GetSize(HDPA hdpa)
1024c2c66affSColin Finck {
1025c2c66affSColin Finck     TRACE("(%p)\n", hdpa);
1026c2c66affSColin Finck 
1027c2c66affSColin Finck     if (!hdpa) return 0;
1028c2c66affSColin Finck 
1029c2c66affSColin Finck     return sizeof(DPA) + hdpa->nMaxCount*sizeof(PVOID);
1030c2c66affSColin Finck }
1031