Moved error codes to cderr.h.
[wine/multimedia.git] / objects / cursoricon.c
blobfc787f32d3aea69cb061fd85257ff4860826da7c
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 */
57 /**********************************************************************
58 * ICONCACHE for cursors/icons loaded with LR_SHARED.
60 * FIXME: This should not be allocated on the system heap, but on a
61 * subsystem-global heap (i.e. one for all Win16 processes,
62 * and one each for every Win32 process).
64 typedef struct tagICONCACHE
66 struct tagICONCACHE *next;
68 HMODULE hModule;
69 HRSRC hRsrc;
70 HANDLE handle;
72 INT count;
74 } ICONCACHE;
76 static ICONCACHE *IconAnchor = NULL;
77 static CRITICAL_SECTION IconCrst;
79 /**********************************************************************
80 * CURSORICON_Init
82 void CURSORICON_Init( void )
84 InitializeCriticalSection( &IconCrst );
85 MakeCriticalSectionGlobal( &IconCrst );
88 /**********************************************************************
89 * CURSORICON_FindSharedIcon
91 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
93 HANDLE handle = 0;
94 ICONCACHE *ptr;
96 EnterCriticalSection( &IconCrst );
98 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
99 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
101 ptr->count++;
102 handle = ptr->handle;
103 break;
106 LeaveCriticalSection( &IconCrst );
108 return handle;
111 /**********************************************************************
112 * CURSORICON_AddSharedIcon
114 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HANDLE handle )
116 ICONCACHE *ptr = HeapAlloc( SystemHeap, 0, sizeof(ICONCACHE) );
117 if ( !ptr ) return;
119 ptr->hModule = hModule;
120 ptr->hRsrc = hRsrc;
121 ptr->handle = handle;
122 ptr->count = 1;
124 EnterCriticalSection( &IconCrst );
125 ptr->next = IconAnchor;
126 IconAnchor = ptr;
127 LeaveCriticalSection( &IconCrst );
130 /**********************************************************************
131 * CURSORICON_DelSharedIcon
133 static INT CURSORICON_DelSharedIcon( HANDLE handle )
135 INT count = -1;
136 ICONCACHE *ptr;
138 EnterCriticalSection( &IconCrst );
140 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
141 if ( ptr->handle == handle )
143 if ( ptr->count > 0 ) ptr->count--;
144 count = ptr->count;
145 break;
148 LeaveCriticalSection( &IconCrst );
150 return count;
153 /**********************************************************************
154 * CURSORICON_FreeModuleIcons
156 void CURSORICON_FreeModuleIcons( HMODULE hModule )
158 ICONCACHE **ptr = &IconAnchor;
160 if ( HIWORD( hModule ) )
161 hModule = MapHModuleLS( hModule );
162 else
163 hModule = GetExePtr( hModule );
165 EnterCriticalSection( &IconCrst );
167 while ( *ptr )
169 if ( (*ptr)->hModule == hModule )
171 ICONCACHE *freePtr = *ptr;
172 *ptr = freePtr->next;
174 GlobalFree16( freePtr->handle );
175 HeapFree( SystemHeap, 0, freePtr );
176 continue;
178 ptr = &(*ptr)->next;
181 LeaveCriticalSection( &IconCrst );
184 /**********************************************************************
185 * CURSORICON_FindBestIcon
187 * Find the icon closest to the requested size and number of colors.
189 static ICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
190 int height, int colors )
192 int i, maxcolors, maxwidth, maxheight;
193 ICONDIRENTRY *entry, *bestEntry = NULL;
195 if (dir->idCount < 1)
197 WARN(icon, "Empty directory!\n" );
198 return NULL;
200 if (dir->idCount == 1) return &dir->idEntries[0].icon; /* No choice... */
202 /* First find the exact size with less colors */
204 maxcolors = 0;
205 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
206 if ((entry->bWidth == width) && (entry->bHeight == height) &&
207 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
209 bestEntry = entry;
210 maxcolors = entry->bColorCount;
212 if (bestEntry) return bestEntry;
214 /* First find the exact size with more colors */
216 maxcolors = 255;
217 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
218 if ((entry->bWidth == width) && (entry->bHeight == height) &&
219 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
221 bestEntry = entry;
222 maxcolors = entry->bColorCount;
224 if (bestEntry) return bestEntry;
226 /* Now find a smaller one with less colors */
228 maxcolors = maxwidth = maxheight = 0;
229 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
230 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
231 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
232 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
234 bestEntry = entry;
235 maxwidth = entry->bWidth;
236 maxheight = entry->bHeight;
237 maxcolors = entry->bColorCount;
239 if (bestEntry) return bestEntry;
241 /* Now find a smaller one with more colors */
243 maxcolors = 255;
244 maxwidth = maxheight = 0;
245 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
246 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
247 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
248 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
250 bestEntry = entry;
251 maxwidth = entry->bWidth;
252 maxheight = entry->bHeight;
253 maxcolors = entry->bColorCount;
255 if (bestEntry) return bestEntry;
257 /* Now find a larger one with less colors */
259 maxcolors = 0;
260 maxwidth = maxheight = 255;
261 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
262 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
263 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
265 bestEntry = entry;
266 maxwidth = entry->bWidth;
267 maxheight = entry->bHeight;
268 maxcolors = entry->bColorCount;
270 if (bestEntry) return bestEntry;
272 /* Now find a larger one with more colors */
274 maxcolors = maxwidth = maxheight = 255;
275 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
276 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
277 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
279 bestEntry = entry;
280 maxwidth = entry->bWidth;
281 maxheight = entry->bHeight;
282 maxcolors = entry->bColorCount;
285 return bestEntry;
289 /**********************************************************************
290 * CURSORICON_FindBestCursor
292 * Find the cursor closest to the requested size.
293 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
294 * ignored too
296 static CURSORDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
297 int width, int height, int color)
299 int i, maxwidth, maxheight;
300 CURSORDIRENTRY *entry, *bestEntry = NULL;
302 if (dir->idCount < 1)
304 WARN(cursor, "Empty directory!\n" );
305 return NULL;
307 if (dir->idCount == 1) return &dir->idEntries[0].cursor; /* No choice... */
309 /* First find the largest one smaller than or equal to the requested size*/
311 maxwidth = maxheight = 0;
312 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
313 if ((entry->wWidth <= width) && (entry->wHeight <= height) &&
314 (entry->wWidth > maxwidth) && (entry->wHeight > maxheight) &&
315 (entry->wBitCount == 1))
317 bestEntry = entry;
318 maxwidth = entry->wWidth;
319 maxheight = entry->wHeight;
321 if (bestEntry) return bestEntry;
323 /* Now find the smallest one larger than the requested size */
325 maxwidth = maxheight = 255;
326 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
327 if ((entry->wWidth < maxwidth) && (entry->wHeight < maxheight) &&
328 (entry->wBitCount == 1))
330 bestEntry = entry;
331 maxwidth = entry->wWidth;
332 maxheight = entry->wHeight;
335 return bestEntry;
338 /*********************************************************************
339 * The main purpose of this function is to create fake resource directory
340 * and fake resource entries. There are several reasons for this:
341 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
342 * fields
343 * There are some "bad" cursor files which do not have
344 * bColorCount initialized but instead one must read this info
345 * directly from corresponding DIB sections
346 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
348 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
349 CURSORICONDIR **res, LPBYTE **ptr)
351 LPBYTE _free;
352 CURSORICONFILEDIR *bits;
353 int entries, size, i;
355 *res = NULL;
356 *ptr = NULL;
357 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
359 /* FIXME: test for inimated icons
360 * hack to load the first icon from the *.ani file
362 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
363 { LPBYTE pos = (LPBYTE) bits;
364 FIXME (cursor,"Animated icons not correctly implemented! %p \n", bits);
366 for (;;)
367 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
368 { FIXME (cursor,"icon entry found! %p\n", bits);
369 pos+=4;
370 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
371 { goto fail;
373 bits+=2;
374 FIXME (cursor,"icon size ok %p \n", bits);
375 break;
377 pos+=2;
378 if (pos>=(LPBYTE)bits+766) goto fail;
381 if (!(entries = bits->idCount)) goto fail;
382 (int)_free = size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) *
383 (entries - 1);
384 for (i=0; i < entries; i++)
385 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
387 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
388 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
389 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
391 _free = (LPBYTE)(*res) + (int)_free;
392 memcpy((*res), bits, 6);
393 for (i=0; i<entries; i++)
395 ((LPBYTE*)(*ptr))[i] = _free;
396 if (fCursor) {
397 (*res)->idEntries[i].cursor.wWidth=bits->idEntries[i].bWidth;
398 (*res)->idEntries[i].cursor.wHeight=bits->idEntries[i].bHeight;
399 (*res)->idEntries[i].cursor.wPlanes=1;
400 (*res)->idEntries[i].cursor.wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
401 bits->idEntries[i].dwDIBOffset))->biBitCount;
402 (*res)->idEntries[i].cursor.dwBytesInRes = bits->idEntries[i].dwDIBSize;
403 (*res)->idEntries[i].cursor.wResId=i+1;
404 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
405 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
406 _free+=sizeof(POINT16);
407 } else {
408 (*res)->idEntries[i].icon.bWidth=bits->idEntries[i].bWidth;
409 (*res)->idEntries[i].icon.bHeight=bits->idEntries[i].bHeight;
410 (*res)->idEntries[i].icon.bColorCount = bits->idEntries[i].bColorCount;
411 (*res)->idEntries[i].icon.wPlanes=1;
412 (*res)->idEntries[i].icon.wBitCount= ((LPBITMAPINFOHEADER)((LPBYTE)bits +
413 bits->idEntries[i].dwDIBOffset))->biBitCount;
414 (*res)->idEntries[i].icon.dwBytesInRes = bits->idEntries[i].dwDIBSize;
415 (*res)->idEntries[i].icon.wResId=i+1;
417 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
418 (*res)->idEntries[i].icon.dwBytesInRes);
419 _free += (*res)->idEntries[i].icon.dwBytesInRes;
421 UnmapViewOfFile( bits );
422 return TRUE;
423 fail:
424 if (*res) HeapFree( GetProcessHeap(), 0, *res );
425 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
426 UnmapViewOfFile( bits );
427 return FALSE;
431 /**********************************************************************
432 * CURSORICON_CreateFromResource
434 * Create a cursor or icon from in-memory resource template.
436 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
437 * with cbSize parameter as well.
439 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
440 UINT cbSize, BOOL bIcon, DWORD dwVersion,
441 INT width, INT height, UINT loadflags )
443 int sizeAnd, sizeXor;
444 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
445 BITMAPOBJ *bmpXor, *bmpAnd;
446 POINT16 hotspot = { 0 ,0 };
447 BITMAPINFO *bmi;
448 HDC hdc;
449 BOOL DoStretch;
450 INT size;
452 TRACE(cursor,"%08x (%u bytes), ver %08x, %ix%i %s %s\n",
453 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
454 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
455 if (dwVersion == 0x00020000)
457 FIXME(cursor,"\t2.xx resources are not supported\n");
458 return 0;
461 if (bIcon)
462 bmi = (BITMAPINFO *)bits;
463 else /* get the hotspot */
465 POINT16 *pt = (POINT16 *)bits;
466 hotspot = *pt;
467 bmi = (BITMAPINFO *)(pt + 1);
469 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
471 if (!width) width = bmi->bmiHeader.biWidth;
472 if (!height) height = bmi->bmiHeader.biHeight/2;
473 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
474 (bmi->bmiHeader.biWidth != width);
476 /* Check bitmap header */
478 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
479 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
480 bmi->bmiHeader.biCompression != BI_RGB) )
482 WARN(cursor,"\tinvalid resource bitmap header.\n");
483 return 0;
486 if( (hdc = GetDC( 0 )) )
488 BITMAPINFO* pInfo;
490 /* Make sure we have room for the monochrome bitmap later on.
491 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
492 * up to and including the biBitCount. In-memory icon resource
493 * format is as follows:
495 * BITMAPINFOHEADER icHeader // DIB header
496 * RGBQUAD icColors[] // Color table
497 * BYTE icXOR[] // DIB bits for XOR mask
498 * BYTE icAND[] // DIB bits for AND mask
501 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
502 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
504 memcpy( pInfo, bmi, size );
505 pInfo->bmiHeader.biHeight /= 2;
507 /* Create the XOR bitmap */
509 if (DoStretch) {
510 if ((hXorBits = CreateCompatibleBitmap(hdc, width, height))) {
511 HBITMAP hOld;
512 HDC hMem = CreateCompatibleDC(hdc);
513 BOOL res;
515 if (hMem) {
516 hOld = SelectObject(hMem, hXorBits);
517 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
518 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
519 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
520 SelectObject(hMem, hOld);
521 DeleteDC(hMem);
522 } else res = FALSE;
523 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
525 } else hXorBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
526 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
527 if( hXorBits )
529 char* bits = (char *)bmi + size + bmi->bmiHeader.biHeight *
530 DIB_GetDIBWidthBytes(bmi->bmiHeader.biWidth,
531 bmi->bmiHeader.biBitCount) / 2;
533 pInfo->bmiHeader.biBitCount = 1;
534 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
536 RGBQUAD *rgb = pInfo->bmiColors;
538 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
539 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
540 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
541 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
543 else
545 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
547 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
548 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
551 /* Create the AND bitmap */
553 if (DoStretch) {
554 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
555 HBITMAP hOld;
556 HDC hMem = CreateCompatibleDC(hdc);
557 BOOL res;
559 if (hMem) {
560 hOld = SelectObject(hMem, hAndBits);
561 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
562 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
563 bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
564 SelectObject(hMem, hOld);
565 DeleteDC(hMem);
566 } else res = FALSE;
567 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
569 } else hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
570 CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
572 if( !hAndBits ) DeleteObject( hXorBits );
574 HeapFree( GetProcessHeap(), 0, pInfo );
576 ReleaseDC( 0, hdc );
579 if( !hXorBits || !hAndBits )
581 WARN(cursor,"\tunable to create an icon bitmap.\n");
582 return 0;
585 /* Now create the CURSORICONINFO structure */
586 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
587 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
588 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
589 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
591 if (hObj) hObj = GlobalReAlloc16( hObj,
592 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
593 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
594 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
595 if (hObj)
597 CURSORICONINFO *info;
599 /* Make it owned by the module */
600 if (hInstance) FarSetOwner16( hObj, GetExePtr(hInstance) );
602 info = (CURSORICONINFO *)GlobalLock16( hObj );
603 info->ptHotSpot.x = hotspot.x;
604 info->ptHotSpot.y = hotspot.y;
605 info->nWidth = bmpXor->bitmap.bmWidth;
606 info->nHeight = bmpXor->bitmap.bmHeight;
607 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
608 info->bPlanes = bmpXor->bitmap.bmPlanes;
609 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
611 /* Transfer the bitmap bits to the CURSORICONINFO structure */
613 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
614 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
615 GlobalUnlock16( hObj );
618 DeleteObject( hXorBits );
619 DeleteObject( hAndBits );
620 return hObj;
624 /**********************************************************************
625 * CreateIconFromResourceEx16 (USER.450)
627 * FIXME: not sure about exact parameter types
629 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
630 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
632 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
633 width, height, cFlag);
637 /**********************************************************************
638 * CreateIconFromResource (USER32.76)
640 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
641 BOOL bIcon, DWORD dwVersion)
643 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
647 /**********************************************************************
648 * CreateIconFromResourceEx32 (USER32.77)
650 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
651 BOOL bIcon, DWORD dwVersion,
652 INT width, INT height,
653 UINT cFlag )
655 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
656 if( pTask )
657 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
658 width, height, cFlag );
659 return 0;
662 /**********************************************************************
663 * CURSORICON_Load
665 * Load a cursor or icon from resource or file.
667 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
668 INT width, INT height, INT colors,
669 BOOL fCursor, UINT loadflags )
671 HANDLE handle = 0, h = 0;
672 HANDLE hRsrc;
673 CURSORICONDIR *dir;
674 CURSORICONDIRENTRY *dirEntry;
675 LPBYTE bits;
677 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
679 LPBYTE *ptr;
680 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
681 return 0;
682 if (fCursor)
683 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
684 else
685 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
686 bits = ptr[dirEntry->icon.wResId-1];
687 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->icon.dwBytesInRes,
688 !fCursor, 0x00030000, width, height, loadflags);
689 HeapFree( GetProcessHeap(), 0, dir );
690 HeapFree( GetProcessHeap(), 0, ptr );
693 else if ( !hInstance ) /* Load OEM cursor/icon */
695 WORD resid;
696 HDC hdc;
697 DC *dc;
699 if ( HIWORD(name) )
701 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
702 if( ansi[0]=='#') /*Check for '#xxx' name */
704 resid = atoi(ansi+1);
705 HeapFree( GetProcessHeap(), 0, ansi );
707 else
709 HeapFree( GetProcessHeap(), 0, ansi );
710 return 0;
713 else resid = LOWORD(name);
714 hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
715 dc = DC_GetDCPtr( hdc );
716 if (dc->funcs->pLoadOEMResource)
717 h = dc->funcs->pLoadOEMResource( resid, fCursor ?
718 OEM_CURSOR : OEM_ICON );
719 GDI_HEAP_UNLOCK( hdc );
720 DeleteDC( hdc );
723 else /* Load from resource */
725 WORD wResId;
726 DWORD dwBytesInRes;
728 /* Normalize hInstance (must be uniquely represented for icon cache) */
730 if ( HIWORD( hInstance ) )
731 hInstance = MapHModuleLS( hInstance );
732 else
733 hInstance = GetExePtr( hInstance );
735 /* Get directory resource ID */
737 if (!(hRsrc = FindResourceW( hInstance, name,
738 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
739 return 0;
741 /* If shared icon, check whether it was already loaded */
743 if ( (loadflags & LR_SHARED)
744 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
745 return h;
747 /* Find the best entry in the directory */
749 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
750 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
751 if (fCursor)
752 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
753 width, height, 1);
754 else
755 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
756 width, height, colors );
757 if (!dirEntry) return 0;
758 wResId = dirEntry->icon.wResId;
759 dwBytesInRes = dirEntry->icon.dwBytesInRes;
760 FreeResource( handle );
762 /* Load the resource */
764 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
765 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
766 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
767 bits = (LPBYTE)LockResource( handle );
768 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
769 !fCursor, 0x00030000, width, height, loadflags);
770 FreeResource( handle );
772 /* If shared icon, add to icon cache */
774 if ( h && (loadflags & LR_SHARED) )
775 CURSORICON_AddSharedIcon( hInstance, hRsrc, h );
778 return h;
781 /***********************************************************************
782 * CURSORICON_Copy
784 * Make a copy of a cursor or icon.
786 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
788 char *ptrOld, *ptrNew;
789 int size;
790 HGLOBAL16 hNew;
792 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
793 if (!(hInstance = GetExePtr( hInstance ))) return 0;
794 size = GlobalSize16( handle );
795 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
796 FarSetOwner16( hNew, hInstance );
797 ptrNew = (char *)GlobalLock16( hNew );
798 memcpy( ptrNew, ptrOld, size );
799 GlobalUnlock16( handle );
800 GlobalUnlock16( hNew );
801 return hNew;
804 /***********************************************************************
805 * CURSORICON_IconToCursor
807 * Converts bitmap to mono and truncates if icon is too large (should
808 * probably do StretchBlt() instead).
810 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
812 HCURSOR16 hRet = 0;
813 CURSORICONINFO *pIcon = NULL;
814 HTASK16 hTask = GetCurrentTask();
815 TDB* pTask = (TDB *)GlobalLock16(hTask);
817 if(hIcon && pTask)
818 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
819 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
820 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
821 else
823 BYTE pAndBits[128];
824 BYTE pXorBits[128];
825 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
826 BYTE* psPtr, *pxbPtr = pXorBits;
827 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
828 BYTE* pbc = NULL;
830 COLORREF col;
831 CURSORICONINFO cI;
833 TRACE(icon, "[%04x] %ix%i %ibpp (bogus %ibps)\n",
834 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
836 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
837 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
838 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
840 memset(pXorBits, 0, 128);
841 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
842 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
843 cI.nWidth = 32; cI.nHeight = 32;
844 cI.nWidthBytes = 4; /* 32x1bpp */
846 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
847 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
849 for( iy = 0; iy < maxy; iy++ )
851 unsigned shift = iy % 2;
853 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
854 (and_width > 4) ? 4 : and_width );
855 for( ix = 0; ix < maxx; ix++ )
857 if( bSemiTransparent && ((ix+shift)%2) )
859 /* set AND bit, XOR bit stays 0 */
861 pbc = pAndBits + iy * 4 + ix/8;
862 *pbc |= 0x80 >> (ix%8);
864 else
866 /* keep AND bit, set XOR bit */
868 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
869 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
870 col = COLOR_ToLogical(val);
871 if( (GetRValue(col) + GetGValue(col) + GetBValue(col)) > 0x180 )
873 pbc = pxbPtr + ix/8;
874 *pbc |= 0x80 >> (ix%8);
878 psPtr += xor_width;
879 pxbPtr += 4;
882 hRet = CreateCursorIconIndirect16( pTask->hInstance , &cI, pAndBits, pXorBits);
884 if( !hRet ) /* fall back on default drag cursor */
885 hRet = CURSORICON_Copy( pTask->hInstance ,
886 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
887 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0) );
890 return hRet;
894 /***********************************************************************
895 * LoadCursor16 (USER.173)
897 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
899 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
900 return LoadCursorA( hInstance, nameStr );
904 /***********************************************************************
905 * LoadIcon16 (USER.174)
907 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
909 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
910 return LoadIconA( hInstance, nameStr );
914 /***********************************************************************
915 * CreateCursor16 (USER.406)
917 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
918 INT16 xHotSpot, INT16 yHotSpot,
919 INT16 nWidth, INT16 nHeight,
920 LPCVOID lpANDbits, LPCVOID lpXORbits )
922 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
924 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
925 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
926 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
930 /***********************************************************************
931 * CreateCursor32 (USER32.67)
933 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
934 INT xHotSpot, INT yHotSpot,
935 INT nWidth, INT nHeight,
936 LPCVOID lpANDbits, LPCVOID lpXORbits )
938 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
940 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
941 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
942 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
946 /***********************************************************************
947 * CreateIcon16 (USER.407)
949 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
950 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
951 LPCVOID lpANDbits, LPCVOID lpXORbits )
953 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
955 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
956 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
957 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
961 /***********************************************************************
962 * CreateIcon32 (USER32.75)
964 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
965 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
966 LPCVOID lpANDbits, LPCVOID lpXORbits )
968 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
970 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
971 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
972 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
976 /***********************************************************************
977 * CreateCursorIconIndirect (USER.408)
979 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
980 CURSORICONINFO *info,
981 LPCVOID lpANDbits,
982 LPCVOID lpXORbits )
984 HGLOBAL16 handle;
985 char *ptr;
986 int sizeAnd, sizeXor;
988 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
989 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
990 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
991 sizeXor = info->nHeight * info->nWidthBytes;
992 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
993 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
994 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
995 return 0;
996 if (hInstance) FarSetOwner16( handle, hInstance );
997 ptr = (char *)GlobalLock16( handle );
998 memcpy( ptr, info, sizeof(*info) );
999 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1000 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1001 GlobalUnlock16( handle );
1002 return handle;
1006 /***********************************************************************
1007 * CopyIcon16 (USER.368)
1009 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1011 TRACE(icon, "%04x %04x\n", hInstance, hIcon );
1012 return CURSORICON_Copy( hInstance, hIcon );
1016 /***********************************************************************
1017 * CopyIcon32 (USER32.60)
1019 HICON WINAPI CopyIcon( HICON hIcon )
1021 HTASK16 hTask = GetCurrentTask ();
1022 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1023 TRACE(icon, "%04x\n", hIcon );
1024 return CURSORICON_Copy( pTask->hInstance, hIcon );
1028 /***********************************************************************
1029 * CopyCursor16 (USER.369)
1031 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1033 TRACE(cursor, "%04x %04x\n", hInstance, hCursor );
1034 return CURSORICON_Copy( hInstance, hCursor );
1037 /**********************************************************************
1038 * CURSORICON_Destroy (USER.610)
1040 * This routine is actually exported from Win95 USER under the name
1041 * DestroyIcon32 ... The behaviour implemented here should mimic
1042 * the Win95 one exactly, especially the return values, which
1043 * depend on the setting of various flags.
1045 WORD CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1047 WORD retv;
1049 TRACE( icon, "(%04x, %04x)\n", handle, flags );
1051 /* Check whether destroying active cursor */
1053 if ( hActiveCursor == handle )
1055 ERR( cursor, "Destroying active cursor!\n" );
1056 SetCursor( 0 );
1059 /* Try shared cursor/icon first */
1061 if ( !(flags & CID_NONSHARED) )
1063 INT count = CURSORICON_DelSharedIcon( handle );
1065 if ( count != -1 )
1066 return (flags & CID_WIN32)? TRUE : (count == 0);
1068 /* FIXME: OEM cursors/icons should be recognized */
1071 /* Now assume non-shared cursor/icon */
1073 retv = GlobalFree16( handle );
1074 return (flags & CID_RESOURCE)? retv : TRUE;
1077 /***********************************************************************
1078 * DestroyIcon16 (USER.457)
1080 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1082 return CURSORICON_Destroy( hIcon, 0 );
1085 /***********************************************************************
1086 * DestroyIcon (USER32.133)
1088 BOOL WINAPI DestroyIcon( HICON hIcon )
1090 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1093 /***********************************************************************
1094 * DestroyCursor16 (USER.458)
1096 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1098 return CURSORICON_Destroy( hCursor, 0 );
1101 /***********************************************************************
1102 * DestroyCursor (USER32.132)
1104 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1106 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1110 /***********************************************************************
1111 * DrawIcon16 (USER.84)
1113 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1115 return DrawIcon( hdc, x, y, hIcon );
1119 /***********************************************************************
1120 * DrawIcon32 (USER32.159)
1122 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1124 CURSORICONINFO *ptr;
1125 HDC hMemDC;
1126 HBITMAP hXorBits, hAndBits;
1127 COLORREF oldFg, oldBg;
1129 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1130 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1131 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1132 (char *)(ptr+1) );
1133 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1134 ptr->bBitsPerPixel, (char *)(ptr + 1)
1135 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1136 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1137 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1139 if (hXorBits && hAndBits)
1141 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1142 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1143 SelectObject( hMemDC, hXorBits );
1144 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1145 SelectObject( hMemDC, hBitTemp );
1147 DeleteDC( hMemDC );
1148 if (hXorBits) DeleteObject( hXorBits );
1149 if (hAndBits) DeleteObject( hAndBits );
1150 GlobalUnlock16( hIcon );
1151 SetTextColor( hdc, oldFg );
1152 SetBkColor( hdc, oldBg );
1153 return TRUE;
1157 /***********************************************************************
1158 * DumpIcon (USER.459)
1160 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1161 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1163 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1164 int sizeAnd, sizeXor;
1166 if (!info) return 0;
1167 sizeXor = info->nHeight * info->nWidthBytes;
1168 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1169 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1170 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1171 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1172 return MAKELONG( sizeXor, sizeXor );
1176 /***********************************************************************
1177 * SetCursor16 (USER.69)
1179 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1181 return (HCURSOR16)SetCursor( hCursor );
1185 /***********************************************************************
1186 * SetCursor32 (USER32.472)
1187 * RETURNS:
1188 * A handle to the previous cursor shape.
1190 HCURSOR WINAPI SetCursor(
1191 HCURSOR hCursor /* Handle of cursor to show */
1193 HCURSOR hOldCursor;
1195 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1196 TRACE(cursor, "%04x\n", hCursor );
1197 hOldCursor = hActiveCursor;
1198 hActiveCursor = hCursor;
1199 /* Change the cursor shape only if it is visible */
1200 if (CURSOR_ShowCount >= 0)
1202 DISPLAY_SetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1203 GlobalUnlock16( hActiveCursor );
1205 return hOldCursor;
1209 /***********************************************************************
1210 * SetCursorPos16 (USER.70)
1212 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1214 SetCursorPos( x, y );
1218 /***********************************************************************
1219 * SetCursorPos32 (USER32.474)
1221 BOOL WINAPI SetCursorPos( INT x, INT y )
1223 DISPLAY_MoveCursor( x, y );
1224 return TRUE;
1228 /***********************************************************************
1229 * ShowCursor16 (USER.71)
1231 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1233 return ShowCursor( bShow );
1237 /***********************************************************************
1238 * ShowCursor32 (USER32.530)
1240 INT WINAPI ShowCursor( BOOL bShow )
1242 TRACE(cursor, "%d, count=%d\n",
1243 bShow, CURSOR_ShowCount );
1245 if (bShow)
1247 if (++CURSOR_ShowCount == 0) /* Show it */
1249 DISPLAY_SetCursor((CURSORICONINFO*)GlobalLock16( hActiveCursor ));
1250 GlobalUnlock16( hActiveCursor );
1253 else
1255 if (--CURSOR_ShowCount == -1) /* Hide it */
1256 DISPLAY_SetCursor( NULL );
1258 return CURSOR_ShowCount;
1262 /***********************************************************************
1263 * GetCursor16 (USER.247)
1265 HCURSOR16 WINAPI GetCursor16(void)
1267 return hActiveCursor;
1271 /***********************************************************************
1272 * GetCursor32 (USER32.227)
1274 HCURSOR WINAPI GetCursor(void)
1276 return hActiveCursor;
1280 /***********************************************************************
1281 * ClipCursor16 (USER.16)
1283 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1285 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1286 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1287 return TRUE;
1291 /***********************************************************************
1292 * ClipCursor32 (USER32.53)
1294 BOOL WINAPI ClipCursor( const RECT *rect )
1296 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1297 else CopyRect( &CURSOR_ClipRect, rect );
1298 return TRUE;
1302 /***********************************************************************
1303 * GetCursorPos16 (USER.17)
1305 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
1307 DWORD posX, posY, state;
1309 if (!pt) return 0;
1310 if (!EVENT_QueryPointer( &posX, &posY, &state ))
1311 pt->x = pt->y = 0;
1312 else
1314 pt->x = posX;
1315 pt->y = posY;
1316 if (state & MK_LBUTTON)
1317 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1318 else
1319 MouseButtonsStates[0] = FALSE;
1320 if (state & MK_MBUTTON)
1321 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1322 else
1323 MouseButtonsStates[1] = FALSE;
1324 if (state & MK_RBUTTON)
1325 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1326 else
1327 MouseButtonsStates[2] = FALSE;
1329 TRACE(cursor, "ret=%d,%d\n", pt->x, pt->y );
1330 return 1;
1334 /***********************************************************************
1335 * GetCursorPos32 (USER32.229)
1337 BOOL WINAPI GetCursorPos( POINT *pt )
1339 BOOL ret;
1341 POINT16 pt16;
1342 ret = GetCursorPos16( &pt16 );
1343 if (pt) CONV_POINT16TO32( &pt16, pt );
1344 return ((pt) ? ret : 0);
1348 /***********************************************************************
1349 * GetClipCursor16 (USER.309)
1351 void WINAPI GetClipCursor16( RECT16 *rect )
1353 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1357 /***********************************************************************
1358 * GetClipCursor32 (USER32.221)
1360 BOOL WINAPI GetClipCursor( RECT *rect )
1362 if (rect)
1364 CopyRect( rect, &CURSOR_ClipRect );
1365 return TRUE;
1367 return FALSE;
1370 /**********************************************************************
1371 * LookupIconIdFromDirectoryEx16 (USER.364)
1373 * FIXME: exact parameter sizes
1375 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1376 INT16 width, INT16 height, UINT16 cFlag )
1378 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1379 UINT16 retVal = 0;
1380 if( dir && !dir->idReserved && (dir->idType & 3) )
1382 HDC hdc = GetDC(0);
1383 UINT palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1384 int colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1385 ReleaseDC(0, hdc);
1387 if( bIcon )
1389 ICONDIRENTRY* entry;
1390 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1391 if( entry ) retVal = entry->wResId;
1393 else
1395 CURSORDIRENTRY* entry;
1396 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1397 if( entry ) retVal = entry->wResId;
1400 else WARN(cursor, "invalid resource directory\n");
1401 return retVal;
1404 /**********************************************************************
1405 * LookupIconIdFromDirectoryEx32 (USER32.380)
1407 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1408 INT width, INT height, UINT cFlag )
1410 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1413 /**********************************************************************
1414 * LookupIconIdFromDirectory (USER.???)
1416 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1418 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1419 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1420 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1423 /**********************************************************************
1424 * LookupIconIdFromDirectory (USER32.379)
1426 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1428 return LookupIconIdFromDirectoryEx( dir, bIcon,
1429 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1430 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1433 /**********************************************************************
1434 * GetIconID (USER.455)
1436 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1438 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1440 TRACE(cursor, "hRes=%04x, entries=%i\n",
1441 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1443 switch(resType)
1445 case RT_CURSOR16:
1446 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1447 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1448 case RT_ICON16:
1449 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1450 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1451 default:
1452 WARN(cursor, "invalid res type %ld\n", resType );
1454 return 0;
1457 /**********************************************************************
1458 * LoadCursorIconHandler (USER.336)
1460 * Supposed to load resources of Windows 2.x applications.
1462 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1464 FIXME(cursor,"(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1465 hResource, hModule, hRsrc);
1466 return (HGLOBAL16)0;
1469 /**********************************************************************
1470 * LoadDIBIconHandler (USER.357)
1472 * RT_ICON resource loader, installed by USER_SignalProc when module
1473 * is initialized.
1475 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1477 /* If hResource is zero we must allocate a new memory block, if it's
1478 * non-zero but GlobalLock() returns NULL then it was discarded and
1479 * we have to recommit some memory, otherwise we just need to check
1480 * the block size. See LoadProc() in 16-bit SDK for more.
1483 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1484 if( hMemObj )
1486 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1487 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1488 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1489 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1491 return hMemObj;
1494 /**********************************************************************
1495 * LoadDIBCursorHandler (USER.356)
1497 * RT_CURSOR resource loader. Same as above.
1499 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1501 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1502 if( hMemObj )
1504 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1505 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1506 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1507 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1509 return hMemObj;
1512 /**********************************************************************
1513 * LoadIconHandler (USER.456)
1515 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1517 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1519 TRACE(cursor,"hRes=%04x\n",hResource);
1521 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1522 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1525 /***********************************************************************
1526 * LoadCursorW (USER32.362)
1528 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1530 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1531 LR_SHARED | LR_DEFAULTSIZE );
1534 /***********************************************************************
1535 * LoadCursorA (USER32.359)
1537 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1539 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1540 LR_SHARED | LR_DEFAULTSIZE );
1543 /***********************************************************************
1544 * LoadCursorFromFileW (USER32.361)
1546 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1548 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1549 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1552 /***********************************************************************
1553 * LoadCursorFromFileA (USER32.360)
1555 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1557 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1558 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1561 /***********************************************************************
1562 * LoadIconW (USER32.364)
1564 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1566 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1567 LR_SHARED | LR_DEFAULTSIZE );
1570 /***********************************************************************
1571 * LoadIconA (USER32.363)
1573 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1575 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1576 LR_SHARED | LR_DEFAULTSIZE );
1579 /**********************************************************************
1580 * GetIconInfo16 (USER.395)
1582 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1584 ICONINFO ii32;
1585 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1587 iconinfo->fIcon = ii32.fIcon;
1588 iconinfo->xHotspot = ii32.xHotspot;
1589 iconinfo->yHotspot = ii32.yHotspot;
1590 iconinfo->hbmMask = ii32.hbmMask;
1591 iconinfo->hbmColor = ii32.hbmColor;
1592 return ret;
1595 /**********************************************************************
1596 * GetIconInfo32 (USER32.242)
1598 BOOL WINAPI GetIconInfo(HICON hIcon,LPICONINFO iconinfo) {
1599 CURSORICONINFO *ciconinfo;
1601 ciconinfo = GlobalLock16(hIcon);
1602 if (!ciconinfo)
1603 return FALSE;
1604 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1605 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1606 iconinfo->fIcon = TRUE; /* hmm */
1608 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1609 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1610 (char *)(ciconinfo + 1)
1611 + ciconinfo->nHeight *
1612 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1613 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1614 1, 1, (char *)(ciconinfo + 1));
1616 GlobalUnlock16(hIcon);
1618 return TRUE;
1621 /**********************************************************************
1622 * CreateIconIndirect (USER32.78)
1624 HICON WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1625 BITMAPOBJ *bmpXor,*bmpAnd;
1626 HICON hObj;
1627 int sizeXor,sizeAnd;
1629 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1630 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1632 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1633 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1635 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1636 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1637 if (hObj)
1639 CURSORICONINFO *info;
1641 info = (CURSORICONINFO *)GlobalLock16( hObj );
1642 info->ptHotSpot.x = iconinfo->xHotspot;
1643 info->ptHotSpot.y = iconinfo->yHotspot;
1644 info->nWidth = bmpXor->bitmap.bmWidth;
1645 info->nHeight = bmpXor->bitmap.bmHeight;
1646 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1647 info->bPlanes = bmpXor->bitmap.bmPlanes;
1648 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1650 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1652 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1653 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1654 GlobalUnlock16( hObj );
1656 return hObj;
1660 /**********************************************************************
1662 DrawIconEx16 (USER.394)
1664 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1665 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1666 HBRUSH16 hbr, UINT16 flags)
1668 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1669 istep, hbr, flags);
1673 /******************************************************************************
1674 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1676 * NOTES
1677 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1679 * PARAMS
1680 * hdc [I] Handle to device context
1681 * x0 [I] X coordinate of upper left corner
1682 * y0 [I] Y coordinate of upper left corner
1683 * hIcon [I] Handle to icon to draw
1684 * cxWidth [I] Width of icon
1685 * cyWidth [I] Height of icon
1686 * istep [I] Index of frame in animated cursor
1687 * hbr [I] Handle to background brush
1688 * flags [I] Icon-drawing flags
1690 * RETURNS
1691 * Success: TRUE
1692 * Failure: FALSE
1694 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1695 INT cxWidth, INT cyWidth, UINT istep,
1696 HBRUSH hbr, UINT flags )
1698 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1699 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1700 BOOL result = FALSE, DoOffscreen = FALSE;
1701 HBITMAP hB_off = 0, hOld = 0;
1703 if (!ptr) return FALSE;
1705 if (istep)
1706 FIXME(icon, "Ignoring istep=%d\n", istep);
1707 if (flags & DI_COMPAT)
1708 FIXME(icon, "Ignoring flag DI_COMPAT\n");
1710 /* Calculate the size of the destination image. */
1711 if (cxWidth == 0)
1713 if (flags & DI_DEFAULTSIZE)
1714 cxWidth = GetSystemMetrics (SM_CXICON);
1715 else
1716 cxWidth = ptr->nWidth;
1718 if (cyWidth == 0)
1720 if (flags & DI_DEFAULTSIZE)
1721 cyWidth = GetSystemMetrics (SM_CYICON);
1722 else
1723 cyWidth = ptr->nHeight;
1726 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1727 STOCK_HOLLOW_BRUSH)))
1729 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1730 if (object)
1732 UINT16 magic = object->wMagic;
1733 GDI_HEAP_UNLOCK(hbr);
1734 DoOffscreen = magic == BRUSH_MAGIC;
1737 if (DoOffscreen) {
1738 RECT r = {0, 0, cxWidth, cxWidth};
1740 hDC_off = CreateCompatibleDC(hdc);
1741 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1742 if (hDC_off && hB_off) {
1743 hOld = SelectObject(hDC_off, hB_off);
1744 FillRect(hDC_off, &r, hbr);
1748 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1750 HBITMAP hXorBits, hAndBits;
1751 COLORREF oldFg, oldBg;
1752 INT nStretchMode;
1754 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1756 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1757 ptr->bPlanes, ptr->bBitsPerPixel,
1758 (char *)(ptr + 1)
1759 + ptr->nHeight *
1760 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1761 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1762 1, 1, (char *)(ptr+1) );
1763 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1764 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1766 if (hXorBits && hAndBits)
1768 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1769 if (flags & DI_MASK)
1771 if (DoOffscreen)
1772 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1773 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1774 else
1775 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1776 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1778 SelectObject( hMemDC, hXorBits );
1779 if (flags & DI_IMAGE)
1781 if (DoOffscreen)
1782 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1783 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1784 else
1785 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1786 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1788 SelectObject( hMemDC, hBitTemp );
1789 result = TRUE;
1792 SetTextColor( hdc, oldFg );
1793 SetBkColor( hdc, oldBg );
1794 if (hXorBits) DeleteObject( hXorBits );
1795 if (hAndBits) DeleteObject( hAndBits );
1796 SetStretchBltMode (hdc, nStretchMode);
1797 if (DoOffscreen) {
1798 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
1799 SelectObject(hDC_off, hOld);
1802 if (hMemDC) DeleteDC( hMemDC );
1803 if (hDC_off) DeleteDC(hDC_off);
1804 if (hB_off) DeleteObject(hB_off);
1805 GlobalUnlock16( hIcon );
1806 return result;