Release 990226.
[wine/gsoc-2012-control.git] / objects / cursoricon.c
blob7e2e89ca2355111040e00f7846745870880d8a12
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 "wine/winbase16.h"
35 #include "heap.h"
36 #include "color.h"
37 #include "bitmap.h"
38 #include "cursoricon.h"
39 #include "dc.h"
40 #include "gdi.h"
41 #include "sysmetrics.h"
42 #include "global.h"
43 #include "module.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 HCURSOR hActiveCursor = 0; /* Active cursor */
53 static INT CURSOR_ShowCount = 0; /* Cursor display count */
54 static RECT 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 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL 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 BOOL CURSORICON_LoadDirEntry16( HINSTANCE hInstance, SEGPTR name,
309 INT width, INT height, INT colors,
310 BOOL 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 BOOL CURSORICON_LoadDirEntry( HINSTANCE hInstance, LPCWSTR name,
343 INT width, INT height, INT colors,
344 BOOL fCursor, CURSORICONDIRENTRY *dirEntry )
346 HANDLE hRsrc;
347 HANDLE hMem;
348 CURSORICONDIR *dir;
349 CURSORICONDIRENTRY *entry = NULL;
351 if (!(hRsrc = FindResourceW( hInstance, name,
352 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
353 return FALSE;
354 if (!(hMem = LoadResource( hInstance, hRsrc ))) return FALSE;
355 if ((dir = (CURSORICONDIR*)LockResource( 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 FreeResource( 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 UINT cbSize, BOOL bIcon, DWORD dwVersion,
380 INT width, INT height, UINT loadflags )
382 int sizeAnd, sizeXor;
383 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
384 BITMAPOBJ *bmpXor, *bmpAnd;
385 POINT16 hotspot = { 0 ,0 };
386 BITMAPINFO *bmi;
387 HDC hdc;
388 BOOL DoStretch;
389 INT 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 = GetDC( 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 = CreateCompatibleBitmap(hdc, width, height))) {
450 HBITMAP hOld;
451 HDC hMem = CreateCompatibleDC(hdc);
452 BOOL res;
454 if (hMem) {
455 hOld = SelectObject(hMem, hXorBits);
456 res = StretchDIBits(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 SelectObject(hMem, hOld);
460 DeleteDC(hMem);
461 } else res = FALSE;
462 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
464 } else hXorBits = CreateDIBitmap( 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 = CreateBitmap(width, height, 1, 1, NULL))) {
494 HBITMAP hOld;
495 HDC hMem = CreateCompatibleDC(hdc);
496 BOOL res;
498 if (hMem) {
499 hOld = SelectObject(hMem, hAndBits);
500 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
501 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
502 bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
503 SelectObject(hMem, hOld);
504 DeleteDC(hMem);
505 } else res = FALSE;
506 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
508 } else hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
509 CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
511 if( !hAndBits ) DeleteObject( hXorBits );
513 HeapFree( GetProcessHeap(), 0, pInfo );
515 ReleaseDC( 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) FarSetOwner16( 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 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
553 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
554 GlobalUnlock16( hObj );
557 DeleteObject( hXorBits );
558 DeleteObject( 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 CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
572 width, height, cFlag);
576 /**********************************************************************
577 * CreateIconFromResource (USER32.76)
579 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
580 BOOL bIcon, DWORD dwVersion)
582 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
586 /**********************************************************************
587 * CreateIconFromResourceEx32 (USER32.77)
589 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
590 BOOL bIcon, DWORD dwVersion,
591 INT width, INT height,
592 UINT 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 INT width, INT height, INT colors,
609 BOOL fCursor, UINT loadflags)
611 HGLOBAL16 handle = 0;
612 HRSRC16 hRsrc;
613 CURSORICONDIRENTRY dirEntry;
615 if (!hInstance) /* OEM cursor/icon */
617 HDC hdc;
618 DC *dc;
620 if (HIWORD(name)) /* Check for '#xxx' name */
622 char *ptr = PTR_SEG_TO_LIN( name );
623 if (ptr[0] != '#') return 0;
624 if (!(name = (SEGPTR)atoi( ptr + 1 ))) return 0;
626 hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
627 dc = DC_GetDCPtr( hdc );
628 if(dc->funcs->pLoadOEMResource)
629 handle = dc->funcs->pLoadOEMResource( LOWORD(name), fCursor ?
630 OEM_CURSOR : OEM_ICON);
631 GDI_HEAP_UNLOCK( hdc );
632 DeleteDC( hdc );
633 return handle;
636 /* Find the best entry in the directory */
638 if ( !CURSORICON_LoadDirEntry16( hInstance, name, width, height,
639 colors, fCursor, &dirEntry ) ) return 0;
640 /* Load the resource */
642 if ( (hRsrc = FindResource16( hInstance,
643 MAKEINTRESOURCE16( dirEntry.icon.wResId ),
644 fCursor ? RT_CURSOR16 : RT_ICON16 )) )
646 /* 16-bit icon or cursor resources are processed
647 * transparently by the LoadResource16() via custom
648 * resource handlers set by SetResourceHandler().
651 if ( (handle = LoadResource16( hInstance, hRsrc )) )
652 return handle;
654 return 0;
657 /**********************************************************************
658 * CURSORICON_Load32
660 * Load a cursor or icon from a 32-bit resource.
662 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
663 int width, int height, int colors,
664 BOOL fCursor, UINT loadflags )
666 HANDLE handle = 0, h = 0;
667 HANDLE hRsrc;
668 CURSORICONDIRENTRY dirEntry;
669 LPBYTE bits;
671 if (!(loadflags & LR_LOADFROMFILE))
673 if (!hInstance) /* OEM cursor/icon */
675 WORD resid;
676 HDC hdc;
677 DC *dc;
679 if(HIWORD(name))
681 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
682 if( ansi[0]=='#') /*Check for '#xxx' name */
684 resid = atoi(ansi+1);
685 HeapFree( GetProcessHeap(), 0, ansi );
687 else
689 HeapFree( GetProcessHeap(), 0, ansi );
690 return 0;
693 else resid = LOWORD(name);
694 hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
695 dc = DC_GetDCPtr( hdc );
696 if(dc->funcs->pLoadOEMResource)
697 handle = dc->funcs->pLoadOEMResource( resid, fCursor ?
698 OEM_CURSOR : OEM_ICON );
699 GDI_HEAP_UNLOCK( hdc );
700 DeleteDC( hdc );
701 return handle;
704 /* Find the best entry in the directory */
706 if (!CURSORICON_LoadDirEntry( hInstance, name, width, height,
707 colors, fCursor, &dirEntry ) ) return 0;
708 /* Load the resource */
710 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(dirEntry.icon.wResId),
711 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
712 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
713 /* Hack to keep LoadCursor/Icon32() from spawning multiple
714 * copies of the same object.
716 #define pRsrcEntry ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)
717 if( pRsrcEntry->ResourceHandle ) return pRsrcEntry->ResourceHandle;
718 bits = (LPBYTE)LockResource( handle );
719 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry.icon.dwBytesInRes,
720 !fCursor, 0x00030000, width, height, loadflags);
721 pRsrcEntry->ResourceHandle = h;
723 else
725 CURSORICONDIR *res;
726 LPBYTE *ptr;
727 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &res, &ptr))
728 return 0;
729 if (fCursor)
730 dirEntry = *(CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(res, width, height, 1);
731 else
732 dirEntry = *(CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(res, width, height, colors);
733 bits = ptr[dirEntry.icon.wResId-1];
734 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry.icon.dwBytesInRes,
735 !fCursor, 0x00030000, width, height, loadflags);
736 HeapFree( GetProcessHeap(), 0, res );
737 HeapFree( GetProcessHeap(), 0, ptr );
739 return h;
740 #undef pRsrcEntry
744 /***********************************************************************
745 * CURSORICON_Copy
747 * Make a copy of a cursor or icon.
749 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
751 char *ptrOld, *ptrNew;
752 int size;
753 HGLOBAL16 hNew;
755 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
756 if (!(hInstance = GetExePtr( hInstance ))) return 0;
757 size = GlobalSize16( handle );
758 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
759 FarSetOwner16( hNew, hInstance );
760 ptrNew = (char *)GlobalLock16( hNew );
761 memcpy( ptrNew, ptrOld, size );
762 GlobalUnlock16( handle );
763 GlobalUnlock16( hNew );
764 return hNew;
767 /***********************************************************************
768 * CURSORICON_IconToCursor
770 * Converts bitmap to mono and truncates if icon is too large (should
771 * probably do StretchBlt() instead).
773 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
775 HCURSOR16 hRet = 0;
776 CURSORICONINFO *pIcon = NULL;
777 HTASK16 hTask = GetCurrentTask();
778 TDB* pTask = (TDB *)GlobalLock16(hTask);
780 if(hIcon && pTask)
781 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
782 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
783 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
784 else
786 BYTE pAndBits[128];
787 BYTE pXorBits[128];
788 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
789 BYTE* psPtr, *pxbPtr = pXorBits;
790 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
791 BYTE* pbc = NULL;
793 COLORREF col;
794 CURSORICONINFO cI;
796 TRACE(icon, "[%04x] %ix%i %ibpp (bogus %ibps)\n",
797 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
799 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
800 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
801 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
803 memset(pXorBits, 0, 128);
804 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
805 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
806 cI.nWidth = 32; cI.nHeight = 32;
807 cI.nWidthBytes = 4; /* 32x1bpp */
809 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
810 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
812 for( iy = 0; iy < maxy; iy++ )
814 unsigned shift = iy % 2;
816 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
817 (and_width > 4) ? 4 : and_width );
818 for( ix = 0; ix < maxx; ix++ )
820 if( bSemiTransparent && ((ix+shift)%2) )
822 /* set AND bit, XOR bit stays 0 */
824 pbc = pAndBits + iy * 4 + ix/8;
825 *pbc |= 0x80 >> (ix%8);
827 else
829 /* keep AND bit, set XOR bit */
831 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
832 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
833 col = COLOR_ToLogical(val);
834 if( (GetRValue(col) + GetGValue(col) + GetBValue(col)) > 0x180 )
836 pbc = pxbPtr + ix/8;
837 *pbc |= 0x80 >> (ix%8);
841 psPtr += xor_width;
842 pxbPtr += 4;
845 hRet = CreateCursorIconIndirect16( pTask->hInstance , &cI, pAndBits, pXorBits);
847 if( !hRet ) /* fall back on default drag cursor */
848 hRet = CURSORICON_Copy( pTask->hInstance ,
849 CURSORICON_Load16(0,MAKEINTRESOURCE16(OCR_DRAGOBJECT),
850 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0) );
853 return hRet;
857 /***********************************************************************
858 * LoadCursor16 (USER.173)
860 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
862 if (HIWORD(name))
863 TRACE(cursor, "%04x '%s'\n",
864 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
865 else
866 TRACE(cursor, "%04x %04x\n",
867 hInstance, LOWORD(name) );
869 return CURSORICON_Load16( hInstance, name,
870 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0);
874 /***********************************************************************
875 * LoadIcon16 (USER.174)
877 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
879 HDC hdc = GetDC(0);
880 UINT palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
881 ReleaseDC(0, hdc);
883 if (HIWORD(name))
884 TRACE(icon, "%04x '%s'\n",
885 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
886 else
887 TRACE(icon, "%04x %04x\n",
888 hInstance, LOWORD(name) );
890 return CURSORICON_Load16( hInstance, name,
891 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
892 MIN(16, palEnts), FALSE, 0);
896 /***********************************************************************
897 * CreateCursor16 (USER.406)
899 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
900 INT16 xHotSpot, INT16 yHotSpot,
901 INT16 nWidth, INT16 nHeight,
902 LPCVOID lpANDbits, LPCVOID lpXORbits )
904 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
906 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
907 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
908 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
912 /***********************************************************************
913 * CreateCursor32 (USER32.67)
915 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
916 INT xHotSpot, INT yHotSpot,
917 INT nWidth, INT nHeight,
918 LPCVOID lpANDbits, LPCVOID lpXORbits )
920 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
922 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
923 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
924 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
928 /***********************************************************************
929 * CreateIcon16 (USER.407)
931 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
932 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
933 LPCVOID lpANDbits, LPCVOID lpXORbits )
935 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
937 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
938 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
939 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
943 /***********************************************************************
944 * CreateIcon32 (USER32.75)
946 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
947 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
948 LPCVOID lpANDbits, LPCVOID lpXORbits )
950 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
952 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
953 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
954 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
958 /***********************************************************************
959 * CreateCursorIconIndirect (USER.408)
961 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
962 CURSORICONINFO *info,
963 LPCVOID lpANDbits,
964 LPCVOID lpXORbits )
966 HGLOBAL16 handle;
967 char *ptr;
968 int sizeAnd, sizeXor;
970 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
971 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
972 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
973 sizeXor = info->nHeight * info->nWidthBytes;
974 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
975 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
976 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
977 return 0;
978 if (hInstance) FarSetOwner16( handle, hInstance );
979 ptr = (char *)GlobalLock16( handle );
980 memcpy( ptr, info, sizeof(*info) );
981 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
982 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
983 GlobalUnlock16( handle );
984 return handle;
988 /***********************************************************************
989 * CopyIcon16 (USER.368)
991 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
993 TRACE(icon, "%04x %04x\n", hInstance, hIcon );
994 return CURSORICON_Copy( hInstance, hIcon );
998 /***********************************************************************
999 * CopyIcon32 (USER32.60)
1001 HICON WINAPI CopyIcon( HICON hIcon )
1003 HTASK16 hTask = GetCurrentTask ();
1004 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1005 TRACE(icon, "%04x\n", hIcon );
1006 return CURSORICON_Copy( pTask->hInstance, hIcon );
1010 /***********************************************************************
1011 * CopyCursor16 (USER.369)
1013 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1015 TRACE(cursor, "%04x %04x\n", hInstance, hCursor );
1016 return CURSORICON_Copy( hInstance, hCursor );
1020 /***********************************************************************
1021 * DestroyIcon16 (USER.457)
1023 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1025 TRACE(icon, "%04x\n", hIcon );
1026 /* FIXME: should check for OEM/global heap icon here */
1027 return (FreeResource16( hIcon ) == 0);
1031 /***********************************************************************
1032 * DestroyIcon32 (USER32.133)
1034 BOOL WINAPI DestroyIcon( HICON hIcon )
1036 TRACE(icon, "%04x\n", hIcon );
1037 /* FIXME: should check for OEM/global heap icon here */
1038 /* Unlike DestroyIcon16, only icons created with CreateIcon32
1039 are valid for DestroyIcon32, so don't use FreeResource32 */
1040 return (GlobalFree16( hIcon ) == 0);
1044 /***********************************************************************
1045 * DestroyCursor16 (USER.458)
1047 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1049 TRACE(cursor, "%04x\n", hCursor );
1050 if (FreeResource16( hCursor ) == 0)
1051 return TRUE;
1052 else
1053 /* I believe this very same line should be added for every function
1054 where appears the comment:
1056 "FIXME: should check for OEM/global heap cursor here"
1058 which are most (all?) the ones that call FreeResource, at least
1059 in this module. Maybe this should go to a wrapper to avoid
1060 repetition. Or: couldn't it go to FreeResoutce itself?
1062 I'll let this to someone savvy on the subject.
1064 return (GlobalFree16 (hCursor) == 0);
1068 /***********************************************************************
1069 * DestroyCursor32 (USER32.132)
1071 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1073 TRACE(cursor, "%04x\n", hCursor );
1074 /* FIXME: should check for OEM/global heap cursor here */
1075 /* Unlike DestroyCursor16, only cursors created with CreateCursor32
1076 are valid for DestroyCursor32, so don't use FreeResource32 */
1077 return (GlobalFree16( hCursor ) == 0);
1081 /***********************************************************************
1082 * DrawIcon16 (USER.84)
1084 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1086 return DrawIcon( hdc, x, y, hIcon );
1090 /***********************************************************************
1091 * DrawIcon32 (USER32.159)
1093 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1095 CURSORICONINFO *ptr;
1096 HDC hMemDC;
1097 HBITMAP hXorBits, hAndBits;
1098 COLORREF oldFg, oldBg;
1100 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1101 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1102 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1103 (char *)(ptr+1) );
1104 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1105 ptr->bBitsPerPixel, (char *)(ptr + 1)
1106 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1107 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1108 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1110 if (hXorBits && hAndBits)
1112 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1113 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1114 SelectObject( hMemDC, hXorBits );
1115 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1116 SelectObject( hMemDC, hBitTemp );
1118 DeleteDC( hMemDC );
1119 if (hXorBits) DeleteObject( hXorBits );
1120 if (hAndBits) DeleteObject( hAndBits );
1121 GlobalUnlock16( hIcon );
1122 SetTextColor( hdc, oldFg );
1123 SetBkColor( hdc, oldBg );
1124 return TRUE;
1128 /***********************************************************************
1129 * DumpIcon (USER.459)
1131 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1132 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1134 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1135 int sizeAnd, sizeXor;
1137 if (!info) return 0;
1138 sizeXor = info->nHeight * info->nWidthBytes;
1139 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1140 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1141 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1142 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1143 return MAKELONG( sizeXor, sizeXor );
1147 /***********************************************************************
1148 * SetCursor16 (USER.69)
1150 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1152 return (HCURSOR16)SetCursor( hCursor );
1156 /***********************************************************************
1157 * SetCursor32 (USER32.472)
1158 * RETURNS:
1159 * A handle to the previous cursor shape.
1161 HCURSOR WINAPI SetCursor(
1162 HCURSOR hCursor /* Handle of cursor to show */
1164 HCURSOR hOldCursor;
1166 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1167 TRACE(cursor, "%04x\n", hCursor );
1168 hOldCursor = hActiveCursor;
1169 hActiveCursor = hCursor;
1170 /* Change the cursor shape only if it is visible */
1171 if (CURSOR_ShowCount >= 0)
1173 DISPLAY_SetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1174 GlobalUnlock16( hActiveCursor );
1176 return hOldCursor;
1180 /***********************************************************************
1181 * SetCursorPos16 (USER.70)
1183 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1185 SetCursorPos( x, y );
1189 /***********************************************************************
1190 * SetCursorPos32 (USER32.474)
1192 BOOL WINAPI SetCursorPos( INT x, INT y )
1194 DISPLAY_MoveCursor( x, y );
1195 return TRUE;
1199 /***********************************************************************
1200 * ShowCursor16 (USER.71)
1202 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1204 return ShowCursor( bShow );
1208 /***********************************************************************
1209 * ShowCursor32 (USER32.530)
1211 INT WINAPI ShowCursor( BOOL bShow )
1213 TRACE(cursor, "%d, count=%d\n",
1214 bShow, CURSOR_ShowCount );
1216 if (bShow)
1218 if (++CURSOR_ShowCount == 0) /* Show it */
1220 DISPLAY_SetCursor((CURSORICONINFO*)GlobalLock16( hActiveCursor ));
1221 GlobalUnlock16( hActiveCursor );
1224 else
1226 if (--CURSOR_ShowCount == -1) /* Hide it */
1227 DISPLAY_SetCursor( NULL );
1229 return CURSOR_ShowCount;
1233 /***********************************************************************
1234 * GetCursor16 (USER.247)
1236 HCURSOR16 WINAPI GetCursor16(void)
1238 return hActiveCursor;
1242 /***********************************************************************
1243 * GetCursor32 (USER32.227)
1245 HCURSOR WINAPI GetCursor(void)
1247 return hActiveCursor;
1251 /***********************************************************************
1252 * ClipCursor16 (USER.16)
1254 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1256 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1257 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1258 return TRUE;
1262 /***********************************************************************
1263 * ClipCursor32 (USER32.53)
1265 BOOL WINAPI ClipCursor( const RECT *rect )
1267 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1268 else CopyRect( &CURSOR_ClipRect, rect );
1269 return TRUE;
1273 /***********************************************************************
1274 * GetCursorPos16 (USER.17)
1276 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
1278 DWORD posX, posY, state;
1280 if (!pt) return 0;
1281 if (!EVENT_QueryPointer( &posX, &posY, &state ))
1282 pt->x = pt->y = 0;
1283 else
1285 pt->x = posX;
1286 pt->y = posY;
1287 if (state & MK_LBUTTON)
1288 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1289 else
1290 MouseButtonsStates[0] = FALSE;
1291 if (state & MK_MBUTTON)
1292 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1293 else
1294 MouseButtonsStates[1] = FALSE;
1295 if (state & MK_RBUTTON)
1296 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1297 else
1298 MouseButtonsStates[2] = FALSE;
1300 TRACE(cursor, "ret=%d,%d\n", pt->x, pt->y );
1301 return 1;
1305 /***********************************************************************
1306 * GetCursorPos32 (USER32.229)
1308 BOOL WINAPI GetCursorPos( POINT *pt )
1310 BOOL ret;
1312 POINT16 pt16;
1313 ret = GetCursorPos16( &pt16 );
1314 if (pt) CONV_POINT16TO32( &pt16, pt );
1315 return ((pt) ? ret : 0);
1319 /***********************************************************************
1320 * GetClipCursor16 (USER.309)
1322 void WINAPI GetClipCursor16( RECT16 *rect )
1324 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1328 /***********************************************************************
1329 * GetClipCursor32 (USER32.221)
1331 BOOL WINAPI GetClipCursor( RECT *rect )
1333 if (rect)
1335 CopyRect( rect, &CURSOR_ClipRect );
1336 return TRUE;
1338 return FALSE;
1341 /**********************************************************************
1342 * LookupIconIdFromDirectoryEx16 (USER.364)
1344 * FIXME: exact parameter sizes
1346 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1347 INT16 width, INT16 height, UINT16 cFlag )
1349 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1350 UINT16 retVal = 0;
1351 if( dir && !dir->idReserved && (dir->idType & 3) )
1353 HDC hdc = GetDC(0);
1354 UINT palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1355 int colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1356 ReleaseDC(0, hdc);
1358 if( bIcon )
1360 ICONDIRENTRY* entry;
1361 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1362 if( entry ) retVal = entry->wResId;
1364 else
1366 CURSORDIRENTRY* entry;
1367 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1368 if( entry ) retVal = entry->wResId;
1371 else WARN(cursor, "invalid resource directory\n");
1372 return retVal;
1375 /**********************************************************************
1376 * LookupIconIdFromDirectoryEx32 (USER32.380)
1378 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1379 INT width, INT height, UINT cFlag )
1381 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1384 /**********************************************************************
1385 * LookupIconIdFromDirectory (USER.???)
1387 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1389 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1390 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1391 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1394 /**********************************************************************
1395 * LookupIconIdFromDirectory (USER32.379)
1397 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1399 return LookupIconIdFromDirectoryEx( dir, bIcon,
1400 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1401 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1404 /**********************************************************************
1405 * GetIconID (USER.455)
1407 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1409 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1411 TRACE(cursor, "hRes=%04x, entries=%i\n",
1412 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1414 switch(resType)
1416 case RT_CURSOR16:
1417 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1418 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1419 case RT_ICON16:
1420 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1421 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1422 default:
1423 WARN(cursor, "invalid res type %ld\n", resType );
1425 return 0;
1428 /**********************************************************************
1429 * LoadCursorIconHandler (USER.336)
1431 * Supposed to load resources of Windows 2.x applications.
1433 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1435 FIXME(cursor,"(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1436 hResource, hModule, hRsrc);
1437 return (HGLOBAL16)0;
1440 /**********************************************************************
1441 * LoadDIBIconHandler (USER.357)
1443 * RT_ICON resource loader, installed by USER_SignalProc when module
1444 * is initialized.
1446 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1448 /* If hResource is zero we must allocate a new memory block, if it's
1449 * non-zero but GlobalLock() returns NULL then it was discarded and
1450 * we have to recommit some memory, otherwise we just need to check
1451 * the block size. See LoadProc() in 16-bit SDK for more.
1454 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1455 if( hMemObj )
1457 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1458 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1459 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1460 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1462 return hMemObj;
1465 /**********************************************************************
1466 * LoadDIBCursorHandler (USER.356)
1468 * RT_CURSOR resource loader. Same as above.
1470 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1472 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1473 if( hMemObj )
1475 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1476 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1477 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1478 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1480 return hMemObj;
1483 /**********************************************************************
1484 * LoadIconHandler (USER.456)
1486 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1488 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1490 TRACE(cursor,"hRes=%04x\n",hResource);
1492 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1493 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1496 /***********************************************************************
1497 * LoadCursorW (USER32.362)
1499 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1501 return CURSORICON_Load( hInstance, name,
1502 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0);
1505 /***********************************************************************
1506 * LoadCursorA (USER32.359)
1508 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1510 HCURSOR res=0;
1511 if(!HIWORD(name))
1512 return LoadCursorW(hInstance,(LPCWSTR)name);
1513 else
1515 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1516 res = LoadCursorW(hInstance, uni);
1517 HeapFree( GetProcessHeap(), 0, uni);
1519 return res;
1521 /***********************************************************************
1522 * LoadCursorFromFile32W (USER32.361)
1524 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1526 return LoadImageW(0, name, IMAGE_CURSOR, SYSMETRICS_CXCURSOR,
1527 SYSMETRICS_CYCURSOR, LR_LOADFROMFILE);
1530 /***********************************************************************
1531 * LoadCursorFromFile32A (USER32.360)
1533 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1535 HCURSOR hcur;
1536 LPWSTR u_name = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1537 hcur = LoadCursorFromFileW(u_name);
1538 HeapFree( GetProcessHeap(), 0, u_name );
1539 return hcur;
1542 /***********************************************************************
1543 * LoadIconW (USER32.364)
1545 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1547 HDC hdc = GetDC(0);
1548 UINT palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1549 ReleaseDC(0, hdc);
1551 return CURSORICON_Load( hInstance, name,
1552 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
1553 MIN( 16, palEnts ), FALSE, 0);
1556 /***********************************************************************
1557 * LoadIconA (USER32.363)
1559 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1561 HICON res=0;
1563 if( !HIWORD(name) )
1564 return LoadIconW(hInstance, (LPCWSTR)name);
1565 else
1567 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1568 res = LoadIconW( hInstance, uni );
1569 HeapFree( GetProcessHeap(), 0, uni );
1571 return res;
1574 /**********************************************************************
1575 * GetIconInfo16 (USER.395)
1577 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1579 ICONINFO ii32;
1580 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1582 iconinfo->fIcon = ii32.fIcon;
1583 iconinfo->xHotspot = ii32.xHotspot;
1584 iconinfo->yHotspot = ii32.yHotspot;
1585 iconinfo->hbmMask = ii32.hbmMask;
1586 iconinfo->hbmColor = ii32.hbmColor;
1587 return ret;
1590 /**********************************************************************
1591 * GetIconInfo32 (USER32.242)
1593 BOOL WINAPI GetIconInfo(HICON hIcon,LPICONINFO iconinfo) {
1594 CURSORICONINFO *ciconinfo;
1596 ciconinfo = GlobalLock16(hIcon);
1597 if (!ciconinfo)
1598 return FALSE;
1599 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1600 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1601 iconinfo->fIcon = TRUE; /* hmm */
1603 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1604 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1605 (char *)(ciconinfo + 1)
1606 + ciconinfo->nHeight *
1607 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1608 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1609 1, 1, (char *)(ciconinfo + 1));
1611 GlobalUnlock16(hIcon);
1613 return TRUE;
1616 /**********************************************************************
1617 * CreateIconIndirect (USER32.78)
1619 HICON WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1620 BITMAPOBJ *bmpXor,*bmpAnd;
1621 HICON hObj;
1622 int sizeXor,sizeAnd;
1624 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1625 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1627 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1628 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1630 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1631 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1632 if (hObj)
1634 CURSORICONINFO *info;
1636 info = (CURSORICONINFO *)GlobalLock16( hObj );
1637 info->ptHotSpot.x = iconinfo->xHotspot;
1638 info->ptHotSpot.y = iconinfo->yHotspot;
1639 info->nWidth = bmpXor->bitmap.bmWidth;
1640 info->nHeight = bmpXor->bitmap.bmHeight;
1641 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1642 info->bPlanes = bmpXor->bitmap.bmPlanes;
1643 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1645 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1647 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1648 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1649 GlobalUnlock16( hObj );
1651 return hObj;
1655 /**********************************************************************
1657 DrawIconEx16 (USER.394)
1659 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1660 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1661 HBRUSH16 hbr, UINT16 flags)
1663 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1664 istep, hbr, flags);
1668 /******************************************************************************
1669 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1671 * NOTES
1672 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1674 * PARAMS
1675 * hdc [I] Handle to device context
1676 * x0 [I] X coordinate of upper left corner
1677 * y0 [I] Y coordinate of upper left corner
1678 * hIcon [I] Handle to icon to draw
1679 * cxWidth [I] Width of icon
1680 * cyWidth [I] Height of icon
1681 * istep [I] Index of frame in animated cursor
1682 * hbr [I] Handle to background brush
1683 * flags [I] Icon-drawing flags
1685 * RETURNS
1686 * Success: TRUE
1687 * Failure: FALSE
1689 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1690 INT cxWidth, INT cyWidth, UINT istep,
1691 HBRUSH hbr, UINT flags )
1693 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1694 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1695 BOOL result = FALSE, DoOffscreen = FALSE;
1696 HBITMAP hB_off = 0, hOld = 0;
1698 if (!ptr) return FALSE;
1700 if (istep)
1701 FIXME(icon, "Ignoring istep=%d\n", istep);
1702 if (flags & DI_COMPAT)
1703 FIXME(icon, "Ignoring flag DI_COMPAT\n");
1705 /* Calculate the size of the destination image. */
1706 if (cxWidth == 0)
1708 if (flags & DI_DEFAULTSIZE)
1709 cxWidth = GetSystemMetrics (SM_CXICON);
1710 else
1711 cxWidth = ptr->nWidth;
1713 if (cyWidth == 0)
1715 if (flags & DI_DEFAULTSIZE)
1716 cyWidth = GetSystemMetrics (SM_CYICON);
1717 else
1718 cyWidth = ptr->nHeight;
1721 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1722 STOCK_HOLLOW_BRUSH)))
1724 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1725 if (object)
1727 UINT16 magic = object->wMagic;
1728 GDI_HEAP_UNLOCK(hbr);
1729 DoOffscreen = magic == BRUSH_MAGIC;
1732 if (DoOffscreen) {
1733 RECT r = {0, 0, cxWidth, cxWidth};
1735 hDC_off = CreateCompatibleDC(hdc);
1736 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1737 if (hDC_off && hB_off) {
1738 hOld = SelectObject(hDC_off, hB_off);
1739 FillRect(hDC_off, &r, hbr);
1743 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1745 HBITMAP hXorBits, hAndBits;
1746 COLORREF oldFg, oldBg;
1747 INT nStretchMode;
1749 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1751 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1752 ptr->bPlanes, ptr->bBitsPerPixel,
1753 (char *)(ptr + 1)
1754 + ptr->nHeight *
1755 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1756 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1757 1, 1, (char *)(ptr+1) );
1758 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1759 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1761 if (hXorBits && hAndBits)
1763 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1764 if (flags & DI_MASK)
1766 if (DoOffscreen)
1767 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1768 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1769 else
1770 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1771 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1773 SelectObject( hMemDC, hXorBits );
1774 if (flags & DI_IMAGE)
1776 if (DoOffscreen)
1777 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1778 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1779 else
1780 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1781 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1783 SelectObject( hMemDC, hBitTemp );
1784 result = TRUE;
1787 SetTextColor( hdc, oldFg );
1788 SetBkColor( hdc, oldBg );
1789 if (hXorBits) DeleteObject( hXorBits );
1790 if (hAndBits) DeleteObject( hAndBits );
1791 SetStretchBltMode (hdc, nStretchMode);
1792 if (DoOffscreen) {
1793 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
1794 SelectObject(hDC_off, hOld);
1797 if (hMemDC) DeleteDC( hMemDC );
1798 if (hDC_off) DeleteDC(hDC_off);
1799 if (hB_off) DeleteObject(hB_off);
1800 GlobalUnlock16( hIcon );
1801 return result;