Release 980601
[wine.git] / objects / cursoricon.c
blob439660f8adc264dc1e48f61ecdecdbd6c04142ac
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"
45 #include "x11drv.h"
47 Cursor CURSORICON_XCursor = None; /* Current X cursor */
48 static HCURSOR32 hActiveCursor = 0; /* Active cursor */
49 static INT32 CURSOR_ShowCount = 0; /* Cursor display count */
50 static RECT32 CURSOR_ClipRect; /* Cursor clipping rect */
52 /**********************************************************************
53 * CURSORICON_FindBestIcon
55 * Find the icon closest to the requested size and number of colors.
57 static ICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
58 int height, int colors )
60 int i, maxcolors, maxwidth, maxheight;
61 ICONDIRENTRY *entry, *bestEntry = NULL;
63 if (dir->idCount < 1)
65 WARN(icon, "Empty directory!\n" );
66 return NULL;
68 if (dir->idCount == 1) return &dir->idEntries[0].icon; /* No choice... */
70 /* First find the exact size with less colors */
72 maxcolors = 0;
73 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
74 if ((entry->bWidth == width) && (entry->bHeight == height) &&
75 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
77 bestEntry = entry;
78 maxcolors = entry->bColorCount;
80 if (bestEntry) return bestEntry;
82 /* First find the exact size with more colors */
84 maxcolors = 255;
85 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
86 if ((entry->bWidth == width) && (entry->bHeight == height) &&
87 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
89 bestEntry = entry;
90 maxcolors = entry->bColorCount;
92 if (bestEntry) return bestEntry;
94 /* Now find a smaller one with less colors */
96 maxcolors = maxwidth = maxheight = 0;
97 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
98 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
99 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
100 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
102 bestEntry = entry;
103 maxwidth = entry->bWidth;
104 maxheight = entry->bHeight;
105 maxcolors = entry->bColorCount;
107 if (bestEntry) return bestEntry;
109 /* Now find a smaller one with more colors */
111 maxcolors = 255;
112 maxwidth = maxheight = 0;
113 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
114 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
115 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
116 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
118 bestEntry = entry;
119 maxwidth = entry->bWidth;
120 maxheight = entry->bHeight;
121 maxcolors = entry->bColorCount;
123 if (bestEntry) return bestEntry;
125 /* Now find a larger one with less colors */
127 maxcolors = 0;
128 maxwidth = maxheight = 255;
129 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
130 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
131 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
133 bestEntry = entry;
134 maxwidth = entry->bWidth;
135 maxheight = entry->bHeight;
136 maxcolors = entry->bColorCount;
138 if (bestEntry) return bestEntry;
140 /* Now find a larger one with more colors */
142 maxcolors = maxwidth = maxheight = 255;
143 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
144 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
145 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
147 bestEntry = entry;
148 maxwidth = entry->bWidth;
149 maxheight = entry->bHeight;
150 maxcolors = entry->bColorCount;
153 return bestEntry;
157 /**********************************************************************
158 * CURSORICON_FindBestCursor
160 * Find the cursor closest to the requested size.
162 static CURSORDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
163 int width, int height )
165 int i, maxwidth, maxheight;
166 CURSORDIRENTRY *entry, *bestEntry = NULL;
168 if (dir->idCount < 1)
170 WARN(cursor, "Empty directory!\n" );
171 return NULL;
173 if (dir->idCount == 1) return &dir->idEntries[0].cursor; /* No choice... */
175 /* First find the largest one smaller than or equal to the requested size*/
177 maxwidth = maxheight = 0;
178 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
179 if ((entry->wWidth <= width) && (entry->wHeight <= height) &&
180 (entry->wWidth > maxwidth) && (entry->wHeight > maxheight))
182 bestEntry = entry;
183 maxwidth = entry->wWidth;
184 maxheight = entry->wHeight;
186 if (bestEntry) return bestEntry;
188 /* Now find the smallest one larger than the requested size */
190 maxwidth = maxheight = 255;
191 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
192 if ((entry->wWidth < maxwidth) && (entry->wHeight < maxheight))
194 bestEntry = entry;
195 maxwidth = entry->wWidth;
196 maxheight = entry->wHeight;
199 return bestEntry;
203 /**********************************************************************
204 * CURSORICON_LoadDirEntry16
206 * Load the icon/cursor directory for a given resource name and find the
207 * best matching entry.
209 static BOOL32 CURSORICON_LoadDirEntry16( HINSTANCE32 hInstance, SEGPTR name,
210 INT32 width, INT32 height, INT32 colors,
211 BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
213 HRSRC16 hRsrc;
214 HGLOBAL16 hMem;
215 CURSORICONDIR *dir;
216 CURSORICONDIRENTRY *entry = NULL;
218 if (!(hRsrc = FindResource16( hInstance, name,
219 fCursor ? RT_GROUP_CURSOR16 : RT_GROUP_ICON16 )))
220 return FALSE;
221 if (!(hMem = LoadResource16( hInstance, hRsrc ))) return FALSE;
222 if ((dir = (CURSORICONDIR *)LockResource16( hMem )))
224 if (fCursor)
225 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
226 width, height );
227 else
228 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
229 width, height, colors );
230 if (entry) *dirEntry = *entry;
232 FreeResource16( hMem );
233 return (entry != NULL);
237 /**********************************************************************
238 * CURSORICON_LoadDirEntry32
240 * Load the icon/cursor directory for a given resource name and find the
241 * best matching entry.
243 static BOOL32 CURSORICON_LoadDirEntry32( HINSTANCE32 hInstance, LPCWSTR name,
244 INT32 width, INT32 height, INT32 colors,
245 BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
247 HANDLE32 hRsrc;
248 HANDLE32 hMem;
249 CURSORICONDIR *dir;
250 CURSORICONDIRENTRY *entry = NULL;
252 if (!(hRsrc = FindResource32W( hInstance, name,
253 fCursor ? RT_GROUP_CURSOR32W : RT_GROUP_ICON32W )))
254 return FALSE;
255 if (!(hMem = LoadResource32( hInstance, hRsrc ))) return FALSE;
256 if ((dir = (CURSORICONDIR*)LockResource32( hMem )))
258 if (fCursor)
259 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
260 width, height );
261 else
262 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
263 width, height, colors );
264 if (entry) *dirEntry = *entry;
266 FreeResource32( hMem );
267 return (entry != NULL);
271 /**********************************************************************
272 * CURSORICON_CreateFromResource
274 * Create a cursor or icon from in-memory resource template.
276 * FIXME: Adjust icon size when width and height are nonzero (stretchblt).
277 * Convert to mono when cFlag is LR_MONOCHROME. Do something
278 * with cbSize parameter as well.
280 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
281 UINT32 cbSize, BOOL32 bIcon, DWORD dwVersion,
282 INT32 width, INT32 height, UINT32 cFlag )
284 int sizeAnd, sizeXor;
285 HBITMAP32 hAndBits = 0, hXorBits = 0; /* error condition for later */
286 BITMAPOBJ *bmpXor, *bmpAnd;
287 POINT16 hotspot = { 0 ,0 };
288 BITMAPINFO *bmi;
289 HDC32 hdc;
291 TRACE(cursor,"%08x (%u bytes), ver %08x, %ix%i %s %s\n",
292 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
293 bIcon ? "icon" : "cursor", cFlag ? "mono" : "" );
294 if (dwVersion == 0x00020000)
296 FIXME(cursor,"\t2.xx resources are not supported\n");
297 return 0;
300 if (bIcon)
301 bmi = (BITMAPINFO *)bits;
302 else /* get the hotspot */
304 POINT16 *pt = (POINT16 *)bits;
305 hotspot = *pt;
306 bmi = (BITMAPINFO *)(pt + 1);
309 /* Check bitmap header */
311 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
312 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
313 bmi->bmiHeader.biCompression != BI_RGB) )
315 WARN(cursor,"\tinvalid resource bitmap header.\n");
316 return 0;
319 if( (hdc = GetDC32( 0 )) )
321 BITMAPINFO* pInfo;
322 INT32 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
324 /* Make sure we have room for the monochrome bitmap later on.
325 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
326 * up to and including the biBitCount. In-memory icon resource
327 * format is as follows:
329 * BITMAPINFOHEADER icHeader // DIB header
330 * RGBQUAD icColors[] // Color table
331 * BYTE icXOR[] // DIB bits for XOR mask
332 * BYTE icAND[] // DIB bits for AND mask
335 if( (pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
336 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))) )
338 memcpy( pInfo, bmi, size );
339 pInfo->bmiHeader.biHeight /= 2;
341 /* Create the XOR bitmap */
343 hXorBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader, CBM_INIT,
344 (char*)bmi + size, pInfo, DIB_RGB_COLORS );
345 if( hXorBits )
347 char* bits = (char *)bmi + size + bmi->bmiHeader.biHeight *
348 DIB_GetDIBWidthBytes(bmi->bmiHeader.biWidth,
349 bmi->bmiHeader.biBitCount) / 2;
351 pInfo->bmiHeader.biBitCount = 1;
352 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
354 RGBQUAD *rgb = pInfo->bmiColors;
356 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
357 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
358 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
359 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
361 else
363 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
365 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
366 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
369 /* Create the AND bitmap */
371 hAndBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader, CBM_INIT,
372 bits, pInfo, DIB_RGB_COLORS );
373 if( !hAndBits ) DeleteObject32( hXorBits );
375 HeapFree( GetProcessHeap(), 0, pInfo );
377 ReleaseDC32( 0, hdc );
380 if( !hXorBits || !hAndBits )
382 WARN(cursor,"\tunable to create an icon bitmap.\n");
383 return 0;
386 /* Now create the CURSORICONINFO structure */
388 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
389 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
390 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
391 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
393 if (hObj) hObj = GlobalReAlloc16( hObj,
394 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
395 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
396 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
397 if (hObj)
399 CURSORICONINFO *info;
401 /* Make it owned by the module */
402 if (hInstance) FarSetOwner( hObj, GetExePtr(hInstance) );
404 info = (CURSORICONINFO *)GlobalLock16( hObj );
405 info->ptHotSpot.x = hotspot.x;
406 info->ptHotSpot.y = hotspot.y;
407 info->nWidth = bmpXor->bitmap.bmWidth;
408 info->nHeight = bmpXor->bitmap.bmHeight;
409 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
410 info->bPlanes = bmpXor->bitmap.bmPlanes;
411 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
413 /* Transfer the bitmap bits to the CURSORICONINFO structure */
415 GetBitmapBits32( hAndBits, sizeAnd, (char *)(info + 1) );
416 GetBitmapBits32( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
417 GlobalUnlock16( hObj );
420 DeleteObject32( hXorBits );
421 DeleteObject32( hAndBits );
422 return hObj;
426 /**********************************************************************
427 * CreateIconFromResourceEx16 (USER.450)
429 * FIXME: not sure about exact parameter types
431 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
432 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
434 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
435 if( pTask )
436 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
437 width, height, cFlag );
438 return 0;
442 /**********************************************************************
443 * CreateIconFromResource (USER32.76)
444 * FIXME:
445 * bon@elektron.ikp.physik.tu-darmstadt.de 971130: Test with weditres
446 * showed only blank layout. Couldn't determine if this is a problem
447 * with CreateIconFromResource32 or the application. The application
448 * windows behaves strange (no redraw) before CreateIconFromResource32
450 HICON32 WINAPI CreateIconFromResource32( LPBYTE bits, UINT32 cbSize,
451 BOOL32 bIcon, DWORD dwVersion)
453 HICON32 ret;
454 ret = CreateIconFromResourceEx16( bits, cbSize, bIcon, dwVersion, 0,0,0);
455 FIXME(icon,"probably only a stub\n");
456 TRACE(icon, "%s at %p size %d winver %d return 0x%04x\n",
457 (bIcon)?"Icon":"Cursor",bits,cbSize,bIcon,ret);
458 return ret;
462 /**********************************************************************
463 * CreateIconFromResourceEx32 (USER32.77)
465 HICON32 WINAPI CreateIconFromResourceEx32( LPBYTE bits, UINT32 cbSize,
466 BOOL32 bIcon, DWORD dwVersion,
467 INT32 width, INT32 height,
468 UINT32 cFlag )
470 return CreateIconFromResourceEx16( bits, cbSize, bIcon, dwVersion, width, height, cFlag );
474 /**********************************************************************
475 * CURSORICON_Load16
477 * Load a cursor or icon from a 16-bit resource.
479 static HGLOBAL16 CURSORICON_Load16( HINSTANCE16 hInstance, SEGPTR name,
480 INT32 width, INT32 height, INT32 colors,
481 BOOL32 fCursor )
483 HGLOBAL16 handle;
484 HRSRC16 hRsrc;
485 CURSORICONDIRENTRY dirEntry;
487 if (!hInstance) /* OEM cursor/icon */
489 if (HIWORD(name)) /* Check for '#xxx' name */
491 char *ptr = PTR_SEG_TO_LIN( name );
492 if (ptr[0] != '#') return 0;
493 if (!(name = (SEGPTR)atoi( ptr + 1 ))) return 0;
495 return OBM_LoadCursorIcon( LOWORD(name), fCursor );
498 /* Find the best entry in the directory */
500 if ( !CURSORICON_LoadDirEntry16( hInstance, name, width, height,
501 colors, fCursor, &dirEntry ) ) return 0;
502 /* Load the resource */
504 if ( (hRsrc = FindResource16( hInstance,
505 MAKEINTRESOURCE16( dirEntry.icon.wResId ),
506 fCursor ? RT_CURSOR16 : RT_ICON16 )) )
508 /* 16-bit icon or cursor resources are processed
509 * transparently by the LoadResource16() via custom
510 * resource handlers set by SetResourceHandler().
513 if ( (handle = LoadResource16( hInstance, hRsrc )) )
514 return handle;
516 return 0;
519 /**********************************************************************
520 * CURSORICON_Load32
522 * Load a cursor or icon from a 32-bit resource.
524 static HGLOBAL32 CURSORICON_Load32( HINSTANCE32 hInstance, LPCWSTR name,
525 int width, int height, int colors,
526 BOOL32 fCursor )
528 HANDLE32 handle;
529 HANDLE32 hRsrc;
530 CURSORICONDIRENTRY dirEntry;
532 if(!hInstance) /* OEM cursor/icon */
534 WORD resid;
535 if(HIWORD(name))
537 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
538 if( ansi[0]=='#') /*Check for '#xxx' name */
540 resid = atoi(ansi+1);
541 HeapFree( GetProcessHeap(), 0, ansi );
543 else
545 HeapFree( GetProcessHeap(), 0, ansi );
546 return 0;
549 else resid = LOWORD(name);
550 return OBM_LoadCursorIcon(resid, fCursor);
553 /* Find the best entry in the directory */
555 if ( !CURSORICON_LoadDirEntry32( hInstance, name, width, height,
556 colors, fCursor, &dirEntry ) ) return 0;
557 /* Load the resource */
559 if ( (hRsrc = FindResource32W( hInstance,
560 MAKEINTRESOURCE32W( dirEntry.icon.wResId ),
561 fCursor ? RT_CURSOR32W : RT_ICON32W )) )
563 HANDLE32 h = 0;
564 if ( (handle = LoadResource32( hInstance, hRsrc )) )
566 /* Hack to keep LoadCursor/Icon32() from spawning multiple
567 * copies of the same object.
569 #define pRsrcEntry ((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)
570 if( !pRsrcEntry->ResourceHandle )
572 LPBYTE bits = (LPBYTE)LockResource32( handle );
573 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry.icon.dwBytesInRes,
574 !fCursor, 0x00030000, width, height, LR_DEFAULTCOLOR );
575 pRsrcEntry->ResourceHandle = h;
577 else h = pRsrcEntry->ResourceHandle;
578 #undef pRsrcEntry
580 return h;
582 return 0;
586 /***********************************************************************
587 * CURSORICON_Copy
589 * Make a copy of a cursor or icon.
591 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
593 char *ptrOld, *ptrNew;
594 int size;
595 HGLOBAL16 hNew;
597 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
598 if (!(hInstance = GetExePtr( hInstance ))) return 0;
599 size = GlobalSize16( handle );
600 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
601 FarSetOwner( hNew, hInstance );
602 ptrNew = (char *)GlobalLock16( hNew );
603 memcpy( ptrNew, ptrOld, size );
604 GlobalUnlock16( handle );
605 GlobalUnlock16( hNew );
606 return hNew;
609 /***********************************************************************
610 * CURSORICON_IconToCursor
612 * Converts bitmap to mono and truncates if icon is too large (should
613 * probably do StretchBlt() instead).
615 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL32 bSemiTransparent)
617 HCURSOR16 hRet = 0;
618 CURSORICONINFO *pIcon = NULL;
619 HTASK16 hTask = GetCurrentTask();
620 TDB* pTask = (TDB *)GlobalLock16(hTask);
622 if(hIcon && pTask)
623 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
624 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
625 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
626 else
628 BYTE pAndBits[128];
629 BYTE pXorBits[128];
630 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
631 BYTE* psPtr, *pxbPtr = pXorBits;
632 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
633 BYTE* pbc = NULL;
635 COLORREF col;
636 CURSORICONINFO cI;
638 TRACE(icon, "[%04x] %ix%i %ibpp (bogus %ibps)\n",
639 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
641 xor_width = BITMAP_GetBitsWidth( pIcon->nWidth, bpp );
642 and_width = BITMAP_GetBitsWidth( pIcon->nWidth, 1 );
643 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
645 memset(pXorBits, 0, 128);
646 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
647 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
648 cI.nWidth = 32; cI.nHeight = 32;
649 cI.nWidthBytes = 4; /* 32x1bpp */
651 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
652 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
654 for( iy = 0; iy < maxy; iy++ )
656 unsigned shift = iy % 2;
658 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
659 (and_width > 4) ? 4 : and_width );
660 for( ix = 0; ix < maxx; ix++ )
662 if( bSemiTransparent && ((ix+shift)%2) )
664 /* set AND bit, XOR bit stays 0 */
666 pbc = pAndBits + iy * 4 + ix/8;
667 *pbc |= 0x80 >> (ix%8);
669 else
671 /* keep AND bit, set XOR bit */
673 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
674 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
675 col = COLOR_ToLogical(val);
676 if( (GetRValue(col) + GetGValue(col) + GetBValue(col)) > 0x180 )
678 pbc = pxbPtr + ix/8;
679 *pbc |= 0x80 >> (ix%8);
683 psPtr += xor_width;
684 pxbPtr += 4;
687 hRet = CreateCursorIconIndirect( pTask->hInstance , &cI, pAndBits, pXorBits);
689 if( !hRet ) /* fall back on default drag cursor */
690 hRet = CURSORICON_Copy( pTask->hInstance ,
691 CURSORICON_Load16(0,MAKEINTRESOURCE16(OCR_DRAGOBJECT),
692 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE) );
695 return hRet;
699 /***********************************************************************
700 * LoadCursor16 (USER.173)
702 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
704 if (HIWORD(name))
705 TRACE(cursor, "%04x '%s'\n",
706 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
707 else
708 TRACE(cursor, "%04x %04x\n",
709 hInstance, LOWORD(name) );
711 return CURSORICON_Load16( hInstance, name,
712 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
716 /***********************************************************************
717 * LoadIcon16 (USER.174)
719 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
721 if (HIWORD(name))
722 TRACE(icon, "%04x '%s'\n",
723 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
724 else
725 TRACE(icon, "%04x %04x\n",
726 hInstance, LOWORD(name) );
728 return CURSORICON_Load16( hInstance, name,
729 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
730 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE );
734 /***********************************************************************
735 * CreateCursor16 (USER.406)
737 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
738 INT16 xHotSpot, INT16 yHotSpot,
739 INT16 nWidth, INT16 nHeight,
740 LPCVOID lpANDbits, LPCVOID lpXORbits )
742 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
744 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
745 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
746 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
750 /***********************************************************************
751 * CreateCursor32 (USER32.67)
753 HCURSOR32 WINAPI CreateCursor32( HINSTANCE32 hInstance,
754 INT32 xHotSpot, INT32 yHotSpot,
755 INT32 nWidth, INT32 nHeight,
756 LPCVOID lpANDbits, LPCVOID lpXORbits )
758 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
760 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
761 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
762 return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
766 /***********************************************************************
767 * CreateIcon16 (USER.407)
769 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
770 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
771 LPCVOID lpANDbits, LPCVOID lpXORbits )
773 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
775 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
776 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
777 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
781 /***********************************************************************
782 * CreateIcon32 (USER32.75)
784 HICON32 WINAPI CreateIcon32( HINSTANCE32 hInstance, INT32 nWidth,
785 INT32 nHeight, BYTE bPlanes, BYTE bBitsPixel,
786 LPCVOID lpANDbits, LPCVOID lpXORbits )
788 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
790 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
791 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
792 return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
796 /***********************************************************************
797 * CreateCursorIconIndirect (USER.408)
799 HGLOBAL16 WINAPI CreateCursorIconIndirect( HINSTANCE16 hInstance,
800 CURSORICONINFO *info,
801 LPCVOID lpANDbits,
802 LPCVOID lpXORbits )
804 HGLOBAL16 handle;
805 char *ptr;
806 int sizeAnd, sizeXor;
808 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
809 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
810 info->nWidthBytes = BITMAP_WIDTH_BYTES(info->nWidth,info->bBitsPerPixel);
811 sizeXor = info->nHeight * info->nWidthBytes;
812 sizeAnd = info->nHeight * BITMAP_WIDTH_BYTES( info->nWidth, 1 );
813 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
814 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
815 return 0;
816 if (hInstance) FarSetOwner( handle, hInstance );
817 ptr = (char *)GlobalLock16( handle );
818 memcpy( ptr, info, sizeof(*info) );
819 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
820 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
821 GlobalUnlock16( handle );
822 return handle;
826 /***********************************************************************
827 * CopyIcon16 (USER.368)
829 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
831 TRACE(icon, "%04x %04x\n", hInstance, hIcon );
832 return CURSORICON_Copy( hInstance, hIcon );
836 /***********************************************************************
837 * CopyIcon32 (USER32.60)
839 HICON32 WINAPI CopyIcon32( HICON32 hIcon )
841 HTASK16 hTask = GetCurrentTask ();
842 TDB* pTask = (TDB *) GlobalLock16 (hTask);
843 TRACE(icon, "%04x\n", hIcon );
844 return CURSORICON_Copy( pTask->hInstance, hIcon );
848 /***********************************************************************
849 * CopyCursor16 (USER.369)
851 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
853 TRACE(cursor, "%04x %04x\n", hInstance, hCursor );
854 return CURSORICON_Copy( hInstance, hCursor );
858 /***********************************************************************
859 * DestroyIcon16 (USER.457)
861 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
863 return DestroyIcon32( hIcon );
867 /***********************************************************************
868 * DestroyIcon32 (USER32.133)
870 BOOL32 WINAPI DestroyIcon32( HICON32 hIcon )
872 TRACE(icon, "%04x\n", hIcon );
873 /* FIXME: should check for OEM icon here */
874 return (FreeResource16( hIcon ) == 0);
878 /***********************************************************************
879 * DestroyCursor16 (USER.458)
881 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
883 return DestroyCursor32( hCursor );
887 /***********************************************************************
888 * DestroyCursor32 (USER32.132)
890 BOOL32 WINAPI DestroyCursor32( HCURSOR32 hCursor )
892 TRACE(cursor, "%04x\n", hCursor );
893 /* FIXME: should check for OEM cursor here */
894 return (FreeResource16( hCursor ) == 0);
898 /***********************************************************************
899 * DrawIcon16 (USER.84)
901 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
903 return DrawIcon32( hdc, x, y, hIcon );
907 /***********************************************************************
908 * DrawIcon32 (USER32.159)
910 BOOL32 WINAPI DrawIcon32( HDC32 hdc, INT32 x, INT32 y, HICON32 hIcon )
912 CURSORICONINFO *ptr;
913 HDC32 hMemDC;
914 HBITMAP32 hXorBits, hAndBits;
915 COLORREF oldFg, oldBg;
917 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
918 if (!(hMemDC = CreateCompatibleDC32( hdc ))) return FALSE;
919 hAndBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, 1, 1,
920 (char *)(ptr+1) );
921 hXorBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
922 ptr->bBitsPerPixel, (char *)(ptr + 1)
923 + ptr->nHeight * BITMAP_WIDTH_BYTES(ptr->nWidth,1) );
924 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
925 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
927 if (hXorBits && hAndBits)
929 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
930 BitBlt32( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
931 SelectObject32( hMemDC, hXorBits );
932 BitBlt32(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
933 SelectObject32( hMemDC, hBitTemp );
935 DeleteDC32( hMemDC );
936 if (hXorBits) DeleteObject32( hXorBits );
937 if (hAndBits) DeleteObject32( hAndBits );
938 GlobalUnlock16( hIcon );
939 SetTextColor32( hdc, oldFg );
940 SetBkColor32( hdc, oldBg );
941 return TRUE;
945 /***********************************************************************
946 * DumpIcon (USER.459)
948 DWORD WINAPI DumpIcon( SEGPTR pInfo, WORD *lpLen,
949 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
951 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
952 int sizeAnd, sizeXor;
954 if (!info) return 0;
955 sizeXor = info->nHeight * info->nWidthBytes;
956 sizeAnd = info->nHeight * BITMAP_WIDTH_BYTES( info->nWidth, 1 );
957 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
958 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
959 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
960 return MAKELONG( sizeXor, sizeXor );
964 /***********************************************************************
965 * CURSORICON_SetCursor
967 * Change the X cursor. Helper function for SetCursor() and ShowCursor().
968 * The Xlib critical section must be entered before calling this function.
970 static BOOL32 CURSORICON_SetCursor( HCURSOR16 hCursor )
972 Pixmap pixmapBits, pixmapMask, pixmapAll;
973 XColor fg, bg;
974 Cursor cursor = None;
976 if (!hCursor) /* Create an empty cursor */
978 static const char data[] = { 0 };
980 bg.red = bg.green = bg.blue = 0x0000;
981 pixmapBits = XCreateBitmapFromData( display, rootWindow, data, 1, 1 );
982 if (pixmapBits)
984 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapBits,
985 &bg, &bg, 0, 0 );
986 XFreePixmap( display, pixmapBits );
989 else /* Create the X cursor from the bits */
991 CURSORICONINFO *ptr;
992 XImage *image;
994 if (!(ptr = (CURSORICONINFO*)GlobalLock16( hCursor ))) return FALSE;
995 if (ptr->bPlanes * ptr->bBitsPerPixel != 1)
997 WARN(cursor, "Cursor %04x has more than 1 bpp!\n", hCursor );
998 return FALSE;
1001 /* Create a pixmap and transfer all the bits to it */
1003 /* NOTE: Following hack works, but only because XFree depth
1004 * 1 images really use 1 bit/pixel (and so the same layout
1005 * as the Windows cursor data). Perhaps use a more generic
1006 * algorithm here.
1008 pixmapAll = XCreatePixmap( display, rootWindow,
1009 ptr->nWidth, ptr->nHeight * 2, 1 );
1010 image = XCreateImage( display, DefaultVisualOfScreen(screen),
1011 1, ZPixmap, 0, (char *)(ptr + 1), ptr->nWidth,
1012 ptr->nHeight * 2, 16, ptr->nWidthBytes);
1013 if (image)
1015 image->byte_order = MSBFirst;
1016 image->bitmap_bit_order = MSBFirst;
1017 image->bitmap_unit = 16;
1018 _XInitImageFuncPtrs(image);
1019 if (pixmapAll)
1020 XPutImage( display, pixmapAll, BITMAP_monoGC, image,
1021 0, 0, 0, 0, ptr->nWidth, ptr->nHeight * 2 );
1022 image->data = NULL;
1023 XDestroyImage( image );
1026 /* Now create the 2 pixmaps for bits and mask */
1028 pixmapBits = XCreatePixmap( display, rootWindow,
1029 ptr->nWidth, ptr->nHeight, 1 );
1030 pixmapMask = XCreatePixmap( display, rootWindow,
1031 ptr->nWidth, ptr->nHeight, 1 );
1033 /* Make sure everything went OK so far */
1035 if (pixmapBits && pixmapMask && pixmapAll)
1037 /* We have to do some magic here, as cursors are not fully
1038 * compatible between Windows and X11. Under X11, there
1039 * are only 3 possible color cursor: black, white and
1040 * masked. So we map the 4th Windows color (invert the
1041 * bits on the screen) to black. This require some boolean
1042 * arithmetic:
1044 * Windows | X11
1045 * Xor And Result | Bits Mask Result
1046 * 0 0 black | 0 1 background
1047 * 0 1 no change | X 0 no change
1048 * 1 0 white | 1 1 foreground
1049 * 1 1 inverted | 0 1 background
1051 * which gives:
1052 * Bits = 'Xor' and not 'And'
1053 * Mask = 'Xor' or not 'And'
1055 * FIXME: apparently some servers do support 'inverted' color.
1056 * I don't know if it's correct per the X spec, but maybe
1057 * we ought to take advantage of it. -- AJ
1059 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
1060 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
1061 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
1062 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
1063 XSetFunction( display, BITMAP_monoGC, GXandReverse );
1064 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
1065 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
1066 XSetFunction( display, BITMAP_monoGC, GXorReverse );
1067 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
1068 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
1069 XSetFunction( display, BITMAP_monoGC, GXcopy );
1070 fg.red = fg.green = fg.blue = 0xffff;
1071 bg.red = bg.green = bg.blue = 0x0000;
1072 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapMask,
1073 &fg, &bg, ptr->ptHotSpot.x, ptr->ptHotSpot.y );
1076 /* Now free everything */
1078 if (pixmapAll) XFreePixmap( display, pixmapAll );
1079 if (pixmapBits) XFreePixmap( display, pixmapBits );
1080 if (pixmapMask) XFreePixmap( display, pixmapMask );
1081 GlobalUnlock16( hCursor );
1084 if (cursor == None) return FALSE;
1085 if (CURSORICON_XCursor != None) XFreeCursor( display, CURSORICON_XCursor );
1086 CURSORICON_XCursor = cursor;
1088 if (rootWindow != DefaultRootWindow(display))
1090 /* Set the cursor on the desktop window */
1091 XDefineCursor( display, rootWindow, cursor );
1093 else
1095 /* Set the same cursor for all top-level windows */
1096 HWND32 hwnd = GetWindow32( GetDesktopWindow32(), GW_CHILD );
1097 while(hwnd)
1099 Window win = WIN_GetXWindow( hwnd );
1100 if (win && win!=DefaultRootWindow(display))
1101 XDefineCursor( display, win, cursor );
1102 hwnd = GetWindow32( hwnd, GW_HWNDNEXT );
1105 return TRUE;
1109 /***********************************************************************
1110 * SetCursor16 (USER.69)
1112 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1114 return (HCURSOR16)SetCursor32( hCursor );
1118 /***********************************************************************
1119 * SetCursor32 (USER32.472)
1120 * RETURNS:
1121 * A handle to the previous cursor shape.
1123 HCURSOR32 WINAPI SetCursor32(
1124 HCURSOR32 hCursor /* Handle of cursor to show */
1126 HCURSOR32 hOldCursor;
1128 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1129 TRACE(cursor, "%04x\n", hCursor );
1130 hOldCursor = hActiveCursor;
1131 hActiveCursor = hCursor;
1132 /* Change the cursor shape only if it is visible */
1133 if (CURSOR_ShowCount >= 0)
1135 EnterCriticalSection( &X11DRV_CritSection );
1136 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1137 LeaveCriticalSection( &X11DRV_CritSection );
1139 return hOldCursor;
1143 /***********************************************************************
1144 * SetCursorPos16 (USER.70)
1146 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1148 SetCursorPos32( x, y );
1152 /***********************************************************************
1153 * SetCursorPos32 (USER32.474)
1155 BOOL32 WINAPI SetCursorPos32( INT32 x, INT32 y )
1157 TRACE(cursor, "x=%d y=%d\n", x, y );
1158 TSXWarpPointer( display, rootWindow, rootWindow, 0, 0, 0, 0, x, y );
1159 return TRUE;
1163 /***********************************************************************
1164 * ShowCursor16 (USER.71)
1166 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1168 return ShowCursor32( bShow );
1172 /***********************************************************************
1173 * ShowCursor32 (USER32.530)
1175 INT32 WINAPI ShowCursor32( BOOL32 bShow )
1177 TRACE(cursor, "%d, count=%d\n",
1178 bShow, CURSOR_ShowCount );
1180 EnterCriticalSection( &X11DRV_CritSection );
1181 if (bShow)
1183 if (++CURSOR_ShowCount == 0) /* Show it */
1184 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1186 else
1188 if (--CURSOR_ShowCount == -1) /* Hide it */
1189 CALL_LARGE_STACK( CURSORICON_SetCursor, 0 );
1191 LeaveCriticalSection( &X11DRV_CritSection );
1192 return CURSOR_ShowCount;
1196 /***********************************************************************
1197 * GetCursor16 (USER.247)
1199 HCURSOR16 WINAPI GetCursor16(void)
1201 return hActiveCursor;
1205 /***********************************************************************
1206 * GetCursor32 (USER32.227)
1208 HCURSOR32 WINAPI GetCursor32(void)
1210 return hActiveCursor;
1214 /***********************************************************************
1215 * ClipCursor16 (USER.16)
1217 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1219 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1220 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1221 return TRUE;
1225 /***********************************************************************
1226 * ClipCursor32 (USER32.53)
1228 BOOL32 WINAPI ClipCursor32( const RECT32 *rect )
1230 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1231 else CopyRect32( &CURSOR_ClipRect, rect );
1232 return TRUE;
1236 /***********************************************************************
1237 * GetCursorPos16 (USER.17)
1239 void WINAPI GetCursorPos16( POINT16 *pt )
1241 Window root, child;
1242 int rootX, rootY, childX, childY;
1243 unsigned int mousebut;
1245 if (!pt) return;
1246 if (!TSXQueryPointer( display, rootWindow, &root, &child,
1247 &rootX, &rootY, &childX, &childY, &mousebut ))
1248 pt->x = pt->y = 0;
1249 else
1251 pt->x = childX;
1252 pt->y = childY;
1253 if (mousebut & Button1Mask)
1254 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1255 else
1256 MouseButtonsStates[0] = FALSE;
1257 if (mousebut & Button2Mask)
1258 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1259 else
1260 MouseButtonsStates[1] = FALSE;
1261 if (mousebut & Button3Mask)
1262 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1263 else
1264 MouseButtonsStates[2] = FALSE;
1266 TRACE(cursor, "ret=%d,%d\n", pt->x, pt->y );
1270 /***********************************************************************
1271 * GetCursorPos32 (USER32.229)
1273 void WINAPI GetCursorPos32( POINT32 *pt )
1275 POINT16 pt16;
1276 GetCursorPos16( &pt16 );
1277 if (pt) CONV_POINT16TO32( &pt16, pt );
1281 /***********************************************************************
1282 * GetClipCursor16 (USER.309)
1284 void WINAPI GetClipCursor16( RECT16 *rect )
1286 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1290 /***********************************************************************
1291 * GetClipCursor32 (USER32.221)
1293 void WINAPI GetClipCursor32( RECT32 *rect )
1295 if (rect) CopyRect32( rect, &CURSOR_ClipRect );
1298 /**********************************************************************
1299 * LookupIconIdFromDirectoryEx16 (USER.364)
1301 * FIXME: exact parameter sizes
1303 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1304 INT16 width, INT16 height, UINT16 cFlag )
1306 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1307 UINT16 retVal = 0;
1308 if( dir && !dir->idReserved && (dir->idType & 3) )
1310 int colors = (cFlag == LR_MONOCHROME) ? 2 : COLOR_GetSystemPaletteSize();
1311 if( bIcon )
1313 ICONDIRENTRY* entry;
1314 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1315 if( entry ) retVal = entry->wResId;
1317 else
1319 CURSORDIRENTRY* entry;
1320 entry = CURSORICON_FindBestCursor( dir, width, height );
1321 if( entry ) retVal = entry->wResId;
1324 else WARN(cursor, "invalid resource directory\n");
1325 return retVal;
1328 /**********************************************************************
1329 * LookupIconIdFromDirectoryEx32 (USER32.380)
1331 INT32 WINAPI LookupIconIdFromDirectoryEx32( LPBYTE dir, BOOL32 bIcon,
1332 INT32 width, INT32 height, UINT32 cFlag )
1334 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1337 /**********************************************************************
1338 * LookupIconIdFromDirectory (USER.???)
1340 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1342 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1343 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1344 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1347 /**********************************************************************
1348 * LookupIconIdFromDirectory (USER32.379)
1350 INT32 WINAPI LookupIconIdFromDirectory32( LPBYTE dir, BOOL32 bIcon )
1352 return LookupIconIdFromDirectoryEx32( dir, bIcon,
1353 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1354 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1357 /**********************************************************************
1358 * GetIconID (USER.455)
1360 WORD WINAPI GetIconID( HGLOBAL16 hResource, DWORD resType )
1362 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1364 TRACE(cursor, "hRes=%04x, entries=%i\n",
1365 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1367 switch(resType)
1369 case RT_CURSOR16:
1370 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1371 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1372 case RT_ICON16:
1373 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1374 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1375 default:
1376 WARN(cursor, "invalid res type %ld\n", resType );
1378 return 0;
1381 /**********************************************************************
1382 * LoadCursorIconHandler (USER.336)
1384 * Supposed to load resources of Windows 2.x applications.
1386 HGLOBAL16 WINAPI LoadCursorIconHandler( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1388 FIXME(cursor,"(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1389 hResource, hModule, hRsrc);
1390 return (HGLOBAL16)0;
1393 /**********************************************************************
1394 * LoadDIBIconHandler (USER.357)
1396 * RT_ICON resource loader, installed by USER_SignalProc when module
1397 * is initialized.
1399 HGLOBAL16 WINAPI LoadDIBIconHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1401 /* If hResource is zero we must allocate a new memory block, if it's
1402 * non-zero but GlobalLock() returns NULL then it was discarded and
1403 * we have to recommit some memory, otherwise we just need to check
1404 * the block size. See LoadProc() in 16-bit SDK for more.
1407 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1408 if( hMemObj )
1410 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1411 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1412 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1413 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1415 return hMemObj;
1418 /**********************************************************************
1419 * LoadDIBCursorHandler (USER.356)
1421 * RT_CURSOR resource loader. Same as above.
1423 HGLOBAL16 WINAPI LoadDIBCursorHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1425 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1426 if( hMemObj )
1428 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1429 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1430 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1431 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1433 return hMemObj;
1436 /**********************************************************************
1437 * LoadIconHandler (USER.456)
1439 HICON16 WINAPI LoadIconHandler( HGLOBAL16 hResource, BOOL16 bNew )
1441 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1443 TRACE(cursor,"hRes=%04x\n",hResource);
1445 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1446 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1449 /***********************************************************************
1450 * LoadCursorW (USER32.362)
1452 HCURSOR32 WINAPI LoadCursor32W(HINSTANCE32 hInstance, LPCWSTR name)
1454 return CURSORICON_Load32( hInstance, name,
1455 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
1458 /***********************************************************************
1459 * LoadCursorA (USER32.359)
1461 HCURSOR32 WINAPI LoadCursor32A(HINSTANCE32 hInstance, LPCSTR name)
1463 HCURSOR32 res=0;
1464 if(!HIWORD(name))
1465 return LoadCursor32W(hInstance,(LPCWSTR)name);
1466 else
1468 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1469 res = LoadCursor32W(hInstance, uni);
1470 HeapFree( GetProcessHeap(), 0, uni);
1472 return res;
1475 /***********************************************************************
1476 * LoadIconW (USER32.364)
1478 HICON32 WINAPI LoadIcon32W(HINSTANCE32 hInstance, LPCWSTR name)
1480 return CURSORICON_Load32( hInstance, name,
1481 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
1482 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE );
1485 /***********************************************************************
1486 * LoadIconA (USER32.363)
1488 HICON32 WINAPI LoadIcon32A(HINSTANCE32 hInstance, LPCSTR name)
1490 HICON32 res=0;
1492 if( !HIWORD(name) )
1493 return LoadIcon32W(hInstance, (LPCWSTR)name);
1494 else
1496 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1497 res = LoadIcon32W( hInstance, uni );
1498 HeapFree( GetProcessHeap(), 0, uni );
1500 return res;
1503 /**********************************************************************
1504 * GetIconInfo (USER32.242)
1506 BOOL32 WINAPI GetIconInfo(HICON32 hIcon,LPICONINFO iconinfo) {
1507 CURSORICONINFO *ciconinfo;
1509 ciconinfo = GlobalLock16(hIcon);
1510 if (!ciconinfo)
1511 return FALSE;
1512 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1513 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1514 iconinfo->fIcon = TRUE; /* hmm */
1515 /* FIXME ... add both bitmaps */
1516 return TRUE;
1519 /**********************************************************************
1520 * CreateIconIndirect (USER32.78)
1522 HICON32 WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1523 BITMAPOBJ *bmpXor,*bmpAnd;
1524 HICON32 hObj;
1525 int sizeXor,sizeAnd;
1527 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1528 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1530 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1531 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1533 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1534 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1535 if (hObj)
1537 CURSORICONINFO *info;
1539 info = (CURSORICONINFO *)GlobalLock16( hObj );
1540 info->ptHotSpot.x = iconinfo->xHotspot;
1541 info->ptHotSpot.y = iconinfo->yHotspot;
1542 info->nWidth = bmpXor->bitmap.bmWidth;
1543 info->nHeight = bmpXor->bitmap.bmHeight;
1544 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1545 info->bPlanes = bmpXor->bitmap.bmPlanes;
1546 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1548 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1550 GetBitmapBits32( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1551 GetBitmapBits32( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1552 GlobalUnlock16( hObj );
1554 return hObj;
1558 /**********************************************************************
1559 * DrawIconEx16 (USER.394)
1561 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1562 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1563 HBRUSH16 hbr, UINT16 flags)
1565 return DrawIconEx32(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1566 istep, hbr, flags);
1570 /******************************************************************************
1571 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1573 * NOTES
1574 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1576 * PARAMS
1577 * hdc [I] Handle to device context
1578 * x0 [I] X coordinate of upper left corner
1579 * y0 [I] Y coordinate of upper left corner
1580 * hIcon [I] Handle to icon to draw
1581 * cxWidth [I] Width of icon
1582 * cyWidth [I] Height of icon
1583 * istep [I] Index of frame in animated cursor
1584 * hbr [I] Handle to background brush
1585 * flags [I] Icon-drawing flags
1587 * RETURNS
1588 * Success: TRUE
1589 * Failure: FALSE
1591 BOOL32 WINAPI DrawIconEx32( HDC32 hdc, INT32 x0, INT32 y0, HICON32 hIcon,
1592 INT32 cxWidth, INT32 cyWidth, UINT32 istep,
1593 HBRUSH32 hbr, UINT32 flags )
1595 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1596 HDC32 hMemDC = CreateCompatibleDC32 (hdc);
1597 BOOL32 result = FALSE;
1599 if (istep)
1600 FIXME(icon, "Ignoring istep=%d\n", istep);
1601 if (hbr)
1602 FIXME(icon, "Ignoring hbr=%x\n", hbr);
1603 if (flags & DI_COMPAT)
1604 FIXME(icon, "Ignoring flag DI_COMPAT\n");
1606 if (hMemDC && ptr)
1608 HBITMAP32 hXorBits, hAndBits;
1609 COLORREF oldFg, oldBg;
1611 /* Calculate the size of the destination image. */
1612 if (cxWidth == 0)
1613 if (flags & DI_DEFAULTSIZE)
1614 cxWidth = GetSystemMetrics32 (SM_CXICON);
1615 else
1616 cxWidth = ptr->nWidth;
1617 if (cyWidth == 0)
1618 if (flags & DI_DEFAULTSIZE)
1619 cyWidth = GetSystemMetrics32 (SM_CYICON);
1620 else
1621 cyWidth = ptr->nHeight;
1623 hXorBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
1624 ptr->bPlanes, ptr->bBitsPerPixel,
1625 (char *)(ptr + 1)
1626 + ptr->nHeight *
1627 BITMAP_WIDTH_BYTES(ptr->nWidth,1) );
1628 hAndBits = CreateBitmap32 ( cxWidth, cyWidth,
1629 1, 1, (char *)(ptr+1) );
1630 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
1631 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
1633 if (hXorBits && hAndBits)
1635 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
1636 if (flags & DI_MASK)
1637 BitBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1638 hMemDC, 0, 0, SRCAND);
1639 SelectObject32( hMemDC, hXorBits );
1640 if (flags & DI_IMAGE)
1641 BitBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1642 hMemDC, 0, 0, SRCPAINT);
1643 SelectObject32( hMemDC, hBitTemp );
1644 result = TRUE;
1647 SetTextColor32( hdc, oldFg );
1648 SetBkColor32( hdc, oldBg );
1649 if (hXorBits) DeleteObject32( hXorBits );
1650 if (hAndBits) DeleteObject32( hAndBits );
1652 if (hMemDC) DeleteDC32( hMemDC );
1653 GlobalUnlock16( hIcon );
1654 return result;