blob: 9560b3a2d6a99100472b76d298b297cec714b327 [file] [log] [blame]
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001/*
2 * Cursor and icon support
3 *
4 * Copyright 1995 Alexandre Julliard
Alexandre Julliard77b99181997-09-14 17:17:23 +00005 * 1996 Martin Von Loewis
6 * 1997 Alex Korobka
Turchanov Sergey62d6e981998-10-18 13:42:55 +00007 * 1998 Turchanov Sergey
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00008 */
9
10/*
11 * Theory:
12 *
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000013 * http://www.microsoft.com/win32dev/ui/icons.htm
14 *
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000015 * Cursors and icons are stored in a global heap block, with the
16 * following layout:
17 *
18 * CURSORICONINFO info;
19 * BYTE[] ANDbits;
20 * BYTE[] XORbits;
21 *
22 * The bits structures are in the format of a device-dependent bitmap.
23 *
24 * This layout is very sub-optimal, as the bitmap bits are stored in
25 * the X client instead of in the server like other bitmaps; however,
26 * some programs (notably Paint Brush) expect to be able to manipulate
27 * the bits directly :-(
Turchanov Sergey62d6e981998-10-18 13:42:55 +000028 *
29 * FIXME: what are we going to do with animation and color (bpp > 1) cursors ?!
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000030 */
31
32#include <string.h>
33#include <stdlib.h>
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +000034
Jeremy Whited3e22d92000-02-10 19:03:02 +000035#include "windef.h"
36#include "wingdi.h"
Marcus Meissner61afa331999-02-22 10:16:00 +000037#include "wine/winbase16.h"
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +000038#include "wine/winuser16.h"
Alexandre Julliard77b99181997-09-14 17:17:23 +000039#include "heap.h"
Alexandre Julliard5ab9d862000-08-09 22:35:05 +000040#include "palette.h"
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000041#include "bitmap.h"
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000042#include "cursoricon.h"
Turchanov Sergey62d6e981998-10-18 13:42:55 +000043#include "global.h"
Alexandre Julliard77b99181997-09-14 17:17:23 +000044#include "module.h"
Alexandre Julliard06c275a1999-05-02 14:32:27 +000045#include "debugtools.h"
Alexandre Julliardade697e1995-11-26 13:59:11 +000046#include "task.h"
Alexandre Julliard44ed71f1997-12-21 19:17:50 +000047#include "user.h"
Ulrich Weiganda11ce321998-11-08 12:27:26 +000048#include "input.h"
Ulrich Weigand431d1a01998-11-14 18:57:47 +000049#include "message.h"
Alexandre Julliardf90efa91998-06-14 15:24:15 +000050#include "winerror.h"
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000051
Alexandre Julliardb52aed42000-03-24 21:40:30 +000052DECLARE_DEBUG_CHANNEL(cursor);
53DECLARE_DEBUG_CHANNEL(icon);
54DECLARE_DEBUG_CHANNEL(resource);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000055
Alexandre Julliarda3960291999-02-26 11:11:13 +000056static HCURSOR hActiveCursor = 0; /* Active cursor */
57static INT CURSOR_ShowCount = 0; /* Cursor display count */
58static RECT CURSOR_ClipRect; /* Cursor clipping rect */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000059
Ulrich Weigand50a09151999-03-10 14:00:29 +000060
61/**********************************************************************
62 * ICONCACHE for cursors/icons loaded with LR_SHARED.
63 *
64 * FIXME: This should not be allocated on the system heap, but on a
65 * subsystem-global heap (i.e. one for all Win16 processes,
66 * and one each for every Win32 process).
67 */
68typedef struct tagICONCACHE
69{
70 struct tagICONCACHE *next;
71
72 HMODULE hModule;
73 HRSRC hRsrc;
Pierre Mageau4ac8db71999-09-04 11:16:48 +000074 HRSRC hGroupRsrc;
Ulrich Weigand50a09151999-03-10 14:00:29 +000075 HANDLE handle;
76
77 INT count;
78
79} ICONCACHE;
80
81static ICONCACHE *IconAnchor = NULL;
Alexandre Julliard227a0892000-04-08 21:06:06 +000082static CRITICAL_SECTION IconCrst = CRITICAL_SECTION_INIT;
Dave Hawkesdbb6ab22000-07-09 12:16:58 +000083static WORD ICON_HOTSPOT = 0x4242;
Ulrich Weigand50a09151999-03-10 14:00:29 +000084
85/**********************************************************************
Ulrich Weigand50a09151999-03-10 14:00:29 +000086 * CURSORICON_FindSharedIcon
87 */
88static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
89{
90 HANDLE handle = 0;
91 ICONCACHE *ptr;
92
93 EnterCriticalSection( &IconCrst );
94
95 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
96 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
97 {
98 ptr->count++;
99 handle = ptr->handle;
100 break;
101 }
102
103 LeaveCriticalSection( &IconCrst );
104
105 return handle;
106}
107
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000108/*************************************************************************
109 * CURSORICON_FindCache
110 *
111 * Given a handle, find the coresponding cache element
112 *
113 * PARAMS
114 * Handle [I] handle to an Image
115 *
116 * RETURNS
117 * Success: The cache entry
118 * Failure: NULL
119 *
120 */
121static ICONCACHE* CURSORICON_FindCache(HANDLE handle)
122{
123 ICONCACHE *ptr;
124 ICONCACHE *pRet=NULL;
125 BOOL IsFound = FALSE;
126 int count;
127
128 EnterCriticalSection( &IconCrst );
129
130 for (count = 0, ptr = IconAnchor; ptr != NULL && !IsFound; ptr = ptr->next, count++ )
131 {
132 if ( handle == ptr->handle )
133 {
134 IsFound = TRUE;
135 pRet = ptr;
136 }
137 }
138
139 LeaveCriticalSection( &IconCrst );
140
141 return pRet;
142}
143
Ulrich Weigand50a09151999-03-10 14:00:29 +0000144/**********************************************************************
145 * CURSORICON_AddSharedIcon
146 */
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000147static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle )
Ulrich Weigand50a09151999-03-10 14:00:29 +0000148{
149 ICONCACHE *ptr = HeapAlloc( SystemHeap, 0, sizeof(ICONCACHE) );
150 if ( !ptr ) return;
151
152 ptr->hModule = hModule;
153 ptr->hRsrc = hRsrc;
154 ptr->handle = handle;
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000155 ptr->hGroupRsrc = hGroupRsrc;
Ulrich Weigand50a09151999-03-10 14:00:29 +0000156 ptr->count = 1;
157
158 EnterCriticalSection( &IconCrst );
159 ptr->next = IconAnchor;
160 IconAnchor = ptr;
161 LeaveCriticalSection( &IconCrst );
162}
163
164/**********************************************************************
165 * CURSORICON_DelSharedIcon
166 */
167static INT CURSORICON_DelSharedIcon( HANDLE handle )
168{
169 INT count = -1;
170 ICONCACHE *ptr;
171
172 EnterCriticalSection( &IconCrst );
173
174 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
175 if ( ptr->handle == handle )
176 {
177 if ( ptr->count > 0 ) ptr->count--;
178 count = ptr->count;
179 break;
180 }
181
182 LeaveCriticalSection( &IconCrst );
183
184 return count;
185}
186
187/**********************************************************************
188 * CURSORICON_FreeModuleIcons
189 */
190void CURSORICON_FreeModuleIcons( HMODULE hModule )
191{
192 ICONCACHE **ptr = &IconAnchor;
193
194 if ( HIWORD( hModule ) )
195 hModule = MapHModuleLS( hModule );
196 else
197 hModule = GetExePtr( hModule );
198
199 EnterCriticalSection( &IconCrst );
200
201 while ( *ptr )
202 {
203 if ( (*ptr)->hModule == hModule )
204 {
205 ICONCACHE *freePtr = *ptr;
206 *ptr = freePtr->next;
207
208 GlobalFree16( freePtr->handle );
209 HeapFree( SystemHeap, 0, freePtr );
210 continue;
211 }
212 ptr = &(*ptr)->next;
213 }
214
215 LeaveCriticalSection( &IconCrst );
216}
217
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000218/**********************************************************************
219 * CURSORICON_FindBestIcon
220 *
221 * Find the icon closest to the requested size and number of colors.
222 */
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000223static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000224 int height, int colors )
225{
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000226 int i;
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000227 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000228 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
229 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000230
231 if (dir->idCount < 1)
232 {
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000233 WARN_(icon)("Empty directory!\n" );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000234 return NULL;
235 }
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000236 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000237
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000238 /* Find Best Fit */
239 iTotalDiff = 0xFFFFFFFF;
240 iColorDiff = 0xFFFFFFFF;
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000241 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000242 {
243 iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
244 iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
245
246 if(iTotalDiff > (iTempXDiff + iTempYDiff))
247 {
248 iXDiff = iTempXDiff;
249 iYDiff = iTempYDiff;
250 iTotalDiff = iXDiff + iYDiff;
251 }
252 }
253
254 /* Find Best Colors for Best Fit */
255 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
256 {
257 if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
258 abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
259 {
260 iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
261 if(iColorDiff > iTempColorDiff)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000262 {
263 bestEntry = entry;
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000264 iColorDiff = iTempColorDiff;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000265 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000266 }
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000267 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000268
269 return bestEntry;
270}
271
272
273/**********************************************************************
274 * CURSORICON_FindBestCursor
275 *
276 * Find the cursor closest to the requested size.
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000277 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
278 * ignored too
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000279 */
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000280static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000281 int width, int height, int color)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000282{
283 int i, maxwidth, maxheight;
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000284 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000285
286 if (dir->idCount < 1)
287 {
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000288 WARN_(cursor)("Empty directory!\n" );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000289 return NULL;
290 }
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000291 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000292
Steve Tibbett85692c81999-08-15 16:35:21 +0000293 /* Double height to account for AND and XOR masks */
294
295 height *= 2;
296
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000297 /* First find the largest one smaller than or equal to the requested size*/
298
299 maxwidth = maxheight = 0;
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000300 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
301 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
302 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000303 (entry->wBitCount == 1))
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000304 {
305 bestEntry = entry;
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000306 maxwidth = entry->ResInfo.cursor.wWidth;
307 maxheight = entry->ResInfo.cursor.wHeight;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000308 }
309 if (bestEntry) return bestEntry;
310
311 /* Now find the smallest one larger than the requested size */
312
313 maxwidth = maxheight = 255;
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000314 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
315 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000316 (entry->wBitCount == 1))
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000317 {
318 bestEntry = entry;
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000319 maxwidth = entry->ResInfo.cursor.wWidth;
320 maxheight = entry->ResInfo.cursor.wHeight;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000321 }
322
323 return bestEntry;
324}
325
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000326/*********************************************************************
327 * The main purpose of this function is to create fake resource directory
328 * and fake resource entries. There are several reasons for this:
329 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
330 * fields
331 * There are some "bad" cursor files which do not have
332 * bColorCount initialized but instead one must read this info
333 * directly from corresponding DIB sections
334 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
335 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000336BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000337 CURSORICONDIR **res, LPBYTE **ptr)
338{
339 LPBYTE _free;
340 CURSORICONFILEDIR *bits;
341 int entries, size, i;
342
343 *res = NULL;
344 *ptr = NULL;
345 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
Juergen Schmied4493a741998-11-30 17:29:28 +0000346
347 /* FIXME: test for inimated icons
348 * hack to load the first icon from the *.ani file
349 */
350 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
351 { LPBYTE pos = (LPBYTE) bits;
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000352 FIXME_(cursor)("Animated icons not correctly implemented! %p \n", bits);
Juergen Schmied4493a741998-11-30 17:29:28 +0000353
354 for (;;)
355 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000356 { FIXME_(cursor)("icon entry found! %p\n", bits);
Juergen Schmied4493a741998-11-30 17:29:28 +0000357 pos+=4;
358 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
359 { goto fail;
360 }
Juergen Schmiedcb2e4d31999-09-19 18:56:40 +0000361 bits=(CURSORICONFILEDIR*)(pos+4);
362 FIXME_(cursor)("icon size ok. offset=%p \n", bits);
Juergen Schmied4493a741998-11-30 17:29:28 +0000363 break;
364 }
365 pos+=2;
366 if (pos>=(LPBYTE)bits+766) goto fail;
367 }
368 }
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000369 if (!(entries = bits->idCount)) goto fail;
Patrik Stridvalla9a671d1999-04-25 19:01:52 +0000370 size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) * (entries - 1);
371 _free = (LPBYTE) size;
372
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000373 for (i=0; i < entries; i++)
374 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
375
376 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
377 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
378 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
379
380 _free = (LPBYTE)(*res) + (int)_free;
381 memcpy((*res), bits, 6);
382 for (i=0; i<entries; i++)
383 {
384 ((LPBYTE*)(*ptr))[i] = _free;
385 if (fCursor) {
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000386 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
387 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000388 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
389 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
390 _free+=sizeof(POINT16);
391 } else {
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000392 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
393 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
394 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000395 }
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000396 (*res)->idEntries[i].wPlanes=1;
397 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
398 bits->idEntries[i].dwDIBOffset))->biBitCount;
399 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
400 (*res)->idEntries[i].wResId=i+1;
401
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000402 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000403 (*res)->idEntries[i].dwBytesInRes);
404 _free += (*res)->idEntries[i].dwBytesInRes;
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000405 }
406 UnmapViewOfFile( bits );
407 return TRUE;
408fail:
409 if (*res) HeapFree( GetProcessHeap(), 0, *res );
410 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
411 UnmapViewOfFile( bits );
412 return FALSE;
413}
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000414
Alexandre Julliard77b99181997-09-14 17:17:23 +0000415
416/**********************************************************************
417 * CURSORICON_CreateFromResource
418 *
419 * Create a cursor or icon from in-memory resource template.
420 *
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000421 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
Alexandre Julliard77b99181997-09-14 17:17:23 +0000422 * with cbSize parameter as well.
423 */
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000424static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
Alexandre Julliarda3960291999-02-26 11:11:13 +0000425 UINT cbSize, BOOL bIcon, DWORD dwVersion,
426 INT width, INT height, UINT loadflags )
Alexandre Julliard77b99181997-09-14 17:17:23 +0000427{
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000428 int sizeAnd, sizeXor;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000429 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
Alexandre Julliardb0efe282000-08-04 04:18:04 +0000430 BITMAP bmpXor, bmpAnd;
Patrik Stridvalle92331f1999-09-20 18:52:06 +0000431 POINT16 hotspot;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000432 BITMAPINFO *bmi;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000433 HDC hdc;
434 BOOL DoStretch;
435 INT size;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000436
Patrik Stridvalle92331f1999-09-20 18:52:06 +0000437 hotspot.x = ICON_HOTSPOT;
438 hotspot.y = ICON_HOTSPOT;
439
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000440 TRACE_(cursor)("%08x (%u bytes), ver %08x, %ix%i %s %s\n",
Alexandre Julliard77b99181997-09-14 17:17:23 +0000441 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000442 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
Alexandre Julliard77b99181997-09-14 17:17:23 +0000443 if (dwVersion == 0x00020000)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000444 {
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000445 FIXME_(cursor)("\t2.xx resources are not supported\n");
Alexandre Julliard77b99181997-09-14 17:17:23 +0000446 return 0;
447 }
448
449 if (bIcon)
450 bmi = (BITMAPINFO *)bits;
451 else /* get the hotspot */
452 {
453 POINT16 *pt = (POINT16 *)bits;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000454 hotspot = *pt;
455 bmi = (BITMAPINFO *)(pt + 1);
456 }
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000457 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
458
459 if (!width) width = bmi->bmiHeader.biWidth;
460 if (!height) height = bmi->bmiHeader.biHeight/2;
461 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
462 (bmi->bmiHeader.biWidth != width);
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000463
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000464 /* Check bitmap header */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000465
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000466 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
467 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
468 bmi->bmiHeader.biCompression != BI_RGB) )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000469 {
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000470 WARN_(cursor)("\tinvalid resource bitmap header.\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000471 return 0;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000472 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000473
Alexandre Julliarda3960291999-02-26 11:11:13 +0000474 if( (hdc = GetDC( 0 )) )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000475 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000476 BITMAPINFO* pInfo;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000477
478 /* Make sure we have room for the monochrome bitmap later on.
479 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
480 * up to and including the biBitCount. In-memory icon resource
481 * format is as follows:
482 *
483 * BITMAPINFOHEADER icHeader // DIB header
484 * RGBQUAD icColors[] // Color table
485 * BYTE icXOR[] // DIB bits for XOR mask
486 * BYTE icAND[] // DIB bits for AND mask
487 */
488
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000489 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000490 max(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000491 {
492 memcpy( pInfo, bmi, size );
493 pInfo->bmiHeader.biHeight /= 2;
494
495 /* Create the XOR bitmap */
496
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000497 if (DoStretch) {
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000498 if(bIcon)
499 {
500 hXorBits = CreateCompatibleBitmap(hdc, width, height);
501 }
502 else
503 {
504 hXorBits = CreateBitmap(width, height, 1, 1, NULL);
505 }
506 if(hXorBits)
507 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000508 HBITMAP hOld;
509 HDC hMem = CreateCompatibleDC(hdc);
510 BOOL res;
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000511
512 if (hMem) {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000513 hOld = SelectObject(hMem, hXorBits);
514 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000515 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
516 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000517 SelectObject(hMem, hOld);
518 DeleteDC(hMem);
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000519 } else res = FALSE;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000520 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000521 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000522 } else hXorBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000523 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000524 if( hXorBits )
525 {
Marcus Meissner64c86ffe2000-08-07 04:16:43 +0000526 char* xbits = (char *)bmi + size +
Huw D M Davies608629b1999-04-18 12:07:00 +0000527 DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
528 bmi->bmiHeader.biHeight,
529 bmi->bmiHeader.biBitCount) / 2;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000530
531 pInfo->bmiHeader.biBitCount = 1;
532 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
533 {
534 RGBQUAD *rgb = pInfo->bmiColors;
535
536 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
537 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
538 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
539 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
540 }
541 else
542 {
543 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
544
545 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
546 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
547 }
548
549 /* Create the AND bitmap */
550
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000551 if (DoStretch) {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000552 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
553 HBITMAP hOld;
554 HDC hMem = CreateCompatibleDC(hdc);
555 BOOL res;
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000556
557 if (hMem) {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000558 hOld = SelectObject(hMem, hAndBits);
559 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000560 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
Marcus Meissner64c86ffe2000-08-07 04:16:43 +0000561 xbits, pInfo, DIB_RGB_COLORS, SRCCOPY);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000562 SelectObject(hMem, hOld);
563 DeleteDC(hMem);
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000564 } else res = FALSE;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000565 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000566 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000567 } else hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
Marcus Meissner64c86ffe2000-08-07 04:16:43 +0000568 CBM_INIT, xbits, pInfo, DIB_RGB_COLORS );
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000569
Alexandre Julliarda3960291999-02-26 11:11:13 +0000570 if( !hAndBits ) DeleteObject( hXorBits );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000571 }
572 HeapFree( GetProcessHeap(), 0, pInfo );
573 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000574 ReleaseDC( 0, hdc );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000575 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000576
577 if( !hXorBits || !hAndBits )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000578 {
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000579 WARN_(cursor)("\tunable to create an icon bitmap.\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000580 return 0;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000581 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000582
583 /* Now create the CURSORICONINFO structure */
Alexandre Julliardb0efe282000-08-04 04:18:04 +0000584 GetObjectA( hXorBits, sizeof(bmpXor), &bmpXor );
585 GetObjectA( hAndBits, sizeof(bmpAnd), &bmpAnd );
586 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
587 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000588
Alexandre Julliard77b99181997-09-14 17:17:23 +0000589 if (hObj) hObj = GlobalReAlloc16( hObj,
590 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
591 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
592 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
593 if (hObj)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000594 {
Alexandre Julliard77b99181997-09-14 17:17:23 +0000595 CURSORICONINFO *info;
596
597 /* Make it owned by the module */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000598 if (hInstance) FarSetOwner16( hObj, GetExePtr(hInstance) );
Alexandre Julliard77b99181997-09-14 17:17:23 +0000599
600 info = (CURSORICONINFO *)GlobalLock16( hObj );
601 info->ptHotSpot.x = hotspot.x;
602 info->ptHotSpot.y = hotspot.y;
Alexandre Julliardb0efe282000-08-04 04:18:04 +0000603 info->nWidth = bmpXor.bmWidth;
604 info->nHeight = bmpXor.bmHeight;
605 info->nWidthBytes = bmpXor.bmWidthBytes;
606 info->bPlanes = bmpXor.bmPlanes;
607 info->bBitsPerPixel = bmpXor.bmBitsPixel;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000608
609 /* Transfer the bitmap bits to the CURSORICONINFO structure */
610
Alexandre Julliarda3960291999-02-26 11:11:13 +0000611 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
612 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
Alexandre Julliard77b99181997-09-14 17:17:23 +0000613 GlobalUnlock16( hObj );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000614 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000615
Alexandre Julliarda3960291999-02-26 11:11:13 +0000616 DeleteObject( hAndBits );
Alexandre Julliard2a2321b2000-08-19 21:38:55 +0000617 DeleteObject( hXorBits );
Alexandre Julliard77b99181997-09-14 17:17:23 +0000618 return hObj;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000619}
620
Alexandre Julliard77b99181997-09-14 17:17:23 +0000621
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000622/**********************************************************************
Alexandre Julliard77b99181997-09-14 17:17:23 +0000623 * CreateIconFromResourceEx16 (USER.450)
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000624 *
Alexandre Julliard77b99181997-09-14 17:17:23 +0000625 * FIXME: not sure about exact parameter types
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000626 */
Alexandre Julliard77b99181997-09-14 17:17:23 +0000627HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
628 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000629{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000630 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000631 width, height, cFlag);
Alexandre Julliard77b99181997-09-14 17:17:23 +0000632}
633
634
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000635/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000636 * CreateIconFromResource (USER32.76)
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000637 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000638HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
639 BOOL bIcon, DWORD dwVersion)
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000640{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000641 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000642}
643
644
Alexandre Julliard77b99181997-09-14 17:17:23 +0000645/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000646 * CreateIconFromResourceEx (USER32.77)
Alexandre Julliard77b99181997-09-14 17:17:23 +0000647 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000648HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
649 BOOL bIcon, DWORD dwVersion,
650 INT width, INT height,
651 UINT cFlag )
Alexandre Julliard77b99181997-09-14 17:17:23 +0000652{
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000653 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
654 if( pTask )
655 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
656 width, height, cFlag );
657 return 0;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000658}
659
Alexandre Julliard77b99181997-09-14 17:17:23 +0000660/**********************************************************************
Ulrich Weigand50a09151999-03-10 14:00:29 +0000661 * CURSORICON_Load
Alexandre Julliard77b99181997-09-14 17:17:23 +0000662 *
Ulrich Weigand50a09151999-03-10 14:00:29 +0000663 * Load a cursor or icon from resource or file.
Alexandre Julliard77b99181997-09-14 17:17:23 +0000664 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000665HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
Ulrich Weigand50a09151999-03-10 14:00:29 +0000666 INT width, INT height, INT colors,
667 BOOL fCursor, UINT loadflags )
Alexandre Julliard77b99181997-09-14 17:17:23 +0000668{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000669 HANDLE handle = 0, h = 0;
670 HANDLE hRsrc;
Ulrich Weigand50a09151999-03-10 14:00:29 +0000671 CURSORICONDIR *dir;
672 CURSORICONDIRENTRY *dirEntry;
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000673 LPBYTE bits;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000674
Ulrich Weigand50a09151999-03-10 14:00:29 +0000675 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
Alexandre Julliard77b99181997-09-14 17:17:23 +0000676 {
Ulrich Weigand50a09151999-03-10 14:00:29 +0000677 LPBYTE *ptr;
678 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
679 return 0;
680 if (fCursor)
681 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
682 else
683 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000684 bits = ptr[dirEntry->wResId-1];
685 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
Ulrich Weigand50a09151999-03-10 14:00:29 +0000686 !fCursor, 0x00030000, width, height, loadflags);
687 HeapFree( GetProcessHeap(), 0, dir );
688 HeapFree( GetProcessHeap(), 0, ptr );
689 }
Huw D M Daviesd6a91b71998-12-02 10:29:04 +0000690
Ulrich Weigand50a09151999-03-10 14:00:29 +0000691 else if ( !hInstance ) /* Load OEM cursor/icon */
692 {
693 WORD resid;
Ulrich Weigand50a09151999-03-10 14:00:29 +0000694
695 if ( HIWORD(name) )
696 {
697 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
698 if( ansi[0]=='#') /*Check for '#xxx' name */
Alexandre Julliard77b99181997-09-14 17:17:23 +0000699 {
Ulrich Weigand50a09151999-03-10 14:00:29 +0000700 resid = atoi(ansi+1);
701 HeapFree( GetProcessHeap(), 0, ansi );
Alexandre Julliard77b99181997-09-14 17:17:23 +0000702 }
Ulrich Weigand50a09151999-03-10 14:00:29 +0000703 else
704 {
705 HeapFree( GetProcessHeap(), 0, ansi );
706 return 0;
707 }
Alexandre Julliard77b99181997-09-14 17:17:23 +0000708 }
Ulrich Weigand50a09151999-03-10 14:00:29 +0000709 else resid = LOWORD(name);
Alexandre Julliard42d20f92000-08-10 01:16:19 +0000710 h = USER_Driver.pLoadOEMResource( resid, fCursor ? OEM_CURSOR : OEM_ICON );
Ulrich Weigand50a09151999-03-10 14:00:29 +0000711 }
712
713 else /* Load from resource */
714 {
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000715 HANDLE hGroupRsrc;
Ulrich Weigand50a09151999-03-10 14:00:29 +0000716 WORD wResId;
717 DWORD dwBytesInRes;
718
719 /* Normalize hInstance (must be uniquely represented for icon cache) */
720
721 if ( HIWORD( hInstance ) )
722 hInstance = MapHModuleLS( hInstance );
723 else
724 hInstance = GetExePtr( hInstance );
725
726 /* Get directory resource ID */
727
728 if (!(hRsrc = FindResourceW( hInstance, name,
729 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
730 return 0;
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000731 hGroupRsrc = hRsrc;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000732
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000733 /* Find the best entry in the directory */
Alexandre Julliard77b99181997-09-14 17:17:23 +0000734
Ulrich Weigand50a09151999-03-10 14:00:29 +0000735 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
736 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
737 if (fCursor)
738 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
739 width, height, 1);
740 else
741 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
742 width, height, colors );
743 if (!dirEntry) return 0;
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000744 wResId = dirEntry->wResId;
745 dwBytesInRes = dirEntry->dwBytesInRes;
Ulrich Weigand50a09151999-03-10 14:00:29 +0000746 FreeResource( handle );
747
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000748 /* Load the resource */
Alexandre Julliard77b99181997-09-14 17:17:23 +0000749
Ulrich Weigand50a09151999-03-10 14:00:29 +0000750 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
Alexandre Julliarda3960291999-02-26 11:11:13 +0000751 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
Alexandre Julliardb4c68722000-06-08 00:39:16 +0000752
753 /* If shared icon, check whether it was already loaded */
754 if ( (loadflags & LR_SHARED)
755 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
756 return h;
757
Alexandre Julliarda3960291999-02-26 11:11:13 +0000758 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000759 bits = (LPBYTE)LockResource( handle );
Ulrich Weigand50a09151999-03-10 14:00:29 +0000760 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000761 !fCursor, 0x00030000, width, height, loadflags);
Ulrich Weigand50a09151999-03-10 14:00:29 +0000762 FreeResource( handle );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000763
Ulrich Weigand50a09151999-03-10 14:00:29 +0000764 /* If shared icon, add to icon cache */
765
766 if ( h && (loadflags & LR_SHARED) )
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000767 CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, h );
Ulrich Weigand50a09151999-03-10 14:00:29 +0000768 }
769
770 return h;
771}
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000772
773/***********************************************************************
774 * CURSORICON_Copy
775 *
776 * Make a copy of a cursor or icon.
777 */
Alexandre Julliardbf9130a1996-10-13 17:45:47 +0000778static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000779{
780 char *ptrOld, *ptrNew;
781 int size;
Alexandre Julliardbf9130a1996-10-13 17:45:47 +0000782 HGLOBAL16 hNew;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000783
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000784 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000785 if (!(hInstance = GetExePtr( hInstance ))) return 0;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000786 size = GlobalSize16( handle );
787 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000788 FarSetOwner16( hNew, hInstance );
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000789 ptrNew = (char *)GlobalLock16( hNew );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000790 memcpy( ptrNew, ptrOld, size );
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000791 GlobalUnlock16( handle );
792 GlobalUnlock16( hNew );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000793 return hNew;
794}
795
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000796/*************************************************************************
797 * CURSORICON_ExtCopy
798 *
799 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified
800 *
801 * PARAMS
802 * Handle [I] handle to an Image
803 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)
804 * iDesiredCX [I] The Desired width of the Image
805 * iDesiredCY [I] The desired height of the Image
806 * nFlags [I] The flags from CopyImage
807 *
808 * RETURNS
809 * Success: The new handle of the Image
810 *
811 * NOTES
812 * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented.
813 * LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource.
814 * LR_COPYFROMRESOURCE will only work if the Image is in the Cache.
815 *
816 *
817 */
818
819HGLOBAL CURSORICON_ExtCopy(HGLOBAL Handle, UINT nType,
820 INT iDesiredCX, INT iDesiredCY,
821 UINT nFlags)
822{
823 HGLOBAL16 hNew=0;
824
825 TRACE_(icon)("Handle %u, uType %u, iDesiredCX %i, iDesiredCY %i, nFlags %u\n",
826 Handle, nType, iDesiredCX, iDesiredCY, nFlags);
827
828 if(Handle == 0)
829 {
830 return 0;
831 }
832
833 /* Best Fit or Monochrome */
834 if( (nFlags & LR_COPYFROMRESOURCE
835 && (iDesiredCX > 0 || iDesiredCY > 0))
836 || nFlags & LR_MONOCHROME)
837 {
838 ICONCACHE* pIconCache = CURSORICON_FindCache(Handle);
839
840 /* Not Found in Cache, then do a strait copy
841 */
842 if(pIconCache == NULL)
843 {
844 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
845 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
846 if(nFlags & LR_COPYFROMRESOURCE)
847 {
848 TRACE_(icon)("LR_COPYFROMRESOURCE: Failed to load from cache\n");
849 }
850 }
851 else
852 {
Juergen Schmied44016842000-02-25 20:52:01 +0000853 int iTargetCY = iDesiredCY, iTargetCX = iDesiredCX;
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000854 LPBYTE pBits;
855 HANDLE hMem;
856 HRSRC hRsrc;
857 DWORD dwBytesInRes;
858 WORD wResId;
859 CURSORICONDIR *pDir;
860 CURSORICONDIRENTRY *pDirEntry;
861 BOOL bIsIcon = (nType == IMAGE_ICON);
862
863 /* Completing iDesiredCX CY for Monochrome Bitmaps if needed
864 */
865 if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE))
866 || (iDesiredCX == 0 && iDesiredCY == 0))
867 {
868 iDesiredCY = GetSystemMetrics(bIsIcon ?
869 SM_CYICON : SM_CYCURSOR);
870 iDesiredCX = GetSystemMetrics(bIsIcon ?
871 SM_CXICON : SM_CXCURSOR);
872 }
873
874 /* Retreive the CURSORICONDIRENTRY
875 */
876 if (!(hMem = LoadResource( pIconCache->hModule ,
877 pIconCache->hGroupRsrc)))
878 {
879 return 0;
880 }
881 if (!(pDir = (CURSORICONDIR*)LockResource( hMem )))
882 {
883 return 0;
884 }
885
886 /* Find Best Fit
887 */
888 if(bIsIcon)
889 {
890 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(
891 pDir, iDesiredCX, iDesiredCY, 256);
892 }
893 else
894 {
895 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(
896 pDir, iDesiredCX, iDesiredCY, 1);
897 }
898
899 wResId = pDirEntry->wResId;
900 dwBytesInRes = pDirEntry->dwBytesInRes;
901 FreeResource(hMem);
902
903 TRACE_(icon)("ResID %u, BytesInRes %lu, Width %d, Height %d DX %d, DY %d\n",
904 wResId, dwBytesInRes, pDirEntry->ResInfo.icon.bWidth,
905 pDirEntry->ResInfo.icon.bHeight, iDesiredCX, iDesiredCY);
906
907 /* Get the Best Fit
908 */
909 if (!(hRsrc = FindResourceW(pIconCache->hModule ,
910 MAKEINTRESOURCEW(wResId), bIsIcon ? RT_ICONW : RT_CURSORW)))
911 {
912 return 0;
913 }
914 if (!(hMem = LoadResource( pIconCache->hModule , hRsrc )))
915 {
916 return 0;
917 }
918
919 pBits = (LPBYTE)LockResource( hMem );
920
Juergen Schmied44016842000-02-25 20:52:01 +0000921 if(nFlags & LR_DEFAULTSIZE)
922 {
923 iTargetCY = GetSystemMetrics(SM_CYICON);
924 iTargetCX = GetSystemMetrics(SM_CXICON);
925 }
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000926
927 /* Create a New Icon with the proper dimension
928 */
929 hNew = CURSORICON_CreateFromResource( 0, 0, pBits, dwBytesInRes,
930 bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
931 FreeResource(hMem);
932 }
933 }
934 else
935 {
936 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
937 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
938 }
939 return hNew;
940}
941
Alexandre Julliardade697e1995-11-26 13:59:11 +0000942/***********************************************************************
943 * CURSORICON_IconToCursor
944 *
Alexandre Julliard77b99181997-09-14 17:17:23 +0000945 * Converts bitmap to mono and truncates if icon is too large (should
946 * probably do StretchBlt() instead).
Alexandre Julliardade697e1995-11-26 13:59:11 +0000947 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000948HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
Alexandre Julliardade697e1995-11-26 13:59:11 +0000949{
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000950 HCURSOR16 hRet = 0;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000951 CURSORICONINFO *pIcon = NULL;
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000952 HTASK16 hTask = GetCurrentTask();
953 TDB* pTask = (TDB *)GlobalLock16(hTask);
Alexandre Julliardade697e1995-11-26 13:59:11 +0000954
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000955 if(hIcon && pTask)
Alexandre Julliard77b99181997-09-14 17:17:23 +0000956 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
957 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
Francis Beaudet699900b1999-09-05 12:15:49 +0000958 {
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000959 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
Francis Beaudet699900b1999-09-05 12:15:49 +0000960
961
962 pIcon = GlobalLock16(hRet);
963
964 pIcon->ptHotSpot.x = pIcon->ptHotSpot.y = 15;
965
Serge Ivanov15f86462000-03-04 19:07:08 +0000966 GlobalUnlock16(hRet);
Francis Beaudet699900b1999-09-05 12:15:49 +0000967 }
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000968 else
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000969 {
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000970 BYTE pAndBits[128];
971 BYTE pXorBits[128];
Alexandre Julliard77b99181997-09-14 17:17:23 +0000972 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
973 BYTE* psPtr, *pxbPtr = pXorBits;
974 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000975 BYTE* pbc = NULL;
976
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000977 CURSORICONINFO cI;
978
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000979 TRACE_(icon)("[%04x] %ix%i %ibpp (bogus %ibps)\n",
Alexandre Julliard77b99181997-09-14 17:17:23 +0000980 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
981
Huw D M Davies82617361998-11-01 16:35:42 +0000982 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
983 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
Alexandre Julliard77b99181997-09-14 17:17:23 +0000984 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
985
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000986 memset(pXorBits, 0, 128);
987 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
988 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
989 cI.nWidth = 32; cI.nHeight = 32;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000990 cI.nWidthBytes = 4; /* 32x1bpp */
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000991
Alexandre Julliard77b99181997-09-14 17:17:23 +0000992 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
993 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000994
Alexandre Julliard77b99181997-09-14 17:17:23 +0000995 for( iy = 0; iy < maxy; iy++ )
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000996 {
Alexandre Julliard77b99181997-09-14 17:17:23 +0000997 unsigned shift = iy % 2;
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000998
Alexandre Julliard77b99181997-09-14 17:17:23 +0000999 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
1000 (and_width > 4) ? 4 : and_width );
1001 for( ix = 0; ix < maxx; ix++ )
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001002 {
1003 if( bSemiTransparent && ((ix+shift)%2) )
1004 {
Alexandre Julliard77b99181997-09-14 17:17:23 +00001005 /* set AND bit, XOR bit stays 0 */
1006
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001007 pbc = pAndBits + iy * 4 + ix/8;
1008 *pbc |= 0x80 >> (ix%8);
1009 }
1010 else
1011 {
Alexandre Julliard77b99181997-09-14 17:17:23 +00001012 /* keep AND bit, set XOR bit */
1013
1014 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
1015 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +00001016 if(!PALETTE_Driver->pIsDark(val))
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001017 {
1018 pbc = pxbPtr + ix/8;
1019 *pbc |= 0x80 >> (ix%8);
1020 }
1021 }
1022 }
Alexandre Julliard77b99181997-09-14 17:17:23 +00001023 psPtr += xor_width;
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001024 pxbPtr += 4;
1025 }
Alexandre Julliard77b99181997-09-14 17:17:23 +00001026
Alexandre Julliarda3960291999-02-26 11:11:13 +00001027 hRet = CreateCursorIconIndirect16( pTask->hInstance , &cI, pAndBits, pXorBits);
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001028
1029 if( !hRet ) /* fall back on default drag cursor */
1030 hRet = CURSORICON_Copy( pTask->hInstance ,
Ulrich Weigand50a09151999-03-10 14:00:29 +00001031 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
Marcus Meissnerddca3151999-05-22 11:33:23 +00001032 GetSystemMetrics(SM_CXCURSOR),
1033 GetSystemMetrics(SM_CYCURSOR), 1, TRUE, 0) );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001034 }
Alexandre Julliardade697e1995-11-26 13:59:11 +00001035
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001036 return hRet;
Alexandre Julliardade697e1995-11-26 13:59:11 +00001037}
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001038
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001039
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001040/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001041 * LoadCursor16 (USER.173)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001042 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001043HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001044{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001045 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1046 return LoadCursorA( hInstance, nameStr );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001047}
1048
1049
1050/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001051 * LoadIcon16 (USER.174)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001052 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001053HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001054{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001055 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1056 return LoadIconA( hInstance, nameStr );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001057}
1058
1059
1060/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001061 * CreateCursor16 (USER.406)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001062 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001063HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
1064 INT16 xHotSpot, INT16 yHotSpot,
1065 INT16 nWidth, INT16 nHeight,
1066 LPCVOID lpANDbits, LPCVOID lpXORbits )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001067{
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001068 CURSORICONINFO info;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001069
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001070 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001071 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001072
1073 info.ptHotSpot.x = xHotSpot;
1074 info.ptHotSpot.y = yHotSpot;
1075 info.nWidth = nWidth;
1076 info.nHeight = nHeight;
1077 info.nWidthBytes = 0;
1078 info.bPlanes = 1;
1079 info.bBitsPerPixel = 1;
1080
Alexandre Julliarda3960291999-02-26 11:11:13 +00001081 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001082}
1083
1084
1085/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001086 * CreateCursor (USER32.67)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001087 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001088HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
1089 INT xHotSpot, INT yHotSpot,
1090 INT nWidth, INT nHeight,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001091 LPCVOID lpANDbits, LPCVOID lpXORbits )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001092{
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001093 CURSORICONINFO info;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001094
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001095 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001096 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001097
1098 info.ptHotSpot.x = xHotSpot;
1099 info.ptHotSpot.y = yHotSpot;
1100 info.nWidth = nWidth;
1101 info.nHeight = nHeight;
1102 info.nWidthBytes = 0;
1103 info.bPlanes = 1;
1104 info.bBitsPerPixel = 1;
1105
Alexandre Julliarda3960291999-02-26 11:11:13 +00001106 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001107}
1108
1109
1110/***********************************************************************
1111 * CreateIcon16 (USER.407)
1112 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001113HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
1114 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
1115 LPCVOID lpANDbits, LPCVOID lpXORbits )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001116{
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001117 CURSORICONINFO info;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001118
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001119 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001120 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001121
Francis Beaudet699900b1999-09-05 12:15:49 +00001122 info.ptHotSpot.x = ICON_HOTSPOT;
1123 info.ptHotSpot.y = ICON_HOTSPOT;
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001124 info.nWidth = nWidth;
1125 info.nHeight = nHeight;
1126 info.nWidthBytes = 0;
1127 info.bPlanes = bPlanes;
1128 info.bBitsPerPixel = bBitsPixel;
1129
Alexandre Julliarda3960291999-02-26 11:11:13 +00001130 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001131}
1132
1133
1134/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001135 * CreateIcon (USER32.75)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001136 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001137HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
1138 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001139 LPCVOID lpANDbits, LPCVOID lpXORbits )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001140{
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001141 CURSORICONINFO info;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001142
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001143 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001144 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001145
Francis Beaudet699900b1999-09-05 12:15:49 +00001146 info.ptHotSpot.x = ICON_HOTSPOT;
1147 info.ptHotSpot.y = ICON_HOTSPOT;
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001148 info.nWidth = nWidth;
1149 info.nHeight = nHeight;
1150 info.nWidthBytes = 0;
1151 info.bPlanes = bPlanes;
1152 info.bBitsPerPixel = bBitsPixel;
1153
Alexandre Julliarda3960291999-02-26 11:11:13 +00001154 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001155}
1156
1157
1158/***********************************************************************
1159 * CreateCursorIconIndirect (USER.408)
1160 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001161HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001162 CURSORICONINFO *info,
1163 LPCVOID lpANDbits,
1164 LPCVOID lpXORbits )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001165{
Alexandre Julliardbf9130a1996-10-13 17:45:47 +00001166 HGLOBAL16 handle;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001167 char *ptr;
1168 int sizeAnd, sizeXor;
1169
1170 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001171 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
Huw D M Davies82617361998-11-01 16:35:42 +00001172 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001173 sizeXor = info->nHeight * info->nWidthBytes;
Huw D M Davies82617361998-11-01 16:35:42 +00001174 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001175 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001176 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1177 return 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001178 if (hInstance) FarSetOwner16( handle, hInstance );
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001179 ptr = (char *)GlobalLock16( handle );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001180 memcpy( ptr, info, sizeof(*info) );
1181 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1182 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001183 GlobalUnlock16( handle );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001184 return handle;
1185}
1186
1187
1188/***********************************************************************
Alexandre Julliardca22b331996-07-12 19:02:39 +00001189 * CopyIcon16 (USER.368)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001190 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001191HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001192{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001193 TRACE_(icon)("%04x %04x\n", hInstance, hIcon );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001194 return CURSORICON_Copy( hInstance, hIcon );
1195}
1196
1197
1198/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001199 * CopyIcon (USER32.60)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001200 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001201HICON WINAPI CopyIcon( HICON hIcon )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001202{
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001203 HTASK16 hTask = GetCurrentTask ();
1204 TDB* pTask = (TDB *) GlobalLock16 (hTask);
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001205 TRACE_(icon)("%04x\n", hIcon );
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001206 return CURSORICON_Copy( pTask->hInstance, hIcon );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001207}
Alexandre Julliardca22b331996-07-12 19:02:39 +00001208
1209
1210/***********************************************************************
1211 * CopyCursor16 (USER.369)
1212 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001213HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001214{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001215 TRACE_(cursor)("%04x %04x\n", hInstance, hCursor );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001216 return CURSORICON_Copy( hInstance, hCursor );
1217}
1218
Ulrich Weigand50a09151999-03-10 14:00:29 +00001219/**********************************************************************
1220 * CURSORICON_Destroy (USER.610)
1221 *
1222 * This routine is actually exported from Win95 USER under the name
1223 * DestroyIcon32 ... The behaviour implemented here should mimic
1224 * the Win95 one exactly, especially the return values, which
1225 * depend on the setting of various flags.
1226 */
Marcus Meissnerc600afb1999-03-24 14:55:37 +00001227WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
Ulrich Weigand50a09151999-03-10 14:00:29 +00001228{
1229 WORD retv;
1230
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001231 TRACE_(icon)("(%04x, %04x)\n", handle, flags );
Ulrich Weigand50a09151999-03-10 14:00:29 +00001232
1233 /* Check whether destroying active cursor */
1234
1235 if ( hActiveCursor == handle )
1236 {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001237 ERR_(cursor)("Destroying active cursor!\n" );
Ulrich Weigand50a09151999-03-10 14:00:29 +00001238 SetCursor( 0 );
1239 }
1240
1241 /* Try shared cursor/icon first */
1242
1243 if ( !(flags & CID_NONSHARED) )
1244 {
1245 INT count = CURSORICON_DelSharedIcon( handle );
1246
1247 if ( count != -1 )
1248 return (flags & CID_WIN32)? TRUE : (count == 0);
1249
1250 /* FIXME: OEM cursors/icons should be recognized */
1251 }
1252
1253 /* Now assume non-shared cursor/icon */
1254
1255 retv = GlobalFree16( handle );
1256 return (flags & CID_RESOURCE)? retv : TRUE;
1257}
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001258
1259/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001260 * DestroyIcon16 (USER.457)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001261 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001262BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001263{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001264 return CURSORICON_Destroy( hIcon, 0 );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001265}
1266
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001267/***********************************************************************
Ulrich Weigand50a09151999-03-10 14:00:29 +00001268 * DestroyIcon (USER32.133)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001269 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001270BOOL WINAPI DestroyIcon( HICON hIcon )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001271{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001272 return CURSORICON_Destroy( hIcon, CID_WIN32 );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001273}
1274
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001275/***********************************************************************
Ulrich Weigand50a09151999-03-10 14:00:29 +00001276 * DestroyCursor16 (USER.458)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001277 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001278BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001279{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001280 return CURSORICON_Destroy( hCursor, 0 );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001281}
1282
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001283/***********************************************************************
Ulrich Weigand50a09151999-03-10 14:00:29 +00001284 * DestroyCursor (USER32.132)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001285 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001286BOOL WINAPI DestroyCursor( HCURSOR hCursor )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001287{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001288 return CURSORICON_Destroy( hCursor, CID_WIN32 );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001289}
1290
1291
1292/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001293 * DrawIcon16 (USER.84)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001294 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001295BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001296{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001297 return DrawIcon( hdc, x, y, hIcon );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001298}
1299
1300
1301/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001302 * DrawIcon (USER32.159)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001303 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001304BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001305{
1306 CURSORICONINFO *ptr;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001307 HDC hMemDC;
1308 HBITMAP hXorBits, hAndBits;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001309 COLORREF oldFg, oldBg;
1310
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001311 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001312 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1313 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
Alexandre Julliard21979011997-03-05 08:22:35 +00001314 (char *)(ptr+1) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001315 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
Alexandre Julliard21979011997-03-05 08:22:35 +00001316 ptr->bBitsPerPixel, (char *)(ptr + 1)
Huw D M Davies82617361998-11-01 16:35:42 +00001317 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001318 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1319 oldBg = SetBkColor( hdc, RGB(255,255,255) );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001320
1321 if (hXorBits && hAndBits)
1322 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001323 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1324 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1325 SelectObject( hMemDC, hXorBits );
1326 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1327 SelectObject( hMemDC, hBitTemp );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001328 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001329 DeleteDC( hMemDC );
1330 if (hXorBits) DeleteObject( hXorBits );
1331 if (hAndBits) DeleteObject( hAndBits );
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001332 GlobalUnlock16( hIcon );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001333 SetTextColor( hdc, oldFg );
1334 SetBkColor( hdc, oldBg );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001335 return TRUE;
1336}
1337
1338
1339/***********************************************************************
Andreas Mohr1f0c2162000-06-24 12:54:00 +00001340 * IconSize16 (USER.86)
1341 *
1342 * See "Undocumented Windows". Used by W2.0 paint.exe.
1343 */
1344DWORD WINAPI IconSize16( void )
1345{
1346 return MAKELONG(GetSystemMetrics(SM_CYICON), GetSystemMetrics(SM_CXICON));
1347}
1348
1349
1350/***********************************************************************
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001351 * DumpIcon (USER.459)
1352 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001353DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001354 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001355{
Alexandre Julliardade697e1995-11-26 13:59:11 +00001356 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001357 int sizeAnd, sizeXor;
1358
1359 if (!info) return 0;
1360 sizeXor = info->nHeight * info->nWidthBytes;
Huw D M Davies82617361998-11-01 16:35:42 +00001361 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
Alexandre Julliardade697e1995-11-26 13:59:11 +00001362 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1363 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001364 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1365 return MAKELONG( sizeXor, sizeXor );
1366}
1367
1368
1369/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001370 * SetCursor16 (USER.69)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001371 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001372HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001373{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001374 return (HCURSOR16)SetCursor( hCursor );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001375}
1376
1377
1378/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001379 * SetCursor (USER32.472)
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001380 * RETURNS:
1381 * A handle to the previous cursor shape.
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001382 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001383HCURSOR WINAPI SetCursor(
1384 HCURSOR hCursor /* Handle of cursor to show */
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001385) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001386 HCURSOR hOldCursor;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001387
1388 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001389 TRACE_(cursor)("%04x\n", hCursor );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001390 hOldCursor = hActiveCursor;
1391 hActiveCursor = hCursor;
1392 /* Change the cursor shape only if it is visible */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001393 if (CURSOR_ShowCount >= 0)
Alexandre Julliard03468f71998-02-15 19:40:49 +00001394 {
Alexandre Julliard42d20f92000-08-10 01:16:19 +00001395 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
Ulrich Weigand431d1a01998-11-14 18:57:47 +00001396 GlobalUnlock16( hActiveCursor );
Alexandre Julliard03468f71998-02-15 19:40:49 +00001397 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001398 return hOldCursor;
1399}
1400
1401
1402/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001403 * SetCursorPos16 (USER.70)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001404 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001405void WINAPI SetCursorPos16( INT16 x, INT16 y )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001406{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001407 SetCursorPos( x, y );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001408}
1409
1410
1411/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001412 * SetCursorPos (USER32.474)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001413 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001414BOOL WINAPI SetCursorPos( INT x, INT y )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001415{
Alexandre Julliard42d20f92000-08-10 01:16:19 +00001416 USER_Driver.pMoveCursor( x, y );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001417 return TRUE;
1418}
1419
1420
1421/***********************************************************************
1422 * ShowCursor16 (USER.71)
1423 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001424INT16 WINAPI ShowCursor16( BOOL16 bShow )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001425{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001426 return ShowCursor( bShow );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001427}
1428
1429
1430/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001431 * ShowCursor (USER32.530)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001432 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001433INT WINAPI ShowCursor( BOOL bShow )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001434{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001435 TRACE_(cursor)("%d, count=%d\n",
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001436 bShow, CURSOR_ShowCount );
1437
1438 if (bShow)
1439 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001440 if (++CURSOR_ShowCount == 0) /* Show it */
Ulrich Weigand431d1a01998-11-14 18:57:47 +00001441 {
Alexandre Julliard42d20f92000-08-10 01:16:19 +00001442 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
Ulrich Weigand431d1a01998-11-14 18:57:47 +00001443 GlobalUnlock16( hActiveCursor );
1444 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001445 }
1446 else
1447 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001448 if (--CURSOR_ShowCount == -1) /* Hide it */
Alexandre Julliard42d20f92000-08-10 01:16:19 +00001449 USER_Driver.pSetCursor( NULL );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001450 }
1451 return CURSOR_ShowCount;
1452}
1453
1454
1455/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001456 * GetCursor16 (USER.247)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001457 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001458HCURSOR16 WINAPI GetCursor16(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001459{
1460 return hActiveCursor;
1461}
1462
1463
1464/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001465 * GetCursor (USER32.227)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001466 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001467HCURSOR WINAPI GetCursor(void)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001468{
1469 return hActiveCursor;
1470}
1471
1472
1473/***********************************************************************
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001474 * ClipCursor16 (USER.16)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001475 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001476BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001477{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001478 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001479 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001480 return TRUE;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001481}
1482
1483
1484/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001485 * ClipCursor (USER32.53)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001486 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001487BOOL WINAPI ClipCursor( const RECT *rect )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001488{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001489 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1490 else CopyRect( &CURSOR_ClipRect, rect );
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001491 return TRUE;
1492}
1493
1494
1495/***********************************************************************
1496 * GetCursorPos16 (USER.17)
1497 */
Paul Quinnf8db63b1999-02-09 14:24:45 +00001498BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001499{
Paul Quinnf8db63b1999-02-09 14:24:45 +00001500 if (!pt) return 0;
Lionel Ulmeracc74671999-11-07 21:25:57 +00001501
1502 pt->x = PosX;
1503 pt->y = PosY;
1504
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001505 TRACE_(cursor)("ret=%d,%d\n", pt->x, pt->y );
Paul Quinnf8db63b1999-02-09 14:24:45 +00001506 return 1;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001507}
1508
1509
1510/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001511 * GetCursorPos (USER32.229)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001512 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001513BOOL WINAPI GetCursorPos( POINT *pt )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001514{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001515 BOOL ret;
Paul Quinnf8db63b1999-02-09 14:24:45 +00001516
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001517 POINT16 pt16;
Paul Quinnf8db63b1999-02-09 14:24:45 +00001518 ret = GetCursorPos16( &pt16 );
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001519 if (pt) CONV_POINT16TO32( &pt16, pt );
Paul Quinnf8db63b1999-02-09 14:24:45 +00001520 return ((pt) ? ret : 0);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001521}
1522
1523
1524/***********************************************************************
1525 * GetClipCursor16 (USER.309)
1526 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001527void WINAPI GetClipCursor16( RECT16 *rect )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001528{
1529 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1530}
1531
1532
1533/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001534 * GetClipCursor (USER32.221)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001535 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001536BOOL WINAPI GetClipCursor( RECT *rect )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001537{
Eric Pouechb9544f11999-02-14 14:09:42 +00001538 if (rect)
1539 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001540 CopyRect( rect, &CURSOR_ClipRect );
Eric Pouechb9544f11999-02-14 14:09:42 +00001541 return TRUE;
1542 }
1543 return FALSE;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001544}
1545
Alexandre Julliard77b99181997-09-14 17:17:23 +00001546/**********************************************************************
1547 * LookupIconIdFromDirectoryEx16 (USER.364)
1548 *
1549 * FIXME: exact parameter sizes
1550 */
Alexandre Julliarde658d821997-11-30 17:45:40 +00001551INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
Alexandre Julliard77b99181997-09-14 17:17:23 +00001552 INT16 width, INT16 height, UINT16 cFlag )
1553{
Alexandre Julliarde658d821997-11-30 17:45:40 +00001554 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
Alexandre Julliard77b99181997-09-14 17:17:23 +00001555 UINT16 retVal = 0;
1556 if( dir && !dir->idReserved && (dir->idType & 3) )
1557 {
Juergen Schmiedc45bbee1999-04-11 11:46:32 +00001558 CURSORICONDIRENTRY* entry;
Pavel Roskin5b14b531999-04-18 09:34:51 +00001559 HDC hdc;
1560 UINT palEnts;
1561 int colors;
1562 hdc = GetDC(0);
1563 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1564 if (palEnts == 0)
1565 palEnts = 256;
1566 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
Juergen Schmiedc45bbee1999-04-11 11:46:32 +00001567
Alexandre Julliarda3960291999-02-26 11:11:13 +00001568 ReleaseDC(0, hdc);
Huw D M Daviesa38d84d1998-11-30 11:18:26 +00001569
Alexandre Julliard77b99181997-09-14 17:17:23 +00001570 if( bIcon )
Alexandre Julliard77b99181997-09-14 17:17:23 +00001571 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001572 else
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001573 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
Juergen Schmiedc45bbee1999-04-11 11:46:32 +00001574
1575 if( entry ) retVal = entry->wResId;
Alexandre Julliard77b99181997-09-14 17:17:23 +00001576 }
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001577 else WARN_(cursor)("invalid resource directory\n");
Alexandre Julliard77b99181997-09-14 17:17:23 +00001578 return retVal;
1579}
1580
1581/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001582 * LookupIconIdFromDirectoryEx (USER32.380)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001583 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001584INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1585 INT width, INT height, UINT cFlag )
Alexandre Julliard77b99181997-09-14 17:17:23 +00001586{
1587 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1588}
1589
1590/**********************************************************************
Alexandre Julliarde658d821997-11-30 17:45:40 +00001591 * LookupIconIdFromDirectory (USER.???)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001592 */
Alexandre Julliarde658d821997-11-30 17:45:40 +00001593INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
Alexandre Julliard77b99181997-09-14 17:17:23 +00001594{
1595 return LookupIconIdFromDirectoryEx16( dir, bIcon,
Marcus Meissnerddca3151999-05-22 11:33:23 +00001596 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1597 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001598}
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001599
1600/**********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001601 * LookupIconIdFromDirectory (USER32.379)
Alexandre Julliarde658d821997-11-30 17:45:40 +00001602 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001603INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
Alexandre Julliarde658d821997-11-30 17:45:40 +00001604{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001605 return LookupIconIdFromDirectoryEx( dir, bIcon,
Marcus Meissnerddca3151999-05-22 11:33:23 +00001606 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1607 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
Alexandre Julliarde658d821997-11-30 17:45:40 +00001608}
1609
1610/**********************************************************************
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001611 * GetIconID (USER.455)
1612 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001613WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001614{
Alexandre Julliarde658d821997-11-30 17:45:40 +00001615 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001616
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001617 TRACE_(cursor)("hRes=%04x, entries=%i\n",
Alexandre Julliarde658d821997-11-30 17:45:40 +00001618 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001619
1620 switch(resType)
1621 {
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001622 case RT_CURSOR16:
Alexandre Julliard77b99181997-09-14 17:17:23 +00001623 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
Marcus Meissnerddca3151999-05-22 11:33:23 +00001624 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001625 case RT_ICON16:
Alexandre Julliard77b99181997-09-14 17:17:23 +00001626 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
Marcus Meissnerddca3151999-05-22 11:33:23 +00001627 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0 );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001628 default:
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001629 WARN_(cursor)("invalid res type %ld\n", resType );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001630 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001631 return 0;
1632}
1633
Alexandre Julliard77b99181997-09-14 17:17:23 +00001634/**********************************************************************
1635 * LoadCursorIconHandler (USER.336)
1636 *
1637 * Supposed to load resources of Windows 2.x applications.
1638 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001639HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
Alexandre Julliard77b99181997-09-14 17:17:23 +00001640{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001641 FIXME_(cursor)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
Alexandre Julliard54c27111998-03-29 19:44:57 +00001642 hResource, hModule, hRsrc);
Alexandre Julliard77b99181997-09-14 17:17:23 +00001643 return (HGLOBAL16)0;
1644}
1645
1646/**********************************************************************
1647 * LoadDIBIconHandler (USER.357)
1648 *
1649 * RT_ICON resource loader, installed by USER_SignalProc when module
1650 * is initialized.
1651 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001652HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
Alexandre Julliard77b99181997-09-14 17:17:23 +00001653{
1654 /* If hResource is zero we must allocate a new memory block, if it's
1655 * non-zero but GlobalLock() returns NULL then it was discarded and
1656 * we have to recommit some memory, otherwise we just need to check
1657 * the block size. See LoadProc() in 16-bit SDK for more.
1658 */
1659
Ulrich Weigand50a09151999-03-10 14:00:29 +00001660 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001661 if( hMemObj )
1662 {
1663 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1664 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1665 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
Marcus Meissnerddca3151999-05-22 11:33:23 +00001666 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001667 }
1668 return hMemObj;
1669}
1670
1671/**********************************************************************
1672 * LoadDIBCursorHandler (USER.356)
1673 *
1674 * RT_CURSOR resource loader. Same as above.
1675 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001676HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
Alexandre Julliard77b99181997-09-14 17:17:23 +00001677{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001678 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001679 if( hMemObj )
1680 {
1681 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1682 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1683 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
Marcus Meissnerddca3151999-05-22 11:33:23 +00001684 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001685 }
1686 return hMemObj;
1687}
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001688
1689/**********************************************************************
1690 * LoadIconHandler (USER.456)
1691 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001692HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001693{
Alexandre Julliard77b99181997-09-14 17:17:23 +00001694 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1695
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001696 TRACE_(cursor)("hRes=%04x\n",hResource);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001697
Alexandre Julliard77b99181997-09-14 17:17:23 +00001698 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1699 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1700}
1701
1702/***********************************************************************
Ulrich Weigand50a09151999-03-10 14:00:29 +00001703 * LoadCursorW (USER32.362)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001704 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001705HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001706{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001707 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1708 LR_SHARED | LR_DEFAULTSIZE );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001709}
1710
1711/***********************************************************************
Ulrich Weigand50a09151999-03-10 14:00:29 +00001712 * LoadCursorA (USER32.359)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001713 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001714HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001715{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001716 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1717 LR_SHARED | LR_DEFAULTSIZE );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00001718}
Alexandre Julliard77b99181997-09-14 17:17:23 +00001719
1720/***********************************************************************
Ulrich Weigand50a09151999-03-10 14:00:29 +00001721* LoadCursorFromFileW (USER32.361)
1722*/
1723HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1724{
1725 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1726 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1727}
1728
1729/***********************************************************************
1730* LoadCursorFromFileA (USER32.360)
Alexandre Julliardf90efa91998-06-14 15:24:15 +00001731*/
Alexandre Julliarda3960291999-02-26 11:11:13 +00001732HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001733{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001734 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1735 LR_LOADFROMFILE | LR_DEFAULTSIZE );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00001736}
1737
1738/***********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001739 * LoadIconW (USER32.364)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001740 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001741HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001742{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001743 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1744 LR_SHARED | LR_DEFAULTSIZE );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001745}
1746
1747/***********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001748 * LoadIconA (USER32.363)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001749 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001750HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001751{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001752 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1753 LR_SHARED | LR_DEFAULTSIZE );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001754}
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001755
1756/**********************************************************************
Andreas Mohr22c904d1999-01-26 14:56:01 +00001757 * GetIconInfo16 (USER.395)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001758 */
Marcus Meissnerffb912e1999-01-28 09:14:38 +00001759BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
Andreas Mohr22c904d1999-01-26 14:56:01 +00001760{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001761 ICONINFO ii32;
1762 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
Marcus Meissnerffb912e1999-01-28 09:14:38 +00001763
1764 iconinfo->fIcon = ii32.fIcon;
1765 iconinfo->xHotspot = ii32.xHotspot;
1766 iconinfo->yHotspot = ii32.yHotspot;
1767 iconinfo->hbmMask = ii32.hbmMask;
1768 iconinfo->hbmColor = ii32.hbmColor;
1769 return ret;
Andreas Mohr22c904d1999-01-26 14:56:01 +00001770}
1771
1772/**********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001773 * GetIconInfo (USER32.242)
Andreas Mohr22c904d1999-01-26 14:56:01 +00001774 */
Francois Gouget67c96912000-10-12 23:18:55 +00001775BOOL WINAPI GetIconInfo(HICON hIcon,PICONINFO iconinfo) {
Alexandre Julliard491502b1997-11-01 19:08:16 +00001776 CURSORICONINFO *ciconinfo;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001777
Alexandre Julliard491502b1997-11-01 19:08:16 +00001778 ciconinfo = GlobalLock16(hIcon);
1779 if (!ciconinfo)
1780 return FALSE;
Francis Beaudet699900b1999-09-05 12:15:49 +00001781
1782 if ( (ciconinfo->ptHotSpot.x == ICON_HOTSPOT) &&
1783 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT) )
1784 {
1785 iconinfo->fIcon = TRUE;
Dave Hawkesdbb6ab22000-07-09 12:16:58 +00001786 iconinfo->xHotspot = ciconinfo->nWidth / 2;
1787 iconinfo->yHotspot = ciconinfo->nHeight / 2;
Francis Beaudet699900b1999-09-05 12:15:49 +00001788 }
1789 else
1790 {
1791 iconinfo->fIcon = FALSE;
1792 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1793 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1794 }
Alexandre Julliard829fe321998-07-26 14:27:39 +00001795
Alexandre Julliarda3960291999-02-26 11:11:13 +00001796 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
Alexandre Julliard829fe321998-07-26 14:27:39 +00001797 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1798 (char *)(ciconinfo + 1)
1799 + ciconinfo->nHeight *
Huw D M Davies82617361998-11-01 16:35:42 +00001800 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001801 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
Alexandre Julliard829fe321998-07-26 14:27:39 +00001802 1, 1, (char *)(ciconinfo + 1));
1803
1804 GlobalUnlock16(hIcon);
1805
Alexandre Julliard491502b1997-11-01 19:08:16 +00001806 return TRUE;
1807}
1808
1809/**********************************************************************
1810 * CreateIconIndirect (USER32.78)
1811 */
Francois Gouget67c96912000-10-12 23:18:55 +00001812HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001813{
1814 BITMAP bmpXor,bmpAnd;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001815 HICON hObj;
Alexandre Julliard491502b1997-11-01 19:08:16 +00001816 int sizeXor,sizeAnd;
1817
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001818 GetObjectA( iconinfo->hbmColor, sizeof(bmpXor), &bmpXor );
1819 GetObjectA( iconinfo->hbmMask, sizeof(bmpAnd), &bmpAnd );
Alexandre Julliard491502b1997-11-01 19:08:16 +00001820
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001821 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
1822 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
Alexandre Julliard491502b1997-11-01 19:08:16 +00001823
1824 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1825 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1826 if (hObj)
1827 {
1828 CURSORICONINFO *info;
1829
1830 info = (CURSORICONINFO *)GlobalLock16( hObj );
Francis Beaudet699900b1999-09-05 12:15:49 +00001831
1832 /* If we are creating an icon, the hotspot is unused */
1833 if (iconinfo->fIcon)
1834 {
1835 info->ptHotSpot.x = ICON_HOTSPOT;
1836 info->ptHotSpot.y = ICON_HOTSPOT;
1837 }
1838 else
1839 {
1840 info->ptHotSpot.x = iconinfo->xHotspot;
1841 info->ptHotSpot.y = iconinfo->yHotspot;
1842 }
1843
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001844 info->nWidth = bmpXor.bmWidth;
1845 info->nHeight = bmpXor.bmHeight;
1846 info->nWidthBytes = bmpXor.bmWidthBytes;
1847 info->bPlanes = bmpXor.bmPlanes;
1848 info->bBitsPerPixel = bmpXor.bmBitsPixel;
Alexandre Julliard491502b1997-11-01 19:08:16 +00001849
1850 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1851
Alexandre Julliarda3960291999-02-26 11:11:13 +00001852 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1853 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
Alexandre Julliard491502b1997-11-01 19:08:16 +00001854 GlobalUnlock16( hObj );
1855 }
1856 return hObj;
1857}
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001858
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001859
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001860/**********************************************************************
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001861 *
1862 DrawIconEx16 (USER.394)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001863 */
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001864BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1865 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1866 HBRUSH16 hbr, UINT16 flags)
1867{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001868 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001869 istep, hbr, flags);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001870}
1871
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001872
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001873/******************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001874 * DrawIconEx [USER32.160] Draws an icon or cursor on device context
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001875 *
1876 * NOTES
1877 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1878 *
1879 * PARAMS
1880 * hdc [I] Handle to device context
1881 * x0 [I] X coordinate of upper left corner
1882 * y0 [I] Y coordinate of upper left corner
1883 * hIcon [I] Handle to icon to draw
1884 * cxWidth [I] Width of icon
1885 * cyWidth [I] Height of icon
1886 * istep [I] Index of frame in animated cursor
1887 * hbr [I] Handle to background brush
1888 * flags [I] Icon-drawing flags
1889 *
1890 * RETURNS
1891 * Success: TRUE
1892 * Failure: FALSE
1893 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001894BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1895 INT cxWidth, INT cyWidth, UINT istep,
1896 HBRUSH hbr, UINT flags )
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001897{
1898 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001899 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
Alexandre Julliard2a2321b2000-08-19 21:38:55 +00001900 BOOL result = FALSE, DoOffscreen;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001901 HBITMAP hB_off = 0, hOld = 0;
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001902
1903 if (!ptr) return FALSE;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001904
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001905 if (istep)
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001906 FIXME_(icon)("Ignoring istep=%d\n", istep);
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001907 if (flags & DI_COMPAT)
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001908 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001909
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001910 /* Calculate the size of the destination image. */
1911 if (cxWidth == 0)
Jesper Skov5c3e4571998-11-01 19:27:22 +00001912 {
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001913 if (flags & DI_DEFAULTSIZE)
Alexandre Julliarda3960291999-02-26 11:11:13 +00001914 cxWidth = GetSystemMetrics (SM_CXICON);
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001915 else
1916 cxWidth = ptr->nWidth;
Jesper Skov5c3e4571998-11-01 19:27:22 +00001917 }
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001918 if (cyWidth == 0)
Jesper Skov5c3e4571998-11-01 19:27:22 +00001919 {
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001920 if (flags & DI_DEFAULTSIZE)
Alexandre Julliarda3960291999-02-26 11:11:13 +00001921 cyWidth = GetSystemMetrics (SM_CYICON);
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001922 else
1923 cyWidth = ptr->nHeight;
Jesper Skov5c3e4571998-11-01 19:27:22 +00001924 }
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001925
Alexandre Julliard2a2321b2000-08-19 21:38:55 +00001926 DoOffscreen = (GetObjectType( hbr ) == OBJ_BRUSH);
1927
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001928 if (DoOffscreen) {
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001929 RECT r;
1930
1931 r.left = 0;
1932 r.top = 0;
1933 r.right = cxWidth;
1934 r.bottom = cxWidth;
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001935
Alexandre Julliarda3960291999-02-26 11:11:13 +00001936 hDC_off = CreateCompatibleDC(hdc);
1937 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001938 if (hDC_off && hB_off) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001939 hOld = SelectObject(hDC_off, hB_off);
1940 FillRect(hDC_off, &r, hbr);
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001941 }
Alexandre Julliard2a2321b2000-08-19 21:38:55 +00001942 }
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001943
1944 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001945 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001946 HBITMAP hXorBits, hAndBits;
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001947 COLORREF oldFg, oldBg;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001948 INT nStretchMode;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001949
Alexandre Julliarda3960291999-02-26 11:11:13 +00001950 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001951
Alexandre Julliarda3960291999-02-26 11:11:13 +00001952 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001953 ptr->bPlanes, ptr->bBitsPerPixel,
1954 (char *)(ptr + 1)
1955 + ptr->nHeight *
Huw D M Davies82617361998-11-01 16:35:42 +00001956 BITMAP_GetWidthBytes(ptr->nWidth,1) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001957 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001958 1, 1, (char *)(ptr+1) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001959 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1960 oldBg = SetBkColor( hdc, RGB(255,255,255) );
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001961
1962 if (hXorBits && hAndBits)
1963 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001964 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001965 if (flags & DI_MASK)
Jesper Skov5c3e4571998-11-01 19:27:22 +00001966 {
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001967 if (DoOffscreen)
Alexandre Julliarda3960291999-02-26 11:11:13 +00001968 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001969 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1970 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001971 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001972 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
Jesper Skov5c3e4571998-11-01 19:27:22 +00001973 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001974 SelectObject( hMemDC, hXorBits );
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001975 if (flags & DI_IMAGE)
Jesper Skov5c3e4571998-11-01 19:27:22 +00001976 {
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001977 if (DoOffscreen)
Alexandre Julliarda3960291999-02-26 11:11:13 +00001978 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001979 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1980 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001981 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
Eric Kohl1b1bf2b1998-10-11 13:10:08 +00001982 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
Jesper Skov5c3e4571998-11-01 19:27:22 +00001983 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001984 SelectObject( hMemDC, hBitTemp );
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001985 result = TRUE;
1986 }
1987
Alexandre Julliarda3960291999-02-26 11:11:13 +00001988 SetTextColor( hdc, oldFg );
1989 SetBkColor( hdc, oldBg );
1990 if (hXorBits) DeleteObject( hXorBits );
1991 if (hAndBits) DeleteObject( hAndBits );
1992 SetStretchBltMode (hdc, nStretchMode);
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001993 if (DoOffscreen) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001994 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
1995 SelectObject(hDC_off, hOld);
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001996 }
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001997 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001998 if (hMemDC) DeleteDC( hMemDC );
1999 if (hDC_off) DeleteDC(hDC_off);
2000 if (hB_off) DeleteObject(hB_off);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00002001 GlobalUnlock16( hIcon );
2002 return result;
2003}
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002004
Alexandre Julliarda660c792000-06-03 20:45:20 +00002005/***********************************************************************
2006 * DIB_FixColorsToLoadflags
2007 *
2008 * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
2009 * are in loadflags
2010 */
2011static void DIB_FixColorsToLoadflags(BITMAPINFO * bmi, UINT loadflags, BYTE pix)
2012{
2013 int colors;
2014 COLORREF c_W, c_S, c_F, c_L, c_C;
2015 int incr,i;
2016 RGBQUAD *ptr;
2017
2018 if (bmi->bmiHeader.biBitCount > 8) return;
2019 if (bmi->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) incr = 4;
2020 else if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) incr = 3;
2021 else {
2022 WARN_(resource)("Wrong bitmap header size!\n");
2023 return;
2024 }
2025 colors = bmi->bmiHeader.biClrUsed;
2026 if (!colors && (bmi->bmiHeader.biBitCount <= 8))
2027 colors = 1 << bmi->bmiHeader.biBitCount;
2028 c_W = GetSysColor(COLOR_WINDOW);
2029 c_S = GetSysColor(COLOR_3DSHADOW);
2030 c_F = GetSysColor(COLOR_3DFACE);
2031 c_L = GetSysColor(COLOR_3DLIGHT);
2032 if (loadflags & LR_LOADTRANSPARENT) {
2033 switch (bmi->bmiHeader.biBitCount) {
2034 case 1: pix = pix >> 7; break;
2035 case 4: pix = pix >> 4; break;
2036 case 8: break;
2037 default:
2038 WARN_(resource)("(%d): Unsupported depth\n", bmi->bmiHeader.biBitCount);
2039 return;
2040 }
2041 if (pix >= colors) {
2042 WARN_(resource)("pixel has color index greater than biClrUsed!\n");
2043 return;
2044 }
2045 if (loadflags & LR_LOADMAP3DCOLORS) c_W = c_F;
2046 ptr = (RGBQUAD*)((char*)bmi->bmiColors+pix*incr);
2047 ptr->rgbBlue = GetBValue(c_W);
2048 ptr->rgbGreen = GetGValue(c_W);
2049 ptr->rgbRed = GetRValue(c_W);
2050 }
2051 if (loadflags & LR_LOADMAP3DCOLORS)
2052 for (i=0; i<colors; i++) {
2053 ptr = (RGBQUAD*)((char*)bmi->bmiColors+i*incr);
2054 c_C = RGB(ptr->rgbRed, ptr->rgbGreen, ptr->rgbBlue);
2055 if (c_C == RGB(128, 128, 128)) {
2056 ptr->rgbRed = GetRValue(c_S);
2057 ptr->rgbGreen = GetGValue(c_S);
2058 ptr->rgbBlue = GetBValue(c_S);
2059 } else if (c_C == RGB(192, 192, 192)) {
2060 ptr->rgbRed = GetRValue(c_F);
2061 ptr->rgbGreen = GetGValue(c_F);
2062 ptr->rgbBlue = GetBValue(c_F);
2063 } else if (c_C == RGB(223, 223, 223)) {
2064 ptr->rgbRed = GetRValue(c_L);
2065 ptr->rgbGreen = GetGValue(c_L);
2066 ptr->rgbBlue = GetBValue(c_L);
2067 }
2068 }
2069}
2070
2071
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002072/**********************************************************************
2073 * BITMAP_Load
2074 */
2075static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
2076{
2077 HBITMAP hbitmap = 0;
2078 HDC hdc;
2079 HRSRC hRsrc;
2080 HGLOBAL handle;
2081 char *ptr = NULL;
2082 BITMAPINFO *info, *fix_info=NULL;
2083 HGLOBAL hFix;
2084 int size;
2085
2086 if (!(loadflags & LR_LOADFROMFILE)) {
2087 if (!instance) /* OEM bitmap */
2088 {
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002089 if (HIWORD((int)name)) return 0;
Alexandre Julliard42d20f92000-08-10 01:16:19 +00002090 return USER_Driver.pLoadOEMResource( LOWORD((int)name), OEM_BITMAP );
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002091 }
2092
2093 if (!(hRsrc = FindResourceW( instance, name, RT_BITMAPW ))) return 0;
2094 if (!(handle = LoadResource( instance, hRsrc ))) return 0;
2095
2096 if ((info = (BITMAPINFO *)LockResource( handle )) == NULL) return 0;
2097 }
2098 else
2099 {
2100 if (!(ptr = (char *)VIRTUAL_MapFileW( name ))) return 0;
2101 info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
2102 }
2103 size = DIB_BitmapInfoSize(info, DIB_RGB_COLORS);
2104 if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
2105 if (fix_info) {
2106 BYTE pix;
2107
2108 memcpy(fix_info, info, size);
2109 pix = *((LPBYTE)info+DIB_BitmapInfoSize(info, DIB_RGB_COLORS));
2110 DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
2111 if ((hdc = GetDC(0)) != 0) {
2112 char *bits = (char *)info + size;
2113 if (loadflags & LR_CREATEDIBSECTION) {
2114 DIBSECTION dib;
2115 hbitmap = CreateDIBSection(hdc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
2116 GetObjectA(hbitmap, sizeof(DIBSECTION), &dib);
2117 SetDIBits(hdc, hbitmap, 0, dib.dsBm.bmHeight, bits, info,
2118 DIB_RGB_COLORS);
2119 }
2120 else {
2121 hbitmap = CreateDIBitmap( hdc, &fix_info->bmiHeader, CBM_INIT,
2122 bits, fix_info, DIB_RGB_COLORS );
2123 }
2124 ReleaseDC( 0, hdc );
2125 }
2126 GlobalUnlock(hFix);
2127 GlobalFree(hFix);
2128 }
2129 if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
2130 return hbitmap;
2131}
2132
2133
2134/***********************************************************************
2135 * LoadImage16 [USER.389]
2136 *
2137 */
2138HANDLE16 WINAPI LoadImage16( HINSTANCE16 hinst, LPCSTR name, UINT16 type,
2139 INT16 desiredx, INT16 desiredy, UINT16 loadflags)
2140{
2141 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
2142 return LoadImageA( hinst, nameStr, type,
2143 desiredx, desiredy, loadflags );
2144}
2145
2146/**********************************************************************
2147 * LoadImageA (USER32.365)
2148 *
2149 * FIXME: implementation lacks some features, see LR_ defines in windows.h
2150 */
2151
2152HANDLE WINAPI LoadImageA( HINSTANCE hinst, LPCSTR name, UINT type,
2153 INT desiredx, INT desiredy, UINT loadflags)
2154{
2155 HANDLE res;
2156 LPWSTR u_name;
2157
2158 if (HIWORD(name)) u_name = HEAP_strdupAtoW(GetProcessHeap(), 0, name);
2159 else u_name=(LPWSTR)name;
2160 res = LoadImageW(hinst, u_name, type, desiredx, desiredy, loadflags);
2161 if (HIWORD(name)) HeapFree(GetProcessHeap(), 0, u_name);
2162 return res;
2163}
2164
2165
2166/******************************************************************************
2167 * LoadImageW [USER32.366] Loads an icon, cursor, or bitmap
2168 *
2169 * PARAMS
2170 * hinst [I] Handle of instance that contains image
2171 * name [I] Name of image
2172 * type [I] Type of image
2173 * desiredx [I] Desired width
2174 * desiredy [I] Desired height
2175 * loadflags [I] Load flags
2176 *
2177 * RETURNS
2178 * Success: Handle to newly loaded image
2179 * Failure: NULL
2180 *
2181 * FIXME: Implementation lacks some features, see LR_ defines in windows.h
2182 */
2183HANDLE WINAPI LoadImageW( HINSTANCE hinst, LPCWSTR name, UINT type,
2184 INT desiredx, INT desiredy, UINT loadflags )
2185{
2186 if (HIWORD(name)) {
2187 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2188 hinst,name,type,desiredx,desiredy,loadflags);
2189 } else {
2190 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2191 hinst,name,type,desiredx,desiredy,loadflags);
2192 }
2193 if (loadflags & LR_DEFAULTSIZE) {
2194 if (type == IMAGE_ICON) {
2195 if (!desiredx) desiredx = GetSystemMetrics(SM_CXICON);
2196 if (!desiredy) desiredy = GetSystemMetrics(SM_CYICON);
2197 } else if (type == IMAGE_CURSOR) {
2198 if (!desiredx) desiredx = GetSystemMetrics(SM_CXCURSOR);
2199 if (!desiredy) desiredy = GetSystemMetrics(SM_CYCURSOR);
2200 }
2201 }
2202 if (loadflags & LR_LOADFROMFILE) loadflags &= ~LR_SHARED;
2203 switch (type) {
2204 case IMAGE_BITMAP:
2205 return BITMAP_Load( hinst, name, loadflags );
2206
2207 case IMAGE_ICON:
2208 {
2209 HDC hdc = GetDC(0);
2210 UINT palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
2211 if (palEnts == 0)
2212 palEnts = 256;
2213 ReleaseDC(0, hdc);
2214
2215 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2216 palEnts, FALSE, loadflags);
2217 }
2218
2219 case IMAGE_CURSOR:
2220 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2221 1, TRUE, loadflags);
2222 }
2223 return 0;
2224}
2225
2226
2227/******************************************************************************
2228 * CopyImage16 [USER.390] Creates new image and copies attributes to it
2229 *
2230 */
2231HICON16 WINAPI CopyImage16( HANDLE16 hnd, UINT16 type, INT16 desiredx,
2232 INT16 desiredy, UINT16 flags )
2233{
2234 return (HICON16)CopyImage((HANDLE)hnd, (UINT)type, (INT)desiredx,
2235 (INT)desiredy, (UINT)flags);
2236}
2237
2238/******************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00002239 * CopyImage [USER32.61] Creates new image and copies attributes to it
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002240 *
2241 * PARAMS
2242 * hnd [I] Handle to image to copy
2243 * type [I] Type of image to copy
2244 * desiredx [I] Desired width of new image
2245 * desiredy [I] Desired height of new image
2246 * flags [I] Copy flags
2247 *
2248 * RETURNS
2249 * Success: Handle to newly created image
2250 * Failure: NULL
2251 *
2252 * FIXME: implementation still lacks nearly all features, see LR_*
2253 * defines in windows.h
2254 */
2255HICON WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
2256 INT desiredy, UINT flags )
2257{
2258 switch (type)
2259 {
2260 case IMAGE_BITMAP:
2261 return BITMAP_CopyBitmap(hnd);
2262 case IMAGE_ICON:
2263 return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags);
2264 case IMAGE_CURSOR:
2265 /* Should call CURSORICON_ExtCopy but more testing
2266 * needs to be done before we change this
2267 */
2268 return CopyCursor(hnd);
2269 }
2270 return 0;
2271}
2272
2273
2274/******************************************************************************
2275 * LoadBitmapW [USER32.358] Loads bitmap from the executable file
2276 *
2277 * RETURNS
2278 * Success: Handle to specified bitmap
2279 * Failure: NULL
2280 */
2281HBITMAP WINAPI LoadBitmapW(
2282 HINSTANCE instance, /* [in] Handle to application instance */
2283 LPCWSTR name) /* [in] Address of bitmap resource name */
2284{
2285 return LoadImageW( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2286}
2287
2288/**********************************************************************
2289 * LoadBitmapA (USER32.357)
2290 */
2291HBITMAP WINAPI LoadBitmapA( HINSTANCE instance, LPCSTR name )
2292{
2293 return LoadImageA( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2294}
2295
2296/**********************************************************************
2297 * LoadBitmap16 (USER.175)
2298 */
2299HBITMAP16 WINAPI LoadBitmap16( HINSTANCE16 instance, SEGPTR name )
2300{
2301 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
2302 return LoadBitmapA( instance, nameStr );
2303}