Release 980329
[wine/multimedia.git] / objects / cursoricon.c
blobc25333f2522b3ab439fc93ba99f12c233dbde820
1 /*
2 * Cursor and icon support
4 * Copyright 1995 Alexandre Julliard
5 * 1996 Martin Von Loewis
6 * 1997 Alex Korobka
7 */
9 /*
10 * Theory:
12 * http://www.microsoft.com/win32dev/ui/icons.htm
14 * Cursors and icons are stored in a global heap block, with the
15 * following layout:
17 * CURSORICONINFO info;
18 * BYTE[] ANDbits;
19 * BYTE[] XORbits;
21 * The bits structures are in the format of a device-dependent bitmap.
23 * This layout is very sub-optimal, as the bitmap bits are stored in
24 * the X client instead of in the server like other bitmaps; however,
25 * some programs (notably Paint Brush) expect to be able to manipulate
26 * the bits directly :-(
29 #include <string.h>
30 #include <stdlib.h>
31 #include "heap.h"
32 #include "windows.h"
33 #include "peexe.h"
34 #include "color.h"
35 #include "bitmap.h"
36 #include "callback.h"
37 #include "cursoricon.h"
38 #include "sysmetrics.h"
39 #include "module.h"
40 #include "win.h"
41 #include "debug.h"
42 #include "task.h"
43 #include "user.h"
44 #include "keyboard.h"
46 extern UINT16 COLOR_GetSystemPaletteSize();
48 Cursor CURSORICON_XCursor = None; /* Current X cursor */
49 static HCURSOR32 hActiveCursor = 0; /* Active cursor */
50 static INT32 CURSOR_ShowCount = 0; /* Cursor display count */
51 static RECT32 CURSOR_ClipRect; /* Cursor clipping rect */
53 /**********************************************************************
54 * CURSORICON_FindBestIcon
56 * Find the icon closest to the requested size and number of colors.
58 static ICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
59 int height, int colors )
61 int i, maxcolors, maxwidth, maxheight;
62 ICONDIRENTRY *entry, *bestEntry = NULL;
64 if (dir->idCount < 1)
66 fprintf( stderr, "Icon: empty directory!\n" );
67 return NULL;
69 if (dir->idCount == 1) return &dir->idEntries[0].icon; /* No choice... */
71 /* First find the exact size with less colors */
73 maxcolors = 0;
74 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
75 if ((entry->bWidth == width) && (entry->bHeight == height) &&
76 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
78 bestEntry = entry;
79 maxcolors = entry->bColorCount;
81 if (bestEntry) return bestEntry;
83 /* First find the exact size with more colors */
85 maxcolors = 255;
86 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
87 if ((entry->bWidth == width) && (entry->bHeight == height) &&
88 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
90 bestEntry = entry;
91 maxcolors = entry->bColorCount;
93 if (bestEntry) return bestEntry;
95 /* Now find a smaller one with less colors */
97 maxcolors = maxwidth = maxheight = 0;
98 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
99 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
100 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
101 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
103 bestEntry = entry;
104 maxwidth = entry->bWidth;
105 maxheight = entry->bHeight;
106 maxcolors = entry->bColorCount;
108 if (bestEntry) return bestEntry;
110 /* Now find a smaller one with more colors */
112 maxcolors = 255;
113 maxwidth = maxheight = 0;
114 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
115 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
116 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
117 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
119 bestEntry = entry;
120 maxwidth = entry->bWidth;
121 maxheight = entry->bHeight;
122 maxcolors = entry->bColorCount;
124 if (bestEntry) return bestEntry;
126 /* Now find a larger one with less colors */
128 maxcolors = 0;
129 maxwidth = maxheight = 255;
130 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
131 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
132 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
134 bestEntry = entry;
135 maxwidth = entry->bWidth;
136 maxheight = entry->bHeight;
137 maxcolors = entry->bColorCount;
139 if (bestEntry) return bestEntry;
141 /* Now find a larger one with more colors */
143 maxcolors = maxwidth = maxheight = 255;
144 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
145 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
146 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
148 bestEntry = entry;
149 maxwidth = entry->bWidth;
150 maxheight = entry->bHeight;
151 maxcolors = entry->bColorCount;
154 return bestEntry;
158 /**********************************************************************
159 * CURSORICON_FindBestCursor
161 * Find the cursor closest to the requested size.
163 static CURSORDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
164 int width, int height )
166 int i, maxwidth, maxheight;
167 CURSORDIRENTRY *entry, *bestEntry = NULL;
169 if (dir->idCount < 1)
171 fprintf( stderr, "Cursor: empty directory!\n" );
172 return NULL;
174 if (dir->idCount == 1) return &dir->idEntries[0].cursor; /* No choice... */
176 /* First find the largest one smaller than or equal to the requested size*/
178 maxwidth = maxheight = 0;
179 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
180 if ((entry->wWidth <= width) && (entry->wHeight <= height) &&
181 (entry->wWidth > maxwidth) && (entry->wHeight > maxheight))
183 bestEntry = entry;
184 maxwidth = entry->wWidth;
185 maxheight = entry->wHeight;
187 if (bestEntry) return bestEntry;
189 /* Now find the smallest one larger than the requested size */
191 maxwidth = maxheight = 255;
192 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
193 if ((entry->wWidth < maxwidth) && (entry->wHeight < maxheight))
195 bestEntry = entry;
196 maxwidth = entry->wWidth;
197 maxheight = entry->wHeight;
200 return bestEntry;
204 /**********************************************************************
205 * CURSORICON_LoadDirEntry16
207 * Load the icon/cursor directory for a given resource name and find the
208 * best matching entry.
210 static BOOL32 CURSORICON_LoadDirEntry16( HINSTANCE32 hInstance, SEGPTR name,
211 INT32 width, INT32 height, INT32 colors,
212 BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
214 HRSRC16 hRsrc;
215 HGLOBAL16 hMem;
216 CURSORICONDIR *dir;
217 CURSORICONDIRENTRY *entry = NULL;
219 if (!(hRsrc = FindResource16( hInstance, name,
220 fCursor ? RT_GROUP_CURSOR : RT_GROUP_ICON )))
221 return FALSE;
222 if (!(hMem = LoadResource16( hInstance, hRsrc ))) return FALSE;
223 if ((dir = (CURSORICONDIR *)LockResource16( hMem )))
225 if (fCursor)
226 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
227 width, height );
228 else
229 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
230 width, height, colors );
231 if (entry) *dirEntry = *entry;
233 FreeResource16( hMem );
234 return (entry != NULL);
238 /**********************************************************************
239 * CURSORICON_LoadDirEntry32
241 * Load the icon/cursor directory for a given resource name and find the
242 * best matching entry.
244 static BOOL32 CURSORICON_LoadDirEntry32( HINSTANCE32 hInstance, LPCWSTR name,
245 INT32 width, INT32 height, INT32 colors,
246 BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
248 HANDLE32 hRsrc;
249 HANDLE32 hMem;
250 CURSORICONDIR *dir;
251 CURSORICONDIRENTRY *entry = NULL;
253 if (!(hRsrc = FindResource32W( hInstance, name,
254 (LPCWSTR)(fCursor ? RT_GROUP_CURSOR : RT_GROUP_ICON) )))
255 return FALSE;
256 if (!(hMem = LoadResource32( hInstance, hRsrc ))) return FALSE;
257 if ((dir = (CURSORICONDIR*)LockResource32( hMem )))
259 if (fCursor)
260 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
261 width, height );
262 else
263 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
264 width, height, colors );
265 if (entry) *dirEntry = *entry;
267 FreeResource32( hMem );
268 return (entry != NULL);
272 /**********************************************************************
273 * CURSORICON_CreateFromResource
275 * Create a cursor or icon from in-memory resource template.
277 * FIXME: Adjust icon size when width and height are nonzero (stretchblt).
278 * Convert to mono when cFlag is LR_MONOCHROME. Do something
279 * with cbSize parameter as well.
281 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE32 hInstance, HGLOBAL16 hObj, LPBYTE bits,
282 UINT32 cbSize, BOOL32 bIcon, DWORD dwVersion,
283 INT32 width, INT32 height, UINT32 cFlag )
285 int sizeAnd, sizeXor;
286 HBITMAP32 hAndBits = 0, hXorBits = 0; /* error condition for later */
287 BITMAPOBJ *bmpXor, *bmpAnd;
288 POINT16 hotspot = { 0 ,0 };
289 BITMAPINFO *bmi;
290 HDC32 hdc;
292 TRACE(cursor,"%08x (%u bytes), ver %08x, %ix%i %s %s\n",
293 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
294 bIcon ? "icon" : "cursor", cFlag ? "mono" : "" );
295 if (dwVersion == 0x00020000)
297 FIXME(cursor,"\t2.xx resources are not supported\n");
298 return 0;
301 if (bIcon)
302 bmi = (BITMAPINFO *)bits;
303 else /* get the hotspot */
305 POINT16 *pt = (POINT16 *)bits;
306 hotspot = *pt;
307 bmi = (BITMAPINFO *)(pt + 1);
310 /* Check bitmap header */
312 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
313 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
314 bmi->bmiHeader.biCompression != BI_RGB) )
316 WARN(cursor,"\tinvalid resource bitmap header.\n");
317 return 0;
320 if( (hdc = GetDC32( 0 )) )
322 BITMAPINFO* pInfo;
323 INT32 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
325 /* Make sure we have room for the monochrome bitmap later on.
326 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
327 * up to and including the biBitCount. In-memory icon resource
328 * format is as follows:
330 * BITMAPINFOHEADER icHeader // DIB header
331 * RGBQUAD icColors[] // Color table
332 * BYTE icXOR[] // DIB bits for XOR mask
333 * BYTE icAND[] // DIB bits for AND mask
336 if( (pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
337 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))) )
339 memcpy( pInfo, bmi, size );
340 pInfo->bmiHeader.biHeight /= 2;
342 /* Create the XOR bitmap */
344 hXorBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader, CBM_INIT,
345 (char*)bmi + size, pInfo, DIB_RGB_COLORS );
346 if( hXorBits )
348 char* bits = (char *)bmi + size + bmi->bmiHeader.biHeight *
349 DIB_GetDIBWidthBytes(bmi->bmiHeader.biWidth,
350 bmi->bmiHeader.biBitCount) / 2;
352 pInfo->bmiHeader.biBitCount = 1;
353 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
355 RGBQUAD *rgb = pInfo->bmiColors;
357 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
358 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
359 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
360 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
362 else
364 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
366 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
367 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
370 /* Create the AND bitmap */
372 hAndBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader, CBM_INIT,
373 bits, pInfo, DIB_RGB_COLORS );
374 if( !hAndBits ) DeleteObject32( hXorBits );
376 HeapFree( GetProcessHeap(), 0, pInfo );
378 ReleaseDC32( 0, hdc );
381 if( !hXorBits || !hAndBits )
383 WARN(cursor,"\tunable to create an icon bitmap.\n");
384 return 0;
387 /* Now create the CURSORICONINFO structure */
389 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
390 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
391 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
392 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
394 if (hObj) hObj = GlobalReAlloc16( hObj,
395 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
396 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
397 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
398 if (hObj)
400 CURSORICONINFO *info;
402 /* Make it owned by the module */
403 if (hInstance) FarSetOwner( hObj, MODULE_HANDLEtoHMODULE16(hInstance));
405 info = (CURSORICONINFO *)GlobalLock16( hObj );
406 info->ptHotSpot.x = hotspot.x;
407 info->ptHotSpot.y = hotspot.y;
408 info->nWidth = bmpXor->bitmap.bmWidth;
409 info->nHeight = bmpXor->bitmap.bmHeight;
410 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
411 info->bPlanes = bmpXor->bitmap.bmPlanes;
412 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
414 /* Transfer the bitmap bits to the CURSORICONINFO structure */
416 GetBitmapBits32( hAndBits, sizeAnd, (char *)(info + 1) );
417 GetBitmapBits32( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
418 GlobalUnlock16( hObj );
421 DeleteObject32( hXorBits );
422 DeleteObject32( hAndBits );
423 return hObj;
427 /**********************************************************************
428 * CreateIconFromResourceEx16 (USER.450)
430 * FIXME: not sure about exact parameter types
432 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
433 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
435 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
436 if( pTask )
437 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
438 width, height, cFlag );
439 return 0;
443 /**********************************************************************
444 * CreateIconFromResource (USER32.???)
445 * FIXME:
446 * bon@elektron.ikp.physik.tu-darmstadt.de 971130: Test with weditres
447 * showed only blank layout. Couldn't determine if this is a problem
448 * with CreateIconFromResource32 or the application. The application
449 * windows behaves strange (no redraw) before CreateIconFromResource32
451 HICON32 WINAPI CreateIconFromResource32( LPBYTE bits, UINT32 cbSize,
452 BOOL32 bIcon, DWORD dwVersion)
454 HICON32 ret;
455 ret = CreateIconFromResourceEx16( bits, cbSize, bIcon, dwVersion, 0,0,0);
456 FIXME(icon,"probably only a stub\n");
457 TRACE(icon, "%s at %p size %d winver %d return 0x%04x\n",
458 (bIcon)?"Icon":"Cursor",bits,cbSize,bIcon,ret);
459 return ret;
463 /**********************************************************************
464 * CreateIconFromResourceEx32 (USER32.76)
466 HICON32 WINAPI CreateIconFromResourceEx32( LPBYTE bits, UINT32 cbSize,
467 BOOL32 bIcon, DWORD dwVersion,
468 INT32 width, INT32 height,
469 UINT32 cFlag )
471 return CreateIconFromResourceEx16( bits, cbSize, bIcon, dwVersion, width, height, cFlag );
475 /**********************************************************************
476 * CURSORICON_Load16
478 * Load a cursor or icon from a 16-bit resource.
480 static HGLOBAL16 CURSORICON_Load16( HINSTANCE16 hInstance, SEGPTR name,
481 INT32 width, INT32 height, INT32 colors,
482 BOOL32 fCursor )
484 HGLOBAL16 handle;
485 HRSRC16 hRsrc;
486 CURSORICONDIRENTRY dirEntry;
488 if (!hInstance) /* OEM cursor/icon */
490 if (HIWORD(name)) /* Check for '#xxx' name */
492 char *ptr = PTR_SEG_TO_LIN( name );
493 if (ptr[0] != '#') return 0;
494 if (!(name = (SEGPTR)atoi( ptr + 1 ))) return 0;
496 return OBM_LoadCursorIcon( LOWORD(name), fCursor );
499 /* Find the best entry in the directory */
501 if ( !CURSORICON_LoadDirEntry16( hInstance, name, width, height,
502 colors, fCursor, &dirEntry ) ) return 0;
503 /* Load the resource */
505 if ( (hRsrc = FindResource16( hInstance,
506 MAKEINTRESOURCE( dirEntry.icon.wResId ),
507 fCursor ? RT_CURSOR : RT_ICON )) )
509 /* 16-bit icon or cursor resources are processed
510 * transparently by the LoadResource16() via custom
511 * resource handlers set by SetResourceHandler().
514 if ( (handle = LoadResource16( hInstance, hRsrc )) )
515 return handle;
517 return 0;
520 /**********************************************************************
521 * CURSORICON_Load32
523 * Load a cursor or icon from a 32-bit resource.
525 static HGLOBAL32 CURSORICON_Load32( HINSTANCE32 hInstance, LPCWSTR name,
526 int width, int height, int colors,
527 BOOL32 fCursor )
529 HANDLE32 handle;
530 HANDLE32 hRsrc;
531 CURSORICONDIRENTRY dirEntry;
533 if(!hInstance) /* OEM cursor/icon */
535 WORD resid;
536 if(HIWORD(name))
538 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
539 if( ansi[0]=='#') /*Check for '#xxx' name */
541 resid = atoi(ansi+1);
542 HeapFree( GetProcessHeap(), 0, ansi );
544 else
546 HeapFree( GetProcessHeap(), 0, ansi );
547 return 0;
550 else resid = LOWORD(name);
551 return OBM_LoadCursorIcon(resid, fCursor);
554 /* Find the best entry in the directory */
556 if ( !CURSORICON_LoadDirEntry32( hInstance, name, width, height,
557 colors, fCursor, &dirEntry ) ) return 0;
558 /* Load the resource */
560 if ( (hRsrc = FindResource32W( hInstance,
561 (LPWSTR) (DWORD) dirEntry.icon.wResId,
562 (LPWSTR) (fCursor ? RT_CURSOR : RT_ICON ))) )
564 HANDLE32 h = 0;
565 if ( (handle = LoadResource32( hInstance, hRsrc )) )
567 /* Hack to keep LoadCursor/Icon32() from spawning multiple
568 * copies of the same object.
570 #define pRsrcEntry ((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)
571 if( !pRsrcEntry->ResourceHandle )
573 LPBYTE bits = (LPBYTE)LockResource32( handle );
574 h = CURSORICON_CreateFromResource( hInstance, 0, bits, dirEntry.icon.dwBytesInRes,
575 !fCursor, 0x00030000, width, height, LR_DEFAULTCOLOR );
576 pRsrcEntry->ResourceHandle = h;
578 else h = pRsrcEntry->ResourceHandle;
579 #undef pRsrcEntry
581 return h;
583 return 0;
587 /***********************************************************************
588 * CURSORICON_Copy
590 * Make a copy of a cursor or icon.
592 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
594 char *ptrOld, *ptrNew;
595 int size;
596 HGLOBAL16 hNew;
598 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
599 if (!(hInstance = GetExePtr( hInstance ))) return 0;
600 size = GlobalSize16( handle );
601 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
602 FarSetOwner( hNew, hInstance );
603 ptrNew = (char *)GlobalLock16( hNew );
604 memcpy( ptrNew, ptrOld, size );
605 GlobalUnlock16( handle );
606 GlobalUnlock16( hNew );
607 return hNew;
610 /***********************************************************************
611 * CURSORICON_IconToCursor
613 * Converts bitmap to mono and truncates if icon is too large (should
614 * probably do StretchBlt() instead).
616 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL32 bSemiTransparent)
618 HCURSOR16 hRet = 0;
619 CURSORICONINFO *pIcon = NULL;
620 HTASK16 hTask = GetCurrentTask();
621 TDB* pTask = (TDB *)GlobalLock16(hTask);
623 if(hIcon && pTask)
624 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
625 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
626 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
627 else
629 BYTE pAndBits[128];
630 BYTE pXorBits[128];
631 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
632 BYTE* psPtr, *pxbPtr = pXorBits;
633 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
634 BYTE* pbc = NULL;
636 COLORREF col;
637 CURSORICONINFO cI;
639 TRACE(icon, "[%04x] %ix%i %ibpp (bogus %ibps)\n",
640 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
642 xor_width = BITMAP_GetBitsWidth( pIcon->nWidth, bpp );
643 and_width = BITMAP_GetBitsWidth( pIcon->nWidth, 1 );
644 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
646 memset(pXorBits, 0, 128);
647 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
648 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
649 cI.nWidth = 32; cI.nHeight = 32;
650 cI.nWidthBytes = 4; /* 32x1bpp */
652 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
653 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
655 for( iy = 0; iy < maxy; iy++ )
657 unsigned shift = iy % 2;
659 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
660 (and_width > 4) ? 4 : and_width );
661 for( ix = 0; ix < maxx; ix++ )
663 if( bSemiTransparent && ((ix+shift)%2) )
665 /* set AND bit, XOR bit stays 0 */
667 pbc = pAndBits + iy * 4 + ix/8;
668 *pbc |= 0x80 >> (ix%8);
670 else
672 /* keep AND bit, set XOR bit */
674 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
675 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
676 col = COLOR_ToLogical(val);
677 if( (GetRValue(col) + GetGValue(col) + GetBValue(col)) > 0x180 )
679 pbc = pxbPtr + ix/8;
680 *pbc |= 0x80 >> (ix%8);
684 psPtr += xor_width;
685 pxbPtr += 4;
688 hRet = CreateCursorIconIndirect( pTask->hInstance , &cI, pAndBits, pXorBits);
690 if( !hRet ) /* fall back on default drag cursor */
691 hRet = CURSORICON_Copy( pTask->hInstance ,
692 CURSORICON_Load16(0,MAKEINTRESOURCE(OCR_DRAGOBJECT),
693 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE) );
696 return hRet;
700 /***********************************************************************
701 * LoadCursor16 (USER.173)
703 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
705 if (HIWORD(name))
706 TRACE(cursor, "%04x '%s'\n",
707 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
708 else
709 TRACE(cursor, "%04x %04x\n",
710 hInstance, LOWORD(name) );
712 return CURSORICON_Load16( hInstance, name,
713 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
717 /***********************************************************************
718 * LoadIcon16 (USER.174)
720 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
722 if (HIWORD(name))
723 TRACE(icon, "%04x '%s'\n",
724 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
725 else
726 TRACE(icon, "%04x %04x\n",
727 hInstance, LOWORD(name) );
729 return CURSORICON_Load16( hInstance, name,
730 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
731 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE );
735 /***********************************************************************
736 * CreateCursor16 (USER.406)
738 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
739 INT16 xHotSpot, INT16 yHotSpot,
740 INT16 nWidth, INT16 nHeight,
741 LPCVOID lpANDbits, LPCVOID lpXORbits )
743 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
745 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
746 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
747 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
751 /***********************************************************************
752 * CreateCursor32 (USER32.66)
754 HCURSOR32 WINAPI CreateCursor32( HINSTANCE32 hInstance,
755 INT32 xHotSpot, INT32 yHotSpot,
756 INT32 nWidth, INT32 nHeight,
757 LPCVOID lpANDbits, LPCVOID lpXORbits )
759 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
761 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
762 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
763 return CreateCursorIconIndirect( MODULE_HANDLEtoHMODULE16( hInstance ),
764 &info, lpANDbits, lpXORbits );
768 /***********************************************************************
769 * CreateIcon16 (USER.407)
771 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
772 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
773 LPCVOID lpANDbits, LPCVOID lpXORbits )
775 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
777 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
778 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
779 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
783 /***********************************************************************
784 * CreateIcon32 (USER32.74)
786 HICON32 WINAPI CreateIcon32( HINSTANCE32 hInstance, INT32 nWidth,
787 INT32 nHeight, BYTE bPlanes, BYTE bBitsPixel,
788 LPCVOID lpANDbits, LPCVOID lpXORbits )
790 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
792 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
793 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
794 return CreateCursorIconIndirect( MODULE_HANDLEtoHMODULE16( hInstance ),
795 &info, lpANDbits, lpXORbits );
799 /***********************************************************************
800 * CreateCursorIconIndirect (USER.408)
802 HGLOBAL16 WINAPI CreateCursorIconIndirect( HINSTANCE16 hInstance,
803 CURSORICONINFO *info,
804 LPCVOID lpANDbits,
805 LPCVOID lpXORbits )
807 HGLOBAL16 handle;
808 char *ptr;
809 int sizeAnd, sizeXor;
811 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
812 if (!hInstance || !lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
813 info->nWidthBytes = BITMAP_WIDTH_BYTES(info->nWidth,info->bBitsPerPixel);
814 sizeXor = info->nHeight * info->nWidthBytes;
815 sizeAnd = info->nHeight * BITMAP_WIDTH_BYTES( info->nWidth, 1 );
816 if (!(handle = DirectResAlloc(hInstance, 0x10,
817 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
818 return 0;
819 ptr = (char *)GlobalLock16( handle );
820 memcpy( ptr, info, sizeof(*info) );
821 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
822 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
823 GlobalUnlock16( handle );
824 return handle;
828 /***********************************************************************
829 * CopyIcon16 (USER.368)
831 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
833 TRACE(icon, "%04x %04x\n", hInstance, hIcon );
834 return CURSORICON_Copy( hInstance, hIcon );
838 /***********************************************************************
839 * CopyIcon32 (USER32.59)
841 HICON32 WINAPI CopyIcon32( HICON32 hIcon )
843 HTASK16 hTask = GetCurrentTask ();
844 TDB* pTask = (TDB *) GlobalLock16 (hTask);
845 TRACE(icon, "%04x\n", hIcon );
846 return CURSORICON_Copy( pTask->hInstance, hIcon );
850 /***********************************************************************
851 * CopyCursor16 (USER.369)
853 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
855 TRACE(cursor, "%04x %04x\n", hInstance, hCursor );
856 return CURSORICON_Copy( hInstance, hCursor );
860 /***********************************************************************
861 * DestroyIcon16 (USER.457)
863 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
865 return DestroyIcon32( hIcon );
869 /***********************************************************************
870 * DestroyIcon32 (USER32.132)
872 BOOL32 WINAPI DestroyIcon32( HICON32 hIcon )
874 TRACE(icon, "%04x\n", hIcon );
875 /* FIXME: should check for OEM icon here */
876 return (FreeResource16( hIcon ) == 0);
880 /***********************************************************************
881 * DestroyCursor16 (USER.458)
883 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
885 return DestroyCursor32( hCursor );
889 /***********************************************************************
890 * DestroyCursor32 (USER32.131)
892 BOOL32 WINAPI DestroyCursor32( HCURSOR32 hCursor )
894 TRACE(cursor, "%04x\n", hCursor );
895 /* FIXME: should check for OEM cursor here */
896 return (FreeResource16( hCursor ) == 0);
900 /***********************************************************************
901 * DrawIcon16 (USER.84)
903 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
905 return DrawIcon32( hdc, x, y, hIcon );
909 /***********************************************************************
910 * DrawIcon32 (USER32.158)
912 BOOL32 WINAPI DrawIcon32( HDC32 hdc, INT32 x, INT32 y, HICON32 hIcon )
914 CURSORICONINFO *ptr;
915 HDC32 hMemDC;
916 HBITMAP32 hXorBits, hAndBits;
917 COLORREF oldFg, oldBg;
919 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
920 if (!(hMemDC = CreateCompatibleDC32( hdc ))) return FALSE;
921 hAndBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, 1, 1,
922 (char *)(ptr+1) );
923 hXorBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
924 ptr->bBitsPerPixel, (char *)(ptr + 1)
925 + ptr->nHeight * BITMAP_WIDTH_BYTES(ptr->nWidth,1) );
926 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
927 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
929 if (hXorBits && hAndBits)
931 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
932 BitBlt32( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
933 SelectObject32( hMemDC, hXorBits );
934 BitBlt32(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
935 SelectObject32( hMemDC, hBitTemp );
937 DeleteDC32( hMemDC );
938 if (hXorBits) DeleteObject32( hXorBits );
939 if (hAndBits) DeleteObject32( hAndBits );
940 GlobalUnlock16( hIcon );
941 SetTextColor32( hdc, oldFg );
942 SetBkColor32( hdc, oldBg );
943 return TRUE;
947 /***********************************************************************
948 * DumpIcon (USER.459)
950 DWORD WINAPI DumpIcon( SEGPTR pInfo, WORD *lpLen,
951 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
953 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
954 int sizeAnd, sizeXor;
956 if (!info) return 0;
957 sizeXor = info->nHeight * info->nWidthBytes;
958 sizeAnd = info->nHeight * BITMAP_WIDTH_BYTES( info->nWidth, 1 );
959 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
960 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
961 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
962 return MAKELONG( sizeXor, sizeXor );
966 /***********************************************************************
967 * CURSORICON_SetCursor
969 * Change the X cursor. Helper function for SetCursor() and ShowCursor().
970 * The Xlib critical section must be entered before calling this function.
972 static BOOL32 CURSORICON_SetCursor( HCURSOR16 hCursor )
974 Pixmap pixmapBits, pixmapMask, pixmapAll;
975 XColor fg, bg;
976 Cursor cursor = None;
978 if (!hCursor) /* Create an empty cursor */
980 static const char data[] = { 0 };
982 bg.red = bg.green = bg.blue = 0x0000;
983 pixmapBits = XCreateBitmapFromData( display, rootWindow, data, 1, 1 );
984 if (pixmapBits)
986 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapBits,
987 &bg, &bg, 0, 0 );
988 XFreePixmap( display, pixmapBits );
991 else /* Create the X cursor from the bits */
993 CURSORICONINFO *ptr;
994 XImage *image;
996 if (!(ptr = (CURSORICONINFO*)GlobalLock16( hCursor ))) return FALSE;
997 if (ptr->bPlanes * ptr->bBitsPerPixel != 1)
999 WARN(cursor, "Cursor %04x has more than 1 bpp!\n", hCursor );
1000 return FALSE;
1003 /* Create a pixmap and transfer all the bits to it */
1005 /* NOTE: Following hack works, but only because XFree depth
1006 * 1 images really use 1 bit/pixel (and so the same layout
1007 * as the Windows cursor data). Perhaps use a more generic
1008 * algorithm here.
1010 pixmapAll = XCreatePixmap( display, rootWindow,
1011 ptr->nWidth, ptr->nHeight * 2, 1 );
1012 image = XCreateImage( display, DefaultVisualOfScreen(screen),
1013 1, ZPixmap, 0, (char *)(ptr + 1), ptr->nWidth,
1014 ptr->nHeight * 2, 16, ptr->nWidthBytes);
1015 if (image)
1017 image->byte_order = MSBFirst;
1018 image->bitmap_bit_order = MSBFirst;
1019 image->bitmap_unit = 16;
1020 _XInitImageFuncPtrs(image);
1021 if (pixmapAll)
1022 XPutImage( display, pixmapAll, BITMAP_monoGC, image,
1023 0, 0, 0, 0, ptr->nWidth, ptr->nHeight * 2 );
1024 image->data = NULL;
1025 XDestroyImage( image );
1028 /* Now create the 2 pixmaps for bits and mask */
1030 pixmapBits = XCreatePixmap( display, rootWindow,
1031 ptr->nWidth, ptr->nHeight, 1 );
1032 pixmapMask = XCreatePixmap( display, rootWindow,
1033 ptr->nWidth, ptr->nHeight, 1 );
1035 /* Make sure everything went OK so far */
1037 if (pixmapBits && pixmapMask && pixmapAll)
1039 /* We have to do some magic here, as cursors are not fully
1040 * compatible between Windows and X11. Under X11, there
1041 * are only 3 possible color cursor: black, white and
1042 * masked. So we map the 4th Windows color (invert the
1043 * bits on the screen) to black. This require some boolean
1044 * arithmetic:
1046 * Windows | X11
1047 * Xor And Result | Bits Mask Result
1048 * 0 0 black | 0 1 background
1049 * 0 1 no change | X 0 no change
1050 * 1 0 white | 1 1 foreground
1051 * 1 1 inverted | 0 1 background
1053 * which gives:
1054 * Bits = 'Xor' and not 'And'
1055 * Mask = 'Xor' or not 'And'
1057 * FIXME: apparently some servers do support 'inverted' color.
1058 * I don't know if it's correct per the X spec, but maybe
1059 * we ought to take advantage of it. -- AJ
1061 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
1062 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
1063 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
1064 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
1065 XSetFunction( display, BITMAP_monoGC, GXandReverse );
1066 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
1067 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
1068 XSetFunction( display, BITMAP_monoGC, GXorReverse );
1069 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
1070 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
1071 XSetFunction( display, BITMAP_monoGC, GXcopy );
1072 fg.red = fg.green = fg.blue = 0xffff;
1073 bg.red = bg.green = bg.blue = 0x0000;
1074 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapMask,
1075 &fg, &bg, ptr->ptHotSpot.x, ptr->ptHotSpot.y );
1078 /* Now free everything */
1080 if (pixmapAll) XFreePixmap( display, pixmapAll );
1081 if (pixmapBits) XFreePixmap( display, pixmapBits );
1082 if (pixmapMask) XFreePixmap( display, pixmapMask );
1083 GlobalUnlock16( hCursor );
1086 if (cursor == None) return FALSE;
1087 if (CURSORICON_XCursor != None) XFreeCursor( display, CURSORICON_XCursor );
1088 CURSORICON_XCursor = cursor;
1090 if (rootWindow != DefaultRootWindow(display))
1092 /* Set the cursor on the desktop window */
1093 XDefineCursor( display, rootWindow, cursor );
1095 else
1097 /* Set the same cursor for all top-level windows */
1098 HWND32 hwnd = GetWindow32( GetDesktopWindow32(), GW_CHILD );
1099 while(hwnd)
1101 Window win = WIN_GetXWindow( hwnd );
1102 if (win) XDefineCursor( display, win, cursor );
1103 hwnd = GetWindow32( hwnd, GW_HWNDNEXT );
1106 return TRUE;
1110 /***********************************************************************
1111 * SetCursor16 (USER.69)
1113 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1115 return (HCURSOR16)SetCursor32( hCursor );
1119 /***********************************************************************
1120 * SetCursor32 (USER32.471)
1121 * RETURNS:
1122 * A handle to the previous cursor shape.
1124 HCURSOR32 WINAPI SetCursor32(
1125 HCURSOR32 hCursor /* Handle of cursor to show */
1127 HCURSOR32 hOldCursor;
1129 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1130 TRACE(cursor, "%04x\n", hCursor );
1131 hOldCursor = hActiveCursor;
1132 hActiveCursor = hCursor;
1133 /* Change the cursor shape only if it is visible */
1134 if (CURSOR_ShowCount >= 0)
1136 EnterCriticalSection( &X11DRV_CritSection );
1137 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1138 LeaveCriticalSection( &X11DRV_CritSection );
1140 return hOldCursor;
1144 /***********************************************************************
1145 * SetCursorPos16 (USER.70)
1147 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1149 SetCursorPos32( x, y );
1153 /***********************************************************************
1154 * SetCursorPos32 (USER32.473)
1156 BOOL32 WINAPI SetCursorPos32( INT32 x, INT32 y )
1158 TRACE(cursor, "x=%d y=%d\n", x, y );
1159 TSXWarpPointer( display, rootWindow, rootWindow, 0, 0, 0, 0, x, y );
1160 return TRUE;
1164 /***********************************************************************
1165 * ShowCursor16 (USER.71)
1167 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1169 return ShowCursor32( bShow );
1173 /***********************************************************************
1174 * ShowCursor32 (USER32.529)
1176 INT32 WINAPI ShowCursor32( BOOL32 bShow )
1178 TRACE(cursor, "%d, count=%d\n",
1179 bShow, CURSOR_ShowCount );
1181 EnterCriticalSection( &X11DRV_CritSection );
1182 if (bShow)
1184 if (++CURSOR_ShowCount == 0) /* Show it */
1185 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1187 else
1189 if (--CURSOR_ShowCount == -1) /* Hide it */
1190 CALL_LARGE_STACK( CURSORICON_SetCursor, 0 );
1192 LeaveCriticalSection( &X11DRV_CritSection );
1193 return CURSOR_ShowCount;
1197 /***********************************************************************
1198 * GetCursor16 (USER.247)
1200 HCURSOR16 WINAPI GetCursor16(void)
1202 return hActiveCursor;
1206 /***********************************************************************
1207 * GetCursor32 (USER32.226)
1209 HCURSOR32 WINAPI GetCursor32(void)
1211 return hActiveCursor;
1215 /***********************************************************************
1216 * ClipCursor16 (USER.16)
1218 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1220 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1221 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1222 return TRUE;
1226 /***********************************************************************
1227 * ClipCursor32 (USER32.52)
1229 BOOL32 WINAPI ClipCursor32( const RECT32 *rect )
1231 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1232 else CopyRect32( &CURSOR_ClipRect, rect );
1233 return TRUE;
1237 /***********************************************************************
1238 * GetCursorPos16 (USER.17)
1240 void WINAPI GetCursorPos16( POINT16 *pt )
1242 Window root, child;
1243 int rootX, rootY, childX, childY;
1244 unsigned int mousebut;
1246 if (!pt) return;
1247 if (!TSXQueryPointer( display, rootWindow, &root, &child,
1248 &rootX, &rootY, &childX, &childY, &mousebut ))
1249 pt->x = pt->y = 0;
1250 else
1252 pt->x = childX;
1253 pt->y = childY;
1254 if (mousebut & Button1Mask)
1255 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1256 else
1257 MouseButtonsStates[0] = FALSE;
1258 if (mousebut & Button2Mask)
1259 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1260 else
1261 MouseButtonsStates[1] = FALSE;
1262 if (mousebut & Button3Mask)
1263 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1264 else
1265 MouseButtonsStates[2] = FALSE;
1267 TRACE(cursor, "ret=%d,%d\n", pt->x, pt->y );
1271 /***********************************************************************
1272 * GetCursorPos32 (USER32.228)
1274 void WINAPI GetCursorPos32( POINT32 *pt )
1276 POINT16 pt16;
1277 GetCursorPos16( &pt16 );
1278 if (pt) CONV_POINT16TO32( &pt16, pt );
1282 /***********************************************************************
1283 * GetClipCursor16 (USER.309)
1285 void WINAPI GetClipCursor16( RECT16 *rect )
1287 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1291 /***********************************************************************
1292 * GetClipCursor32 (USER32.220)
1294 void WINAPI GetClipCursor32( RECT32 *rect )
1296 if (rect) CopyRect32( rect, &CURSOR_ClipRect );
1299 /**********************************************************************
1300 * LookupIconIdFromDirectoryEx16 (USER.364)
1302 * FIXME: exact parameter sizes
1304 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1305 INT16 width, INT16 height, UINT16 cFlag )
1307 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1308 UINT16 retVal = 0;
1309 if( dir && !dir->idReserved && (dir->idType & 3) )
1311 int colors = (cFlag == LR_MONOCHROME) ? 2 : COLOR_GetSystemPaletteSize();
1312 if( bIcon )
1314 ICONDIRENTRY* entry;
1315 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1316 if( entry ) retVal = entry->wResId;
1318 else
1320 CURSORDIRENTRY* entry;
1321 entry = CURSORICON_FindBestCursor( dir, width, height );
1322 if( entry ) retVal = entry->wResId;
1325 else WARN(cursor, "invalid resource directory\n");
1326 return retVal;
1329 /**********************************************************************
1330 * LookupIconIdFromDirectoryEx32 (USER32.379)
1332 INT32 WINAPI LookupIconIdFromDirectoryEx32( LPBYTE dir, BOOL32 bIcon,
1333 INT32 width, INT32 height, UINT32 cFlag )
1335 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1338 /**********************************************************************
1339 * LookupIconIdFromDirectory (USER.???)
1341 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1343 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1344 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1345 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1348 /**********************************************************************
1349 * LookupIconIdFromDirectory (USER32.378)
1351 INT32 WINAPI LookupIconIdFromDirectory32( LPBYTE dir, BOOL32 bIcon )
1353 return LookupIconIdFromDirectoryEx32( dir, bIcon,
1354 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1355 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1358 /**********************************************************************
1359 * GetIconID (USER.455)
1361 WORD WINAPI GetIconID( HGLOBAL16 hResource, DWORD resType )
1363 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1365 TRACE(cursor, "hRes=%04x, entries=%i\n",
1366 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1368 switch(resType)
1370 case RT_CURSOR:
1371 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1372 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1373 case RT_ICON:
1374 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1375 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1376 default:
1377 WARN(cursor, "invalid res type %ld\n", resType );
1379 return 0;
1382 /**********************************************************************
1383 * LoadCursorIconHandler (USER.336)
1385 * Supposed to load resources of Windows 2.x applications.
1387 HGLOBAL16 WINAPI LoadCursorIconHandler( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1389 FIXME(cursor,"(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1390 hResource, hModule, hRsrc);
1391 return (HGLOBAL16)0;
1394 /**********************************************************************
1395 * LoadDIBIconHandler (USER.357)
1397 * RT_ICON resource loader, installed by USER_SignalProc when module
1398 * is initialized.
1400 HGLOBAL16 WINAPI LoadDIBIconHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1402 /* If hResource is zero we must allocate a new memory block, if it's
1403 * non-zero but GlobalLock() returns NULL then it was discarded and
1404 * we have to recommit some memory, otherwise we just need to check
1405 * the block size. See LoadProc() in 16-bit SDK for more.
1408 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1409 if( hMemObj )
1411 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1412 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1413 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1414 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1416 return hMemObj;
1419 /**********************************************************************
1420 * LoadDIBCursorHandler (USER.356)
1422 * RT_CURSOR resource loader. Same as above.
1424 HGLOBAL16 WINAPI LoadDIBCursorHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1426 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1427 if( hMemObj )
1429 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1430 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1431 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1432 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1434 return hMemObj;
1437 /**********************************************************************
1438 * LoadIconHandler (USER.456)
1440 HICON16 WINAPI LoadIconHandler( HGLOBAL16 hResource, BOOL16 bNew )
1442 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1444 TRACE(cursor,"hRes=%04x\n",hResource);
1446 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1447 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1450 /***********************************************************************
1451 * LoadCursorW (USER32.361)
1453 HCURSOR32 WINAPI LoadCursor32W(HINSTANCE32 hInstance, LPCWSTR name)
1455 return CURSORICON_Load32( hInstance, name,
1456 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
1459 /***********************************************************************
1460 * LoadCursorA (USER32.358)
1462 HCURSOR32 WINAPI LoadCursor32A(HINSTANCE32 hInstance, LPCSTR name)
1464 HCURSOR32 res=0;
1465 if(!HIWORD(name))
1466 return LoadCursor32W(hInstance,(LPCWSTR)name);
1467 else
1469 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1470 res = LoadCursor32W(hInstance, uni);
1471 HeapFree( GetProcessHeap(), 0, uni);
1473 return res;
1476 /***********************************************************************
1477 * LoadIconW (USER32.363)
1479 HICON32 WINAPI LoadIcon32W(HINSTANCE32 hInstance, LPCWSTR name)
1481 return CURSORICON_Load32( hInstance, name,
1482 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
1483 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE );
1486 /***********************************************************************
1487 * LoadIconA (USER32.362)
1489 HICON32 WINAPI LoadIcon32A(HINSTANCE32 hInstance, LPCSTR name)
1491 HICON32 res=0;
1493 if( !HIWORD(name) )
1494 return LoadIcon32W(hInstance, (LPCWSTR)name);
1495 else
1497 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1498 res = LoadIcon32W( hInstance, uni );
1499 HeapFree( GetProcessHeap(), 0, uni );
1501 return res;
1504 /**********************************************************************
1505 * GetIconInfo (USER32.241)
1507 BOOL32 WINAPI GetIconInfo(HICON32 hIcon,LPICONINFO iconinfo) {
1508 CURSORICONINFO *ciconinfo;
1510 ciconinfo = GlobalLock16(hIcon);
1511 if (!ciconinfo)
1512 return FALSE;
1513 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1514 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1515 iconinfo->fIcon = TRUE; /* hmm */
1516 /* FIXME ... add both bitmaps */
1517 return TRUE;
1520 /**********************************************************************
1521 * CreateIconIndirect (USER32.78)
1523 HICON32 WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1524 BITMAPOBJ *bmpXor,*bmpAnd;
1525 HICON32 hObj;
1526 int sizeXor,sizeAnd;
1528 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1529 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1531 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1532 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1534 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1535 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1536 if (hObj)
1538 CURSORICONINFO *info;
1540 info = (CURSORICONINFO *)GlobalLock16( hObj );
1541 info->ptHotSpot.x = iconinfo->xHotspot;
1542 info->ptHotSpot.y = iconinfo->yHotspot;
1543 info->nWidth = bmpXor->bitmap.bmWidth;
1544 info->nHeight = bmpXor->bitmap.bmHeight;
1545 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1546 info->bPlanes = bmpXor->bitmap.bmPlanes;
1547 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1549 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1551 GetBitmapBits32( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1552 GetBitmapBits32( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1553 GlobalUnlock16( hObj );
1555 return hObj;
1558 /**********************************************************************
1559 * DrawIconEx16 (USER.394)
1562 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1563 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1564 HBRUSH16 hbr, UINT16 flags)
1566 return DrawIconEx32 (hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1567 istep, hbr, flags);
1570 /**********************************************************************
1571 * DrawIconEx32 (USER32.160)
1574 BOOL32 WINAPI DrawIconEx32 (HDC32 hdc, INT32 x0, INT32 y0, HICON32 hIcon,
1575 INT32 cxWidth, INT32 cyWidth, UINT32 istep,
1576 HBRUSH32 hbr, UINT32 flags)
1578 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1579 HDC32 hMemDC = CreateCompatibleDC32 (hdc);
1580 BOOL32 result = FALSE;
1582 FIXME(icon, "part stub.\n");
1584 if (hMemDC && ptr)
1586 HBITMAP32 hXorBits, hAndBits;
1587 COLORREF oldFg, oldBg;
1589 /* Calculate the size of the destination image. */
1590 if (cxWidth == 0)
1591 if (flags & DI_DEFAULTSIZE)
1592 cxWidth = GetSystemMetrics32 (SM_CXICON);
1593 else
1594 cxWidth = ptr->nWidth;
1595 if (cyWidth == 0)
1596 if (flags & DI_DEFAULTSIZE)
1597 cyWidth = GetSystemMetrics32 (SM_CYICON);
1598 else
1599 cyWidth = ptr->nHeight;
1601 hXorBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
1602 ptr->bPlanes, ptr->bBitsPerPixel,
1603 (char *)(ptr + 1)
1604 + ptr->nHeight *
1605 BITMAP_WIDTH_BYTES(ptr->nWidth,1) );
1606 hAndBits = CreateBitmap32 ( cxWidth, cyWidth,
1607 1, 1, (char *)(ptr+1) );
1608 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
1609 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
1611 if (hXorBits && hAndBits)
1613 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
1614 if (flags & DI_MASK)
1615 BitBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1616 hMemDC, 0, 0, SRCAND);
1617 SelectObject32( hMemDC, hXorBits );
1618 if (flags & DI_IMAGE)
1619 BitBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1620 hMemDC, 0, 0, SRCPAINT);
1621 SelectObject32( hMemDC, hBitTemp );
1622 result = TRUE;
1625 SetTextColor32( hdc, oldFg );
1626 SetBkColor32( hdc, oldBg );
1627 if (hXorBits) DeleteObject32( hXorBits );
1628 if (hAndBits) DeleteObject32( hAndBits );
1630 if (hMemDC) DeleteDC32( hMemDC );
1631 GlobalUnlock16( hIcon );
1632 return result;