Reduced fragment size.
[wine/multimedia.git] / objects / cursoricon.c
blob39d461dc43deaaad14a85948ab18028b472a8afc
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 "debug.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 static HCURSOR hActiveCursor = 0; /* Active cursor */
55 static INT CURSOR_ShowCount = 0; /* Cursor display count */
56 static RECT CURSOR_ClipRect; /* Cursor clipping rect */
59 /**********************************************************************
60 * ICONCACHE for cursors/icons loaded with LR_SHARED.
62 * FIXME: This should not be allocated on the system heap, but on a
63 * subsystem-global heap (i.e. one for all Win16 processes,
64 * and one each for every Win32 process).
66 typedef struct tagICONCACHE
68 struct tagICONCACHE *next;
70 HMODULE hModule;
71 HRSRC hRsrc;
72 HANDLE handle;
74 INT count;
76 } ICONCACHE;
78 static ICONCACHE *IconAnchor = NULL;
79 static CRITICAL_SECTION IconCrst;
81 /**********************************************************************
82 * CURSORICON_Init
84 void CURSORICON_Init( void )
86 InitializeCriticalSection( &IconCrst );
87 MakeCriticalSectionGlobal( &IconCrst );
90 /**********************************************************************
91 * CURSORICON_FindSharedIcon
93 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
95 HANDLE handle = 0;
96 ICONCACHE *ptr;
98 EnterCriticalSection( &IconCrst );
100 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
101 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
103 ptr->count++;
104 handle = ptr->handle;
105 break;
108 LeaveCriticalSection( &IconCrst );
110 return handle;
113 /**********************************************************************
114 * CURSORICON_AddSharedIcon
116 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HANDLE handle )
118 ICONCACHE *ptr = HeapAlloc( SystemHeap, 0, sizeof(ICONCACHE) );
119 if ( !ptr ) return;
121 ptr->hModule = hModule;
122 ptr->hRsrc = hRsrc;
123 ptr->handle = handle;
124 ptr->count = 1;
126 EnterCriticalSection( &IconCrst );
127 ptr->next = IconAnchor;
128 IconAnchor = ptr;
129 LeaveCriticalSection( &IconCrst );
132 /**********************************************************************
133 * CURSORICON_DelSharedIcon
135 static INT CURSORICON_DelSharedIcon( HANDLE handle )
137 INT count = -1;
138 ICONCACHE *ptr;
140 EnterCriticalSection( &IconCrst );
142 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
143 if ( ptr->handle == handle )
145 if ( ptr->count > 0 ) ptr->count--;
146 count = ptr->count;
147 break;
150 LeaveCriticalSection( &IconCrst );
152 return count;
155 /**********************************************************************
156 * CURSORICON_FreeModuleIcons
158 void CURSORICON_FreeModuleIcons( HMODULE hModule )
160 ICONCACHE **ptr = &IconAnchor;
162 if ( HIWORD( hModule ) )
163 hModule = MapHModuleLS( hModule );
164 else
165 hModule = GetExePtr( hModule );
167 EnterCriticalSection( &IconCrst );
169 while ( *ptr )
171 if ( (*ptr)->hModule == hModule )
173 ICONCACHE *freePtr = *ptr;
174 *ptr = freePtr->next;
176 GlobalFree16( freePtr->handle );
177 HeapFree( SystemHeap, 0, freePtr );
178 continue;
180 ptr = &(*ptr)->next;
183 LeaveCriticalSection( &IconCrst );
186 /**********************************************************************
187 * CURSORICON_FindBestIcon
189 * Find the icon closest to the requested size and number of colors.
191 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
192 int height, int colors )
194 int i, maxcolors, maxwidth, maxheight;
195 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
197 if (dir->idCount < 1)
199 WARN(icon, "Empty directory!\n" );
200 return NULL;
202 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
204 /* First find the exact size with less colors */
206 maxcolors = 0;
207 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
208 if ((entry->ResInfo.icon.bWidth == width) && (entry->ResInfo.icon.bHeight == height) &&
209 (entry->ResInfo.icon.bColorCount <= colors) && (entry->ResInfo.icon.bColorCount > maxcolors))
211 bestEntry = entry;
212 maxcolors = entry->ResInfo.icon.bColorCount;
214 if (bestEntry) return bestEntry;
216 /* First find the exact size with more colors */
218 maxcolors = 255;
219 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
220 if ((entry->ResInfo.icon.bWidth == width) && (entry->ResInfo.icon.bHeight == height) &&
221 (entry->ResInfo.icon.bColorCount > colors) && (entry->ResInfo.icon.bColorCount <= maxcolors))
223 bestEntry = entry;
224 maxcolors = entry->ResInfo.icon.bColorCount;
226 if (bestEntry) return bestEntry;
228 /* Now find a smaller one with less colors */
230 maxcolors = maxwidth = maxheight = 0;
231 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
232 if ((entry->ResInfo.icon.bWidth <= width) && (entry->ResInfo.icon.bHeight <= height) &&
233 (entry->ResInfo.icon.bWidth >= maxwidth) && (entry->ResInfo.icon.bHeight >= maxheight) &&
234 (entry->ResInfo.icon.bColorCount <= colors) && (entry->ResInfo.icon.bColorCount > maxcolors))
236 bestEntry = entry;
237 maxwidth = entry->ResInfo.icon.bWidth;
238 maxheight = entry->ResInfo.icon.bHeight;
239 maxcolors = entry->ResInfo.icon.bColorCount;
241 if (bestEntry) return bestEntry;
243 /* Now find a smaller one with more colors */
245 maxcolors = 255;
246 maxwidth = maxheight = 0;
247 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
248 if ((entry->ResInfo.icon.bWidth <= width) && (entry->ResInfo.icon.bHeight <= height) &&
249 (entry->ResInfo.icon.bWidth >= maxwidth) && (entry->ResInfo.icon.bHeight >= maxheight) &&
250 (entry->ResInfo.icon.bColorCount > colors) && (entry->ResInfo.icon.bColorCount <= maxcolors))
252 bestEntry = entry;
253 maxwidth = entry->ResInfo.icon.bWidth;
254 maxheight = entry->ResInfo.icon.bHeight;
255 maxcolors = entry->ResInfo.icon.bColorCount;
257 if (bestEntry) return bestEntry;
259 /* Now find a larger one with less colors */
261 maxcolors = 0;
262 maxwidth = maxheight = 255;
263 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
264 if ((entry->ResInfo.icon.bWidth <= maxwidth) && (entry->ResInfo.icon.bHeight <= maxheight) &&
265 (entry->ResInfo.icon.bColorCount <= colors) && (entry->ResInfo.icon.bColorCount > maxcolors))
267 bestEntry = entry;
268 maxwidth = entry->ResInfo.icon.bWidth;
269 maxheight = entry->ResInfo.icon.bHeight;
270 maxcolors = entry->ResInfo.icon.bColorCount;
272 if (bestEntry) return bestEntry;
274 /* Now find a larger one with more colors */
276 maxcolors = maxwidth = maxheight = 255;
277 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
278 if ((entry->ResInfo.icon.bWidth <= maxwidth) && (entry->ResInfo.icon.bHeight <= maxheight) &&
279 (entry->ResInfo.icon.bColorCount > colors) && (entry->ResInfo.icon.bColorCount <= maxcolors))
281 bestEntry = entry;
282 maxwidth = entry->ResInfo.icon.bWidth;
283 maxheight = entry->ResInfo.icon.bHeight;
284 maxcolors = entry->ResInfo.icon.bColorCount;
287 return bestEntry;
291 /**********************************************************************
292 * CURSORICON_FindBestCursor
294 * Find the cursor closest to the requested size.
295 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
296 * ignored too
298 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
299 int width, int height, int color)
301 int i, maxwidth, maxheight;
302 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
304 if (dir->idCount < 1)
306 WARN(cursor, "Empty directory!\n" );
307 return NULL;
309 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
311 /* First find the largest one smaller than or equal to the requested size*/
313 maxwidth = maxheight = 0;
314 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
315 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
316 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
317 (entry->wBitCount == 1))
319 bestEntry = entry;
320 maxwidth = entry->ResInfo.cursor.wWidth;
321 maxheight = entry->ResInfo.cursor.wHeight;
323 if (bestEntry) return bestEntry;
325 /* Now find the smallest one larger than the requested size */
327 maxwidth = maxheight = 255;
328 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
329 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
330 (entry->wBitCount == 1))
332 bestEntry = entry;
333 maxwidth = entry->ResInfo.cursor.wWidth;
334 maxheight = entry->ResInfo.cursor.wHeight;
337 return bestEntry;
340 /*********************************************************************
341 * The main purpose of this function is to create fake resource directory
342 * and fake resource entries. There are several reasons for this:
343 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
344 * fields
345 * There are some "bad" cursor files which do not have
346 * bColorCount initialized but instead one must read this info
347 * directly from corresponding DIB sections
348 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
350 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
351 CURSORICONDIR **res, LPBYTE **ptr)
353 LPBYTE _free;
354 CURSORICONFILEDIR *bits;
355 int entries, size, i;
357 *res = NULL;
358 *ptr = NULL;
359 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
361 /* FIXME: test for inimated icons
362 * hack to load the first icon from the *.ani file
364 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
365 { LPBYTE pos = (LPBYTE) bits;
366 FIXME (cursor,"Animated icons not correctly implemented! %p \n", bits);
368 for (;;)
369 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
370 { FIXME (cursor,"icon entry found! %p\n", bits);
371 pos+=4;
372 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
373 { goto fail;
375 bits+=2;
376 FIXME (cursor,"icon size ok %p \n", bits);
377 break;
379 pos+=2;
380 if (pos>=(LPBYTE)bits+766) goto fail;
383 if (!(entries = bits->idCount)) goto fail;
384 (int)_free = size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) *
385 (entries - 1);
386 for (i=0; i < entries; i++)
387 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
389 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
390 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
391 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
393 _free = (LPBYTE)(*res) + (int)_free;
394 memcpy((*res), bits, 6);
395 for (i=0; i<entries; i++)
397 ((LPBYTE*)(*ptr))[i] = _free;
398 if (fCursor) {
399 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
400 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
401 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
402 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
403 _free+=sizeof(POINT16);
404 } else {
405 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
406 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
407 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
409 (*res)->idEntries[i].wPlanes=1;
410 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
411 bits->idEntries[i].dwDIBOffset))->biBitCount;
412 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
413 (*res)->idEntries[i].wResId=i+1;
415 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
416 (*res)->idEntries[i].dwBytesInRes);
417 _free += (*res)->idEntries[i].dwBytesInRes;
419 UnmapViewOfFile( bits );
420 return TRUE;
421 fail:
422 if (*res) HeapFree( GetProcessHeap(), 0, *res );
423 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
424 UnmapViewOfFile( bits );
425 return FALSE;
429 /**********************************************************************
430 * CURSORICON_CreateFromResource
432 * Create a cursor or icon from in-memory resource template.
434 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
435 * with cbSize parameter as well.
437 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
438 UINT cbSize, BOOL bIcon, DWORD dwVersion,
439 INT width, INT height, UINT loadflags )
441 int sizeAnd, sizeXor;
442 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
443 BITMAPOBJ *bmpXor, *bmpAnd;
444 POINT16 hotspot = { 0 ,0 };
445 BITMAPINFO *bmi;
446 HDC hdc;
447 BOOL DoStretch;
448 INT size;
450 TRACE(cursor,"%08x (%u bytes), ver %08x, %ix%i %s %s\n",
451 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
452 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
453 if (dwVersion == 0x00020000)
455 FIXME(cursor,"\t2.xx resources are not supported\n");
456 return 0;
459 if (bIcon)
460 bmi = (BITMAPINFO *)bits;
461 else /* get the hotspot */
463 POINT16 *pt = (POINT16 *)bits;
464 hotspot = *pt;
465 bmi = (BITMAPINFO *)(pt + 1);
467 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
469 if (!width) width = bmi->bmiHeader.biWidth;
470 if (!height) height = bmi->bmiHeader.biHeight/2;
471 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
472 (bmi->bmiHeader.biWidth != width);
474 /* Check bitmap header */
476 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
477 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
478 bmi->bmiHeader.biCompression != BI_RGB) )
480 WARN(cursor,"\tinvalid resource bitmap header.\n");
481 return 0;
484 if( (hdc = GetDC( 0 )) )
486 BITMAPINFO* pInfo;
488 /* Make sure we have room for the monochrome bitmap later on.
489 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
490 * up to and including the biBitCount. In-memory icon resource
491 * format is as follows:
493 * BITMAPINFOHEADER icHeader // DIB header
494 * RGBQUAD icColors[] // Color table
495 * BYTE icXOR[] // DIB bits for XOR mask
496 * BYTE icAND[] // DIB bits for AND mask
499 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
500 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
502 memcpy( pInfo, bmi, size );
503 pInfo->bmiHeader.biHeight /= 2;
505 /* Create the XOR bitmap */
507 if (DoStretch) {
508 if ((hXorBits = CreateCompatibleBitmap(hdc, width, height))) {
509 HBITMAP hOld;
510 HDC hMem = CreateCompatibleDC(hdc);
511 BOOL res;
513 if (hMem) {
514 hOld = SelectObject(hMem, hXorBits);
515 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
516 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
517 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
518 SelectObject(hMem, hOld);
519 DeleteDC(hMem);
520 } else res = FALSE;
521 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
523 } else hXorBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
524 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
525 if( hXorBits )
527 char* bits = (char *)bmi + size + bmi->bmiHeader.biHeight *
528 DIB_GetDIBWidthBytes(bmi->bmiHeader.biWidth,
529 bmi->bmiHeader.biBitCount) / 2;
531 pInfo->bmiHeader.biBitCount = 1;
532 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
534 RGBQUAD *rgb = pInfo->bmiColors;
536 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
537 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
538 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
539 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
541 else
543 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
545 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
546 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
549 /* Create the AND bitmap */
551 if (DoStretch) {
552 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
553 HBITMAP hOld;
554 HDC hMem = CreateCompatibleDC(hdc);
555 BOOL res;
557 if (hMem) {
558 hOld = SelectObject(hMem, hAndBits);
559 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
560 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
561 bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
562 SelectObject(hMem, hOld);
563 DeleteDC(hMem);
564 } else res = FALSE;
565 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
567 } else hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
568 CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
570 if( !hAndBits ) DeleteObject( hXorBits );
572 HeapFree( GetProcessHeap(), 0, pInfo );
574 ReleaseDC( 0, hdc );
577 if( !hXorBits || !hAndBits )
579 WARN(cursor,"\tunable to create an icon bitmap.\n");
580 return 0;
583 /* Now create the CURSORICONINFO structure */
584 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
585 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
586 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
587 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
589 if (hObj) hObj = GlobalReAlloc16( hObj,
590 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
591 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
592 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
593 if (hObj)
595 CURSORICONINFO *info;
597 /* Make it owned by the module */
598 if (hInstance) FarSetOwner16( hObj, GetExePtr(hInstance) );
600 info = (CURSORICONINFO *)GlobalLock16( hObj );
601 info->ptHotSpot.x = hotspot.x;
602 info->ptHotSpot.y = hotspot.y;
603 info->nWidth = bmpXor->bitmap.bmWidth;
604 info->nHeight = bmpXor->bitmap.bmHeight;
605 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
606 info->bPlanes = bmpXor->bitmap.bmPlanes;
607 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
609 /* Transfer the bitmap bits to the CURSORICONINFO structure */
611 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
612 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
613 GlobalUnlock16( hObj );
616 DeleteObject( hXorBits );
617 DeleteObject( hAndBits );
618 return hObj;
622 /**********************************************************************
623 * CreateIconFromResourceEx16 (USER.450)
625 * FIXME: not sure about exact parameter types
627 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
628 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
630 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
631 width, height, cFlag);
635 /**********************************************************************
636 * CreateIconFromResource (USER32.76)
638 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
639 BOOL bIcon, DWORD dwVersion)
641 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
645 /**********************************************************************
646 * CreateIconFromResourceEx32 (USER32.77)
648 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
649 BOOL bIcon, DWORD dwVersion,
650 INT width, INT height,
651 UINT cFlag )
653 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
654 if( pTask )
655 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
656 width, height, cFlag );
657 return 0;
660 /**********************************************************************
661 * CURSORICON_Load
663 * Load a cursor or icon from resource or file.
665 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
666 INT width, INT height, INT colors,
667 BOOL fCursor, UINT loadflags )
669 HANDLE handle = 0, h = 0;
670 HANDLE hRsrc;
671 CURSORICONDIR *dir;
672 CURSORICONDIRENTRY *dirEntry;
673 LPBYTE bits;
675 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
677 LPBYTE *ptr;
678 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
679 return 0;
680 if (fCursor)
681 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
682 else
683 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
684 bits = ptr[dirEntry->wResId-1];
685 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
686 !fCursor, 0x00030000, width, height, loadflags);
687 HeapFree( GetProcessHeap(), 0, dir );
688 HeapFree( GetProcessHeap(), 0, ptr );
691 else if ( !hInstance ) /* Load OEM cursor/icon */
693 WORD resid;
694 HDC hdc;
695 DC *dc;
697 if ( HIWORD(name) )
699 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
700 if( ansi[0]=='#') /*Check for '#xxx' name */
702 resid = atoi(ansi+1);
703 HeapFree( GetProcessHeap(), 0, ansi );
705 else
707 HeapFree( GetProcessHeap(), 0, ansi );
708 return 0;
711 else resid = LOWORD(name);
712 hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
713 dc = DC_GetDCPtr( hdc );
714 if (dc->funcs->pLoadOEMResource)
715 h = dc->funcs->pLoadOEMResource( resid, fCursor ?
716 OEM_CURSOR : OEM_ICON );
717 GDI_HEAP_UNLOCK( hdc );
718 DeleteDC( hdc );
721 else /* Load from resource */
723 WORD wResId;
724 DWORD dwBytesInRes;
726 /* Normalize hInstance (must be uniquely represented for icon cache) */
728 if ( HIWORD( hInstance ) )
729 hInstance = MapHModuleLS( hInstance );
730 else
731 hInstance = GetExePtr( hInstance );
733 /* Get directory resource ID */
735 if (!(hRsrc = FindResourceW( hInstance, name,
736 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
737 return 0;
739 /* If shared icon, check whether it was already loaded */
741 if ( (loadflags & LR_SHARED)
742 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
743 return h;
745 /* Find the best entry in the directory */
747 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
748 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
749 if (fCursor)
750 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
751 width, height, 1);
752 else
753 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
754 width, height, colors );
755 if (!dirEntry) return 0;
756 wResId = dirEntry->wResId;
757 dwBytesInRes = dirEntry->dwBytesInRes;
758 FreeResource( handle );
760 /* Load the resource */
762 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
763 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
764 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
765 bits = (LPBYTE)LockResource( handle );
766 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
767 !fCursor, 0x00030000, width, height, loadflags);
768 FreeResource( handle );
770 /* If shared icon, add to icon cache */
772 if ( h && (loadflags & LR_SHARED) )
773 CURSORICON_AddSharedIcon( hInstance, hRsrc, h );
776 return h;
779 /***********************************************************************
780 * CURSORICON_Copy
782 * Make a copy of a cursor or icon.
784 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
786 char *ptrOld, *ptrNew;
787 int size;
788 HGLOBAL16 hNew;
790 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
791 if (!(hInstance = GetExePtr( hInstance ))) return 0;
792 size = GlobalSize16( handle );
793 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
794 FarSetOwner16( hNew, hInstance );
795 ptrNew = (char *)GlobalLock16( hNew );
796 memcpy( ptrNew, ptrOld, size );
797 GlobalUnlock16( handle );
798 GlobalUnlock16( hNew );
799 return hNew;
802 /***********************************************************************
803 * CURSORICON_IconToCursor
805 * Converts bitmap to mono and truncates if icon is too large (should
806 * probably do StretchBlt() instead).
808 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
810 HCURSOR16 hRet = 0;
811 CURSORICONINFO *pIcon = NULL;
812 HTASK16 hTask = GetCurrentTask();
813 TDB* pTask = (TDB *)GlobalLock16(hTask);
815 if(hIcon && pTask)
816 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
817 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
818 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
819 else
821 BYTE pAndBits[128];
822 BYTE pXorBits[128];
823 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
824 BYTE* psPtr, *pxbPtr = pXorBits;
825 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
826 BYTE* pbc = NULL;
828 CURSORICONINFO cI;
830 TRACE(icon, "[%04x] %ix%i %ibpp (bogus %ibps)\n",
831 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
833 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
834 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
835 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
837 memset(pXorBits, 0, 128);
838 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
839 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
840 cI.nWidth = 32; cI.nHeight = 32;
841 cI.nWidthBytes = 4; /* 32x1bpp */
843 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
844 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
846 for( iy = 0; iy < maxy; iy++ )
848 unsigned shift = iy % 2;
850 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
851 (and_width > 4) ? 4 : and_width );
852 for( ix = 0; ix < maxx; ix++ )
854 if( bSemiTransparent && ((ix+shift)%2) )
856 /* set AND bit, XOR bit stays 0 */
858 pbc = pAndBits + iy * 4 + ix/8;
859 *pbc |= 0x80 >> (ix%8);
861 else
863 /* keep AND bit, set XOR bit */
865 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
866 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
867 if(!PALETTE_Driver->pIsDark(val))
869 pbc = pxbPtr + ix/8;
870 *pbc |= 0x80 >> (ix%8);
874 psPtr += xor_width;
875 pxbPtr += 4;
878 hRet = CreateCursorIconIndirect16( pTask->hInstance , &cI, pAndBits, pXorBits);
880 if( !hRet ) /* fall back on default drag cursor */
881 hRet = CURSORICON_Copy( pTask->hInstance ,
882 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
883 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0) );
886 return hRet;
890 /***********************************************************************
891 * LoadCursor16 (USER.173)
893 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
895 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
896 return LoadCursorA( hInstance, nameStr );
900 /***********************************************************************
901 * LoadIcon16 (USER.174)
903 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
905 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
906 return LoadIconA( hInstance, nameStr );
910 /***********************************************************************
911 * CreateCursor16 (USER.406)
913 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
914 INT16 xHotSpot, INT16 yHotSpot,
915 INT16 nWidth, INT16 nHeight,
916 LPCVOID lpANDbits, LPCVOID lpXORbits )
918 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
920 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
921 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
922 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
926 /***********************************************************************
927 * CreateCursor32 (USER32.67)
929 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
930 INT xHotSpot, INT yHotSpot,
931 INT nWidth, INT nHeight,
932 LPCVOID lpANDbits, LPCVOID lpXORbits )
934 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
936 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
937 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
938 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
942 /***********************************************************************
943 * CreateIcon16 (USER.407)
945 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
946 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
947 LPCVOID lpANDbits, LPCVOID lpXORbits )
949 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
951 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
952 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
953 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
957 /***********************************************************************
958 * CreateIcon32 (USER32.75)
960 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
961 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
962 LPCVOID lpANDbits, LPCVOID lpXORbits )
964 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
966 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
967 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
968 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
972 /***********************************************************************
973 * CreateCursorIconIndirect (USER.408)
975 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
976 CURSORICONINFO *info,
977 LPCVOID lpANDbits,
978 LPCVOID lpXORbits )
980 HGLOBAL16 handle;
981 char *ptr;
982 int sizeAnd, sizeXor;
984 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
985 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
986 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
987 sizeXor = info->nHeight * info->nWidthBytes;
988 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
989 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
990 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
991 return 0;
992 if (hInstance) FarSetOwner16( handle, hInstance );
993 ptr = (char *)GlobalLock16( handle );
994 memcpy( ptr, info, sizeof(*info) );
995 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
996 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
997 GlobalUnlock16( handle );
998 return handle;
1002 /***********************************************************************
1003 * CopyIcon16 (USER.368)
1005 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1007 TRACE(icon, "%04x %04x\n", hInstance, hIcon );
1008 return CURSORICON_Copy( hInstance, hIcon );
1012 /***********************************************************************
1013 * CopyIcon32 (USER32.60)
1015 HICON WINAPI CopyIcon( HICON hIcon )
1017 HTASK16 hTask = GetCurrentTask ();
1018 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1019 TRACE(icon, "%04x\n", hIcon );
1020 return CURSORICON_Copy( pTask->hInstance, hIcon );
1024 /***********************************************************************
1025 * CopyCursor16 (USER.369)
1027 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1029 TRACE(cursor, "%04x %04x\n", hInstance, hCursor );
1030 return CURSORICON_Copy( hInstance, hCursor );
1033 /**********************************************************************
1034 * CURSORICON_Destroy (USER.610)
1036 * This routine is actually exported from Win95 USER under the name
1037 * DestroyIcon32 ... The behaviour implemented here should mimic
1038 * the Win95 one exactly, especially the return values, which
1039 * depend on the setting of various flags.
1041 WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1043 WORD retv;
1045 TRACE( icon, "(%04x, %04x)\n", handle, flags );
1047 /* Check whether destroying active cursor */
1049 if ( hActiveCursor == handle )
1051 ERR( cursor, "Destroying active cursor!\n" );
1052 SetCursor( 0 );
1055 /* Try shared cursor/icon first */
1057 if ( !(flags & CID_NONSHARED) )
1059 INT count = CURSORICON_DelSharedIcon( handle );
1061 if ( count != -1 )
1062 return (flags & CID_WIN32)? TRUE : (count == 0);
1064 /* FIXME: OEM cursors/icons should be recognized */
1067 /* Now assume non-shared cursor/icon */
1069 retv = GlobalFree16( handle );
1070 return (flags & CID_RESOURCE)? retv : TRUE;
1073 /***********************************************************************
1074 * DestroyIcon16 (USER.457)
1076 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1078 return CURSORICON_Destroy( hIcon, 0 );
1081 /***********************************************************************
1082 * DestroyIcon (USER32.133)
1084 BOOL WINAPI DestroyIcon( HICON hIcon )
1086 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1089 /***********************************************************************
1090 * DestroyCursor16 (USER.458)
1092 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1094 return CURSORICON_Destroy( hCursor, 0 );
1097 /***********************************************************************
1098 * DestroyCursor (USER32.132)
1100 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1102 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1106 /***********************************************************************
1107 * DrawIcon16 (USER.84)
1109 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1111 return DrawIcon( hdc, x, y, hIcon );
1115 /***********************************************************************
1116 * DrawIcon32 (USER32.159)
1118 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1120 CURSORICONINFO *ptr;
1121 HDC hMemDC;
1122 HBITMAP hXorBits, hAndBits;
1123 COLORREF oldFg, oldBg;
1125 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1126 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1127 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1128 (char *)(ptr+1) );
1129 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1130 ptr->bBitsPerPixel, (char *)(ptr + 1)
1131 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1132 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1133 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1135 if (hXorBits && hAndBits)
1137 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1138 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1139 SelectObject( hMemDC, hXorBits );
1140 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1141 SelectObject( hMemDC, hBitTemp );
1143 DeleteDC( hMemDC );
1144 if (hXorBits) DeleteObject( hXorBits );
1145 if (hAndBits) DeleteObject( hAndBits );
1146 GlobalUnlock16( hIcon );
1147 SetTextColor( hdc, oldFg );
1148 SetBkColor( hdc, oldBg );
1149 return TRUE;
1153 /***********************************************************************
1154 * DumpIcon (USER.459)
1156 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1157 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1159 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1160 int sizeAnd, sizeXor;
1162 if (!info) return 0;
1163 sizeXor = info->nHeight * info->nWidthBytes;
1164 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1165 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1166 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1167 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1168 return MAKELONG( sizeXor, sizeXor );
1172 /***********************************************************************
1173 * SetCursor16 (USER.69)
1175 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1177 return (HCURSOR16)SetCursor( hCursor );
1181 /***********************************************************************
1182 * SetCursor32 (USER32.472)
1183 * RETURNS:
1184 * A handle to the previous cursor shape.
1186 HCURSOR WINAPI SetCursor(
1187 HCURSOR hCursor /* Handle of cursor to show */
1189 HCURSOR hOldCursor;
1191 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1192 TRACE(cursor, "%04x\n", hCursor );
1193 hOldCursor = hActiveCursor;
1194 hActiveCursor = hCursor;
1195 /* Change the cursor shape only if it is visible */
1196 if (CURSOR_ShowCount >= 0)
1198 DISPLAY_SetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1199 GlobalUnlock16( hActiveCursor );
1201 return hOldCursor;
1205 /***********************************************************************
1206 * SetCursorPos16 (USER.70)
1208 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1210 SetCursorPos( x, y );
1214 /***********************************************************************
1215 * SetCursorPos32 (USER32.474)
1217 BOOL WINAPI SetCursorPos( INT x, INT y )
1219 DISPLAY_MoveCursor( x, y );
1220 return TRUE;
1224 /***********************************************************************
1225 * ShowCursor16 (USER.71)
1227 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1229 return ShowCursor( bShow );
1233 /***********************************************************************
1234 * ShowCursor32 (USER32.530)
1236 INT WINAPI ShowCursor( BOOL bShow )
1238 TRACE(cursor, "%d, count=%d\n",
1239 bShow, CURSOR_ShowCount );
1241 if (bShow)
1243 if (++CURSOR_ShowCount == 0) /* Show it */
1245 DISPLAY_SetCursor((CURSORICONINFO*)GlobalLock16( hActiveCursor ));
1246 GlobalUnlock16( hActiveCursor );
1249 else
1251 if (--CURSOR_ShowCount == -1) /* Hide it */
1252 DISPLAY_SetCursor( NULL );
1254 return CURSOR_ShowCount;
1258 /***********************************************************************
1259 * GetCursor16 (USER.247)
1261 HCURSOR16 WINAPI GetCursor16(void)
1263 return hActiveCursor;
1267 /***********************************************************************
1268 * GetCursor32 (USER32.227)
1270 HCURSOR WINAPI GetCursor(void)
1272 return hActiveCursor;
1276 /***********************************************************************
1277 * ClipCursor16 (USER.16)
1279 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1281 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1282 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1283 return TRUE;
1287 /***********************************************************************
1288 * ClipCursor32 (USER32.53)
1290 BOOL WINAPI ClipCursor( const RECT *rect )
1292 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1293 else CopyRect( &CURSOR_ClipRect, rect );
1294 return TRUE;
1298 /***********************************************************************
1299 * GetCursorPos16 (USER.17)
1301 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
1303 DWORD posX, posY, state;
1305 if (!pt) return 0;
1306 if (!EVENT_QueryPointer( &posX, &posY, &state ))
1307 pt->x = pt->y = 0;
1308 else
1310 pt->x = posX;
1311 pt->y = posY;
1312 if (state & MK_LBUTTON)
1313 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1314 else
1315 MouseButtonsStates[0] = FALSE;
1316 if (state & MK_MBUTTON)
1317 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1318 else
1319 MouseButtonsStates[1] = FALSE;
1320 if (state & MK_RBUTTON)
1321 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1322 else
1323 MouseButtonsStates[2] = FALSE;
1325 TRACE(cursor, "ret=%d,%d\n", pt->x, pt->y );
1326 return 1;
1330 /***********************************************************************
1331 * GetCursorPos32 (USER32.229)
1333 BOOL WINAPI GetCursorPos( POINT *pt )
1335 BOOL ret;
1337 POINT16 pt16;
1338 ret = GetCursorPos16( &pt16 );
1339 if (pt) CONV_POINT16TO32( &pt16, pt );
1340 return ((pt) ? ret : 0);
1344 /***********************************************************************
1345 * GetClipCursor16 (USER.309)
1347 void WINAPI GetClipCursor16( RECT16 *rect )
1349 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1353 /***********************************************************************
1354 * GetClipCursor32 (USER32.221)
1356 BOOL WINAPI GetClipCursor( RECT *rect )
1358 if (rect)
1360 CopyRect( rect, &CURSOR_ClipRect );
1361 return TRUE;
1363 return FALSE;
1366 /**********************************************************************
1367 * LookupIconIdFromDirectoryEx16 (USER.364)
1369 * FIXME: exact parameter sizes
1371 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1372 INT16 width, INT16 height, UINT16 cFlag )
1374 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1375 UINT16 retVal = 0;
1376 if( dir && !dir->idReserved && (dir->idType & 3) )
1378 HDC hdc = GetDC(0);
1379 UINT palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1380 int colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1381 CURSORICONDIRENTRY* entry;
1383 ReleaseDC(0, hdc);
1385 if( bIcon )
1386 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1387 else
1388 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1390 if( entry ) retVal = entry->wResId;
1392 else WARN(cursor, "invalid resource directory\n");
1393 return retVal;
1396 /**********************************************************************
1397 * LookupIconIdFromDirectoryEx32 (USER32.380)
1399 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1400 INT width, INT height, UINT cFlag )
1402 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1405 /**********************************************************************
1406 * LookupIconIdFromDirectory (USER.???)
1408 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1410 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1411 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1412 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1415 /**********************************************************************
1416 * LookupIconIdFromDirectory (USER32.379)
1418 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1420 return LookupIconIdFromDirectoryEx( dir, bIcon,
1421 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1422 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1425 /**********************************************************************
1426 * GetIconID (USER.455)
1428 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1430 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1432 TRACE(cursor, "hRes=%04x, entries=%i\n",
1433 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1435 switch(resType)
1437 case RT_CURSOR16:
1438 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1439 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1440 case RT_ICON16:
1441 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1442 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1443 default:
1444 WARN(cursor, "invalid res type %ld\n", resType );
1446 return 0;
1449 /**********************************************************************
1450 * LoadCursorIconHandler (USER.336)
1452 * Supposed to load resources of Windows 2.x applications.
1454 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1456 FIXME(cursor,"(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1457 hResource, hModule, hRsrc);
1458 return (HGLOBAL16)0;
1461 /**********************************************************************
1462 * LoadDIBIconHandler (USER.357)
1464 * RT_ICON resource loader, installed by USER_SignalProc when module
1465 * is initialized.
1467 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1469 /* If hResource is zero we must allocate a new memory block, if it's
1470 * non-zero but GlobalLock() returns NULL then it was discarded and
1471 * we have to recommit some memory, otherwise we just need to check
1472 * the block size. See LoadProc() in 16-bit SDK for more.
1475 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1476 if( hMemObj )
1478 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1479 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1480 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1481 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1483 return hMemObj;
1486 /**********************************************************************
1487 * LoadDIBCursorHandler (USER.356)
1489 * RT_CURSOR resource loader. Same as above.
1491 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1493 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1494 if( hMemObj )
1496 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1497 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1498 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1499 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1501 return hMemObj;
1504 /**********************************************************************
1505 * LoadIconHandler (USER.456)
1507 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1509 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1511 TRACE(cursor,"hRes=%04x\n",hResource);
1513 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1514 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1517 /***********************************************************************
1518 * LoadCursorW (USER32.362)
1520 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1522 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1523 LR_SHARED | LR_DEFAULTSIZE );
1526 /***********************************************************************
1527 * LoadCursorA (USER32.359)
1529 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1531 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1532 LR_SHARED | LR_DEFAULTSIZE );
1535 /***********************************************************************
1536 * LoadCursorFromFileW (USER32.361)
1538 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1540 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1541 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1544 /***********************************************************************
1545 * LoadCursorFromFileA (USER32.360)
1547 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1549 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1550 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1553 /***********************************************************************
1554 * LoadIconW (USER32.364)
1556 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1558 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1559 LR_SHARED | LR_DEFAULTSIZE );
1562 /***********************************************************************
1563 * LoadIconA (USER32.363)
1565 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1567 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1568 LR_SHARED | LR_DEFAULTSIZE );
1571 /**********************************************************************
1572 * GetIconInfo16 (USER.395)
1574 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1576 ICONINFO ii32;
1577 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1579 iconinfo->fIcon = ii32.fIcon;
1580 iconinfo->xHotspot = ii32.xHotspot;
1581 iconinfo->yHotspot = ii32.yHotspot;
1582 iconinfo->hbmMask = ii32.hbmMask;
1583 iconinfo->hbmColor = ii32.hbmColor;
1584 return ret;
1587 /**********************************************************************
1588 * GetIconInfo32 (USER32.242)
1590 BOOL WINAPI GetIconInfo(HICON hIcon,LPICONINFO iconinfo) {
1591 CURSORICONINFO *ciconinfo;
1593 ciconinfo = GlobalLock16(hIcon);
1594 if (!ciconinfo)
1595 return FALSE;
1596 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1597 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1598 iconinfo->fIcon = TRUE; /* hmm */
1600 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1601 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1602 (char *)(ciconinfo + 1)
1603 + ciconinfo->nHeight *
1604 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1605 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1606 1, 1, (char *)(ciconinfo + 1));
1608 GlobalUnlock16(hIcon);
1610 return TRUE;
1613 /**********************************************************************
1614 * CreateIconIndirect (USER32.78)
1616 HICON WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1617 BITMAPOBJ *bmpXor,*bmpAnd;
1618 HICON hObj;
1619 int sizeXor,sizeAnd;
1621 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1622 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1624 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1625 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1627 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1628 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1629 if (hObj)
1631 CURSORICONINFO *info;
1633 info = (CURSORICONINFO *)GlobalLock16( hObj );
1634 info->ptHotSpot.x = iconinfo->xHotspot;
1635 info->ptHotSpot.y = iconinfo->yHotspot;
1636 info->nWidth = bmpXor->bitmap.bmWidth;
1637 info->nHeight = bmpXor->bitmap.bmHeight;
1638 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1639 info->bPlanes = bmpXor->bitmap.bmPlanes;
1640 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1642 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1644 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1645 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1646 GlobalUnlock16( hObj );
1648 return hObj;
1652 /**********************************************************************
1654 DrawIconEx16 (USER.394)
1656 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1657 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1658 HBRUSH16 hbr, UINT16 flags)
1660 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1661 istep, hbr, flags);
1665 /******************************************************************************
1666 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1668 * NOTES
1669 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1671 * PARAMS
1672 * hdc [I] Handle to device context
1673 * x0 [I] X coordinate of upper left corner
1674 * y0 [I] Y coordinate of upper left corner
1675 * hIcon [I] Handle to icon to draw
1676 * cxWidth [I] Width of icon
1677 * cyWidth [I] Height of icon
1678 * istep [I] Index of frame in animated cursor
1679 * hbr [I] Handle to background brush
1680 * flags [I] Icon-drawing flags
1682 * RETURNS
1683 * Success: TRUE
1684 * Failure: FALSE
1686 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1687 INT cxWidth, INT cyWidth, UINT istep,
1688 HBRUSH hbr, UINT flags )
1690 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1691 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1692 BOOL result = FALSE, DoOffscreen = FALSE;
1693 HBITMAP hB_off = 0, hOld = 0;
1695 if (!ptr) return FALSE;
1697 if (istep)
1698 FIXME(icon, "Ignoring istep=%d\n", istep);
1699 if (flags & DI_COMPAT)
1700 FIXME(icon, "Ignoring flag DI_COMPAT\n");
1702 /* Calculate the size of the destination image. */
1703 if (cxWidth == 0)
1705 if (flags & DI_DEFAULTSIZE)
1706 cxWidth = GetSystemMetrics (SM_CXICON);
1707 else
1708 cxWidth = ptr->nWidth;
1710 if (cyWidth == 0)
1712 if (flags & DI_DEFAULTSIZE)
1713 cyWidth = GetSystemMetrics (SM_CYICON);
1714 else
1715 cyWidth = ptr->nHeight;
1718 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1719 STOCK_HOLLOW_BRUSH)))
1721 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1722 if (object)
1724 UINT16 magic = object->wMagic;
1725 GDI_HEAP_UNLOCK(hbr);
1726 DoOffscreen = magic == BRUSH_MAGIC;
1729 if (DoOffscreen) {
1730 RECT r = {0, 0, cxWidth, cxWidth};
1732 hDC_off = CreateCompatibleDC(hdc);
1733 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1734 if (hDC_off && hB_off) {
1735 hOld = SelectObject(hDC_off, hB_off);
1736 FillRect(hDC_off, &r, hbr);
1740 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1742 HBITMAP hXorBits, hAndBits;
1743 COLORREF oldFg, oldBg;
1744 INT nStretchMode;
1746 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1748 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1749 ptr->bPlanes, ptr->bBitsPerPixel,
1750 (char *)(ptr + 1)
1751 + ptr->nHeight *
1752 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1753 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1754 1, 1, (char *)(ptr+1) );
1755 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1756 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1758 if (hXorBits && hAndBits)
1760 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1761 if (flags & DI_MASK)
1763 if (DoOffscreen)
1764 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1765 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1766 else
1767 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1768 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1770 SelectObject( hMemDC, hXorBits );
1771 if (flags & DI_IMAGE)
1773 if (DoOffscreen)
1774 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1775 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1776 else
1777 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1778 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1780 SelectObject( hMemDC, hBitTemp );
1781 result = TRUE;
1784 SetTextColor( hdc, oldFg );
1785 SetBkColor( hdc, oldBg );
1786 if (hXorBits) DeleteObject( hXorBits );
1787 if (hAndBits) DeleteObject( hAndBits );
1788 SetStretchBltMode (hdc, nStretchMode);
1789 if (DoOffscreen) {
1790 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
1791 SelectObject(hDC_off, hOld);
1794 if (hMemDC) DeleteDC( hMemDC );
1795 if (hDC_off) DeleteDC(hDC_off);
1796 if (hB_off) DeleteObject(hB_off);
1797 GlobalUnlock16( hIcon );
1798 return result;