blob: c30c9e7bf0da438fd969e0444c74b8615014f0d2 [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 Julliarda0d77311998-09-13 16:32:00 +00008 * NOTES
9 * All of these functions are UNDOCUMENTED!! And I mean UNDOCUMENTED!!!!
10 * Do NOT rely on names or contents of undocumented structures and types!!!
11 * These functions are used by EXPLORER.EXE, IEXPLORE.EXE and
12 * COMCTL32.DLL (internally).
13 *
14 * TODO
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000015 * - Add more functions.
16 * - Write some documentation.
Alexandre Julliarda0d77311998-09-13 16:32:00 +000017 */
18
19#include <string.h>
Marcus Meissner317af321999-02-17 13:51:06 +000020#include <stdlib.h> /* atoi */
Alexandre Julliarda0d77311998-09-13 16:32:00 +000021#include <ctype.h>
Marcus Meissner317af321999-02-17 13:51:06 +000022
Patrik Stridvall33929be2001-07-18 21:04:23 +000023#include "commctrl.h"
24#include "objbase.h"
Marcus Meissner9f3eb191999-05-22 11:22:36 +000025#include "winbase.h"
Eric Kohld37b0191999-06-26 11:57:04 +000026#include "winerror.h"
Guy Albertelli45e9cea2001-09-20 18:58:43 +000027#include "winreg.h"
Patrik Stridvall33929be2001-07-18 21:04:23 +000028
Alexandre Julliard5ea22472000-06-13 01:10:29 +000029#include "wine/unicode.h"
Patrik Stridvall33929be2001-07-18 21:04:23 +000030#include "comctl32.h"
31
Alexandre Julliarda099a551999-06-12 15:45:58 +000032#include "debugtools.h"
Alexandre Julliarda0d77311998-09-13 16:32:00 +000033
Alexandre Julliard5ea22472000-06-13 01:10:29 +000034DEFAULT_DEBUG_CHANNEL(commctrl);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000035
Alexandre Julliarda0d77311998-09-13 16:32:00 +000036
Alexandre Julliarda3960291999-02-26 11:11:13 +000037extern HANDLE COMCTL32_hHeap; /* handle to the private heap */
Alexandre Julliarda0d77311998-09-13 16:32:00 +000038
39
Eric Kohld37b0191999-06-26 11:57:04 +000040typedef struct _STREAMDATA
41{
42 DWORD dwSize;
43 DWORD dwData2;
44 DWORD dwItems;
45} STREAMDATA, *PSTREAMDATA;
46
47typedef struct _LOADDATA
48{
49 INT nCount;
50 PVOID ptr;
51} LOADDATA, *LPLOADDATA;
52
François Gouget5e632112001-02-14 21:41:35 +000053typedef HRESULT CALLBACK (*DPALOADPROC)(LPLOADDATA,IStream*,LPARAM);
Eric Kohld37b0191999-06-26 11:57:04 +000054
Chris Morgan87e4dbf2001-04-30 18:16:28 +000055INT __cdecl _wtoi(LPWSTR string);
Eric Kohld37b0191999-06-26 11:57:04 +000056
57/**************************************************************************
58 * DPA_LoadStream [COMCTL32.9]
59 *
60 * Loads a dynamic pointer array from a stream
61 *
62 * PARAMS
63 * phDpa [O] pointer to a handle to a dynamic pointer array
64 * loadProc [I] pointer to a callback function
65 * pStream [I] pointer to a stream
66 * lParam [I] application specific value
67 *
68 * NOTES
69 * No more information available yet!
70 */
71
72HRESULT WINAPI
73DPA_LoadStream (HDPA *phDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lParam)
74{
75 HRESULT errCode;
76 LARGE_INTEGER position;
77 ULARGE_INTEGER newPosition;
78 STREAMDATA streamData;
79 LOADDATA loadData;
80 ULONG ulRead;
81 HDPA hDpa;
82 PVOID *ptr;
83
84 FIXME ("phDpa=%p loadProc=%p pStream=%p lParam=%lx\n",
85 phDpa, loadProc, pStream, lParam);
86
87 if (!phDpa || !loadProc || !pStream)
88 return E_INVALIDARG;
89
90 *phDpa = (HDPA)NULL;
91
Patrik Stridvall311e4561999-09-19 14:20:33 +000092 position.s.LowPart = 0;
93 position.s.HighPart = 0;
Eric Kohld37b0191999-06-26 11:57:04 +000094
95 errCode = IStream_Seek (pStream, position, STREAM_SEEK_CUR, &newPosition);
96 if (errCode != S_OK)
97 return errCode;
98
99 errCode = IStream_Read (pStream, &streamData, sizeof(STREAMDATA), &ulRead);
100 if (errCode != S_OK)
101 return errCode;
102
103 FIXME ("dwSize=%lu dwData2=%lu dwItems=%lu\n",
104 streamData.dwSize, streamData.dwData2, streamData.dwItems);
105
106 if (lParam < sizeof(STREAMDATA) ||
107 streamData.dwSize < sizeof(STREAMDATA) ||
108 streamData.dwData2 < 1) {
109 errCode = E_FAIL;
110 }
111
112 /* create the dpa */
113 hDpa = DPA_Create (streamData.dwItems);
114 if (!hDpa)
115 return E_OUTOFMEMORY;
116
117 if (!DPA_Grow (hDpa, streamData.dwItems))
118 return E_OUTOFMEMORY;
119
120 /* load data from the stream into the dpa */
121 ptr = hDpa->ptrs;
122 for (loadData.nCount = 0; loadData.nCount < streamData.dwItems; loadData.nCount++) {
123 errCode = (loadProc)(&loadData, pStream, lParam);
124 if (errCode != S_OK) {
125 errCode = S_FALSE;
126 break;
127 }
128
129 *ptr = loadData.ptr;
130 ptr++;
131 }
132
133 /* set the number of items */
134 hDpa->nItemCount = loadData.nCount;
135
136 /* store the handle to the dpa */
137 *phDpa = hDpa;
138 FIXME ("new hDpa=%p\n", hDpa);
139
140 return errCode;
141}
142
143
144/**************************************************************************
145 * DPA_SaveStream [COMCTL32.10]
146 *
147 * Saves a dynamic pointer array to a stream
148 *
149 * PARAMS
150 * hDpa [I] handle to a dynamic pointer array
151 * loadProc [I] pointer to a callback function
152 * pStream [I] pointer to a stream
153 * lParam [I] application specific value
154 *
155 * NOTES
156 * No more information available yet!
157 */
158
159HRESULT WINAPI
160DPA_SaveStream (const HDPA hDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lParam)
161{
162
163 FIXME ("hDpa=%p loadProc=%p pStream=%p lParam=%lx\n",
164 hDpa, loadProc, pStream, lParam);
165
166 return E_FAIL;
167}
168
169
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000170/**************************************************************************
Eric Kohl0f7d5211998-11-22 17:54:40 +0000171 * DPA_Merge [COMCTL32.11]
Eric Kohl17216d31998-10-11 13:21:17 +0000172 *
173 * PARAMS
Guy L. Albertelli97178452000-11-30 19:58:56 +0000174 * hdpa1 [I] handle to a dynamic pointer array
175 * hdpa2 [I] handle to a dynamic pointer array
176 * dwFlags [I] flags
177 * pfnCompare [I] pointer to sort function
178 * pfnMerge [I] pointer to merge function
179 * lParam [I] application specific value
Eric Kohl17216d31998-10-11 13:21:17 +0000180 *
181 * NOTES
182 * No more information available yet!
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000183 */
184
Alexandre Julliarda3960291999-02-26 11:11:13 +0000185BOOL WINAPI
Eric Kohl0f7d5211998-11-22 17:54:40 +0000186DPA_Merge (const HDPA hdpa1, const HDPA hdpa2, DWORD dwFlags,
Eric Kohld37b0191999-06-26 11:57:04 +0000187 PFNDPACOMPARE pfnCompare, PFNDPAMERGE pfnMerge, LPARAM lParam)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000188{
Ian Schmidt45584801999-07-28 16:35:24 +0000189 INT nCount;
Guy L. Albertelli97178452000-11-30 19:58:56 +0000190 LPVOID *pWork1, *pWork2;
Eric Kohld37b0191999-06-26 11:57:04 +0000191 INT nResult;
Ian Schmidt45584801999-07-28 16:35:24 +0000192 INT nIndex;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000193
Guy L. Albertelli97178452000-11-30 19:58:56 +0000194 TRACE("%p %p %08lx %p %p %08lx)\n",
Eric Kohld37b0191999-06-26 11:57:04 +0000195 hdpa1, hdpa2, dwFlags, pfnCompare, pfnMerge, lParam);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000196
Alexandre Julliarda3960291999-02-26 11:11:13 +0000197 if (IsBadWritePtr (hdpa1, sizeof(DPA)))
Eric Kohl0f7d5211998-11-22 17:54:40 +0000198 return FALSE;
199
Alexandre Julliarda3960291999-02-26 11:11:13 +0000200 if (IsBadWritePtr (hdpa2, sizeof(DPA)))
Eric Kohl0f7d5211998-11-22 17:54:40 +0000201 return FALSE;
202
Alexandre Julliarda3960291999-02-26 11:11:13 +0000203 if (IsBadCodePtr ((FARPROC)pfnCompare))
Eric Kohl0f7d5211998-11-22 17:54:40 +0000204 return FALSE;
205
Eric Kohld37b0191999-06-26 11:57:04 +0000206 if (IsBadCodePtr ((FARPROC)pfnMerge))
Eric Kohl0f7d5211998-11-22 17:54:40 +0000207 return FALSE;
208
209 if (dwFlags & DPAM_SORT) {
Alexandre Julliarda099a551999-06-12 15:45:58 +0000210 TRACE("sorting dpa's!\n");
Eric Kohld37b0191999-06-26 11:57:04 +0000211 if (hdpa1->nItemCount > 0)
Eric Kohl0f7d5211998-11-22 17:54:40 +0000212 DPA_Sort (hdpa1, pfnCompare, lParam);
Eric Kohld37b0191999-06-26 11:57:04 +0000213 TRACE ("dpa 1 sorted!\n");
214 if (hdpa2->nItemCount > 0)
Eric Kohl0f7d5211998-11-22 17:54:40 +0000215 DPA_Sort (hdpa2, pfnCompare, lParam);
Eric Kohld37b0191999-06-26 11:57:04 +0000216 TRACE ("dpa 2 sorted!\n");
Eric Kohl0f7d5211998-11-22 17:54:40 +0000217 }
218
Eric Kohld37b0191999-06-26 11:57:04 +0000219 if (hdpa2->nItemCount < 1)
Eric Kohl0f7d5211998-11-22 17:54:40 +0000220 return TRUE;
221
Eric Kohld37b0191999-06-26 11:57:04 +0000222 TRACE("hdpa1->nItemCount=%d hdpa2->nItemCount=%d\n",
223 hdpa1->nItemCount, hdpa2->nItemCount);
Eric Kohl0f7d5211998-11-22 17:54:40 +0000224
Eric Kohl0f7d5211998-11-22 17:54:40 +0000225
Guy L. Albertelli97178452000-11-30 19:58:56 +0000226 /* working but untrusted implementation */
Eric Kohl0f7d5211998-11-22 17:54:40 +0000227
Eric Kohld37b0191999-06-26 11:57:04 +0000228 pWork1 = &(hdpa1->ptrs[hdpa1->nItemCount - 1]);
229 pWork2 = &(hdpa2->ptrs[hdpa2->nItemCount - 1]);
Eric Kohl0f7d5211998-11-22 17:54:40 +0000230
Eric Kohld37b0191999-06-26 11:57:04 +0000231 nIndex = hdpa1->nItemCount - 1;
232 nCount = hdpa2->nItemCount - 1;
Eric Kohl0f7d5211998-11-22 17:54:40 +0000233
Eric Kohld37b0191999-06-26 11:57:04 +0000234 do
235 {
Guy L. Albertelli97178452000-11-30 19:58:56 +0000236 if (nIndex < 0) break;
237 nResult = (pfnCompare)(*pWork1, *pWork2, lParam);
238 TRACE("compare result=%d, dpa1.cnt=%d, dpa2.cnt=%d\n",
239 nResult, nIndex, nCount);
Eric Kohl0f7d5211998-11-22 17:54:40 +0000240
Eric Kohld37b0191999-06-26 11:57:04 +0000241 if (nResult == 0)
242 {
243 PVOID ptr;
244
Guy L. Albertelli97178452000-11-30 19:58:56 +0000245 ptr = (pfnMerge)(1, *pWork1, *pWork2, lParam);
Eric Kohld37b0191999-06-26 11:57:04 +0000246 if (!ptr)
247 return FALSE;
248
249 nCount--;
250 pWork2--;
Guy L. Albertelli97178452000-11-30 19:58:56 +0000251 *pWork1 = ptr;
252 nIndex--;
253 pWork1--;
Eric Kohl0f7d5211998-11-22 17:54:40 +0000254 }
Eric Kohld37b0191999-06-26 11:57:04 +0000255 else if (nResult < 0)
256 {
257 if (!dwFlags & 8)
258 {
259 PVOID ptr;
Eric Kohl0f7d5211998-11-22 17:54:40 +0000260
Eric Kohld37b0191999-06-26 11:57:04 +0000261 ptr = DPA_DeletePtr (hdpa1, hdpa1->nItemCount - 1);
Eric Kohl0f7d5211998-11-22 17:54:40 +0000262
Eric Kohld37b0191999-06-26 11:57:04 +0000263 (pfnMerge)(2, ptr, NULL, lParam);
264 }
Guy L. Albertelli97178452000-11-30 19:58:56 +0000265 nIndex--;
266 pWork1--;
Eric Kohl0f7d5211998-11-22 17:54:40 +0000267 }
Eric Kohld37b0191999-06-26 11:57:04 +0000268 else
269 {
270 if (!dwFlags & 4)
271 {
272 PVOID ptr;
273
Guy L. Albertelli97178452000-11-30 19:58:56 +0000274 ptr = (pfnMerge)(3, *pWork2, NULL, lParam);
Eric Kohld37b0191999-06-26 11:57:04 +0000275 if (!ptr)
276 return FALSE;
277 DPA_InsertPtr (hdpa1, nIndex, ptr);
Guy L. Albertelli97178452000-11-30 19:58:56 +0000278 }
Eric Kohld37b0191999-06-26 11:57:04 +0000279 nCount--;
280 pWork2--;
281 }
282
Eric Kohl0f7d5211998-11-22 17:54:40 +0000283 }
Eric Kohld37b0191999-06-26 11:57:04 +0000284 while (nCount >= 0);
Eric Kohl0f7d5211998-11-22 17:54:40 +0000285
Eric Kohl0f7d5211998-11-22 17:54:40 +0000286 return TRUE;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000287}
288
289
290/**************************************************************************
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000291 * Alloc [COMCTL32.71]
292 *
Eric Kohl17216d31998-10-11 13:21:17 +0000293 * Allocates memory block from the dll's private heap
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000294 *
295 * PARAMS
296 * dwSize [I] size of the allocated memory block
297 *
298 * RETURNS
299 * Success: pointer to allocated memory block
300 * Failure: NULL
301 */
302
303LPVOID WINAPI
304COMCTL32_Alloc (DWORD dwSize)
305{
306 LPVOID lpPtr;
307
Alexandre Julliarda099a551999-06-12 15:45:58 +0000308 TRACE("(0x%lx)\n", dwSize);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000309
Eric Kohl17216d31998-10-11 13:21:17 +0000310 lpPtr = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000311
Alexandre Julliarda099a551999-06-12 15:45:58 +0000312 TRACE("-- ret=%p\n", lpPtr);
Eric Kohl17216d31998-10-11 13:21:17 +0000313
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000314 return lpPtr;
315}
316
317
318/**************************************************************************
319 * ReAlloc [COMCTL32.72]
320 *
321 * Changes the size of an allocated memory block or allocates a memory
Eric Kohl17216d31998-10-11 13:21:17 +0000322 * block using the dll's private heap.
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000323 *
324 * PARAMS
325 * lpSrc [I] pointer to memory block which will be resized
326 * dwSize [I] new size of the memory block.
327 *
328 * RETURNS
329 * Success: pointer to the resized memory block
330 * Failure: NULL
331 *
332 * NOTES
333 * If lpSrc is a NULL-pointer, then COMCTL32_ReAlloc allocates a memory
334 * block like COMCTL32_Alloc.
335 */
336
337LPVOID WINAPI
338COMCTL32_ReAlloc (LPVOID lpSrc, DWORD dwSize)
339{
340 LPVOID lpDest;
341
Alexandre Julliarda099a551999-06-12 15:45:58 +0000342 TRACE("(%p 0x%08lx)\n", lpSrc, dwSize);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000343
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000344 if (lpSrc)
Eric Kohl17216d31998-10-11 13:21:17 +0000345 lpDest = HeapReAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, lpSrc, dwSize);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000346 else
Eric Kohl17216d31998-10-11 13:21:17 +0000347 lpDest = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000348
Alexandre Julliarda099a551999-06-12 15:45:58 +0000349 TRACE("-- ret=%p\n", lpDest);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000350
351 return lpDest;
352}
353
354
355/**************************************************************************
356 * Free [COMCTL32.73]
Eric Kohl65016631999-01-24 19:09:56 +0000357 *
Eric Kohl17216d31998-10-11 13:21:17 +0000358 * Frees an allocated memory block from the dll's private heap.
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000359 *
360 * PARAMS
361 * lpMem [I] pointer to memory block which will be freed
362 *
363 * RETURNS
364 * Success: TRUE
365 * Failure: FALSE
366 */
367
Alexandre Julliarda3960291999-02-26 11:11:13 +0000368BOOL WINAPI
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000369COMCTL32_Free (LPVOID lpMem)
370{
Alexandre Julliarda099a551999-06-12 15:45:58 +0000371 TRACE("(%p)\n", lpMem);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000372
Eric Kohl17216d31998-10-11 13:21:17 +0000373 return HeapFree (COMCTL32_hHeap, 0, lpMem);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000374}
375
376
377/**************************************************************************
378 * GetSize [COMCTL32.74]
379 *
380 * Retrieves the size of the specified memory block from the dll's
Eric Kohl17216d31998-10-11 13:21:17 +0000381 * private heap.
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000382 *
383 * PARAMS
384 * lpMem [I] pointer to an allocated memory block
385 *
386 * RETURNS
387 * Success: size of the specified memory block
388 * Failure: 0
389 */
390
391DWORD WINAPI
392COMCTL32_GetSize (LPVOID lpMem)
393{
Alexandre Julliarda099a551999-06-12 15:45:58 +0000394 TRACE("(%p)\n", lpMem);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000395
Eric Kohl17216d31998-10-11 13:21:17 +0000396 return HeapSize (COMCTL32_hHeap, 0, lpMem);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000397}
398
399
400/**************************************************************************
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000401 * The MRU-API is a set of functions to manipulate MRU(Most Recently Used)
402 * lists.
403 *
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000404 * Stored in the reg. as a set of values under a single key. Each item in the
405 * list has a value name that is a single char. 'a' - 'z', '{', '|' or '}'.
406 * The order of the list is stored with value name 'MRUList' which is a string
407 * containing the value names (i.e. 'a', 'b', etc.) in the relevant order.
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000408 */
409
Eric Kohl33910f171999-11-23 23:14:53 +0000410typedef struct tagCREATEMRULIST
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000411{
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000412 DWORD cbSize; /* size of struct */
413 DWORD nMaxItems; /* max no. of items in list */
414 DWORD dwFlags; /* see below */
415 HKEY hKey; /* root reg. key under which list is saved */
416 LPCSTR lpszSubKey; /* reg. subkey */
417 PROC lpfnCompare; /* item compare proc */
Eric Kohl33910f171999-11-23 23:14:53 +0000418} CREATEMRULIST, *LPCREATEMRULIST;
Eric Kohl17216d31998-10-11 13:21:17 +0000419
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000420/* dwFlags */
421#define MRUF_STRING_LIST 0 /* list will contain strings */
422#define MRUF_BINARY_LIST 1 /* list will contain binary data */
423#define MRUF_DELAYED_SAVE 2 /* only save list order to reg. is FreeMRUList */
424
425/* If list is a string list lpfnCompare has the following prototype
426 * int CALLBACK MRUCompareString(LPCSTR s1, LPCSTR s2)
427 * for binary lists the prototype is
428 * int CALLBACK MRUCompareBinary(LPCVOID data1, LPCVOID data2, DWORD cbData)
429 * where cbData is the no. of bytes to compare.
430 * Need to check what return value means identical - 0?
431 */
432
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000433typedef struct tagWINEMRUITEM
Eric Kohl17216d31998-10-11 13:21:17 +0000434{
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000435 DWORD size; /* size of data stored */
436 DWORD itemFlag; /* flags */
437 BYTE datastart;
438} WINEMRUITEM, *LPWINEMRUITEM;
439
440/* itemFlag */
441#define WMRUIF_CHANGED 0x0001 /* this dataitem changed */
442
443typedef struct tagWINEMRULIST
444{
445 CREATEMRULIST extview; /* original create information */
446 DWORD wineFlags; /* internal flags */
447 DWORD cursize; /* current size of realMRU */
448 LPSTR realMRU; /* pointer to string of index names */
449 LPWINEMRUITEM *array; /* array of pointers to data */
450 /* in 'a' to 'z' order */
451} WINEMRULIST, *LPWINEMRULIST;
452
453/* wineFlags */
454#define WMRUF_CHANGED 0x0001 /* MRU list has changed */
Eric Kohl17216d31998-10-11 13:21:17 +0000455
Eric Kohl33910f171999-11-23 23:14:53 +0000456HANDLE WINAPI
457CreateMRUListLazyA (LPCREATEMRULIST lpcml, DWORD dwParam2,
Eric Kohl17216d31998-10-11 13:21:17 +0000458 DWORD dwParam3, DWORD dwParam4);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000459
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000460/**************************************************************************
461 * MRU_SaveChanged - Localize MRU saving code
462 *
463 */
464VOID MRU_SaveChanged( LPWINEMRULIST mp )
465{
466 INT i, err;
467 HKEY newkey;
468 CHAR realname[2];
469 LPWINEMRUITEM witem;
470
471 /* or should we do the following instead of RegOpenKeyEx:
472 */
473
474 /* open the sub key */
475 if ((err = RegOpenKeyExA( mp->extview.hKey, mp->extview.lpszSubKey,
476 0, KEY_WRITE, &newkey))) {
477 /* not present - what to do ??? */
478 ERR("Can not open key, error=%d, attempting to create\n",
479 err);
480 if ((err = RegCreateKeyExA( mp->extview.hKey, mp->extview.lpszSubKey,
481 0,
482 "",
483 REG_OPTION_NON_VOLATILE,
484 KEY_READ | KEY_WRITE,
485 0,
486 &newkey,
487 0))) {
488 ERR("failed to create key /%s/, err=%d\n",
489 mp->extview.lpszSubKey, err);
490 return;
491 }
492 }
493 if (mp->wineFlags & WMRUF_CHANGED) {
494 mp->wineFlags &= ~WMRUF_CHANGED;
495 err = RegSetValueExA(newkey, "MRUList", 0, REG_SZ,
496 mp->realMRU, lstrlenA(mp->realMRU) + 1);
497 if (err) {
498 ERR("error saving MRUList, err=%d\n", err);
499 }
500 TRACE("saving MRUList=/%s/\n", mp->realMRU);
501 }
502 realname[1] = 0;
503 for(i=0; i<mp->cursize; i++) {
504 witem = mp->array[i];
505 if (witem->itemFlag & WMRUIF_CHANGED) {
506 witem->itemFlag &= ~WMRUIF_CHANGED;
507 realname[0] = 'a' + i;
508 err = RegSetValueExA(newkey, realname, 0,
509 (mp->extview.dwFlags & MRUF_BINARY_LIST) ?
510 REG_BINARY : REG_SZ,
511 &witem->datastart, witem->size);
512 if (err) {
513 ERR("error saving /%s/, err=%d\n", realname, err);
514 }
515 TRACE("saving value for name /%s/ size=%ld\n",
516 realname, witem->size);
517 }
518 }
519 RegCloseKey( newkey );
520}
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000521
522/**************************************************************************
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000523 * CreateMRUListA [COMCTL32.151]
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000524 *
525 * PARAMS
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000526 * lpcml [I] ptr to CREATEMRULIST structure.
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000527 *
528 * RETURNS
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000529 * Handle to MRU list.
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000530 */
Eric Kohl33910f171999-11-23 23:14:53 +0000531HANDLE WINAPI
532CreateMRUListA (LPCREATEMRULIST lpcml)
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000533{
Eric Kohl33910f171999-11-23 23:14:53 +0000534 return CreateMRUListLazyA (lpcml, 0, 0, 0);
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000535}
536
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000537/**************************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000538 * FreeMRUList [COMCTL32.152]
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000539 *
540 * PARAMS
541 * hMRUList [I] Handle to list.
542 *
543 */
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000544DWORD WINAPI
Eric Kohl33910f171999-11-23 23:14:53 +0000545FreeMRUListA (HANDLE hMRUList)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000546{
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000547 LPWINEMRULIST mp = (LPWINEMRULIST)hMRUList;
548 INT i;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000549
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000550 TRACE("\n");
551 if (mp->wineFlags & WMRUF_CHANGED) {
552 /* need to open key and then save the info */
553 MRU_SaveChanged( mp );
Eric Kohl17216d31998-10-11 13:21:17 +0000554 }
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000555
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000556 for(i=0; i<mp->extview.nMaxItems; i++) {
557 if (mp->array[i])
558 COMCTL32_Free(mp->array[i]);
559 }
560 COMCTL32_Free(mp->realMRU);
561 COMCTL32_Free(mp->array);
562 return COMCTL32_Free(mp);
563}
Eric Kohl17216d31998-10-11 13:21:17 +0000564
Eric Kohl17216d31998-10-11 13:21:17 +0000565
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000566/**************************************************************************
567 * FindMRUData [COMCTL32.169]
568 *
569 * Searches binary list for item that matches lpData of length cbData.
570 * Returns position in list order 0 -> MRU and if lpRegNum != NULL then value
571 * corresponding to item's reg. name will be stored in it ('a' -> 0).
572 *
573 * PARAMS
574 * hList [I] list handle
575 * lpData [I] data to find
576 * cbData [I] length of data
577 * lpRegNum [O] position in registry (maybe NULL)
578 *
579 * RETURNS
580 * Position in list 0 -> MRU. -1 if item not found.
581 */
582INT WINAPI
583FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum)
584{
585 LPWINEMRULIST mp = (LPWINEMRULIST)hList;
586 INT i, ret;
587
588 if (!mp->extview.lpfnCompare) {
589 ERR("MRU list not properly created. No compare procedure.\n");
590 return -1;
591 }
592
593 for(i=0; i<mp->cursize; i++) {
594 if (mp->extview.dwFlags & MRUF_BINARY_LIST) {
595 if (!mp->extview.lpfnCompare(lpData, &mp->array[i]->datastart,
596 cbData))
597 break;
598 }
599 else {
600 if (!mp->extview.lpfnCompare(lpData, &mp->array[i]->datastart))
601 break;
602 }
603 }
604 if (i < mp->cursize)
605 ret = i;
606 else
607 ret = -1;
608 if (lpRegNum && (ret != -1))
609 *lpRegNum = 'a' + i;
610
611 TRACE("(%08x, %p, %ld, %p) returning %d\n",
612 hList, lpData, cbData, lpRegNum, ret);
613
614 return ret;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000615}
616
617
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000618/**************************************************************************
619 * AddMRUData [COMCTL32.167]
620 *
Andreas Mohr99f2f392001-06-22 23:21:47 +0000621 * Add item to MRU binary list. If item already exists in list then it is
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000622 * simply moved up to the top of the list and not added again. If list is
623 * full then the least recently used item is removed to make room.
624 *
625 * PARAMS
626 * hList [I] Handle to list.
627 * lpData [I] ptr to data to add.
628 * cbData [I] no. of bytes of data.
629 *
630 * RETURNS
631 * No. corresponding to registry name where value is stored 'a' -> 0 etc.
632 * -1 on error.
633 */
634INT WINAPI
635AddMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData)
Eric Kohl17216d31998-10-11 13:21:17 +0000636{
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000637 LPWINEMRULIST mp = (LPWINEMRULIST)hList;
638 LPWINEMRUITEM witem;
639 INT i, replace, ret;
Eric Kohl17216d31998-10-11 13:21:17 +0000640
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000641 if ((replace = FindMRUData (hList, lpData, cbData, NULL)) < 0) {
642 /* either add a new entry or replace oldest */
643 if (mp->cursize < mp->extview.nMaxItems) {
644 /* Add in a new item */
645 replace = mp->cursize;
646 mp->cursize++;
647 }
648 else {
649 /* get the oldest entry and replace data */
650 replace = mp->realMRU[mp->cursize - 1] - 'a';
651 COMCTL32_Free(mp->array[replace]);
652 }
653 }
654 else {
655 /* free up the old data */
656 COMCTL32_Free(mp->array[replace]);
657 }
658
659 /* Allocate space for new item and move in the data */
660 mp->array[replace] = witem = (LPWINEMRUITEM)COMCTL32_Alloc(cbData +
661 sizeof(WINEMRUITEM));
662 witem->itemFlag |= WMRUIF_CHANGED;
663 witem->size = cbData;
664 memcpy( &witem->datastart, lpData, cbData);
665
666 /* now rotate MRU list */
667 mp->wineFlags |= WMRUF_CHANGED;
668 for(i=mp->cursize-1; i>=1; i--) {
669 mp->realMRU[i] = mp->realMRU[i-1];
670 }
671 mp->realMRU[0] = replace + 'a';
672 TRACE("(%08x, %p, %ld) adding data, /%c/ now most current\n",
673 hList, lpData, cbData, replace+'a');
674 ret = replace;
675
676 if (!(mp->extview.dwFlags & MRUF_DELAYED_SAVE)) {
677 /* save changed stuff right now */
678 MRU_SaveChanged( mp );
679 }
680
681 return ret;
Eric Kohl17216d31998-10-11 13:21:17 +0000682}
683
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000684/**************************************************************************
685 * AddMRUStringA [COMCTL32.153]
686 *
687 * Add item to MRU string list. If item already exists in list them it is
688 * simply moved up to the top of the list and not added again. If list is
689 * full then the least recently used item is removed to make room.
690 *
691 * PARAMS
692 * hList [I] Handle to list.
693 * lpszString [I] ptr to string to add.
694 *
695 * RETURNS
696 * No. corresponding to registry name where value is stored 'a' -> 0 etc.
697 * -1 on error.
698 */
699INT WINAPI
700AddMRUStringA(HANDLE hList, LPCSTR lpszString)
Eric Kohl17216d31998-10-11 13:21:17 +0000701{
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000702 FIXME("(%08x, %s) empty stub!\n", hList, debugstr_a(lpszString));
Eric Kohl17216d31998-10-11 13:21:17 +0000703
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000704 return 0;
705}
Eric Kohl17216d31998-10-11 13:21:17 +0000706
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000707/**************************************************************************
708 * DelMRUString [COMCTL32.156]
709 *
710 * Removes item from either string or binary list (despite its name)
711 *
712 * PARAMS
713 * hList [I] list handle
714 * nItemPos [I] item position to remove 0 -> MRU
715 *
716 * RETURNS
Andreas Mohr99f2f392001-06-22 23:21:47 +0000717 * TRUE if successful, FALSE if nItemPos is out of range.
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000718 */
719BOOL WINAPI
720DelMRUString(HANDLE hList, INT nItemPos)
721{
722 FIXME("(%08x, %d): stub\n", hList, nItemPos);
Eric Kohl3ad67461998-10-24 10:48:31 +0000723 return TRUE;
Eric Kohl17216d31998-10-11 13:21:17 +0000724}
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000725
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000726/**************************************************************************
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000727 * FindMRUStringA [COMCTL32.155]
728 *
729 * Searches string list for item that matches lpszString.
730 * Returns position in list order 0 -> MRU and if lpRegNum != NULL then value
731 * corresponding to item's reg. name will be stored in it ('a' -> 0).
732 *
733 * PARAMS
734 * hList [I] list handle
735 * lpszString [I] string to find
736 * lpRegNum [O] position in registry (maybe NULL)
737 *
738 * RETURNS
739 * Position in list 0 -> MRU. -1 if item not found.
740 */
741INT WINAPI
742FindMRUStringA (HANDLE hList, LPCSTR lpszString, LPINT lpRegNum)
743{
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000744 return FindMRUData(hList, (LPVOID)lpszString, lstrlenA(lpszString),
745 lpRegNum);
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000746}
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000747
Patrik Stridvallfcfacb92000-03-24 20:46:04 +0000748/**************************************************************************
749 * CreateMRUListLazyA [COMCTL32.157]
750 */
Eric Kohl33910f171999-11-23 23:14:53 +0000751HANDLE WINAPI
752CreateMRUListLazyA (LPCREATEMRULIST lpcml, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000753{
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000754 LPWINEMRULIST mp;
755 INT i, err;
756 HKEY newkey;
757 DWORD datasize, dwdisp;
758 CHAR realname[2];
759 LPWINEMRUITEM witem;
760 DWORD type;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000761
Eric Kohl33910f171999-11-23 23:14:53 +0000762 if (lpcml == NULL)
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000763 return 0;
Eric Kohl33910f171999-11-23 23:14:53 +0000764
765 if (lpcml->cbSize < sizeof(CREATEMRULIST))
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000766 return 0;
Eric Kohl33910f171999-11-23 23:14:53 +0000767
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000768 mp = (LPWINEMRULIST) COMCTL32_Alloc(sizeof(WINEMRULIST));
769 memcpy(mp, lpcml, sizeof(CREATEMRULIST));
770
771 /* get space to save indexes that will turn into names
772 * but in order of most to least recently used
773 */
774 mp->realMRU = (LPSTR) COMCTL32_Alloc(mp->extview.nMaxItems + 2);
775
776 /* get space to save pointers to actual data in order of
777 * 'a' to 'z' (0 to n).
778 */
779 mp->array = (LPVOID) COMCTL32_Alloc(mp->extview.nMaxItems *
780 sizeof(LPVOID));
781
782 /* open the sub key */
783 if ((err = RegCreateKeyExA( mp->extview.hKey, mp->extview.lpszSubKey,
784 0,
785 "",
786 REG_OPTION_NON_VOLATILE,
787 KEY_READ | KEY_WRITE,
788 0,
789 &newkey,
790 &dwdisp))) {
791 /* error - what to do ??? */
792 ERR("(%lu %lu %lx %lx \"%s\" %p): Can not open key, error=%d\n",
793 lpcml->cbSize, lpcml->nMaxItems, lpcml->dwFlags,
794 (DWORD)lpcml->hKey, lpcml->lpszSubKey, lpcml->lpfnCompare,
795 err);
796 return 0;
797 }
798
799 /* get values from key 'MRUList' */
800 if (newkey) {
801 datasize = mp->extview.nMaxItems + 1;
802 if((err=RegQueryValueExA( newkey, "MRUList", 0, &type, mp->realMRU,
803 &datasize))) {
804 /* not present - set size to 1 (will become 0 later) */
805 datasize = 1;
806 *mp->realMRU = 0;
807 }
808
809 TRACE("MRU list = %s\n", mp->realMRU);
810
811 mp->cursize = datasize - 1;
812 /* datasize now has number of items in the MRUList */
813
814 /* get actual values for each entry */
815 realname[1] = 0;
816 for(i=0; i<mp->cursize; i++) {
817 realname[0] = 'a' + i;
818 if(RegQueryValueExA( newkey, realname, 0, &type, 0, &datasize)) {
819 /* not present - what to do ??? */
820 ERR("Key %s not found 1\n", realname);
821 }
822 mp->array[i] = witem = (LPWINEMRUITEM)COMCTL32_Alloc(datasize +
823 sizeof(WINEMRUITEM));
824 witem->size = datasize;
825 if(RegQueryValueExA( newkey, realname, 0, &type,
826 &witem->datastart, &datasize)) {
827 /* not present - what to do ??? */
828 ERR("Key %s not found 2\n", realname);
829 }
830 }
831 RegCloseKey( newkey );
832 }
833 else
834 mp->cursize = 0;
835
836 TRACE("(%lu %lu %lx %lx \"%s\" %p): Current Size = %ld\n",
Eric Kohl33910f171999-11-23 23:14:53 +0000837 lpcml->cbSize, lpcml->nMaxItems, lpcml->dwFlags,
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000838 (DWORD)lpcml->hKey, lpcml->lpszSubKey, lpcml->lpfnCompare,
839 mp->cursize);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000840
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000841 return (HANDLE)mp;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000842}
843
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000844/**************************************************************************
845 * EnumMRUListA [COMCTL32.154]
846 *
847 * Enumerate item in a list
848 *
849 * PARAMS
850 * hList [I] list handle
851 * nItemPos [I] item position to enumerate
852 * lpBuffer [O] buffer to receive item
853 * nBufferSize [I] size of buffer
854 *
855 * RETURNS
856 * For binary lists specifies how many bytes were copied to buffer, for
857 * string lists specifies full length of string. Enumerating past the end
858 * of list returns -1.
859 * If lpBuffer == NULL or nItemPos is -ve return value is no. of items in
860 * the list.
861 */
862INT WINAPI EnumMRUListA(HANDLE hList, INT nItemPos, LPVOID lpBuffer,
863DWORD nBufferSize)
864{
Guy Albertelli45e9cea2001-09-20 18:58:43 +0000865 LPWINEMRULIST mp = (LPWINEMRULIST) hList;
866 LPWINEMRUITEM witem;
867 INT desired, datasize;
868
869 if (nItemPos >= mp->cursize) return -1;
870 if ((nItemPos < 0) || !lpBuffer) return mp->cursize;
871 desired = mp->realMRU[nItemPos];
872 desired -= 'a';
873 TRACE("nItemPos=%d, desired=%d\n", nItemPos, desired);
874 witem = mp->array[desired];
875 datasize = min( witem->size, nBufferSize );
876 memcpy( lpBuffer, &witem->datastart, datasize);
877 TRACE("(%08x, %d, %p, %ld): returning len=%d\n",
878 hList, nItemPos, lpBuffer, nBufferSize, datasize);
879 return datasize;
Huw D M Daviesbbe263b1999-12-04 04:01:41 +0000880}
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000881
882/**************************************************************************
883 * Str_GetPtrA [COMCTL32.233]
884 *
885 * PARAMS
886 * lpSrc [I]
887 * lpDest [O]
888 * nMaxLen [I]
889 *
890 * RETURNS
891 */
892
Alexandre Julliarda3960291999-02-26 11:11:13 +0000893INT WINAPI
894Str_GetPtrA (LPCSTR lpSrc, LPSTR lpDest, INT nMaxLen)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000895{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000896 INT len;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000897
Alexandre Julliarda099a551999-06-12 15:45:58 +0000898 TRACE("(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000899
900 if (!lpDest && lpSrc)
Alexandre Julliardc7e7df82000-08-14 14:41:19 +0000901 return strlen (lpSrc);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000902
903 if (nMaxLen == 0)
904 return 0;
905
906 if (lpSrc == NULL) {
907 lpDest[0] = '\0';
908 return 0;
909 }
910
Alexandre Julliardc7e7df82000-08-14 14:41:19 +0000911 len = strlen (lpSrc);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000912 if (len >= nMaxLen)
913 len = nMaxLen - 1;
914
915 RtlMoveMemory (lpDest, lpSrc, len);
916 lpDest[len] = '\0';
917
918 return len;
919}
920
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000921
922/**************************************************************************
923 * Str_SetPtrA [COMCTL32.234]
924 *
925 * PARAMS
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000926 * lppDest [O]
927 * lpSrc [I]
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000928 *
929 * RETURNS
930 */
931
Alexandre Julliarda3960291999-02-26 11:11:13 +0000932BOOL WINAPI
933Str_SetPtrA (LPSTR *lppDest, LPCSTR lpSrc)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000934{
Alexandre Julliarda099a551999-06-12 15:45:58 +0000935 TRACE("(%p %p)\n", lppDest, lpSrc);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000936
937 if (lpSrc) {
Alexandre Julliardc7e7df82000-08-14 14:41:19 +0000938 LPSTR ptr = COMCTL32_ReAlloc (*lppDest, strlen (lpSrc) + 1);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000939 if (!ptr)
940 return FALSE;
Alexandre Julliardc7e7df82000-08-14 14:41:19 +0000941 strcpy (ptr, lpSrc);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000942 *lppDest = ptr;
943 }
944 else {
945 if (*lppDest) {
946 COMCTL32_Free (*lppDest);
947 *lppDest = NULL;
948 }
949 }
950
951 return TRUE;
952}
953
954
955/**************************************************************************
956 * Str_GetPtrW [COMCTL32.235]
957 *
958 * PARAMS
959 * lpSrc [I]
960 * lpDest [O]
961 * nMaxLen [I]
962 *
963 * RETURNS
964 */
965
Alexandre Julliarda3960291999-02-26 11:11:13 +0000966INT WINAPI
967Str_GetPtrW (LPCWSTR lpSrc, LPWSTR lpDest, INT nMaxLen)
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000968{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000969 INT len;
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000970
Alexandre Julliarda099a551999-06-12 15:45:58 +0000971 TRACE("(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000972
973 if (!lpDest && lpSrc)
Alexandre Julliardc7e7df82000-08-14 14:41:19 +0000974 return strlenW (lpSrc);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000975
976 if (nMaxLen == 0)
977 return 0;
978
979 if (lpSrc == NULL) {
980 lpDest[0] = L'\0';
981 return 0;
982 }
983
Alexandre Julliardc7e7df82000-08-14 14:41:19 +0000984 len = strlenW (lpSrc);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000985 if (len >= nMaxLen)
986 len = nMaxLen - 1;
987
988 RtlMoveMemory (lpDest, lpSrc, len*sizeof(WCHAR));
989 lpDest[len] = L'\0';
990
991 return len;
992}
993
994
995/**************************************************************************
996 * Str_SetPtrW [COMCTL32.236]
997 *
998 * PARAMS
999 * lpDest [O]
1000 * lpSrc [I]
1001 *
1002 * RETURNS
1003 */
1004
Alexandre Julliarda3960291999-02-26 11:11:13 +00001005BOOL WINAPI
1006Str_SetPtrW (LPWSTR *lppDest, LPCWSTR lpSrc)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001007{
Alexandre Julliarda099a551999-06-12 15:45:58 +00001008 TRACE("(%p %p)\n", lppDest, lpSrc);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001009
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001010 if (lpSrc) {
Alexandre Julliardc7e7df82000-08-14 14:41:19 +00001011 INT len = strlenW (lpSrc) + 1;
Eric Kohl0f7d5211998-11-22 17:54:40 +00001012 LPWSTR ptr = COMCTL32_ReAlloc (*lppDest, len * sizeof(WCHAR));
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001013 if (!ptr)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001014 return FALSE;
Alexandre Julliardc7e7df82000-08-14 14:41:19 +00001015 strcpyW (ptr, lpSrc);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001016 *lppDest = ptr;
1017 }
1018 else {
1019 if (*lppDest) {
1020 COMCTL32_Free (*lppDest);
1021 *lppDest = NULL;
1022 }
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001023 }
1024
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001025 return TRUE;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001026}
1027
1028
1029/**************************************************************************
Eric Kohlb7546b62000-11-15 22:14:43 +00001030 * Str_GetPtrWtoA [internal]
1031 *
1032 * Converts a unicode string into a multi byte string
1033 *
1034 * PARAMS
1035 * lpSrc [I] Pointer to the unicode source string
1036 * lpDest [O] Pointer to caller supplied storage for the multi byte string
1037 * nMaxLen [I] Size, in bytes, of the destination buffer
1038 *
1039 * RETURNS
1040 * Length, in bytes, of the converted string.
1041 */
1042
1043INT
1044Str_GetPtrWtoA (LPCWSTR lpSrc, LPSTR lpDest, INT nMaxLen)
1045{
1046 INT len;
1047
1048 TRACE("(%s %p %d)\n", debugstr_w(lpSrc), lpDest, nMaxLen);
1049
1050 if (!lpDest && lpSrc)
1051 return WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL);
1052
1053 if (nMaxLen == 0)
1054 return 0;
1055
1056 if (lpSrc == NULL) {
1057 lpDest[0] = '\0';
1058 return 0;
1059 }
1060
1061 len = WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL);
1062 if (len >= nMaxLen)
1063 len = nMaxLen - 1;
1064
1065 WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, lpDest, len, NULL, NULL);
1066 lpDest[len] = '\0';
1067
1068 return len;
1069}
1070
1071
1072/**************************************************************************
1073 * Str_SetPtrAtoW [internal]
1074 *
1075 * Converts a multi byte string to a unicode string.
1076 * If the pointer to the destination buffer is NULL a buffer is allocated.
1077 * If the destination buffer is too small to keep the converted multi byte
1078 * string the destination buffer is reallocated. If the source pointer is
1079 * NULL, the destination buffer is freed.
1080 *
1081 * PARAMS
1082 * lppDest [I/O] pointer to a pointer to the destination buffer
1083 * lpSrc [I] pointer to a multi byte string
1084 *
1085 * RETURNS
1086 * TRUE: conversion successful
1087 * FALSE: error
1088 */
1089
1090BOOL
1091Str_SetPtrAtoW (LPWSTR *lppDest, LPCSTR lpSrc)
1092{
1093 TRACE("(%p %s)\n", lppDest, lpSrc);
1094
1095 if (lpSrc) {
1096 INT len = MultiByteToWideChar(CP_ACP,0,lpSrc,-1,NULL,0);
Marcus Meissnerc2806fa2000-11-25 01:20:53 +00001097 LPWSTR ptr = COMCTL32_ReAlloc (*lppDest, len*sizeof(WCHAR));
Eric Kohlb7546b62000-11-15 22:14:43 +00001098
1099 if (!ptr)
1100 return FALSE;
1101 MultiByteToWideChar(CP_ACP,0,lpSrc,-1,ptr,len);
1102 *lppDest = ptr;
1103 }
1104 else {
1105 if (*lppDest) {
1106 COMCTL32_Free (*lppDest);
1107 *lppDest = NULL;
1108 }
1109 }
1110
1111 return TRUE;
1112}
1113
1114
1115/**************************************************************************
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001116 * The DSA-API is a set of functions to create and manipulate arrays of
Andreas Mohrfd79ce02000-07-08 11:44:20 +00001117 * fixed-size memory blocks. These arrays can store any kind of data
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001118 * (strings, icons...).
1119 */
1120
1121/**************************************************************************
1122 * DSA_Create [COMCTL32.320] Creates a dynamic storage array
1123 *
1124 * PARAMS
1125 * nSize [I] size of the array elements
1126 * nGrow [I] number of elements by which the array grows when it is filled
1127 *
1128 * RETURNS
Andreas Mohrfd79ce02000-07-08 11:44:20 +00001129 * Success: pointer to an array control structure. Use this like a handle.
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001130 * Failure: NULL
1131 */
1132
1133HDSA WINAPI
Alexandre Julliarda3960291999-02-26 11:11:13 +00001134DSA_Create (INT nSize, INT nGrow)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001135{
1136 HDSA hdsa;
1137
Alexandre Julliarda099a551999-06-12 15:45:58 +00001138 TRACE("(size=%d grow=%d)\n", nSize, nGrow);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001139
1140 hdsa = (HDSA)COMCTL32_Alloc (sizeof(DSA));
1141 if (hdsa)
1142 {
1143 hdsa->nItemCount = 0;
1144 hdsa->pData = NULL;
1145 hdsa->nMaxCount = 0;
1146 hdsa->nItemSize = nSize;
Francois Gouget6d77d3a2000-03-25 21:44:35 +00001147 hdsa->nGrow = max(1, nGrow);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001148 }
1149
1150 return hdsa;
1151}
1152
1153
1154/**************************************************************************
1155 * DSA_Destroy [COMCTL32.321] Destroys a dynamic storage array
1156 *
1157 * PARAMS
1158 * hdsa [I] pointer to the array control structure
1159 *
1160 * RETURNS
1161 * Success: TRUE
1162 * Failure: FALSE
1163 */
1164
Alexandre Julliarda3960291999-02-26 11:11:13 +00001165BOOL WINAPI
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001166DSA_Destroy (const HDSA hdsa)
1167{
Alexandre Julliarda099a551999-06-12 15:45:58 +00001168 TRACE("(%p)\n", hdsa);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001169
1170 if (!hdsa)
1171 return FALSE;
1172
1173 if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
1174 return FALSE;
1175
1176 return COMCTL32_Free (hdsa);
1177}
1178
1179
1180/**************************************************************************
1181 * DSA_GetItem [COMCTL32.322]
1182 *
1183 * PARAMS
1184 * hdsa [I] pointer to the array control structure
1185 * nIndex [I] number of the Item to get
1186 * pDest [O] destination buffer. Has to be >= dwElementSize.
1187 *
1188 * RETURNS
1189 * Success: TRUE
1190 * Failure: FALSE
1191 */
1192
Alexandre Julliarda3960291999-02-26 11:11:13 +00001193BOOL WINAPI
1194DSA_GetItem (const HDSA hdsa, INT nIndex, LPVOID pDest)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001195{
1196 LPVOID pSrc;
1197
Alexandre Julliarda099a551999-06-12 15:45:58 +00001198 TRACE("(%p %d %p)\n", hdsa, nIndex, pDest);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001199
1200 if (!hdsa)
1201 return FALSE;
1202 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
1203 return FALSE;
1204
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001205 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001206 memmove (pDest, pSrc, hdsa->nItemSize);
1207
1208 return TRUE;
1209}
1210
1211
1212/**************************************************************************
1213 * DSA_GetItemPtr [COMCTL32.323]
1214 *
1215 * Retrieves a pointer to the specified item.
1216 *
1217 * PARAMS
1218 * hdsa [I] pointer to the array control structure
1219 * nIndex [I] index of the desired item
1220 *
1221 * RETURNS
1222 * Success: pointer to an item
1223 * Failure: NULL
1224 */
1225
1226LPVOID WINAPI
Alexandre Julliarda3960291999-02-26 11:11:13 +00001227DSA_GetItemPtr (const HDSA hdsa, INT nIndex)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001228{
1229 LPVOID pSrc;
1230
Alexandre Julliarda099a551999-06-12 15:45:58 +00001231 TRACE("(%p %d)\n", hdsa, nIndex);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001232
1233 if (!hdsa)
1234 return NULL;
1235 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
1236 return NULL;
1237
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001238 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001239
Alexandre Julliarda099a551999-06-12 15:45:58 +00001240 TRACE("-- ret=%p\n", pSrc);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001241
Andreas Mohrfd79ce02000-07-08 11:44:20 +00001242 return pSrc;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001243}
1244
1245
1246/**************************************************************************
1247 * DSA_SetItem [COMCTL32.325]
1248 *
1249 * Sets the contents of an item in the array.
1250 *
1251 * PARAMS
1252 * hdsa [I] pointer to the array control structure
1253 * nIndex [I] index for the item
1254 * pSrc [I] pointer to the new item data
1255 *
1256 * RETURNS
1257 * Success: TRUE
1258 * Failure: FALSE
1259 */
1260
Alexandre Julliarda3960291999-02-26 11:11:13 +00001261BOOL WINAPI
1262DSA_SetItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001263{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001264 INT nSize, nNewItems;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001265 LPVOID pDest, lpTemp;
1266
Alexandre Julliarda099a551999-06-12 15:45:58 +00001267 TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001268
1269 if ((!hdsa) || nIndex < 0)
1270 return FALSE;
1271
1272 if (hdsa->nItemCount <= nIndex) {
1273 /* within the old array */
1274 if (hdsa->nMaxCount > nIndex) {
1275 /* within the allocated space, set a new boundary */
Ian Schmidt64eed991999-06-12 06:48:49 +00001276 hdsa->nItemCount = nIndex + 1;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001277 }
1278 else {
1279 /* resize the block of memory */
1280 nNewItems =
Eric Pouech200f89211999-09-13 15:11:02 +00001281 hdsa->nGrow * ((INT)(((nIndex + 1) - 1) / hdsa->nGrow) + 1);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001282 nSize = hdsa->nItemSize * nNewItems;
1283
1284 lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
1285 if (!lpTemp)
1286 return FALSE;
1287
1288 hdsa->nMaxCount = nNewItems;
Ian Schmidt64eed991999-06-12 06:48:49 +00001289 hdsa->nItemCount = nIndex + 1;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001290 hdsa->pData = lpTemp;
1291 }
1292 }
1293
1294 /* put the new entry in */
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001295 pDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
Alexandre Julliarda099a551999-06-12 15:45:58 +00001296 TRACE("-- move dest=%p src=%p size=%d\n",
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001297 pDest, pSrc, hdsa->nItemSize);
1298 memmove (pDest, pSrc, hdsa->nItemSize);
1299
1300 return TRUE;
1301}
1302
1303
1304/**************************************************************************
Patrik Stridvall60767292001-06-19 03:34:07 +00001305 * DSA_InsertItem [COMCTL32.324]
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001306 *
1307 * PARAMS
1308 * hdsa [I] pointer to the array control structure
1309 * nIndex [I] index for the new item
1310 * pSrc [I] pointer to the element
1311 *
1312 * RETURNS
1313 * Success: position of the new item
1314 * Failure: -1
1315 */
1316
Alexandre Julliarda3960291999-02-26 11:11:13 +00001317INT WINAPI
1318DSA_InsertItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001319{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001320 INT nNewItems, nSize, i;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001321 LPVOID lpTemp, lpDest;
1322 LPDWORD p;
1323
Alexandre Julliarda099a551999-06-12 15:45:58 +00001324 TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001325
1326 if ((!hdsa) || nIndex < 0)
1327 return -1;
1328
1329 for (i = 0; i < hdsa->nItemSize; i += 4) {
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001330 p = *(DWORD**)((char *) pSrc + i);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001331 if (IsBadStringPtrA ((char*)p, 256))
Alexandre Julliarda099a551999-06-12 15:45:58 +00001332 TRACE("-- %d=%p\n", i, (DWORD*)p);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001333 else
Alexandre Julliarda099a551999-06-12 15:45:58 +00001334 TRACE("-- %d=%p [%s]\n", i, p, debugstr_a((char*)p));
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001335 }
1336
Andreas Mohrfd79ce02000-07-08 11:44:20 +00001337 /* when nIndex >= nItemCount then append */
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001338 if (nIndex >= hdsa->nItemCount)
1339 nIndex = hdsa->nItemCount;
1340
1341 /* do we need to resize ? */
1342 if (hdsa->nItemCount >= hdsa->nMaxCount) {
1343 nNewItems = hdsa->nMaxCount + hdsa->nGrow;
1344 nSize = hdsa->nItemSize * nNewItems;
1345
1346 lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
1347 if (!lpTemp)
1348 return -1;
1349
1350 hdsa->nMaxCount = nNewItems;
1351 hdsa->pData = lpTemp;
1352 }
1353
1354 /* do we need to move elements ? */
1355 if (nIndex < hdsa->nItemCount) {
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001356 lpTemp = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1357 lpDest = (char *) lpTemp + hdsa->nItemSize;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001358 nSize = (hdsa->nItemCount - nIndex) * hdsa->nItemSize;
Alexandre Julliarda099a551999-06-12 15:45:58 +00001359 TRACE("-- move dest=%p src=%p size=%d\n",
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001360 lpDest, lpTemp, nSize);
1361 memmove (lpDest, lpTemp, nSize);
1362 }
1363
1364 /* ok, we can put the new Item in */
1365 hdsa->nItemCount++;
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001366 lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
Alexandre Julliarda099a551999-06-12 15:45:58 +00001367 TRACE("-- move dest=%p src=%p size=%d\n",
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001368 lpDest, pSrc, hdsa->nItemSize);
1369 memmove (lpDest, pSrc, hdsa->nItemSize);
1370
Andreas Mohrfd79ce02000-07-08 11:44:20 +00001371 return nIndex;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001372}
1373
1374
1375/**************************************************************************
1376 * DSA_DeleteItem [COMCTL32.326]
1377 *
1378 * PARAMS
1379 * hdsa [I] pointer to the array control structure
1380 * nIndex [I] index for the element to delete
1381 *
1382 * RETURNS
1383 * Success: number of the deleted element
1384 * Failure: -1
1385 */
1386
Alexandre Julliarda3960291999-02-26 11:11:13 +00001387INT WINAPI
1388DSA_DeleteItem (const HDSA hdsa, INT nIndex)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001389{
1390 LPVOID lpDest,lpSrc;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001391 INT nSize;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001392
Alexandre Julliarda099a551999-06-12 15:45:58 +00001393 TRACE("(%p %d)\n", hdsa, nIndex);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001394
1395 if (!hdsa)
1396 return -1;
1397 if (nIndex < 0 || nIndex >= hdsa->nItemCount)
1398 return -1;
1399
1400 /* do we need to move ? */
1401 if (nIndex < hdsa->nItemCount - 1) {
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001402 lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1403 lpSrc = (char *) lpDest + hdsa->nItemSize;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001404 nSize = hdsa->nItemSize * (hdsa->nItemCount - nIndex - 1);
Alexandre Julliarda099a551999-06-12 15:45:58 +00001405 TRACE("-- move dest=%p src=%p size=%d\n",
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001406 lpDest, lpSrc, nSize);
1407 memmove (lpDest, lpSrc, nSize);
1408 }
1409
1410 hdsa->nItemCount--;
1411
1412 /* free memory ? */
1413 if ((hdsa->nMaxCount - hdsa->nItemCount) >= hdsa->nGrow) {
1414 nSize = hdsa->nItemSize * hdsa->nItemCount;
1415
1416 lpDest = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
1417 if (!lpDest)
1418 return -1;
1419
1420 hdsa->nMaxCount = hdsa->nItemCount;
1421 hdsa->pData = lpDest;
1422 }
1423
1424 return nIndex;
1425}
1426
1427
1428/**************************************************************************
Patrik Stridvall60767292001-06-19 03:34:07 +00001429 * DSA_DeleteAllItems [COMCTL32.327]
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001430 *
1431 * Removes all items and reinitializes the array.
1432 *
1433 * PARAMS
1434 * hdsa [I] pointer to the array control structure
1435 *
1436 * RETURNS
1437 * Success: TRUE
1438 * Failure: FALSE
1439 */
1440
Alexandre Julliarda3960291999-02-26 11:11:13 +00001441BOOL WINAPI
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001442DSA_DeleteAllItems (const HDSA hdsa)
1443{
Alexandre Julliarda099a551999-06-12 15:45:58 +00001444 TRACE("(%p)\n", hdsa);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001445
1446 if (!hdsa)
1447 return FALSE;
1448 if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
1449 return FALSE;
1450
1451 hdsa->nItemCount = 0;
1452 hdsa->pData = NULL;
1453 hdsa->nMaxCount = 0;
1454
1455 return TRUE;
1456}
1457
1458
1459/**************************************************************************
1460 * The DPA-API is a set of functions to create and manipulate arrays of
1461 * pointers.
1462 */
1463
1464/**************************************************************************
1465 * DPA_Create [COMCTL32.328] Creates a dynamic pointer array
1466 *
1467 * PARAMS
1468 * nGrow [I] number of items by which the array grows when it is filled
1469 *
1470 * RETURNS
1471 * Success: handle (pointer) to the pointer array.
1472 * Failure: NULL
1473 */
1474
1475HDPA WINAPI
Alexandre Julliarda3960291999-02-26 11:11:13 +00001476DPA_Create (INT nGrow)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001477{
1478 HDPA hdpa;
1479
Alexandre Julliarda099a551999-06-12 15:45:58 +00001480 TRACE("(%d)\n", nGrow);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001481
1482 hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
1483 if (hdpa) {
Francois Gouget6d77d3a2000-03-25 21:44:35 +00001484 hdpa->nGrow = max(8, nGrow);
Eric Kohl17216d31998-10-11 13:21:17 +00001485 hdpa->hHeap = COMCTL32_hHeap;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001486 hdpa->nMaxCount = hdpa->nGrow * 2;
1487 hdpa->ptrs =
1488 (LPVOID*)COMCTL32_Alloc (hdpa->nMaxCount * sizeof(LPVOID));
1489 }
1490
Alexandre Julliarda099a551999-06-12 15:45:58 +00001491 TRACE("-- %p\n", hdpa);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001492
1493 return hdpa;
1494}
1495
1496
1497/**************************************************************************
1498 * DPA_Destroy [COMCTL32.329] Destroys a dynamic pointer array
1499 *
1500 * PARAMS
1501 * hdpa [I] handle (pointer) to the pointer array
1502 *
1503 * RETURNS
1504 * Success: TRUE
1505 * Failure: FALSE
1506 */
1507
Alexandre Julliarda3960291999-02-26 11:11:13 +00001508BOOL WINAPI
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001509DPA_Destroy (const HDPA hdpa)
1510{
Alexandre Julliarda099a551999-06-12 15:45:58 +00001511 TRACE("(%p)\n", hdpa);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001512
1513 if (!hdpa)
1514 return FALSE;
1515
1516 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
1517 return FALSE;
1518
1519 return HeapFree (hdpa->hHeap, 0, hdpa);
1520}
1521
1522
1523/**************************************************************************
1524 * DPA_Grow [COMCTL32.330]
1525 *
1526 * Sets the growth amount.
1527 *
1528 * PARAMS
1529 * hdpa [I] handle (pointer) to the existing (source) pointer array
Andreas Mohr99f2f392001-06-22 23:21:47 +00001530 * nGrow [I] number of items by which the array grows when it's too small
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001531 *
1532 * RETURNS
1533 * Success: TRUE
1534 * Failure: FALSE
1535 */
1536
Alexandre Julliarda3960291999-02-26 11:11:13 +00001537BOOL WINAPI
1538DPA_Grow (const HDPA hdpa, INT nGrow)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001539{
Alexandre Julliarda099a551999-06-12 15:45:58 +00001540 TRACE("(%p %d)\n", hdpa, nGrow);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001541
1542 if (!hdpa)
1543 return FALSE;
1544
Francois Gouget6d77d3a2000-03-25 21:44:35 +00001545 hdpa->nGrow = max(8, nGrow);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001546
1547 return TRUE;
1548}
1549
1550
1551/**************************************************************************
1552 * DPA_Clone [COMCTL32.331]
1553 *
1554 * Copies a pointer array to an other one or creates a copy
1555 *
1556 * PARAMS
1557 * hdpa [I] handle (pointer) to the existing (source) pointer array
1558 * hdpaNew [O] handle (pointer) to the destination pointer array
1559 *
1560 * RETURNS
1561 * Success: pointer to the destination pointer array.
1562 * Failure: NULL
1563 *
1564 * NOTES
1565 * - If the 'hdpaNew' is a NULL-Pointer, a copy of the source pointer
1566 * array will be created and it's handle (pointer) is returned.
1567 * - If 'hdpa' is a NULL-Pointer, the original implementation crashes,
1568 * this implementation just returns NULL.
1569 */
1570
1571HDPA WINAPI
1572DPA_Clone (const HDPA hdpa, const HDPA hdpaNew)
1573{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001574 INT nNewItems, nSize;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001575 HDPA hdpaTemp;
1576
1577 if (!hdpa)
1578 return NULL;
1579
Alexandre Julliarda099a551999-06-12 15:45:58 +00001580 TRACE("(%p %p)\n", hdpa, hdpaNew);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001581
1582 if (!hdpaNew) {
1583 /* create a new DPA */
1584 hdpaTemp = (HDPA)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1585 sizeof(DPA));
1586 hdpaTemp->hHeap = hdpa->hHeap;
1587 hdpaTemp->nGrow = hdpa->nGrow;
1588 }
1589 else
1590 hdpaTemp = hdpaNew;
1591
1592 if (hdpaTemp->ptrs) {
1593 /* remove old pointer array */
1594 HeapFree (hdpaTemp->hHeap, 0, hdpaTemp->ptrs);
1595 hdpaTemp->ptrs = NULL;
1596 hdpaTemp->nItemCount = 0;
1597 hdpaTemp->nMaxCount = 0;
1598 }
1599
1600 /* create a new pointer array */
1601 nNewItems = hdpaTemp->nGrow *
Alexandre Julliarda3960291999-02-26 11:11:13 +00001602 ((INT)((hdpa->nItemCount - 1) / hdpaTemp->nGrow) + 1);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001603 nSize = nNewItems * sizeof(LPVOID);
1604 hdpaTemp->ptrs =
1605 (LPVOID*)HeapAlloc (hdpaTemp->hHeap, HEAP_ZERO_MEMORY, nSize);
1606 hdpaTemp->nMaxCount = nNewItems;
1607
1608 /* clone the pointer array */
1609 hdpaTemp->nItemCount = hdpa->nItemCount;
1610 memmove (hdpaTemp->ptrs, hdpa->ptrs,
1611 hdpaTemp->nItemCount * sizeof(LPVOID));
1612
1613 return hdpaTemp;
1614}
1615
1616
1617/**************************************************************************
1618 * DPA_GetPtr [COMCTL32.332]
1619 *
1620 * Retrieves a pointer from a dynamic pointer array
1621 *
1622 * PARAMS
1623 * hdpa [I] handle (pointer) to the pointer array
1624 * nIndex [I] array index of the desired pointer
1625 *
1626 * RETURNS
1627 * Success: pointer
1628 * Failure: NULL
1629 */
1630
1631LPVOID WINAPI
Alexandre Julliarda3960291999-02-26 11:11:13 +00001632DPA_GetPtr (const HDPA hdpa, INT i)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001633{
Alexandre Julliarda099a551999-06-12 15:45:58 +00001634 TRACE("(%p %d)\n", hdpa, i);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001635
1636 if (!hdpa)
1637 return NULL;
Marcus Meissnerddedfa22000-11-04 02:56:38 +00001638 if (!hdpa->ptrs) {
1639 WARN("no pointer array.\n");
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001640 return NULL;
Marcus Meissnerddedfa22000-11-04 02:56:38 +00001641 }
1642 if ((i < 0) || (i >= hdpa->nItemCount)) {
1643 WARN("not enough pointers in array (%d vs %d).\n",i,hdpa->nItemCount);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001644 return NULL;
Marcus Meissnerddedfa22000-11-04 02:56:38 +00001645 }
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001646
Alexandre Julliarda099a551999-06-12 15:45:58 +00001647 TRACE("-- %p\n", hdpa->ptrs[i]);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001648
1649 return hdpa->ptrs[i];
1650}
1651
1652
1653/**************************************************************************
1654 * DPA_GetPtrIndex [COMCTL32.333]
1655 *
1656 * Retrieves the index of the specified pointer
1657 *
1658 * PARAMS
1659 * hdpa [I] handle (pointer) to the pointer array
1660 * p [I] pointer
1661 *
1662 * RETURNS
1663 * Success: index of the specified pointer
1664 * Failure: -1
1665 */
1666
Alexandre Julliarda3960291999-02-26 11:11:13 +00001667INT WINAPI
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001668DPA_GetPtrIndex (const HDPA hdpa, LPVOID p)
1669{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001670 INT i;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001671
1672 if (!hdpa->ptrs)
1673 return -1;
1674
1675 for (i = 0; i < hdpa->nItemCount; i++) {
1676 if (hdpa->ptrs[i] == p)
1677 return i;
1678 }
1679
1680 return -1;
1681}
1682
1683
1684/**************************************************************************
1685 * DPA_InsertPtr [COMCTL32.334]
1686 *
1687 * Inserts a pointer into a dynamic pointer array
1688 *
1689 * PARAMS
1690 * hdpa [I] handle (pointer) to the array
1691 * i [I] array index
1692 * p [I] pointer to insert
1693 *
1694 * RETURNS
1695 * Success: index of the inserted pointer
1696 * Failure: -1
1697 */
1698
Alexandre Julliarda3960291999-02-26 11:11:13 +00001699INT WINAPI
1700DPA_InsertPtr (const HDPA hdpa, INT i, LPVOID p)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001701{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001702 INT nNewItems, nSize, nIndex = 0;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001703 LPVOID *lpTemp, *lpDest;
1704
Alexandre Julliarda099a551999-06-12 15:45:58 +00001705 TRACE("(%p %d %p)\n", hdpa, i, p);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001706
1707 if ((!hdpa) || (i < 0))
1708 return -1;
1709
1710 if (!hdpa->ptrs) {
1711 hdpa->ptrs =
1712 (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
Eric Kohl17216d31998-10-11 13:21:17 +00001713 2 * hdpa->nGrow * sizeof(LPVOID));
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001714 if (!hdpa->ptrs)
1715 return -1;
Eric Kohl17216d31998-10-11 13:21:17 +00001716 hdpa->nMaxCount = hdpa->nGrow * 2;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001717 nIndex = 0;
1718 }
1719 else {
Eric Kohl17216d31998-10-11 13:21:17 +00001720 if (hdpa->nItemCount >= hdpa->nMaxCount) {
Alexandre Julliarda099a551999-06-12 15:45:58 +00001721 TRACE("-- resizing\n");
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001722 nNewItems = hdpa->nMaxCount + hdpa->nGrow;
1723 nSize = nNewItems * sizeof(LPVOID);
1724
1725 lpTemp = (LPVOID*)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1726 hdpa->ptrs, nSize);
1727 if (!lpTemp)
1728 return -1;
1729 hdpa->nMaxCount = nNewItems;
1730 hdpa->ptrs = lpTemp;
1731 }
1732
1733 if (i >= hdpa->nItemCount) {
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001734 nIndex = hdpa->nItemCount;
Alexandre Julliarda099a551999-06-12 15:45:58 +00001735 TRACE("-- appending at %d\n", nIndex);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001736 }
1737 else {
Alexandre Julliarda099a551999-06-12 15:45:58 +00001738 TRACE("-- inserting at %d\n", i);
Eric Kohl65016631999-01-24 19:09:56 +00001739 lpTemp = hdpa->ptrs + i;
1740 lpDest = lpTemp + 1;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001741 nSize = (hdpa->nItemCount - i) * sizeof(LPVOID);
Alexandre Julliarda099a551999-06-12 15:45:58 +00001742 TRACE("-- move dest=%p src=%p size=%x\n",
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001743 lpDest, lpTemp, nSize);
1744 memmove (lpDest, lpTemp, nSize);
1745 nIndex = i;
1746 }
1747 }
1748
1749 /* insert item */
1750 hdpa->nItemCount++;
1751 hdpa->ptrs[nIndex] = p;
1752
1753 return nIndex;
1754}
1755
1756
1757/**************************************************************************
1758 * DPA_SetPtr [COMCTL32.335]
1759 *
1760 * Sets a pointer in the pointer array
1761 *
1762 * PARAMS
1763 * hdpa [I] handle (pointer) to the pointer array
1764 * i [I] index of the pointer that will be set
1765 * p [I] pointer to be set
1766 *
1767 * RETURNS
1768 * Success: TRUE
1769 * Failure: FALSE
1770 */
1771
Alexandre Julliarda3960291999-02-26 11:11:13 +00001772BOOL WINAPI
1773DPA_SetPtr (const HDPA hdpa, INT i, LPVOID p)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001774{
1775 LPVOID *lpTemp;
1776
Alexandre Julliarda099a551999-06-12 15:45:58 +00001777 TRACE("(%p %d %p)\n", hdpa, i, p);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001778
1779 if ((!hdpa) || i < 0)
1780 return FALSE;
1781
1782 if (hdpa->nItemCount <= i) {
1783 /* within the old array */
1784 if (hdpa->nMaxCount > i) {
1785 /* within the allocated space, set a new boundary */
Marcus Meissnerddedfa22000-11-04 02:56:38 +00001786 hdpa->nItemCount = i+1;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001787 }
1788 else {
1789 /* resize the block of memory */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001790 INT nNewItems =
Eric Pouech200f89211999-09-13 15:11:02 +00001791 hdpa->nGrow * ((INT)(((i+1) - 1) / hdpa->nGrow) + 1);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001792 INT nSize = nNewItems * sizeof(LPVOID);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001793
1794 lpTemp = (LPVOID*)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1795 hdpa->ptrs, nSize);
1796 if (!lpTemp)
1797 return FALSE;
1798
1799 hdpa->nItemCount = nNewItems;
1800 hdpa->ptrs = lpTemp;
1801 }
1802 }
1803
1804 /* put the new entry in */
1805 hdpa->ptrs[i] = p;
1806
1807 return TRUE;
1808}
1809
1810
1811/**************************************************************************
1812 * DPA_DeletePtr [COMCTL32.336]
1813 *
1814 * Removes a pointer from the pointer array.
1815 *
1816 * PARAMS
1817 * hdpa [I] handle (pointer) to the pointer array
1818 * i [I] index of the pointer that will be deleted
1819 *
1820 * RETURNS
1821 * Success: deleted pointer
1822 * Failure: NULL
1823 */
1824
1825LPVOID WINAPI
Alexandre Julliarda3960291999-02-26 11:11:13 +00001826DPA_DeletePtr (const HDPA hdpa, INT i)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001827{
Eric Kohla0a516d1999-02-02 10:33:08 +00001828 LPVOID *lpDest, *lpSrc, lpTemp = NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001829 INT nSize;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001830
Alexandre Julliarda099a551999-06-12 15:45:58 +00001831 TRACE("(%p %d)\n", hdpa, i);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001832
1833 if ((!hdpa) || i < 0 || i >= hdpa->nItemCount)
1834 return NULL;
1835
1836 lpTemp = hdpa->ptrs[i];
1837
1838 /* do we need to move ?*/
1839 if (i < hdpa->nItemCount - 1) {
Eric Kohl65016631999-01-24 19:09:56 +00001840 lpDest = hdpa->ptrs + i;
1841 lpSrc = lpDest + 1;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001842 nSize = (hdpa->nItemCount - i - 1) * sizeof(LPVOID);
Alexandre Julliarda099a551999-06-12 15:45:58 +00001843 TRACE("-- move dest=%p src=%p size=%x\n",
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001844 lpDest, lpSrc, nSize);
1845 memmove (lpDest, lpSrc, nSize);
1846 }
1847
1848 hdpa->nItemCount --;
1849
1850 /* free memory ?*/
1851 if ((hdpa->nMaxCount - hdpa->nItemCount) >= hdpa->nGrow) {
Francois Gouget6d77d3a2000-03-25 21:44:35 +00001852 INT nNewItems = max(hdpa->nGrow * 2, hdpa->nItemCount);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001853 nSize = nNewItems * sizeof(LPVOID);
1854 lpDest = (LPVOID)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1855 hdpa->ptrs, nSize);
1856 if (!lpDest)
1857 return NULL;
1858
1859 hdpa->nMaxCount = nNewItems;
1860 hdpa->ptrs = (LPVOID*)lpDest;
1861 }
1862
1863 return lpTemp;
1864}
1865
1866
1867/**************************************************************************
1868 * DPA_DeleteAllPtrs [COMCTL32.337]
1869 *
1870 * Removes all pointers and reinitializes the array.
1871 *
1872 * PARAMS
1873 * hdpa [I] handle (pointer) to the pointer array
1874 *
1875 * RETURNS
1876 * Success: TRUE
1877 * Failure: FALSE
1878 */
1879
Alexandre Julliarda3960291999-02-26 11:11:13 +00001880BOOL WINAPI
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001881DPA_DeleteAllPtrs (const HDPA hdpa)
1882{
Alexandre Julliarda099a551999-06-12 15:45:58 +00001883 TRACE("(%p)\n", hdpa);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001884
1885 if (!hdpa)
1886 return FALSE;
1887
1888 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
1889 return FALSE;
1890
1891 hdpa->nItemCount = 0;
1892 hdpa->nMaxCount = hdpa->nGrow * 2;
1893 hdpa->ptrs = (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1894 hdpa->nMaxCount * sizeof(LPVOID));
1895
1896 return TRUE;
1897}
1898
1899
1900/**************************************************************************
1901 * DPA_QuickSort [Internal]
1902 *
Eric Kohl17216d31998-10-11 13:21:17 +00001903 * Ordinary quicksort (used by DPA_Sort).
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001904 *
1905 * PARAMS
1906 * lpPtrs [I] pointer to the pointer array
1907 * l [I] index of the "left border" of the partition
1908 * r [I] index of the "right border" of the partition
1909 * pfnCompare [I] pointer to the compare function
1910 * lParam [I] user defined value (3rd parameter in compare function)
1911 *
1912 * RETURNS
1913 * NONE
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001914 */
1915
1916static VOID
Alexandre Julliarda3960291999-02-26 11:11:13 +00001917DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r,
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001918 PFNDPACOMPARE pfnCompare, LPARAM lParam)
1919{
Mike McCormackf97b5432000-09-04 20:19:07 +00001920 INT m;
1921 LPVOID t;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001922
Alexandre Julliarda099a551999-06-12 15:45:58 +00001923 TRACE("l=%i r=%i\n", l, r);
Eric Kohl17216d31998-10-11 13:21:17 +00001924
Mike McCormackf97b5432000-09-04 20:19:07 +00001925 if (l==r) /* one element is always sorted */
1926 return;
1927 if (r<l) /* oops, got it in the wrong order */
Eric Kohl17216d31998-10-11 13:21:17 +00001928 {
Mike McCormackf97b5432000-09-04 20:19:07 +00001929 DPA_QuickSort(lpPtrs, r, l, pfnCompare, lParam);
1930 return;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001931 }
Mike McCormackf97b5432000-09-04 20:19:07 +00001932 m = (l+r)/2; /* divide by two */
1933 DPA_QuickSort(lpPtrs, l, m, pfnCompare, lParam);
1934 DPA_QuickSort(lpPtrs, m+1, r, pfnCompare, lParam);
1935
1936 /* join the two sides */
1937 while( (l<=m) && (m<r) )
1938 {
1939 if(pfnCompare(lpPtrs[l],lpPtrs[m+1],lParam)>0)
1940 {
1941 t = lpPtrs[m+1];
Mike McCormack4f2300a2000-09-06 19:43:38 +00001942 memmove(&lpPtrs[l+1],&lpPtrs[l],(m-l+1)*sizeof lpPtrs[l]);
Mike McCormackf97b5432000-09-04 20:19:07 +00001943 lpPtrs[l] = t;
1944
1945 m++;
1946 }
1947 l++;
1948 }
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001949}
1950
1951
1952/**************************************************************************
1953 * DPA_Sort [COMCTL32.338]
1954 *
1955 * Sorts a pointer array using a user defined compare function
1956 *
1957 * PARAMS
1958 * hdpa [I] handle (pointer) to the pointer array
1959 * pfnCompare [I] pointer to the compare function
1960 * lParam [I] user defined value (3rd parameter of compare function)
1961 *
1962 * RETURNS
1963 * Success: TRUE
1964 * Failure: FALSE
1965 */
1966
Alexandre Julliarda3960291999-02-26 11:11:13 +00001967BOOL WINAPI
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001968DPA_Sort (const HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam)
1969{
1970 if (!hdpa || !pfnCompare)
1971 return FALSE;
1972
Alexandre Julliarda099a551999-06-12 15:45:58 +00001973 TRACE("(%p %p 0x%lx)\n", hdpa, pfnCompare, lParam);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001974
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001975 if ((hdpa->nItemCount > 1) && (hdpa->ptrs))
1976 DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1,
1977 pfnCompare, lParam);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001978
1979 return TRUE;
1980}
1981
1982
1983/**************************************************************************
1984 * DPA_Search [COMCTL32.339]
1985 *
1986 * Searches a pointer array for a specified pointer
1987 *
1988 * PARAMS
1989 * hdpa [I] handle (pointer) to the pointer array
1990 * pFind [I] pointer to search for
1991 * nStart [I] start index
1992 * pfnCompare [I] pointer to the compare function
1993 * lParam [I] user defined value (3rd parameter of compare function)
1994 * uOptions [I] search options
1995 *
1996 * RETURNS
1997 * Success: index of the pointer in the array.
1998 * Failure: -1
1999 *
2000 * NOTES
2001 * Binary search taken from R.Sedgewick "Algorithms in C"!
Eric Kohl17216d31998-10-11 13:21:17 +00002002 * Function is NOT tested!
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002003 * If something goes wrong, blame HIM not ME! (Eric Kohl)
2004 */
2005
Alexandre Julliarda3960291999-02-26 11:11:13 +00002006INT WINAPI
2007DPA_Search (const HDPA hdpa, LPVOID pFind, INT nStart,
2008 PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002009{
2010 if (!hdpa || !pfnCompare || !pFind)
2011 return -1;
2012
Alexandre Julliarda099a551999-06-12 15:45:58 +00002013 TRACE("(%p %p %d %p 0x%08lx 0x%08x)\n",
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002014 hdpa, pFind, nStart, pfnCompare, lParam, uOptions);
2015
2016 if (uOptions & DPAS_SORTED) {
2017 /* array is sorted --> use binary search */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002018 INT l, r, x, n;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002019 LPVOID *lpPtr;
2020
Alexandre Julliarda099a551999-06-12 15:45:58 +00002021 TRACE("binary search\n");
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002022
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002023 l = (nStart == -1) ? 0 : nStart;
2024 r = hdpa->nItemCount - 1;
2025 lpPtr = hdpa->ptrs;
2026 while (r >= l) {
2027 x = (l + r) / 2;
2028 n = (pfnCompare)(pFind, lpPtr[x], lParam);
2029 if (n < 0)
2030 r = x - 1;
2031 else
2032 l = x + 1;
2033 if (n == 0) {
Alexandre Julliarda099a551999-06-12 15:45:58 +00002034 TRACE("-- ret=%d\n", n);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002035 return n;
2036 }
2037 }
2038
2039 if (uOptions & DPAS_INSERTBEFORE) {
Alexandre Julliarda099a551999-06-12 15:45:58 +00002040 TRACE("-- ret=%d\n", r);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002041 return r;
2042 }
2043
2044 if (uOptions & DPAS_INSERTAFTER) {
Alexandre Julliarda099a551999-06-12 15:45:58 +00002045 TRACE("-- ret=%d\n", l);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002046 return l;
2047 }
2048 }
2049 else {
2050 /* array is not sorted --> use linear search */
2051 LPVOID *lpPtr;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002052 INT nIndex;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002053
Alexandre Julliarda099a551999-06-12 15:45:58 +00002054 TRACE("linear search\n");
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002055
2056 nIndex = (nStart == -1)? 0 : nStart;
2057 lpPtr = hdpa->ptrs;
2058 for (; nIndex < hdpa->nItemCount; nIndex++) {
2059 if ((pfnCompare)(pFind, lpPtr[nIndex], lParam) == 0) {
Alexandre Julliarda099a551999-06-12 15:45:58 +00002060 TRACE("-- ret=%d\n", nIndex);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002061 return nIndex;
2062 }
2063 }
2064 }
2065
Alexandre Julliarda099a551999-06-12 15:45:58 +00002066 TRACE("-- not found: ret=-1\n");
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002067 return -1;
2068}
2069
2070
2071/**************************************************************************
2072 * DPA_CreateEx [COMCTL32.340]
2073 *
2074 * Creates a dynamic pointer array using the specified size and heap.
2075 *
2076 * PARAMS
2077 * nGrow [I] number of items by which the array grows when it is filled
2078 * hHeap [I] handle to the heap where the array is stored
2079 *
2080 * RETURNS
2081 * Success: handle (pointer) to the pointer array.
2082 * Failure: NULL
2083 */
2084
2085HDPA WINAPI
Alexandre Julliarda3960291999-02-26 11:11:13 +00002086DPA_CreateEx (INT nGrow, HANDLE hHeap)
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002087{
2088 HDPA hdpa;
2089
Alexandre Julliarda099a551999-06-12 15:45:58 +00002090 TRACE("(%d 0x%x)\n", nGrow, hHeap);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002091
2092 if (hHeap)
2093 hdpa = (HDPA)HeapAlloc (hHeap, HEAP_ZERO_MEMORY, sizeof(DPA));
2094 else
2095 hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
2096
2097 if (hdpa) {
Francois Gouget6d77d3a2000-03-25 21:44:35 +00002098 hdpa->nGrow = min(8, nGrow);
Eric Kohl17216d31998-10-11 13:21:17 +00002099 hdpa->hHeap = hHeap ? hHeap : COMCTL32_hHeap;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002100 hdpa->nMaxCount = hdpa->nGrow * 2;
2101 hdpa->ptrs =
2102 (LPVOID*)HeapAlloc (hHeap, HEAP_ZERO_MEMORY,
2103 hdpa->nMaxCount * sizeof(LPVOID));
2104 }
2105
Alexandre Julliarda099a551999-06-12 15:45:58 +00002106 TRACE("-- %p\n", hdpa);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002107
2108 return hdpa;
2109}
2110
2111
2112/**************************************************************************
Eric Kohl17216d31998-10-11 13:21:17 +00002113 * Notification functions
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002114 */
2115
Eric Kohl17216d31998-10-11 13:21:17 +00002116typedef struct tagNOTIFYDATA
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002117{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002118 HWND hwndFrom;
2119 HWND hwndTo;
Eric Kohl17216d31998-10-11 13:21:17 +00002120 DWORD dwParam3;
2121 DWORD dwParam4;
2122 DWORD dwParam5;
2123 DWORD dwParam6;
2124} NOTIFYDATA, *LPNOTIFYDATA;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002125
Eric Kohl17216d31998-10-11 13:21:17 +00002126
2127/**************************************************************************
2128 * DoNotify [Internal]
2129 */
2130
2131static LRESULT
Alexandre Julliarda3960291999-02-26 11:11:13 +00002132DoNotify (LPNOTIFYDATA lpNotify, UINT uCode, LPNMHDR lpHdr)
Eric Kohl17216d31998-10-11 13:21:17 +00002133{
2134 NMHDR nmhdr;
2135 LPNMHDR lpNmh = NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002136 UINT idFrom = 0;
Eric Kohl17216d31998-10-11 13:21:17 +00002137
Alexandre Julliarda099a551999-06-12 15:45:58 +00002138 TRACE("(0x%04x 0x%04x %d %p 0x%08lx)\n",
Eric Kohl17216d31998-10-11 13:21:17 +00002139 lpNotify->hwndFrom, lpNotify->hwndTo, uCode, lpHdr,
2140 lpNotify->dwParam5);
2141
2142 if (!lpNotify->hwndTo)
2143 return 0;
2144
2145 if (lpNotify->hwndFrom == -1) {
2146 lpNmh = lpHdr;
2147 idFrom = lpHdr->idFrom;
2148 }
2149 else {
2150 if (lpNotify->hwndFrom) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002151 HWND hwndParent = GetParent (lpNotify->hwndFrom);
Eric Kohl17216d31998-10-11 13:21:17 +00002152 if (hwndParent) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002153 hwndParent = GetWindow (lpNotify->hwndFrom, GW_OWNER);
Eric Kohl17216d31998-10-11 13:21:17 +00002154 if (hwndParent)
Alexandre Julliarda3960291999-02-26 11:11:13 +00002155 idFrom = GetDlgCtrlID (lpNotify->hwndFrom);
Eric Kohl17216d31998-10-11 13:21:17 +00002156 }
2157 }
2158
2159 lpNmh = (lpHdr) ? lpHdr : &nmhdr;
2160
2161 lpNmh->hwndFrom = lpNotify->hwndFrom;
2162 lpNmh->idFrom = idFrom;
2163 lpNmh->code = uCode;
2164 }
2165
Alexandre Julliarda3960291999-02-26 11:11:13 +00002166 return SendMessageA (lpNotify->hwndTo, WM_NOTIFY, idFrom, (LPARAM)lpNmh);
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002167}
2168
2169
Eric Kohl17216d31998-10-11 13:21:17 +00002170/**************************************************************************
2171 * SendNotify [COMCTL32.341]
2172 *
2173 * PARAMS
2174 * hwndFrom [I]
2175 * hwndTo [I]
2176 * uCode [I]
2177 * lpHdr [I]
2178 *
2179 * RETURNS
2180 * Success: return value from notification
2181 * Failure: 0
2182 */
2183
2184LRESULT WINAPI
Alexandre Julliarda3960291999-02-26 11:11:13 +00002185COMCTL32_SendNotify (HWND hwndFrom, HWND hwndTo,
2186 UINT uCode, LPNMHDR lpHdr)
Eric Kohl17216d31998-10-11 13:21:17 +00002187{
2188 NOTIFYDATA notify;
2189
Alexandre Julliarda099a551999-06-12 15:45:58 +00002190 TRACE("(0x%04x 0x%04x %d %p)\n",
Eric Kohl17216d31998-10-11 13:21:17 +00002191 hwndFrom, hwndTo, uCode, lpHdr);
2192
2193 notify.hwndFrom = hwndFrom;
2194 notify.hwndTo = hwndTo;
2195 notify.dwParam5 = 0;
2196 notify.dwParam6 = 0;
2197
2198 return DoNotify (&notify, uCode, lpHdr);
2199}
2200
2201
2202/**************************************************************************
2203 * SendNotifyEx [COMCTL32.342]
2204 *
2205 * PARAMS
2206 * hwndFrom [I]
2207 * hwndTo [I]
2208 * uCode [I]
2209 * lpHdr [I]
2210 * dwParam5 [I]
2211 *
2212 * RETURNS
2213 * Success: return value from notification
2214 * Failure: 0
2215 */
2216
2217LRESULT WINAPI
Alexandre Julliarda3960291999-02-26 11:11:13 +00002218COMCTL32_SendNotifyEx (HWND hwndTo, HWND hwndFrom, UINT uCode,
Eric Kohl17216d31998-10-11 13:21:17 +00002219 LPNMHDR lpHdr, DWORD dwParam5)
2220{
2221 NOTIFYDATA notify;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002222 HWND hwndNotify;
Eric Kohl17216d31998-10-11 13:21:17 +00002223
Alexandre Julliarda099a551999-06-12 15:45:58 +00002224 TRACE("(0x%04x 0x%04x %d %p 0x%08lx)\n",
Eric Kohl17216d31998-10-11 13:21:17 +00002225 hwndFrom, hwndTo, uCode, lpHdr, dwParam5);
2226
2227 hwndNotify = hwndTo;
2228 if (!hwndTo) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002229 if (IsWindow (hwndFrom)) {
2230 hwndNotify = GetParent (hwndFrom);
Eric Kohl17216d31998-10-11 13:21:17 +00002231 if (!hwndNotify)
2232 return 0;
2233 }
2234 }
2235
2236 notify.hwndFrom = hwndFrom;
2237 notify.hwndTo = hwndNotify;
2238 notify.dwParam5 = dwParam5;
2239 notify.dwParam6 = 0;
2240
2241 return DoNotify (&notify, uCode, lpHdr);
2242}
2243
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002244
2245/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002246 * StrChrA [COMCTL32.350]
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002247 *
2248 */
2249
2250LPSTR WINAPI
2251COMCTL32_StrChrA (LPCSTR lpString, CHAR cChar)
2252{
2253 return strchr (lpString, cChar);
2254}
2255
2256
2257/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002258 * StrStrIA [COMCTL32.355]
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002259 */
2260
2261LPSTR WINAPI
2262COMCTL32_StrStrIA (LPCSTR lpStr1, LPCSTR lpStr2)
2263{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002264 INT len1, len2, i;
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002265 CHAR first;
2266
2267 if (*lpStr2 == 0)
2268 return ((LPSTR)lpStr1);
2269 len1 = 0;
2270 while (lpStr1[len1] != 0) ++len1;
2271 len2 = 0;
2272 while (lpStr2[len2] != 0) ++len2;
2273 if (len2 == 0)
2274 return ((LPSTR)(lpStr1 + len1));
2275 first = tolower (*lpStr2);
2276 while (len1 >= len2) {
2277 if (tolower(*lpStr1) == first) {
2278 for (i = 1; i < len2; ++i)
2279 if (tolower (lpStr1[i]) != tolower(lpStr2[i]))
2280 break;
2281 if (i >= len2)
2282 return ((LPSTR)lpStr1);
2283 }
2284 ++lpStr1; --len1;
2285 }
2286 return (NULL);
2287}
2288
2289
2290/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002291 * StrToIntA [COMCTL32.357] Converts a string to a signed integer.
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002292 */
2293
Alexandre Julliarda3960291999-02-26 11:11:13 +00002294INT WINAPI
Alexandre Julliarda0d77311998-09-13 16:32:00 +00002295COMCTL32_StrToIntA (LPSTR lpString)
2296{
2297 return atoi(lpString);
2298}
2299
Chris Morgan87e4dbf2001-04-30 18:16:28 +00002300/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002301 * StrToIntW [COMCTL32.365] Converts a wide char string to a signed integer.
Chris Morgan87e4dbf2001-04-30 18:16:28 +00002302 */
2303
2304INT WINAPI
2305COMCTL32_StrToIntW (LPWSTR lpString)
2306{
2307 return _wtoi(lpString);
2308}
2309
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002310
2311/**************************************************************************
Eric Kohl0f7d5211998-11-22 17:54:40 +00002312 * DPA_EnumCallback [COMCTL32.385]
Eric Kohl17216d31998-10-11 13:21:17 +00002313 *
2314 * Enumerates all items in a dynamic pointer array.
2315 *
2316 * PARAMS
2317 * hdpa [I] handle to the dynamic pointer array
2318 * enumProc [I]
Eric Kohl0f7d5211998-11-22 17:54:40 +00002319 * lParam [I]
Eric Kohl17216d31998-10-11 13:21:17 +00002320 *
2321 * RETURNS
2322 * none
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002323 */
2324
Eric Kohl17216d31998-10-11 13:21:17 +00002325VOID WINAPI
Eric Kohl0f7d5211998-11-22 17:54:40 +00002326DPA_EnumCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002327{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002328 INT i;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002329
Alexandre Julliarda099a551999-06-12 15:45:58 +00002330 TRACE("(%p %p %08lx)\n", hdpa, enumProc, lParam);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002331
Eric Kohl17216d31998-10-11 13:21:17 +00002332 if (!hdpa)
2333 return;
2334 if (hdpa->nItemCount <= 0)
2335 return;
2336
2337 for (i = 0; i < hdpa->nItemCount; i++) {
Eric Kohl0f7d5211998-11-22 17:54:40 +00002338 if ((enumProc)(hdpa->ptrs[i], lParam) == 0)
Eric Kohl17216d31998-10-11 13:21:17 +00002339 return;
2340 }
2341
2342 return;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002343}
2344
2345
2346/**************************************************************************
Eric Kohl0f7d5211998-11-22 17:54:40 +00002347 * DPA_DestroyCallback [COMCTL32.386]
Eric Kohl17216d31998-10-11 13:21:17 +00002348 *
2349 * Enumerates all items in a dynamic pointer array and destroys it.
2350 *
2351 * PARAMS
2352 * hdpa [I] handle to the dynamic pointer array
2353 * enumProc [I]
Eric Kohl0f7d5211998-11-22 17:54:40 +00002354 * lParam [I]
Eric Kohl17216d31998-10-11 13:21:17 +00002355 *
2356 * RETURNS
2357 * Success: TRUE
2358 * Failure: FALSE
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002359 */
2360
Alexandre Julliarda3960291999-02-26 11:11:13 +00002361BOOL WINAPI
Eric Kohl0f7d5211998-11-22 17:54:40 +00002362DPA_DestroyCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002363{
Alexandre Julliarda099a551999-06-12 15:45:58 +00002364 TRACE("(%p %p %08lx)\n", hdpa, enumProc, lParam);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002365
Eric Kohl0f7d5211998-11-22 17:54:40 +00002366 DPA_EnumCallback (hdpa, enumProc, lParam);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002367
Eric Kohl17216d31998-10-11 13:21:17 +00002368 return DPA_Destroy (hdpa);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002369}
2370
2371
2372/**************************************************************************
Eric Kohl0f7d5211998-11-22 17:54:40 +00002373 * DSA_EnumCallback [COMCTL32.387]
Eric Kohl17216d31998-10-11 13:21:17 +00002374 *
2375 * Enumerates all items in a dynamic storage array.
2376 *
2377 * PARAMS
2378 * hdsa [I] handle to the dynamic storage array
2379 * enumProc [I]
Eric Kohl0f7d5211998-11-22 17:54:40 +00002380 * lParam [I]
Eric Kohl17216d31998-10-11 13:21:17 +00002381 *
2382 * RETURNS
2383 * none
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002384 */
2385
Eric Kohl17216d31998-10-11 13:21:17 +00002386VOID WINAPI
Eric Kohl0f7d5211998-11-22 17:54:40 +00002387DSA_EnumCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002388{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002389 INT i;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002390
Alexandre Julliarda099a551999-06-12 15:45:58 +00002391 TRACE("(%p %p %08lx)\n", hdsa, enumProc, lParam);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002392
Eric Kohl17216d31998-10-11 13:21:17 +00002393 if (!hdsa)
2394 return;
2395 if (hdsa->nItemCount <= 0)
2396 return;
2397
2398 for (i = 0; i < hdsa->nItemCount; i++) {
2399 LPVOID lpItem = DSA_GetItemPtr (hdsa, i);
Eric Kohl0f7d5211998-11-22 17:54:40 +00002400 if ((enumProc)(lpItem, lParam) == 0)
Eric Kohl17216d31998-10-11 13:21:17 +00002401 return;
2402 }
2403
2404 return;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002405}
2406
2407
2408/**************************************************************************
Eric Kohl0f7d5211998-11-22 17:54:40 +00002409 * DSA_DestroyCallback [COMCTL32.388]
Eric Kohl17216d31998-10-11 13:21:17 +00002410 *
2411 * Enumerates all items in a dynamic storage array and destroys it.
2412 *
2413 * PARAMS
2414 * hdsa [I] handle to the dynamic storage array
2415 * enumProc [I]
Eric Kohl0f7d5211998-11-22 17:54:40 +00002416 * lParam [I]
Eric Kohl17216d31998-10-11 13:21:17 +00002417 *
2418 * RETURNS
2419 * Success: TRUE
2420 * Failure: FALSE
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002421 */
2422
Alexandre Julliarda3960291999-02-26 11:11:13 +00002423BOOL WINAPI
Eric Kohl0f7d5211998-11-22 17:54:40 +00002424DSA_DestroyCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002425{
Alexandre Julliarda099a551999-06-12 15:45:58 +00002426 TRACE("(%p %p %08lx)\n", hdsa, enumProc, lParam);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002427
Eric Kohl0f7d5211998-11-22 17:54:40 +00002428 DSA_EnumCallback (hdsa, enumProc, lParam);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002429
Eric Kohl17216d31998-10-11 13:21:17 +00002430 return DSA_Destroy (hdsa);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00002431}
2432
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002433/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002434 * StrCSpnA [COMCTL32.356]
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002435 *
2436 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002437INT WINAPI COMCTL32_StrCSpnA( LPCSTR lpStr, LPCSTR lpSet) {
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002438 return strcspn(lpStr, lpSet);
2439}
2440
2441/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002442 * StrChrW [COMCTL32.358]
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002443 *
2444 */
2445LPWSTR WINAPI COMCTL32_StrChrW( LPCWSTR lpStart, WORD wMatch) {
Alexandre Julliard5ea22472000-06-13 01:10:29 +00002446 return strchrW(lpStart, wMatch);
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002447}
2448
2449/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002450 * StrCmpNA [COMCTL32.352]
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002451 *
2452 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002453INT WINAPI COMCTL32_StrCmpNA( LPCSTR lpStr1, LPCSTR lpStr2, int nChar) {
Alexandre Julliard89f079b1999-08-08 18:54:47 +00002454 return strncmp(lpStr1, lpStr2, nChar);
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002455}
2456
2457/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002458 * StrCmpNIA [COMCTL32.353]
Uwe Bonnesbd638801999-09-04 11:04:45 +00002459 *
2460 */
2461INT WINAPI COMCTL32_StrCmpNIA( LPCSTR lpStr1, LPCSTR lpStr2, int nChar) {
2462 return strncasecmp(lpStr1, lpStr2, nChar);
2463}
2464
2465/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002466 * StrCmpNW [COMCTL32.360]
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002467 *
2468 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002469INT WINAPI COMCTL32_StrCmpNW( LPCWSTR lpStr1, LPCWSTR lpStr2, int nChar) {
Alexandre Julliard5ea22472000-06-13 01:10:29 +00002470 return strncmpW(lpStr1, lpStr2, nChar);
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002471}
2472
2473/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002474 * StrCmpNIW [COMCTL32.361]
Patrik Stridvalld7da4861999-10-24 21:35:16 +00002475 *
2476 */
2477INT WINAPI COMCTL32_StrCmpNIW( LPCWSTR lpStr1, LPCWSTR lpStr2, int nChar) {
2478 FIXME("(%s, %s, %i): stub\n", debugstr_w(lpStr1), debugstr_w(lpStr2), nChar);
2479 return 0;
2480}
2481
2482/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002483 * StrRChrA [COMCTL32.351]
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002484 *
2485 */
Alexandre Julliard3850c1a2000-08-06 02:42:46 +00002486LPSTR WINAPI COMCTL32_StrRChrA( LPCSTR lpStart, LPCSTR lpEnd, WORD wMatch )
2487{
2488 LPCSTR lpGotIt = NULL;
2489 BOOL dbcs = IsDBCSLeadByte( LOBYTE(wMatch) );
2490
2491 TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
2492
2493 if (!lpEnd) lpEnd = lpStart + strlen(lpStart);
2494
2495 for(; lpStart < lpEnd; lpStart = CharNextA(lpStart))
2496 {
2497 if (*lpStart != LOBYTE(wMatch)) continue;
2498 if (dbcs && lpStart[1] != HIBYTE(wMatch)) continue;
2499 lpGotIt = lpStart;
2500 }
2501 return (LPSTR)lpGotIt;
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002502}
2503
Alexandre Julliard3850c1a2000-08-06 02:42:46 +00002504
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002505/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002506 * StrRChrW [COMCTL32.359]
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002507 *
2508 */
Alexandre Julliard3850c1a2000-08-06 02:42:46 +00002509LPWSTR WINAPI COMCTL32_StrRChrW( LPCWSTR lpStart, LPCWSTR lpEnd, WORD wMatch)
2510{
2511 LPCWSTR lpGotIt = NULL;
2512
2513 TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
2514 if (!lpEnd) lpEnd = lpStart + strlenW(lpStart);
2515
2516 for(; lpStart < lpEnd; lpStart = CharNextW(lpStart))
2517 if (*lpStart == wMatch) lpGotIt = lpStart;
2518
2519 return (LPWSTR)lpGotIt;
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002520}
2521
Alexandre Julliard3850c1a2000-08-06 02:42:46 +00002522
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002523/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002524 * StrStrA [COMCTL32.354]
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002525 *
2526 */
2527LPSTR WINAPI COMCTL32_StrStrA( LPCSTR lpFirst, LPCSTR lpSrch) {
2528 return strstr(lpFirst, lpSrch);
2529}
2530
2531/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002532 * StrStrW [COMCTL32.362]
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002533 *
2534 */
2535LPWSTR WINAPI COMCTL32_StrStrW( LPCWSTR lpFirst, LPCWSTR lpSrch) {
Alexandre Julliard5ea22472000-06-13 01:10:29 +00002536 return strstrW(lpFirst, lpSrch);
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002537}
2538
2539/**************************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00002540 * StrSpnW [COMCTL32.364]
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002541 *
2542 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002543INT WINAPI COMCTL32_StrSpnW( LPWSTR lpStr, LPWSTR lpSet) {
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002544 LPWSTR lpLoop = lpStr;
2545
2546 /* validate ptr */
2547 if ((lpStr == 0) || (lpSet == 0)) return 0;
2548
2549/* while(*lpLoop) { if lpLoop++; } */
2550
2551 for(; (*lpLoop != 0); lpLoop++)
Alexandre Julliard5ea22472000-06-13 01:10:29 +00002552 if( strchrW(lpSet, *(WORD*)lpLoop))
Alexandre Julliarda3960291999-02-26 11:11:13 +00002553 return (INT)(lpLoop-lpStr);
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002554
Alexandre Julliarda3960291999-02-26 11:11:13 +00002555 return (INT)(lpLoop-lpStr);
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00002556}
Ian Schmidt45584801999-07-28 16:35:24 +00002557
2558/**************************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002559 * @ [COMCTL32.410]
Ian Schmidt45584801999-07-28 16:35:24 +00002560 *
2561 * FIXME: What's this supposed to do?
2562 * Parameter 1 is an HWND, you're on your own for the rest.
2563 */
2564
Patrik Stridvall54fe8382000-04-06 20:21:16 +00002565BOOL WINAPI COMCTL32_410( HWND hw, DWORD b, DWORD c, DWORD d) {
Ian Schmidt45584801999-07-28 16:35:24 +00002566
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00002567 FIXME("(%x, %lx, %lx, %lx): stub!\n", hw, b, c, d);
Ian Schmidt45584801999-07-28 16:35:24 +00002568
2569 return TRUE;
2570}
2571
Eric Kohl33910f171999-11-23 23:14:53 +00002572/**************************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002573 * @ [COMCTL32.411]
Eric Kohl33910f171999-11-23 23:14:53 +00002574 *
2575 * FIXME: What's this supposed to do?
2576 * Parameter 1 is an HWND, you're on your own for the rest.
2577 */
2578
Patrik Stridvall54fe8382000-04-06 20:21:16 +00002579BOOL WINAPI COMCTL32_411( HWND hw, DWORD b, DWORD c) {
Eric Kohl33910f171999-11-23 23:14:53 +00002580
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00002581 FIXME("(%x, %lx, %lx): stub!\n", hw, b, c);
Eric Kohl33910f171999-11-23 23:14:53 +00002582
2583 return TRUE;
2584}
2585
2586/**************************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002587 * @ [COMCTL32.412]
Eric Kohl33910f171999-11-23 23:14:53 +00002588 *
2589 * FIXME: What's this supposed to do?
2590 * Parameter 1 is an HWND, you're on your own for the rest.
2591 */
2592
Patrik Stridvall54fe8382000-04-06 20:21:16 +00002593BOOL WINAPI COMCTL32_412( HWND hwnd, DWORD b, DWORD c)
Eric Kohl33910f171999-11-23 23:14:53 +00002594{
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00002595 FIXME("(%x, %lx, %lx): stub!\n", hwnd, b, c);
Eric Kohl33910f171999-11-23 23:14:53 +00002596
2597 if (IsWindow (hwnd) == FALSE)
2598 return FALSE;
2599
2600 if (b == 0)
2601 return FALSE;
2602
2603
2604 return TRUE;
2605}
2606
2607/**************************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002608 * @ [COMCTL32.413]
Eric Kohl33910f171999-11-23 23:14:53 +00002609 *
2610 * FIXME: What's this supposed to do?
2611 * Parameter 1 is an HWND, you're on your own for the rest.
2612 */
2613
Patrik Stridvall54fe8382000-04-06 20:21:16 +00002614BOOL WINAPI COMCTL32_413( HWND hw, DWORD b, DWORD c, DWORD d) {
Eric Kohl33910f171999-11-23 23:14:53 +00002615
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00002616 FIXME("(%x, %lx, %lx, %lx): stub!\n", hw, b, c, d);
Eric Kohl33910f171999-11-23 23:14:53 +00002617
2618 return TRUE;
2619}
2620
Eric Kohlb3f681e2000-06-03 21:06:44 +00002621
2622/**************************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002623 * @ [COMCTL32.415]
Ian Schmidt45584801999-07-28 16:35:24 +00002624 *
Eric Kohlb3f681e2000-06-03 21:06:44 +00002625 * FIXME: What's this supposed to do?
2626 * Parameter 1 is an HWND, you're on your own for the rest.
Ian Schmidt45584801999-07-28 16:35:24 +00002627 */
2628
Eric Kohlb3f681e2000-06-03 21:06:44 +00002629BOOL WINAPI COMCTL32_415( HWND hwnd, DWORD b, DWORD c, DWORD d, DWORD e)
2630{
Ian Schmidt45584801999-07-28 16:35:24 +00002631
Eric Kohlb3f681e2000-06-03 21:06:44 +00002632 FIXME("(%x, %lx, %lx, %lx, %lx): stub!\n", hwnd, b, c, d, e);
Ian Schmidt45584801999-07-28 16:35:24 +00002633
2634 return TRUE;
2635}