blob: 88a8ace13e3b39cdd952d2cb98b027edf59eec42 [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"
Alexandre Julliard77b99181997-09-14 17:17:23 +000043#include "module.h"
Alexandre Julliard06c275a1999-05-02 14:32:27 +000044#include "debugtools.h"
Alexandre Julliard44ed71f1997-12-21 19:17:50 +000045#include "user.h"
Ulrich Weiganda11ce321998-11-08 12:27:26 +000046#include "input.h"
Ulrich Weigand431d1a01998-11-14 18:57:47 +000047#include "message.h"
Alexandre Julliardf90efa91998-06-14 15:24:15 +000048#include "winerror.h"
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000049
Alexandre Julliardb52aed42000-03-24 21:40:30 +000050DECLARE_DEBUG_CHANNEL(cursor);
51DECLARE_DEBUG_CHANNEL(icon);
52DECLARE_DEBUG_CHANNEL(resource);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000053
Alexandre Julliarda3960291999-02-26 11:11:13 +000054static HCURSOR hActiveCursor = 0; /* Active cursor */
55static INT CURSOR_ShowCount = 0; /* Cursor display count */
56static RECT CURSOR_ClipRect; /* Cursor clipping rect */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000057
Alexandre Julliard16cbf402001-01-18 20:32:01 +000058static HDC screen_dc;
Ulrich Weigand50a09151999-03-10 14:00:29 +000059
60/**********************************************************************
61 * ICONCACHE for cursors/icons loaded with LR_SHARED.
62 *
63 * FIXME: This should not be allocated on the system heap, but on a
64 * subsystem-global heap (i.e. one for all Win16 processes,
François Gouget4188fbc2001-02-14 21:43:06 +000065 * and one for each Win32 process).
Ulrich Weigand50a09151999-03-10 14:00:29 +000066 */
67typedef struct tagICONCACHE
68{
69 struct tagICONCACHE *next;
70
71 HMODULE hModule;
72 HRSRC hRsrc;
Pierre Mageau4ac8db71999-09-04 11:16:48 +000073 HRSRC hGroupRsrc;
Ulrich Weigand50a09151999-03-10 14:00:29 +000074 HANDLE handle;
75
76 INT count;
77
78} ICONCACHE;
79
80static ICONCACHE *IconAnchor = NULL;
Alexandre Julliard301df6b2001-08-16 18:12:56 +000081static CRITICAL_SECTION IconCrst = CRITICAL_SECTION_INIT("IconCrst");
Dave Hawkesdbb6ab22000-07-09 12:16:58 +000082static WORD ICON_HOTSPOT = 0x4242;
Ulrich Weigand50a09151999-03-10 14:00:29 +000083
Alexandre Julliard982a2232000-12-13 20:20:09 +000084
85/***********************************************************************
86 * map_fileW
87 *
88 * Helper function to map a file to memory:
89 * name - file name
90 * [RETURN] ptr - pointer to mapped file
91 */
92static void *map_fileW( LPCWSTR name )
93{
94 HANDLE hFile, hMapping;
95 LPVOID ptr = NULL;
96
97 hFile = CreateFileW( name, GENERIC_READ, FILE_SHARE_READ, NULL,
98 OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0 );
99 if (hFile != INVALID_HANDLE_VALUE)
100 {
101 hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
102 CloseHandle( hFile );
103 if (hMapping)
104 {
105 ptr = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
106 CloseHandle( hMapping );
107 }
108 }
109 return ptr;
110}
111
112
Ulrich Weigand50a09151999-03-10 14:00:29 +0000113/**********************************************************************
Ulrich Weigand50a09151999-03-10 14:00:29 +0000114 * CURSORICON_FindSharedIcon
115 */
116static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
117{
118 HANDLE handle = 0;
119 ICONCACHE *ptr;
120
121 EnterCriticalSection( &IconCrst );
122
123 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
124 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
125 {
126 ptr->count++;
127 handle = ptr->handle;
128 break;
129 }
130
131 LeaveCriticalSection( &IconCrst );
132
133 return handle;
134}
135
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000136/*************************************************************************
137 * CURSORICON_FindCache
138 *
Andreas Mohra59324d2000-11-25 01:40:10 +0000139 * Given a handle, find the corresponding cache element
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000140 *
141 * PARAMS
142 * Handle [I] handle to an Image
143 *
144 * RETURNS
145 * Success: The cache entry
146 * Failure: NULL
147 *
148 */
149static ICONCACHE* CURSORICON_FindCache(HANDLE handle)
150{
151 ICONCACHE *ptr;
152 ICONCACHE *pRet=NULL;
153 BOOL IsFound = FALSE;
154 int count;
155
156 EnterCriticalSection( &IconCrst );
157
158 for (count = 0, ptr = IconAnchor; ptr != NULL && !IsFound; ptr = ptr->next, count++ )
159 {
160 if ( handle == ptr->handle )
161 {
162 IsFound = TRUE;
163 pRet = ptr;
164 }
165 }
166
167 LeaveCriticalSection( &IconCrst );
168
169 return pRet;
170}
171
Ulrich Weigand50a09151999-03-10 14:00:29 +0000172/**********************************************************************
173 * CURSORICON_AddSharedIcon
174 */
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000175static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle )
Ulrich Weigand50a09151999-03-10 14:00:29 +0000176{
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000177 ICONCACHE *ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(ICONCACHE) );
Ulrich Weigand50a09151999-03-10 14:00:29 +0000178 if ( !ptr ) return;
179
180 ptr->hModule = hModule;
181 ptr->hRsrc = hRsrc;
182 ptr->handle = handle;
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000183 ptr->hGroupRsrc = hGroupRsrc;
Ulrich Weigand50a09151999-03-10 14:00:29 +0000184 ptr->count = 1;
185
186 EnterCriticalSection( &IconCrst );
187 ptr->next = IconAnchor;
188 IconAnchor = ptr;
189 LeaveCriticalSection( &IconCrst );
190}
191
192/**********************************************************************
193 * CURSORICON_DelSharedIcon
194 */
195static INT CURSORICON_DelSharedIcon( HANDLE handle )
196{
197 INT count = -1;
198 ICONCACHE *ptr;
199
200 EnterCriticalSection( &IconCrst );
201
202 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
203 if ( ptr->handle == handle )
204 {
205 if ( ptr->count > 0 ) ptr->count--;
206 count = ptr->count;
207 break;
208 }
209
210 LeaveCriticalSection( &IconCrst );
211
212 return count;
213}
214
215/**********************************************************************
216 * CURSORICON_FreeModuleIcons
217 */
218void CURSORICON_FreeModuleIcons( HMODULE hModule )
219{
220 ICONCACHE **ptr = &IconAnchor;
221
222 if ( HIWORD( hModule ) )
223 hModule = MapHModuleLS( hModule );
224 else
225 hModule = GetExePtr( hModule );
226
227 EnterCriticalSection( &IconCrst );
228
229 while ( *ptr )
230 {
231 if ( (*ptr)->hModule == hModule )
232 {
233 ICONCACHE *freePtr = *ptr;
234 *ptr = freePtr->next;
235
236 GlobalFree16( freePtr->handle );
Alexandre Julliardda2892c2001-02-23 01:13:42 +0000237 HeapFree( GetProcessHeap(), 0, freePtr );
Ulrich Weigand50a09151999-03-10 14:00:29 +0000238 continue;
239 }
240 ptr = &(*ptr)->next;
241 }
242
243 LeaveCriticalSection( &IconCrst );
244}
245
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000246/**********************************************************************
247 * CURSORICON_FindBestIcon
248 *
249 * Find the icon closest to the requested size and number of colors.
250 */
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000251static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000252 int height, int colors )
253{
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000254 int i;
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000255 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000256 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
257 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000258
259 if (dir->idCount < 1)
260 {
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000261 WARN_(icon)("Empty directory!\n" );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000262 return NULL;
263 }
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000264 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000265
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000266 /* Find Best Fit */
267 iTotalDiff = 0xFFFFFFFF;
268 iColorDiff = 0xFFFFFFFF;
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000269 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000270 {
271 iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
272 iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
273
274 if(iTotalDiff > (iTempXDiff + iTempYDiff))
275 {
276 iXDiff = iTempXDiff;
277 iYDiff = iTempYDiff;
278 iTotalDiff = iXDiff + iYDiff;
279 }
280 }
281
282 /* Find Best Colors for Best Fit */
283 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
284 {
285 if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
286 abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
287 {
288 iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
289 if(iColorDiff > iTempColorDiff)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000290 {
291 bestEntry = entry;
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000292 iColorDiff = iTempColorDiff;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000293 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000294 }
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000295 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000296
297 return bestEntry;
298}
299
300
301/**********************************************************************
302 * CURSORICON_FindBestCursor
303 *
304 * Find the cursor closest to the requested size.
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000305 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
306 * ignored too
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000307 */
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000308static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000309 int width, int height, int color)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000310{
311 int i, maxwidth, maxheight;
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000312 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000313
314 if (dir->idCount < 1)
315 {
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000316 WARN_(cursor)("Empty directory!\n" );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000317 return NULL;
318 }
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000319 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000320
Steve Tibbett85692c81999-08-15 16:35:21 +0000321 /* Double height to account for AND and XOR masks */
322
323 height *= 2;
324
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000325 /* First find the largest one smaller than or equal to the requested size*/
326
327 maxwidth = maxheight = 0;
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000328 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
329 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
330 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000331 (entry->wBitCount == 1))
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000332 {
333 bestEntry = entry;
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000334 maxwidth = entry->ResInfo.cursor.wWidth;
335 maxheight = entry->ResInfo.cursor.wHeight;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000336 }
337 if (bestEntry) return bestEntry;
338
339 /* Now find the smallest one larger than the requested size */
340
341 maxwidth = maxheight = 255;
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000342 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
343 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000344 (entry->wBitCount == 1))
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000345 {
346 bestEntry = entry;
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000347 maxwidth = entry->ResInfo.cursor.wWidth;
348 maxheight = entry->ResInfo.cursor.wHeight;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000349 }
350
351 return bestEntry;
352}
353
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000354/*********************************************************************
355 * The main purpose of this function is to create fake resource directory
356 * and fake resource entries. There are several reasons for this:
357 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
358 * fields
359 * There are some "bad" cursor files which do not have
360 * bColorCount initialized but instead one must read this info
361 * directly from corresponding DIB sections
362 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
363 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000364BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000365 CURSORICONDIR **res, LPBYTE **ptr)
366{
367 LPBYTE _free;
368 CURSORICONFILEDIR *bits;
369 int entries, size, i;
370
371 *res = NULL;
372 *ptr = NULL;
Alexandre Julliard982a2232000-12-13 20:20:09 +0000373 if (!(bits = map_fileW( filename ))) return FALSE;
Juergen Schmied4493a741998-11-30 17:29:28 +0000374
375 /* FIXME: test for inimated icons
376 * hack to load the first icon from the *.ani file
377 */
378 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
379 { LPBYTE pos = (LPBYTE) bits;
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000380 FIXME_(cursor)("Animated icons not correctly implemented! %p \n", bits);
Juergen Schmied4493a741998-11-30 17:29:28 +0000381
382 for (;;)
383 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000384 { FIXME_(cursor)("icon entry found! %p\n", bits);
Juergen Schmied4493a741998-11-30 17:29:28 +0000385 pos+=4;
386 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
387 { goto fail;
388 }
Juergen Schmiedcb2e4d31999-09-19 18:56:40 +0000389 bits=(CURSORICONFILEDIR*)(pos+4);
390 FIXME_(cursor)("icon size ok. offset=%p \n", bits);
Juergen Schmied4493a741998-11-30 17:29:28 +0000391 break;
392 }
393 pos+=2;
394 if (pos>=(LPBYTE)bits+766) goto fail;
395 }
396 }
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000397 if (!(entries = bits->idCount)) goto fail;
Patrik Stridvalla9a671d1999-04-25 19:01:52 +0000398 size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) * (entries - 1);
399 _free = (LPBYTE) size;
400
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000401 for (i=0; i < entries; i++)
402 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
403
404 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
405 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
406 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
407
408 _free = (LPBYTE)(*res) + (int)_free;
409 memcpy((*res), bits, 6);
410 for (i=0; i<entries; i++)
411 {
412 ((LPBYTE*)(*ptr))[i] = _free;
413 if (fCursor) {
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000414 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
415 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000416 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
417 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
418 _free+=sizeof(POINT16);
419 } else {
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000420 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
421 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
422 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000423 }
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000424 (*res)->idEntries[i].wPlanes=1;
425 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
426 bits->idEntries[i].dwDIBOffset))->biBitCount;
427 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
428 (*res)->idEntries[i].wResId=i+1;
429
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000430 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000431 (*res)->idEntries[i].dwBytesInRes);
432 _free += (*res)->idEntries[i].dwBytesInRes;
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000433 }
434 UnmapViewOfFile( bits );
435 return TRUE;
436fail:
437 if (*res) HeapFree( GetProcessHeap(), 0, *res );
438 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
439 UnmapViewOfFile( bits );
440 return FALSE;
441}
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000442
Alexandre Julliard77b99181997-09-14 17:17:23 +0000443
444/**********************************************************************
445 * CURSORICON_CreateFromResource
446 *
447 * Create a cursor or icon from in-memory resource template.
448 *
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000449 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
Alexandre Julliard77b99181997-09-14 17:17:23 +0000450 * with cbSize parameter as well.
451 */
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000452static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
Alexandre Julliarda3960291999-02-26 11:11:13 +0000453 UINT cbSize, BOOL bIcon, DWORD dwVersion,
454 INT width, INT height, UINT loadflags )
Alexandre Julliard77b99181997-09-14 17:17:23 +0000455{
Alexandre Julliard16cbf402001-01-18 20:32:01 +0000456 static HDC hdcMem;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000457 int sizeAnd, sizeXor;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000458 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
Alexandre Julliardb0efe282000-08-04 04:18:04 +0000459 BITMAP bmpXor, bmpAnd;
Patrik Stridvalle92331f1999-09-20 18:52:06 +0000460 POINT16 hotspot;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000461 BITMAPINFO *bmi;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000462 BOOL DoStretch;
463 INT size;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000464
Patrik Stridvalle92331f1999-09-20 18:52:06 +0000465 hotspot.x = ICON_HOTSPOT;
466 hotspot.y = ICON_HOTSPOT;
467
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000468 TRACE_(cursor)("%08x (%u bytes), ver %08x, %ix%i %s %s\n",
Alexandre Julliard77b99181997-09-14 17:17:23 +0000469 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000470 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
Alexandre Julliard77b99181997-09-14 17:17:23 +0000471 if (dwVersion == 0x00020000)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000472 {
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000473 FIXME_(cursor)("\t2.xx resources are not supported\n");
Alexandre Julliard77b99181997-09-14 17:17:23 +0000474 return 0;
475 }
476
477 if (bIcon)
478 bmi = (BITMAPINFO *)bits;
479 else /* get the hotspot */
480 {
481 POINT16 *pt = (POINT16 *)bits;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000482 hotspot = *pt;
483 bmi = (BITMAPINFO *)(pt + 1);
484 }
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000485 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
486
487 if (!width) width = bmi->bmiHeader.biWidth;
488 if (!height) height = bmi->bmiHeader.biHeight/2;
489 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
490 (bmi->bmiHeader.biWidth != width);
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000491
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000492 /* Check bitmap header */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000493
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000494 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
495 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
496 bmi->bmiHeader.biCompression != BI_RGB) )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000497 {
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000498 WARN_(cursor)("\tinvalid resource bitmap header.\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000499 return 0;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000500 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000501
Alexandre Julliard16cbf402001-01-18 20:32:01 +0000502 if (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
503 if (screen_dc)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000504 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000505 BITMAPINFO* pInfo;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000506
507 /* Make sure we have room for the monochrome bitmap later on.
508 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
509 * up to and including the biBitCount. In-memory icon resource
510 * format is as follows:
511 *
512 * BITMAPINFOHEADER icHeader // DIB header
513 * RGBQUAD icColors[] // Color table
514 * BYTE icXOR[] // DIB bits for XOR mask
515 * BYTE icAND[] // DIB bits for AND mask
516 */
517
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000518 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
Francois Gouget6d77d3a2000-03-25 21:44:35 +0000519 max(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000520 {
521 memcpy( pInfo, bmi, size );
522 pInfo->bmiHeader.biHeight /= 2;
523
524 /* Create the XOR bitmap */
525
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000526 if (DoStretch) {
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000527 if(bIcon)
528 {
Alexandre Julliard16cbf402001-01-18 20:32:01 +0000529 hXorBits = CreateCompatibleBitmap(screen_dc, width, height);
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000530 }
531 else
532 {
533 hXorBits = CreateBitmap(width, height, 1, 1, NULL);
534 }
535 if(hXorBits)
536 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000537 HBITMAP hOld;
Alexandre Julliard16cbf402001-01-18 20:32:01 +0000538 BOOL res = FALSE;
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000539
Alexandre Julliard16cbf402001-01-18 20:32:01 +0000540 if (!hdcMem) hdcMem = CreateCompatibleDC(screen_dc);
541 if (hdcMem) {
542 hOld = SelectObject(hdcMem, hXorBits);
543 res = StretchDIBits(hdcMem, 0, 0, width, height, 0, 0,
544 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
545 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
546 SelectObject(hdcMem, hOld);
547 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000548 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000549 }
Alexandre Julliard16cbf402001-01-18 20:32:01 +0000550 } else hXorBits = CreateDIBitmap( screen_dc, &pInfo->bmiHeader,
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000551 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000552 if( hXorBits )
553 {
Marcus Meissner64c86ffe2000-08-07 04:16:43 +0000554 char* xbits = (char *)bmi + size +
Huw D M Davies608629b1999-04-18 12:07:00 +0000555 DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
556 bmi->bmiHeader.biHeight,
557 bmi->bmiHeader.biBitCount) / 2;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000558
559 pInfo->bmiHeader.biBitCount = 1;
560 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
561 {
562 RGBQUAD *rgb = pInfo->bmiColors;
563
564 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
565 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
566 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
567 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
568 }
569 else
570 {
571 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
572
573 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
574 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
575 }
576
577 /* Create the AND bitmap */
578
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000579 if (DoStretch) {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000580 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
581 HBITMAP hOld;
Alexandre Julliard16cbf402001-01-18 20:32:01 +0000582 BOOL res = FALSE;
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000583
Alexandre Julliard16cbf402001-01-18 20:32:01 +0000584 if (!hdcMem) hdcMem = CreateCompatibleDC(screen_dc);
585 if (hdcMem) {
586 hOld = SelectObject(hdcMem, hAndBits);
587 res = StretchDIBits(hdcMem, 0, 0, width, height, 0, 0,
588 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
589 xbits, pInfo, DIB_RGB_COLORS, SRCCOPY);
590 SelectObject(hdcMem, hOld);
591 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000592 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000593 }
Alexandre Julliard16cbf402001-01-18 20:32:01 +0000594 } else hAndBits = CreateDIBitmap( screen_dc, &pInfo->bmiHeader,
Marcus Meissner64c86ffe2000-08-07 04:16:43 +0000595 CBM_INIT, xbits, pInfo, DIB_RGB_COLORS );
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000596
Alexandre Julliarda3960291999-02-26 11:11:13 +0000597 if( !hAndBits ) DeleteObject( hXorBits );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000598 }
599 HeapFree( GetProcessHeap(), 0, pInfo );
600 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000601 }
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000602
603 if( !hXorBits || !hAndBits )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000604 {
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000605 WARN_(cursor)("\tunable to create an icon bitmap.\n");
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000606 return 0;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000607 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000608
609 /* Now create the CURSORICONINFO structure */
Alexandre Julliardb0efe282000-08-04 04:18:04 +0000610 GetObjectA( hXorBits, sizeof(bmpXor), &bmpXor );
611 GetObjectA( hAndBits, sizeof(bmpAnd), &bmpAnd );
612 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
613 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000614
Alexandre Julliard77b99181997-09-14 17:17:23 +0000615 if (hObj) hObj = GlobalReAlloc16( hObj,
616 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
617 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
618 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
619 if (hObj)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000620 {
Alexandre Julliard77b99181997-09-14 17:17:23 +0000621 CURSORICONINFO *info;
622
623 /* Make it owned by the module */
Alexandre Julliard7d5bc5c2001-01-15 20:09:09 +0000624 if (hInstance) hInstance = GetExePtr(hInstance);
625 FarSetOwner16( hObj, hInstance );
Alexandre Julliard77b99181997-09-14 17:17:23 +0000626
627 info = (CURSORICONINFO *)GlobalLock16( hObj );
628 info->ptHotSpot.x = hotspot.x;
629 info->ptHotSpot.y = hotspot.y;
Alexandre Julliardb0efe282000-08-04 04:18:04 +0000630 info->nWidth = bmpXor.bmWidth;
631 info->nHeight = bmpXor.bmHeight;
632 info->nWidthBytes = bmpXor.bmWidthBytes;
633 info->bPlanes = bmpXor.bmPlanes;
634 info->bBitsPerPixel = bmpXor.bmBitsPixel;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000635
636 /* Transfer the bitmap bits to the CURSORICONINFO structure */
637
Alexandre Julliarda3960291999-02-26 11:11:13 +0000638 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
639 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
Alexandre Julliard77b99181997-09-14 17:17:23 +0000640 GlobalUnlock16( hObj );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000641 }
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000642
Alexandre Julliarda3960291999-02-26 11:11:13 +0000643 DeleteObject( hAndBits );
Alexandre Julliard2a2321b2000-08-19 21:38:55 +0000644 DeleteObject( hXorBits );
Alexandre Julliard77b99181997-09-14 17:17:23 +0000645 return hObj;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000646}
647
Alexandre Julliard77b99181997-09-14 17:17:23 +0000648
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000649/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000650 * CreateIconFromResourceEx (USER.450)
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000651 *
Alexandre Julliard77b99181997-09-14 17:17:23 +0000652 * FIXME: not sure about exact parameter types
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000653 */
Alexandre Julliard77b99181997-09-14 17:17:23 +0000654HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
655 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000656{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000657 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000658 width, height, cFlag);
Alexandre Julliard77b99181997-09-14 17:17:23 +0000659}
660
661
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000662/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000663 * CreateIconFromResource (USER32.@)
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000664 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000665HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
666 BOOL bIcon, DWORD dwVersion)
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000667{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000668 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000669}
670
671
Alexandre Julliard77b99181997-09-14 17:17:23 +0000672/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000673 * CreateIconFromResourceEx (USER32.@)
Alexandre Julliard77b99181997-09-14 17:17:23 +0000674 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000675HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
676 BOOL bIcon, DWORD dwVersion,
677 INT width, INT height,
678 UINT cFlag )
Alexandre Julliard77b99181997-09-14 17:17:23 +0000679{
Alexandre Julliard7d5bc5c2001-01-15 20:09:09 +0000680 return CURSORICON_CreateFromResource( 0, 0, bits, cbSize, bIcon, dwVersion,
681 width, height, cFlag );
Alexandre Julliard77b99181997-09-14 17:17:23 +0000682}
683
Alexandre Julliard77b99181997-09-14 17:17:23 +0000684/**********************************************************************
Ulrich Weigand50a09151999-03-10 14:00:29 +0000685 * CURSORICON_Load
Alexandre Julliard77b99181997-09-14 17:17:23 +0000686 *
Ulrich Weigand50a09151999-03-10 14:00:29 +0000687 * Load a cursor or icon from resource or file.
Alexandre Julliard77b99181997-09-14 17:17:23 +0000688 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000689HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
Ulrich Weigand50a09151999-03-10 14:00:29 +0000690 INT width, INT height, INT colors,
691 BOOL fCursor, UINT loadflags )
Alexandre Julliard77b99181997-09-14 17:17:23 +0000692{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000693 HANDLE handle = 0, h = 0;
694 HANDLE hRsrc;
Ulrich Weigand50a09151999-03-10 14:00:29 +0000695 CURSORICONDIR *dir;
696 CURSORICONDIRENTRY *dirEntry;
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000697 LPBYTE bits;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000698
Ulrich Weigand50a09151999-03-10 14:00:29 +0000699 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
Alexandre Julliard77b99181997-09-14 17:17:23 +0000700 {
Ulrich Weigand50a09151999-03-10 14:00:29 +0000701 LPBYTE *ptr;
702 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
703 return 0;
704 if (fCursor)
705 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
706 else
707 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000708 bits = ptr[dirEntry->wResId-1];
709 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
Ulrich Weigand50a09151999-03-10 14:00:29 +0000710 !fCursor, 0x00030000, width, height, loadflags);
711 HeapFree( GetProcessHeap(), 0, dir );
712 HeapFree( GetProcessHeap(), 0, ptr );
713 }
Ulrich Weigand50a09151999-03-10 14:00:29 +0000714 else /* Load from resource */
715 {
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000716 HANDLE hGroupRsrc;
Ulrich Weigand50a09151999-03-10 14:00:29 +0000717 WORD wResId;
718 DWORD dwBytesInRes;
719
Alexandre Julliard16cbf402001-01-18 20:32:01 +0000720 if (!hInstance) /* Load OEM cursor/icon */
721 {
722 if (!(hInstance = GetModuleHandleA( "user32.dll" ))) return 0;
723 }
724
Ulrich Weigand50a09151999-03-10 14:00:29 +0000725 /* Normalize hInstance (must be uniquely represented for icon cache) */
726
727 if ( HIWORD( hInstance ) )
728 hInstance = MapHModuleLS( hInstance );
729 else
730 hInstance = GetExePtr( hInstance );
731
732 /* Get directory resource ID */
733
734 if (!(hRsrc = FindResourceW( hInstance, name,
735 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
736 return 0;
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000737 hGroupRsrc = hRsrc;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000738
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000739 /* Find the best entry in the directory */
Alexandre Julliard77b99181997-09-14 17:17:23 +0000740
Ulrich Weigand50a09151999-03-10 14:00:29 +0000741 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
742 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
743 if (fCursor)
744 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
745 width, height, 1);
746 else
747 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
748 width, height, colors );
749 if (!dirEntry) return 0;
Juergen Schmiedc45bbee1999-04-11 11:46:32 +0000750 wResId = dirEntry->wResId;
751 dwBytesInRes = dirEntry->dwBytesInRes;
Ulrich Weigand50a09151999-03-10 14:00:29 +0000752 FreeResource( handle );
753
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000754 /* Load the resource */
Alexandre Julliard77b99181997-09-14 17:17:23 +0000755
Ulrich Weigand50a09151999-03-10 14:00:29 +0000756 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
Alexandre Julliarda3960291999-02-26 11:11:13 +0000757 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
Alexandre Julliardb4c68722000-06-08 00:39:16 +0000758
759 /* If shared icon, check whether it was already loaded */
760 if ( (loadflags & LR_SHARED)
761 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
762 return h;
763
Alexandre Julliarda3960291999-02-26 11:11:13 +0000764 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000765 bits = (LPBYTE)LockResource( handle );
Ulrich Weigand50a09151999-03-10 14:00:29 +0000766 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
Turchanov Sergey62d6e981998-10-18 13:42:55 +0000767 !fCursor, 0x00030000, width, height, loadflags);
Ulrich Weigand50a09151999-03-10 14:00:29 +0000768 FreeResource( handle );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000769
Ulrich Weigand50a09151999-03-10 14:00:29 +0000770 /* If shared icon, add to icon cache */
771
772 if ( h && (loadflags & LR_SHARED) )
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000773 CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, h );
Ulrich Weigand50a09151999-03-10 14:00:29 +0000774 }
775
776 return h;
777}
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000778
779/***********************************************************************
780 * CURSORICON_Copy
781 *
782 * Make a copy of a cursor or icon.
783 */
Alexandre Julliardbf9130a1996-10-13 17:45:47 +0000784static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000785{
786 char *ptrOld, *ptrNew;
787 int size;
Alexandre Julliardbf9130a1996-10-13 17:45:47 +0000788 HGLOBAL16 hNew;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000789
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000790 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
Alexandre Julliard7d5bc5c2001-01-15 20:09:09 +0000791 if (hInstance && !(hInstance = GetExePtr( hInstance ))) return 0;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000792 size = GlobalSize16( handle );
793 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
Alexandre Julliarda3960291999-02-26 11:11:13 +0000794 FarSetOwner16( hNew, hInstance );
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000795 ptrNew = (char *)GlobalLock16( hNew );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000796 memcpy( ptrNew, ptrOld, size );
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000797 GlobalUnlock16( handle );
798 GlobalUnlock16( hNew );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000799 return hNew;
800}
801
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000802/*************************************************************************
803 * CURSORICON_ExtCopy
804 *
805 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified
806 *
807 * PARAMS
808 * Handle [I] handle to an Image
809 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)
810 * iDesiredCX [I] The Desired width of the Image
811 * iDesiredCY [I] The desired height of the Image
812 * nFlags [I] The flags from CopyImage
813 *
814 * RETURNS
815 * Success: The new handle of the Image
816 *
817 * NOTES
818 * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented.
819 * LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource.
820 * LR_COPYFROMRESOURCE will only work if the Image is in the Cache.
821 *
822 *
823 */
824
825HGLOBAL CURSORICON_ExtCopy(HGLOBAL Handle, UINT nType,
826 INT iDesiredCX, INT iDesiredCY,
827 UINT nFlags)
828{
829 HGLOBAL16 hNew=0;
830
831 TRACE_(icon)("Handle %u, uType %u, iDesiredCX %i, iDesiredCY %i, nFlags %u\n",
832 Handle, nType, iDesiredCX, iDesiredCY, nFlags);
833
834 if(Handle == 0)
835 {
836 return 0;
837 }
838
839 /* Best Fit or Monochrome */
840 if( (nFlags & LR_COPYFROMRESOURCE
841 && (iDesiredCX > 0 || iDesiredCY > 0))
842 || nFlags & LR_MONOCHROME)
843 {
844 ICONCACHE* pIconCache = CURSORICON_FindCache(Handle);
845
François Gouget4188fbc2001-02-14 21:43:06 +0000846 /* Not Found in Cache, then do a straight copy
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000847 */
848 if(pIconCache == NULL)
849 {
Alexandre Julliard7d5bc5c2001-01-15 20:09:09 +0000850 hNew = CURSORICON_Copy(0, Handle);
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000851 if(nFlags & LR_COPYFROMRESOURCE)
852 {
853 TRACE_(icon)("LR_COPYFROMRESOURCE: Failed to load from cache\n");
854 }
855 }
856 else
857 {
Juergen Schmied44016842000-02-25 20:52:01 +0000858 int iTargetCY = iDesiredCY, iTargetCX = iDesiredCX;
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000859 LPBYTE pBits;
860 HANDLE hMem;
861 HRSRC hRsrc;
862 DWORD dwBytesInRes;
863 WORD wResId;
864 CURSORICONDIR *pDir;
865 CURSORICONDIRENTRY *pDirEntry;
866 BOOL bIsIcon = (nType == IMAGE_ICON);
867
868 /* Completing iDesiredCX CY for Monochrome Bitmaps if needed
869 */
870 if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE))
871 || (iDesiredCX == 0 && iDesiredCY == 0))
872 {
873 iDesiredCY = GetSystemMetrics(bIsIcon ?
874 SM_CYICON : SM_CYCURSOR);
875 iDesiredCX = GetSystemMetrics(bIsIcon ?
876 SM_CXICON : SM_CXCURSOR);
877 }
878
François Gouget4188fbc2001-02-14 21:43:06 +0000879 /* Retrieve the CURSORICONDIRENTRY
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000880 */
881 if (!(hMem = LoadResource( pIconCache->hModule ,
882 pIconCache->hGroupRsrc)))
883 {
884 return 0;
885 }
886 if (!(pDir = (CURSORICONDIR*)LockResource( hMem )))
887 {
888 return 0;
889 }
890
891 /* Find Best Fit
892 */
893 if(bIsIcon)
894 {
895 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(
896 pDir, iDesiredCX, iDesiredCY, 256);
897 }
898 else
899 {
900 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(
901 pDir, iDesiredCX, iDesiredCY, 1);
902 }
903
904 wResId = pDirEntry->wResId;
905 dwBytesInRes = pDirEntry->dwBytesInRes;
906 FreeResource(hMem);
907
908 TRACE_(icon)("ResID %u, BytesInRes %lu, Width %d, Height %d DX %d, DY %d\n",
909 wResId, dwBytesInRes, pDirEntry->ResInfo.icon.bWidth,
910 pDirEntry->ResInfo.icon.bHeight, iDesiredCX, iDesiredCY);
911
912 /* Get the Best Fit
913 */
914 if (!(hRsrc = FindResourceW(pIconCache->hModule ,
915 MAKEINTRESOURCEW(wResId), bIsIcon ? RT_ICONW : RT_CURSORW)))
916 {
917 return 0;
918 }
919 if (!(hMem = LoadResource( pIconCache->hModule , hRsrc )))
920 {
921 return 0;
922 }
923
924 pBits = (LPBYTE)LockResource( hMem );
925
Juergen Schmied44016842000-02-25 20:52:01 +0000926 if(nFlags & LR_DEFAULTSIZE)
927 {
928 iTargetCY = GetSystemMetrics(SM_CYICON);
929 iTargetCX = GetSystemMetrics(SM_CXICON);
930 }
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000931
932 /* Create a New Icon with the proper dimension
933 */
934 hNew = CURSORICON_CreateFromResource( 0, 0, pBits, dwBytesInRes,
935 bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
936 FreeResource(hMem);
937 }
938 }
Alexandre Julliard7d5bc5c2001-01-15 20:09:09 +0000939 else hNew = CURSORICON_Copy(0, Handle);
Pierre Mageau4ac8db71999-09-04 11:16:48 +0000940 return hNew;
941}
942
Alexandre Julliardade697e1995-11-26 13:59:11 +0000943/***********************************************************************
944 * CURSORICON_IconToCursor
945 *
Alexandre Julliard77b99181997-09-14 17:17:23 +0000946 * Converts bitmap to mono and truncates if icon is too large (should
947 * probably do StretchBlt() instead).
Alexandre Julliardade697e1995-11-26 13:59:11 +0000948 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000949HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
Alexandre Julliardade697e1995-11-26 13:59:11 +0000950{
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000951 HCURSOR16 hRet = 0;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000952 CURSORICONINFO *pIcon = NULL;
Alexandre Julliardade697e1995-11-26 13:59:11 +0000953
Alexandre Julliard7d5bc5c2001-01-15 20:09:09 +0000954 if(hIcon)
Alexandre Julliard77b99181997-09-14 17:17:23 +0000955 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
956 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
Francis Beaudet699900b1999-09-05 12:15:49 +0000957 {
Alexandre Julliard7d5bc5c2001-01-15 20:09:09 +0000958 hRet = CURSORICON_Copy( 0, hIcon );
Francis Beaudet699900b1999-09-05 12:15:49 +0000959
960
961 pIcon = GlobalLock16(hRet);
962
963 pIcon->ptHotSpot.x = pIcon->ptHotSpot.y = 15;
964
Serge Ivanov15f86462000-03-04 19:07:08 +0000965 GlobalUnlock16(hRet);
Francis Beaudet699900b1999-09-05 12:15:49 +0000966 }
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000967 else
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000968 {
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000969 BYTE pAndBits[128];
970 BYTE pXorBits[128];
Alexandre Julliard77b99181997-09-14 17:17:23 +0000971 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
972 BYTE* psPtr, *pxbPtr = pXorBits;
973 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000974 BYTE* pbc = NULL;
975
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000976 CURSORICONINFO cI;
977
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000978 TRACE_(icon)("[%04x] %ix%i %ibpp (bogus %ibps)\n",
Alexandre Julliard77b99181997-09-14 17:17:23 +0000979 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
980
Huw D M Davies82617361998-11-01 16:35:42 +0000981 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
982 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
Alexandre Julliard77b99181997-09-14 17:17:23 +0000983 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
984
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000985 memset(pXorBits, 0, 128);
986 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
987 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
988 cI.nWidth = 32; cI.nHeight = 32;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000989 cI.nWidthBytes = 4; /* 32x1bpp */
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000990
Alexandre Julliard77b99181997-09-14 17:17:23 +0000991 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
992 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000993
Alexandre Julliard77b99181997-09-14 17:17:23 +0000994 for( iy = 0; iy < maxy; iy++ )
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000995 {
Alexandre Julliard77b99181997-09-14 17:17:23 +0000996 unsigned shift = iy % 2;
Alexandre Julliard75d86e11996-11-17 18:59:11 +0000997
Alexandre Julliard77b99181997-09-14 17:17:23 +0000998 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
999 (and_width > 4) ? 4 : and_width );
1000 for( ix = 0; ix < maxx; ix++ )
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001001 {
1002 if( bSemiTransparent && ((ix+shift)%2) )
1003 {
Alexandre Julliard77b99181997-09-14 17:17:23 +00001004 /* set AND bit, XOR bit stays 0 */
1005
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001006 pbc = pAndBits + iy * 4 + ix/8;
1007 *pbc |= 0x80 >> (ix%8);
1008 }
1009 else
1010 {
Alexandre Julliard77b99181997-09-14 17:17:23 +00001011 /* keep AND bit, set XOR bit */
1012
1013 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
1014 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +00001015 if(!PALETTE_Driver->pIsDark(val))
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001016 {
1017 pbc = pxbPtr + ix/8;
1018 *pbc |= 0x80 >> (ix%8);
1019 }
1020 }
1021 }
Alexandre Julliard77b99181997-09-14 17:17:23 +00001022 psPtr += xor_width;
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001023 pxbPtr += 4;
1024 }
Alexandre Julliard77b99181997-09-14 17:17:23 +00001025
Alexandre Julliard7d5bc5c2001-01-15 20:09:09 +00001026 hRet = CreateCursorIconIndirect16( 0 , &cI, pAndBits, pXorBits);
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001027
1028 if( !hRet ) /* fall back on default drag cursor */
Alexandre Julliard7d5bc5c2001-01-15 20:09:09 +00001029 hRet = CURSORICON_Copy( 0 ,
Ulrich Weigand50a09151999-03-10 14:00:29 +00001030 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
Marcus Meissnerddca3151999-05-22 11:33:23 +00001031 GetSystemMetrics(SM_CXCURSOR),
1032 GetSystemMetrics(SM_CYCURSOR), 1, TRUE, 0) );
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001033 }
Alexandre Julliardade697e1995-11-26 13:59:11 +00001034
Alexandre Julliard75d86e11996-11-17 18:59:11 +00001035 return hRet;
Alexandre Julliardade697e1995-11-26 13:59:11 +00001036}
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001037
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001038
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001039/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001040 * LoadCursor (USER.173)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001041 */
Alexandre Julliardac7efef2000-11-27 21:54:01 +00001042HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, LPCSTR name )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001043{
Alexandre Julliardac7efef2000-11-27 21:54:01 +00001044 return LoadCursorA( hInstance, name );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001045}
1046
1047
1048/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001049 * LoadIcon (USER.174)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001050 */
Alexandre Julliardac7efef2000-11-27 21:54:01 +00001051HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, LPCSTR name )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001052{
Alexandre Julliardac7efef2000-11-27 21:54:01 +00001053 return LoadIconA( hInstance, name );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001054}
1055
1056
1057/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001058 * CreateCursor (USER.406)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001059 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001060HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
1061 INT16 xHotSpot, INT16 yHotSpot,
1062 INT16 nWidth, INT16 nHeight,
1063 LPCVOID lpANDbits, LPCVOID lpXORbits )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001064{
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001065 CURSORICONINFO info;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001066
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001067 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001068 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001069
1070 info.ptHotSpot.x = xHotSpot;
1071 info.ptHotSpot.y = yHotSpot;
1072 info.nWidth = nWidth;
1073 info.nHeight = nHeight;
1074 info.nWidthBytes = 0;
1075 info.bPlanes = 1;
1076 info.bBitsPerPixel = 1;
1077
Alexandre Julliarda3960291999-02-26 11:11:13 +00001078 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001079}
1080
1081
1082/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001083 * CreateCursor (USER32.@)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001084 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001085HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
1086 INT xHotSpot, INT yHotSpot,
1087 INT nWidth, INT nHeight,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001088 LPCVOID lpANDbits, LPCVOID lpXORbits )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001089{
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001090 CURSORICONINFO info;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001091
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001092 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001093 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001094
1095 info.ptHotSpot.x = xHotSpot;
1096 info.ptHotSpot.y = yHotSpot;
1097 info.nWidth = nWidth;
1098 info.nHeight = nHeight;
1099 info.nWidthBytes = 0;
1100 info.bPlanes = 1;
1101 info.bBitsPerPixel = 1;
1102
Alexandre Julliarda3960291999-02-26 11:11:13 +00001103 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001104}
1105
1106
1107/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001108 * CreateIcon (USER.407)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001109 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001110HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
1111 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
1112 LPCVOID lpANDbits, LPCVOID lpXORbits )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001113{
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001114 CURSORICONINFO info;
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001115
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001116 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001117 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001118
Francis Beaudet699900b1999-09-05 12:15:49 +00001119 info.ptHotSpot.x = ICON_HOTSPOT;
1120 info.ptHotSpot.y = ICON_HOTSPOT;
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001121 info.nWidth = nWidth;
1122 info.nHeight = nHeight;
1123 info.nWidthBytes = 0;
1124 info.bPlanes = bPlanes;
1125 info.bBitsPerPixel = bBitsPixel;
1126
Alexandre Julliarda3960291999-02-26 11:11:13 +00001127 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001128}
1129
1130
1131/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001132 * CreateIcon (USER32.@)
François Gouget2c865062001-02-13 01:48:14 +00001133 *
1134 * Creates an icon based on the specified bitmaps. The bitmaps must be
1135 * provided in a device dependent format and will be resized to
1136 * (SM_CXICON,SM_CYICON) and depth converted to match the screen's color
1137 * depth. The provided bitmaps must be top-down bitmaps.
1138 * Although Windows does not support 15bpp(*) this API must support it
1139 * for Winelib applications.
1140 *
1141 * (*) Windows does not support 15bpp but it supports the 555 RGB 16bpp
1142 * format!
1143 *
1144 * BUGS
1145 *
1146 * - The provided bitmaps are not resized!
1147 * - The documentation says the lpXORbits bitmap must be in a device
1148 * dependent format. But we must still resize it and perform depth
1149 * conversions if necessary.
1150 * - I'm a bit unsure about the how the 'device dependent format' thing works.
1151 * I did some tests on windows and found that if you provide a 16bpp bitmap
1152 * in lpXORbits, then its format but be 565 RGB if the screen's bit depth
1153 * is 16bpp but it must be 555 RGB if the screen's bit depth is anything
1154 * else. I don't know if this is part of the GDI specs or if this is a
1155 * quirk of the graphics card driver.
1156 * - You may think that we check whether the bit depths match or not
1157 * as an optimization. But the truth is that the conversion using
1158 * CreateDIBitmap does not work for some bit depth (e.g. 8bpp) and I have
1159 * no idea why.
1160 * - I'm pretty sure that all the things we do in CreateIcon should
1161 * also be done in CreateIconIndirect...
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001162 */
François Gouget2c865062001-02-13 01:48:14 +00001163HICON WINAPI CreateIcon(
Patrik Stridvallb3086a72001-04-25 19:54:21 +00001164 HINSTANCE hInstance, /* [in] the application's hInstance, currently unused */
1165 INT nWidth, /* [in] the width of the provided bitmaps */
1166 INT nHeight, /* [in] the height of the provided bitmaps */
1167 BYTE bPlanes, /* [in] the number of planes in the provided bitmaps */
1168 BYTE bBitsPixel, /* [in] the number of bits per pixel of the lpXORbits bitmap */
1169 LPCVOID lpANDbits, /* [in] a monochrome bitmap representing the icon's mask */
1170 LPCVOID lpXORbits) /* [in] the icon's 'color' bitmap */
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001171{
François Gouget2c865062001-02-13 01:48:14 +00001172 HICON hIcon;
1173 HDC hdc;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001174
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001175 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
François Gouget2c865062001-02-13 01:48:14 +00001176 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001177
François Gouget2c865062001-02-13 01:48:14 +00001178 hdc=GetDC(0);
1179 if (!hdc)
1180 return 0;
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001181
François Gouget2c865062001-02-13 01:48:14 +00001182 if (GetDeviceCaps(hdc,BITSPIXEL)==bBitsPixel) {
1183 CURSORICONINFO info;
1184
1185 info.ptHotSpot.x = ICON_HOTSPOT;
1186 info.ptHotSpot.y = ICON_HOTSPOT;
1187 info.nWidth = nWidth;
1188 info.nHeight = nHeight;
1189 info.nWidthBytes = 0;
1190 info.bPlanes = bPlanes;
1191 info.bBitsPerPixel = bBitsPixel;
1192
1193 hIcon=CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1194 } else {
1195 ICONINFO iinfo;
1196 BITMAPINFO bmi;
1197
1198 iinfo.fIcon=TRUE;
1199 iinfo.xHotspot=ICON_HOTSPOT;
1200 iinfo.yHotspot=ICON_HOTSPOT;
1201 iinfo.hbmMask=CreateBitmap(nWidth,nHeight,1,1,lpANDbits);
1202
1203 bmi.bmiHeader.biSize=sizeof(bmi.bmiHeader);
1204 bmi.bmiHeader.biWidth=nWidth;
1205 bmi.bmiHeader.biHeight=-nHeight;
1206 bmi.bmiHeader.biPlanes=bPlanes;
1207 bmi.bmiHeader.biBitCount=bBitsPixel;
1208 bmi.bmiHeader.biCompression=BI_RGB;
1209 bmi.bmiHeader.biSizeImage=0;
1210 bmi.bmiHeader.biXPelsPerMeter=0;
1211 bmi.bmiHeader.biYPelsPerMeter=0;
1212 bmi.bmiHeader.biClrUsed=0;
1213 bmi.bmiHeader.biClrImportant=0;
1214
1215 iinfo.hbmColor = CreateDIBitmap( hdc, &bmi.bmiHeader,
1216 CBM_INIT, lpXORbits,
1217 &bmi, DIB_RGB_COLORS );
1218
1219 hIcon=CreateIconIndirect(&iinfo);
1220 DeleteObject(iinfo.hbmMask);
1221 DeleteObject(iinfo.hbmColor);
1222 }
1223 ReleaseDC(0,hdc);
1224 return hIcon;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001225}
1226
1227
1228/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001229 * CreateCursorIconIndirect (USER.408)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001230 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001231HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001232 CURSORICONINFO *info,
1233 LPCVOID lpANDbits,
1234 LPCVOID lpXORbits )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001235{
Alexandre Julliardbf9130a1996-10-13 17:45:47 +00001236 HGLOBAL16 handle;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001237 char *ptr;
1238 int sizeAnd, sizeXor;
1239
1240 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001241 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
Huw D M Davies82617361998-11-01 16:35:42 +00001242 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001243 sizeXor = info->nHeight * info->nWidthBytes;
Huw D M Davies82617361998-11-01 16:35:42 +00001244 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001245 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001246 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1247 return 0;
Alexandre Julliard7d5bc5c2001-01-15 20:09:09 +00001248 FarSetOwner16( handle, hInstance );
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001249 ptr = (char *)GlobalLock16( handle );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001250 memcpy( ptr, info, sizeof(*info) );
1251 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1252 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001253 GlobalUnlock16( handle );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001254 return handle;
1255}
1256
1257
1258/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001259 * CopyIcon (USER.368)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001260 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001261HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001262{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001263 TRACE_(icon)("%04x %04x\n", hInstance, hIcon );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001264 return CURSORICON_Copy( hInstance, hIcon );
1265}
1266
1267
1268/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001269 * CopyIcon (USER32.@)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001270 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001271HICON WINAPI CopyIcon( HICON hIcon )
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001272{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001273 TRACE_(icon)("%04x\n", hIcon );
Alexandre Julliard7d5bc5c2001-01-15 20:09:09 +00001274 return CURSORICON_Copy( 0, hIcon );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001275}
Alexandre Julliardca22b331996-07-12 19:02:39 +00001276
1277
1278/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001279 * CopyCursor (USER.369)
Alexandre Julliardca22b331996-07-12 19:02:39 +00001280 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001281HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001282{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001283 TRACE_(cursor)("%04x %04x\n", hInstance, hCursor );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001284 return CURSORICON_Copy( hInstance, hCursor );
1285}
1286
Ulrich Weigand50a09151999-03-10 14:00:29 +00001287/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001288 * DestroyIcon32 (USER.610)
Ulrich Weigand50a09151999-03-10 14:00:29 +00001289 *
1290 * This routine is actually exported from Win95 USER under the name
1291 * DestroyIcon32 ... The behaviour implemented here should mimic
1292 * the Win95 one exactly, especially the return values, which
1293 * depend on the setting of various flags.
1294 */
Marcus Meissnerc600afb1999-03-24 14:55:37 +00001295WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
Ulrich Weigand50a09151999-03-10 14:00:29 +00001296{
1297 WORD retv;
1298
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001299 TRACE_(icon)("(%04x, %04x)\n", handle, flags );
Ulrich Weigand50a09151999-03-10 14:00:29 +00001300
1301 /* Check whether destroying active cursor */
1302
1303 if ( hActiveCursor == handle )
1304 {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001305 ERR_(cursor)("Destroying active cursor!\n" );
Ulrich Weigand50a09151999-03-10 14:00:29 +00001306 SetCursor( 0 );
1307 }
1308
1309 /* Try shared cursor/icon first */
1310
1311 if ( !(flags & CID_NONSHARED) )
1312 {
1313 INT count = CURSORICON_DelSharedIcon( handle );
1314
1315 if ( count != -1 )
1316 return (flags & CID_WIN32)? TRUE : (count == 0);
1317
1318 /* FIXME: OEM cursors/icons should be recognized */
1319 }
1320
1321 /* Now assume non-shared cursor/icon */
1322
1323 retv = GlobalFree16( handle );
1324 return (flags & CID_RESOURCE)? retv : TRUE;
1325}
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001326
1327/***********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00001328 * DestroyIcon (USER.457)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001329 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001330BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001331{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001332 return CURSORICON_Destroy( hIcon, 0 );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001333}
1334
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001335/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001336 * DestroyIcon (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001337 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001338BOOL WINAPI DestroyIcon( HICON hIcon )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001339{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001340 return CURSORICON_Destroy( hIcon, CID_WIN32 );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001341}
1342
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001343/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001344 * DestroyCursor (USER.458)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001345 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001346BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001347{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001348 return CURSORICON_Destroy( hCursor, 0 );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001349}
1350
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001351/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001352 * DestroyCursor (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001353 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001354BOOL WINAPI DestroyCursor( HCURSOR hCursor )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001355{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001356 return CURSORICON_Destroy( hCursor, CID_WIN32 );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001357}
1358
1359
1360/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001361 * DrawIcon (USER.84)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001362 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001363BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001364{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001365 return DrawIcon( hdc, x, y, hIcon );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001366}
1367
1368
1369/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001370 * DrawIcon (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001371 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001372BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001373{
1374 CURSORICONINFO *ptr;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001375 HDC hMemDC;
1376 HBITMAP hXorBits, hAndBits;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001377 COLORREF oldFg, oldBg;
1378
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001379 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001380 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1381 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
Alexandre Julliard21979011997-03-05 08:22:35 +00001382 (char *)(ptr+1) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001383 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
Alexandre Julliard21979011997-03-05 08:22:35 +00001384 ptr->bBitsPerPixel, (char *)(ptr + 1)
Huw D M Davies82617361998-11-01 16:35:42 +00001385 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001386 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1387 oldBg = SetBkColor( hdc, RGB(255,255,255) );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001388
1389 if (hXorBits && hAndBits)
1390 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001391 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1392 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1393 SelectObject( hMemDC, hXorBits );
1394 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1395 SelectObject( hMemDC, hBitTemp );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001396 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001397 DeleteDC( hMemDC );
1398 if (hXorBits) DeleteObject( hXorBits );
1399 if (hAndBits) DeleteObject( hAndBits );
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001400 GlobalUnlock16( hIcon );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001401 SetTextColor( hdc, oldFg );
1402 SetBkColor( hdc, oldBg );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001403 return TRUE;
1404}
1405
1406
1407/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001408 * IconSize (USER.86)
Andreas Mohr1f0c2162000-06-24 12:54:00 +00001409 *
1410 * See "Undocumented Windows". Used by W2.0 paint.exe.
1411 */
1412DWORD WINAPI IconSize16( void )
1413{
1414 return MAKELONG(GetSystemMetrics(SM_CYICON), GetSystemMetrics(SM_CXICON));
1415}
1416
1417
1418/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001419 * DumpIcon (USER.459)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001420 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001421DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001422 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001423{
Alexandre Julliard982a2232000-12-13 20:20:09 +00001424 CURSORICONINFO *info = MapSL( pInfo );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001425 int sizeAnd, sizeXor;
1426
1427 if (!info) return 0;
1428 sizeXor = info->nHeight * info->nWidthBytes;
Huw D M Davies82617361998-11-01 16:35:42 +00001429 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
Alexandre Julliardade697e1995-11-26 13:59:11 +00001430 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1431 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001432 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1433 return MAKELONG( sizeXor, sizeXor );
1434}
1435
1436
1437/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001438 * SetCursor (USER.69)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001439 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001440HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001441{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001442 return (HCURSOR16)SetCursor( hCursor );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001443}
1444
1445
1446/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001447 * SetCursor (USER32.@)
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001448 * RETURNS:
1449 * A handle to the previous cursor shape.
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001450 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001451HCURSOR WINAPI SetCursor(
Patrik Stridvall2b3aa612000-12-01 23:58:28 +00001452 HCURSOR hCursor /* [in] Handle of cursor to show */
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001453) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001454 HCURSOR hOldCursor;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001455
1456 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001457 TRACE_(cursor)("%04x\n", hCursor );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001458 hOldCursor = hActiveCursor;
1459 hActiveCursor = hCursor;
1460 /* Change the cursor shape only if it is visible */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001461 if (CURSOR_ShowCount >= 0)
Alexandre Julliard03468f71998-02-15 19:40:49 +00001462 {
Alexandre Julliard42d20f92000-08-10 01:16:19 +00001463 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
Ulrich Weigand431d1a01998-11-14 18:57:47 +00001464 GlobalUnlock16( hActiveCursor );
Alexandre Julliard03468f71998-02-15 19:40:49 +00001465 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001466 return hOldCursor;
1467}
1468
1469
1470/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001471 * ShowCursor (USER.71)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001472 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001473INT16 WINAPI ShowCursor16( BOOL16 bShow )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001474{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001475 return ShowCursor( bShow );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001476}
1477
1478
1479/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001480 * ShowCursor (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001481 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001482INT WINAPI ShowCursor( BOOL bShow )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001483{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001484 TRACE_(cursor)("%d, count=%d\n",
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001485 bShow, CURSOR_ShowCount );
1486
1487 if (bShow)
1488 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001489 if (++CURSOR_ShowCount == 0) /* Show it */
Ulrich Weigand431d1a01998-11-14 18:57:47 +00001490 {
Alexandre Julliard42d20f92000-08-10 01:16:19 +00001491 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
Ulrich Weigand431d1a01998-11-14 18:57:47 +00001492 GlobalUnlock16( hActiveCursor );
1493 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001494 }
1495 else
1496 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001497 if (--CURSOR_ShowCount == -1) /* Hide it */
Alexandre Julliard42d20f92000-08-10 01:16:19 +00001498 USER_Driver.pSetCursor( NULL );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001499 }
1500 return CURSOR_ShowCount;
1501}
1502
1503
1504/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001505 * GetCursor (USER.247)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001506 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001507HCURSOR16 WINAPI GetCursor16(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001508{
1509 return hActiveCursor;
1510}
1511
1512
1513/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001514 * GetCursor (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001515 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001516HCURSOR WINAPI GetCursor(void)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001517{
1518 return hActiveCursor;
1519}
1520
1521
1522/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001523 * ClipCursor (USER.16)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001524 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001525BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001526{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001527 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001528 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001529 return TRUE;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001530}
1531
1532
1533/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001534 * ClipCursor (USER32.@)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001535 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001536BOOL WINAPI ClipCursor( const RECT *rect )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001537{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001538 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1539 else CopyRect( &CURSOR_ClipRect, rect );
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001540 return TRUE;
1541}
1542
1543
1544/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001545 * GetClipCursor (USER.309)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001546 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001547void WINAPI GetClipCursor16( RECT16 *rect )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001548{
1549 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1550}
1551
1552
1553/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001554 * GetClipCursor (USER32.@)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001555 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001556BOOL WINAPI GetClipCursor( RECT *rect )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001557{
Eric Pouechb9544f11999-02-14 14:09:42 +00001558 if (rect)
1559 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001560 CopyRect( rect, &CURSOR_ClipRect );
Eric Pouechb9544f11999-02-14 14:09:42 +00001561 return TRUE;
1562 }
1563 return FALSE;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001564}
1565
Alexandre Julliard77b99181997-09-14 17:17:23 +00001566/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001567 * LookupIconIdFromDirectoryEx (USER.364)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001568 *
1569 * FIXME: exact parameter sizes
1570 */
Alexandre Julliarde658d821997-11-30 17:45:40 +00001571INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
Alexandre Julliard77b99181997-09-14 17:17:23 +00001572 INT16 width, INT16 height, UINT16 cFlag )
1573{
Alexandre Julliarde658d821997-11-30 17:45:40 +00001574 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
Alexandre Julliard77b99181997-09-14 17:17:23 +00001575 UINT16 retVal = 0;
1576 if( dir && !dir->idReserved && (dir->idType & 3) )
1577 {
Juergen Schmiedc45bbee1999-04-11 11:46:32 +00001578 CURSORICONDIRENTRY* entry;
Pavel Roskin5b14b531999-04-18 09:34:51 +00001579 HDC hdc;
1580 UINT palEnts;
1581 int colors;
1582 hdc = GetDC(0);
1583 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1584 if (palEnts == 0)
1585 palEnts = 256;
1586 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
Juergen Schmiedc45bbee1999-04-11 11:46:32 +00001587
Alexandre Julliarda3960291999-02-26 11:11:13 +00001588 ReleaseDC(0, hdc);
Huw D M Daviesa38d84d1998-11-30 11:18:26 +00001589
Alexandre Julliard77b99181997-09-14 17:17:23 +00001590 if( bIcon )
Alexandre Julliard77b99181997-09-14 17:17:23 +00001591 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001592 else
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001593 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
Juergen Schmiedc45bbee1999-04-11 11:46:32 +00001594
1595 if( entry ) retVal = entry->wResId;
Alexandre Julliard77b99181997-09-14 17:17:23 +00001596 }
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001597 else WARN_(cursor)("invalid resource directory\n");
Alexandre Julliard77b99181997-09-14 17:17:23 +00001598 return retVal;
1599}
1600
1601/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001602 * LookupIconIdFromDirectoryEx (USER32.@)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001603 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001604INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1605 INT width, INT height, UINT cFlag )
Alexandre Julliard77b99181997-09-14 17:17:23 +00001606{
1607 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1608}
1609
1610/**********************************************************************
Patrik Stridvall044855c2001-07-11 18:56:41 +00001611 * LookupIconIdFromDirectory (USER.?)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001612 */
Alexandre Julliarde658d821997-11-30 17:45:40 +00001613INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
Alexandre Julliard77b99181997-09-14 17:17:23 +00001614{
1615 return LookupIconIdFromDirectoryEx16( dir, bIcon,
Marcus Meissnerddca3151999-05-22 11:33:23 +00001616 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1617 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001618}
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001619
1620/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001621 * LookupIconIdFromDirectory (USER32.@)
Alexandre Julliarde658d821997-11-30 17:45:40 +00001622 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001623INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
Alexandre Julliarde658d821997-11-30 17:45:40 +00001624{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001625 return LookupIconIdFromDirectoryEx( dir, bIcon,
Marcus Meissnerddca3151999-05-22 11:33:23 +00001626 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1627 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
Alexandre Julliarde658d821997-11-30 17:45:40 +00001628}
1629
1630/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001631 * GetIconID (USER.455)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001632 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001633WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001634{
Alexandre Julliarde658d821997-11-30 17:45:40 +00001635 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001636
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001637 TRACE_(cursor)("hRes=%04x, entries=%i\n",
Alexandre Julliarde658d821997-11-30 17:45:40 +00001638 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001639
1640 switch(resType)
1641 {
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001642 case RT_CURSOR16:
Alexandre Julliard77b99181997-09-14 17:17:23 +00001643 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
Marcus Meissnerddca3151999-05-22 11:33:23 +00001644 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001645 case RT_ICON16:
Alexandre Julliard77b99181997-09-14 17:17:23 +00001646 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
Marcus Meissnerddca3151999-05-22 11:33:23 +00001647 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0 );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001648 default:
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001649 WARN_(cursor)("invalid res type %ld\n", resType );
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001650 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001651 return 0;
1652}
1653
Alexandre Julliard77b99181997-09-14 17:17:23 +00001654/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001655 * LoadCursorIconHandler (USER.336)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001656 *
1657 * Supposed to load resources of Windows 2.x applications.
1658 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001659HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
Alexandre Julliard77b99181997-09-14 17:17:23 +00001660{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001661 FIXME_(cursor)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
Alexandre Julliard54c27111998-03-29 19:44:57 +00001662 hResource, hModule, hRsrc);
Alexandre Julliard77b99181997-09-14 17:17:23 +00001663 return (HGLOBAL16)0;
1664}
1665
1666/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001667 * LoadDIBIconHandler (USER.357)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001668 *
1669 * RT_ICON resource loader, installed by USER_SignalProc when module
1670 * is initialized.
1671 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001672HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
Alexandre Julliard77b99181997-09-14 17:17:23 +00001673{
1674 /* If hResource is zero we must allocate a new memory block, if it's
1675 * non-zero but GlobalLock() returns NULL then it was discarded and
1676 * we have to recommit some memory, otherwise we just need to check
1677 * the block size. See LoadProc() in 16-bit SDK for more.
1678 */
1679
Ulrich Weigand50a09151999-03-10 14:00:29 +00001680 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001681 if( hMemObj )
1682 {
1683 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1684 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1685 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
Marcus Meissnerddca3151999-05-22 11:33:23 +00001686 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001687 }
1688 return hMemObj;
1689}
1690
1691/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001692 * LoadDIBCursorHandler (USER.356)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001693 *
1694 * RT_CURSOR resource loader. Same as above.
1695 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001696HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
Alexandre Julliard77b99181997-09-14 17:17:23 +00001697{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001698 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001699 if( hMemObj )
1700 {
1701 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1702 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1703 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
Marcus Meissnerddca3151999-05-22 11:33:23 +00001704 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001705 }
1706 return hMemObj;
1707}
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001708
1709/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001710 * LoadIconHandler (USER.456)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001711 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001712HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001713{
Alexandre Julliard77b99181997-09-14 17:17:23 +00001714 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1715
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001716 TRACE_(cursor)("hRes=%04x\n",hResource);
Alexandre Julliard7e56f681996-01-31 19:02:28 +00001717
Alexandre Julliard77b99181997-09-14 17:17:23 +00001718 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1719 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1720}
1721
1722/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001723 * LoadCursorW (USER32.@)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001724 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001725HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001726{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001727 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1728 LR_SHARED | LR_DEFAULTSIZE );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001729}
1730
1731/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001732 * LoadCursorA (USER32.@)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001733 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001734HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001735{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001736 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1737 LR_SHARED | LR_DEFAULTSIZE );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00001738}
Alexandre Julliard77b99181997-09-14 17:17:23 +00001739
1740/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001741 * LoadCursorFromFileW (USER32.@)
1742 */
Ulrich Weigand50a09151999-03-10 14:00:29 +00001743HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1744{
1745 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1746 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1747}
1748
1749/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001750 * LoadCursorFromFileA (USER32.@)
1751 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001752HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001753{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001754 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1755 LR_LOADFROMFILE | LR_DEFAULTSIZE );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00001756}
1757
1758/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001759 * LoadIconW (USER32.@)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001760 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001761HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001762{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001763 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1764 LR_SHARED | LR_DEFAULTSIZE );
Alexandre Julliard77b99181997-09-14 17:17:23 +00001765}
1766
1767/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001768 * LoadIconA (USER32.@)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001769 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001770HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001771{
Ulrich Weigand50a09151999-03-10 14:00:29 +00001772 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1773 LR_SHARED | LR_DEFAULTSIZE );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001774}
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001775
1776/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001777 * GetIconInfo (USER.395)
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001778 */
Marcus Meissnerffb912e1999-01-28 09:14:38 +00001779BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
Andreas Mohr22c904d1999-01-26 14:56:01 +00001780{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001781 ICONINFO ii32;
1782 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
Marcus Meissnerffb912e1999-01-28 09:14:38 +00001783
1784 iconinfo->fIcon = ii32.fIcon;
1785 iconinfo->xHotspot = ii32.xHotspot;
1786 iconinfo->yHotspot = ii32.yHotspot;
1787 iconinfo->hbmMask = ii32.hbmMask;
1788 iconinfo->hbmColor = ii32.hbmColor;
1789 return ret;
Andreas Mohr22c904d1999-01-26 14:56:01 +00001790}
1791
1792/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001793 * GetIconInfo (USER32.@)
Andreas Mohr22c904d1999-01-26 14:56:01 +00001794 */
Francois Gouget67c96912000-10-12 23:18:55 +00001795BOOL WINAPI GetIconInfo(HICON hIcon,PICONINFO iconinfo) {
Alexandre Julliard491502b1997-11-01 19:08:16 +00001796 CURSORICONINFO *ciconinfo;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001797
Alexandre Julliard491502b1997-11-01 19:08:16 +00001798 ciconinfo = GlobalLock16(hIcon);
1799 if (!ciconinfo)
1800 return FALSE;
Francis Beaudet699900b1999-09-05 12:15:49 +00001801
1802 if ( (ciconinfo->ptHotSpot.x == ICON_HOTSPOT) &&
1803 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT) )
1804 {
1805 iconinfo->fIcon = TRUE;
Dave Hawkesdbb6ab22000-07-09 12:16:58 +00001806 iconinfo->xHotspot = ciconinfo->nWidth / 2;
1807 iconinfo->yHotspot = ciconinfo->nHeight / 2;
Francis Beaudet699900b1999-09-05 12:15:49 +00001808 }
1809 else
1810 {
1811 iconinfo->fIcon = FALSE;
1812 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1813 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1814 }
Alexandre Julliard829fe321998-07-26 14:27:39 +00001815
Alexandre Julliarda3960291999-02-26 11:11:13 +00001816 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
Alexandre Julliard829fe321998-07-26 14:27:39 +00001817 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1818 (char *)(ciconinfo + 1)
1819 + ciconinfo->nHeight *
Huw D M Davies82617361998-11-01 16:35:42 +00001820 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001821 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
Alexandre Julliard829fe321998-07-26 14:27:39 +00001822 1, 1, (char *)(ciconinfo + 1));
1823
1824 GlobalUnlock16(hIcon);
1825
Alexandre Julliard491502b1997-11-01 19:08:16 +00001826 return TRUE;
1827}
1828
1829/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001830 * CreateIconIndirect (USER32.@)
Alexandre Julliard491502b1997-11-01 19:08:16 +00001831 */
Francois Gouget67c96912000-10-12 23:18:55 +00001832HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001833{
1834 BITMAP bmpXor,bmpAnd;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001835 HICON hObj;
Alexandre Julliard491502b1997-11-01 19:08:16 +00001836 int sizeXor,sizeAnd;
1837
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001838 GetObjectA( iconinfo->hbmColor, sizeof(bmpXor), &bmpXor );
1839 GetObjectA( iconinfo->hbmMask, sizeof(bmpAnd), &bmpAnd );
Alexandre Julliard491502b1997-11-01 19:08:16 +00001840
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001841 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
1842 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
Alexandre Julliard491502b1997-11-01 19:08:16 +00001843
1844 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1845 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1846 if (hObj)
1847 {
1848 CURSORICONINFO *info;
1849
1850 info = (CURSORICONINFO *)GlobalLock16( hObj );
Francis Beaudet699900b1999-09-05 12:15:49 +00001851
1852 /* If we are creating an icon, the hotspot is unused */
1853 if (iconinfo->fIcon)
1854 {
1855 info->ptHotSpot.x = ICON_HOTSPOT;
1856 info->ptHotSpot.y = ICON_HOTSPOT;
1857 }
1858 else
1859 {
1860 info->ptHotSpot.x = iconinfo->xHotspot;
1861 info->ptHotSpot.y = iconinfo->yHotspot;
1862 }
1863
Alexandre Julliardb0efe282000-08-04 04:18:04 +00001864 info->nWidth = bmpXor.bmWidth;
1865 info->nHeight = bmpXor.bmHeight;
1866 info->nWidthBytes = bmpXor.bmWidthBytes;
1867 info->bPlanes = bmpXor.bmPlanes;
1868 info->bBitsPerPixel = bmpXor.bmBitsPixel;
Alexandre Julliard491502b1997-11-01 19:08:16 +00001869
1870 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1871
Alexandre Julliarda3960291999-02-26 11:11:13 +00001872 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1873 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
Alexandre Julliard491502b1997-11-01 19:08:16 +00001874 GlobalUnlock16( hObj );
1875 }
1876 return hObj;
1877}
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001878
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001879
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001880/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001881 * DrawIconEx (USER.394)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001882 */
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001883BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1884 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1885 HBRUSH16 hbr, UINT16 flags)
1886{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001887 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001888 istep, hbr, flags);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001889}
1890
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001891
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001892/******************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001893 * DrawIconEx (USER32.@) Draws an icon or cursor on device context
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001894 *
1895 * NOTES
1896 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1897 *
1898 * PARAMS
1899 * hdc [I] Handle to device context
1900 * x0 [I] X coordinate of upper left corner
1901 * y0 [I] Y coordinate of upper left corner
1902 * hIcon [I] Handle to icon to draw
1903 * cxWidth [I] Width of icon
1904 * cyWidth [I] Height of icon
1905 * istep [I] Index of frame in animated cursor
1906 * hbr [I] Handle to background brush
1907 * flags [I] Icon-drawing flags
1908 *
1909 * RETURNS
1910 * Success: TRUE
1911 * Failure: FALSE
1912 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001913BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1914 INT cxWidth, INT cyWidth, UINT istep,
1915 HBRUSH hbr, UINT flags )
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001916{
1917 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001918 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
Alexandre Julliard2a2321b2000-08-19 21:38:55 +00001919 BOOL result = FALSE, DoOffscreen;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001920 HBITMAP hB_off = 0, hOld = 0;
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001921
1922 if (!ptr) return FALSE;
Marcus Meissner9199f4a2000-11-01 21:36:35 +00001923 TRACE_(icon)("(hdc=%x,pos=%d.%d,hicon=%x,extend=%d.%d,istep=%d,br=%x,flags=0x%08x)\n",
1924 hdc,x0,y0,hIcon,cxWidth,cyWidth,istep,hbr,flags
1925 );
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001926
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001927 if (istep)
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001928 FIXME_(icon)("Ignoring istep=%d\n", istep);
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001929 if (flags & DI_COMPAT)
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001930 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001931
Marcus Meissner9199f4a2000-11-01 21:36:35 +00001932 if (!flags) {
1933 FIXME_(icon)("no flags set? setting to DI_NORMAL\n");
1934 flags = DI_NORMAL;
1935 }
1936
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001937 /* Calculate the size of the destination image. */
1938 if (cxWidth == 0)
Jesper Skov5c3e4571998-11-01 19:27:22 +00001939 {
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001940 if (flags & DI_DEFAULTSIZE)
Alexandre Julliarda3960291999-02-26 11:11:13 +00001941 cxWidth = GetSystemMetrics (SM_CXICON);
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001942 else
1943 cxWidth = ptr->nWidth;
Jesper Skov5c3e4571998-11-01 19:27:22 +00001944 }
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001945 if (cyWidth == 0)
Jesper Skov5c3e4571998-11-01 19:27:22 +00001946 {
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001947 if (flags & DI_DEFAULTSIZE)
Alexandre Julliarda3960291999-02-26 11:11:13 +00001948 cyWidth = GetSystemMetrics (SM_CYICON);
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001949 else
1950 cyWidth = ptr->nHeight;
Jesper Skov5c3e4571998-11-01 19:27:22 +00001951 }
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001952
Alexandre Julliard2a2321b2000-08-19 21:38:55 +00001953 DoOffscreen = (GetObjectType( hbr ) == OBJ_BRUSH);
1954
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001955 if (DoOffscreen) {
Patrik Stridvalla9a671d1999-04-25 19:01:52 +00001956 RECT r;
1957
1958 r.left = 0;
1959 r.top = 0;
1960 r.right = cxWidth;
1961 r.bottom = cxWidth;
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001962
Alexandre Julliarda3960291999-02-26 11:11:13 +00001963 hDC_off = CreateCompatibleDC(hdc);
1964 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001965 if (hDC_off && hB_off) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001966 hOld = SelectObject(hDC_off, hB_off);
1967 FillRect(hDC_off, &r, hbr);
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001968 }
Alexandre Julliard2a2321b2000-08-19 21:38:55 +00001969 }
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001970
1971 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001972 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001973 HBITMAP hXorBits, hAndBits;
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001974 COLORREF oldFg, oldBg;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001975 INT nStretchMode;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001976
Alexandre Julliarda3960291999-02-26 11:11:13 +00001977 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001978
Alexandre Julliarda3960291999-02-26 11:11:13 +00001979 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001980 ptr->bPlanes, ptr->bBitsPerPixel,
1981 (char *)(ptr + 1)
1982 + ptr->nHeight *
Huw D M Davies82617361998-11-01 16:35:42 +00001983 BITMAP_GetWidthBytes(ptr->nWidth,1) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001984 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001985 1, 1, (char *)(ptr+1) );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001986 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1987 oldBg = SetBkColor( hdc, RGB(255,255,255) );
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001988
1989 if (hXorBits && hAndBits)
1990 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001991 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001992 if (flags & DI_MASK)
Jesper Skov5c3e4571998-11-01 19:27:22 +00001993 {
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001994 if (DoOffscreen)
Alexandre Julliarda3960291999-02-26 11:11:13 +00001995 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
Turchanov Sergey62d6e981998-10-18 13:42:55 +00001996 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1997 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00001998 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001999 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
Jesper Skov5c3e4571998-11-01 19:27:22 +00002000 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00002001 SelectObject( hMemDC, hXorBits );
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00002002 if (flags & DI_IMAGE)
Jesper Skov5c3e4571998-11-01 19:27:22 +00002003 {
Turchanov Sergey62d6e981998-10-18 13:42:55 +00002004 if (DoOffscreen)
Alexandre Julliarda3960291999-02-26 11:11:13 +00002005 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
Turchanov Sergey62d6e981998-10-18 13:42:55 +00002006 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
2007 else
Alexandre Julliarda3960291999-02-26 11:11:13 +00002008 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
Eric Kohl1b1bf2b1998-10-11 13:10:08 +00002009 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
Jesper Skov5c3e4571998-11-01 19:27:22 +00002010 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00002011 SelectObject( hMemDC, hBitTemp );
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00002012 result = TRUE;
2013 }
2014
Alexandre Julliarda3960291999-02-26 11:11:13 +00002015 SetTextColor( hdc, oldFg );
2016 SetBkColor( hdc, oldBg );
2017 if (hXorBits) DeleteObject( hXorBits );
2018 if (hAndBits) DeleteObject( hAndBits );
2019 SetStretchBltMode (hdc, nStretchMode);
Turchanov Sergey62d6e981998-10-18 13:42:55 +00002020 if (DoOffscreen) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002021 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
2022 SelectObject(hDC_off, hOld);
Turchanov Sergey62d6e981998-10-18 13:42:55 +00002023 }
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00002024 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00002025 if (hMemDC) DeleteDC( hMemDC );
2026 if (hDC_off) DeleteDC(hDC_off);
2027 if (hB_off) DeleteObject(hB_off);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00002028 GlobalUnlock16( hIcon );
2029 return result;
2030}
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002031
Alexandre Julliarda660c792000-06-03 20:45:20 +00002032/***********************************************************************
2033 * DIB_FixColorsToLoadflags
2034 *
2035 * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
2036 * are in loadflags
2037 */
2038static void DIB_FixColorsToLoadflags(BITMAPINFO * bmi, UINT loadflags, BYTE pix)
2039{
2040 int colors;
2041 COLORREF c_W, c_S, c_F, c_L, c_C;
2042 int incr,i;
2043 RGBQUAD *ptr;
2044
2045 if (bmi->bmiHeader.biBitCount > 8) return;
2046 if (bmi->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) incr = 4;
2047 else if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) incr = 3;
2048 else {
2049 WARN_(resource)("Wrong bitmap header size!\n");
2050 return;
2051 }
2052 colors = bmi->bmiHeader.biClrUsed;
2053 if (!colors && (bmi->bmiHeader.biBitCount <= 8))
2054 colors = 1 << bmi->bmiHeader.biBitCount;
2055 c_W = GetSysColor(COLOR_WINDOW);
2056 c_S = GetSysColor(COLOR_3DSHADOW);
2057 c_F = GetSysColor(COLOR_3DFACE);
2058 c_L = GetSysColor(COLOR_3DLIGHT);
2059 if (loadflags & LR_LOADTRANSPARENT) {
2060 switch (bmi->bmiHeader.biBitCount) {
2061 case 1: pix = pix >> 7; break;
2062 case 4: pix = pix >> 4; break;
2063 case 8: break;
2064 default:
2065 WARN_(resource)("(%d): Unsupported depth\n", bmi->bmiHeader.biBitCount);
2066 return;
2067 }
2068 if (pix >= colors) {
2069 WARN_(resource)("pixel has color index greater than biClrUsed!\n");
2070 return;
2071 }
2072 if (loadflags & LR_LOADMAP3DCOLORS) c_W = c_F;
2073 ptr = (RGBQUAD*)((char*)bmi->bmiColors+pix*incr);
2074 ptr->rgbBlue = GetBValue(c_W);
2075 ptr->rgbGreen = GetGValue(c_W);
2076 ptr->rgbRed = GetRValue(c_W);
2077 }
2078 if (loadflags & LR_LOADMAP3DCOLORS)
2079 for (i=0; i<colors; i++) {
2080 ptr = (RGBQUAD*)((char*)bmi->bmiColors+i*incr);
2081 c_C = RGB(ptr->rgbRed, ptr->rgbGreen, ptr->rgbBlue);
2082 if (c_C == RGB(128, 128, 128)) {
2083 ptr->rgbRed = GetRValue(c_S);
2084 ptr->rgbGreen = GetGValue(c_S);
2085 ptr->rgbBlue = GetBValue(c_S);
2086 } else if (c_C == RGB(192, 192, 192)) {
2087 ptr->rgbRed = GetRValue(c_F);
2088 ptr->rgbGreen = GetGValue(c_F);
2089 ptr->rgbBlue = GetBValue(c_F);
2090 } else if (c_C == RGB(223, 223, 223)) {
2091 ptr->rgbRed = GetRValue(c_L);
2092 ptr->rgbGreen = GetGValue(c_L);
2093 ptr->rgbBlue = GetBValue(c_L);
2094 }
2095 }
2096}
2097
2098
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002099/**********************************************************************
2100 * BITMAP_Load
2101 */
2102static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
2103{
2104 HBITMAP hbitmap = 0;
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002105 HRSRC hRsrc;
2106 HGLOBAL handle;
2107 char *ptr = NULL;
2108 BITMAPINFO *info, *fix_info=NULL;
2109 HGLOBAL hFix;
2110 int size;
2111
2112 if (!(loadflags & LR_LOADFROMFILE)) {
2113 if (!instance) /* OEM bitmap */
2114 {
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002115 if (HIWORD((int)name)) return 0;
Alexandre Julliard42d20f92000-08-10 01:16:19 +00002116 return USER_Driver.pLoadOEMResource( LOWORD((int)name), OEM_BITMAP );
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002117 }
2118
2119 if (!(hRsrc = FindResourceW( instance, name, RT_BITMAPW ))) return 0;
2120 if (!(handle = LoadResource( instance, hRsrc ))) return 0;
2121
2122 if ((info = (BITMAPINFO *)LockResource( handle )) == NULL) return 0;
2123 }
2124 else
2125 {
Alexandre Julliard982a2232000-12-13 20:20:09 +00002126 if (!(ptr = map_fileW( name ))) return 0;
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002127 info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
2128 }
2129 size = DIB_BitmapInfoSize(info, DIB_RGB_COLORS);
2130 if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
2131 if (fix_info) {
2132 BYTE pix;
2133
2134 memcpy(fix_info, info, size);
2135 pix = *((LPBYTE)info+DIB_BitmapInfoSize(info, DIB_RGB_COLORS));
2136 DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
Alexandre Julliard16cbf402001-01-18 20:32:01 +00002137 if (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
2138 if (screen_dc)
2139 {
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002140 char *bits = (char *)info + size;
2141 if (loadflags & LR_CREATEDIBSECTION) {
2142 DIBSECTION dib;
Alexandre Julliard16cbf402001-01-18 20:32:01 +00002143 hbitmap = CreateDIBSection(screen_dc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002144 GetObjectA(hbitmap, sizeof(DIBSECTION), &dib);
Alexandre Julliard16cbf402001-01-18 20:32:01 +00002145 SetDIBits(screen_dc, hbitmap, 0, dib.dsBm.bmHeight, bits, info,
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002146 DIB_RGB_COLORS);
2147 }
2148 else {
Alexandre Julliard16cbf402001-01-18 20:32:01 +00002149 hbitmap = CreateDIBitmap( screen_dc, &fix_info->bmiHeader, CBM_INIT,
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002150 bits, fix_info, DIB_RGB_COLORS );
2151 }
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002152 }
2153 GlobalUnlock(hFix);
2154 GlobalFree(hFix);
2155 }
2156 if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
2157 return hbitmap;
2158}
2159
2160
2161/***********************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00002162 * LoadImage (USER.389)
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002163 *
2164 */
2165HANDLE16 WINAPI LoadImage16( HINSTANCE16 hinst, LPCSTR name, UINT16 type,
2166 INT16 desiredx, INT16 desiredy, UINT16 loadflags)
2167{
Alexandre Julliarda67369e2000-12-12 00:48:06 +00002168 return LoadImageA( hinst, name, type, desiredx, desiredy, loadflags );
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002169}
2170
2171/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002172 * LoadImageA (USER32.@)
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002173 *
2174 * FIXME: implementation lacks some features, see LR_ defines in windows.h
2175 */
2176
2177HANDLE WINAPI LoadImageA( HINSTANCE hinst, LPCSTR name, UINT type,
2178 INT desiredx, INT desiredy, UINT loadflags)
2179{
2180 HANDLE res;
2181 LPWSTR u_name;
2182
2183 if (HIWORD(name)) u_name = HEAP_strdupAtoW(GetProcessHeap(), 0, name);
2184 else u_name=(LPWSTR)name;
2185 res = LoadImageW(hinst, u_name, type, desiredx, desiredy, loadflags);
2186 if (HIWORD(name)) HeapFree(GetProcessHeap(), 0, u_name);
2187 return res;
2188}
2189
2190
2191/******************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002192 * LoadImageW (USER32.@) Loads an icon, cursor, or bitmap
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002193 *
2194 * PARAMS
2195 * hinst [I] Handle of instance that contains image
2196 * name [I] Name of image
2197 * type [I] Type of image
2198 * desiredx [I] Desired width
2199 * desiredy [I] Desired height
2200 * loadflags [I] Load flags
2201 *
2202 * RETURNS
2203 * Success: Handle to newly loaded image
2204 * Failure: NULL
2205 *
2206 * FIXME: Implementation lacks some features, see LR_ defines in windows.h
2207 */
2208HANDLE WINAPI LoadImageW( HINSTANCE hinst, LPCWSTR name, UINT type,
2209 INT desiredx, INT desiredy, UINT loadflags )
2210{
2211 if (HIWORD(name)) {
2212 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2213 hinst,name,type,desiredx,desiredy,loadflags);
2214 } else {
2215 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2216 hinst,name,type,desiredx,desiredy,loadflags);
2217 }
2218 if (loadflags & LR_DEFAULTSIZE) {
2219 if (type == IMAGE_ICON) {
2220 if (!desiredx) desiredx = GetSystemMetrics(SM_CXICON);
2221 if (!desiredy) desiredy = GetSystemMetrics(SM_CYICON);
2222 } else if (type == IMAGE_CURSOR) {
2223 if (!desiredx) desiredx = GetSystemMetrics(SM_CXCURSOR);
2224 if (!desiredy) desiredy = GetSystemMetrics(SM_CYCURSOR);
2225 }
2226 }
2227 if (loadflags & LR_LOADFROMFILE) loadflags &= ~LR_SHARED;
2228 switch (type) {
2229 case IMAGE_BITMAP:
2230 return BITMAP_Load( hinst, name, loadflags );
2231
2232 case IMAGE_ICON:
Alexandre Julliard16cbf402001-01-18 20:32:01 +00002233 if (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
2234 if (screen_dc)
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002235 {
Alexandre Julliard16cbf402001-01-18 20:32:01 +00002236 UINT palEnts = GetSystemPaletteEntries(screen_dc, 0, 0, NULL);
2237 if (palEnts == 0) palEnts = 256;
2238 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2239 palEnts, FALSE, loadflags);
2240 }
2241 break;
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002242
2243 case IMAGE_CURSOR:
2244 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2245 1, TRUE, loadflags);
2246 }
2247 return 0;
2248}
2249
2250
2251/******************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002252 * CopyImage (USER.390) Creates new image and copies attributes to it
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002253 *
2254 */
2255HICON16 WINAPI CopyImage16( HANDLE16 hnd, UINT16 type, INT16 desiredx,
2256 INT16 desiredy, UINT16 flags )
2257{
2258 return (HICON16)CopyImage((HANDLE)hnd, (UINT)type, (INT)desiredx,
2259 (INT)desiredy, (UINT)flags);
2260}
2261
2262/******************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002263 * CopyImage (USER32.@) Creates new image and copies attributes to it
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002264 *
2265 * PARAMS
2266 * hnd [I] Handle to image to copy
2267 * type [I] Type of image to copy
2268 * desiredx [I] Desired width of new image
2269 * desiredy [I] Desired height of new image
2270 * flags [I] Copy flags
2271 *
2272 * RETURNS
2273 * Success: Handle to newly created image
2274 * Failure: NULL
2275 *
2276 * FIXME: implementation still lacks nearly all features, see LR_*
2277 * defines in windows.h
2278 */
2279HICON WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
2280 INT desiredy, UINT flags )
2281{
2282 switch (type)
2283 {
2284 case IMAGE_BITMAP:
2285 return BITMAP_CopyBitmap(hnd);
2286 case IMAGE_ICON:
2287 return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags);
2288 case IMAGE_CURSOR:
2289 /* Should call CURSORICON_ExtCopy but more testing
2290 * needs to be done before we change this
2291 */
2292 return CopyCursor(hnd);
2293 }
2294 return 0;
2295}
2296
2297
2298/******************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002299 * LoadBitmapW (USER32.@) Loads bitmap from the executable file
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002300 *
2301 * RETURNS
2302 * Success: Handle to specified bitmap
2303 * Failure: NULL
2304 */
2305HBITMAP WINAPI LoadBitmapW(
2306 HINSTANCE instance, /* [in] Handle to application instance */
2307 LPCWSTR name) /* [in] Address of bitmap resource name */
2308{
2309 return LoadImageW( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2310}
2311
2312/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002313 * LoadBitmapA (USER32.@)
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002314 */
2315HBITMAP WINAPI LoadBitmapA( HINSTANCE instance, LPCSTR name )
2316{
2317 return LoadImageA( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2318}
2319
2320/**********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00002321 * LoadBitmap (USER.175)
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002322 */
Alexandre Julliardac7efef2000-11-27 21:54:01 +00002323HBITMAP16 WINAPI LoadBitmap16( HINSTANCE16 instance, LPCSTR name )
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002324{
Alexandre Julliardac7efef2000-11-27 21:54:01 +00002325 return LoadBitmapA( instance, name );
Alexandre Julliardb52aed42000-03-24 21:40:30 +00002326}