Implemented Local32Info, stubs for Local32First/Next (KERNEL.444-446).
[wine/multimedia.git] / objects / cursoricon.c
blob30a8870f80783c39f8b503d66c9a393b1c1a406f
1 /*
2 * Cursor and icon support
4 * Copyright 1995 Alexandre Julliard
5 * 1996 Martin Von Loewis
6 * 1997 Alex Korobka
7 * 1998 Turchanov Sergey
8 */
11 * Theory:
13 * http://www.microsoft.com/win32dev/ui/icons.htm
15 * Cursors and icons are stored in a global heap block, with the
16 * following layout:
18 * CURSORICONINFO info;
19 * BYTE[] ANDbits;
20 * BYTE[] XORbits;
22 * The bits structures are in the format of a device-dependent bitmap.
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 :-(
29 * FIXME: what are we going to do with animation and color (bpp > 1) cursors ?!
32 #include <string.h>
33 #include <stdlib.h>
34 #include "heap.h"
35 #include "windows.h"
36 #include "peexe.h"
37 #include "color.h"
38 #include "bitmap.h"
39 #include "cursoricon.h"
40 #include "sysmetrics.h"
41 #include "global.h"
42 #include "module.h"
43 #include "win.h"
44 #include "debug.h"
45 #include "task.h"
46 #include "user.h"
47 #include "input.h"
48 #include "display.h"
49 #include "message.h"
50 #include "winerror.h"
52 static HCURSOR32 hActiveCursor = 0; /* Active cursor */
53 static INT32 CURSOR_ShowCount = 0; /* Cursor display count */
54 static RECT32 CURSOR_ClipRect; /* Cursor clipping rect */
56 /**********************************************************************
57 * CURSORICON_FindBestIcon
59 * Find the icon closest to the requested size and number of colors.
61 static ICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
62 int height, int colors )
64 int i, maxcolors, maxwidth, maxheight;
65 ICONDIRENTRY *entry, *bestEntry = NULL;
67 if (dir->idCount < 1)
69 WARN(icon, "Empty directory!\n" );
70 return NULL;
72 if (dir->idCount == 1) return &dir->idEntries[0].icon; /* No choice... */
74 /* First find the exact size with less colors */
76 maxcolors = 0;
77 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
78 if ((entry->bWidth == width) && (entry->bHeight == height) &&
79 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
81 bestEntry = entry;
82 maxcolors = entry->bColorCount;
84 if (bestEntry) return bestEntry;
86 /* First find the exact size with more colors */
88 maxcolors = 255;
89 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
90 if ((entry->bWidth == width) && (entry->bHeight == height) &&
91 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
93 bestEntry = entry;
94 maxcolors = entry->bColorCount;
96 if (bestEntry) return bestEntry;
98 /* Now find a smaller one with less colors */
100 maxcolors = maxwidth = maxheight = 0;
101 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
102 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
103 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
104 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
106 bestEntry = entry;
107 maxwidth = entry->bWidth;
108 maxheight = entry->bHeight;
109 maxcolors = entry->bColorCount;
111 if (bestEntry) return bestEntry;
113 /* Now find a smaller one with more colors */
115 maxcolors = 255;
116 maxwidth = maxheight = 0;
117 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
118 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
119 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
120 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
122 bestEntry = entry;
123 maxwidth = entry->bWidth;
124 maxheight = entry->bHeight;
125 maxcolors = entry->bColorCount;
127 if (bestEntry) return bestEntry;
129 /* Now find a larger one with less colors */
131 maxcolors = 0;
132 maxwidth = maxheight = 255;
133 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
134 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
135 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
137 bestEntry = entry;
138 maxwidth = entry->bWidth;
139 maxheight = entry->bHeight;
140 maxcolors = entry->bColorCount;
142 if (bestEntry) return bestEntry;
144 /* Now find a larger one with more colors */
146 maxcolors = maxwidth = maxheight = 255;
147 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
148 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
149 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
151 bestEntry = entry;
152 maxwidth = entry->bWidth;
153 maxheight = entry->bHeight;
154 maxcolors = entry->bColorCount;
157 return bestEntry;
161 /**********************************************************************
162 * CURSORICON_FindBestCursor
164 * Find the cursor closest to the requested size.
165 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
166 * ignored too
168 static CURSORDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
169 int width, int height, int color)
171 int i, maxwidth, maxheight;
172 CURSORDIRENTRY *entry, *bestEntry = NULL;
174 if (dir->idCount < 1)
176 WARN(cursor, "Empty directory!\n" );
177 return NULL;
179 if (dir->idCount == 1) return &dir->idEntries[0].cursor; /* No choice... */
181 /* First find the largest one smaller than or equal to the requested size*/
183 maxwidth = maxheight = 0;
184 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
185 if ((entry->wWidth <= width) && (entry->wHeight <= height) &&
186 (entry->wWidth > maxwidth) && (entry->wHeight > maxheight) &&
187 (entry->wBitCount == 1))
189 bestEntry = entry;
190 maxwidth = entry->wWidth;
191 maxheight = entry->wHeight;
193 if (bestEntry) return bestEntry;
195 /* Now find the smallest one larger than the requested size */
197 maxwidth = maxheight = 255;
198 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
199 if ((entry->wWidth < maxwidth) && (entry->wHeight < maxheight) &&
200 (entry->wBitCount == 1))
202 bestEntry = entry;
203 maxwidth = entry->wWidth;
204 maxheight = entry->wHeight;
207 return bestEntry;
210 /*********************************************************************
211 * The main purpose of this function is to create fake resource directory
212 * and fake resource entries. There are several reasons for this:
213 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
214 * fields
215 * There are some "bad" cursor files which do not have
216 * bColorCount initialized but instead one must read this info
217 * directly from corresponding DIB sections
218 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
220 BOOL32 CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL32 fCursor,
221 CURSORICONDIR **res, LPBYTE **ptr)
223 LPBYTE _free;
224 CURSORICONFILEDIR *bits;
225 int entries, size, i;
227 *res = NULL;
228 *ptr = NULL;
229 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
231 /* FIXME: test for inimated icons
232 * hack to load the first icon from the *.ani file
234 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
235 { LPBYTE pos = (LPBYTE) bits;
236 FIXME (cursor,"Animated icons not correctly implemented! %p \n", bits);
238 for (;;)
239 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
240 { FIXME (cursor,"icon entry found! %p\n", bits);
241 pos+=4;
242 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
243 { goto fail;
245 bits+=2;
246 FIXME (cursor,"icon size ok %p \n", bits);
247 break;
249 pos+=2;
250 if (pos>=(LPBYTE)bits+766) goto fail;
253 if (!(entries = bits->idCount)) goto fail;
254 (int)_free = size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) *
255 (entries - 1);
256 for (i=0; i < entries; i++)
257 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
259 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
260 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
261 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
263 _free = (LPBYTE)(*res) + (int)_free;
264 memcpy((*res), bits, 6);
265 for (i=0; i<entries; i++)
267 ((LPBYTE*)(*ptr))[i] = _free;
268 if (fCursor) {
269 (*res)->idEntries[i].cursor.wWidth=bits->idEntries[i].bWidth;
270 (*res)->idEntries[i].cursor.wHeight=bits->idEntries[i].bHeight;
271 (*res)->idEntries[i].cursor.wPlanes=1;
272 (*res)->idEntries[i].cursor.wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
273 bits->idEntries[i].dwDIBOffset))->biBitCount;
274 (*res)->idEntries[i].cursor.dwBytesInRes = bits->idEntries[i].dwDIBSize;
275 (*res)->idEntries[i].cursor.wResId=i+1;
276 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
277 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
278 _free+=sizeof(POINT16);
279 } else {
280 (*res)->idEntries[i].icon.bWidth=bits->idEntries[i].bWidth;
281 (*res)->idEntries[i].icon.bHeight=bits->idEntries[i].bHeight;
282 (*res)->idEntries[i].icon.bColorCount = bits->idEntries[i].bColorCount;
283 (*res)->idEntries[i].icon.wPlanes=1;
284 (*res)->idEntries[i].icon.wBitCount= ((LPBITMAPINFOHEADER)((LPBYTE)bits +
285 bits->idEntries[i].dwDIBOffset))->biBitCount;
286 (*res)->idEntries[i].icon.dwBytesInRes = bits->idEntries[i].dwDIBSize;
287 (*res)->idEntries[i].icon.wResId=i+1;
289 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
290 (*res)->idEntries[i].icon.dwBytesInRes);
291 _free += (*res)->idEntries[i].icon.dwBytesInRes;
293 UnmapViewOfFile( bits );
294 return TRUE;
295 fail:
296 if (*res) HeapFree( GetProcessHeap(), 0, *res );
297 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
298 UnmapViewOfFile( bits );
299 return FALSE;
302 /**********************************************************************
303 * CURSORICON_LoadDirEntry16
305 * Load the icon/cursor directory for a given resource name and find the
306 * best matching entry.
308 static BOOL32 CURSORICON_LoadDirEntry16( HINSTANCE32 hInstance, SEGPTR name,
309 INT32 width, INT32 height, INT32 colors,
310 BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
312 HRSRC16 hRsrc;
313 HGLOBAL16 hMem;
314 CURSORICONDIR *dir;
315 CURSORICONDIRENTRY *entry = NULL;
317 if (!(hRsrc = FindResource16( hInstance, name,
318 fCursor ? RT_GROUP_CURSOR16 : RT_GROUP_ICON16 )))
319 return FALSE;
320 if (!(hMem = LoadResource16( hInstance, hRsrc ))) return FALSE;
321 if ((dir = (CURSORICONDIR *)LockResource16( hMem )))
323 if (fCursor)
324 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
325 width, height, 1);
326 else
327 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
328 width, height, colors );
329 if (entry) *dirEntry = *entry;
331 FreeResource16( hMem );
332 return (entry != NULL);
336 /**********************************************************************
337 * CURSORICON_LoadDirEntry32
339 * Load the icon/cursor directory for a given resource name and find the
340 * best matching entry.
342 static BOOL32 CURSORICON_LoadDirEntry32( HINSTANCE32 hInstance, LPCWSTR name,
343 INT32 width, INT32 height, INT32 colors,
344 BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
346 HANDLE32 hRsrc;
347 HANDLE32 hMem;
348 CURSORICONDIR *dir;
349 CURSORICONDIRENTRY *entry = NULL;
351 if (!(hRsrc = FindResource32W( hInstance, name,
352 fCursor ? RT_GROUP_CURSOR32W : RT_GROUP_ICON32W )))
353 return FALSE;
354 if (!(hMem = LoadResource32( hInstance, hRsrc ))) return FALSE;
355 if ((dir = (CURSORICONDIR*)LockResource32( hMem )))
357 if (fCursor)
358 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
359 width, height, 1);
360 else
361 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
362 width, height, colors );
363 if (entry) *dirEntry = *entry;
365 FreeResource32( hMem );
366 return (entry != NULL);
370 /**********************************************************************
371 * CURSORICON_CreateFromResource
373 * Create a cursor or icon from in-memory resource template.
375 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
376 * with cbSize parameter as well.
378 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
379 UINT32 cbSize, BOOL32 bIcon, DWORD dwVersion,
380 INT32 width, INT32 height, UINT32 loadflags )
382 int sizeAnd, sizeXor;
383 HBITMAP32 hAndBits = 0, hXorBits = 0; /* error condition for later */
384 BITMAPOBJ *bmpXor, *bmpAnd;
385 POINT16 hotspot = { 0 ,0 };
386 BITMAPINFO *bmi;
387 HDC32 hdc;
388 BOOL32 DoStretch;
389 INT32 size;
391 TRACE(cursor,"%08x (%u bytes), ver %08x, %ix%i %s %s\n",
392 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
393 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
394 if (dwVersion == 0x00020000)
396 FIXME(cursor,"\t2.xx resources are not supported\n");
397 return 0;
400 if (bIcon)
401 bmi = (BITMAPINFO *)bits;
402 else /* get the hotspot */
404 POINT16 *pt = (POINT16 *)bits;
405 hotspot = *pt;
406 bmi = (BITMAPINFO *)(pt + 1);
408 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
410 if (!width) width = bmi->bmiHeader.biWidth;
411 if (!height) height = bmi->bmiHeader.biHeight/2;
412 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
413 (bmi->bmiHeader.biWidth != width);
415 /* Check bitmap header */
417 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
418 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
419 bmi->bmiHeader.biCompression != BI_RGB) )
421 WARN(cursor,"\tinvalid resource bitmap header.\n");
422 return 0;
425 if( (hdc = GetDC32( 0 )) )
427 BITMAPINFO* pInfo;
429 /* Make sure we have room for the monochrome bitmap later on.
430 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
431 * up to and including the biBitCount. In-memory icon resource
432 * format is as follows:
434 * BITMAPINFOHEADER icHeader // DIB header
435 * RGBQUAD icColors[] // Color table
436 * BYTE icXOR[] // DIB bits for XOR mask
437 * BYTE icAND[] // DIB bits for AND mask
440 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
441 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
443 memcpy( pInfo, bmi, size );
444 pInfo->bmiHeader.biHeight /= 2;
446 /* Create the XOR bitmap */
448 if (DoStretch) {
449 if ((hXorBits = CreateCompatibleBitmap32(hdc, width, height))) {
450 HBITMAP32 hOld;
451 HDC32 hMem = CreateCompatibleDC32(hdc);
452 BOOL32 res;
454 if (hMem) {
455 hOld = SelectObject32(hMem, hXorBits);
456 res = StretchDIBits32(hMem, 0, 0, width, height, 0, 0,
457 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
458 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
459 SelectObject32(hMem, hOld);
460 DeleteDC32(hMem);
461 } else res = FALSE;
462 if (!res) { DeleteObject32(hXorBits); hXorBits = 0; }
464 } else hXorBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader,
465 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
466 if( hXorBits )
468 char* bits = (char *)bmi + size + bmi->bmiHeader.biHeight *
469 DIB_GetDIBWidthBytes(bmi->bmiHeader.biWidth,
470 bmi->bmiHeader.biBitCount) / 2;
472 pInfo->bmiHeader.biBitCount = 1;
473 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
475 RGBQUAD *rgb = pInfo->bmiColors;
477 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
478 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
479 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
480 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
482 else
484 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
486 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
487 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
490 /* Create the AND bitmap */
492 if (DoStretch) {
493 if ((hAndBits = CreateBitmap32(width, height, 1, 1, NULL))) {
494 HBITMAP32 hOld;
495 HDC32 hMem = CreateCompatibleDC32(hdc);
496 BOOL32 res;
498 if (hMem) {
499 hOld = SelectObject32(hMem, hAndBits);
500 res = StretchDIBits32(hMem, 0, 0, width, height, 0, 0,
501 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
502 bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
503 SelectObject32(hMem, hOld);
504 DeleteDC32(hMem);
505 } else res = FALSE;
506 if (!res) { DeleteObject32(hAndBits); hAndBits = 0; }
508 } else hAndBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader,
509 CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
511 if( !hAndBits ) DeleteObject32( hXorBits );
513 HeapFree( GetProcessHeap(), 0, pInfo );
515 ReleaseDC32( 0, hdc );
518 if( !hXorBits || !hAndBits )
520 WARN(cursor,"\tunable to create an icon bitmap.\n");
521 return 0;
524 /* Now create the CURSORICONINFO structure */
525 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
526 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
527 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
528 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
530 if (hObj) hObj = GlobalReAlloc16( hObj,
531 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
532 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
533 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
534 if (hObj)
536 CURSORICONINFO *info;
538 /* Make it owned by the module */
539 if (hInstance) FarSetOwner( hObj, GetExePtr(hInstance) );
541 info = (CURSORICONINFO *)GlobalLock16( hObj );
542 info->ptHotSpot.x = hotspot.x;
543 info->ptHotSpot.y = hotspot.y;
544 info->nWidth = bmpXor->bitmap.bmWidth;
545 info->nHeight = bmpXor->bitmap.bmHeight;
546 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
547 info->bPlanes = bmpXor->bitmap.bmPlanes;
548 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
550 /* Transfer the bitmap bits to the CURSORICONINFO structure */
552 GetBitmapBits32( hAndBits, sizeAnd, (char *)(info + 1) );
553 GetBitmapBits32( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
554 GlobalUnlock16( hObj );
557 DeleteObject32( hXorBits );
558 DeleteObject32( hAndBits );
559 return hObj;
563 /**********************************************************************
564 * CreateIconFromResourceEx16 (USER.450)
566 * FIXME: not sure about exact parameter types
568 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
569 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
571 return CreateIconFromResourceEx32(bits, cbSize, bIcon, dwVersion,
572 width, height, cFlag);
576 /**********************************************************************
577 * CreateIconFromResource (USER32.76)
579 HICON32 WINAPI CreateIconFromResource32( LPBYTE bits, UINT32 cbSize,
580 BOOL32 bIcon, DWORD dwVersion)
582 return CreateIconFromResourceEx32( bits, cbSize, bIcon, dwVersion, 0,0,0);
586 /**********************************************************************
587 * CreateIconFromResourceEx32 (USER32.77)
589 HICON32 WINAPI CreateIconFromResourceEx32( LPBYTE bits, UINT32 cbSize,
590 BOOL32 bIcon, DWORD dwVersion,
591 INT32 width, INT32 height,
592 UINT32 cFlag )
594 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
595 if( pTask )
596 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
597 width, height, cFlag );
598 return 0;
602 /**********************************************************************
603 * CURSORICON_Load16
605 * Load a cursor or icon from a 16-bit resource.
607 static HGLOBAL16 CURSORICON_Load16( HINSTANCE16 hInstance, SEGPTR name,
608 INT32 width, INT32 height, INT32 colors,
609 BOOL32 fCursor, UINT32 loadflags)
611 HGLOBAL16 handle;
612 HRSRC16 hRsrc;
613 CURSORICONDIRENTRY dirEntry;
615 if (!hInstance) /* OEM cursor/icon */
617 if (HIWORD(name)) /* Check for '#xxx' name */
619 char *ptr = PTR_SEG_TO_LIN( name );
620 if (ptr[0] != '#') return 0;
621 if (!(name = (SEGPTR)atoi( ptr + 1 ))) return 0;
623 return OBM_LoadCursorIcon( LOWORD(name), fCursor );
626 /* Find the best entry in the directory */
628 if ( !CURSORICON_LoadDirEntry16( hInstance, name, width, height,
629 colors, fCursor, &dirEntry ) ) return 0;
630 /* Load the resource */
632 if ( (hRsrc = FindResource16( hInstance,
633 MAKEINTRESOURCE16( dirEntry.icon.wResId ),
634 fCursor ? RT_CURSOR16 : RT_ICON16 )) )
636 /* 16-bit icon or cursor resources are processed
637 * transparently by the LoadResource16() via custom
638 * resource handlers set by SetResourceHandler().
641 if ( (handle = LoadResource16( hInstance, hRsrc )) )
642 return handle;
644 return 0;
647 /**********************************************************************
648 * CURSORICON_Load32
650 * Load a cursor or icon from a 32-bit resource.
652 HGLOBAL32 CURSORICON_Load32( HINSTANCE32 hInstance, LPCWSTR name,
653 int width, int height, int colors,
654 BOOL32 fCursor, UINT32 loadflags )
656 HANDLE32 handle, h = 0;
657 HANDLE32 hRsrc;
658 CURSORICONDIRENTRY dirEntry;
659 LPBYTE bits;
661 if (!(loadflags & LR_LOADFROMFILE))
663 if (!hInstance) /* OEM cursor/icon */
665 WORD resid;
666 if(HIWORD(name))
668 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
669 if( ansi[0]=='#') /*Check for '#xxx' name */
671 resid = atoi(ansi+1);
672 HeapFree( GetProcessHeap(), 0, ansi );
674 else
676 HeapFree( GetProcessHeap(), 0, ansi );
677 return 0;
680 else resid = LOWORD(name);
681 return OBM_LoadCursorIcon(resid, fCursor);
684 /* Find the best entry in the directory */
686 if (!CURSORICON_LoadDirEntry32( hInstance, name, width, height,
687 colors, fCursor, &dirEntry ) ) return 0;
688 /* Load the resource */
690 if (!(hRsrc = FindResource32W(hInstance,MAKEINTRESOURCE32W(dirEntry.icon.wResId),
691 fCursor ? RT_CURSOR32W : RT_ICON32W ))) return 0;
692 if (!(handle = LoadResource32( hInstance, hRsrc ))) return 0;
693 /* Hack to keep LoadCursor/Icon32() from spawning multiple
694 * copies of the same object.
696 #define pRsrcEntry ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)
697 if( pRsrcEntry->ResourceHandle ) return pRsrcEntry->ResourceHandle;
698 bits = (LPBYTE)LockResource32( handle );
699 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry.icon.dwBytesInRes,
700 !fCursor, 0x00030000, width, height, loadflags);
701 pRsrcEntry->ResourceHandle = h;
703 else
705 CURSORICONDIR *res;
706 LPBYTE *ptr;
707 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &res, &ptr))
708 return 0;
709 if (fCursor)
710 dirEntry = *(CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(res, width, height, 1);
711 else
712 dirEntry = *(CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(res, width, height, colors);
713 bits = ptr[dirEntry.icon.wResId-1];
714 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry.icon.dwBytesInRes,
715 !fCursor, 0x00030000, width, height, loadflags);
716 HeapFree( GetProcessHeap(), 0, res );
717 HeapFree( GetProcessHeap(), 0, ptr );
719 return h;
720 #undef pRsrcEntry
724 /***********************************************************************
725 * CURSORICON_Copy
727 * Make a copy of a cursor or icon.
729 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
731 char *ptrOld, *ptrNew;
732 int size;
733 HGLOBAL16 hNew;
735 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
736 if (!(hInstance = GetExePtr( hInstance ))) return 0;
737 size = GlobalSize16( handle );
738 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
739 FarSetOwner( hNew, hInstance );
740 ptrNew = (char *)GlobalLock16( hNew );
741 memcpy( ptrNew, ptrOld, size );
742 GlobalUnlock16( handle );
743 GlobalUnlock16( hNew );
744 return hNew;
747 /***********************************************************************
748 * CURSORICON_IconToCursor
750 * Converts bitmap to mono and truncates if icon is too large (should
751 * probably do StretchBlt() instead).
753 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL32 bSemiTransparent)
755 HCURSOR16 hRet = 0;
756 CURSORICONINFO *pIcon = NULL;
757 HTASK16 hTask = GetCurrentTask();
758 TDB* pTask = (TDB *)GlobalLock16(hTask);
760 if(hIcon && pTask)
761 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
762 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
763 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
764 else
766 BYTE pAndBits[128];
767 BYTE pXorBits[128];
768 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
769 BYTE* psPtr, *pxbPtr = pXorBits;
770 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
771 BYTE* pbc = NULL;
773 COLORREF col;
774 CURSORICONINFO cI;
776 TRACE(icon, "[%04x] %ix%i %ibpp (bogus %ibps)\n",
777 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
779 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
780 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
781 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
783 memset(pXorBits, 0, 128);
784 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
785 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
786 cI.nWidth = 32; cI.nHeight = 32;
787 cI.nWidthBytes = 4; /* 32x1bpp */
789 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
790 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
792 for( iy = 0; iy < maxy; iy++ )
794 unsigned shift = iy % 2;
796 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
797 (and_width > 4) ? 4 : and_width );
798 for( ix = 0; ix < maxx; ix++ )
800 if( bSemiTransparent && ((ix+shift)%2) )
802 /* set AND bit, XOR bit stays 0 */
804 pbc = pAndBits + iy * 4 + ix/8;
805 *pbc |= 0x80 >> (ix%8);
807 else
809 /* keep AND bit, set XOR bit */
811 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
812 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
813 col = COLOR_ToLogical(val);
814 if( (GetRValue(col) + GetGValue(col) + GetBValue(col)) > 0x180 )
816 pbc = pxbPtr + ix/8;
817 *pbc |= 0x80 >> (ix%8);
821 psPtr += xor_width;
822 pxbPtr += 4;
825 hRet = CreateCursorIconIndirect( pTask->hInstance , &cI, pAndBits, pXorBits);
827 if( !hRet ) /* fall back on default drag cursor */
828 hRet = CURSORICON_Copy( pTask->hInstance ,
829 CURSORICON_Load16(0,MAKEINTRESOURCE16(OCR_DRAGOBJECT),
830 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0) );
833 return hRet;
837 /***********************************************************************
838 * LoadCursor16 (USER.173)
840 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
842 if (HIWORD(name))
843 TRACE(cursor, "%04x '%s'\n",
844 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
845 else
846 TRACE(cursor, "%04x %04x\n",
847 hInstance, LOWORD(name) );
849 return CURSORICON_Load16( hInstance, name,
850 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0);
854 /***********************************************************************
855 * LoadIcon16 (USER.174)
857 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
859 HDC32 hdc = GetDC32(0);
860 UINT32 palEnts = GetSystemPaletteEntries32(hdc, 0, 0, NULL);
861 ReleaseDC32(0, hdc);
863 if (HIWORD(name))
864 TRACE(icon, "%04x '%s'\n",
865 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
866 else
867 TRACE(icon, "%04x %04x\n",
868 hInstance, LOWORD(name) );
870 return CURSORICON_Load16( hInstance, name,
871 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
872 MIN(16, palEnts), FALSE, 0);
876 /***********************************************************************
877 * CreateCursor16 (USER.406)
879 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
880 INT16 xHotSpot, INT16 yHotSpot,
881 INT16 nWidth, INT16 nHeight,
882 LPCVOID lpANDbits, LPCVOID lpXORbits )
884 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
886 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
887 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
888 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
892 /***********************************************************************
893 * CreateCursor32 (USER32.67)
895 HCURSOR32 WINAPI CreateCursor32( HINSTANCE32 hInstance,
896 INT32 xHotSpot, INT32 yHotSpot,
897 INT32 nWidth, INT32 nHeight,
898 LPCVOID lpANDbits, LPCVOID lpXORbits )
900 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
902 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
903 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
904 return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
908 /***********************************************************************
909 * CreateIcon16 (USER.407)
911 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
912 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
913 LPCVOID lpANDbits, LPCVOID lpXORbits )
915 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
917 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
918 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
919 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
923 /***********************************************************************
924 * CreateIcon32 (USER32.75)
926 HICON32 WINAPI CreateIcon32( HINSTANCE32 hInstance, INT32 nWidth,
927 INT32 nHeight, BYTE bPlanes, BYTE bBitsPixel,
928 LPCVOID lpANDbits, LPCVOID lpXORbits )
930 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
932 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
933 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
934 return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
938 /***********************************************************************
939 * CreateCursorIconIndirect (USER.408)
941 HGLOBAL16 WINAPI CreateCursorIconIndirect( HINSTANCE16 hInstance,
942 CURSORICONINFO *info,
943 LPCVOID lpANDbits,
944 LPCVOID lpXORbits )
946 HGLOBAL16 handle;
947 char *ptr;
948 int sizeAnd, sizeXor;
950 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
951 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
952 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
953 sizeXor = info->nHeight * info->nWidthBytes;
954 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
955 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
956 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
957 return 0;
958 if (hInstance) FarSetOwner( handle, hInstance );
959 ptr = (char *)GlobalLock16( handle );
960 memcpy( ptr, info, sizeof(*info) );
961 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
962 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
963 GlobalUnlock16( handle );
964 return handle;
968 /***********************************************************************
969 * CopyIcon16 (USER.368)
971 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
973 TRACE(icon, "%04x %04x\n", hInstance, hIcon );
974 return CURSORICON_Copy( hInstance, hIcon );
978 /***********************************************************************
979 * CopyIcon32 (USER32.60)
981 HICON32 WINAPI CopyIcon32( HICON32 hIcon )
983 HTASK16 hTask = GetCurrentTask ();
984 TDB* pTask = (TDB *) GlobalLock16 (hTask);
985 TRACE(icon, "%04x\n", hIcon );
986 return CURSORICON_Copy( pTask->hInstance, hIcon );
990 /***********************************************************************
991 * CopyCursor16 (USER.369)
993 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
995 TRACE(cursor, "%04x %04x\n", hInstance, hCursor );
996 return CURSORICON_Copy( hInstance, hCursor );
1000 /***********************************************************************
1001 * DestroyIcon16 (USER.457)
1003 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1005 TRACE(icon, "%04x\n", hIcon );
1006 /* FIXME: should check for OEM/global heap icon here */
1007 return (FreeResource16( hIcon ) == 0);
1011 /***********************************************************************
1012 * DestroyIcon32 (USER32.133)
1014 BOOL32 WINAPI DestroyIcon32( HICON32 hIcon )
1016 TRACE(icon, "%04x\n", hIcon );
1017 /* FIXME: should check for OEM/global heap icon here */
1018 /* Unlike DestroyIcon16, only icons created with CreateIcon32
1019 are valid for DestroyIcon32, so don't use FreeResource32 */
1020 return (GlobalFree16( hIcon ) == 0);
1024 /***********************************************************************
1025 * DestroyCursor16 (USER.458)
1027 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1029 TRACE(cursor, "%04x\n", hCursor );
1030 if (FreeResource16( hCursor ) == 0)
1031 return TRUE;
1032 else
1033 /* I believe this very same line should be added for every function
1034 where appears the comment:
1036 "FIXME: should check for OEM/global heap cursor here"
1038 which are most (all?) the ones that call FreeResource, at least
1039 in this module. Maybe this should go to a wrapper to avoid
1040 repetition. Or: couldn't it go to FreeResoutce itself?
1042 I'll let this to someone savvy on the subject.
1044 return (GlobalFree16 (hCursor) == 0);
1048 /***********************************************************************
1049 * DestroyCursor32 (USER32.132)
1051 BOOL32 WINAPI DestroyCursor32( HCURSOR32 hCursor )
1053 TRACE(cursor, "%04x\n", hCursor );
1054 /* FIXME: should check for OEM/global heap cursor here */
1055 /* Unlike DestroyCursor16, only cursors created with CreateCursor32
1056 are valid for DestroyCursor32, so don't use FreeResource32 */
1057 return (GlobalFree16( hCursor ) == 0);
1061 /***********************************************************************
1062 * DrawIcon16 (USER.84)
1064 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1066 return DrawIcon32( hdc, x, y, hIcon );
1070 /***********************************************************************
1071 * DrawIcon32 (USER32.159)
1073 BOOL32 WINAPI DrawIcon32( HDC32 hdc, INT32 x, INT32 y, HICON32 hIcon )
1075 CURSORICONINFO *ptr;
1076 HDC32 hMemDC;
1077 HBITMAP32 hXorBits, hAndBits;
1078 COLORREF oldFg, oldBg;
1080 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1081 if (!(hMemDC = CreateCompatibleDC32( hdc ))) return FALSE;
1082 hAndBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, 1, 1,
1083 (char *)(ptr+1) );
1084 hXorBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1085 ptr->bBitsPerPixel, (char *)(ptr + 1)
1086 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1087 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
1088 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
1090 if (hXorBits && hAndBits)
1092 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
1093 BitBlt32( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1094 SelectObject32( hMemDC, hXorBits );
1095 BitBlt32(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1096 SelectObject32( hMemDC, hBitTemp );
1098 DeleteDC32( hMemDC );
1099 if (hXorBits) DeleteObject32( hXorBits );
1100 if (hAndBits) DeleteObject32( hAndBits );
1101 GlobalUnlock16( hIcon );
1102 SetTextColor32( hdc, oldFg );
1103 SetBkColor32( hdc, oldBg );
1104 return TRUE;
1108 /***********************************************************************
1109 * DumpIcon (USER.459)
1111 DWORD WINAPI DumpIcon( SEGPTR pInfo, WORD *lpLen,
1112 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1114 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1115 int sizeAnd, sizeXor;
1117 if (!info) return 0;
1118 sizeXor = info->nHeight * info->nWidthBytes;
1119 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1120 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1121 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1122 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1123 return MAKELONG( sizeXor, sizeXor );
1127 /***********************************************************************
1128 * SetCursor16 (USER.69)
1130 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1132 return (HCURSOR16)SetCursor32( hCursor );
1136 /***********************************************************************
1137 * SetCursor32 (USER32.472)
1138 * RETURNS:
1139 * A handle to the previous cursor shape.
1141 HCURSOR32 WINAPI SetCursor32(
1142 HCURSOR32 hCursor /* Handle of cursor to show */
1144 HCURSOR32 hOldCursor;
1146 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1147 TRACE(cursor, "%04x\n", hCursor );
1148 hOldCursor = hActiveCursor;
1149 hActiveCursor = hCursor;
1150 /* Change the cursor shape only if it is visible */
1151 if (CURSOR_ShowCount >= 0)
1153 DISPLAY_SetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1154 GlobalUnlock16( hActiveCursor );
1156 return hOldCursor;
1160 /***********************************************************************
1161 * SetCursorPos16 (USER.70)
1163 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1165 SetCursorPos32( x, y );
1169 /***********************************************************************
1170 * SetCursorPos32 (USER32.474)
1172 BOOL32 WINAPI SetCursorPos32( INT32 x, INT32 y )
1174 DISPLAY_MoveCursor( x, y );
1175 return TRUE;
1179 /***********************************************************************
1180 * ShowCursor16 (USER.71)
1182 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1184 return ShowCursor32( bShow );
1188 /***********************************************************************
1189 * ShowCursor32 (USER32.530)
1191 INT32 WINAPI ShowCursor32( BOOL32 bShow )
1193 TRACE(cursor, "%d, count=%d\n",
1194 bShow, CURSOR_ShowCount );
1196 if (bShow)
1198 if (++CURSOR_ShowCount == 0) /* Show it */
1200 DISPLAY_SetCursor((CURSORICONINFO*)GlobalLock16( hActiveCursor ));
1201 GlobalUnlock16( hActiveCursor );
1204 else
1206 if (--CURSOR_ShowCount == -1) /* Hide it */
1207 DISPLAY_SetCursor( NULL );
1209 return CURSOR_ShowCount;
1213 /***********************************************************************
1214 * GetCursor16 (USER.247)
1216 HCURSOR16 WINAPI GetCursor16(void)
1218 return hActiveCursor;
1222 /***********************************************************************
1223 * GetCursor32 (USER32.227)
1225 HCURSOR32 WINAPI GetCursor32(void)
1227 return hActiveCursor;
1231 /***********************************************************************
1232 * ClipCursor16 (USER.16)
1234 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1236 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1237 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1238 return TRUE;
1242 /***********************************************************************
1243 * ClipCursor32 (USER32.53)
1245 BOOL32 WINAPI ClipCursor32( const RECT32 *rect )
1247 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1248 else CopyRect32( &CURSOR_ClipRect, rect );
1249 return TRUE;
1253 /***********************************************************************
1254 * GetCursorPos16 (USER.17)
1256 void WINAPI GetCursorPos16( POINT16 *pt )
1258 DWORD posX, posY, state;
1260 if (!pt) return;
1261 if (!EVENT_QueryPointer( &posX, &posY, &state ))
1262 pt->x = pt->y = 0;
1263 else
1265 pt->x = posX;
1266 pt->y = posY;
1267 if (state & MK_LBUTTON)
1268 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1269 else
1270 MouseButtonsStates[0] = FALSE;
1271 if (state & MK_MBUTTON)
1272 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1273 else
1274 MouseButtonsStates[1] = FALSE;
1275 if (state & MK_RBUTTON)
1276 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1277 else
1278 MouseButtonsStates[2] = FALSE;
1280 TRACE(cursor, "ret=%d,%d\n", pt->x, pt->y );
1284 /***********************************************************************
1285 * GetCursorPos32 (USER32.229)
1287 void WINAPI GetCursorPos32( POINT32 *pt )
1289 POINT16 pt16;
1290 GetCursorPos16( &pt16 );
1291 if (pt) CONV_POINT16TO32( &pt16, pt );
1295 /***********************************************************************
1296 * GetClipCursor16 (USER.309)
1298 void WINAPI GetClipCursor16( RECT16 *rect )
1300 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1304 /***********************************************************************
1305 * GetClipCursor32 (USER32.221)
1307 void WINAPI GetClipCursor32( RECT32 *rect )
1309 if (rect) CopyRect32( rect, &CURSOR_ClipRect );
1312 /**********************************************************************
1313 * LookupIconIdFromDirectoryEx16 (USER.364)
1315 * FIXME: exact parameter sizes
1317 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1318 INT16 width, INT16 height, UINT16 cFlag )
1320 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1321 UINT16 retVal = 0;
1322 if( dir && !dir->idReserved && (dir->idType & 3) )
1324 HDC32 hdc = GetDC32(0);
1325 UINT32 palEnts = GetSystemPaletteEntries32(hdc, 0, 0, NULL);
1326 int colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1327 ReleaseDC32(0, hdc);
1329 if( bIcon )
1331 ICONDIRENTRY* entry;
1332 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1333 if( entry ) retVal = entry->wResId;
1335 else
1337 CURSORDIRENTRY* entry;
1338 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1339 if( entry ) retVal = entry->wResId;
1342 else WARN(cursor, "invalid resource directory\n");
1343 return retVal;
1346 /**********************************************************************
1347 * LookupIconIdFromDirectoryEx32 (USER32.380)
1349 INT32 WINAPI LookupIconIdFromDirectoryEx32( LPBYTE dir, BOOL32 bIcon,
1350 INT32 width, INT32 height, UINT32 cFlag )
1352 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1355 /**********************************************************************
1356 * LookupIconIdFromDirectory (USER.???)
1358 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1360 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1361 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1362 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1365 /**********************************************************************
1366 * LookupIconIdFromDirectory (USER32.379)
1368 INT32 WINAPI LookupIconIdFromDirectory32( LPBYTE dir, BOOL32 bIcon )
1370 return LookupIconIdFromDirectoryEx32( dir, bIcon,
1371 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1372 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1375 /**********************************************************************
1376 * GetIconID (USER.455)
1378 WORD WINAPI GetIconID( HGLOBAL16 hResource, DWORD resType )
1380 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1382 TRACE(cursor, "hRes=%04x, entries=%i\n",
1383 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1385 switch(resType)
1387 case RT_CURSOR16:
1388 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1389 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1390 case RT_ICON16:
1391 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1392 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1393 default:
1394 WARN(cursor, "invalid res type %ld\n", resType );
1396 return 0;
1399 /**********************************************************************
1400 * LoadCursorIconHandler (USER.336)
1402 * Supposed to load resources of Windows 2.x applications.
1404 HGLOBAL16 WINAPI LoadCursorIconHandler( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1406 FIXME(cursor,"(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1407 hResource, hModule, hRsrc);
1408 return (HGLOBAL16)0;
1411 /**********************************************************************
1412 * LoadDIBIconHandler (USER.357)
1414 * RT_ICON resource loader, installed by USER_SignalProc when module
1415 * is initialized.
1417 HGLOBAL16 WINAPI LoadDIBIconHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1419 /* If hResource is zero we must allocate a new memory block, if it's
1420 * non-zero but GlobalLock() returns NULL then it was discarded and
1421 * we have to recommit some memory, otherwise we just need to check
1422 * the block size. See LoadProc() in 16-bit SDK for more.
1425 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1426 if( hMemObj )
1428 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1429 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1430 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1431 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1433 return hMemObj;
1436 /**********************************************************************
1437 * LoadDIBCursorHandler (USER.356)
1439 * RT_CURSOR resource loader. Same as above.
1441 HGLOBAL16 WINAPI LoadDIBCursorHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1443 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1444 if( hMemObj )
1446 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1447 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1448 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1449 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1451 return hMemObj;
1454 /**********************************************************************
1455 * LoadIconHandler (USER.456)
1457 HICON16 WINAPI LoadIconHandler( HGLOBAL16 hResource, BOOL16 bNew )
1459 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1461 TRACE(cursor,"hRes=%04x\n",hResource);
1463 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1464 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1467 /***********************************************************************
1468 * LoadCursorW (USER32.362)
1470 HCURSOR32 WINAPI LoadCursor32W(HINSTANCE32 hInstance, LPCWSTR name)
1472 return CURSORICON_Load32( hInstance, name,
1473 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0);
1476 /***********************************************************************
1477 * LoadCursorA (USER32.359)
1479 HCURSOR32 WINAPI LoadCursor32A(HINSTANCE32 hInstance, LPCSTR name)
1481 HCURSOR32 res=0;
1482 if(!HIWORD(name))
1483 return LoadCursor32W(hInstance,(LPCWSTR)name);
1484 else
1486 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1487 res = LoadCursor32W(hInstance, uni);
1488 HeapFree( GetProcessHeap(), 0, uni);
1490 return res;
1492 /***********************************************************************
1493 * LoadCursorFromFile32W (USER32.361)
1495 HCURSOR32 WINAPI LoadCursorFromFile32W (LPCWSTR name)
1497 return LoadImage32W(0, name, IMAGE_CURSOR, SYSMETRICS_CXCURSOR,
1498 SYSMETRICS_CYCURSOR, LR_LOADFROMFILE);
1501 /***********************************************************************
1502 * LoadCursorFromFile32A (USER32.360)
1504 HCURSOR32 WINAPI LoadCursorFromFile32A (LPCSTR name)
1506 HCURSOR32 hcur;
1507 LPWSTR u_name = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1508 hcur = LoadCursorFromFile32W(u_name);
1509 HeapFree( GetProcessHeap(), 0, u_name );
1510 return hcur;
1513 /***********************************************************************
1514 * LoadIconW (USER32.364)
1516 HICON32 WINAPI LoadIcon32W(HINSTANCE32 hInstance, LPCWSTR name)
1518 HDC32 hdc = GetDC32(0);
1519 UINT32 palEnts = GetSystemPaletteEntries32(hdc, 0, 0, NULL);
1520 ReleaseDC32(0, hdc);
1522 return CURSORICON_Load32( hInstance, name,
1523 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
1524 MIN( 16, palEnts ), FALSE, 0);
1527 /***********************************************************************
1528 * LoadIconA (USER32.363)
1530 HICON32 WINAPI LoadIcon32A(HINSTANCE32 hInstance, LPCSTR name)
1532 HICON32 res=0;
1534 if( !HIWORD(name) )
1535 return LoadIcon32W(hInstance, (LPCWSTR)name);
1536 else
1538 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1539 res = LoadIcon32W( hInstance, uni );
1540 HeapFree( GetProcessHeap(), 0, uni );
1542 return res;
1545 /**********************************************************************
1546 * GetIconInfo (USER32.242)
1548 BOOL32 WINAPI GetIconInfo(HICON32 hIcon,LPICONINFO iconinfo) {
1549 CURSORICONINFO *ciconinfo;
1551 ciconinfo = GlobalLock16(hIcon);
1552 if (!ciconinfo)
1553 return FALSE;
1554 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1555 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1556 iconinfo->fIcon = TRUE; /* hmm */
1558 iconinfo->hbmColor = CreateBitmap32 ( ciconinfo->nWidth, ciconinfo->nHeight,
1559 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1560 (char *)(ciconinfo + 1)
1561 + ciconinfo->nHeight *
1562 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1563 iconinfo->hbmMask = CreateBitmap32 ( ciconinfo->nWidth, ciconinfo->nHeight,
1564 1, 1, (char *)(ciconinfo + 1));
1566 GlobalUnlock16(hIcon);
1568 return TRUE;
1571 /**********************************************************************
1572 * CreateIconIndirect (USER32.78)
1574 HICON32 WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1575 BITMAPOBJ *bmpXor,*bmpAnd;
1576 HICON32 hObj;
1577 int sizeXor,sizeAnd;
1579 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1580 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1582 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1583 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1585 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1586 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1587 if (hObj)
1589 CURSORICONINFO *info;
1591 info = (CURSORICONINFO *)GlobalLock16( hObj );
1592 info->ptHotSpot.x = iconinfo->xHotspot;
1593 info->ptHotSpot.y = iconinfo->yHotspot;
1594 info->nWidth = bmpXor->bitmap.bmWidth;
1595 info->nHeight = bmpXor->bitmap.bmHeight;
1596 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1597 info->bPlanes = bmpXor->bitmap.bmPlanes;
1598 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1600 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1602 GetBitmapBits32( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1603 GetBitmapBits32( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1604 GlobalUnlock16( hObj );
1606 return hObj;
1610 /**********************************************************************
1612 DrawIconEx16 (USER.394)
1614 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1615 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1616 HBRUSH16 hbr, UINT16 flags)
1618 return DrawIconEx32(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1619 istep, hbr, flags);
1623 /******************************************************************************
1624 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1626 * NOTES
1627 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1629 * PARAMS
1630 * hdc [I] Handle to device context
1631 * x0 [I] X coordinate of upper left corner
1632 * y0 [I] Y coordinate of upper left corner
1633 * hIcon [I] Handle to icon to draw
1634 * cxWidth [I] Width of icon
1635 * cyWidth [I] Height of icon
1636 * istep [I] Index of frame in animated cursor
1637 * hbr [I] Handle to background brush
1638 * flags [I] Icon-drawing flags
1640 * RETURNS
1641 * Success: TRUE
1642 * Failure: FALSE
1644 BOOL32 WINAPI DrawIconEx32( HDC32 hdc, INT32 x0, INT32 y0, HICON32 hIcon,
1645 INT32 cxWidth, INT32 cyWidth, UINT32 istep,
1646 HBRUSH32 hbr, UINT32 flags )
1648 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1649 HDC32 hDC_off = 0, hMemDC = CreateCompatibleDC32 (hdc);
1650 BOOL32 result = FALSE, DoOffscreen = FALSE;
1651 HBITMAP32 hB_off = 0, hOld = 0;
1653 if (!ptr) return FALSE;
1655 if (istep)
1656 FIXME(icon, "Ignoring istep=%d\n", istep);
1657 if (flags & DI_COMPAT)
1658 FIXME(icon, "Ignoring flag DI_COMPAT\n");
1660 /* Calculate the size of the destination image. */
1661 if (cxWidth == 0)
1663 if (flags & DI_DEFAULTSIZE)
1664 cxWidth = GetSystemMetrics32 (SM_CXICON);
1665 else
1666 cxWidth = ptr->nWidth;
1668 if (cyWidth == 0)
1670 if (flags & DI_DEFAULTSIZE)
1671 cyWidth = GetSystemMetrics32 (SM_CYICON);
1672 else
1673 cyWidth = ptr->nHeight;
1676 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1677 STOCK_HOLLOW_BRUSH)))
1679 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1680 if (object)
1682 UINT16 magic = object->wMagic;
1683 GDI_HEAP_UNLOCK(hbr);
1684 DoOffscreen = magic == BRUSH_MAGIC;
1687 if (DoOffscreen) {
1688 RECT32 r = {0, 0, cxWidth, cxWidth};
1690 hDC_off = CreateCompatibleDC32(hdc);
1691 hB_off = CreateCompatibleBitmap32(hdc, cxWidth, cyWidth);
1692 if (hDC_off && hB_off) {
1693 hOld = SelectObject32(hDC_off, hB_off);
1694 FillRect32(hDC_off, &r, hbr);
1698 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1700 HBITMAP32 hXorBits, hAndBits;
1701 COLORREF oldFg, oldBg;
1702 INT32 nStretchMode;
1704 nStretchMode = SetStretchBltMode32 (hdc, STRETCH_DELETESCANS);
1706 hXorBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
1707 ptr->bPlanes, ptr->bBitsPerPixel,
1708 (char *)(ptr + 1)
1709 + ptr->nHeight *
1710 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1711 hAndBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
1712 1, 1, (char *)(ptr+1) );
1713 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
1714 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
1716 if (hXorBits && hAndBits)
1718 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
1719 if (flags & DI_MASK)
1721 if (DoOffscreen)
1722 StretchBlt32 (hDC_off, 0, 0, cxWidth, cyWidth,
1723 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1724 else
1725 StretchBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1726 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1728 SelectObject32( hMemDC, hXorBits );
1729 if (flags & DI_IMAGE)
1731 if (DoOffscreen)
1732 StretchBlt32 (hDC_off, 0, 0, cxWidth, cyWidth,
1733 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1734 else
1735 StretchBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1736 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1738 SelectObject32( hMemDC, hBitTemp );
1739 result = TRUE;
1742 SetTextColor32( hdc, oldFg );
1743 SetBkColor32( hdc, oldBg );
1744 if (hXorBits) DeleteObject32( hXorBits );
1745 if (hAndBits) DeleteObject32( hAndBits );
1746 SetStretchBltMode32 (hdc, nStretchMode);
1747 if (DoOffscreen) {
1748 BitBlt32(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
1749 SelectObject32(hDC_off, hOld);
1752 if (hMemDC) DeleteDC32( hMemDC );
1753 if (hDC_off) DeleteDC32(hDC_off);
1754 if (hB_off) DeleteObject32(hB_off);
1755 GlobalUnlock16( hIcon );
1756 return result;