blob: 7fda24c16d1a3c916b141eef21f06d4d8518505d [file] [log] [blame]
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001/*
2 * Undocumented functions from COMCTL32.DLL
3 *
Eric Kohlb7546b62000-11-15 22:14:43 +00004 * Copyright 1998 Eric Kohl
Alexandre Julliarda0d77311998-09-13 16:32:00 +00005 * 1998 Juergen Schmied <j.schmied@metronet.de>
Eric Kohlb7546b62000-11-15 22:14:43 +00006 * 2000 Eric Kohl for CodeWeavers
7 *
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00008 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
Alexandre Julliarda0d77311998-09-13 16:32:00 +000022 * NOTES
23 * All of these functions are UNDOCUMENTED!! And I mean UNDOCUMENTED!!!!
24 * Do NOT rely on names or contents of undocumented structures and types!!!
25 * These functions are used by EXPLORER.EXE, IEXPLORE.EXE and
26 * COMCTL32.DLL (internally).
27 *
28 * TODO
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000029 * - Add more functions.
30 * - Write some documentation.
Alexandre Julliarda0d77311998-09-13 16:32:00 +000031 */
Rolf Kalbermatter6c799302002-12-16 22:43:58 +000032#include "config.h"
33#include "wine/port.h"
Alexandre Julliarda0d77311998-09-13 16:32:00 +000034
35#include <string.h>
Marcus Meissner317af321999-02-17 13:51:06 +000036#include <stdlib.h> /* atoi */
Alexandre Julliarda0d77311998-09-13 16:32:00 +000037#include <ctype.h>
Aric Stewartca2f40b2002-01-15 20:43:05 +000038#include <limits.h>
Marcus Meissner317af321999-02-17 13:51:06 +000039
Dimitrie O. Paun297f3d82003-01-07 20:36:20 +000040#define NONAMELESSUNION
41#define NONAMELESSSTRUCT
Patrik Stridvall33929be2001-07-18 21:04:23 +000042#include "commctrl.h"
43#include "objbase.h"
Marcus Meissner9f3eb191999-05-22 11:22:36 +000044#include "winbase.h"
Eric Kohld37b0191999-06-26 11:57:04 +000045#include "winerror.h"
Guy Albertelli45e9cea2001-09-20 18:58:43 +000046#include "winreg.h"
Patrik Stridvall33929be2001-07-18 21:04:23 +000047
Alexandre Julliard5ea22472000-06-13 01:10:29 +000048#include "wine/unicode.h"
Patrik Stridvall33929be2001-07-18 21:04:23 +000049#include "comctl32.h"
50
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000051#include "wine/debug.h"
Alexandre Julliarda0d77311998-09-13 16:32:00 +000052
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000053WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000054
Alexandre Julliarda0d77311998-09-13 16:32:00 +000055
Alexandre Julliarda3960291999-02-26 11:11:13 +000056extern HANDLE COMCTL32_hHeap; /* handle to the private heap */
Alexandre Julliarda0d77311998-09-13 16:32:00 +000057
58
Eric Kohld37b0191999-06-26 11:57:04 +000059typedef struct _STREAMDATA
60{
61 DWORD dwSize;
62 DWORD dwData2;
63 DWORD dwItems;
64} STREAMDATA, *PSTREAMDATA;
65
66typedef struct _LOADDATA
67{
68 INT nCount;
69 PVOID ptr;
70} LOADDATA, *LPLOADDATA;
71
Andreas Mohr2295e872002-02-02 18:06:03 +000072typedef HRESULT (CALLBACK *DPALOADPROC)(LPLOADDATA,IStream*,LPARAM);
Eric Kohld37b0191999-06-26 11:57:04 +000073
Eric Kohld37b0191999-06-26 11:57:04 +000074/**************************************************************************
75 * DPA_LoadStream [COMCTL32.9]
76 *
77 * Loads a dynamic pointer array from a stream
78 *
79 * PARAMS
80 * phDpa [O] pointer to a handle to a dynamic pointer array
81 * loadProc [I] pointer to a callback function
82 * pStream [I] pointer to a stream
83 * lParam [I] application specific value
84 *
85 * NOTES
86 * No more information available yet!
87 */
88
89HRESULT WINAPI
90DPA_LoadStream (HDPA *phDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lParam)
91{
92 HRESULT errCode;
93 LARGE_INTEGER position;
94 ULARGE_INTEGER newPosition;
95 STREAMDATA streamData;
96 LOADDATA loadData;
97 ULONG ulRead;
98 HDPA hDpa;
99 PVOID *ptr;
100
101 FIXME ("phDpa=%p loadProc=%p pStream=%p lParam=%lx\n",
102 phDpa, loadProc, pStream, lParam);
103
104 if (!phDpa || !loadProc || !pStream)
105 return E_INVALIDARG;
106
107 *phDpa = (HDPA)NULL;
108
Patrik Stridvall311e4561999-09-19 14:20:33 +0000109 position.s.LowPart = 0;
110 position.s.HighPart = 0;
Eric Kohld37b0191999-06-26 11:57:04 +0000111
Aric Stewart97b8c572002-01-18 19:04:39 +0000112 /*
113 * Zero out our streamData
114 */
115 memset(&streamData,0,sizeof(STREAMDATA));
116
Eric Kohld37b0191999-06-26 11:57:04 +0000117 errCode = IStream_Seek (pStream, position, STREAM_SEEK_CUR, &newPosition);
118 if (errCode != S_OK)
119 return errCode;
120
121 errCode = IStream_Read (pStream, &streamData, sizeof(STREAMDATA), &ulRead);
122 if (errCode != S_OK)
123 return errCode;
124
125 FIXME ("dwSize=%lu dwData2=%lu dwItems=%lu\n",
126 streamData.dwSize, streamData.dwData2, streamData.dwItems);
127
Aric Stewart97b8c572002-01-18 19:04:39 +0000128 if ( ulRead < sizeof(STREAMDATA) ||
129 lParam < sizeof(STREAMDATA) ||
Eric Kohld37b0191999-06-26 11:57:04 +0000130 streamData.dwSize < sizeof(STREAMDATA) ||
131 streamData.dwData2 < 1) {
132 errCode = E_FAIL;
133 }
134
Aric Stewartca2f40b2002-01-15 20:43:05 +0000135 if (streamData.dwItems > (UINT_MAX / 2 / sizeof(VOID*))) /* 536870911 */
136 return E_OUTOFMEMORY;
137
Eric Kohld37b0191999-06-26 11:57:04 +0000138 /* create the dpa */
139 hDpa = DPA_Create (streamData.dwItems);
140 if (!hDpa)
141 return E_OUTOFMEMORY;
142
143 if (!DPA_Grow (hDpa, streamData.dwItems))
144 return E_OUTOFMEMORY;
145
146 /* load data from the stream into the dpa */
147 ptr = hDpa->ptrs;
148 for (loadData.nCount = 0; loadData.nCount < streamData.dwItems; loadData.nCount++) {
149 errCode = (loadProc)(&loadData, pStream, lParam);
150 if (errCode != S_OK) {
151 errCode = S_FALSE;
152 break;
153 }
154
155 *ptr = loadData.ptr;
156 ptr++;
157 }
158
159 /* set the number of items */
160 hDpa->nItemCount = loadData.nCount;
161
162 /* store the handle to the dpa */
163 *phDpa = hDpa;
164 FIXME ("new hDpa=%p\n", hDpa);
165
166 return errCode;
167}
168
169
170/**************************************************************************
171 * DPA_SaveStream [COMCTL32.10]
172 *
173 * Saves a dynamic pointer array to a stream
174 *
175 * PARAMS
176 * hDpa [I] handle to a dynamic pointer array
177 * loadProc [I] pointer to a callback function
178 * pStream [I] pointer to a stream
179 * lParam [I] application specific value
180 *
181 * NOTES
182 * No more information available yet!
183 */
184
185HRESULT WINAPI
186DPA_SaveStream (const HDPA hDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lParam)
187{
188
189 FIXME ("hDpa=%p loadProc=%p pStream=%p lParam=%lx\n",
190 hDpa, loadProc, pStream, lParam);
191
192 return E_FAIL;
193}
194
195
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000196/**************************************************************************
Eric Kohl0f7d5211998-11-22 17:54:40 +0000197 * DPA_Merge [COMCTL32.11]
Eric Kohl17216d31998-10-11 13:21:17 +0000198 *
199 * PARAMS
Guy L. Albertelli97178452000-11-30 19:58:56 +0000200 * hdpa1 [I] handle to a dynamic pointer array
201 * hdpa2 [I] handle to a dynamic pointer array
202 * dwFlags [I] flags
203 * pfnCompare [I] pointer to sort function
204 * pfnMerge [I] pointer to merge function
205 * lParam [I] application specific value
Eric Kohl17216d31998-10-11 13:21:17 +0000206 *
207 * NOTES
208 * No more information available yet!
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000209 */
210
Alexandre Julliarda3960291999-02-26 11:11:13 +0000211BOOL WINAPI
Eric Kohl0f7d5211998-11-22 17:54:40 +0000212DPA_Merge (const HDPA hdpa1, const HDPA hdpa2, DWORD dwFlags,
Eric Kohld37b0191999-06-26 11:57:04 +0000213 PFNDPACOMPARE pfnCompare, PFNDPAMERGE pfnMerge, LPARAM lParam)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000214{
Ian Schmidt45584801999-07-28 16:35:24 +0000215 INT nCount;
Guy L. Albertelli97178452000-11-30 19:58:56 +0000216 LPVOID *pWork1, *pWork2;
Guy L. Albertellia8bba782002-02-21 20:08:29 +0000217 INT nResult, i;
Ian Schmidt45584801999-07-28 16:35:24 +0000218 INT nIndex;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000219
Guy L. Albertelli97178452000-11-30 19:58:56 +0000220 TRACE("%p %p %08lx %p %p %08lx)\n",
Eric Kohld37b0191999-06-26 11:57:04 +0000221 hdpa1, hdpa2, dwFlags, pfnCompare, pfnMerge, lParam);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000222
Alexandre Julliarda3960291999-02-26 11:11:13 +0000223 if (IsBadWritePtr (hdpa1, sizeof(DPA)))
Eric Kohl0f7d5211998-11-22 17:54:40 +0000224 return FALSE;
225
Alexandre Julliarda3960291999-02-26 11:11:13 +0000226 if (IsBadWritePtr (hdpa2, sizeof(DPA)))
Eric Kohl0f7d5211998-11-22 17:54:40 +0000227 return FALSE;
228
Alexandre Julliarda3960291999-02-26 11:11:13 +0000229 if (IsBadCodePtr ((FARPROC)pfnCompare))
Eric Kohl0f7d5211998-11-22 17:54:40 +0000230 return FALSE;
231
Eric Kohld37b0191999-06-26 11:57:04 +0000232 if (IsBadCodePtr ((FARPROC)pfnMerge))
Eric Kohl0f7d5211998-11-22 17:54:40 +0000233 return FALSE;
234
Guy L. Albertellia8bba782002-02-21 20:08:29 +0000235 if (!(dwFlags & DPAM_NOSORT)) {
Alexandre Julliarda099a551999-06-12 15:45:58 +0000236 TRACE("sorting dpa's!\n");
Eric Kohld37b0191999-06-26 11:57:04 +0000237 if (hdpa1->nItemCount > 0)
Eric Kohl0f7d5211998-11-22 17:54:40 +0000238 DPA_Sort (hdpa1, pfnCompare, lParam);
Eric Kohld37b0191999-06-26 11:57:04 +0000239 TRACE ("dpa 1 sorted!\n");
240 if (hdpa2->nItemCount > 0)
Eric Kohl0f7d5211998-11-22 17:54:40 +0000241 DPA_Sort (hdpa2, pfnCompare, lParam);
Eric Kohld37b0191999-06-26 11:57:04 +0000242 TRACE ("dpa 2 sorted!\n");
Eric Kohl0f7d5211998-11-22 17:54:40 +0000243 }
244
Eric Kohld37b0191999-06-26 11:57:04 +0000245 if (hdpa2->nItemCount < 1)
Eric Kohl0f7d5211998-11-22 17:54:40 +0000246 return TRUE;
247
Eric Kohld37b0191999-06-26 11:57:04 +0000248 TRACE("hdpa1->nItemCount=%d hdpa2->nItemCount=%d\n",
249 hdpa1->nItemCount, hdpa2->nItemCount);
Eric Kohl0f7d5211998-11-22 17:54:40 +0000250
Eric Kohl0f7d5211998-11-22 17:54:40 +0000251
Guy L. Albertelli97178452000-11-30 19:58:56 +0000252 /* working but untrusted implementation */
Eric Kohl0f7d5211998-11-22 17:54:40 +0000253
Eric Kohld37b0191999-06-26 11:57:04 +0000254 pWork1 = &(hdpa1->ptrs[hdpa1->nItemCount - 1]);
255 pWork2 = &(hdpa2->ptrs[hdpa2->nItemCount - 1]);
Eric Kohl0f7d5211998-11-22 17:54:40 +0000256
Eric Kohld37b0191999-06-26 11:57:04 +0000257 nIndex = hdpa1->nItemCount - 1;
258 nCount = hdpa2->nItemCount - 1;
Eric Kohl0f7d5211998-11-22 17:54:40 +0000259
Eric Kohld37b0191999-06-26 11:57:04 +0000260 do
261 {
Guy L. Albertellia8bba782002-02-21 20:08:29 +0000262 if (nIndex < 0) {
263 if ((nCount >= 0) && (dwFlags & DPAM_INSERT)) {
264 /* Now insert the remaining new items into DPA 1 */
265 TRACE("%d items to be inserted at start of DPA 1\n",
266 nCount+1);
267 for (i=nCount; i>=0; i--) {
268 PVOID ptr;
269
270 ptr = (pfnMerge)(3, *pWork2, NULL, lParam);
271 if (!ptr)
272 return FALSE;
273 DPA_InsertPtr (hdpa1, 0, ptr);
274 pWork2--;
275 }
276 }
277 break;
278 }
Guy L. Albertelli97178452000-11-30 19:58:56 +0000279 nResult = (pfnCompare)(*pWork1, *pWork2, lParam);
Vincent Béron9a624912002-05-31 23:06:46 +0000280 TRACE("compare result=%d, dpa1.cnt=%d, dpa2.cnt=%d\n",
Guy L. Albertelli97178452000-11-30 19:58:56 +0000281 nResult, nIndex, nCount);
Eric Kohl0f7d5211998-11-22 17:54:40 +0000282
Eric Kohld37b0191999-06-26 11:57:04 +0000283 if (nResult == 0)
284 {
285 PVOID ptr;
286
Guy L. Albertelli97178452000-11-30 19:58:56 +0000287 ptr = (pfnMerge)(1, *pWork1, *pWork2, lParam);
Eric Kohld37b0191999-06-26 11:57:04 +0000288 if (!ptr)
289 return FALSE;
290
291 nCount--;
292 pWork2--;
Guy L. Albertelli97178452000-11-30 19:58:56 +0000293 *pWork1 = ptr;
294 nIndex--;
295 pWork1--;
Eric Kohl0f7d5211998-11-22 17:54:40 +0000296 }
Guy L. Albertellia8bba782002-02-21 20:08:29 +0000297 else if (nResult > 0)
Eric Kohld37b0191999-06-26 11:57:04 +0000298 {
Guy L. Albertellia8bba782002-02-21 20:08:29 +0000299 /* item in DPA 1 missing from DPA 2 */
300 if (dwFlags & DPAM_DELETE)
Eric Kohld37b0191999-06-26 11:57:04 +0000301 {
Guy L. Albertellia8bba782002-02-21 20:08:29 +0000302 /* Now delete the extra item in DPA1 */
Eric Kohld37b0191999-06-26 11:57:04 +0000303 PVOID ptr;
Eric Kohl0f7d5211998-11-22 17:54:40 +0000304
Eric Kohld37b0191999-06-26 11:57:04 +0000305 ptr = DPA_DeletePtr (hdpa1, hdpa1->nItemCount - 1);
Eric Kohl0f7d5211998-11-22 17:54:40 +0000306
Eric Kohld37b0191999-06-26 11:57:04 +0000307 (pfnMerge)(2, ptr, NULL, lParam);
308 }
Guy L. Albertelli97178452000-11-30 19:58:56 +0000309 nIndex--;
310 pWork1--;
Eric Kohl0f7d5211998-11-22 17:54:40 +0000311 }
Eric Kohld37b0191999-06-26 11:57:04 +0000312 else
313 {
Guy L. Albertellia8bba782002-02-21 20:08:29 +0000314 /* new item in DPA 2 */
315 if (dwFlags & DPAM_INSERT)
Eric Kohld37b0191999-06-26 11:57:04 +0000316 {
Guy L. Albertellia8bba782002-02-21 20:08:29 +0000317 /* Now insert the new item in DPA 1 */
Eric Kohld37b0191999-06-26 11:57:04 +0000318 PVOID ptr;
319
Guy L. Albertelli97178452000-11-30 19:58:56 +0000320 ptr = (pfnMerge)(3, *pWork2, NULL, lParam);
Eric Kohld37b0191999-06-26 11:57:04 +0000321 if (!ptr)
322 return FALSE;
Guy L. Albertellia8bba782002-02-21 20:08:29 +0000323 DPA_InsertPtr (hdpa1, nIndex+1, ptr);
Guy L. Albertelli97178452000-11-30 19:58:56 +0000324 }
Eric Kohld37b0191999-06-26 11:57:04 +0000325 nCount--;
326 pWork2--;
327 }
328
Eric Kohl0f7d5211998-11-22 17:54:40 +0000329 }
Eric Kohld37b0191999-06-26 11:57:04 +0000330 while (nCount >= 0);
Eric Kohl0f7d5211998-11-22 17:54:40 +0000331
Eric Kohl0f7d5211998-11-22 17:54:40 +0000332 return TRUE;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000333}
334
335
336/**************************************************************************
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000337 * Alloc [COMCTL32.71]
338 *
Eric Kohl17216d31998-10-11 13:21:17 +0000339 * Allocates memory block from the dll's private heap
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000340 *
341 * PARAMS
342 * dwSize [I] size of the allocated memory block
343 *
344 * RETURNS
345 * Success: pointer to allocated memory block
346 * Failure: NULL
347 */
348
349LPVOID WINAPI
350COMCTL32_Alloc (DWORD dwSize)
351{
352 LPVOID lpPtr;
353
Alexandre Julliarda099a551999-06-12 15:45:58 +0000354 TRACE("(0x%lx)\n", dwSize);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000355
Eric Kohl17216d31998-10-11 13:21:17 +0000356 lpPtr = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000357
Alexandre Julliarda099a551999-06-12 15:45:58 +0000358 TRACE("-- ret=%p\n", lpPtr);
Eric Kohl17216d31998-10-11 13:21:17 +0000359
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000360 return lpPtr;
361}
362
363
364/**************************************************************************
365 * ReAlloc [COMCTL32.72]
366 *
367 * Changes the size of an allocated memory block or allocates a memory
Eric Kohl17216d31998-10-11 13:21:17 +0000368 * block using the dll's private heap.
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000369 *
370 * PARAMS
371 * lpSrc [I] pointer to memory block which will be resized
372 * dwSize [I] new size of the memory block.
373 *
374 * RETURNS
375 * Success: pointer to the resized memory block
376 * Failure: NULL
377 *
378 * NOTES
379 * If lpSrc is a NULL-pointer, then COMCTL32_ReAlloc allocates a memory
380 * block like COMCTL32_Alloc.
381 */
382
383LPVOID WINAPI
384COMCTL32_ReAlloc (LPVOID lpSrc, DWORD dwSize)
385{
386 LPVOID lpDest;
387
Alexandre Julliarda099a551999-06-12 15:45:58 +0000388 TRACE("(%p 0x%08lx)\n", lpSrc, dwSize);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000389
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000390 if (lpSrc)
Eric Kohl17216d31998-10-11 13:21:17 +0000391 lpDest = HeapReAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, lpSrc, dwSize);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000392 else
Eric Kohl17216d31998-10-11 13:21:17 +0000393 lpDest = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000394
Alexandre Julliarda099a551999-06-12 15:45:58 +0000395 TRACE("-- ret=%p\n", lpDest);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000396
397 return lpDest;
398}
399
400
401/**************************************************************************
402 * Free [COMCTL32.73]
Eric Kohl65016631999-01-24 19:09:56 +0000403 *
Eric Kohl17216d31998-10-11 13:21:17 +0000404 * Frees an allocated memory block from the dll's private heap.
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000405 *
406 * PARAMS
407 * lpMem [I] pointer to memory block which will be freed
408 *
409 * RETURNS
410 * Success: TRUE
411 * Failure: FALSE
412 */
413
Alexandre Julliarda3960291999-02-26 11:11:13 +0000414BOOL WINAPI
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000415COMCTL32_Free (LPVOID lpMem)
416{
Alexandre Julliarda099a551999-06-12 15:45:58 +0000417 TRACE("(%p)\n", lpMem);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000418
Eric Kohl17216d31998-10-11 13:21:17 +0000419 return HeapFree (COMCTL32_hHeap, 0, lpMem);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000420}
421
422
423/**************************************************************************
424 * GetSize [COMCTL32.74]
425 *
426 * Retrieves the size of the specified memory block from the dll's
Eric Kohl17216d31998-10-11 13:21:17 +0000427 * private heap.
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000428 *
429 * PARAMS
430 * lpMem [I] pointer to an allocated memory block
431 *
432 * RETURNS
433 * Success: size of the specified memory block
434 * Failure: 0
435 */
436
437DWORD WINAPI
438COMCTL32_GetSize (LPVOID lpMem)
439{
Alexandre Julliarda099a551999-06-12 15:45:58 +0000440 TRACE("(%p)\n", lpMem);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000441
Eric Kohl17216d31998-10-11 13:21:17 +0000442 return HeapSize (COMCTL32_hHeap, 0, lpMem);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000443}
444
445
446/**************************************************************************
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000447 * The MRU-API is a set of functions to manipulate MRU(Most Recently Used)
448 * lists.
449 *
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000450 * Stored in the reg. as a set of values under a single key. Each item in the
451 * list has a value name that is a single char. 'a' - 'z', '{', '|' or '}'.
452 * The order of the list is stored with value name 'MRUList' which is a string
453 * containing the value names (i.e. 'a', 'b', etc.) in the relevant order.
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000454 */
455
Huw D M Davies02873bb2002-01-14 18:36:03 +0000456typedef struct tagCREATEMRULISTA
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000457{
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000458 DWORD cbSize; /* size of struct */
459 DWORD nMaxItems; /* max no. of items in list */
460 DWORD dwFlags; /* see below */
461 HKEY hKey; /* root reg. key under which list is saved */
462 LPCSTR lpszSubKey; /* reg. subkey */
463 PROC lpfnCompare; /* item compare proc */
Huw D M Davies02873bb2002-01-14 18:36:03 +0000464} CREATEMRULISTA, *LPCREATEMRULISTA;
465
466typedef struct tagCREATEMRULISTW
467{
468 DWORD cbSize; /* size of struct */
469 DWORD nMaxItems; /* max no. of items in list */
470 DWORD dwFlags; /* see below */
471 HKEY hKey; /* root reg. key under which list is saved */
472 LPCWSTR lpszSubKey; /* reg. subkey */
473 PROC lpfnCompare; /* item compare proc */
474} CREATEMRULISTW, *LPCREATEMRULISTW;
Eric Kohl17216d31998-10-11 13:21:17 +0000475
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000476/* dwFlags */
477#define MRUF_STRING_LIST 0 /* list will contain strings */
478#define MRUF_BINARY_LIST 1 /* list will contain binary data */
479#define MRUF_DELAYED_SAVE 2 /* only save list order to reg. is FreeMRUList */
480
481/* If list is a string list lpfnCompare has the following prototype
482 * int CALLBACK MRUCompareString(LPCSTR s1, LPCSTR s2)
483 * for binary lists the prototype is
484 * int CALLBACK MRUCompareBinary(LPCVOID data1, LPCVOID data2, DWORD cbData)
485 * where cbData is the no. of bytes to compare.
486 * Need to check what return value means identical - 0?
487 */
488
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000489typedef struct tagWINEMRUITEM
Eric Kohl17216d31998-10-11 13:21:17 +0000490{
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000491 DWORD size; /* size of data stored */
492 DWORD itemFlag; /* flags */
493 BYTE datastart;
494} WINEMRUITEM, *LPWINEMRUITEM;
495
496/* itemFlag */
497#define WMRUIF_CHANGED 0x0001 /* this dataitem changed */
498
499typedef struct tagWINEMRULIST
500{
Huw D M Davies02873bb2002-01-14 18:36:03 +0000501 CREATEMRULISTW extview; /* original create information */
502 BOOL isUnicode; /* is compare fn Unicode */
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000503 DWORD wineFlags; /* internal flags */
504 DWORD cursize; /* current size of realMRU */
505 LPSTR realMRU; /* pointer to string of index names */
506 LPWINEMRUITEM *array; /* array of pointers to data */
507 /* in 'a' to 'z' order */
508} WINEMRULIST, *LPWINEMRULIST;
509
510/* wineFlags */
511#define WMRUF_CHANGED 0x0001 /* MRU list has changed */
Eric Kohl17216d31998-10-11 13:21:17 +0000512
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000513/**************************************************************************
514 * MRU_SaveChanged - Localize MRU saving code
515 *
516 */
517VOID MRU_SaveChanged( LPWINEMRULIST mp )
518{
Rolf Kalbermatter6c799302002-12-16 22:43:58 +0000519 UINT i, err;
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000520 HKEY newkey;
Huw D M Davies02873bb2002-01-14 18:36:03 +0000521 WCHAR realname[2];
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000522 LPWINEMRUITEM witem;
Huw D M Davies02873bb2002-01-14 18:36:03 +0000523 WCHAR emptyW[] = {'\0'};
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000524
525 /* or should we do the following instead of RegOpenKeyEx:
526 */
527
528 /* open the sub key */
Vincent Béron9a624912002-05-31 23:06:46 +0000529 if ((err = RegOpenKeyExW( mp->extview.hKey, mp->extview.lpszSubKey,
Huw D M Davies02873bb2002-01-14 18:36:03 +0000530 0, KEY_WRITE, &newkey))) {
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000531 /* not present - what to do ??? */
532 ERR("Can not open key, error=%d, attempting to create\n",
533 err);
Huw D M Davies02873bb2002-01-14 18:36:03 +0000534 if ((err = RegCreateKeyExW( mp->extview.hKey, mp->extview.lpszSubKey,
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000535 0,
Huw D M Davies02873bb2002-01-14 18:36:03 +0000536 emptyW,
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000537 REG_OPTION_NON_VOLATILE,
538 KEY_READ | KEY_WRITE,
539 0,
540 &newkey,
541 0))) {
542 ERR("failed to create key /%s/, err=%d\n",
Huw D M Davies02873bb2002-01-14 18:36:03 +0000543 debugstr_w(mp->extview.lpszSubKey), err);
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000544 return;
545 }
546 }
547 if (mp->wineFlags & WMRUF_CHANGED) {
548 mp->wineFlags &= ~WMRUF_CHANGED;
Vincent Béron9a624912002-05-31 23:06:46 +0000549 err = RegSetValueExA(newkey, "MRUList", 0, REG_SZ,
Huw D M Davies02873bb2002-01-14 18:36:03 +0000550 mp->realMRU, strlen(mp->realMRU) + 1);
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000551 if (err) {
552 ERR("error saving MRUList, err=%d\n", err);
553 }
554 TRACE("saving MRUList=/%s/\n", mp->realMRU);
555 }
556 realname[1] = 0;
557 for(i=0; i<mp->cursize; i++) {
558 witem = mp->array[i];
559 if (witem->itemFlag & WMRUIF_CHANGED) {
560 witem->itemFlag &= ~WMRUIF_CHANGED;
561 realname[0] = 'a' + i;
Vincent Béron9a624912002-05-31 23:06:46 +0000562 err = RegSetValueExW(newkey, realname, 0,
563 (mp->extview.dwFlags & MRUF_BINARY_LIST) ?
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000564 REG_BINARY : REG_SZ,
565 &witem->datastart, witem->size);
566 if (err) {
Huw D M Davies02873bb2002-01-14 18:36:03 +0000567 ERR("error saving /%s/, err=%d\n", debugstr_w(realname), err);
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000568 }
569 TRACE("saving value for name /%s/ size=%ld\n",
Huw D M Davies02873bb2002-01-14 18:36:03 +0000570 debugstr_w(realname), witem->size);
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000571 }
572 }
573 RegCloseKey( newkey );
574}
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000575
576/**************************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000577 * FreeMRUList [COMCTL32.152]
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000578 *
579 * PARAMS
580 * hMRUList [I] Handle to list.
581 *
582 */
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000583DWORD WINAPI
Huw D M Davies02873bb2002-01-14 18:36:03 +0000584FreeMRUList (HANDLE hMRUList)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000585{
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000586 LPWINEMRULIST mp = (LPWINEMRULIST)hMRUList;
Rolf Kalbermatter6c799302002-12-16 22:43:58 +0000587 UINT i;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000588
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000589 TRACE("\n");
590 if (mp->wineFlags & WMRUF_CHANGED) {
591 /* need to open key and then save the info */
592 MRU_SaveChanged( mp );
Eric Kohl17216d31998-10-11 13:21:17 +0000593 }
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000594
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000595 for(i=0; i<mp->extview.nMaxItems; i++) {
596 if (mp->array[i])
597 COMCTL32_Free(mp->array[i]);
598 }
599 COMCTL32_Free(mp->realMRU);
600 COMCTL32_Free(mp->array);
Huw D M Davies02873bb2002-01-14 18:36:03 +0000601 COMCTL32_Free((LPWSTR)mp->extview.lpszSubKey);
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000602 return COMCTL32_Free(mp);
603}
Eric Kohl17216d31998-10-11 13:21:17 +0000604
Eric Kohl17216d31998-10-11 13:21:17 +0000605
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000606/**************************************************************************
607 * FindMRUData [COMCTL32.169]
Vincent Béron9a624912002-05-31 23:06:46 +0000608 *
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000609 * Searches binary list for item that matches lpData of length cbData.
610 * Returns position in list order 0 -> MRU and if lpRegNum != NULL then value
611 * corresponding to item's reg. name will be stored in it ('a' -> 0).
612 *
613 * PARAMS
614 * hList [I] list handle
615 * lpData [I] data to find
616 * cbData [I] length of data
617 * lpRegNum [O] position in registry (maybe NULL)
618 *
619 * RETURNS
620 * Position in list 0 -> MRU. -1 if item not found.
621 */
622INT WINAPI
623FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum)
624{
625 LPWINEMRULIST mp = (LPWINEMRULIST)hList;
Rolf Kalbermatter6c799302002-12-16 22:43:58 +0000626 UINT i, ret;
Huw D M Davies02873bb2002-01-14 18:36:03 +0000627 LPSTR dataA = NULL;
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000628
629 if (!mp->extview.lpfnCompare) {
630 ERR("MRU list not properly created. No compare procedure.\n");
631 return -1;
632 }
633
Huw D M Davies02873bb2002-01-14 18:36:03 +0000634 if(!(mp->extview.dwFlags & MRUF_BINARY_LIST) && !mp->isUnicode) {
635 DWORD len = WideCharToMultiByte(CP_ACP, 0, lpData, -1,
636 NULL, 0, NULL, NULL);
637 dataA = COMCTL32_Alloc(len);
638 WideCharToMultiByte(CP_ACP, 0, lpData, -1, dataA, len, NULL, NULL);
639 }
640
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000641 for(i=0; i<mp->cursize; i++) {
642 if (mp->extview.dwFlags & MRUF_BINARY_LIST) {
Vincent Béron9a624912002-05-31 23:06:46 +0000643 if (!mp->extview.lpfnCompare(lpData, &mp->array[i]->datastart,
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000644 cbData))
645 break;
646 }
647 else {
Huw D M Davies02873bb2002-01-14 18:36:03 +0000648 if(mp->isUnicode) {
649 if (!mp->extview.lpfnCompare(lpData, &mp->array[i]->datastart))
650 break;
651 } else {
652 DWORD len = WideCharToMultiByte(CP_ACP, 0,
653 (LPWSTR)&mp->array[i]->datastart, -1,
654 NULL, 0, NULL, NULL);
655 LPSTR itemA = COMCTL32_Alloc(len);
656 INT cmp;
657 WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&mp->array[i]->datastart, -1,
658 itemA, len, NULL, NULL);
659
660 cmp = mp->extview.lpfnCompare(dataA, itemA);
661 COMCTL32_Free(itemA);
662 if(!cmp)
663 break;
664 }
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000665 }
666 }
Huw D M Davies02873bb2002-01-14 18:36:03 +0000667 if(dataA)
668 COMCTL32_Free(dataA);
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000669 if (i < mp->cursize)
670 ret = i;
671 else
672 ret = -1;
673 if (lpRegNum && (ret != -1))
674 *lpRegNum = 'a' + i;
675
Michael Stefaniuc353529b2002-10-23 22:19:10 +0000676 TRACE("(%p, %p, %ld, %p) returning %d\n",
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000677 hList, lpData, cbData, lpRegNum, ret);
678
679 return ret;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000680}
681
682
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000683/**************************************************************************
684 * AddMRUData [COMCTL32.167]
Vincent Béron9a624912002-05-31 23:06:46 +0000685 *
Andreas Mohr99f2f392001-06-22 23:21:47 +0000686 * Add item to MRU binary list. If item already exists in list then it is
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000687 * simply moved up to the top of the list and not added again. If list is
688 * full then the least recently used item is removed to make room.
689 *
690 * PARAMS
691 * hList [I] Handle to list.
692 * lpData [I] ptr to data to add.
693 * cbData [I] no. of bytes of data.
694 *
695 * RETURNS
696 * No. corresponding to registry name where value is stored 'a' -> 0 etc.
697 * -1 on error.
698 */
699INT WINAPI
700AddMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData)
Eric Kohl17216d31998-10-11 13:21:17 +0000701{
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000702 LPWINEMRULIST mp = (LPWINEMRULIST)hList;
703 LPWINEMRUITEM witem;
704 INT i, replace, ret;
Eric Kohl17216d31998-10-11 13:21:17 +0000705
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000706 if ((replace = FindMRUData (hList, lpData, cbData, NULL)) < 0) {
707 /* either add a new entry or replace oldest */
708 if (mp->cursize < mp->extview.nMaxItems) {
709 /* Add in a new item */
710 replace = mp->cursize;
711 mp->cursize++;
712 }
713 else {
714 /* get the oldest entry and replace data */
715 replace = mp->realMRU[mp->cursize - 1] - 'a';
716 COMCTL32_Free(mp->array[replace]);
717 }
718 }
719 else {
720 /* free up the old data */
721 COMCTL32_Free(mp->array[replace]);
722 }
723
724 /* Allocate space for new item and move in the data */
Vincent Béron9a624912002-05-31 23:06:46 +0000725 mp->array[replace] = witem = (LPWINEMRUITEM)COMCTL32_Alloc(cbData +
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000726 sizeof(WINEMRUITEM));
727 witem->itemFlag |= WMRUIF_CHANGED;
728 witem->size = cbData;
729 memcpy( &witem->datastart, lpData, cbData);
730
731 /* now rotate MRU list */
732 mp->wineFlags |= WMRUF_CHANGED;
733 for(i=mp->cursize-1; i>=1; i--) {
734 mp->realMRU[i] = mp->realMRU[i-1];
735 }
736 mp->realMRU[0] = replace + 'a';
Michael Stefaniuc353529b2002-10-23 22:19:10 +0000737 TRACE("(%p, %p, %ld) adding data, /%c/ now most current\n",
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000738 hList, lpData, cbData, replace+'a');
739 ret = replace;
740
741 if (!(mp->extview.dwFlags & MRUF_DELAYED_SAVE)) {
742 /* save changed stuff right now */
743 MRU_SaveChanged( mp );
744 }
745
746 return ret;
Eric Kohl17216d31998-10-11 13:21:17 +0000747}
748
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000749/**************************************************************************
Huw D M Davies02873bb2002-01-14 18:36:03 +0000750 * AddMRUStringW [COMCTL32.401]
Vincent Béron9a624912002-05-31 23:06:46 +0000751 *
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000752 * Add item to MRU string list. If item already exists in list them it is
753 * simply moved up to the top of the list and not added again. If list is
754 * full then the least recently used item is removed to make room.
755 *
756 * PARAMS
757 * hList [I] Handle to list.
758 * lpszString [I] ptr to string to add.
759 *
760 * RETURNS
761 * No. corresponding to registry name where value is stored 'a' -> 0 etc.
762 * -1 on error.
763 */
764INT WINAPI
Huw D M Davies02873bb2002-01-14 18:36:03 +0000765AddMRUStringW(HANDLE hList, LPCWSTR lpszString)
766{
Michael Stefaniuc353529b2002-10-23 22:19:10 +0000767 FIXME("(%p, %s) empty stub!\n", hList, debugstr_w(lpszString));
Huw D M Davies02873bb2002-01-14 18:36:03 +0000768
769 return 0;
770}
771
772/**************************************************************************
773 * AddMRUStringA [COMCTL32.153]
774 */
775INT WINAPI
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000776AddMRUStringA(HANDLE hList, LPCSTR lpszString)
Eric Kohl17216d31998-10-11 13:21:17 +0000777{
Michael Stefaniuc353529b2002-10-23 22:19:10 +0000778 FIXME("(%p, %s) empty stub!\n", hList, debugstr_a(lpszString));
Eric Kohl17216d31998-10-11 13:21:17 +0000779
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000780 return 0;
781}
Eric Kohl17216d31998-10-11 13:21:17 +0000782
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000783/**************************************************************************
784 * DelMRUString [COMCTL32.156]
785 *
786 * Removes item from either string or binary list (despite its name)
787 *
788 * PARAMS
789 * hList [I] list handle
790 * nItemPos [I] item position to remove 0 -> MRU
791 *
792 * RETURNS
Andreas Mohr99f2f392001-06-22 23:21:47 +0000793 * TRUE if successful, FALSE if nItemPos is out of range.
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000794 */
795BOOL WINAPI
796DelMRUString(HANDLE hList, INT nItemPos)
797{
Michael Stefaniuc353529b2002-10-23 22:19:10 +0000798 FIXME("(%p, %d): stub\n", hList, nItemPos);
Eric Kohl3ad67461998-10-24 10:48:31 +0000799 return TRUE;
Eric Kohl17216d31998-10-11 13:21:17 +0000800}
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000801
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000802/**************************************************************************
Huw D M Davies02873bb2002-01-14 18:36:03 +0000803 * FindMRUStringW [COMCTL32.402]
804 */
805INT WINAPI
806FindMRUStringW (HANDLE hList, LPCWSTR lpszString, LPINT lpRegNum)
807{
808 FIXME("stub\n");
809 return -1;
810}
811
812/**************************************************************************
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000813 * FindMRUStringA [COMCTL32.155]
Vincent Béron9a624912002-05-31 23:06:46 +0000814 *
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000815 * Searches string list for item that matches lpszString.
816 * Returns position in list order 0 -> MRU and if lpRegNum != NULL then value
817 * corresponding to item's reg. name will be stored in it ('a' -> 0).
818 *
819 * PARAMS
820 * hList [I] list handle
821 * lpszString [I] string to find
822 * lpRegNum [O] position in registry (maybe NULL)
823 *
824 * RETURNS
825 * Position in list 0 -> MRU. -1 if item not found.
826 */
827INT WINAPI
828FindMRUStringA (HANDLE hList, LPCSTR lpszString, LPINT lpRegNum)
829{
Huw D M Davies02873bb2002-01-14 18:36:03 +0000830 DWORD len = MultiByteToWideChar(CP_ACP, 0, lpszString, -1, NULL, 0);
831 LPWSTR stringW = COMCTL32_Alloc(len * sizeof(WCHAR));
832 INT ret;
833
834 MultiByteToWideChar(CP_ACP, 0, lpszString, -1, stringW, len);
835 ret = FindMRUData(hList, stringW, len * sizeof(WCHAR), lpRegNum);
836 COMCTL32_Free(stringW);
837 return ret;
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000838}
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000839
Huw D M Davies02873bb2002-01-14 18:36:03 +0000840/*************************************************************************
841 * CreateMRUListLazy_common
Patrik Stridvallfcfacb92000-03-24 20:46:04 +0000842 */
Huw D M Davies02873bb2002-01-14 18:36:03 +0000843HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000844{
Rolf Kalbermatter6c799302002-12-16 22:43:58 +0000845 UINT i, err;
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000846 HKEY newkey;
847 DWORD datasize, dwdisp;
Huw D M Davies02873bb2002-01-14 18:36:03 +0000848 WCHAR realname[2];
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000849 LPWINEMRUITEM witem;
850 DWORD type;
Huw D M Davies02873bb2002-01-14 18:36:03 +0000851 WCHAR emptyW[] = {'\0'};
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000852
Huw D M Davies02873bb2002-01-14 18:36:03 +0000853 /* get space to save indices that will turn into names
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000854 * but in order of most to least recently used
855 */
856 mp->realMRU = (LPSTR) COMCTL32_Alloc(mp->extview.nMaxItems + 2);
857
858 /* get space to save pointers to actual data in order of
859 * 'a' to 'z' (0 to n).
860 */
861 mp->array = (LPVOID) COMCTL32_Alloc(mp->extview.nMaxItems *
862 sizeof(LPVOID));
863
864 /* open the sub key */
Vincent Béron9a624912002-05-31 23:06:46 +0000865 if ((err = RegCreateKeyExW( mp->extview.hKey, mp->extview.lpszSubKey,
Huw D M Davies02873bb2002-01-14 18:36:03 +0000866 0,
867 emptyW,
Vincent Béron9a624912002-05-31 23:06:46 +0000868 REG_OPTION_NON_VOLATILE,
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000869 KEY_READ | KEY_WRITE,
870 0,
871 &newkey,
872 &dwdisp))) {
873 /* error - what to do ??? */
874 ERR("(%lu %lu %lx %lx \"%s\" %p): Can not open key, error=%d\n",
Huw D M Davies02873bb2002-01-14 18:36:03 +0000875 mp->extview.cbSize, mp->extview.nMaxItems, mp->extview.dwFlags,
876 (DWORD)mp->extview.hKey, debugstr_w(mp->extview.lpszSubKey),
877 mp->extview.lpfnCompare, err);
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000878 return 0;
879 }
880
881 /* get values from key 'MRUList' */
882 if (newkey) {
883 datasize = mp->extview.nMaxItems + 1;
Vincent Béron9a624912002-05-31 23:06:46 +0000884 if((err=RegQueryValueExA( newkey, "MRUList", 0, &type, mp->realMRU,
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000885 &datasize))) {
886 /* not present - set size to 1 (will become 0 later) */
887 datasize = 1;
888 *mp->realMRU = 0;
889 }
890
891 TRACE("MRU list = %s\n", mp->realMRU);
892
893 mp->cursize = datasize - 1;
894 /* datasize now has number of items in the MRUList */
895
896 /* get actual values for each entry */
897 realname[1] = 0;
898 for(i=0; i<mp->cursize; i++) {
899 realname[0] = 'a' + i;
Huw D M Davies02873bb2002-01-14 18:36:03 +0000900 if(RegQueryValueExW( newkey, realname, 0, &type, 0, &datasize)) {
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000901 /* not present - what to do ??? */
Huw D M Davies02873bb2002-01-14 18:36:03 +0000902 ERR("Key %s not found 1\n", debugstr_w(realname));
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000903 }
Vincent Béron9a624912002-05-31 23:06:46 +0000904 mp->array[i] = witem = (LPWINEMRUITEM)COMCTL32_Alloc(datasize +
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000905 sizeof(WINEMRUITEM));
906 witem->size = datasize;
Vincent Béron9a624912002-05-31 23:06:46 +0000907 if(RegQueryValueExW( newkey, realname, 0, &type,
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000908 &witem->datastart, &datasize)) {
909 /* not present - what to do ??? */
Huw D M Davies02873bb2002-01-14 18:36:03 +0000910 ERR("Key %s not found 2\n", debugstr_w(realname));
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000911 }
912 }
913 RegCloseKey( newkey );
914 }
915 else
916 mp->cursize = 0;
917
918 TRACE("(%lu %lu %lx %lx \"%s\" %p): Current Size = %ld\n",
Huw D M Davies02873bb2002-01-14 18:36:03 +0000919 mp->extview.cbSize, mp->extview.nMaxItems, mp->extview.dwFlags,
920 (DWORD)mp->extview.hKey, debugstr_w(mp->extview.lpszSubKey),
921 mp->extview.lpfnCompare, mp->cursize);
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000922 return (HANDLE)mp;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000923}
924
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000925/**************************************************************************
Huw D M Davies02873bb2002-01-14 18:36:03 +0000926 * CreateMRUListLazyW [COMCTL32.404]
927 */
928HANDLE WINAPI
929CreateMRUListLazyW (LPCREATEMRULISTW lpcml, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
930{
931 LPWINEMRULIST mp;
932
933 if (lpcml == NULL)
934 return 0;
935
936 if (lpcml->cbSize < sizeof(CREATEMRULISTW))
937 return 0;
938
939 mp = (LPWINEMRULIST) COMCTL32_Alloc(sizeof(WINEMRULIST));
940 memcpy(&mp->extview, lpcml, sizeof(CREATEMRULISTW));
941 mp->extview.lpszSubKey = COMCTL32_Alloc((strlenW(lpcml->lpszSubKey) + 1) *
942 sizeof(WCHAR));
943 strcpyW((LPWSTR)mp->extview.lpszSubKey, lpcml->lpszSubKey);
944 mp->isUnicode = TRUE;
945
Vincent Béron9a624912002-05-31 23:06:46 +0000946 return CreateMRUListLazy_common(mp);
Huw D M Davies02873bb2002-01-14 18:36:03 +0000947}
948
949/**************************************************************************
950 * CreateMRUListLazyA [COMCTL32.157]
951 */
952HANDLE WINAPI
953CreateMRUListLazyA (LPCREATEMRULISTA lpcml, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
954{
955 LPWINEMRULIST mp;
956 DWORD len;
957
958 if (lpcml == NULL)
959 return 0;
960
961 if (lpcml->cbSize < sizeof(CREATEMRULISTA))
962 return 0;
963
964 mp = (LPWINEMRULIST) COMCTL32_Alloc(sizeof(WINEMRULIST));
965 memcpy(&mp->extview, lpcml, sizeof(CREATEMRULISTW));
966 len = MultiByteToWideChar(CP_ACP, 0, lpcml->lpszSubKey, -1, NULL, 0);
967 mp->extview.lpszSubKey = COMCTL32_Alloc(len * sizeof(WCHAR));
968 MultiByteToWideChar(CP_ACP, 0, lpcml->lpszSubKey, -1,
969 (LPWSTR)mp->extview.lpszSubKey, len);
970 mp->isUnicode = FALSE;
971 return CreateMRUListLazy_common(mp);
972}
973
974/**************************************************************************
975 * CreateMRUListW [COMCTL32.400]
976 *
977 * PARAMS
978 * lpcml [I] ptr to CREATEMRULIST structure.
979 *
980 * RETURNS
981 * Handle to MRU list.
982 */
983HANDLE WINAPI
984CreateMRUListW (LPCREATEMRULISTW lpcml)
985{
986 return CreateMRUListLazyW(lpcml, 0, 0, 0);
987}
988
989/**************************************************************************
990 * CreateMRUListA [COMCTL32.151]
991 */
992HANDLE WINAPI
993CreateMRUListA (LPCREATEMRULISTA lpcml)
994{
995 return CreateMRUListLazyA (lpcml, 0, 0, 0);
996}
997
998
999/**************************************************************************
1000 * EnumMRUListW [COMCTL32.403]
1001 *
Huw D M Daviesbbe263b1999-12-04 04:01:41 +00001002 * Enumerate item in a list
1003 *
1004 * PARAMS
1005 * hList [I] list handle
1006 * nItemPos [I] item position to enumerate
1007 * lpBuffer [O] buffer to receive item
1008 * nBufferSize [I] size of buffer
1009 *
1010 * RETURNS
1011 * For binary lists specifies how many bytes were copied to buffer, for
1012 * string lists specifies full length of string. Enumerating past the end
1013 * of list returns -1.
1014 * If lpBuffer == NULL or nItemPos is -ve return value is no. of items in
Vincent Béron9a624912002-05-31 23:06:46 +00001015 * the list.
Huw D M Daviesbbe263b1999-12-04 04:01:41 +00001016 */
Huw D M Davies02873bb2002-01-14 18:36:03 +00001017INT WINAPI EnumMRUListW(HANDLE hList, INT nItemPos, LPVOID lpBuffer,
Huw D M Daviesbbe263b1999-12-04 04:01:41 +00001018DWORD nBufferSize)
1019{
Guy Albertelli45e9cea2001-09-20 18:58:43 +00001020 LPWINEMRULIST mp = (LPWINEMRULIST) hList;
1021 LPWINEMRUITEM witem;
1022 INT desired, datasize;
1023
1024 if (nItemPos >= mp->cursize) return -1;
1025 if ((nItemPos < 0) || !lpBuffer) return mp->cursize;
1026 desired = mp->realMRU[nItemPos];
1027 desired -= 'a';
1028 TRACE("nItemPos=%d, desired=%d\n", nItemPos, desired);
1029 witem = mp->array[desired];
Vincent Béron9a624912002-05-31 23:06:46 +00001030 datasize = min( witem->size, nBufferSize );
Guy Albertelli45e9cea2001-09-20 18:58:43 +00001031 memcpy( lpBuffer, &witem->datastart, datasize);
Michael Stefaniuc353529b2002-10-23 22:19:10 +00001032 TRACE("(%p, %d, %p, %ld): returning len=%d\n",
Guy Albertelli45e9cea2001-09-20 18:58:43 +00001033 hList, nItemPos, lpBuffer, nBufferSize, datasize);
1034 return datasize;
Huw D M Daviesbbe263b1999-12-04 04:01:41 +00001035}
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001036
1037/**************************************************************************
Huw D M Davies02873bb2002-01-14 18:36:03 +00001038 * EnumMRUListA [COMCTL32.154]
Vincent Béron9a624912002-05-31 23:06:46 +00001039 *
Huw D M Davies02873bb2002-01-14 18:36:03 +00001040 */
1041INT WINAPI EnumMRUListA(HANDLE hList, INT nItemPos, LPVOID lpBuffer,
1042DWORD nBufferSize)
1043{
1044 LPWINEMRULIST mp = (LPWINEMRULIST) hList;
1045 LPWINEMRUITEM witem;
1046 INT desired, datasize;
1047 DWORD lenA;
1048
1049 if (nItemPos >= mp->cursize) return -1;
1050 if ((nItemPos < 0) || !lpBuffer) return mp->cursize;
1051 desired = mp->realMRU[nItemPos];
1052 desired -= 'a';
1053 TRACE("nItemPos=%d, desired=%d\n", nItemPos, desired);
1054 witem = mp->array[desired];
1055 if(mp->extview.dwFlags & MRUF_BINARY_LIST) {
Vincent Béron9a624912002-05-31 23:06:46 +00001056 datasize = min( witem->size, nBufferSize );
Huw D M Davies02873bb2002-01-14 18:36:03 +00001057 memcpy( lpBuffer, &witem->datastart, datasize);
1058 } else {
1059 lenA = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&witem->datastart, -1,
1060 NULL, 0, NULL, NULL);
1061 datasize = min( witem->size, nBufferSize );
1062 WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&witem->datastart, -1,
1063 lpBuffer, datasize, NULL, NULL);
1064 }
Michael Stefaniuc353529b2002-10-23 22:19:10 +00001065 TRACE("(%p, %d, %p, %ld): returning len=%d\n",
Huw D M Davies02873bb2002-01-14 18:36:03 +00001066 hList, nItemPos, lpBuffer, nBufferSize, datasize);
1067 return datasize;
1068}
Vincent Béron9a624912002-05-31 23:06:46 +00001069
Huw D M Davies02873bb2002-01-14 18:36:03 +00001070
1071/**************************************************************************
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001072 * Str_GetPtrA [COMCTL32.233]
1073 *
1074 * PARAMS
1075 * lpSrc [I]
1076 * lpDest [O]
1077 * nMaxLen [I]
1078 *
1079 * RETURNS
1080 */
1081
Alexandre Julliarda3960291999-02-26 11:11:13 +00001082INT WINAPI
1083Str_GetPtrA (LPCSTR lpSrc, LPSTR lpDest, INT nMaxLen)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001084{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001085 INT len;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001086
Alexandre Julliarda099a551999-06-12 15:45:58 +00001087 TRACE("(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001088
1089 if (!lpDest && lpSrc)
Alexandre Julliardc7e7df82000-08-14 14:41:19 +00001090 return strlen (lpSrc);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001091
1092 if (nMaxLen == 0)
1093 return 0;
1094
1095 if (lpSrc == NULL) {
1096 lpDest[0] = '\0';
1097 return 0;
1098 }
1099
Alexandre Julliardc7e7df82000-08-14 14:41:19 +00001100 len = strlen (lpSrc);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001101 if (len >= nMaxLen)
1102 len = nMaxLen - 1;
1103
1104 RtlMoveMemory (lpDest, lpSrc, len);
1105 lpDest[len] = '\0';
1106
1107 return len;
1108}
1109
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001110
1111/**************************************************************************
1112 * Str_SetPtrA [COMCTL32.234]
1113 *
1114 * PARAMS
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001115 * lppDest [O]
1116 * lpSrc [I]
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001117 *
1118 * RETURNS
1119 */
1120
Alexandre Julliarda3960291999-02-26 11:11:13 +00001121BOOL WINAPI
1122Str_SetPtrA (LPSTR *lppDest, LPCSTR lpSrc)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001123{
Alexandre Julliarda099a551999-06-12 15:45:58 +00001124 TRACE("(%p %p)\n", lppDest, lpSrc);
Vincent Béron9a624912002-05-31 23:06:46 +00001125
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001126 if (lpSrc) {
Alexandre Julliardc7e7df82000-08-14 14:41:19 +00001127 LPSTR ptr = COMCTL32_ReAlloc (*lppDest, strlen (lpSrc) + 1);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001128 if (!ptr)
1129 return FALSE;
Alexandre Julliardc7e7df82000-08-14 14:41:19 +00001130 strcpy (ptr, lpSrc);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001131 *lppDest = ptr;
1132 }
1133 else {
1134 if (*lppDest) {
1135 COMCTL32_Free (*lppDest);
1136 *lppDest = NULL;
1137 }
1138 }
1139
1140 return TRUE;
1141}
1142
1143
1144/**************************************************************************
1145 * Str_GetPtrW [COMCTL32.235]
1146 *
1147 * PARAMS
1148 * lpSrc [I]
1149 * lpDest [O]
1150 * nMaxLen [I]
1151 *
1152 * RETURNS
1153 */
1154
Alexandre Julliarda3960291999-02-26 11:11:13 +00001155INT WINAPI
1156Str_GetPtrW (LPCWSTR lpSrc, LPWSTR lpDest, INT nMaxLen)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001157{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001158 INT len;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001159
Alexandre Julliarda099a551999-06-12 15:45:58 +00001160 TRACE("(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001161
1162 if (!lpDest && lpSrc)
Alexandre Julliardc7e7df82000-08-14 14:41:19 +00001163 return strlenW (lpSrc);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001164
1165 if (nMaxLen == 0)
1166 return 0;
1167
1168 if (lpSrc == NULL) {
1169 lpDest[0] = L'\0';
1170 return 0;
1171 }
1172
Alexandre Julliardc7e7df82000-08-14 14:41:19 +00001173 len = strlenW (lpSrc);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001174 if (len >= nMaxLen)
1175 len = nMaxLen - 1;
1176
1177 RtlMoveMemory (lpDest, lpSrc, len*sizeof(WCHAR));
1178 lpDest[len] = L'\0';
1179
1180 return len;
1181}
1182
1183
1184/**************************************************************************
1185 * Str_SetPtrW [COMCTL32.236]
1186 *
1187 * PARAMS
1188 * lpDest [O]
1189 * lpSrc [I]
1190 *
1191 * RETURNS
1192 */
1193
Alexandre Julliarda3960291999-02-26 11:11:13 +00001194BOOL WINAPI
1195Str_SetPtrW (LPWSTR *lppDest, LPCWSTR lpSrc)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001196{
Alexandre Julliarda099a551999-06-12 15:45:58 +00001197 TRACE("(%p %p)\n", lppDest, lpSrc);
Vincent Béron9a624912002-05-31 23:06:46 +00001198
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001199 if (lpSrc) {
Alexandre Julliardc7e7df82000-08-14 14:41:19 +00001200 INT len = strlenW (lpSrc) + 1;
Eric Kohl0f7d5211998-11-22 17:54:40 +00001201 LPWSTR ptr = COMCTL32_ReAlloc (*lppDest, len * sizeof(WCHAR));
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001202 if (!ptr)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001203 return FALSE;
Alexandre Julliardc7e7df82000-08-14 14:41:19 +00001204 strcpyW (ptr, lpSrc);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001205 *lppDest = ptr;
1206 }
1207 else {
1208 if (*lppDest) {
1209 COMCTL32_Free (*lppDest);
1210 *lppDest = NULL;
1211 }
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001212 }
1213
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001214 return TRUE;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001215}
1216
1217
1218/**************************************************************************
Eric Kohlb7546b62000-11-15 22:14:43 +00001219 * Str_GetPtrWtoA [internal]
1220 *
1221 * Converts a unicode string into a multi byte string
1222 *
1223 * PARAMS
1224 * lpSrc [I] Pointer to the unicode source string
1225 * lpDest [O] Pointer to caller supplied storage for the multi byte string
1226 * nMaxLen [I] Size, in bytes, of the destination buffer
1227 *
1228 * RETURNS
1229 * Length, in bytes, of the converted string.
1230 */
1231
1232INT
1233Str_GetPtrWtoA (LPCWSTR lpSrc, LPSTR lpDest, INT nMaxLen)
1234{
1235 INT len;
1236
1237 TRACE("(%s %p %d)\n", debugstr_w(lpSrc), lpDest, nMaxLen);
1238
1239 if (!lpDest && lpSrc)
1240 return WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL);
1241
1242 if (nMaxLen == 0)
1243 return 0;
1244
1245 if (lpSrc == NULL) {
1246 lpDest[0] = '\0';
1247 return 0;
1248 }
1249
1250 len = WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL);
1251 if (len >= nMaxLen)
1252 len = nMaxLen - 1;
1253
1254 WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, lpDest, len, NULL, NULL);
1255 lpDest[len] = '\0';
1256
1257 return len;
1258}
1259
1260
1261/**************************************************************************
1262 * Str_SetPtrAtoW [internal]
1263 *
1264 * Converts a multi byte string to a unicode string.
1265 * If the pointer to the destination buffer is NULL a buffer is allocated.
1266 * If the destination buffer is too small to keep the converted multi byte
1267 * string the destination buffer is reallocated. If the source pointer is
1268 * NULL, the destination buffer is freed.
1269 *
1270 * PARAMS
1271 * lppDest [I/O] pointer to a pointer to the destination buffer
1272 * lpSrc [I] pointer to a multi byte string
1273 *
1274 * RETURNS
1275 * TRUE: conversion successful
1276 * FALSE: error
1277 */
1278
1279BOOL
1280Str_SetPtrAtoW (LPWSTR *lppDest, LPCSTR lpSrc)
1281{
1282 TRACE("(%p %s)\n", lppDest, lpSrc);
1283
1284 if (lpSrc) {
1285 INT len = MultiByteToWideChar(CP_ACP,0,lpSrc,-1,NULL,0);
Marcus Meissnerc2806fa2000-11-25 01:20:53 +00001286 LPWSTR ptr = COMCTL32_ReAlloc (*lppDest, len*sizeof(WCHAR));
Eric Kohlb7546b62000-11-15 22:14:43 +00001287
1288 if (!ptr)
1289 return FALSE;
1290 MultiByteToWideChar(CP_ACP,0,lpSrc,-1,ptr,len);
1291 *lppDest = ptr;
1292 }
1293 else {
1294 if (*lppDest) {
1295 COMCTL32_Free (*lppDest);
1296 *lppDest = NULL;
1297 }
1298 }
1299
1300 return TRUE;
1301}
1302
1303
1304/**************************************************************************
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001305 * The DSA-API is a set of functions to create and manipulate arrays of
Andreas Mohrfd79ce02000-07-08 11:44:20 +00001306 * fixed-size memory blocks. These arrays can store any kind of data
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001307 * (strings, icons...).
1308 */
1309
1310/**************************************************************************
1311 * DSA_Create [COMCTL32.320] Creates a dynamic storage array
1312 *
1313 * PARAMS
1314 * nSize [I] size of the array elements
1315 * nGrow [I] number of elements by which the array grows when it is filled
1316 *
1317 * RETURNS
Andreas Mohrfd79ce02000-07-08 11:44:20 +00001318 * Success: pointer to an array control structure. Use this like a handle.
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001319 * Failure: NULL
1320 */
1321
1322HDSA WINAPI
Alexandre Julliarda3960291999-02-26 11:11:13 +00001323DSA_Create (INT nSize, INT nGrow)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001324{
1325 HDSA hdsa;
1326
Alexandre Julliarda099a551999-06-12 15:45:58 +00001327 TRACE("(size=%d grow=%d)\n", nSize, nGrow);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001328
1329 hdsa = (HDSA)COMCTL32_Alloc (sizeof(DSA));
1330 if (hdsa)
1331 {
1332 hdsa->nItemCount = 0;
1333 hdsa->pData = NULL;
1334 hdsa->nMaxCount = 0;
1335 hdsa->nItemSize = nSize;
Francois Gouget6d77d3a2000-03-25 21:44:35 +00001336 hdsa->nGrow = max(1, nGrow);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001337 }
1338
1339 return hdsa;
1340}
1341
1342
1343/**************************************************************************
1344 * DSA_Destroy [COMCTL32.321] Destroys a dynamic storage array
1345 *
1346 * PARAMS
1347 * hdsa [I] pointer to the array control structure
1348 *
1349 * RETURNS
1350 * Success: TRUE
1351 * Failure: FALSE
1352 */
1353
Alexandre Julliarda3960291999-02-26 11:11:13 +00001354BOOL WINAPI
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001355DSA_Destroy (const HDSA hdsa)
1356{
Alexandre Julliarda099a551999-06-12 15:45:58 +00001357 TRACE("(%p)\n", hdsa);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001358
1359 if (!hdsa)
1360 return FALSE;
1361
1362 if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
1363 return FALSE;
1364
1365 return COMCTL32_Free (hdsa);
1366}
1367
1368
1369/**************************************************************************
Vincent Béron9a624912002-05-31 23:06:46 +00001370 * DSA_GetItem [COMCTL32.322]
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001371 *
1372 * PARAMS
1373 * hdsa [I] pointer to the array control structure
1374 * nIndex [I] number of the Item to get
1375 * pDest [O] destination buffer. Has to be >= dwElementSize.
1376 *
1377 * RETURNS
1378 * Success: TRUE
1379 * Failure: FALSE
1380 */
1381
Alexandre Julliarda3960291999-02-26 11:11:13 +00001382BOOL WINAPI
1383DSA_GetItem (const HDSA hdsa, INT nIndex, LPVOID pDest)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001384{
1385 LPVOID pSrc;
1386
Alexandre Julliarda099a551999-06-12 15:45:58 +00001387 TRACE("(%p %d %p)\n", hdsa, nIndex, pDest);
Vincent Béron9a624912002-05-31 23:06:46 +00001388
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001389 if (!hdsa)
1390 return FALSE;
1391 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
1392 return FALSE;
1393
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001394 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001395 memmove (pDest, pSrc, hdsa->nItemSize);
1396
1397 return TRUE;
1398}
1399
1400
1401/**************************************************************************
Vincent Béron9a624912002-05-31 23:06:46 +00001402 * DSA_GetItemPtr [COMCTL32.323]
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001403 *
1404 * Retrieves a pointer to the specified item.
1405 *
1406 * PARAMS
1407 * hdsa [I] pointer to the array control structure
1408 * nIndex [I] index of the desired item
1409 *
1410 * RETURNS
1411 * Success: pointer to an item
1412 * Failure: NULL
1413 */
1414
1415LPVOID WINAPI
Alexandre Julliarda3960291999-02-26 11:11:13 +00001416DSA_GetItemPtr (const HDSA hdsa, INT nIndex)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001417{
1418 LPVOID pSrc;
1419
Alexandre Julliarda099a551999-06-12 15:45:58 +00001420 TRACE("(%p %d)\n", hdsa, nIndex);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001421
1422 if (!hdsa)
1423 return NULL;
1424 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
1425 return NULL;
1426
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001427 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
Vincent Béron9a624912002-05-31 23:06:46 +00001428
Alexandre Julliarda099a551999-06-12 15:45:58 +00001429 TRACE("-- ret=%p\n", pSrc);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001430
Andreas Mohrfd79ce02000-07-08 11:44:20 +00001431 return pSrc;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001432}
1433
1434
1435/**************************************************************************
Vincent Béron9a624912002-05-31 23:06:46 +00001436 * DSA_SetItem [COMCTL32.325]
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001437 *
1438 * Sets the contents of an item in the array.
1439 *
1440 * PARAMS
1441 * hdsa [I] pointer to the array control structure
1442 * nIndex [I] index for the item
1443 * pSrc [I] pointer to the new item data
1444 *
1445 * RETURNS
1446 * Success: TRUE
1447 * Failure: FALSE
1448 */
1449
Alexandre Julliarda3960291999-02-26 11:11:13 +00001450BOOL WINAPI
1451DSA_SetItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001452{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001453 INT nSize, nNewItems;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001454 LPVOID pDest, lpTemp;
Vincent Béron9a624912002-05-31 23:06:46 +00001455
Alexandre Julliarda099a551999-06-12 15:45:58 +00001456 TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001457
1458 if ((!hdsa) || nIndex < 0)
1459 return FALSE;
Vincent Béron9a624912002-05-31 23:06:46 +00001460
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001461 if (hdsa->nItemCount <= nIndex) {
1462 /* within the old array */
1463 if (hdsa->nMaxCount > nIndex) {
1464 /* within the allocated space, set a new boundary */
Ian Schmidt64eed991999-06-12 06:48:49 +00001465 hdsa->nItemCount = nIndex + 1;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001466 }
1467 else {
1468 /* resize the block of memory */
1469 nNewItems =
Eric Pouech200f89211999-09-13 15:11:02 +00001470 hdsa->nGrow * ((INT)(((nIndex + 1) - 1) / hdsa->nGrow) + 1);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001471 nSize = hdsa->nItemSize * nNewItems;
1472
1473 lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
1474 if (!lpTemp)
1475 return FALSE;
1476
1477 hdsa->nMaxCount = nNewItems;
Ian Schmidt64eed991999-06-12 06:48:49 +00001478 hdsa->nItemCount = nIndex + 1;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001479 hdsa->pData = lpTemp;
Vincent Béron9a624912002-05-31 23:06:46 +00001480 }
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001481 }
1482
1483 /* put the new entry in */
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001484 pDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
Alexandre Julliarda099a551999-06-12 15:45:58 +00001485 TRACE("-- move dest=%p src=%p size=%d\n",
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001486 pDest, pSrc, hdsa->nItemSize);
1487 memmove (pDest, pSrc, hdsa->nItemSize);
1488
1489 return TRUE;
1490}
1491
1492
1493/**************************************************************************
Vincent Béron9a624912002-05-31 23:06:46 +00001494 * DSA_InsertItem [COMCTL32.324]
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001495 *
1496 * PARAMS
1497 * hdsa [I] pointer to the array control structure
1498 * nIndex [I] index for the new item
1499 * pSrc [I] pointer to the element
1500 *
1501 * RETURNS
1502 * Success: position of the new item
1503 * Failure: -1
1504 */
1505
Alexandre Julliarda3960291999-02-26 11:11:13 +00001506INT WINAPI
1507DSA_InsertItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001508{
Huw D M Davies8ebf7c22002-01-29 16:56:48 +00001509 INT nNewItems, nSize;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001510 LPVOID lpTemp, lpDest;
Vincent Béron9a624912002-05-31 23:06:46 +00001511
Alexandre Julliarda099a551999-06-12 15:45:58 +00001512 TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001513
1514 if ((!hdsa) || nIndex < 0)
1515 return -1;
1516
Andreas Mohrfd79ce02000-07-08 11:44:20 +00001517 /* when nIndex >= nItemCount then append */
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001518 if (nIndex >= hdsa->nItemCount)
1519 nIndex = hdsa->nItemCount;
1520
1521 /* do we need to resize ? */
1522 if (hdsa->nItemCount >= hdsa->nMaxCount) {
1523 nNewItems = hdsa->nMaxCount + hdsa->nGrow;
1524 nSize = hdsa->nItemSize * nNewItems;
1525
1526 lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
1527 if (!lpTemp)
1528 return -1;
1529
1530 hdsa->nMaxCount = nNewItems;
Vincent Béron9a624912002-05-31 23:06:46 +00001531 hdsa->pData = lpTemp;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001532 }
1533
1534 /* do we need to move elements ? */
1535 if (nIndex < hdsa->nItemCount) {
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001536 lpTemp = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1537 lpDest = (char *) lpTemp + hdsa->nItemSize;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001538 nSize = (hdsa->nItemCount - nIndex) * hdsa->nItemSize;
Alexandre Julliarda099a551999-06-12 15:45:58 +00001539 TRACE("-- move dest=%p src=%p size=%d\n",
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001540 lpDest, lpTemp, nSize);
1541 memmove (lpDest, lpTemp, nSize);
1542 }
1543
1544 /* ok, we can put the new Item in */
1545 hdsa->nItemCount++;
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001546 lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
Alexandre Julliarda099a551999-06-12 15:45:58 +00001547 TRACE("-- move dest=%p src=%p size=%d\n",
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001548 lpDest, pSrc, hdsa->nItemSize);
1549 memmove (lpDest, pSrc, hdsa->nItemSize);
1550
Andreas Mohrfd79ce02000-07-08 11:44:20 +00001551 return nIndex;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001552}
1553
1554
1555/**************************************************************************
Vincent Béron9a624912002-05-31 23:06:46 +00001556 * DSA_DeleteItem [COMCTL32.326]
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001557 *
1558 * PARAMS
1559 * hdsa [I] pointer to the array control structure
1560 * nIndex [I] index for the element to delete
1561 *
1562 * RETURNS
1563 * Success: number of the deleted element
1564 * Failure: -1
1565 */
1566
Alexandre Julliarda3960291999-02-26 11:11:13 +00001567INT WINAPI
1568DSA_DeleteItem (const HDSA hdsa, INT nIndex)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001569{
1570 LPVOID lpDest,lpSrc;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001571 INT nSize;
Vincent Béron9a624912002-05-31 23:06:46 +00001572
Alexandre Julliarda099a551999-06-12 15:45:58 +00001573 TRACE("(%p %d)\n", hdsa, nIndex);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001574
1575 if (!hdsa)
1576 return -1;
1577 if (nIndex < 0 || nIndex >= hdsa->nItemCount)
1578 return -1;
1579
1580 /* do we need to move ? */
1581 if (nIndex < hdsa->nItemCount - 1) {
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001582 lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1583 lpSrc = (char *) lpDest + hdsa->nItemSize;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001584 nSize = hdsa->nItemSize * (hdsa->nItemCount - nIndex - 1);
Alexandre Julliarda099a551999-06-12 15:45:58 +00001585 TRACE("-- move dest=%p src=%p size=%d\n",
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001586 lpDest, lpSrc, nSize);
1587 memmove (lpDest, lpSrc, nSize);
1588 }
Vincent Béron9a624912002-05-31 23:06:46 +00001589
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001590 hdsa->nItemCount--;
Vincent Béron9a624912002-05-31 23:06:46 +00001591
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001592 /* free memory ? */
1593 if ((hdsa->nMaxCount - hdsa->nItemCount) >= hdsa->nGrow) {
1594 nSize = hdsa->nItemSize * hdsa->nItemCount;
1595
1596 lpDest = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
1597 if (!lpDest)
1598 return -1;
1599
1600 hdsa->nMaxCount = hdsa->nItemCount;
1601 hdsa->pData = lpDest;
1602 }
1603
1604 return nIndex;
1605}
1606
1607
1608/**************************************************************************
Patrik Stridvall60767292001-06-19 03:34:07 +00001609 * DSA_DeleteAllItems [COMCTL32.327]
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001610 *
1611 * Removes all items and reinitializes the array.
1612 *
1613 * PARAMS
1614 * hdsa [I] pointer to the array control structure
1615 *
1616 * RETURNS
1617 * Success: TRUE
1618 * Failure: FALSE
1619 */
1620
Alexandre Julliarda3960291999-02-26 11:11:13 +00001621BOOL WINAPI
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001622DSA_DeleteAllItems (const HDSA hdsa)
1623{
Alexandre Julliarda099a551999-06-12 15:45:58 +00001624 TRACE("(%p)\n", hdsa);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001625
Vincent Béron9a624912002-05-31 23:06:46 +00001626 if (!hdsa)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001627 return FALSE;
1628 if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
1629 return FALSE;
1630
1631 hdsa->nItemCount = 0;
1632 hdsa->pData = NULL;
1633 hdsa->nMaxCount = 0;
1634
1635 return TRUE;
1636}
1637
1638
1639/**************************************************************************
1640 * The DPA-API is a set of functions to create and manipulate arrays of
1641 * pointers.
1642 */
1643
1644/**************************************************************************
1645 * DPA_Create [COMCTL32.328] Creates a dynamic pointer array
1646 *
1647 * PARAMS
1648 * nGrow [I] number of items by which the array grows when it is filled
1649 *
1650 * RETURNS
1651 * Success: handle (pointer) to the pointer array.
1652 * Failure: NULL
1653 */
1654
1655HDPA WINAPI
Alexandre Julliarda3960291999-02-26 11:11:13 +00001656DPA_Create (INT nGrow)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001657{
1658 HDPA hdpa;
1659
Alexandre Julliarda099a551999-06-12 15:45:58 +00001660 TRACE("(%d)\n", nGrow);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001661
1662 hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
1663 if (hdpa) {
Francois Gouget6d77d3a2000-03-25 21:44:35 +00001664 hdpa->nGrow = max(8, nGrow);
Eric Kohl17216d31998-10-11 13:21:17 +00001665 hdpa->hHeap = COMCTL32_hHeap;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001666 hdpa->nMaxCount = hdpa->nGrow * 2;
1667 hdpa->ptrs =
1668 (LPVOID*)COMCTL32_Alloc (hdpa->nMaxCount * sizeof(LPVOID));
1669 }
1670
Alexandre Julliarda099a551999-06-12 15:45:58 +00001671 TRACE("-- %p\n", hdpa);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001672
1673 return hdpa;
1674}
1675
1676
1677/**************************************************************************
1678 * DPA_Destroy [COMCTL32.329] Destroys a dynamic pointer array
1679 *
1680 * PARAMS
1681 * hdpa [I] handle (pointer) to the pointer array
1682 *
1683 * RETURNS
1684 * Success: TRUE
1685 * Failure: FALSE
1686 */
1687
Alexandre Julliarda3960291999-02-26 11:11:13 +00001688BOOL WINAPI
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001689DPA_Destroy (const HDPA hdpa)
1690{
Alexandre Julliarda099a551999-06-12 15:45:58 +00001691 TRACE("(%p)\n", hdpa);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001692
1693 if (!hdpa)
1694 return FALSE;
1695
1696 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
1697 return FALSE;
1698
1699 return HeapFree (hdpa->hHeap, 0, hdpa);
1700}
1701
1702
1703/**************************************************************************
1704 * DPA_Grow [COMCTL32.330]
1705 *
1706 * Sets the growth amount.
1707 *
1708 * PARAMS
1709 * hdpa [I] handle (pointer) to the existing (source) pointer array
Andreas Mohr99f2f392001-06-22 23:21:47 +00001710 * nGrow [I] number of items by which the array grows when it's too small
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001711 *
1712 * RETURNS
1713 * Success: TRUE
1714 * Failure: FALSE
1715 */
1716
Alexandre Julliarda3960291999-02-26 11:11:13 +00001717BOOL WINAPI
1718DPA_Grow (const HDPA hdpa, INT nGrow)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001719{
Alexandre Julliarda099a551999-06-12 15:45:58 +00001720 TRACE("(%p %d)\n", hdpa, nGrow);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001721
1722 if (!hdpa)
1723 return FALSE;
1724
Francois Gouget6d77d3a2000-03-25 21:44:35 +00001725 hdpa->nGrow = max(8, nGrow);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001726
1727 return TRUE;
1728}
1729
1730
1731/**************************************************************************
1732 * DPA_Clone [COMCTL32.331]
1733 *
1734 * Copies a pointer array to an other one or creates a copy
1735 *
1736 * PARAMS
1737 * hdpa [I] handle (pointer) to the existing (source) pointer array
1738 * hdpaNew [O] handle (pointer) to the destination pointer array
1739 *
1740 * RETURNS
1741 * Success: pointer to the destination pointer array.
1742 * Failure: NULL
1743 *
1744 * NOTES
1745 * - If the 'hdpaNew' is a NULL-Pointer, a copy of the source pointer
1746 * array will be created and it's handle (pointer) is returned.
1747 * - If 'hdpa' is a NULL-Pointer, the original implementation crashes,
1748 * this implementation just returns NULL.
1749 */
1750
1751HDPA WINAPI
1752DPA_Clone (const HDPA hdpa, const HDPA hdpaNew)
1753{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001754 INT nNewItems, nSize;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001755 HDPA hdpaTemp;
1756
1757 if (!hdpa)
1758 return NULL;
1759
Alexandre Julliarda099a551999-06-12 15:45:58 +00001760 TRACE("(%p %p)\n", hdpa, hdpaNew);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001761
1762 if (!hdpaNew) {
1763 /* create a new DPA */
1764 hdpaTemp = (HDPA)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1765 sizeof(DPA));
1766 hdpaTemp->hHeap = hdpa->hHeap;
1767 hdpaTemp->nGrow = hdpa->nGrow;
1768 }
1769 else
1770 hdpaTemp = hdpaNew;
1771
1772 if (hdpaTemp->ptrs) {
1773 /* remove old pointer array */
1774 HeapFree (hdpaTemp->hHeap, 0, hdpaTemp->ptrs);
1775 hdpaTemp->ptrs = NULL;
1776 hdpaTemp->nItemCount = 0;
1777 hdpaTemp->nMaxCount = 0;
1778 }
1779
1780 /* create a new pointer array */
1781 nNewItems = hdpaTemp->nGrow *
Alexandre Julliarda3960291999-02-26 11:11:13 +00001782 ((INT)((hdpa->nItemCount - 1) / hdpaTemp->nGrow) + 1);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001783 nSize = nNewItems * sizeof(LPVOID);
1784 hdpaTemp->ptrs =
1785 (LPVOID*)HeapAlloc (hdpaTemp->hHeap, HEAP_ZERO_MEMORY, nSize);
1786 hdpaTemp->nMaxCount = nNewItems;
1787
1788 /* clone the pointer array */
1789 hdpaTemp->nItemCount = hdpa->nItemCount;
1790 memmove (hdpaTemp->ptrs, hdpa->ptrs,
1791 hdpaTemp->nItemCount * sizeof(LPVOID));
1792
1793 return hdpaTemp;
1794}
1795
1796
1797/**************************************************************************
1798 * DPA_GetPtr [COMCTL32.332]
1799 *
1800 * Retrieves a pointer from a dynamic pointer array
1801 *
1802 * PARAMS
1803 * hdpa [I] handle (pointer) to the pointer array
1804 * nIndex [I] array index of the desired pointer
1805 *
1806 * RETURNS
1807 * Success: pointer
1808 * Failure: NULL
1809 */
1810
1811LPVOID WINAPI
Jon Griffithscd4234a2003-03-18 18:35:48 +00001812DPA_GetPtr (const HDPA hdpa, INT nIndex)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001813{
Jon Griffithscd4234a2003-03-18 18:35:48 +00001814 TRACE("(%p %d)\n", hdpa, nIndex);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001815
1816 if (!hdpa)
1817 return NULL;
Marcus Meissnerddedfa22000-11-04 02:56:38 +00001818 if (!hdpa->ptrs) {
1819 WARN("no pointer array.\n");
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001820 return NULL;
Marcus Meissnerddedfa22000-11-04 02:56:38 +00001821 }
Jon Griffithscd4234a2003-03-18 18:35:48 +00001822 if ((nIndex < 0) || (nIndex >= hdpa->nItemCount)) {
1823 WARN("not enough pointers in array (%d vs %d).\n",nIndex,hdpa->nItemCount);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001824 return NULL;
Marcus Meissnerddedfa22000-11-04 02:56:38 +00001825 }
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001826
Jon Griffithscd4234a2003-03-18 18:35:48 +00001827 TRACE("-- %p\n", hdpa->ptrs[nIndex]);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001828
Jon Griffithscd4234a2003-03-18 18:35:48 +00001829 return hdpa->ptrs[nIndex];
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001830}
1831
1832
1833/**************************************************************************
1834 * DPA_GetPtrIndex [COMCTL32.333]
1835 *
1836 * Retrieves the index of the specified pointer
1837 *
1838 * PARAMS
1839 * hdpa [I] handle (pointer) to the pointer array
1840 * p [I] pointer
1841 *
1842 * RETURNS
1843 * Success: index of the specified pointer
1844 * Failure: -1
1845 */
1846
Alexandre Julliarda3960291999-02-26 11:11:13 +00001847INT WINAPI
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001848DPA_GetPtrIndex (const HDPA hdpa, LPVOID p)
1849{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001850 INT i;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001851
Dmitry Timoshkovcc7042f2002-08-16 01:43:11 +00001852 if (!hdpa || !hdpa->ptrs)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001853 return -1;
1854
1855 for (i = 0; i < hdpa->nItemCount; i++) {
1856 if (hdpa->ptrs[i] == p)
1857 return i;
1858 }
1859
1860 return -1;
1861}
1862
1863
1864/**************************************************************************
1865 * DPA_InsertPtr [COMCTL32.334]
1866 *
1867 * Inserts a pointer into a dynamic pointer array
1868 *
1869 * PARAMS
1870 * hdpa [I] handle (pointer) to the array
1871 * i [I] array index
1872 * p [I] pointer to insert
1873 *
1874 * RETURNS
1875 * Success: index of the inserted pointer
1876 * Failure: -1
1877 */
1878
Alexandre Julliarda3960291999-02-26 11:11:13 +00001879INT WINAPI
1880DPA_InsertPtr (const HDPA hdpa, INT i, LPVOID p)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001881{
Alexandre Julliarda099a551999-06-12 15:45:58 +00001882 TRACE("(%p %d %p)\n", hdpa, i, p);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001883
Dimitrie O. Paun78883852002-10-21 19:48:37 +00001884 if (!hdpa || i < 0) return -1;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001885
Dimitrie O. Paun5ffde292002-10-23 23:32:19 +00001886 if (i >= 0x7fff)
Dimitrie O. Paun254e7482002-10-21 19:54:06 +00001887 i = hdpa->nItemCount;
1888
Dimitrie O. Paun78883852002-10-21 19:48:37 +00001889 if (i >= hdpa->nItemCount)
1890 return DPA_SetPtr(hdpa, i, p) ? i : -1;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001891
Dimitrie O. Paun78883852002-10-21 19:48:37 +00001892 /* create empty spot at the end */
1893 if (!DPA_SetPtr(hdpa, hdpa->nItemCount, 0)) return -1;
1894 memmove (hdpa->ptrs + i + 1, hdpa->ptrs + i, (hdpa->nItemCount - i - 1) * sizeof(LPVOID));
1895 hdpa->ptrs[i] = p;
Dimitrie O. Paun78883852002-10-21 19:48:37 +00001896 return i;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001897}
1898
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001899/**************************************************************************
1900 * DPA_SetPtr [COMCTL32.335]
1901 *
1902 * Sets a pointer in the pointer array
1903 *
1904 * PARAMS
1905 * hdpa [I] handle (pointer) to the pointer array
1906 * i [I] index of the pointer that will be set
1907 * p [I] pointer to be set
1908 *
1909 * RETURNS
1910 * Success: TRUE
1911 * Failure: FALSE
1912 */
1913
Alexandre Julliarda3960291999-02-26 11:11:13 +00001914BOOL WINAPI
1915DPA_SetPtr (const HDPA hdpa, INT i, LPVOID p)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001916{
1917 LPVOID *lpTemp;
Vincent Béron9a624912002-05-31 23:06:46 +00001918
Alexandre Julliarda099a551999-06-12 15:45:58 +00001919 TRACE("(%p %d %p)\n", hdpa, i, p);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001920
Dimitrie O. Paun254e7482002-10-21 19:54:06 +00001921 if (!hdpa || i < 0 || i > 0x7fff)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001922 return FALSE;
Vincent Béron9a624912002-05-31 23:06:46 +00001923
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001924 if (hdpa->nItemCount <= i) {
1925 /* within the old array */
Paul Rupe2fbe9cf2002-09-25 03:19:24 +00001926 if (hdpa->nMaxCount <= i) {
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001927 /* resize the block of memory */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001928 INT nNewItems =
Eric Pouech200f89211999-09-13 15:11:02 +00001929 hdpa->nGrow * ((INT)(((i+1) - 1) / hdpa->nGrow) + 1);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001930 INT nSize = nNewItems * sizeof(LPVOID);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001931
Dimitrie O. Paun6168b982002-10-21 19:49:12 +00001932 if (hdpa->ptrs)
1933 lpTemp = (LPVOID*)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, hdpa->ptrs, nSize);
1934 else
1935 lpTemp = (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, nSize);
1936
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001937 if (!lpTemp)
1938 return FALSE;
1939
Paul Rupe2fbe9cf2002-09-25 03:19:24 +00001940 hdpa->nMaxCount = nNewItems;
Vincent Béron9a624912002-05-31 23:06:46 +00001941 hdpa->ptrs = lpTemp;
1942 }
Paul Rupe2fbe9cf2002-09-25 03:19:24 +00001943 hdpa->nItemCount = i+1;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001944 }
1945
1946 /* put the new entry in */
1947 hdpa->ptrs[i] = p;
1948
1949 return TRUE;
1950}
1951
1952
1953/**************************************************************************
1954 * DPA_DeletePtr [COMCTL32.336]
1955 *
1956 * Removes a pointer from the pointer array.
1957 *
1958 * PARAMS
1959 * hdpa [I] handle (pointer) to the pointer array
1960 * i [I] index of the pointer that will be deleted
1961 *
1962 * RETURNS
1963 * Success: deleted pointer
1964 * Failure: NULL
1965 */
1966
1967LPVOID WINAPI
Alexandre Julliarda3960291999-02-26 11:11:13 +00001968DPA_DeletePtr (const HDPA hdpa, INT i)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001969{
Eric Kohla0a516d1999-02-02 10:33:08 +00001970 LPVOID *lpDest, *lpSrc, lpTemp = NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001971 INT nSize;
Vincent Béron9a624912002-05-31 23:06:46 +00001972
Alexandre Julliarda099a551999-06-12 15:45:58 +00001973 TRACE("(%p %d)\n", hdpa, i);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001974
1975 if ((!hdpa) || i < 0 || i >= hdpa->nItemCount)
1976 return NULL;
1977
1978 lpTemp = hdpa->ptrs[i];
1979
1980 /* do we need to move ?*/
1981 if (i < hdpa->nItemCount - 1) {
Eric Kohl65016631999-01-24 19:09:56 +00001982 lpDest = hdpa->ptrs + i;
1983 lpSrc = lpDest + 1;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001984 nSize = (hdpa->nItemCount - i - 1) * sizeof(LPVOID);
Alexandre Julliarda099a551999-06-12 15:45:58 +00001985 TRACE("-- move dest=%p src=%p size=%x\n",
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001986 lpDest, lpSrc, nSize);
1987 memmove (lpDest, lpSrc, nSize);
1988 }
Vincent Béron9a624912002-05-31 23:06:46 +00001989
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001990 hdpa->nItemCount --;
Vincent Béron9a624912002-05-31 23:06:46 +00001991
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001992 /* free memory ?*/
1993 if ((hdpa->nMaxCount - hdpa->nItemCount) >= hdpa->nGrow) {
Francois Gouget6d77d3a2000-03-25 21:44:35 +00001994 INT nNewItems = max(hdpa->nGrow * 2, hdpa->nItemCount);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001995 nSize = nNewItems * sizeof(LPVOID);
1996 lpDest = (LPVOID)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1997 hdpa->ptrs, nSize);
1998 if (!lpDest)
1999 return NULL;
2000
2001 hdpa->nMaxCount = nNewItems;
Vincent Béron9a624912002-05-31 23:06:46 +00002002 hdpa->ptrs = (LPVOID*)lpDest;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002003 }
2004
2005 return lpTemp;
2006}
2007
2008
2009/**************************************************************************
2010 * DPA_DeleteAllPtrs [COMCTL32.337]
2011 *
2012 * Removes all pointers and reinitializes the array.
2013 *
2014 * PARAMS
2015 * hdpa [I] handle (pointer) to the pointer array
2016 *
2017 * RETURNS
2018 * Success: TRUE
2019 * Failure: FALSE
2020 */
2021
Alexandre Julliarda3960291999-02-26 11:11:13 +00002022BOOL WINAPI
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002023DPA_DeleteAllPtrs (const HDPA hdpa)
2024{
Alexandre Julliarda099a551999-06-12 15:45:58 +00002025 TRACE("(%p)\n", hdpa);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002026
Vincent Béron9a624912002-05-31 23:06:46 +00002027 if (!hdpa)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002028 return FALSE;
2029
2030 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
2031 return FALSE;
2032
2033 hdpa->nItemCount = 0;
2034 hdpa->nMaxCount = hdpa->nGrow * 2;
2035 hdpa->ptrs = (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
2036 hdpa->nMaxCount * sizeof(LPVOID));
2037
2038 return TRUE;
2039}
2040
2041
2042/**************************************************************************
2043 * DPA_QuickSort [Internal]
2044 *
Eric Kohl17216d31998-10-11 13:21:17 +00002045 * Ordinary quicksort (used by DPA_Sort).
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002046 *
2047 * PARAMS
2048 * lpPtrs [I] pointer to the pointer array
2049 * l [I] index of the "left border" of the partition
2050 * r [I] index of the "right border" of the partition
2051 * pfnCompare [I] pointer to the compare function
2052 * lParam [I] user defined value (3rd parameter in compare function)
2053 *
2054 * RETURNS
2055 * NONE
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002056 */
2057
2058static VOID
Alexandre Julliarda3960291999-02-26 11:11:13 +00002059DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r,
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002060 PFNDPACOMPARE pfnCompare, LPARAM lParam)
2061{
Mike McCormackf97b5432000-09-04 20:19:07 +00002062 INT m;
2063 LPVOID t;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002064
Alexandre Julliarda099a551999-06-12 15:45:58 +00002065 TRACE("l=%i r=%i\n", l, r);
Vincent Béron9a624912002-05-31 23:06:46 +00002066
Mike McCormackf97b5432000-09-04 20:19:07 +00002067 if (l==r) /* one element is always sorted */
2068 return;
2069 if (r<l) /* oops, got it in the wrong order */
Eric Kohl17216d31998-10-11 13:21:17 +00002070 {
Mike McCormackf97b5432000-09-04 20:19:07 +00002071 DPA_QuickSort(lpPtrs, r, l, pfnCompare, lParam);
2072 return;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002073 }
Mike McCormackf97b5432000-09-04 20:19:07 +00002074 m = (l+r)/2; /* divide by two */
2075 DPA_QuickSort(lpPtrs, l, m, pfnCompare, lParam);
2076 DPA_QuickSort(lpPtrs, m+1, r, pfnCompare, lParam);
2077
2078 /* join the two sides */
Vincent Béron9a624912002-05-31 23:06:46 +00002079 while( (l<=m) && (m<r) )
Mike McCormackf97b5432000-09-04 20:19:07 +00002080 {
2081 if(pfnCompare(lpPtrs[l],lpPtrs[m+1],lParam)>0)
2082 {
2083 t = lpPtrs[m+1];
Francois Gouget95918362003-06-18 19:45:22 +00002084 memmove(&lpPtrs[l+1],&lpPtrs[l],(m-l+1)*sizeof(lpPtrs[l]));
Mike McCormackf97b5432000-09-04 20:19:07 +00002085 lpPtrs[l] = t;
2086
2087 m++;
2088 }
2089 l++;
2090 }
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002091}
2092
2093
2094/**************************************************************************
2095 * DPA_Sort [COMCTL32.338]
2096 *
2097 * Sorts a pointer array using a user defined compare function
2098 *
2099 * PARAMS
2100 * hdpa [I] handle (pointer) to the pointer array
2101 * pfnCompare [I] pointer to the compare function
2102 * lParam [I] user defined value (3rd parameter of compare function)
2103 *
2104 * RETURNS
2105 * Success: TRUE
2106 * Failure: FALSE
2107 */
2108
Alexandre Julliarda3960291999-02-26 11:11:13 +00002109BOOL WINAPI
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002110DPA_Sort (const HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam)
2111{
2112 if (!hdpa || !pfnCompare)
2113 return FALSE;
2114
Alexandre Julliarda099a551999-06-12 15:45:58 +00002115 TRACE("(%p %p 0x%lx)\n", hdpa, pfnCompare, lParam);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002116
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002117 if ((hdpa->nItemCount > 1) && (hdpa->ptrs))
2118 DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1,
2119 pfnCompare, lParam);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002120
2121 return TRUE;
2122}
2123
2124
2125/**************************************************************************
2126 * DPA_Search [COMCTL32.339]
2127 *
2128 * Searches a pointer array for a specified pointer
2129 *
2130 * PARAMS
2131 * hdpa [I] handle (pointer) to the pointer array
2132 * pFind [I] pointer to search for
2133 * nStart [I] start index
2134 * pfnCompare [I] pointer to the compare function
2135 * lParam [I] user defined value (3rd parameter of compare function)
2136 * uOptions [I] search options
2137 *
2138 * RETURNS
2139 * Success: index of the pointer in the array.
2140 * Failure: -1
2141 *
2142 * NOTES
2143 * Binary search taken from R.Sedgewick "Algorithms in C"!
Eric Kohl17216d31998-10-11 13:21:17 +00002144 * Function is NOT tested!
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002145 * If something goes wrong, blame HIM not ME! (Eric Kohl)
2146 */
2147
Alexandre Julliarda3960291999-02-26 11:11:13 +00002148INT WINAPI
2149DPA_Search (const HDPA hdpa, LPVOID pFind, INT nStart,
2150 PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002151{
2152 if (!hdpa || !pfnCompare || !pFind)
2153 return -1;
2154
Alexandre Julliarda099a551999-06-12 15:45:58 +00002155 TRACE("(%p %p %d %p 0x%08lx 0x%08x)\n",
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002156 hdpa, pFind, nStart, pfnCompare, lParam, uOptions);
2157
2158 if (uOptions & DPAS_SORTED) {
2159 /* array is sorted --> use binary search */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002160 INT l, r, x, n;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002161 LPVOID *lpPtr;
2162
Alexandre Julliarda099a551999-06-12 15:45:58 +00002163 TRACE("binary search\n");
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002164
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002165 l = (nStart == -1) ? 0 : nStart;
2166 r = hdpa->nItemCount - 1;
2167 lpPtr = hdpa->ptrs;
2168 while (r >= l) {
2169 x = (l + r) / 2;
2170 n = (pfnCompare)(pFind, lpPtr[x], lParam);
2171 if (n < 0)
2172 r = x - 1;
2173 else
2174 l = x + 1;
2175 if (n == 0) {
Alexandre Julliarda099a551999-06-12 15:45:58 +00002176 TRACE("-- ret=%d\n", n);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002177 return n;
2178 }
2179 }
2180
2181 if (uOptions & DPAS_INSERTBEFORE) {
Uwe Bonnes29ef8012003-05-15 23:55:12 +00002182 if (r == -1) r = 0;
Alexandre Julliarda099a551999-06-12 15:45:58 +00002183 TRACE("-- ret=%d\n", r);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002184 return r;
2185 }
2186
2187 if (uOptions & DPAS_INSERTAFTER) {
Alexandre Julliarda099a551999-06-12 15:45:58 +00002188 TRACE("-- ret=%d\n", l);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002189 return l;
2190 }
2191 }
2192 else {
2193 /* array is not sorted --> use linear search */
2194 LPVOID *lpPtr;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002195 INT nIndex;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002196
Alexandre Julliarda099a551999-06-12 15:45:58 +00002197 TRACE("linear search\n");
Vincent Béron9a624912002-05-31 23:06:46 +00002198
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002199 nIndex = (nStart == -1)? 0 : nStart;
2200 lpPtr = hdpa->ptrs;
2201 for (; nIndex < hdpa->nItemCount; nIndex++) {
2202 if ((pfnCompare)(pFind, lpPtr[nIndex], lParam) == 0) {
Alexandre Julliarda099a551999-06-12 15:45:58 +00002203 TRACE("-- ret=%d\n", nIndex);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002204 return nIndex;
2205 }
2206 }
2207 }
2208
Alexandre Julliarda099a551999-06-12 15:45:58 +00002209 TRACE("-- not found: ret=-1\n");
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002210 return -1;
2211}
2212
2213
2214/**************************************************************************
2215 * DPA_CreateEx [COMCTL32.340]
2216 *
2217 * Creates a dynamic pointer array using the specified size and heap.
2218 *
2219 * PARAMS
2220 * nGrow [I] number of items by which the array grows when it is filled
2221 * hHeap [I] handle to the heap where the array is stored
2222 *
2223 * RETURNS
2224 * Success: handle (pointer) to the pointer array.
2225 * Failure: NULL
2226 */
2227
2228HDPA WINAPI
Alexandre Julliarda3960291999-02-26 11:11:13 +00002229DPA_CreateEx (INT nGrow, HANDLE hHeap)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002230{
2231 HDPA hdpa;
2232
Michael Stefaniuc353529b2002-10-23 22:19:10 +00002233 TRACE("(%d %p)\n", nGrow, hHeap);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002234
2235 if (hHeap)
2236 hdpa = (HDPA)HeapAlloc (hHeap, HEAP_ZERO_MEMORY, sizeof(DPA));
2237 else
2238 hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
2239
2240 if (hdpa) {
Francois Gouget6d77d3a2000-03-25 21:44:35 +00002241 hdpa->nGrow = min(8, nGrow);
Eric Kohl17216d31998-10-11 13:21:17 +00002242 hdpa->hHeap = hHeap ? hHeap : COMCTL32_hHeap;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002243 hdpa->nMaxCount = hdpa->nGrow * 2;
2244 hdpa->ptrs =
2245 (LPVOID*)HeapAlloc (hHeap, HEAP_ZERO_MEMORY,
2246 hdpa->nMaxCount * sizeof(LPVOID));
2247 }
2248
Alexandre Julliarda099a551999-06-12 15:45:58 +00002249 TRACE("-- %p\n", hdpa);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002250
2251 return hdpa;
2252}
2253
2254
2255/**************************************************************************
Eric Kohl17216d31998-10-11 13:21:17 +00002256 * Notification functions
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002257 */
2258
Eric Kohl17216d31998-10-11 13:21:17 +00002259typedef struct tagNOTIFYDATA
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002260{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002261 HWND hwndFrom;
2262 HWND hwndTo;
Eric Kohl17216d31998-10-11 13:21:17 +00002263 DWORD dwParam3;
2264 DWORD dwParam4;
2265 DWORD dwParam5;
2266 DWORD dwParam6;
2267} NOTIFYDATA, *LPNOTIFYDATA;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002268
Eric Kohl17216d31998-10-11 13:21:17 +00002269
2270/**************************************************************************
2271 * DoNotify [Internal]
2272 */
2273
2274static LRESULT
Alexandre Julliarda3960291999-02-26 11:11:13 +00002275DoNotify (LPNOTIFYDATA lpNotify, UINT uCode, LPNMHDR lpHdr)
Eric Kohl17216d31998-10-11 13:21:17 +00002276{
2277 NMHDR nmhdr;
2278 LPNMHDR lpNmh = NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002279 UINT idFrom = 0;
Eric Kohl17216d31998-10-11 13:21:17 +00002280
Michael Stefaniuc353529b2002-10-23 22:19:10 +00002281 TRACE("(%p %p %d %p 0x%08lx)\n",
Eric Kohl17216d31998-10-11 13:21:17 +00002282 lpNotify->hwndFrom, lpNotify->hwndTo, uCode, lpHdr,
2283 lpNotify->dwParam5);
2284
2285 if (!lpNotify->hwndTo)
2286 return 0;
2287
Michael Stefaniuc025c0b72002-09-06 19:41:17 +00002288 if (lpNotify->hwndFrom == (HWND)-1) {
Eric Kohl17216d31998-10-11 13:21:17 +00002289 lpNmh = lpHdr;
2290 idFrom = lpHdr->idFrom;
2291 }
2292 else {
2293 if (lpNotify->hwndFrom) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002294 HWND hwndParent = GetParent (lpNotify->hwndFrom);
Eric Kohl17216d31998-10-11 13:21:17 +00002295 if (hwndParent) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002296 hwndParent = GetWindow (lpNotify->hwndFrom, GW_OWNER);
Guy Albertelli1cc88172002-01-31 20:37:49 +00002297 /* the following is done even if the return from above
2298 * is zero. GLA 12/2001 */
2299 idFrom = GetDlgCtrlID (lpNotify->hwndFrom);
Eric Kohl17216d31998-10-11 13:21:17 +00002300 }
2301 }
2302
2303 lpNmh = (lpHdr) ? lpHdr : &nmhdr;
2304
2305 lpNmh->hwndFrom = lpNotify->hwndFrom;
2306 lpNmh->idFrom = idFrom;
2307 lpNmh->code = uCode;
2308 }
2309
Alexandre Julliarda3960291999-02-26 11:11:13 +00002310 return SendMessageA (lpNotify->hwndTo, WM_NOTIFY, idFrom, (LPARAM)lpNmh);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002311}
2312
2313
Eric Kohl17216d31998-10-11 13:21:17 +00002314/**************************************************************************
2315 * SendNotify [COMCTL32.341]
2316 *
2317 * PARAMS
Eric Kohl17216d31998-10-11 13:21:17 +00002318 * hwndTo [I]
Guy Albertelli1cc88172002-01-31 20:37:49 +00002319 * hwndFrom [I]
Eric Kohl17216d31998-10-11 13:21:17 +00002320 * uCode [I]
2321 * lpHdr [I]
2322 *
2323 * RETURNS
2324 * Success: return value from notification
2325 * Failure: 0
2326 */
2327
2328LRESULT WINAPI
Guy Albertelli1cc88172002-01-31 20:37:49 +00002329COMCTL32_SendNotify (HWND hwndTo, HWND hwndFrom,
Alexandre Julliarda3960291999-02-26 11:11:13 +00002330 UINT uCode, LPNMHDR lpHdr)
Eric Kohl17216d31998-10-11 13:21:17 +00002331{
2332 NOTIFYDATA notify;
2333
Michael Stefaniuc353529b2002-10-23 22:19:10 +00002334 TRACE("(%p %p %d %p)\n",
Guy Albertelli1cc88172002-01-31 20:37:49 +00002335 hwndTo, hwndFrom, uCode, lpHdr);
Eric Kohl17216d31998-10-11 13:21:17 +00002336
2337 notify.hwndFrom = hwndFrom;
2338 notify.hwndTo = hwndTo;
2339 notify.dwParam5 = 0;
2340 notify.dwParam6 = 0;
2341
2342 return DoNotify (&notify, uCode, lpHdr);
2343}
2344
2345
2346/**************************************************************************
2347 * SendNotifyEx [COMCTL32.342]
2348 *
2349 * PARAMS
2350 * hwndFrom [I]
2351 * hwndTo [I]
2352 * uCode [I]
2353 * lpHdr [I]
2354 * dwParam5 [I]
2355 *
2356 * RETURNS
2357 * Success: return value from notification
2358 * Failure: 0
2359 */
2360
2361LRESULT WINAPI
Alexandre Julliarda3960291999-02-26 11:11:13 +00002362COMCTL32_SendNotifyEx (HWND hwndTo, HWND hwndFrom, UINT uCode,
Eric Kohl17216d31998-10-11 13:21:17 +00002363 LPNMHDR lpHdr, DWORD dwParam5)
2364{
2365 NOTIFYDATA notify;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002366 HWND hwndNotify;
Eric Kohl17216d31998-10-11 13:21:17 +00002367
Michael Stefaniuc353529b2002-10-23 22:19:10 +00002368 TRACE("(%p %p %d %p 0x%08lx)\n",
Eric Kohl17216d31998-10-11 13:21:17 +00002369 hwndFrom, hwndTo, uCode, lpHdr, dwParam5);
2370
2371 hwndNotify = hwndTo;
2372 if (!hwndTo) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002373 if (IsWindow (hwndFrom)) {
2374 hwndNotify = GetParent (hwndFrom);
Eric Kohl17216d31998-10-11 13:21:17 +00002375 if (!hwndNotify)
2376 return 0;
2377 }
2378 }
2379
2380 notify.hwndFrom = hwndFrom;
2381 notify.hwndTo = hwndNotify;
2382 notify.dwParam5 = dwParam5;
2383 notify.dwParam6 = 0;
2384
2385 return DoNotify (&notify, uCode, lpHdr);
2386}
2387
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002388
2389/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002390 * StrChrA [COMCTL32.350]
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002391 *
2392 */
2393
2394LPSTR WINAPI
2395COMCTL32_StrChrA (LPCSTR lpString, CHAR cChar)
2396{
2397 return strchr (lpString, cChar);
2398}
2399
2400
2401/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002402 * StrStrIA [COMCTL32.355]
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002403 */
2404
2405LPSTR WINAPI
2406COMCTL32_StrStrIA (LPCSTR lpStr1, LPCSTR lpStr2)
2407{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002408 INT len1, len2, i;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002409 CHAR first;
2410
2411 if (*lpStr2 == 0)
2412 return ((LPSTR)lpStr1);
2413 len1 = 0;
2414 while (lpStr1[len1] != 0) ++len1;
2415 len2 = 0;
2416 while (lpStr2[len2] != 0) ++len2;
2417 if (len2 == 0)
2418 return ((LPSTR)(lpStr1 + len1));
2419 first = tolower (*lpStr2);
2420 while (len1 >= len2) {
2421 if (tolower(*lpStr1) == first) {
2422 for (i = 1; i < len2; ++i)
2423 if (tolower (lpStr1[i]) != tolower(lpStr2[i]))
2424 break;
2425 if (i >= len2)
2426 return ((LPSTR)lpStr1);
2427 }
2428 ++lpStr1; --len1;
2429 }
2430 return (NULL);
2431}
2432
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002433/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002434 * StrToIntA [COMCTL32.357] Converts a string to a signed integer.
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002435 */
2436
Alexandre Julliarda3960291999-02-26 11:11:13 +00002437INT WINAPI
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002438COMCTL32_StrToIntA (LPSTR lpString)
2439{
2440 return atoi(lpString);
2441}
2442
Chris Morgan87e4dbf2001-04-30 18:16:28 +00002443/**************************************************************************
Robert Shearman096bece2002-12-13 23:25:59 +00002444 * StrStrIW [COMCTL32.363]
2445 */
2446
2447LPWSTR WINAPI
2448COMCTL32_StrStrIW (LPCWSTR lpStr1, LPCWSTR lpStr2)
2449{
2450 INT len1, len2, i;
2451 WCHAR first;
2452
2453 if (*lpStr2 == 0)
2454 return ((LPWSTR)lpStr1);
2455 len1 = 0;
2456 while (lpStr1[len1] != 0) ++len1;
2457 len2 = 0;
2458 while (lpStr2[len2] != 0) ++len2;
2459 if (len2 == 0)
2460 return ((LPWSTR)(lpStr1 + len1));
2461 first = tolowerW (*lpStr2);
2462 while (len1 >= len2) {
2463 if (tolowerW (*lpStr1) == first) {
2464 for (i = 1; i < len2; ++i)
2465 if (tolowerW (lpStr1[i]) != tolowerW(lpStr2[i]))
2466 break;
2467 if (i >= len2)
2468 return ((LPWSTR)lpStr1);
2469 }
2470 ++lpStr1; --len1;
2471 }
2472 return (NULL);
2473}
2474
2475/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002476 * StrToIntW [COMCTL32.365] Converts a wide char string to a signed integer.
Chris Morgan87e4dbf2001-04-30 18:16:28 +00002477 */
2478
2479INT WINAPI
2480COMCTL32_StrToIntW (LPWSTR lpString)
2481{
Alexandre Julliard9b6f4332002-05-16 18:58:47 +00002482 return atoiW(lpString);
Chris Morgan87e4dbf2001-04-30 18:16:28 +00002483}
2484
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002485
2486/**************************************************************************
Eric Kohl0f7d5211998-11-22 17:54:40 +00002487 * DPA_EnumCallback [COMCTL32.385]
Eric Kohl17216d31998-10-11 13:21:17 +00002488 *
2489 * Enumerates all items in a dynamic pointer array.
2490 *
2491 * PARAMS
2492 * hdpa [I] handle to the dynamic pointer array
2493 * enumProc [I]
Vincent Béron9a624912002-05-31 23:06:46 +00002494 * lParam [I]
Eric Kohl17216d31998-10-11 13:21:17 +00002495 *
2496 * RETURNS
2497 * none
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002498 */
2499
Eric Kohl17216d31998-10-11 13:21:17 +00002500VOID WINAPI
Eric Kohl0f7d5211998-11-22 17:54:40 +00002501DPA_EnumCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002502{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002503 INT i;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002504
Alexandre Julliarda099a551999-06-12 15:45:58 +00002505 TRACE("(%p %p %08lx)\n", hdpa, enumProc, lParam);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002506
Eric Kohl17216d31998-10-11 13:21:17 +00002507 if (!hdpa)
2508 return;
2509 if (hdpa->nItemCount <= 0)
2510 return;
2511
2512 for (i = 0; i < hdpa->nItemCount; i++) {
Eric Kohl0f7d5211998-11-22 17:54:40 +00002513 if ((enumProc)(hdpa->ptrs[i], lParam) == 0)
Eric Kohl17216d31998-10-11 13:21:17 +00002514 return;
2515 }
2516
2517 return;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002518}
2519
2520
2521/**************************************************************************
Eric Kohl0f7d5211998-11-22 17:54:40 +00002522 * DPA_DestroyCallback [COMCTL32.386]
Eric Kohl17216d31998-10-11 13:21:17 +00002523 *
2524 * Enumerates all items in a dynamic pointer array and destroys it.
2525 *
2526 * PARAMS
2527 * hdpa [I] handle to the dynamic pointer array
2528 * enumProc [I]
Eric Kohl0f7d5211998-11-22 17:54:40 +00002529 * lParam [I]
Eric Kohl17216d31998-10-11 13:21:17 +00002530 *
2531 * RETURNS
2532 * Success: TRUE
2533 * Failure: FALSE
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002534 */
2535
Alexandre Julliarda3960291999-02-26 11:11:13 +00002536BOOL WINAPI
Eric Kohl0f7d5211998-11-22 17:54:40 +00002537DPA_DestroyCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002538{
Alexandre Julliarda099a551999-06-12 15:45:58 +00002539 TRACE("(%p %p %08lx)\n", hdpa, enumProc, lParam);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002540
Eric Kohl0f7d5211998-11-22 17:54:40 +00002541 DPA_EnumCallback (hdpa, enumProc, lParam);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002542
Eric Kohl17216d31998-10-11 13:21:17 +00002543 return DPA_Destroy (hdpa);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002544}
2545
2546
2547/**************************************************************************
Eric Kohl0f7d5211998-11-22 17:54:40 +00002548 * DSA_EnumCallback [COMCTL32.387]
Eric Kohl17216d31998-10-11 13:21:17 +00002549 *
2550 * Enumerates all items in a dynamic storage array.
2551 *
2552 * PARAMS
2553 * hdsa [I] handle to the dynamic storage array
2554 * enumProc [I]
Eric Kohl0f7d5211998-11-22 17:54:40 +00002555 * lParam [I]
Eric Kohl17216d31998-10-11 13:21:17 +00002556 *
2557 * RETURNS
2558 * none
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002559 */
2560
Eric Kohl17216d31998-10-11 13:21:17 +00002561VOID WINAPI
Eric Kohl0f7d5211998-11-22 17:54:40 +00002562DSA_EnumCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002563{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002564 INT i;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002565
Alexandre Julliarda099a551999-06-12 15:45:58 +00002566 TRACE("(%p %p %08lx)\n", hdsa, enumProc, lParam);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002567
Eric Kohl17216d31998-10-11 13:21:17 +00002568 if (!hdsa)
2569 return;
2570 if (hdsa->nItemCount <= 0)
2571 return;
2572
2573 for (i = 0; i < hdsa->nItemCount; i++) {
2574 LPVOID lpItem = DSA_GetItemPtr (hdsa, i);
Eric Kohl0f7d5211998-11-22 17:54:40 +00002575 if ((enumProc)(lpItem, lParam) == 0)
Eric Kohl17216d31998-10-11 13:21:17 +00002576 return;
2577 }
2578
2579 return;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002580}
2581
2582
2583/**************************************************************************
Eric Kohl0f7d5211998-11-22 17:54:40 +00002584 * DSA_DestroyCallback [COMCTL32.388]
Eric Kohl17216d31998-10-11 13:21:17 +00002585 *
2586 * Enumerates all items in a dynamic storage array and destroys it.
2587 *
2588 * PARAMS
2589 * hdsa [I] handle to the dynamic storage array
2590 * enumProc [I]
Eric Kohl0f7d5211998-11-22 17:54:40 +00002591 * lParam [I]
Eric Kohl17216d31998-10-11 13:21:17 +00002592 *
2593 * RETURNS
2594 * Success: TRUE
2595 * Failure: FALSE
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002596 */
2597
Alexandre Julliarda3960291999-02-26 11:11:13 +00002598BOOL WINAPI
Eric Kohl0f7d5211998-11-22 17:54:40 +00002599DSA_DestroyCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002600{
Alexandre Julliarda099a551999-06-12 15:45:58 +00002601 TRACE("(%p %p %08lx)\n", hdsa, enumProc, lParam);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002602
Eric Kohl0f7d5211998-11-22 17:54:40 +00002603 DSA_EnumCallback (hdsa, enumProc, lParam);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002604
Eric Kohl17216d31998-10-11 13:21:17 +00002605 return DSA_Destroy (hdsa);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002606}
2607
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002608/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002609 * StrCSpnA [COMCTL32.356]
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002610 *
2611 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002612INT WINAPI COMCTL32_StrCSpnA( LPCSTR lpStr, LPCSTR lpSet) {
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002613 return strcspn(lpStr, lpSet);
2614}
2615
2616/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002617 * StrChrW [COMCTL32.358]
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002618 *
2619 */
2620LPWSTR WINAPI COMCTL32_StrChrW( LPCWSTR lpStart, WORD wMatch) {
Alexandre Julliard5ea22472000-06-13 01:10:29 +00002621 return strchrW(lpStart, wMatch);
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002622}
2623
2624/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002625 * StrCmpNA [COMCTL32.352]
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002626 *
2627 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002628INT WINAPI COMCTL32_StrCmpNA( LPCSTR lpStr1, LPCSTR lpStr2, int nChar) {
Alexandre Julliard89f079b1999-08-08 18:54:47 +00002629 return strncmp(lpStr1, lpStr2, nChar);
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002630}
2631
2632/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002633 * StrCmpNIA [COMCTL32.353]
Uwe Bonnesbd638801999-09-04 11:04:45 +00002634 *
2635 */
2636INT WINAPI COMCTL32_StrCmpNIA( LPCSTR lpStr1, LPCSTR lpStr2, int nChar) {
2637 return strncasecmp(lpStr1, lpStr2, nChar);
2638}
2639
2640/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002641 * StrCmpNW [COMCTL32.360]
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002642 *
2643 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002644INT WINAPI COMCTL32_StrCmpNW( LPCWSTR lpStr1, LPCWSTR lpStr2, int nChar) {
Alexandre Julliard5ea22472000-06-13 01:10:29 +00002645 return strncmpW(lpStr1, lpStr2, nChar);
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002646}
2647
2648/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002649 * StrCmpNIW [COMCTL32.361]
Patrik Stridvalld7da4861999-10-24 21:35:16 +00002650 *
2651 */
2652INT WINAPI COMCTL32_StrCmpNIW( LPCWSTR lpStr1, LPCWSTR lpStr2, int nChar) {
2653 FIXME("(%s, %s, %i): stub\n", debugstr_w(lpStr1), debugstr_w(lpStr2), nChar);
2654 return 0;
2655}
2656
2657/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002658 * StrRChrA [COMCTL32.351]
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002659 *
2660 */
Alexandre Julliard3850c1a2000-08-06 02:42:46 +00002661LPSTR WINAPI COMCTL32_StrRChrA( LPCSTR lpStart, LPCSTR lpEnd, WORD wMatch )
2662{
2663 LPCSTR lpGotIt = NULL;
2664 BOOL dbcs = IsDBCSLeadByte( LOBYTE(wMatch) );
2665
2666 TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
2667
2668 if (!lpEnd) lpEnd = lpStart + strlen(lpStart);
2669
2670 for(; lpStart < lpEnd; lpStart = CharNextA(lpStart))
2671 {
2672 if (*lpStart != LOBYTE(wMatch)) continue;
2673 if (dbcs && lpStart[1] != HIBYTE(wMatch)) continue;
2674 lpGotIt = lpStart;
Vincent Béron9a624912002-05-31 23:06:46 +00002675 }
Alexandre Julliard3850c1a2000-08-06 02:42:46 +00002676 return (LPSTR)lpGotIt;
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002677}
2678
Alexandre Julliard3850c1a2000-08-06 02:42:46 +00002679
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002680/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002681 * StrRChrW [COMCTL32.359]
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002682 *
2683 */
Alexandre Julliard3850c1a2000-08-06 02:42:46 +00002684LPWSTR WINAPI COMCTL32_StrRChrW( LPCWSTR lpStart, LPCWSTR lpEnd, WORD wMatch)
2685{
2686 LPCWSTR lpGotIt = NULL;
2687
2688 TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
2689 if (!lpEnd) lpEnd = lpStart + strlenW(lpStart);
2690
2691 for(; lpStart < lpEnd; lpStart = CharNextW(lpStart))
2692 if (*lpStart == wMatch) lpGotIt = lpStart;
2693
2694 return (LPWSTR)lpGotIt;
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002695}
2696
Alexandre Julliard3850c1a2000-08-06 02:42:46 +00002697
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002698/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002699 * StrStrA [COMCTL32.354]
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002700 *
2701 */
2702LPSTR WINAPI COMCTL32_StrStrA( LPCSTR lpFirst, LPCSTR lpSrch) {
2703 return strstr(lpFirst, lpSrch);
2704}
2705
2706/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002707 * StrStrW [COMCTL32.362]
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002708 *
2709 */
2710LPWSTR WINAPI COMCTL32_StrStrW( LPCWSTR lpFirst, LPCWSTR lpSrch) {
Alexandre Julliard5ea22472000-06-13 01:10:29 +00002711 return strstrW(lpFirst, lpSrch);
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002712}
2713
2714/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002715 * StrSpnW [COMCTL32.364]
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002716 *
2717 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002718INT WINAPI COMCTL32_StrSpnW( LPWSTR lpStr, LPWSTR lpSet) {
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002719 LPWSTR lpLoop = lpStr;
2720
2721 /* validate ptr */
2722 if ((lpStr == 0) || (lpSet == 0)) return 0;
2723
2724/* while(*lpLoop) { if lpLoop++; } */
2725
2726 for(; (*lpLoop != 0); lpLoop++)
Alexandre Julliard5ea22472000-06-13 01:10:29 +00002727 if( strchrW(lpSet, *(WORD*)lpLoop))
Alexandre Julliarda3960291999-02-26 11:11:13 +00002728 return (INT)(lpLoop-lpStr);
Vincent Béron9a624912002-05-31 23:06:46 +00002729
Alexandre Julliarda3960291999-02-26 11:11:13 +00002730 return (INT)(lpLoop-lpStr);
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002731}
Ian Schmidt45584801999-07-28 16:35:24 +00002732
2733/**************************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002734 * @ [COMCTL32.415]
Ian Schmidt45584801999-07-28 16:35:24 +00002735 *
Eric Kohlb3f681e2000-06-03 21:06:44 +00002736 * FIXME: What's this supposed to do?
2737 * Parameter 1 is an HWND, you're on your own for the rest.
Ian Schmidt45584801999-07-28 16:35:24 +00002738 */
2739
Eric Kohlb3f681e2000-06-03 21:06:44 +00002740BOOL WINAPI COMCTL32_415( HWND hwnd, DWORD b, DWORD c, DWORD d, DWORD e)
2741{
Ian Schmidt45584801999-07-28 16:35:24 +00002742
Michael Stefaniuc353529b2002-10-23 22:19:10 +00002743 FIXME("(%p, %lx, %lx, %lx, %lx): stub!\n", hwnd, b, c, d, e);
Ian Schmidt45584801999-07-28 16:35:24 +00002744
2745 return TRUE;
2746}
Huw D M Davies964109d2002-01-18 18:08:01 +00002747
2748/**************************************************************************
Dmitry Timoshkovcc7042f2002-08-16 01:43:11 +00002749 * @ [COMCTL32.417]
2750 *
2751 */
2752BOOL WINAPI COMCTL32_417(HDC hdc, INT x, INT y, UINT flags, const RECT *lprect,
2753 LPCWSTR str, UINT count, const INT *lpDx)
2754{
2755 return ExtTextOutW(hdc, x, y, flags, lprect, str, count, lpDx);
2756}
2757
2758/**************************************************************************
Huw D M Davies964109d2002-01-18 18:08:01 +00002759 * @ [COMCTL32.419]
2760 *
2761 * FIXME: What's this supposed to do?
2762 */
2763
2764BOOL WINAPI COMCTL32_419( DWORD a, DWORD b, DWORD c, DWORD d)
2765{
2766
2767 FIXME("(%lx, %lx, %lx, %lx): stub!\n", a, b, c, d);
2768
2769 return TRUE;
2770}