Added RtlUnwind in ntdll, and made kernel32 spec entry a forward to
[wine/multimedia.git] / objects / cursoricon.c
blob0289c409d3b2d523ecbcad21a862c4bad4d913b6
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>
35 #include "wine/winbase16.h"
36 #include "wine/winuser16.h"
37 #include "heap.h"
38 #include "color.h"
39 #include "bitmap.h"
40 #include "cursoricon.h"
41 #include "dc.h"
42 #include "gdi.h"
43 #include "sysmetrics.h"
44 #include "global.h"
45 #include "module.h"
46 #include "debugtools.h"
47 #include "task.h"
48 #include "user.h"
49 #include "input.h"
50 #include "display.h"
51 #include "message.h"
52 #include "winerror.h"
54 DECLARE_DEBUG_CHANNEL(cursor)
55 DECLARE_DEBUG_CHANNEL(icon)
57 static HCURSOR hActiveCursor = 0; /* Active cursor */
58 static INT CURSOR_ShowCount = 0; /* Cursor display count */
59 static RECT CURSOR_ClipRect; /* Cursor clipping rect */
62 /**********************************************************************
63 * ICONCACHE for cursors/icons loaded with LR_SHARED.
65 * FIXME: This should not be allocated on the system heap, but on a
66 * subsystem-global heap (i.e. one for all Win16 processes,
67 * and one each for every Win32 process).
69 typedef struct tagICONCACHE
71 struct tagICONCACHE *next;
73 HMODULE hModule;
74 HRSRC hRsrc;
75 HANDLE handle;
77 INT count;
79 } ICONCACHE;
81 static ICONCACHE *IconAnchor = NULL;
82 static CRITICAL_SECTION IconCrst;
84 /**********************************************************************
85 * CURSORICON_Init
87 void CURSORICON_Init( void )
89 InitializeCriticalSection( &IconCrst );
90 MakeCriticalSectionGlobal( &IconCrst );
93 /**********************************************************************
94 * CURSORICON_FindSharedIcon
96 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
98 HANDLE handle = 0;
99 ICONCACHE *ptr;
101 EnterCriticalSection( &IconCrst );
103 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
104 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
106 ptr->count++;
107 handle = ptr->handle;
108 break;
111 LeaveCriticalSection( &IconCrst );
113 return handle;
116 /**********************************************************************
117 * CURSORICON_AddSharedIcon
119 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HANDLE handle )
121 ICONCACHE *ptr = HeapAlloc( SystemHeap, 0, sizeof(ICONCACHE) );
122 if ( !ptr ) return;
124 ptr->hModule = hModule;
125 ptr->hRsrc = hRsrc;
126 ptr->handle = handle;
127 ptr->count = 1;
129 EnterCriticalSection( &IconCrst );
130 ptr->next = IconAnchor;
131 IconAnchor = ptr;
132 LeaveCriticalSection( &IconCrst );
135 /**********************************************************************
136 * CURSORICON_DelSharedIcon
138 static INT CURSORICON_DelSharedIcon( HANDLE handle )
140 INT count = -1;
141 ICONCACHE *ptr;
143 EnterCriticalSection( &IconCrst );
145 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
146 if ( ptr->handle == handle )
148 if ( ptr->count > 0 ) ptr->count--;
149 count = ptr->count;
150 break;
153 LeaveCriticalSection( &IconCrst );
155 return count;
158 /**********************************************************************
159 * CURSORICON_FreeModuleIcons
161 void CURSORICON_FreeModuleIcons( HMODULE hModule )
163 ICONCACHE **ptr = &IconAnchor;
165 if ( HIWORD( hModule ) )
166 hModule = MapHModuleLS( hModule );
167 else
168 hModule = GetExePtr( hModule );
170 EnterCriticalSection( &IconCrst );
172 while ( *ptr )
174 if ( (*ptr)->hModule == hModule )
176 ICONCACHE *freePtr = *ptr;
177 *ptr = freePtr->next;
179 GlobalFree16( freePtr->handle );
180 HeapFree( SystemHeap, 0, freePtr );
181 continue;
183 ptr = &(*ptr)->next;
186 LeaveCriticalSection( &IconCrst );
189 /**********************************************************************
190 * CURSORICON_FindBestIcon
192 * Find the icon closest to the requested size and number of colors.
194 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
195 int height, int colors )
197 int i, maxcolors, maxwidth, maxheight;
198 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
200 if (dir->idCount < 1)
202 WARN_(icon)("Empty directory!\n" );
203 return NULL;
205 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
207 /* First find the exact size with less colors */
209 maxcolors = 0;
210 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
211 if ((entry->ResInfo.icon.bWidth == width) && (entry->ResInfo.icon.bHeight == height) &&
212 (entry->ResInfo.icon.bColorCount <= colors) && (entry->ResInfo.icon.bColorCount > maxcolors))
214 bestEntry = entry;
215 maxcolors = entry->ResInfo.icon.bColorCount;
217 if (bestEntry) return bestEntry;
219 /* First find the exact size with more colors */
221 maxcolors = 255;
222 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
223 if ((entry->ResInfo.icon.bWidth == width) && (entry->ResInfo.icon.bHeight == height) &&
224 (entry->ResInfo.icon.bColorCount > colors) && (entry->ResInfo.icon.bColorCount <= maxcolors))
226 bestEntry = entry;
227 maxcolors = entry->ResInfo.icon.bColorCount;
229 if (bestEntry) return bestEntry;
231 /* Now find a smaller one with less colors */
233 maxcolors = maxwidth = maxheight = 0;
234 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
235 if ((entry->ResInfo.icon.bWidth <= width) && (entry->ResInfo.icon.bHeight <= height) &&
236 (entry->ResInfo.icon.bWidth >= maxwidth) && (entry->ResInfo.icon.bHeight >= maxheight) &&
237 (entry->ResInfo.icon.bColorCount <= colors) && (entry->ResInfo.icon.bColorCount > maxcolors))
239 bestEntry = entry;
240 maxwidth = entry->ResInfo.icon.bWidth;
241 maxheight = entry->ResInfo.icon.bHeight;
242 maxcolors = entry->ResInfo.icon.bColorCount;
244 if (bestEntry) return bestEntry;
246 /* Now find a smaller one with more colors */
248 maxcolors = 255;
249 maxwidth = maxheight = 0;
250 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
251 if ((entry->ResInfo.icon.bWidth <= width) && (entry->ResInfo.icon.bHeight <= height) &&
252 (entry->ResInfo.icon.bWidth >= maxwidth) && (entry->ResInfo.icon.bHeight >= maxheight) &&
253 (entry->ResInfo.icon.bColorCount > colors) && (entry->ResInfo.icon.bColorCount <= maxcolors))
255 bestEntry = entry;
256 maxwidth = entry->ResInfo.icon.bWidth;
257 maxheight = entry->ResInfo.icon.bHeight;
258 maxcolors = entry->ResInfo.icon.bColorCount;
260 if (bestEntry) return bestEntry;
262 /* Now find a larger one with less colors */
264 maxcolors = 0;
265 maxwidth = maxheight = 255;
266 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
267 if ((entry->ResInfo.icon.bWidth <= maxwidth) && (entry->ResInfo.icon.bHeight <= maxheight) &&
268 (entry->ResInfo.icon.bColorCount <= colors) && (entry->ResInfo.icon.bColorCount > maxcolors))
270 bestEntry = entry;
271 maxwidth = entry->ResInfo.icon.bWidth;
272 maxheight = entry->ResInfo.icon.bHeight;
273 maxcolors = entry->ResInfo.icon.bColorCount;
275 if (bestEntry) return bestEntry;
277 /* Now find a larger one with more colors */
279 maxcolors = maxwidth = maxheight = 255;
280 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
281 if ((entry->ResInfo.icon.bWidth <= maxwidth) && (entry->ResInfo.icon.bHeight <= maxheight) &&
282 (entry->ResInfo.icon.bColorCount > colors) && (entry->ResInfo.icon.bColorCount <= maxcolors))
284 bestEntry = entry;
285 maxwidth = entry->ResInfo.icon.bWidth;
286 maxheight = entry->ResInfo.icon.bHeight;
287 maxcolors = entry->ResInfo.icon.bColorCount;
290 return bestEntry;
294 /**********************************************************************
295 * CURSORICON_FindBestCursor
297 * Find the cursor closest to the requested size.
298 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
299 * ignored too
301 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
302 int width, int height, int color)
304 int i, maxwidth, maxheight;
305 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
307 if (dir->idCount < 1)
309 WARN_(cursor)("Empty directory!\n" );
310 return NULL;
312 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
314 /* First find the largest one smaller than or equal to the requested size*/
316 maxwidth = maxheight = 0;
317 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
318 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
319 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
320 (entry->wBitCount == 1))
322 bestEntry = entry;
323 maxwidth = entry->ResInfo.cursor.wWidth;
324 maxheight = entry->ResInfo.cursor.wHeight;
326 if (bestEntry) return bestEntry;
328 /* Now find the smallest one larger than the requested size */
330 maxwidth = maxheight = 255;
331 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
332 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
333 (entry->wBitCount == 1))
335 bestEntry = entry;
336 maxwidth = entry->ResInfo.cursor.wWidth;
337 maxheight = entry->ResInfo.cursor.wHeight;
340 return bestEntry;
343 /*********************************************************************
344 * The main purpose of this function is to create fake resource directory
345 * and fake resource entries. There are several reasons for this:
346 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
347 * fields
348 * There are some "bad" cursor files which do not have
349 * bColorCount initialized but instead one must read this info
350 * directly from corresponding DIB sections
351 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
353 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
354 CURSORICONDIR **res, LPBYTE **ptr)
356 LPBYTE _free;
357 CURSORICONFILEDIR *bits;
358 int entries, size, i;
360 *res = NULL;
361 *ptr = NULL;
362 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
364 /* FIXME: test for inimated icons
365 * hack to load the first icon from the *.ani file
367 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
368 { LPBYTE pos = (LPBYTE) bits;
369 FIXME_(cursor)("Animated icons not correctly implemented! %p \n", bits);
371 for (;;)
372 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
373 { FIXME_(cursor)("icon entry found! %p\n", bits);
374 pos+=4;
375 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
376 { goto fail;
378 bits+=2;
379 FIXME_(cursor)("icon size ok %p \n", bits);
380 break;
382 pos+=2;
383 if (pos>=(LPBYTE)bits+766) goto fail;
386 if (!(entries = bits->idCount)) goto fail;
387 size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) * (entries - 1);
388 _free = (LPBYTE) size;
390 for (i=0; i < entries; i++)
391 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
393 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
394 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
395 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
397 _free = (LPBYTE)(*res) + (int)_free;
398 memcpy((*res), bits, 6);
399 for (i=0; i<entries; i++)
401 ((LPBYTE*)(*ptr))[i] = _free;
402 if (fCursor) {
403 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
404 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
405 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
406 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
407 _free+=sizeof(POINT16);
408 } else {
409 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
410 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
411 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
413 (*res)->idEntries[i].wPlanes=1;
414 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
415 bits->idEntries[i].dwDIBOffset))->biBitCount;
416 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
417 (*res)->idEntries[i].wResId=i+1;
419 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
420 (*res)->idEntries[i].dwBytesInRes);
421 _free += (*res)->idEntries[i].dwBytesInRes;
423 UnmapViewOfFile( bits );
424 return TRUE;
425 fail:
426 if (*res) HeapFree( GetProcessHeap(), 0, *res );
427 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
428 UnmapViewOfFile( bits );
429 return FALSE;
433 /**********************************************************************
434 * CURSORICON_CreateFromResource
436 * Create a cursor or icon from in-memory resource template.
438 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
439 * with cbSize parameter as well.
441 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
442 UINT cbSize, BOOL bIcon, DWORD dwVersion,
443 INT width, INT height, UINT loadflags )
445 int sizeAnd, sizeXor;
446 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
447 BITMAPOBJ *bmpXor, *bmpAnd;
448 POINT16 hotspot = { 0 ,0 };
449 BITMAPINFO *bmi;
450 HDC hdc;
451 BOOL DoStretch;
452 INT size;
454 TRACE_(cursor)("%08x (%u bytes), ver %08x, %ix%i %s %s\n",
455 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
456 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
457 if (dwVersion == 0x00020000)
459 FIXME_(cursor)("\t2.xx resources are not supported\n");
460 return 0;
463 if (bIcon)
464 bmi = (BITMAPINFO *)bits;
465 else /* get the hotspot */
467 POINT16 *pt = (POINT16 *)bits;
468 hotspot = *pt;
469 bmi = (BITMAPINFO *)(pt + 1);
471 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
473 if (!width) width = bmi->bmiHeader.biWidth;
474 if (!height) height = bmi->bmiHeader.biHeight/2;
475 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
476 (bmi->bmiHeader.biWidth != width);
478 /* Check bitmap header */
480 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
481 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
482 bmi->bmiHeader.biCompression != BI_RGB) )
484 WARN_(cursor)("\tinvalid resource bitmap header.\n");
485 return 0;
488 if( (hdc = GetDC( 0 )) )
490 BITMAPINFO* pInfo;
492 /* Make sure we have room for the monochrome bitmap later on.
493 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
494 * up to and including the biBitCount. In-memory icon resource
495 * format is as follows:
497 * BITMAPINFOHEADER icHeader // DIB header
498 * RGBQUAD icColors[] // Color table
499 * BYTE icXOR[] // DIB bits for XOR mask
500 * BYTE icAND[] // DIB bits for AND mask
503 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
504 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
506 memcpy( pInfo, bmi, size );
507 pInfo->bmiHeader.biHeight /= 2;
509 /* Create the XOR bitmap */
511 if (DoStretch) {
512 if ((hXorBits = CreateCompatibleBitmap(hdc, width, height))) {
513 HBITMAP hOld;
514 HDC hMem = CreateCompatibleDC(hdc);
515 BOOL res;
517 if (hMem) {
518 hOld = SelectObject(hMem, hXorBits);
519 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
520 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
521 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
522 SelectObject(hMem, hOld);
523 DeleteDC(hMem);
524 } else res = FALSE;
525 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
527 } else hXorBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
528 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
529 if( hXorBits )
531 char* bits = (char *)bmi + size +
532 DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
533 bmi->bmiHeader.biHeight,
534 bmi->bmiHeader.biBitCount) / 2;
536 pInfo->bmiHeader.biBitCount = 1;
537 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
539 RGBQUAD *rgb = pInfo->bmiColors;
541 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
542 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
543 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
544 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
546 else
548 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
550 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
551 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
554 /* Create the AND bitmap */
556 if (DoStretch) {
557 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
558 HBITMAP hOld;
559 HDC hMem = CreateCompatibleDC(hdc);
560 BOOL res;
562 if (hMem) {
563 hOld = SelectObject(hMem, hAndBits);
564 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
565 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
566 bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
567 SelectObject(hMem, hOld);
568 DeleteDC(hMem);
569 } else res = FALSE;
570 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
572 } else hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
573 CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
575 if( !hAndBits ) DeleteObject( hXorBits );
577 HeapFree( GetProcessHeap(), 0, pInfo );
579 ReleaseDC( 0, hdc );
582 if( !hXorBits || !hAndBits )
584 WARN_(cursor)("\tunable to create an icon bitmap.\n");
585 return 0;
588 /* Now create the CURSORICONINFO structure */
589 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
590 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
591 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
592 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
594 if (hObj) hObj = GlobalReAlloc16( hObj,
595 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
596 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
597 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
598 if (hObj)
600 CURSORICONINFO *info;
602 /* Make it owned by the module */
603 if (hInstance) FarSetOwner16( hObj, GetExePtr(hInstance) );
605 info = (CURSORICONINFO *)GlobalLock16( hObj );
606 info->ptHotSpot.x = hotspot.x;
607 info->ptHotSpot.y = hotspot.y;
608 info->nWidth = bmpXor->bitmap.bmWidth;
609 info->nHeight = bmpXor->bitmap.bmHeight;
610 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
611 info->bPlanes = bmpXor->bitmap.bmPlanes;
612 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
614 /* Transfer the bitmap bits to the CURSORICONINFO structure */
616 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
617 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
618 GlobalUnlock16( hObj );
621 DeleteObject( hXorBits );
622 DeleteObject( hAndBits );
623 return hObj;
627 /**********************************************************************
628 * CreateIconFromResourceEx16 (USER.450)
630 * FIXME: not sure about exact parameter types
632 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
633 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
635 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
636 width, height, cFlag);
640 /**********************************************************************
641 * CreateIconFromResource (USER32.76)
643 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
644 BOOL bIcon, DWORD dwVersion)
646 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
650 /**********************************************************************
651 * CreateIconFromResourceEx32 (USER32.77)
653 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
654 BOOL bIcon, DWORD dwVersion,
655 INT width, INT height,
656 UINT cFlag )
658 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
659 if( pTask )
660 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
661 width, height, cFlag );
662 return 0;
665 /**********************************************************************
666 * CURSORICON_Load
668 * Load a cursor or icon from resource or file.
670 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
671 INT width, INT height, INT colors,
672 BOOL fCursor, UINT loadflags )
674 HANDLE handle = 0, h = 0;
675 HANDLE hRsrc;
676 CURSORICONDIR *dir;
677 CURSORICONDIRENTRY *dirEntry;
678 LPBYTE bits;
680 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
682 LPBYTE *ptr;
683 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
684 return 0;
685 if (fCursor)
686 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
687 else
688 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
689 bits = ptr[dirEntry->wResId-1];
690 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
691 !fCursor, 0x00030000, width, height, loadflags);
692 HeapFree( GetProcessHeap(), 0, dir );
693 HeapFree( GetProcessHeap(), 0, ptr );
696 else if ( !hInstance ) /* Load OEM cursor/icon */
698 WORD resid;
699 HDC hdc;
700 DC *dc;
702 if ( HIWORD(name) )
704 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
705 if( ansi[0]=='#') /*Check for '#xxx' name */
707 resid = atoi(ansi+1);
708 HeapFree( GetProcessHeap(), 0, ansi );
710 else
712 HeapFree( GetProcessHeap(), 0, ansi );
713 return 0;
716 else resid = LOWORD(name);
717 hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
718 dc = DC_GetDCPtr( hdc );
719 if (dc->funcs->pLoadOEMResource)
720 h = dc->funcs->pLoadOEMResource( resid, fCursor ?
721 OEM_CURSOR : OEM_ICON );
722 GDI_HEAP_UNLOCK( hdc );
723 DeleteDC( hdc );
726 else /* Load from resource */
728 WORD wResId;
729 DWORD dwBytesInRes;
731 /* Normalize hInstance (must be uniquely represented for icon cache) */
733 if ( HIWORD( hInstance ) )
734 hInstance = MapHModuleLS( hInstance );
735 else
736 hInstance = GetExePtr( hInstance );
738 /* Get directory resource ID */
740 if (!(hRsrc = FindResourceW( hInstance, name,
741 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
742 return 0;
744 /* If shared icon, check whether it was already loaded */
746 if ( (loadflags & LR_SHARED)
747 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
748 return h;
750 /* Find the best entry in the directory */
752 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
753 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
754 if (fCursor)
755 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
756 width, height, 1);
757 else
758 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
759 width, height, colors );
760 if (!dirEntry) return 0;
761 wResId = dirEntry->wResId;
762 dwBytesInRes = dirEntry->dwBytesInRes;
763 FreeResource( handle );
765 /* Load the resource */
767 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
768 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
769 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
770 bits = (LPBYTE)LockResource( handle );
771 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
772 !fCursor, 0x00030000, width, height, loadflags);
773 FreeResource( handle );
775 /* If shared icon, add to icon cache */
777 if ( h && (loadflags & LR_SHARED) )
778 CURSORICON_AddSharedIcon( hInstance, hRsrc, h );
781 return h;
784 /***********************************************************************
785 * CURSORICON_Copy
787 * Make a copy of a cursor or icon.
789 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
791 char *ptrOld, *ptrNew;
792 int size;
793 HGLOBAL16 hNew;
795 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
796 if (!(hInstance = GetExePtr( hInstance ))) return 0;
797 size = GlobalSize16( handle );
798 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
799 FarSetOwner16( hNew, hInstance );
800 ptrNew = (char *)GlobalLock16( hNew );
801 memcpy( ptrNew, ptrOld, size );
802 GlobalUnlock16( handle );
803 GlobalUnlock16( hNew );
804 return hNew;
807 /***********************************************************************
808 * CURSORICON_IconToCursor
810 * Converts bitmap to mono and truncates if icon is too large (should
811 * probably do StretchBlt() instead).
813 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
815 HCURSOR16 hRet = 0;
816 CURSORICONINFO *pIcon = NULL;
817 HTASK16 hTask = GetCurrentTask();
818 TDB* pTask = (TDB *)GlobalLock16(hTask);
820 if(hIcon && pTask)
821 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
822 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
823 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
824 else
826 BYTE pAndBits[128];
827 BYTE pXorBits[128];
828 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
829 BYTE* psPtr, *pxbPtr = pXorBits;
830 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
831 BYTE* pbc = NULL;
833 CURSORICONINFO cI;
835 TRACE_(icon)("[%04x] %ix%i %ibpp (bogus %ibps)\n",
836 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
838 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
839 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
840 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
842 memset(pXorBits, 0, 128);
843 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
844 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
845 cI.nWidth = 32; cI.nHeight = 32;
846 cI.nWidthBytes = 4; /* 32x1bpp */
848 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
849 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
851 for( iy = 0; iy < maxy; iy++ )
853 unsigned shift = iy % 2;
855 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
856 (and_width > 4) ? 4 : and_width );
857 for( ix = 0; ix < maxx; ix++ )
859 if( bSemiTransparent && ((ix+shift)%2) )
861 /* set AND bit, XOR bit stays 0 */
863 pbc = pAndBits + iy * 4 + ix/8;
864 *pbc |= 0x80 >> (ix%8);
866 else
868 /* keep AND bit, set XOR bit */
870 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
871 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
872 if(!PALETTE_Driver->pIsDark(val))
874 pbc = pxbPtr + ix/8;
875 *pbc |= 0x80 >> (ix%8);
879 psPtr += xor_width;
880 pxbPtr += 4;
883 hRet = CreateCursorIconIndirect16( pTask->hInstance , &cI, pAndBits, pXorBits);
885 if( !hRet ) /* fall back on default drag cursor */
886 hRet = CURSORICON_Copy( pTask->hInstance ,
887 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
888 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0) );
891 return hRet;
895 /***********************************************************************
896 * LoadCursor16 (USER.173)
898 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
900 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
901 return LoadCursorA( hInstance, nameStr );
905 /***********************************************************************
906 * LoadIcon16 (USER.174)
908 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
910 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
911 return LoadIconA( hInstance, nameStr );
915 /***********************************************************************
916 * CreateCursor16 (USER.406)
918 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
919 INT16 xHotSpot, INT16 yHotSpot,
920 INT16 nWidth, INT16 nHeight,
921 LPCVOID lpANDbits, LPCVOID lpXORbits )
923 CURSORICONINFO info;
925 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
926 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
928 info.ptHotSpot.x = xHotSpot;
929 info.ptHotSpot.y = yHotSpot;
930 info.nWidth = nWidth;
931 info.nHeight = nHeight;
932 info.nWidthBytes = 0;
933 info.bPlanes = 1;
934 info.bBitsPerPixel = 1;
936 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
940 /***********************************************************************
941 * CreateCursor32 (USER32.67)
943 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
944 INT xHotSpot, INT yHotSpot,
945 INT nWidth, INT nHeight,
946 LPCVOID lpANDbits, LPCVOID lpXORbits )
948 CURSORICONINFO info;
950 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
951 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
953 info.ptHotSpot.x = xHotSpot;
954 info.ptHotSpot.y = yHotSpot;
955 info.nWidth = nWidth;
956 info.nHeight = nHeight;
957 info.nWidthBytes = 0;
958 info.bPlanes = 1;
959 info.bBitsPerPixel = 1;
961 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
965 /***********************************************************************
966 * CreateIcon16 (USER.407)
968 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
969 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
970 LPCVOID lpANDbits, LPCVOID lpXORbits )
972 CURSORICONINFO info;
974 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
975 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
977 info.ptHotSpot.x = 0;
978 info.ptHotSpot.y = 0;
979 info.nWidth = nWidth;
980 info.nHeight = nHeight;
981 info.nWidthBytes = 0;
982 info.bPlanes = bPlanes;
983 info.bBitsPerPixel = bBitsPixel;
985 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
989 /***********************************************************************
990 * CreateIcon32 (USER32.75)
992 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
993 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
994 LPCVOID lpANDbits, LPCVOID lpXORbits )
996 CURSORICONINFO info;
998 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
999 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1001 info.ptHotSpot.x = 0;
1002 info.ptHotSpot.y = 0;
1003 info.nWidth = nWidth;
1004 info.nHeight = nHeight;
1005 info.nWidthBytes = 0;
1006 info.bPlanes = bPlanes;
1007 info.bBitsPerPixel = bBitsPixel;
1009 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1013 /***********************************************************************
1014 * CreateCursorIconIndirect (USER.408)
1016 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
1017 CURSORICONINFO *info,
1018 LPCVOID lpANDbits,
1019 LPCVOID lpXORbits )
1021 HGLOBAL16 handle;
1022 char *ptr;
1023 int sizeAnd, sizeXor;
1025 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
1026 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
1027 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
1028 sizeXor = info->nHeight * info->nWidthBytes;
1029 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1030 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
1031 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1032 return 0;
1033 if (hInstance) FarSetOwner16( handle, hInstance );
1034 ptr = (char *)GlobalLock16( handle );
1035 memcpy( ptr, info, sizeof(*info) );
1036 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1037 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1038 GlobalUnlock16( handle );
1039 return handle;
1043 /***********************************************************************
1044 * CopyIcon16 (USER.368)
1046 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1048 TRACE_(icon)("%04x %04x\n", hInstance, hIcon );
1049 return CURSORICON_Copy( hInstance, hIcon );
1053 /***********************************************************************
1054 * CopyIcon32 (USER32.60)
1056 HICON WINAPI CopyIcon( HICON hIcon )
1058 HTASK16 hTask = GetCurrentTask ();
1059 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1060 TRACE_(icon)("%04x\n", hIcon );
1061 return CURSORICON_Copy( pTask->hInstance, hIcon );
1065 /***********************************************************************
1066 * CopyCursor16 (USER.369)
1068 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1070 TRACE_(cursor)("%04x %04x\n", hInstance, hCursor );
1071 return CURSORICON_Copy( hInstance, hCursor );
1074 /**********************************************************************
1075 * CURSORICON_Destroy (USER.610)
1077 * This routine is actually exported from Win95 USER under the name
1078 * DestroyIcon32 ... The behaviour implemented here should mimic
1079 * the Win95 one exactly, especially the return values, which
1080 * depend on the setting of various flags.
1082 WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1084 WORD retv;
1086 TRACE_(icon)("(%04x, %04x)\n", handle, flags );
1088 /* Check whether destroying active cursor */
1090 if ( hActiveCursor == handle )
1092 ERR_(cursor)("Destroying active cursor!\n" );
1093 SetCursor( 0 );
1096 /* Try shared cursor/icon first */
1098 if ( !(flags & CID_NONSHARED) )
1100 INT count = CURSORICON_DelSharedIcon( handle );
1102 if ( count != -1 )
1103 return (flags & CID_WIN32)? TRUE : (count == 0);
1105 /* FIXME: OEM cursors/icons should be recognized */
1108 /* Now assume non-shared cursor/icon */
1110 retv = GlobalFree16( handle );
1111 return (flags & CID_RESOURCE)? retv : TRUE;
1114 /***********************************************************************
1115 * DestroyIcon16 (USER.457)
1117 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1119 return CURSORICON_Destroy( hIcon, 0 );
1122 /***********************************************************************
1123 * DestroyIcon (USER32.133)
1125 BOOL WINAPI DestroyIcon( HICON hIcon )
1127 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1130 /***********************************************************************
1131 * DestroyCursor16 (USER.458)
1133 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1135 return CURSORICON_Destroy( hCursor, 0 );
1138 /***********************************************************************
1139 * DestroyCursor (USER32.132)
1141 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1143 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1147 /***********************************************************************
1148 * DrawIcon16 (USER.84)
1150 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1152 return DrawIcon( hdc, x, y, hIcon );
1156 /***********************************************************************
1157 * DrawIcon32 (USER32.159)
1159 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1161 CURSORICONINFO *ptr;
1162 HDC hMemDC;
1163 HBITMAP hXorBits, hAndBits;
1164 COLORREF oldFg, oldBg;
1166 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1167 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1168 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1169 (char *)(ptr+1) );
1170 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1171 ptr->bBitsPerPixel, (char *)(ptr + 1)
1172 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1173 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1174 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1176 if (hXorBits && hAndBits)
1178 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1179 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1180 SelectObject( hMemDC, hXorBits );
1181 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1182 SelectObject( hMemDC, hBitTemp );
1184 DeleteDC( hMemDC );
1185 if (hXorBits) DeleteObject( hXorBits );
1186 if (hAndBits) DeleteObject( hAndBits );
1187 GlobalUnlock16( hIcon );
1188 SetTextColor( hdc, oldFg );
1189 SetBkColor( hdc, oldBg );
1190 return TRUE;
1194 /***********************************************************************
1195 * DumpIcon (USER.459)
1197 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1198 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1200 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1201 int sizeAnd, sizeXor;
1203 if (!info) return 0;
1204 sizeXor = info->nHeight * info->nWidthBytes;
1205 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1206 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1207 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1208 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1209 return MAKELONG( sizeXor, sizeXor );
1213 /***********************************************************************
1214 * SetCursor16 (USER.69)
1216 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1218 return (HCURSOR16)SetCursor( hCursor );
1222 /***********************************************************************
1223 * SetCursor32 (USER32.472)
1224 * RETURNS:
1225 * A handle to the previous cursor shape.
1227 HCURSOR WINAPI SetCursor(
1228 HCURSOR hCursor /* Handle of cursor to show */
1230 HCURSOR hOldCursor;
1232 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1233 TRACE_(cursor)("%04x\n", hCursor );
1234 hOldCursor = hActiveCursor;
1235 hActiveCursor = hCursor;
1236 /* Change the cursor shape only if it is visible */
1237 if (CURSOR_ShowCount >= 0)
1239 DISPLAY_SetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1240 GlobalUnlock16( hActiveCursor );
1242 return hOldCursor;
1246 /***********************************************************************
1247 * SetCursorPos16 (USER.70)
1249 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1251 SetCursorPos( x, y );
1255 /***********************************************************************
1256 * SetCursorPos32 (USER32.474)
1258 BOOL WINAPI SetCursorPos( INT x, INT y )
1260 DISPLAY_MoveCursor( x, y );
1261 return TRUE;
1265 /***********************************************************************
1266 * ShowCursor16 (USER.71)
1268 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1270 return ShowCursor( bShow );
1274 /***********************************************************************
1275 * ShowCursor32 (USER32.530)
1277 INT WINAPI ShowCursor( BOOL bShow )
1279 TRACE_(cursor)("%d, count=%d\n",
1280 bShow, CURSOR_ShowCount );
1282 if (bShow)
1284 if (++CURSOR_ShowCount == 0) /* Show it */
1286 DISPLAY_SetCursor((CURSORICONINFO*)GlobalLock16( hActiveCursor ));
1287 GlobalUnlock16( hActiveCursor );
1290 else
1292 if (--CURSOR_ShowCount == -1) /* Hide it */
1293 DISPLAY_SetCursor( NULL );
1295 return CURSOR_ShowCount;
1299 /***********************************************************************
1300 * GetCursor16 (USER.247)
1302 HCURSOR16 WINAPI GetCursor16(void)
1304 return hActiveCursor;
1308 /***********************************************************************
1309 * GetCursor32 (USER32.227)
1311 HCURSOR WINAPI GetCursor(void)
1313 return hActiveCursor;
1317 /***********************************************************************
1318 * ClipCursor16 (USER.16)
1320 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1322 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1323 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1324 return TRUE;
1328 /***********************************************************************
1329 * ClipCursor32 (USER32.53)
1331 BOOL WINAPI ClipCursor( const RECT *rect )
1333 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1334 else CopyRect( &CURSOR_ClipRect, rect );
1335 return TRUE;
1339 /***********************************************************************
1340 * GetCursorPos16 (USER.17)
1342 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
1344 DWORD posX, posY, state;
1346 if (!pt) return 0;
1347 if (!EVENT_QueryPointer( &posX, &posY, &state ))
1348 pt->x = pt->y = 0;
1349 else
1351 pt->x = posX;
1352 pt->y = posY;
1353 if (state & MK_LBUTTON)
1354 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1355 else
1356 MouseButtonsStates[0] = FALSE;
1357 if (state & MK_MBUTTON)
1358 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1359 else
1360 MouseButtonsStates[1] = FALSE;
1361 if (state & MK_RBUTTON)
1362 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1363 else
1364 MouseButtonsStates[2] = FALSE;
1366 TRACE_(cursor)("ret=%d,%d\n", pt->x, pt->y );
1367 return 1;
1371 /***********************************************************************
1372 * GetCursorPos32 (USER32.229)
1374 BOOL WINAPI GetCursorPos( POINT *pt )
1376 BOOL ret;
1378 POINT16 pt16;
1379 ret = GetCursorPos16( &pt16 );
1380 if (pt) CONV_POINT16TO32( &pt16, pt );
1381 return ((pt) ? ret : 0);
1385 /***********************************************************************
1386 * GetClipCursor16 (USER.309)
1388 void WINAPI GetClipCursor16( RECT16 *rect )
1390 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1394 /***********************************************************************
1395 * GetClipCursor32 (USER32.221)
1397 BOOL WINAPI GetClipCursor( RECT *rect )
1399 if (rect)
1401 CopyRect( rect, &CURSOR_ClipRect );
1402 return TRUE;
1404 return FALSE;
1407 /**********************************************************************
1408 * LookupIconIdFromDirectoryEx16 (USER.364)
1410 * FIXME: exact parameter sizes
1412 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1413 INT16 width, INT16 height, UINT16 cFlag )
1415 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1416 UINT16 retVal = 0;
1417 if( dir && !dir->idReserved && (dir->idType & 3) )
1419 CURSORICONDIRENTRY* entry;
1420 HDC hdc;
1421 UINT palEnts;
1422 int colors;
1423 hdc = GetDC(0);
1424 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1425 if (palEnts == 0)
1426 palEnts = 256;
1427 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1429 ReleaseDC(0, hdc);
1431 if( bIcon )
1432 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1433 else
1434 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1436 if( entry ) retVal = entry->wResId;
1438 else WARN_(cursor)("invalid resource directory\n");
1439 return retVal;
1442 /**********************************************************************
1443 * LookupIconIdFromDirectoryEx32 (USER32.380)
1445 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1446 INT width, INT height, UINT cFlag )
1448 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1451 /**********************************************************************
1452 * LookupIconIdFromDirectory (USER.???)
1454 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1456 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1457 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1458 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1461 /**********************************************************************
1462 * LookupIconIdFromDirectory (USER32.379)
1464 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1466 return LookupIconIdFromDirectoryEx( dir, bIcon,
1467 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1468 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1471 /**********************************************************************
1472 * GetIconID (USER.455)
1474 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1476 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1478 TRACE_(cursor)("hRes=%04x, entries=%i\n",
1479 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1481 switch(resType)
1483 case RT_CURSOR16:
1484 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1485 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1486 case RT_ICON16:
1487 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1488 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1489 default:
1490 WARN_(cursor)("invalid res type %ld\n", resType );
1492 return 0;
1495 /**********************************************************************
1496 * LoadCursorIconHandler (USER.336)
1498 * Supposed to load resources of Windows 2.x applications.
1500 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1502 FIXME_(cursor)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1503 hResource, hModule, hRsrc);
1504 return (HGLOBAL16)0;
1507 /**********************************************************************
1508 * LoadDIBIconHandler (USER.357)
1510 * RT_ICON resource loader, installed by USER_SignalProc when module
1511 * is initialized.
1513 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1515 /* If hResource is zero we must allocate a new memory block, if it's
1516 * non-zero but GlobalLock() returns NULL then it was discarded and
1517 * we have to recommit some memory, otherwise we just need to check
1518 * the block size. See LoadProc() in 16-bit SDK for more.
1521 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1522 if( hMemObj )
1524 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1525 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1526 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1527 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1529 return hMemObj;
1532 /**********************************************************************
1533 * LoadDIBCursorHandler (USER.356)
1535 * RT_CURSOR resource loader. Same as above.
1537 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1539 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1540 if( hMemObj )
1542 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1543 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1544 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1545 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1547 return hMemObj;
1550 /**********************************************************************
1551 * LoadIconHandler (USER.456)
1553 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1555 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1557 TRACE_(cursor)("hRes=%04x\n",hResource);
1559 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1560 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1563 /***********************************************************************
1564 * LoadCursorW (USER32.362)
1566 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1568 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1569 LR_SHARED | LR_DEFAULTSIZE );
1572 /***********************************************************************
1573 * LoadCursorA (USER32.359)
1575 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1577 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1578 LR_SHARED | LR_DEFAULTSIZE );
1581 /***********************************************************************
1582 * LoadCursorFromFileW (USER32.361)
1584 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1586 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1587 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1590 /***********************************************************************
1591 * LoadCursorFromFileA (USER32.360)
1593 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1595 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1596 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1599 /***********************************************************************
1600 * LoadIconW (USER32.364)
1602 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1604 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1605 LR_SHARED | LR_DEFAULTSIZE );
1608 /***********************************************************************
1609 * LoadIconA (USER32.363)
1611 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1613 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1614 LR_SHARED | LR_DEFAULTSIZE );
1617 /**********************************************************************
1618 * GetIconInfo16 (USER.395)
1620 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1622 ICONINFO ii32;
1623 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1625 iconinfo->fIcon = ii32.fIcon;
1626 iconinfo->xHotspot = ii32.xHotspot;
1627 iconinfo->yHotspot = ii32.yHotspot;
1628 iconinfo->hbmMask = ii32.hbmMask;
1629 iconinfo->hbmColor = ii32.hbmColor;
1630 return ret;
1633 /**********************************************************************
1634 * GetIconInfo32 (USER32.242)
1636 BOOL WINAPI GetIconInfo(HICON hIcon,LPICONINFO iconinfo) {
1637 CURSORICONINFO *ciconinfo;
1639 ciconinfo = GlobalLock16(hIcon);
1640 if (!ciconinfo)
1641 return FALSE;
1642 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1643 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1644 iconinfo->fIcon = TRUE; /* hmm */
1646 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1647 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1648 (char *)(ciconinfo + 1)
1649 + ciconinfo->nHeight *
1650 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1651 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1652 1, 1, (char *)(ciconinfo + 1));
1654 GlobalUnlock16(hIcon);
1656 return TRUE;
1659 /**********************************************************************
1660 * CreateIconIndirect (USER32.78)
1662 HICON WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1663 BITMAPOBJ *bmpXor,*bmpAnd;
1664 HICON hObj;
1665 int sizeXor,sizeAnd;
1667 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1668 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1670 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1671 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1673 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1674 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1675 if (hObj)
1677 CURSORICONINFO *info;
1679 info = (CURSORICONINFO *)GlobalLock16( hObj );
1680 info->ptHotSpot.x = iconinfo->xHotspot;
1681 info->ptHotSpot.y = iconinfo->yHotspot;
1682 info->nWidth = bmpXor->bitmap.bmWidth;
1683 info->nHeight = bmpXor->bitmap.bmHeight;
1684 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1685 info->bPlanes = bmpXor->bitmap.bmPlanes;
1686 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1688 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1690 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1691 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1692 GlobalUnlock16( hObj );
1694 return hObj;
1698 /**********************************************************************
1700 DrawIconEx16 (USER.394)
1702 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1703 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1704 HBRUSH16 hbr, UINT16 flags)
1706 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1707 istep, hbr, flags);
1711 /******************************************************************************
1712 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1714 * NOTES
1715 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1717 * PARAMS
1718 * hdc [I] Handle to device context
1719 * x0 [I] X coordinate of upper left corner
1720 * y0 [I] Y coordinate of upper left corner
1721 * hIcon [I] Handle to icon to draw
1722 * cxWidth [I] Width of icon
1723 * cyWidth [I] Height of icon
1724 * istep [I] Index of frame in animated cursor
1725 * hbr [I] Handle to background brush
1726 * flags [I] Icon-drawing flags
1728 * RETURNS
1729 * Success: TRUE
1730 * Failure: FALSE
1732 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1733 INT cxWidth, INT cyWidth, UINT istep,
1734 HBRUSH hbr, UINT flags )
1736 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1737 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1738 BOOL result = FALSE, DoOffscreen = FALSE;
1739 HBITMAP hB_off = 0, hOld = 0;
1741 if (!ptr) return FALSE;
1743 if (istep)
1744 FIXME_(icon)("Ignoring istep=%d\n", istep);
1745 if (flags & DI_COMPAT)
1746 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
1748 /* Calculate the size of the destination image. */
1749 if (cxWidth == 0)
1751 if (flags & DI_DEFAULTSIZE)
1752 cxWidth = GetSystemMetrics (SM_CXICON);
1753 else
1754 cxWidth = ptr->nWidth;
1756 if (cyWidth == 0)
1758 if (flags & DI_DEFAULTSIZE)
1759 cyWidth = GetSystemMetrics (SM_CYICON);
1760 else
1761 cyWidth = ptr->nHeight;
1764 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1765 STOCK_HOLLOW_BRUSH)))
1767 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1768 if (object)
1770 UINT16 magic = object->wMagic;
1771 GDI_HEAP_UNLOCK(hbr);
1772 DoOffscreen = magic == BRUSH_MAGIC;
1775 if (DoOffscreen) {
1776 RECT r;
1778 r.left = 0;
1779 r.top = 0;
1780 r.right = cxWidth;
1781 r.bottom = cxWidth;
1783 hDC_off = CreateCompatibleDC(hdc);
1784 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1785 if (hDC_off && hB_off) {
1786 hOld = SelectObject(hDC_off, hB_off);
1787 FillRect(hDC_off, &r, hbr);
1791 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1793 HBITMAP hXorBits, hAndBits;
1794 COLORREF oldFg, oldBg;
1795 INT nStretchMode;
1797 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1799 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1800 ptr->bPlanes, ptr->bBitsPerPixel,
1801 (char *)(ptr + 1)
1802 + ptr->nHeight *
1803 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1804 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1805 1, 1, (char *)(ptr+1) );
1806 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1807 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1809 if (hXorBits && hAndBits)
1811 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1812 if (flags & DI_MASK)
1814 if (DoOffscreen)
1815 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1816 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1817 else
1818 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1819 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1821 SelectObject( hMemDC, hXorBits );
1822 if (flags & DI_IMAGE)
1824 if (DoOffscreen)
1825 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1826 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1827 else
1828 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1829 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1831 SelectObject( hMemDC, hBitTemp );
1832 result = TRUE;
1835 SetTextColor( hdc, oldFg );
1836 SetBkColor( hdc, oldBg );
1837 if (hXorBits) DeleteObject( hXorBits );
1838 if (hAndBits) DeleteObject( hAndBits );
1839 SetStretchBltMode (hdc, nStretchMode);
1840 if (DoOffscreen) {
1841 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
1842 SelectObject(hDC_off, hOld);
1845 if (hMemDC) DeleteDC( hMemDC );
1846 if (hDC_off) DeleteDC(hDC_off);
1847 if (hB_off) DeleteObject(hB_off);
1848 GlobalUnlock16( hIcon );
1849 return result;