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

Last change on this file since 9370 was 9370, checked in by sandervl, 23 years ago

Wine resync

File size: 66.7 KB
Line 
1/*
2 * Undocumented functions from COMCTL32.DLL
3 *
4 * Copyright 1998 Eric Kohl
5 * 1998 Juergen Schmied <j.schmied@metronet.de>
6 * 2000 Eric Kohl for CodeWeavers
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 * NOTES
23 * All of these functions are UNDOCUMENTED!! And I mean UNDOCUMENTED!!!!
24 * Do NOT rely on names or contents of undocumented structures and types!!!
25 * These functions are used by EXPLORER.EXE, IEXPLORE.EXE and
26 * COMCTL32.DLL (internally).
27 *
28 * TODO
29 * - Add more functions.
30 * - Write some documentation.
31 */
32#ifdef __WIN32OS2__
33#define WINE_LARGE_INTEGER
34#endif
35
36#include <string.h>
37#include <stdlib.h> /* atoi */
38#include <ctype.h>
39#include <limits.h>
40
41#include "commctrl.h"
42#include "objbase.h"
43#include "winbase.h"
44#include "winerror.h"
45#include "winreg.h"
46
47#include "wine/unicode.h"
48#include "comctl32.h"
49
50#include "wine/debug.h"
51
52WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
53
54
55extern HANDLE COMCTL32_hHeap; /* handle to the private heap */
56
57
58typedef struct _STREAMDATA
59{
60 DWORD dwSize;
61 DWORD dwData2;
62 DWORD dwItems;
63} STREAMDATA, *PSTREAMDATA;
64
65typedef struct _LOADDATA
66{
67 INT nCount;
68 PVOID ptr;
69} LOADDATA, *LPLOADDATA;
70
71#ifdef __WIN32OS2__
72typedef HRESULT (* CALLBACK DPALOADPROC)(LPLOADDATA,IStream*,LPARAM);
73#else
74typedef HRESULT (CALLBACK *DPALOADPROC)(LPLOADDATA,IStream*,LPARAM);
75#endif
76
77/**************************************************************************
78 * DPA_LoadStream [COMCTL32.9]
79 *
80 * Loads a dynamic pointer array from a stream
81 *
82 * PARAMS
83 * phDpa [O] pointer to a handle to a dynamic pointer array
84 * loadProc [I] pointer to a callback function
85 * pStream [I] pointer to a stream
86 * lParam [I] application specific value
87 *
88 * NOTES
89 * No more information available yet!
90 */
91
92HRESULT WINAPI
93DPA_LoadStream (HDPA *phDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lParam)
94{
95 HRESULT errCode;
96 LARGE_INTEGER position;
97 ULARGE_INTEGER newPosition;
98 STREAMDATA streamData;
99 LOADDATA loadData;
100 ULONG ulRead;
101 HDPA hDpa;
102 PVOID *ptr;
103
104 FIXME ("phDpa=%p loadProc=%p pStream=%p lParam=%lx\n",
105 phDpa, loadProc, pStream, lParam);
106
107 if (!phDpa || !loadProc || !pStream)
108 return E_INVALIDARG;
109
110 *phDpa = (HDPA)NULL;
111
112 position.s.LowPart = 0;
113 position.s.HighPart = 0;
114
115 /*
116 * Zero out our streamData
117 */
118 memset(&streamData,0,sizeof(STREAMDATA));
119
120 errCode = IStream_Seek (pStream, position, STREAM_SEEK_CUR, &newPosition);
121 if (errCode != S_OK)
122 return errCode;
123
124 errCode = IStream_Read (pStream, &streamData, sizeof(STREAMDATA), &ulRead);
125 if (errCode != S_OK)
126 return errCode;
127
128 FIXME ("dwSize=%lu dwData2=%lu dwItems=%lu\n",
129 streamData.dwSize, streamData.dwData2, streamData.dwItems);
130
131 if ( ulRead < sizeof(STREAMDATA) ||
132 lParam < sizeof(STREAMDATA) ||
133 streamData.dwSize < sizeof(STREAMDATA) ||
134 streamData.dwData2 < 1) {
135 errCode = E_FAIL;
136 }
137
138 if (streamData.dwItems > (UINT_MAX / 2 / sizeof(VOID*))) /* 536870911 */
139 return E_OUTOFMEMORY;
140
141 /* create the dpa */
142 hDpa = DPA_Create (streamData.dwItems);
143 if (!hDpa)
144 return E_OUTOFMEMORY;
145
146 if (!DPA_Grow (hDpa, streamData.dwItems))
147 return E_OUTOFMEMORY;
148
149 /* load data from the stream into the dpa */
150 ptr = hDpa->ptrs;
151 for (loadData.nCount = 0; loadData.nCount < streamData.dwItems; loadData.nCount++) {
152 errCode = (loadProc)(&loadData, pStream, lParam);
153 if (errCode != S_OK) {
154 errCode = S_FALSE;
155 break;
156 }
157
158 *ptr = loadData.ptr;
159 ptr++;
160 }
161
162 /* set the number of items */
163 hDpa->nItemCount = loadData.nCount;
164
165 /* store the handle to the dpa */
166 *phDpa = hDpa;
167 FIXME ("new hDpa=%p\n", hDpa);
168
169 return errCode;
170}
171
172
173/**************************************************************************
174 * DPA_SaveStream [COMCTL32.10]
175 *
176 * Saves a dynamic pointer array to a stream
177 *
178 * PARAMS
179 * hDpa [I] handle to a dynamic pointer array
180 * loadProc [I] pointer to a callback function
181 * pStream [I] pointer to a stream
182 * lParam [I] application specific value
183 *
184 * NOTES
185 * No more information available yet!
186 */
187
188HRESULT WINAPI
189DPA_SaveStream (const HDPA hDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lParam)
190{
191
192 FIXME ("hDpa=%p loadProc=%p pStream=%p lParam=%lx\n",
193 hDpa, loadProc, pStream, lParam);
194
195 return E_FAIL;
196}
197
198
199/**************************************************************************
200 * DPA_Merge [COMCTL32.11]
201 *
202 * PARAMS
203 * hdpa1 [I] handle to a dynamic pointer array
204 * hdpa2 [I] handle to a dynamic pointer array
205 * dwFlags [I] flags
206 * pfnCompare [I] pointer to sort function
207 * pfnMerge [I] pointer to merge function
208 * lParam [I] application specific value
209 *
210 * NOTES
211 * No more information available yet!
212 */
213
214BOOL WINAPI
215DPA_Merge (const HDPA hdpa1, const HDPA hdpa2, DWORD dwFlags,
216 PFNDPACOMPARE pfnCompare, PFNDPAMERGE pfnMerge, LPARAM lParam)
217{
218 INT nCount;
219 LPVOID *pWork1, *pWork2;
220 INT nResult, i;
221 INT nIndex;
222
223 TRACE("%p %p %08lx %p %p %08lx)\n",
224 hdpa1, hdpa2, dwFlags, pfnCompare, pfnMerge, lParam);
225
226 if (IsBadWritePtr (hdpa1, sizeof(DPA)))
227 return FALSE;
228
229 if (IsBadWritePtr (hdpa2, sizeof(DPA)))
230 return FALSE;
231
232 if (IsBadCodePtr ((FARPROC)pfnCompare))
233 return FALSE;
234
235 if (IsBadCodePtr ((FARPROC)pfnMerge))
236 return FALSE;
237
238 if (!(dwFlags & DPAM_NOSORT)) {
239 TRACE("sorting dpa's!\n");
240 if (hdpa1->nItemCount > 0)
241 DPA_Sort (hdpa1, pfnCompare, lParam);
242 TRACE ("dpa 1 sorted!\n");
243 if (hdpa2->nItemCount > 0)
244 DPA_Sort (hdpa2, pfnCompare, lParam);
245 TRACE ("dpa 2 sorted!\n");
246 }
247
248 if (hdpa2->nItemCount < 1)
249 return TRUE;
250
251 TRACE("hdpa1->nItemCount=%d hdpa2->nItemCount=%d\n",
252 hdpa1->nItemCount, hdpa2->nItemCount);
253
254
255 /* working but untrusted implementation */
256
257 pWork1 = &(hdpa1->ptrs[hdpa1->nItemCount - 1]);
258 pWork2 = &(hdpa2->ptrs[hdpa2->nItemCount - 1]);
259
260 nIndex = hdpa1->nItemCount - 1;
261 nCount = hdpa2->nItemCount - 1;
262
263 do
264 {
265 if (nIndex < 0) {
266 if ((nCount >= 0) && (dwFlags & DPAM_INSERT)) {
267 /* Now insert the remaining new items into DPA 1 */
268 TRACE("%d items to be inserted at start of DPA 1\n",
269 nCount+1);
270 for (i=nCount; i>=0; i--) {
271 PVOID ptr;
272
273 ptr = (pfnMerge)(3, *pWork2, NULL, lParam);
274 if (!ptr)
275 return FALSE;
276 DPA_InsertPtr (hdpa1, 0, ptr);
277 pWork2--;
278 }
279 }
280 break;
281 }
282 nResult = (pfnCompare)(*pWork1, *pWork2, lParam);
283 TRACE("compare result=%d, dpa1.cnt=%d, dpa2.cnt=%d\n",
284 nResult, nIndex, nCount);
285
286 if (nResult == 0)
287 {
288 PVOID ptr;
289
290 ptr = (pfnMerge)(1, *pWork1, *pWork2, lParam);
291 if (!ptr)
292 return FALSE;
293
294 nCount--;
295 pWork2--;
296 *pWork1 = ptr;
297 nIndex--;
298 pWork1--;
299 }
300 else if (nResult > 0)
301 {
302 /* item in DPA 1 missing from DPA 2 */
303 if (dwFlags & DPAM_DELETE)
304 {
305 /* Now delete the extra item in DPA1 */
306 PVOID ptr;
307
308 ptr = DPA_DeletePtr (hdpa1, hdpa1->nItemCount - 1);
309
310 (pfnMerge)(2, ptr, NULL, lParam);
311 }
312 nIndex--;
313 pWork1--;
314 }
315 else
316 {
317 /* new item in DPA 2 */
318 if (dwFlags & DPAM_INSERT)
319 {
320 /* Now insert the new item in DPA 1 */
321 PVOID ptr;
322
323 ptr = (pfnMerge)(3, *pWork2, NULL, lParam);
324 if (!ptr)
325 return FALSE;
326 DPA_InsertPtr (hdpa1, nIndex+1, ptr);
327 }
328 nCount--;
329 pWork2--;
330 }
331
332 }
333 while (nCount >= 0);
334
335 return TRUE;
336}
337
338
339/**************************************************************************
340 * Alloc [COMCTL32.71]
341 *
342 * Allocates memory block from the dll's private heap
343 *
344 * PARAMS
345 * dwSize [I] size of the allocated memory block
346 *
347 * RETURNS
348 * Success: pointer to allocated memory block
349 * Failure: NULL
350 */
351
352LPVOID WINAPI
353COMCTL32_Alloc (DWORD dwSize)
354{
355 LPVOID lpPtr;
356
357 TRACE("(0x%lx)\n", dwSize);
358
359 lpPtr = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
360
361 TRACE("-- ret=%p\n", lpPtr);
362
363 return lpPtr;
364}
365
366
367/**************************************************************************
368 * ReAlloc [COMCTL32.72]
369 *
370 * Changes the size of an allocated memory block or allocates a memory
371 * block using the dll's private heap.
372 *
373 * PARAMS
374 * lpSrc [I] pointer to memory block which will be resized
375 * dwSize [I] new size of the memory block.
376 *
377 * RETURNS
378 * Success: pointer to the resized memory block
379 * Failure: NULL
380 *
381 * NOTES
382 * If lpSrc is a NULL-pointer, then COMCTL32_ReAlloc allocates a memory
383 * block like COMCTL32_Alloc.
384 */
385
386LPVOID WINAPI
387COMCTL32_ReAlloc (LPVOID lpSrc, DWORD dwSize)
388{
389 LPVOID lpDest;
390
391 TRACE("(%p 0x%08lx)\n", lpSrc, dwSize);
392
393 if (lpSrc)
394 lpDest = HeapReAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, lpSrc, dwSize);
395 else
396 lpDest = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
397
398 TRACE("-- ret=%p\n", lpDest);
399
400 return lpDest;
401}
402
403
404/**************************************************************************
405 * Free [COMCTL32.73]
406 *
407 * Frees an allocated memory block from the dll's private heap.
408 *
409 * PARAMS
410 * lpMem [I] pointer to memory block which will be freed
411 *
412 * RETURNS
413 * Success: TRUE
414 * Failure: FALSE
415 */
416
417BOOL WINAPI
418COMCTL32_Free (LPVOID lpMem)
419{
420 TRACE("(%p)\n", lpMem);
421
422 return HeapFree (COMCTL32_hHeap, 0, lpMem);
423}
424
425
426/**************************************************************************
427 * GetSize [COMCTL32.74]
428 *
429 * Retrieves the size of the specified memory block from the dll's
430 * private heap.
431 *
432 * PARAMS
433 * lpMem [I] pointer to an allocated memory block
434 *
435 * RETURNS
436 * Success: size of the specified memory block
437 * Failure: 0
438 */
439
440DWORD WINAPI
441COMCTL32_GetSize (LPVOID lpMem)
442{
443 TRACE("(%p)\n", lpMem);
444
445 return HeapSize (COMCTL32_hHeap, 0, lpMem);
446}
447
448
449/**************************************************************************
450 * The MRU-API is a set of functions to manipulate MRU(Most Recently Used)
451 * lists.
452 *
453 * Stored in the reg. as a set of values under a single key. Each item in the
454 * list has a value name that is a single char. 'a' - 'z', '{', '|' or '}'.
455 * The order of the list is stored with value name 'MRUList' which is a string
456 * containing the value names (i.e. 'a', 'b', etc.) in the relevant order.
457 */
458
459typedef struct tagCREATEMRULISTA
460{
461 DWORD cbSize; /* size of struct */
462 DWORD nMaxItems; /* max no. of items in list */
463 DWORD dwFlags; /* see below */
464 HKEY hKey; /* root reg. key under which list is saved */
465 LPCSTR lpszSubKey; /* reg. subkey */
466 PROC lpfnCompare; /* item compare proc */
467} CREATEMRULISTA, *LPCREATEMRULISTA;
468
469typedef struct tagCREATEMRULISTW
470{
471 DWORD cbSize; /* size of struct */
472 DWORD nMaxItems; /* max no. of items in list */
473 DWORD dwFlags; /* see below */
474 HKEY hKey; /* root reg. key under which list is saved */
475 LPCWSTR lpszSubKey; /* reg. subkey */
476 PROC lpfnCompare; /* item compare proc */
477} CREATEMRULISTW, *LPCREATEMRULISTW;
478
479/* dwFlags */
480#define MRUF_STRING_LIST 0 /* list will contain strings */
481#define MRUF_BINARY_LIST 1 /* list will contain binary data */
482#define MRUF_DELAYED_SAVE 2 /* only save list order to reg. is FreeMRUList */
483
484/* If list is a string list lpfnCompare has the following prototype
485 * int CALLBACK MRUCompareString(LPCSTR s1, LPCSTR s2)
486 * for binary lists the prototype is
487 * int CALLBACK MRUCompareBinary(LPCVOID data1, LPCVOID data2, DWORD cbData)
488 * where cbData is the no. of bytes to compare.
489 * Need to check what return value means identical - 0?
490 */
491
492typedef struct tagWINEMRUITEM
493{
494 DWORD size; /* size of data stored */
495 DWORD itemFlag; /* flags */
496 BYTE datastart;
497} WINEMRUITEM, *LPWINEMRUITEM;
498
499/* itemFlag */
500#define WMRUIF_CHANGED 0x0001 /* this dataitem changed */
501
502typedef struct tagWINEMRULIST
503{
504 CREATEMRULISTW extview; /* original create information */
505 BOOL isUnicode; /* is compare fn Unicode */
506 DWORD wineFlags; /* internal flags */
507 DWORD cursize; /* current size of realMRU */
508 LPSTR realMRU; /* pointer to string of index names */
509 LPWINEMRUITEM *array; /* array of pointers to data */
510 /* in 'a' to 'z' order */
511} WINEMRULIST, *LPWINEMRULIST;
512
513/* wineFlags */
514#define WMRUF_CHANGED 0x0001 /* MRU list has changed */
515
516/**************************************************************************
517 * MRU_SaveChanged - Localize MRU saving code
518 *
519 */
520VOID MRU_SaveChanged( LPWINEMRULIST mp )
521{
522 INT i, err;
523 HKEY newkey;
524 WCHAR realname[2];
525 LPWINEMRUITEM witem;
526 WCHAR emptyW[] = {'\0'};
527
528 /* or should we do the following instead of RegOpenKeyEx:
529 */
530
531 /* open the sub key */
532 if ((err = RegOpenKeyExW( mp->extview.hKey, mp->extview.lpszSubKey,
533 0, KEY_WRITE, &newkey))) {
534 /* not present - what to do ??? */
535 ERR("Can not open key, error=%d, attempting to create\n",
536 err);
537 if ((err = RegCreateKeyExW( mp->extview.hKey, mp->extview.lpszSubKey,
538 0,
539 emptyW,
540 REG_OPTION_NON_VOLATILE,
541 KEY_READ | KEY_WRITE,
542 0,
543 &newkey,
544 0))) {
545 ERR("failed to create key /%s/, err=%d\n",
546 debugstr_w(mp->extview.lpszSubKey), err);
547 return;
548 }
549 }
550 if (mp->wineFlags & WMRUF_CHANGED) {
551 mp->wineFlags &= ~WMRUF_CHANGED;
552 err = RegSetValueExA(newkey, "MRUList", 0, REG_SZ,
553 mp->realMRU, strlen(mp->realMRU) + 1);
554 if (err) {
555 ERR("error saving MRUList, err=%d\n", err);
556 }
557 TRACE("saving MRUList=/%s/\n", mp->realMRU);
558 }
559 realname[1] = 0;
560 for(i=0; i<mp->cursize; i++) {
561 witem = mp->array[i];
562 if (witem->itemFlag & WMRUIF_CHANGED) {
563 witem->itemFlag &= ~WMRUIF_CHANGED;
564 realname[0] = 'a' + i;
565 err = RegSetValueExW(newkey, realname, 0,
566 (mp->extview.dwFlags & MRUF_BINARY_LIST) ?
567 REG_BINARY : REG_SZ,
568 &witem->datastart, witem->size);
569 if (err) {
570 ERR("error saving /%s/, err=%d\n", debugstr_w(realname), err);
571 }
572 TRACE("saving value for name /%s/ size=%ld\n",
573 debugstr_w(realname), witem->size);
574 }
575 }
576 RegCloseKey( newkey );
577}
578
579/**************************************************************************
580 * FreeMRUList [COMCTL32.152]
581 *
582 * PARAMS
583 * hMRUList [I] Handle to list.
584 *
585 */
586DWORD WINAPI
587FreeMRUList (HANDLE hMRUList)
588{
589 LPWINEMRULIST mp = (LPWINEMRULIST)hMRUList;
590 INT i;
591
592 TRACE("\n");
593 if (mp->wineFlags & WMRUF_CHANGED) {
594 /* need to open key and then save the info */
595 MRU_SaveChanged( mp );
596 }
597
598 for(i=0; i<mp->extview.nMaxItems; i++) {
599 if (mp->array[i])
600 COMCTL32_Free(mp->array[i]);
601 }
602 COMCTL32_Free(mp->realMRU);
603 COMCTL32_Free(mp->array);
604 COMCTL32_Free((LPWSTR)mp->extview.lpszSubKey);
605 return COMCTL32_Free(mp);
606}
607
608
609/**************************************************************************
610 * FindMRUData [COMCTL32.169]
611 *
612 * Searches binary list for item that matches lpData of length cbData.
613 * Returns position in list order 0 -> MRU and if lpRegNum != NULL then value
614 * corresponding to item's reg. name will be stored in it ('a' -> 0).
615 *
616 * PARAMS
617 * hList [I] list handle
618 * lpData [I] data to find
619 * cbData [I] length of data
620 * lpRegNum [O] position in registry (maybe NULL)
621 *
622 * RETURNS
623 * Position in list 0 -> MRU. -1 if item not found.
624 */
625INT WINAPI
626FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum)
627{
628 LPWINEMRULIST mp = (LPWINEMRULIST)hList;
629 INT i, ret;
630 LPSTR dataA = NULL;
631
632 if (!mp->extview.lpfnCompare) {
633 ERR("MRU list not properly created. No compare procedure.\n");
634 return -1;
635 }
636
637 if(!(mp->extview.dwFlags & MRUF_BINARY_LIST) && !mp->isUnicode) {
638 DWORD len = WideCharToMultiByte(CP_ACP, 0, lpData, -1,
639 NULL, 0, NULL, NULL);
640 dataA = COMCTL32_Alloc(len);
641 WideCharToMultiByte(CP_ACP, 0, lpData, -1, dataA, len, NULL, NULL);
642 }
643
644 for(i=0; i<mp->cursize; i++) {
645 if (mp->extview.dwFlags & MRUF_BINARY_LIST) {
646 if (!mp->extview.lpfnCompare(lpData, &mp->array[i]->datastart,
647 cbData))
648 break;
649 }
650 else {
651 if(mp->isUnicode) {
652 if (!mp->extview.lpfnCompare(lpData, &mp->array[i]->datastart))
653 break;
654 } else {
655 DWORD len = WideCharToMultiByte(CP_ACP, 0,
656 (LPWSTR)&mp->array[i]->datastart, -1,
657 NULL, 0, NULL, NULL);
658 LPSTR itemA = COMCTL32_Alloc(len);
659 INT cmp;
660 WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&mp->array[i]->datastart, -1,
661 itemA, len, NULL, NULL);
662
663 cmp = mp->extview.lpfnCompare(dataA, itemA);
664 COMCTL32_Free(itemA);
665 if(!cmp)
666 break;
667 }
668 }
669 }
670 if(dataA)
671 COMCTL32_Free(dataA);
672 if (i < mp->cursize)
673 ret = i;
674 else
675 ret = -1;
676 if (lpRegNum && (ret != -1))
677 *lpRegNum = 'a' + i;
678
679 TRACE("(%p, %p, %ld, %p) returning %d\n",
680 hList, lpData, cbData, lpRegNum, ret);
681
682 return ret;
683}
684
685
686/**************************************************************************
687 * AddMRUData [COMCTL32.167]
688 *
689 * Add item to MRU binary list. If item already exists in list then it is
690 * simply moved up to the top of the list and not added again. If list is
691 * full then the least recently used item is removed to make room.
692 *
693 * PARAMS
694 * hList [I] Handle to list.
695 * lpData [I] ptr to data to add.
696 * cbData [I] no. of bytes of data.
697 *
698 * RETURNS
699 * No. corresponding to registry name where value is stored 'a' -> 0 etc.
700 * -1 on error.
701 */
702INT WINAPI
703AddMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData)
704{
705 LPWINEMRULIST mp = (LPWINEMRULIST)hList;
706 LPWINEMRUITEM witem;
707 INT i, replace, ret;
708
709 if ((replace = FindMRUData (hList, lpData, cbData, NULL)) < 0) {
710 /* either add a new entry or replace oldest */
711 if (mp->cursize < mp->extview.nMaxItems) {
712 /* Add in a new item */
713 replace = mp->cursize;
714 mp->cursize++;
715 }
716 else {
717 /* get the oldest entry and replace data */
718 replace = mp->realMRU[mp->cursize - 1] - 'a';
719 COMCTL32_Free(mp->array[replace]);
720 }
721 }
722 else {
723 /* free up the old data */
724 COMCTL32_Free(mp->array[replace]);
725 }
726
727 /* Allocate space for new item and move in the data */
728 mp->array[replace] = witem = (LPWINEMRUITEM)COMCTL32_Alloc(cbData +
729 sizeof(WINEMRUITEM));
730 witem->itemFlag |= WMRUIF_CHANGED;
731 witem->size = cbData;
732 memcpy( &witem->datastart, lpData, cbData);
733
734 /* now rotate MRU list */
735 mp->wineFlags |= WMRUF_CHANGED;
736 for(i=mp->cursize-1; i>=1; i--) {
737 mp->realMRU[i] = mp->realMRU[i-1];
738 }
739 mp->realMRU[0] = replace + 'a';
740 TRACE("(%p, %p, %ld) adding data, /%c/ now most current\n",
741 hList, lpData, cbData, replace+'a');
742 ret = replace;
743
744 if (!(mp->extview.dwFlags & MRUF_DELAYED_SAVE)) {
745 /* save changed stuff right now */
746 MRU_SaveChanged( mp );
747 }
748
749 return ret;
750}
751
752/**************************************************************************
753 * AddMRUStringW [COMCTL32.401]
754 *
755 * Add item to MRU string list. If item already exists in list them it is
756 * simply moved up to the top of the list and not added again. If list is
757 * full then the least recently used item is removed to make room.
758 *
759 * PARAMS
760 * hList [I] Handle to list.
761 * lpszString [I] ptr to string to add.
762 *
763 * RETURNS
764 * No. corresponding to registry name where value is stored 'a' -> 0 etc.
765 * -1 on error.
766 */
767INT WINAPI
768AddMRUStringW(HANDLE hList, LPCWSTR lpszString)
769{
770 FIXME("(%p, %s) empty stub!\n", hList, debugstr_w(lpszString));
771
772 return 0;
773}
774
775/**************************************************************************
776 * AddMRUStringA [COMCTL32.153]
777 */
778INT WINAPI
779AddMRUStringA(HANDLE hList, LPCSTR lpszString)
780{
781 FIXME("(%p, %s) empty stub!\n", hList, debugstr_a(lpszString));
782
783 return 0;
784}
785
786/**************************************************************************
787 * DelMRUString [COMCTL32.156]
788 *
789 * Removes item from either string or binary list (despite its name)
790 *
791 * PARAMS
792 * hList [I] list handle
793 * nItemPos [I] item position to remove 0 -> MRU
794 *
795 * RETURNS
796 * TRUE if successful, FALSE if nItemPos is out of range.
797 */
798BOOL WINAPI
799DelMRUString(HANDLE hList, INT nItemPos)
800{
801 FIXME("(%p, %d): stub\n", hList, nItemPos);
802 return TRUE;
803}
804
805/**************************************************************************
806 * FindMRUStringW [COMCTL32.402]
807 */
808INT WINAPI
809FindMRUStringW (HANDLE hList, LPCWSTR lpszString, LPINT lpRegNum)
810{
811 FIXME("stub\n");
812 return -1;
813}
814
815/**************************************************************************
816 * FindMRUStringA [COMCTL32.155]
817 *
818 * Searches string list for item that matches lpszString.
819 * Returns position in list order 0 -> MRU and if lpRegNum != NULL then value
820 * corresponding to item's reg. name will be stored in it ('a' -> 0).
821 *
822 * PARAMS
823 * hList [I] list handle
824 * lpszString [I] string to find
825 * lpRegNum [O] position in registry (maybe NULL)
826 *
827 * RETURNS
828 * Position in list 0 -> MRU. -1 if item not found.
829 */
830INT WINAPI
831FindMRUStringA (HANDLE hList, LPCSTR lpszString, LPINT lpRegNum)
832{
833 DWORD len = MultiByteToWideChar(CP_ACP, 0, lpszString, -1, NULL, 0);
834 LPWSTR stringW = COMCTL32_Alloc(len * sizeof(WCHAR));
835 INT ret;
836
837 MultiByteToWideChar(CP_ACP, 0, lpszString, -1, stringW, len);
838 ret = FindMRUData(hList, stringW, len * sizeof(WCHAR), lpRegNum);
839 COMCTL32_Free(stringW);
840 return ret;
841}
842
843/*************************************************************************
844 * CreateMRUListLazy_common
845 */
846HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp)
847{
848 INT i, err;
849 HKEY newkey;
850 DWORD datasize, dwdisp;
851 WCHAR realname[2];
852 LPWINEMRUITEM witem;
853 DWORD type;
854 WCHAR emptyW[] = {'\0'};
855
856 /* get space to save indices that will turn into names
857 * but in order of most to least recently used
858 */
859 mp->realMRU = (LPSTR) COMCTL32_Alloc(mp->extview.nMaxItems + 2);
860
861 /* get space to save pointers to actual data in order of
862 * 'a' to 'z' (0 to n).
863 */
864 mp->array = (LPVOID) COMCTL32_Alloc(mp->extview.nMaxItems *
865 sizeof(LPVOID));
866
867 /* open the sub key */
868 if ((err = RegCreateKeyExW( mp->extview.hKey, mp->extview.lpszSubKey,
869 0,
870 emptyW,
871 REG_OPTION_NON_VOLATILE,
872 KEY_READ | KEY_WRITE,
873 0,
874 &newkey,
875 &dwdisp))) {
876 /* error - what to do ??? */
877 ERR("(%lu %lu %lx %lx \"%s\" %p): Can not open key, error=%d\n",
878 mp->extview.cbSize, mp->extview.nMaxItems, mp->extview.dwFlags,
879 (DWORD)mp->extview.hKey, debugstr_w(mp->extview.lpszSubKey),
880 mp->extview.lpfnCompare, err);
881 return 0;
882 }
883
884 /* get values from key 'MRUList' */
885 if (newkey) {
886 datasize = mp->extview.nMaxItems + 1;
887 if((err=RegQueryValueExA( newkey, "MRUList", 0, &type, mp->realMRU,
888 &datasize))) {
889 /* not present - set size to 1 (will become 0 later) */
890 datasize = 1;
891 *mp->realMRU = 0;
892 }
893
894 TRACE("MRU list = %s\n", mp->realMRU);
895
896 mp->cursize = datasize - 1;
897 /* datasize now has number of items in the MRUList */
898
899 /* get actual values for each entry */
900 realname[1] = 0;
901 for(i=0; i<mp->cursize; i++) {
902 realname[0] = 'a' + i;
903 if(RegQueryValueExW( newkey, realname, 0, &type, 0, &datasize)) {
904 /* not present - what to do ??? */
905 ERR("Key %s not found 1\n", debugstr_w(realname));
906 }
907 mp->array[i] = witem = (LPWINEMRUITEM)COMCTL32_Alloc(datasize +
908 sizeof(WINEMRUITEM));
909 witem->size = datasize;
910 if(RegQueryValueExW( newkey, realname, 0, &type,
911 &witem->datastart, &datasize)) {
912 /* not present - what to do ??? */
913 ERR("Key %s not found 2\n", debugstr_w(realname));
914 }
915 }
916 RegCloseKey( newkey );
917 }
918 else
919 mp->cursize = 0;
920
921 TRACE("(%lu %lu %lx %lx \"%s\" %p): Current Size = %ld\n",
922 mp->extview.cbSize, mp->extview.nMaxItems, mp->extview.dwFlags,
923 (DWORD)mp->extview.hKey, debugstr_w(mp->extview.lpszSubKey),
924 mp->extview.lpfnCompare, mp->cursize);
925 return (HANDLE)mp;
926}
927
928/**************************************************************************
929 * CreateMRUListLazyW [COMCTL32.404]
930 */
931HANDLE WINAPI
932CreateMRUListLazyW (LPCREATEMRULISTW lpcml, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
933{
934 LPWINEMRULIST mp;
935
936 if (lpcml == NULL)
937 return 0;
938
939 if (lpcml->cbSize < sizeof(CREATEMRULISTW))
940 return 0;
941
942 mp = (LPWINEMRULIST) COMCTL32_Alloc(sizeof(WINEMRULIST));
943 memcpy(&mp->extview, lpcml, sizeof(CREATEMRULISTW));
944 mp->extview.lpszSubKey = COMCTL32_Alloc((strlenW(lpcml->lpszSubKey) + 1) *
945 sizeof(WCHAR));
946 strcpyW((LPWSTR)mp->extview.lpszSubKey, lpcml->lpszSubKey);
947 mp->isUnicode = TRUE;
948
949 return CreateMRUListLazy_common(mp);
950}
951
952/**************************************************************************
953 * CreateMRUListLazyA [COMCTL32.157]
954 */
955HANDLE WINAPI
956CreateMRUListLazyA (LPCREATEMRULISTA lpcml, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
957{
958 LPWINEMRULIST mp;
959 DWORD len;
960
961 if (lpcml == NULL)
962 return 0;
963
964 if (lpcml->cbSize < sizeof(CREATEMRULISTA))
965 return 0;
966
967 mp = (LPWINEMRULIST) COMCTL32_Alloc(sizeof(WINEMRULIST));
968 memcpy(&mp->extview, lpcml, sizeof(CREATEMRULISTW));
969 len = MultiByteToWideChar(CP_ACP, 0, lpcml->lpszSubKey, -1, NULL, 0);
970 mp->extview.lpszSubKey = COMCTL32_Alloc(len * sizeof(WCHAR));
971 MultiByteToWideChar(CP_ACP, 0, lpcml->lpszSubKey, -1,
972 (LPWSTR)mp->extview.lpszSubKey, len);
973 mp->isUnicode = FALSE;
974 return CreateMRUListLazy_common(mp);
975}
976
977/**************************************************************************
978 * CreateMRUListW [COMCTL32.400]
979 *
980 * PARAMS
981 * lpcml [I] ptr to CREATEMRULIST structure.
982 *
983 * RETURNS
984 * Handle to MRU list.
985 */
986HANDLE WINAPI
987CreateMRUListW (LPCREATEMRULISTW lpcml)
988{
989 return CreateMRUListLazyW(lpcml, 0, 0, 0);
990}
991
992/**************************************************************************
993 * CreateMRUListA [COMCTL32.151]
994 */
995HANDLE WINAPI
996CreateMRUListA (LPCREATEMRULISTA lpcml)
997{
998 return CreateMRUListLazyA (lpcml, 0, 0, 0);
999}
1000
1001
1002/**************************************************************************
1003 * EnumMRUListW [COMCTL32.403]
1004 *
1005 * Enumerate item in a list
1006 *
1007 * PARAMS
1008 * hList [I] list handle
1009 * nItemPos [I] item position to enumerate
1010 * lpBuffer [O] buffer to receive item
1011 * nBufferSize [I] size of buffer
1012 *
1013 * RETURNS
1014 * For binary lists specifies how many bytes were copied to buffer, for
1015 * string lists specifies full length of string. Enumerating past the end
1016 * of list returns -1.
1017 * If lpBuffer == NULL or nItemPos is -ve return value is no. of items in
1018 * the list.
1019 */
1020INT WINAPI EnumMRUListW(HANDLE hList, INT nItemPos, LPVOID lpBuffer,
1021DWORD nBufferSize)
1022{
1023 LPWINEMRULIST mp = (LPWINEMRULIST) hList;
1024 LPWINEMRUITEM witem;
1025 INT desired, datasize;
1026
1027 if (nItemPos >= mp->cursize) return -1;
1028 if ((nItemPos < 0) || !lpBuffer) return mp->cursize;
1029 desired = mp->realMRU[nItemPos];
1030 desired -= 'a';
1031 TRACE("nItemPos=%d, desired=%d\n", nItemPos, desired);
1032 witem = mp->array[desired];
1033 datasize = min( witem->size, nBufferSize );
1034 memcpy( lpBuffer, &witem->datastart, datasize);
1035 TRACE("(%p, %d, %p, %ld): returning len=%d\n",
1036 hList, nItemPos, lpBuffer, nBufferSize, datasize);
1037 return datasize;
1038}
1039
1040/**************************************************************************
1041 * EnumMRUListA [COMCTL32.154]
1042 *
1043 */
1044INT WINAPI EnumMRUListA(HANDLE hList, INT nItemPos, LPVOID lpBuffer,
1045DWORD nBufferSize)
1046{
1047 LPWINEMRULIST mp = (LPWINEMRULIST) hList;
1048 LPWINEMRUITEM witem;
1049 INT desired, datasize;
1050 DWORD lenA;
1051
1052 if (nItemPos >= mp->cursize) return -1;
1053 if ((nItemPos < 0) || !lpBuffer) return mp->cursize;
1054 desired = mp->realMRU[nItemPos];
1055 desired -= 'a';
1056 TRACE("nItemPos=%d, desired=%d\n", nItemPos, desired);
1057 witem = mp->array[desired];
1058 if(mp->extview.dwFlags & MRUF_BINARY_LIST) {
1059 datasize = min( witem->size, nBufferSize );
1060 memcpy( lpBuffer, &witem->datastart, datasize);
1061 } else {
1062 lenA = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&witem->datastart, -1,
1063 NULL, 0, NULL, NULL);
1064 datasize = min( witem->size, nBufferSize );
1065 WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&witem->datastart, -1,
1066 lpBuffer, datasize, NULL, NULL);
1067 }
1068 TRACE("(%p, %d, %p, %ld): returning len=%d\n",
1069 hList, nItemPos, lpBuffer, nBufferSize, datasize);
1070 return datasize;
1071}
1072
1073
1074/**************************************************************************
1075 * Str_GetPtrA [COMCTL32.233]
1076 *
1077 * PARAMS
1078 * lpSrc [I]
1079 * lpDest [O]
1080 * nMaxLen [I]
1081 *
1082 * RETURNS
1083 */
1084
1085INT WINAPI
1086Str_GetPtrA (LPCSTR lpSrc, LPSTR lpDest, INT nMaxLen)
1087{
1088 INT len;
1089
1090 TRACE("(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
1091
1092 if (!lpDest && lpSrc)
1093 return strlen (lpSrc);
1094
1095 if (nMaxLen == 0)
1096 return 0;
1097
1098 if (lpSrc == NULL) {
1099 lpDest[0] = '\0';
1100 return 0;
1101 }
1102
1103 len = strlen (lpSrc);
1104 if (len >= nMaxLen)
1105 len = nMaxLen - 1;
1106
1107 RtlMoveMemory (lpDest, lpSrc, len);
1108 lpDest[len] = '\0';
1109
1110 return len;
1111}
1112
1113
1114/**************************************************************************
1115 * Str_SetPtrA [COMCTL32.234]
1116 *
1117 * PARAMS
1118 * lppDest [O]
1119 * lpSrc [I]
1120 *
1121 * RETURNS
1122 */
1123
1124BOOL WINAPI
1125Str_SetPtrA (LPSTR *lppDest, LPCSTR lpSrc)
1126{
1127 TRACE("(%p %p)\n", lppDest, lpSrc);
1128
1129 if (lpSrc) {
1130 LPSTR ptr = COMCTL32_ReAlloc (*lppDest, strlen (lpSrc) + 1);
1131 if (!ptr)
1132 return FALSE;
1133 strcpy (ptr, lpSrc);
1134 *lppDest = ptr;
1135 }
1136 else {
1137 if (*lppDest) {
1138 COMCTL32_Free (*lppDest);
1139 *lppDest = NULL;
1140 }
1141 }
1142
1143 return TRUE;
1144}
1145
1146
1147/**************************************************************************
1148 * Str_GetPtrW [COMCTL32.235]
1149 *
1150 * PARAMS
1151 * lpSrc [I]
1152 * lpDest [O]
1153 * nMaxLen [I]
1154 *
1155 * RETURNS
1156 */
1157
1158INT WINAPI
1159Str_GetPtrW (LPCWSTR lpSrc, LPWSTR lpDest, INT nMaxLen)
1160{
1161 INT len;
1162
1163 TRACE("(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
1164
1165 if (!lpDest && lpSrc)
1166 return strlenW (lpSrc);
1167
1168 if (nMaxLen == 0)
1169 return 0;
1170
1171 if (lpSrc == NULL) {
1172 lpDest[0] = L'\0';
1173 return 0;
1174 }
1175
1176 len = strlenW (lpSrc);
1177 if (len >= nMaxLen)
1178 len = nMaxLen - 1;
1179
1180 RtlMoveMemory (lpDest, lpSrc, len*sizeof(WCHAR));
1181 lpDest[len] = L'\0';
1182
1183 return len;
1184}
1185
1186
1187/**************************************************************************
1188 * Str_SetPtrW [COMCTL32.236]
1189 *
1190 * PARAMS
1191 * lpDest [O]
1192 * lpSrc [I]
1193 *
1194 * RETURNS
1195 */
1196
1197BOOL WINAPI
1198Str_SetPtrW (LPWSTR *lppDest, LPCWSTR lpSrc)
1199{
1200 TRACE("(%p %p)\n", lppDest, lpSrc);
1201
1202 if (lpSrc) {
1203 INT len = strlenW (lpSrc) + 1;
1204 LPWSTR ptr = COMCTL32_ReAlloc (*lppDest, len * sizeof(WCHAR));
1205 if (!ptr)
1206 return FALSE;
1207 strcpyW (ptr, lpSrc);
1208 *lppDest = ptr;
1209 }
1210 else {
1211 if (*lppDest) {
1212 COMCTL32_Free (*lppDest);
1213 *lppDest = NULL;
1214 }
1215 }
1216
1217 return TRUE;
1218}
1219
1220
1221/**************************************************************************
1222 * Str_GetPtrWtoA [internal]
1223 *
1224 * Converts a unicode string into a multi byte string
1225 *
1226 * PARAMS
1227 * lpSrc [I] Pointer to the unicode source string
1228 * lpDest [O] Pointer to caller supplied storage for the multi byte string
1229 * nMaxLen [I] Size, in bytes, of the destination buffer
1230 *
1231 * RETURNS
1232 * Length, in bytes, of the converted string.
1233 */
1234
1235INT
1236Str_GetPtrWtoA (LPCWSTR lpSrc, LPSTR lpDest, INT nMaxLen)
1237{
1238 INT len;
1239
1240 TRACE("(%s %p %d)\n", debugstr_w(lpSrc), lpDest, nMaxLen);
1241
1242 if (!lpDest && lpSrc)
1243 return WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL);
1244
1245 if (nMaxLen == 0)
1246 return 0;
1247
1248 if (lpSrc == NULL) {
1249 lpDest[0] = '\0';
1250 return 0;
1251 }
1252
1253 len = WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL);
1254 if (len >= nMaxLen)
1255 len = nMaxLen - 1;
1256
1257 WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, lpDest, len, NULL, NULL);
1258 lpDest[len] = '\0';
1259
1260 return len;
1261}
1262
1263
1264/**************************************************************************
1265 * Str_SetPtrAtoW [internal]
1266 *
1267 * Converts a multi byte string to a unicode string.
1268 * If the pointer to the destination buffer is NULL a buffer is allocated.
1269 * If the destination buffer is too small to keep the converted multi byte
1270 * string the destination buffer is reallocated. If the source pointer is
1271 * NULL, the destination buffer is freed.
1272 *
1273 * PARAMS
1274 * lppDest [I/O] pointer to a pointer to the destination buffer
1275 * lpSrc [I] pointer to a multi byte string
1276 *
1277 * RETURNS
1278 * TRUE: conversion successful
1279 * FALSE: error
1280 */
1281
1282BOOL
1283Str_SetPtrAtoW (LPWSTR *lppDest, LPCSTR lpSrc)
1284{
1285 TRACE("(%p %s)\n", lppDest, lpSrc);
1286
1287 if (lpSrc) {
1288 INT len = MultiByteToWideChar(CP_ACP,0,lpSrc,-1,NULL,0);
1289 LPWSTR ptr = COMCTL32_ReAlloc (*lppDest, len*sizeof(WCHAR));
1290
1291 if (!ptr)
1292 return FALSE;
1293 MultiByteToWideChar(CP_ACP,0,lpSrc,-1,ptr,len);
1294 *lppDest = ptr;
1295 }
1296 else {
1297 if (*lppDest) {
1298 COMCTL32_Free (*lppDest);
1299 *lppDest = NULL;
1300 }
1301 }
1302
1303 return TRUE;
1304}
1305
1306
1307/**************************************************************************
1308 * The DSA-API is a set of functions to create and manipulate arrays of
1309 * fixed-size memory blocks. These arrays can store any kind of data
1310 * (strings, icons...).
1311 */
1312
1313/**************************************************************************
1314 * DSA_Create [COMCTL32.320] Creates a dynamic storage array
1315 *
1316 * PARAMS
1317 * nSize [I] size of the array elements
1318 * nGrow [I] number of elements by which the array grows when it is filled
1319 *
1320 * RETURNS
1321 * Success: pointer to an array control structure. Use this like a handle.
1322 * Failure: NULL
1323 */
1324
1325HDSA WINAPI
1326DSA_Create (INT nSize, INT nGrow)
1327{
1328 HDSA hdsa;
1329
1330 TRACE("(size=%d grow=%d)\n", nSize, nGrow);
1331
1332 hdsa = (HDSA)COMCTL32_Alloc (sizeof(DSA));
1333 if (hdsa)
1334 {
1335 hdsa->nItemCount = 0;
1336 hdsa->pData = NULL;
1337 hdsa->nMaxCount = 0;
1338 hdsa->nItemSize = nSize;
1339 hdsa->nGrow = max(1, nGrow);
1340 }
1341
1342 return hdsa;
1343}
1344
1345
1346/**************************************************************************
1347 * DSA_Destroy [COMCTL32.321] Destroys a dynamic storage array
1348 *
1349 * PARAMS
1350 * hdsa [I] pointer to the array control structure
1351 *
1352 * RETURNS
1353 * Success: TRUE
1354 * Failure: FALSE
1355 */
1356
1357BOOL WINAPI
1358DSA_Destroy (const HDSA hdsa)
1359{
1360 TRACE("(%p)\n", hdsa);
1361
1362 if (!hdsa)
1363 return FALSE;
1364
1365 if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
1366 return FALSE;
1367
1368 return COMCTL32_Free (hdsa);
1369}
1370
1371
1372/**************************************************************************
1373 * DSA_GetItem [COMCTL32.322]
1374 *
1375 * PARAMS
1376 * hdsa [I] pointer to the array control structure
1377 * nIndex [I] number of the Item to get
1378 * pDest [O] destination buffer. Has to be >= dwElementSize.
1379 *
1380 * RETURNS
1381 * Success: TRUE
1382 * Failure: FALSE
1383 */
1384
1385BOOL WINAPI
1386DSA_GetItem (const HDSA hdsa, INT nIndex, LPVOID pDest)
1387{
1388 LPVOID pSrc;
1389
1390 TRACE("(%p %d %p)\n", hdsa, nIndex, pDest);
1391
1392 if (!hdsa)
1393 return FALSE;
1394 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
1395 return FALSE;
1396
1397 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1398 memmove (pDest, pSrc, hdsa->nItemSize);
1399
1400 return TRUE;
1401}
1402
1403
1404/**************************************************************************
1405 * DSA_GetItemPtr [COMCTL32.323]
1406 *
1407 * Retrieves a pointer to the specified item.
1408 *
1409 * PARAMS
1410 * hdsa [I] pointer to the array control structure
1411 * nIndex [I] index of the desired item
1412 *
1413 * RETURNS
1414 * Success: pointer to an item
1415 * Failure: NULL
1416 */
1417
1418LPVOID WINAPI
1419DSA_GetItemPtr (const HDSA hdsa, INT nIndex)
1420{
1421 LPVOID pSrc;
1422
1423 TRACE("(%p %d)\n", hdsa, nIndex);
1424
1425 if (!hdsa)
1426 return NULL;
1427 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
1428 return NULL;
1429
1430 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1431
1432 TRACE("-- ret=%p\n", pSrc);
1433
1434 return pSrc;
1435}
1436
1437
1438/**************************************************************************
1439 * DSA_SetItem [COMCTL32.325]
1440 *
1441 * Sets the contents of an item in the array.
1442 *
1443 * PARAMS
1444 * hdsa [I] pointer to the array control structure
1445 * nIndex [I] index for the item
1446 * pSrc [I] pointer to the new item data
1447 *
1448 * RETURNS
1449 * Success: TRUE
1450 * Failure: FALSE
1451 */
1452
1453BOOL WINAPI
1454DSA_SetItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
1455{
1456 INT nSize, nNewItems;
1457 LPVOID pDest, lpTemp;
1458
1459 TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
1460
1461 if ((!hdsa) || nIndex < 0)
1462 return FALSE;
1463
1464 if (hdsa->nItemCount <= nIndex) {
1465 /* within the old array */
1466 if (hdsa->nMaxCount > nIndex) {
1467 /* within the allocated space, set a new boundary */
1468 hdsa->nItemCount = nIndex + 1;
1469 }
1470 else {
1471 /* resize the block of memory */
1472 nNewItems =
1473 hdsa->nGrow * ((INT)(((nIndex + 1) - 1) / hdsa->nGrow) + 1);
1474 nSize = hdsa->nItemSize * nNewItems;
1475
1476 lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
1477 if (!lpTemp)
1478 return FALSE;
1479
1480 hdsa->nMaxCount = nNewItems;
1481 hdsa->nItemCount = nIndex + 1;
1482 hdsa->pData = lpTemp;
1483 }
1484 }
1485
1486 /* put the new entry in */
1487 pDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1488 TRACE("-- move dest=%p src=%p size=%d\n",
1489 pDest, pSrc, hdsa->nItemSize);
1490 memmove (pDest, pSrc, hdsa->nItemSize);
1491
1492 return TRUE;
1493}
1494
1495
1496/**************************************************************************
1497 * DSA_InsertItem [COMCTL32.324]
1498 *
1499 * PARAMS
1500 * hdsa [I] pointer to the array control structure
1501 * nIndex [I] index for the new item
1502 * pSrc [I] pointer to the element
1503 *
1504 * RETURNS
1505 * Success: position of the new item
1506 * Failure: -1
1507 */
1508
1509INT WINAPI
1510DSA_InsertItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
1511{
1512 INT nNewItems, nSize;
1513 LPVOID lpTemp, lpDest;
1514
1515 TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
1516
1517 if ((!hdsa) || nIndex < 0)
1518 return -1;
1519
1520 /* when nIndex >= nItemCount then append */
1521 if (nIndex >= hdsa->nItemCount)
1522 nIndex = hdsa->nItemCount;
1523
1524 /* do we need to resize ? */
1525 if (hdsa->nItemCount >= hdsa->nMaxCount) {
1526 nNewItems = hdsa->nMaxCount + hdsa->nGrow;
1527 nSize = hdsa->nItemSize * nNewItems;
1528
1529 lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
1530 if (!lpTemp)
1531 return -1;
1532
1533 hdsa->nMaxCount = nNewItems;
1534 hdsa->pData = lpTemp;
1535 }
1536
1537 /* do we need to move elements ? */
1538 if (nIndex < hdsa->nItemCount) {
1539 lpTemp = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1540 lpDest = (char *) lpTemp + hdsa->nItemSize;
1541 nSize = (hdsa->nItemCount - nIndex) * hdsa->nItemSize;
1542 TRACE("-- move dest=%p src=%p size=%d\n",
1543 lpDest, lpTemp, nSize);
1544 memmove (lpDest, lpTemp, nSize);
1545 }
1546
1547 /* ok, we can put the new Item in */
1548 hdsa->nItemCount++;
1549 lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1550 TRACE("-- move dest=%p src=%p size=%d\n",
1551 lpDest, pSrc, hdsa->nItemSize);
1552 memmove (lpDest, pSrc, hdsa->nItemSize);
1553
1554 return nIndex;
1555}
1556
1557
1558/**************************************************************************
1559 * DSA_DeleteItem [COMCTL32.326]
1560 *
1561 * PARAMS
1562 * hdsa [I] pointer to the array control structure
1563 * nIndex [I] index for the element to delete
1564 *
1565 * RETURNS
1566 * Success: number of the deleted element
1567 * Failure: -1
1568 */
1569
1570INT WINAPI
1571DSA_DeleteItem (const HDSA hdsa, INT nIndex)
1572{
1573 LPVOID lpDest,lpSrc;
1574 INT nSize;
1575
1576 TRACE("(%p %d)\n", hdsa, nIndex);
1577
1578 if (!hdsa)
1579 return -1;
1580 if (nIndex < 0 || nIndex >= hdsa->nItemCount)
1581 return -1;
1582
1583 /* do we need to move ? */
1584 if (nIndex < hdsa->nItemCount - 1) {
1585 lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1586 lpSrc = (char *) lpDest + hdsa->nItemSize;
1587 nSize = hdsa->nItemSize * (hdsa->nItemCount - nIndex - 1);
1588 TRACE("-- move dest=%p src=%p size=%d\n",
1589 lpDest, lpSrc, nSize);
1590 memmove (lpDest, lpSrc, nSize);
1591 }
1592
1593 hdsa->nItemCount--;
1594
1595 /* free memory ? */
1596 if ((hdsa->nMaxCount - hdsa->nItemCount) >= hdsa->nGrow) {
1597 nSize = hdsa->nItemSize * hdsa->nItemCount;
1598
1599 lpDest = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
1600 if (!lpDest)
1601 return -1;
1602
1603 hdsa->nMaxCount = hdsa->nItemCount;
1604 hdsa->pData = lpDest;
1605 }
1606
1607 return nIndex;
1608}
1609
1610
1611/**************************************************************************
1612 * DSA_DeleteAllItems [COMCTL32.327]
1613 *
1614 * Removes all items and reinitializes the array.
1615 *
1616 * PARAMS
1617 * hdsa [I] pointer to the array control structure
1618 *
1619 * RETURNS
1620 * Success: TRUE
1621 * Failure: FALSE
1622 */
1623
1624BOOL WINAPI
1625DSA_DeleteAllItems (const HDSA hdsa)
1626{
1627 TRACE("(%p)\n", hdsa);
1628
1629 if (!hdsa)
1630 return FALSE;
1631 if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
1632 return FALSE;
1633
1634 hdsa->nItemCount = 0;
1635 hdsa->pData = NULL;
1636 hdsa->nMaxCount = 0;
1637
1638 return TRUE;
1639}
1640
1641
1642/**************************************************************************
1643 * The DPA-API is a set of functions to create and manipulate arrays of
1644 * pointers.
1645 */
1646
1647/**************************************************************************
1648 * DPA_Create [COMCTL32.328] Creates a dynamic pointer array
1649 *
1650 * PARAMS
1651 * nGrow [I] number of items by which the array grows when it is filled
1652 *
1653 * RETURNS
1654 * Success: handle (pointer) to the pointer array.
1655 * Failure: NULL
1656 */
1657
1658HDPA WINAPI
1659DPA_Create (INT nGrow)
1660{
1661 HDPA hdpa;
1662
1663 TRACE("(%d)\n", nGrow);
1664
1665 hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
1666 if (hdpa) {
1667 hdpa->nGrow = max(8, nGrow);
1668 hdpa->hHeap = COMCTL32_hHeap;
1669 hdpa->nMaxCount = hdpa->nGrow * 2;
1670 hdpa->ptrs =
1671 (LPVOID*)COMCTL32_Alloc (hdpa->nMaxCount * sizeof(LPVOID));
1672 }
1673
1674 TRACE("-- %p\n", hdpa);
1675
1676 return hdpa;
1677}
1678
1679
1680/**************************************************************************
1681 * DPA_Destroy [COMCTL32.329] Destroys a dynamic pointer array
1682 *
1683 * PARAMS
1684 * hdpa [I] handle (pointer) to the pointer array
1685 *
1686 * RETURNS
1687 * Success: TRUE
1688 * Failure: FALSE
1689 */
1690
1691BOOL WINAPI
1692DPA_Destroy (const HDPA hdpa)
1693{
1694 TRACE("(%p)\n", hdpa);
1695
1696 if (!hdpa)
1697 return FALSE;
1698
1699 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
1700 return FALSE;
1701
1702 return HeapFree (hdpa->hHeap, 0, hdpa);
1703}
1704
1705
1706/**************************************************************************
1707 * DPA_Grow [COMCTL32.330]
1708 *
1709 * Sets the growth amount.
1710 *
1711 * PARAMS
1712 * hdpa [I] handle (pointer) to the existing (source) pointer array
1713 * nGrow [I] number of items by which the array grows when it's too small
1714 *
1715 * RETURNS
1716 * Success: TRUE
1717 * Failure: FALSE
1718 */
1719
1720BOOL WINAPI
1721DPA_Grow (const HDPA hdpa, INT nGrow)
1722{
1723 TRACE("(%p %d)\n", hdpa, nGrow);
1724
1725 if (!hdpa)
1726 return FALSE;
1727
1728 hdpa->nGrow = max(8, nGrow);
1729
1730 return TRUE;
1731}
1732
1733
1734/**************************************************************************
1735 * DPA_Clone [COMCTL32.331]
1736 *
1737 * Copies a pointer array to an other one or creates a copy
1738 *
1739 * PARAMS
1740 * hdpa [I] handle (pointer) to the existing (source) pointer array
1741 * hdpaNew [O] handle (pointer) to the destination pointer array
1742 *
1743 * RETURNS
1744 * Success: pointer to the destination pointer array.
1745 * Failure: NULL
1746 *
1747 * NOTES
1748 * - If the 'hdpaNew' is a NULL-Pointer, a copy of the source pointer
1749 * array will be created and it's handle (pointer) is returned.
1750 * - If 'hdpa' is a NULL-Pointer, the original implementation crashes,
1751 * this implementation just returns NULL.
1752 */
1753
1754HDPA WINAPI
1755DPA_Clone (const HDPA hdpa, const HDPA hdpaNew)
1756{
1757 INT nNewItems, nSize;
1758 HDPA hdpaTemp;
1759
1760 if (!hdpa)
1761 return NULL;
1762
1763 TRACE("(%p %p)\n", hdpa, hdpaNew);
1764
1765 if (!hdpaNew) {
1766 /* create a new DPA */
1767 hdpaTemp = (HDPA)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1768 sizeof(DPA));
1769 hdpaTemp->hHeap = hdpa->hHeap;
1770 hdpaTemp->nGrow = hdpa->nGrow;
1771 }
1772 else
1773 hdpaTemp = hdpaNew;
1774
1775 if (hdpaTemp->ptrs) {
1776 /* remove old pointer array */
1777 HeapFree (hdpaTemp->hHeap, 0, hdpaTemp->ptrs);
1778 hdpaTemp->ptrs = NULL;
1779 hdpaTemp->nItemCount = 0;
1780 hdpaTemp->nMaxCount = 0;
1781 }
1782
1783 /* create a new pointer array */
1784 nNewItems = hdpaTemp->nGrow *
1785 ((INT)((hdpa->nItemCount - 1) / hdpaTemp->nGrow) + 1);
1786 nSize = nNewItems * sizeof(LPVOID);
1787 hdpaTemp->ptrs =
1788 (LPVOID*)HeapAlloc (hdpaTemp->hHeap, HEAP_ZERO_MEMORY, nSize);
1789 hdpaTemp->nMaxCount = nNewItems;
1790
1791 /* clone the pointer array */
1792 hdpaTemp->nItemCount = hdpa->nItemCount;
1793 memmove (hdpaTemp->ptrs, hdpa->ptrs,
1794 hdpaTemp->nItemCount * sizeof(LPVOID));
1795
1796 return hdpaTemp;
1797}
1798
1799
1800/**************************************************************************
1801 * DPA_GetPtr [COMCTL32.332]
1802 *
1803 * Retrieves a pointer from a dynamic pointer array
1804 *
1805 * PARAMS
1806 * hdpa [I] handle (pointer) to the pointer array
1807 * nIndex [I] array index of the desired pointer
1808 *
1809 * RETURNS
1810 * Success: pointer
1811 * Failure: NULL
1812 */
1813
1814LPVOID WINAPI
1815DPA_GetPtr (const HDPA hdpa, INT i)
1816{
1817 TRACE("(%p %d)\n", hdpa, i);
1818
1819 if (!hdpa)
1820 return NULL;
1821 if (!hdpa->ptrs) {
1822 WARN("no pointer array.\n");
1823 return NULL;
1824 }
1825 if ((i < 0) || (i >= hdpa->nItemCount)) {
1826 WARN("not enough pointers in array (%d vs %d).\n",i,hdpa->nItemCount);
1827 return NULL;
1828 }
1829
1830 TRACE("-- %p\n", hdpa->ptrs[i]);
1831
1832 return hdpa->ptrs[i];
1833}
1834
1835
1836/**************************************************************************
1837 * DPA_GetPtrIndex [COMCTL32.333]
1838 *
1839 * Retrieves the index of the specified pointer
1840 *
1841 * PARAMS
1842 * hdpa [I] handle (pointer) to the pointer array
1843 * p [I] pointer
1844 *
1845 * RETURNS
1846 * Success: index of the specified pointer
1847 * Failure: -1
1848 */
1849
1850INT WINAPI
1851DPA_GetPtrIndex (const HDPA hdpa, LPVOID p)
1852{
1853 INT i;
1854
1855 if (!hdpa || !hdpa->ptrs)
1856 return -1;
1857
1858 for (i = 0; i < hdpa->nItemCount; i++) {
1859 if (hdpa->ptrs[i] == p)
1860 return i;
1861 }
1862
1863 return -1;
1864}
1865
1866
1867/**************************************************************************
1868 * DPA_InsertPtr [COMCTL32.334]
1869 *
1870 * Inserts a pointer into a dynamic pointer array
1871 *
1872 * PARAMS
1873 * hdpa [I] handle (pointer) to the array
1874 * i [I] array index
1875 * p [I] pointer to insert
1876 *
1877 * RETURNS
1878 * Success: index of the inserted pointer
1879 * Failure: -1
1880 */
1881
1882INT WINAPI
1883DPA_InsertPtr (const HDPA hdpa, INT i, LPVOID p)
1884{
1885 TRACE("(%p %d %p)\n", hdpa, i, p);
1886
1887 if (!hdpa || i < 0) return -1;
1888
1889 if (i >= 0x7fff)
1890 i = hdpa->nItemCount;
1891
1892 if (i >= hdpa->nItemCount)
1893 return DPA_SetPtr(hdpa, i, p) ? i : -1;
1894
1895 /* create empty spot at the end */
1896 if (!DPA_SetPtr(hdpa, hdpa->nItemCount, 0)) return -1;
1897 memmove (hdpa->ptrs + i + 1, hdpa->ptrs + i, (hdpa->nItemCount - i - 1) * sizeof(LPVOID));
1898 hdpa->ptrs[i] = p;
1899 return i;
1900}
1901
1902/**************************************************************************
1903 * DPA_SetPtr [COMCTL32.335]
1904 *
1905 * Sets a pointer in the pointer array
1906 *
1907 * PARAMS
1908 * hdpa [I] handle (pointer) to the pointer array
1909 * i [I] index of the pointer that will be set
1910 * p [I] pointer to be set
1911 *
1912 * RETURNS
1913 * Success: TRUE
1914 * Failure: FALSE
1915 */
1916
1917BOOL WINAPI
1918DPA_SetPtr (const HDPA hdpa, INT i, LPVOID p)
1919{
1920 LPVOID *lpTemp;
1921
1922 TRACE("(%p %d %p)\n", hdpa, i, p);
1923
1924 if (!hdpa || i < 0 || i > 0x7fff)
1925 return FALSE;
1926
1927 if (hdpa->nItemCount <= i) {
1928 /* within the old array */
1929 if (hdpa->nMaxCount <= i) {
1930 /* resize the block of memory */
1931 INT nNewItems =
1932 hdpa->nGrow * ((INT)(((i+1) - 1) / hdpa->nGrow) + 1);
1933 INT nSize = nNewItems * sizeof(LPVOID);
1934
1935 if (hdpa->ptrs)
1936 lpTemp = (LPVOID*)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, hdpa->ptrs, nSize);
1937 else
1938 lpTemp = (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, nSize);
1939
1940 if (!lpTemp)
1941 return FALSE;
1942
1943 hdpa->nMaxCount = nNewItems;
1944 hdpa->ptrs = lpTemp;
1945 }
1946 hdpa->nItemCount = i+1;
1947 }
1948
1949 /* put the new entry in */
1950 hdpa->ptrs[i] = p;
1951
1952 return TRUE;
1953}
1954
1955
1956/**************************************************************************
1957 * DPA_DeletePtr [COMCTL32.336]
1958 *
1959 * Removes a pointer from the pointer array.
1960 *
1961 * PARAMS
1962 * hdpa [I] handle (pointer) to the pointer array
1963 * i [I] index of the pointer that will be deleted
1964 *
1965 * RETURNS
1966 * Success: deleted pointer
1967 * Failure: NULL
1968 */
1969
1970LPVOID WINAPI
1971DPA_DeletePtr (const HDPA hdpa, INT i)
1972{
1973 LPVOID *lpDest, *lpSrc, lpTemp = NULL;
1974 INT nSize;
1975
1976 TRACE("(%p %d)\n", hdpa, i);
1977
1978 if ((!hdpa) || i < 0 || i >= hdpa->nItemCount)
1979 return NULL;
1980
1981 lpTemp = hdpa->ptrs[i];
1982
1983 /* do we need to move ?*/
1984 if (i < hdpa->nItemCount - 1) {
1985 lpDest = hdpa->ptrs + i;
1986 lpSrc = lpDest + 1;
1987 nSize = (hdpa->nItemCount - i - 1) * sizeof(LPVOID);
1988 TRACE("-- move dest=%p src=%p size=%x\n",
1989 lpDest, lpSrc, nSize);
1990 memmove (lpDest, lpSrc, nSize);
1991 }
1992
1993 hdpa->nItemCount --;
1994
1995 /* free memory ?*/
1996 if ((hdpa->nMaxCount - hdpa->nItemCount) >= hdpa->nGrow) {
1997 INT nNewItems = max(hdpa->nGrow * 2, hdpa->nItemCount);
1998 nSize = nNewItems * sizeof(LPVOID);
1999 lpDest = (LPVOID)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
2000 hdpa->ptrs, nSize);
2001 if (!lpDest)
2002 return NULL;
2003
2004 hdpa->nMaxCount = nNewItems;
2005 hdpa->ptrs = (LPVOID*)lpDest;
2006 }
2007
2008 return lpTemp;
2009}
2010
2011
2012/**************************************************************************
2013 * DPA_DeleteAllPtrs [COMCTL32.337]
2014 *
2015 * Removes all pointers and reinitializes the array.
2016 *
2017 * PARAMS
2018 * hdpa [I] handle (pointer) to the pointer array
2019 *
2020 * RETURNS
2021 * Success: TRUE
2022 * Failure: FALSE
2023 */
2024
2025BOOL WINAPI
2026DPA_DeleteAllPtrs (const HDPA hdpa)
2027{
2028 TRACE("(%p)\n", hdpa);
2029
2030 if (!hdpa)
2031 return FALSE;
2032
2033 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
2034 return FALSE;
2035
2036 hdpa->nItemCount = 0;
2037 hdpa->nMaxCount = hdpa->nGrow * 2;
2038 hdpa->ptrs = (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
2039 hdpa->nMaxCount * sizeof(LPVOID));
2040
2041 return TRUE;
2042}
2043
2044
2045/**************************************************************************
2046 * DPA_QuickSort [Internal]
2047 *
2048 * Ordinary quicksort (used by DPA_Sort).
2049 *
2050 * PARAMS
2051 * lpPtrs [I] pointer to the pointer array
2052 * l [I] index of the "left border" of the partition
2053 * r [I] index of the "right border" of the partition
2054 * pfnCompare [I] pointer to the compare function
2055 * lParam [I] user defined value (3rd parameter in compare function)
2056 *
2057 * RETURNS
2058 * NONE
2059 */
2060
2061static VOID
2062DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r,
2063 PFNDPACOMPARE pfnCompare, LPARAM lParam)
2064{
2065 INT m;
2066 LPVOID t;
2067
2068 TRACE("l=%i r=%i\n", l, r);
2069
2070 if (l==r) /* one element is always sorted */
2071 return;
2072 if (r<l) /* oops, got it in the wrong order */
2073 {
2074 DPA_QuickSort(lpPtrs, r, l, pfnCompare, lParam);
2075 return;
2076 }
2077 m = (l+r)/2; /* divide by two */
2078 DPA_QuickSort(lpPtrs, l, m, pfnCompare, lParam);
2079 DPA_QuickSort(lpPtrs, m+1, r, pfnCompare, lParam);
2080
2081 /* join the two sides */
2082 while( (l<=m) && (m<r) )
2083 {
2084 if(pfnCompare(lpPtrs[l],lpPtrs[m+1],lParam)>0)
2085 {
2086 t = lpPtrs[m+1];
2087 memmove(&lpPtrs[l+1],&lpPtrs[l],(m-l+1)*sizeof lpPtrs[l]);
2088 lpPtrs[l] = t;
2089
2090 m++;
2091 }
2092 l++;
2093 }
2094}
2095
2096
2097/**************************************************************************
2098 * DPA_Sort [COMCTL32.338]
2099 *
2100 * Sorts a pointer array using a user defined compare function
2101 *
2102 * PARAMS
2103 * hdpa [I] handle (pointer) to the pointer array
2104 * pfnCompare [I] pointer to the compare function
2105 * lParam [I] user defined value (3rd parameter of compare function)
2106 *
2107 * RETURNS
2108 * Success: TRUE
2109 * Failure: FALSE
2110 */
2111
2112BOOL WINAPI
2113DPA_Sort (const HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam)
2114{
2115 if (!hdpa || !pfnCompare)
2116 return FALSE;
2117
2118 TRACE("(%p %p 0x%lx)\n", hdpa, pfnCompare, lParam);
2119
2120 if ((hdpa->nItemCount > 1) && (hdpa->ptrs))
2121 DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1,
2122 pfnCompare, lParam);
2123
2124 return TRUE;
2125}
2126
2127
2128/**************************************************************************
2129 * DPA_Search [COMCTL32.339]
2130 *
2131 * Searches a pointer array for a specified pointer
2132 *
2133 * PARAMS
2134 * hdpa [I] handle (pointer) to the pointer array
2135 * pFind [I] pointer to search for
2136 * nStart [I] start index
2137 * pfnCompare [I] pointer to the compare function
2138 * lParam [I] user defined value (3rd parameter of compare function)
2139 * uOptions [I] search options
2140 *
2141 * RETURNS
2142 * Success: index of the pointer in the array.
2143 * Failure: -1
2144 *
2145 * NOTES
2146 * Binary search taken from R.Sedgewick "Algorithms in C"!
2147 * Function is NOT tested!
2148 * If something goes wrong, blame HIM not ME! (Eric Kohl)
2149 */
2150
2151INT WINAPI
2152DPA_Search (const HDPA hdpa, LPVOID pFind, INT nStart,
2153 PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions)
2154{
2155 if (!hdpa || !pfnCompare || !pFind)
2156 return -1;
2157
2158 TRACE("(%p %p %d %p 0x%08lx 0x%08x)\n",
2159 hdpa, pFind, nStart, pfnCompare, lParam, uOptions);
2160
2161 if (uOptions & DPAS_SORTED) {
2162 /* array is sorted --> use binary search */
2163 INT l, r, x, n;
2164 LPVOID *lpPtr;
2165
2166 TRACE("binary search\n");
2167
2168 l = (nStart == -1) ? 0 : nStart;
2169 r = hdpa->nItemCount - 1;
2170 lpPtr = hdpa->ptrs;
2171 while (r >= l) {
2172 x = (l + r) / 2;
2173 n = (pfnCompare)(pFind, lpPtr[x], lParam);
2174 if (n < 0)
2175 r = x - 1;
2176 else
2177 l = x + 1;
2178 if (n == 0) {
2179 TRACE("-- ret=%d\n", n);
2180 return n;
2181 }
2182 }
2183
2184 if (uOptions & DPAS_INSERTBEFORE) {
2185 TRACE("-- ret=%d\n", r);
2186 return r;
2187 }
2188
2189 if (uOptions & DPAS_INSERTAFTER) {
2190 TRACE("-- ret=%d\n", l);
2191 return l;
2192 }
2193 }
2194 else {
2195 /* array is not sorted --> use linear search */
2196 LPVOID *lpPtr;
2197 INT nIndex;
2198
2199 TRACE("linear search\n");
2200
2201 nIndex = (nStart == -1)? 0 : nStart;
2202 lpPtr = hdpa->ptrs;
2203 for (; nIndex < hdpa->nItemCount; nIndex++) {
2204 if ((pfnCompare)(pFind, lpPtr[nIndex], lParam) == 0) {
2205 TRACE("-- ret=%d\n", nIndex);
2206 return nIndex;
2207 }
2208 }
2209 }
2210
2211 TRACE("-- not found: ret=-1\n");
2212 return -1;
2213}
2214
2215
2216/**************************************************************************
2217 * DPA_CreateEx [COMCTL32.340]
2218 *
2219 * Creates a dynamic pointer array using the specified size and heap.
2220 *
2221 * PARAMS
2222 * nGrow [I] number of items by which the array grows when it is filled
2223 * hHeap [I] handle to the heap where the array is stored
2224 *
2225 * RETURNS
2226 * Success: handle (pointer) to the pointer array.
2227 * Failure: NULL
2228 */
2229
2230HDPA WINAPI
2231DPA_CreateEx (INT nGrow, HANDLE hHeap)
2232{
2233 HDPA hdpa;
2234
2235 TRACE("(%d %p)\n", nGrow, hHeap);
2236
2237 if (hHeap)
2238 hdpa = (HDPA)HeapAlloc (hHeap, HEAP_ZERO_MEMORY, sizeof(DPA));
2239 else
2240 hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
2241
2242 if (hdpa) {
2243 hdpa->nGrow = min(8, nGrow);
2244 hdpa->hHeap = hHeap ? hHeap : COMCTL32_hHeap;
2245 hdpa->nMaxCount = hdpa->nGrow * 2;
2246 hdpa->ptrs =
2247 (LPVOID*)HeapAlloc (hHeap, HEAP_ZERO_MEMORY,
2248 hdpa->nMaxCount * sizeof(LPVOID));
2249 }
2250
2251 TRACE("-- %p\n", hdpa);
2252
2253 return hdpa;
2254}
2255
2256
2257/**************************************************************************
2258 * Notification functions
2259 */
2260
2261typedef struct tagNOTIFYDATA
2262{
2263 HWND hwndFrom;
2264 HWND hwndTo;
2265 DWORD dwParam3;
2266 DWORD dwParam4;
2267 DWORD dwParam5;
2268 DWORD dwParam6;
2269} NOTIFYDATA, *LPNOTIFYDATA;
2270
2271
2272/**************************************************************************
2273 * DoNotify [Internal]
2274 */
2275
2276static LRESULT
2277DoNotify (LPNOTIFYDATA lpNotify, UINT uCode, LPNMHDR lpHdr)
2278{
2279 NMHDR nmhdr;
2280 LPNMHDR lpNmh = NULL;
2281 UINT idFrom = 0;
2282
2283 TRACE("(%p %p %d %p 0x%08lx)\n",
2284 lpNotify->hwndFrom, lpNotify->hwndTo, uCode, lpHdr,
2285 lpNotify->dwParam5);
2286
2287 if (!lpNotify->hwndTo)
2288 return 0;
2289
2290 if (lpNotify->hwndFrom == (HWND)-1) {
2291 lpNmh = lpHdr;
2292 idFrom = lpHdr->idFrom;
2293 }
2294 else {
2295 if (lpNotify->hwndFrom) {
2296 HWND hwndParent = GetParent (lpNotify->hwndFrom);
2297 if (hwndParent) {
2298 hwndParent = GetWindow (lpNotify->hwndFrom, GW_OWNER);
2299 /* the following is done even if the return from above
2300 * is zero. GLA 12/2001 */
2301 idFrom = GetDlgCtrlID (lpNotify->hwndFrom);
2302 }
2303 }
2304
2305 lpNmh = (lpHdr) ? lpHdr : &nmhdr;
2306
2307 lpNmh->hwndFrom = lpNotify->hwndFrom;
2308 lpNmh->idFrom = idFrom;
2309 lpNmh->code = uCode;
2310 }
2311
2312 return SendMessageA (lpNotify->hwndTo, WM_NOTIFY, idFrom, (LPARAM)lpNmh);
2313}
2314
2315
2316/**************************************************************************
2317 * SendNotify [COMCTL32.341]
2318 *
2319 * PARAMS
2320 * hwndTo [I]
2321 * hwndFrom [I]
2322 * uCode [I]
2323 * lpHdr [I]
2324 *
2325 * RETURNS
2326 * Success: return value from notification
2327 * Failure: 0
2328 */
2329
2330LRESULT WINAPI
2331COMCTL32_SendNotify (HWND hwndTo, HWND hwndFrom,
2332 UINT uCode, LPNMHDR lpHdr)
2333{
2334 NOTIFYDATA notify;
2335
2336 TRACE("(%p %p %d %p)\n",
2337 hwndTo, hwndFrom, uCode, lpHdr);
2338
2339 notify.hwndFrom = hwndFrom;
2340 notify.hwndTo = hwndTo;
2341 notify.dwParam5 = 0;
2342 notify.dwParam6 = 0;
2343
2344 return DoNotify (&notify, uCode, lpHdr);
2345}
2346
2347
2348/**************************************************************************
2349 * SendNotifyEx [COMCTL32.342]
2350 *
2351 * PARAMS
2352 * hwndFrom [I]
2353 * hwndTo [I]
2354 * uCode [I]
2355 * lpHdr [I]
2356 * dwParam5 [I]
2357 *
2358 * RETURNS
2359 * Success: return value from notification
2360 * Failure: 0
2361 */
2362
2363LRESULT WINAPI
2364COMCTL32_SendNotifyEx (HWND hwndTo, HWND hwndFrom, UINT uCode,
2365 LPNMHDR lpHdr, DWORD dwParam5)
2366{
2367 NOTIFYDATA notify;
2368 HWND hwndNotify;
2369
2370 TRACE("(%p %p %d %p 0x%08lx)\n",
2371 hwndFrom, hwndTo, uCode, lpHdr, dwParam5);
2372
2373 hwndNotify = hwndTo;
2374 if (!hwndTo) {
2375 if (IsWindow (hwndFrom)) {
2376 hwndNotify = GetParent (hwndFrom);
2377 if (!hwndNotify)
2378 return 0;
2379 }
2380 }
2381
2382 notify.hwndFrom = hwndFrom;
2383 notify.hwndTo = hwndNotify;
2384 notify.dwParam5 = dwParam5;
2385 notify.dwParam6 = 0;
2386
2387 return DoNotify (&notify, uCode, lpHdr);
2388}
2389
2390
2391/**************************************************************************
2392 * StrChrA [COMCTL32.350]
2393 *
2394 */
2395
2396LPSTR WINAPI
2397COMCTL32_StrChrA (LPCSTR lpString, CHAR cChar)
2398{
2399 return strchr (lpString, cChar);
2400}
2401
2402
2403/**************************************************************************
2404 * StrStrIA [COMCTL32.355]
2405 */
2406
2407LPSTR WINAPI
2408COMCTL32_StrStrIA (LPCSTR lpStr1, LPCSTR lpStr2)
2409{
2410 INT len1, len2, i;
2411 CHAR first;
2412
2413 if (*lpStr2 == 0)
2414 return ((LPSTR)lpStr1);
2415 len1 = 0;
2416 while (lpStr1[len1] != 0) ++len1;
2417 len2 = 0;
2418 while (lpStr2[len2] != 0) ++len2;
2419 if (len2 == 0)
2420 return ((LPSTR)(lpStr1 + len1));
2421 first = tolower (*lpStr2);
2422 while (len1 >= len2) {
2423 if (tolower(*lpStr1) == first) {
2424 for (i = 1; i < len2; ++i)
2425 if (tolower (lpStr1[i]) != tolower(lpStr2[i]))
2426 break;
2427 if (i >= len2)
2428 return ((LPSTR)lpStr1);
2429 }
2430 ++lpStr1; --len1;
2431 }
2432 return (NULL);
2433}
2434
2435
2436/**************************************************************************
2437 * StrToIntA [COMCTL32.357] Converts a string to a signed integer.
2438 */
2439
2440INT WINAPI
2441COMCTL32_StrToIntA (LPSTR lpString)
2442{
2443 return atoi(lpString);
2444}
2445
2446/**************************************************************************
2447 * StrToIntW [COMCTL32.365] Converts a wide char string to a signed integer.
2448 */
2449
2450INT WINAPI
2451COMCTL32_StrToIntW (LPWSTR lpString)
2452{
2453 return atoiW(lpString);
2454}
2455
2456
2457/**************************************************************************
2458 * DPA_EnumCallback [COMCTL32.385]
2459 *
2460 * Enumerates all items in a dynamic pointer array.
2461 *
2462 * PARAMS
2463 * hdpa [I] handle to the dynamic pointer array
2464 * enumProc [I]
2465 * lParam [I]
2466 *
2467 * RETURNS
2468 * none
2469 */
2470
2471VOID WINAPI
2472DPA_EnumCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
2473{
2474 INT i;
2475
2476 TRACE("(%p %p %08lx)\n", hdpa, enumProc, lParam);
2477
2478 if (!hdpa)
2479 return;
2480 if (hdpa->nItemCount <= 0)
2481 return;
2482
2483 for (i = 0; i < hdpa->nItemCount; i++) {
2484 if ((enumProc)(hdpa->ptrs[i], lParam) == 0)
2485 return;
2486 }
2487
2488 return;
2489}
2490
2491
2492/**************************************************************************
2493 * DPA_DestroyCallback [COMCTL32.386]
2494 *
2495 * Enumerates all items in a dynamic pointer array and destroys it.
2496 *
2497 * PARAMS
2498 * hdpa [I] handle to the dynamic pointer array
2499 * enumProc [I]
2500 * lParam [I]
2501 *
2502 * RETURNS
2503 * Success: TRUE
2504 * Failure: FALSE
2505 */
2506
2507BOOL WINAPI
2508DPA_DestroyCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
2509{
2510 TRACE("(%p %p %08lx)\n", hdpa, enumProc, lParam);
2511
2512 DPA_EnumCallback (hdpa, enumProc, lParam);
2513
2514 return DPA_Destroy (hdpa);
2515}
2516
2517
2518/**************************************************************************
2519 * DSA_EnumCallback [COMCTL32.387]
2520 *
2521 * Enumerates all items in a dynamic storage array.
2522 *
2523 * PARAMS
2524 * hdsa [I] handle to the dynamic storage array
2525 * enumProc [I]
2526 * lParam [I]
2527 *
2528 * RETURNS
2529 * none
2530 */
2531
2532VOID WINAPI
2533DSA_EnumCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
2534{
2535 INT i;
2536
2537 TRACE("(%p %p %08lx)\n", hdsa, enumProc, lParam);
2538
2539 if (!hdsa)
2540 return;
2541 if (hdsa->nItemCount <= 0)
2542 return;
2543
2544 for (i = 0; i < hdsa->nItemCount; i++) {
2545 LPVOID lpItem = DSA_GetItemPtr (hdsa, i);
2546 if ((enumProc)(lpItem, lParam) == 0)
2547 return;
2548 }
2549
2550 return;
2551}
2552
2553
2554/**************************************************************************
2555 * DSA_DestroyCallback [COMCTL32.388]
2556 *
2557 * Enumerates all items in a dynamic storage array and destroys it.
2558 *
2559 * PARAMS
2560 * hdsa [I] handle to the dynamic storage array
2561 * enumProc [I]
2562 * lParam [I]
2563 *
2564 * RETURNS
2565 * Success: TRUE
2566 * Failure: FALSE
2567 */
2568
2569BOOL WINAPI
2570DSA_DestroyCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
2571{
2572 TRACE("(%p %p %08lx)\n", hdsa, enumProc, lParam);
2573
2574 DSA_EnumCallback (hdsa, enumProc, lParam);
2575
2576 return DSA_Destroy (hdsa);
2577}
2578
2579/**************************************************************************
2580 * StrCSpnA [COMCTL32.356]
2581 *
2582 */
2583INT WINAPI COMCTL32_StrCSpnA( LPCSTR lpStr, LPCSTR lpSet) {
2584 return strcspn(lpStr, lpSet);
2585}
2586
2587/**************************************************************************
2588 * StrChrW [COMCTL32.358]
2589 *
2590 */
2591LPWSTR WINAPI COMCTL32_StrChrW( LPCWSTR lpStart, WORD wMatch) {
2592 return strchrW(lpStart, wMatch);
2593}
2594
2595/**************************************************************************
2596 * StrCmpNA [COMCTL32.352]
2597 *
2598 */
2599INT WINAPI COMCTL32_StrCmpNA( LPCSTR lpStr1, LPCSTR lpStr2, int nChar) {
2600 return strncmp(lpStr1, lpStr2, nChar);
2601}
2602
2603/**************************************************************************
2604 * StrCmpNIA [COMCTL32.353]
2605 *
2606 */
2607INT WINAPI COMCTL32_StrCmpNIA( LPCSTR lpStr1, LPCSTR lpStr2, int nChar) {
2608 return strncasecmp(lpStr1, lpStr2, nChar);
2609}
2610
2611/**************************************************************************
2612 * StrCmpNW [COMCTL32.360]
2613 *
2614 */
2615INT WINAPI COMCTL32_StrCmpNW( LPCWSTR lpStr1, LPCWSTR lpStr2, int nChar) {
2616 return strncmpW(lpStr1, lpStr2, nChar);
2617}
2618
2619/**************************************************************************
2620 * StrCmpNIW [COMCTL32.361]
2621 *
2622 */
2623INT WINAPI COMCTL32_StrCmpNIW( LPCWSTR lpStr1, LPCWSTR lpStr2, int nChar) {
2624 FIXME("(%s, %s, %i): stub\n", debugstr_w(lpStr1), debugstr_w(lpStr2), nChar);
2625 return 0;
2626}
2627
2628/**************************************************************************
2629 * StrRChrA [COMCTL32.351]
2630 *
2631 */
2632LPSTR WINAPI COMCTL32_StrRChrA( LPCSTR lpStart, LPCSTR lpEnd, WORD wMatch )
2633{
2634 LPCSTR lpGotIt = NULL;
2635 BOOL dbcs = IsDBCSLeadByte( LOBYTE(wMatch) );
2636
2637 TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
2638
2639 if (!lpEnd) lpEnd = lpStart + strlen(lpStart);
2640
2641 for(; lpStart < lpEnd; lpStart = CharNextA(lpStart))
2642 {
2643 if (*lpStart != LOBYTE(wMatch)) continue;
2644 if (dbcs && lpStart[1] != HIBYTE(wMatch)) continue;
2645 lpGotIt = lpStart;
2646 }
2647 return (LPSTR)lpGotIt;
2648}
2649
2650
2651/**************************************************************************
2652 * StrRChrW [COMCTL32.359]
2653 *
2654 */
2655LPWSTR WINAPI COMCTL32_StrRChrW( LPCWSTR lpStart, LPCWSTR lpEnd, WORD wMatch)
2656{
2657 LPCWSTR lpGotIt = NULL;
2658
2659 TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
2660 if (!lpEnd) lpEnd = lpStart + strlenW(lpStart);
2661
2662 for(; lpStart < lpEnd; lpStart = CharNextW(lpStart))
2663 if (*lpStart == wMatch) lpGotIt = lpStart;
2664
2665 return (LPWSTR)lpGotIt;
2666}
2667
2668
2669/**************************************************************************
2670 * StrStrA [COMCTL32.354]
2671 *
2672 */
2673LPSTR WINAPI COMCTL32_StrStrA( LPCSTR lpFirst, LPCSTR lpSrch) {
2674 return strstr(lpFirst, lpSrch);
2675}
2676
2677/**************************************************************************
2678 * StrStrW [COMCTL32.362]
2679 *
2680 */
2681LPWSTR WINAPI COMCTL32_StrStrW( LPCWSTR lpFirst, LPCWSTR lpSrch) {
2682 return strstrW(lpFirst, lpSrch);
2683}
2684
2685/**************************************************************************
2686 * StrSpnW [COMCTL32.364]
2687 *
2688 */
2689INT WINAPI COMCTL32_StrSpnW( LPWSTR lpStr, LPWSTR lpSet) {
2690 LPWSTR lpLoop = lpStr;
2691
2692 /* validate ptr */
2693 if ((lpStr == 0) || (lpSet == 0)) return 0;
2694
2695/* while(*lpLoop) { if lpLoop++; } */
2696
2697 for(; (*lpLoop != 0); lpLoop++)
2698 if( strchrW(lpSet, *(WORD*)lpLoop))
2699 return (INT)(lpLoop-lpStr);
2700
2701 return (INT)(lpLoop-lpStr);
2702}
2703
2704/**************************************************************************
2705 * @ [COMCTL32.410]
2706 *
2707 * FIXME: What's this supposed to do?
2708 * Parameter 1 is an HWND, you're on your own for the rest.
2709 */
2710
2711BOOL WINAPI COMCTL32_410( HWND hw, DWORD b, DWORD c, DWORD d) {
2712
2713 FIXME("(%p, %lx, %lx, %lx): stub!\n", hw, b, c, d);
2714
2715 return TRUE;
2716}
2717
2718/**************************************************************************
2719 * @ [COMCTL32.411]
2720 *
2721 * FIXME: What's this supposed to do?
2722 * Parameter 1 is an HWND, you're on your own for the rest.
2723 */
2724
2725BOOL WINAPI COMCTL32_411( HWND hw, DWORD b, DWORD c) {
2726
2727 FIXME("(%p, %lx, %lx): stub!\n", hw, b, c);
2728
2729 return TRUE;
2730}
2731
2732/**************************************************************************
2733 * @ [COMCTL32.412]
2734 *
2735 * FIXME: What's this supposed to do?
2736 * Parameter 1 is an HWND, you're on your own for the rest.
2737 */
2738
2739BOOL WINAPI COMCTL32_412( HWND hwnd, DWORD b, DWORD c)
2740{
2741 FIXME("(%p, %lx, %lx): stub!\n", hwnd, b, c);
2742
2743 if (IsWindow (hwnd) == FALSE)
2744 return FALSE;
2745
2746 if (b == 0)
2747 return FALSE;
2748
2749
2750 return TRUE;
2751}
2752
2753/**************************************************************************
2754 * @ [COMCTL32.413]
2755 *
2756 * FIXME: What's this supposed to do?
2757 * Parameter 1 is an HWND, you're on your own for the rest.
2758 */
2759
2760BOOL WINAPI COMCTL32_413( HWND hw, DWORD b, DWORD c, DWORD d) {
2761
2762 FIXME("(%p, %lx, %lx, %lx): stub!\n", hw, b, c, d);
2763
2764 return TRUE;
2765}
2766
2767
2768/**************************************************************************
2769 * @ [COMCTL32.415]
2770 *
2771 * FIXME: What's this supposed to do?
2772 * Parameter 1 is an HWND, you're on your own for the rest.
2773 */
2774
2775BOOL WINAPI COMCTL32_415( HWND hwnd, DWORD b, DWORD c, DWORD d, DWORD e)
2776{
2777
2778 FIXME("(%p, %lx, %lx, %lx, %lx): stub!\n", hwnd, b, c, d, e);
2779
2780 return TRUE;
2781}
2782
2783/**************************************************************************
2784 * @ [COMCTL32.417]
2785 *
2786 */
2787BOOL WINAPI COMCTL32_417(HDC hdc, INT x, INT y, UINT flags, const RECT *lprect,
2788 LPCWSTR str, UINT count, const INT *lpDx)
2789{
2790 return ExtTextOutW(hdc, x, y, flags, lprect, str, count, lpDx);
2791}
2792
2793/**************************************************************************
2794 * @ [COMCTL32.419]
2795 *
2796 * FIXME: What's this supposed to do?
2797 */
2798
2799BOOL WINAPI COMCTL32_419( DWORD a, DWORD b, DWORD c, DWORD d)
2800{
2801
2802 FIXME("(%lx, %lx, %lx, %lx): stub!\n", a, b, c, d);
2803
2804 return TRUE;
2805}
Note: See TracBrowser for help on using the repository browser.