Release 980104
[wine/multimedia.git] / objects / cursoricon.c
blob2ec3b5961bb102241c22f8e41577c487b55c7ccd
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 "stddebug.h"
42 #include "debug.h"
43 #include "task.h"
44 #include "user.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 dprintf_cursor(stddeb,"CreateFromResource: %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 fprintf(stdnimp,"\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 fprintf(stderr,"\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 fprintf(stderr,"\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)
446 HICON32 WINAPI CreateIconFromResource32( LPBYTE bits, UINT32 cbSize,
447 BOOL32 bIcon, DWORD dwVersion)
448 /*FIXME: bon@elektron.ikp.physik.tu-darmstadt.de 971130: Test with weditres
449 showed only blank layout. Couldn't determine if this is a problem
450 with CreateIconFromResource32 or the application. The application
451 windows behaves strange (no redraw) before CreateIconFromResource32
454 HICON32 ret;
455 ret = CreateIconFromResourceEx16( bits, cbSize, bIcon, dwVersion, 0,0,0);
456 fprintf(stdnimp,"CreateIconFromResource3 probably only a stub\n");
457 dprintf_icon(stddeb,
458 "CreateIconFromResource32 %s at %p size %d winver %d return 0x%04x\n",
459 (bIcon)?"Icon":"Cursor",bits,cbSize,bIcon,ret);
460 return ret;
464 /**********************************************************************
465 * CreateIconFromResourceEx32 (USER32.76)
467 HICON32 WINAPI CreateIconFromResourceEx32( LPBYTE bits, UINT32 cbSize,
468 BOOL32 bIcon, DWORD dwVersion,
469 INT32 width, INT32 height,
470 UINT32 cFlag )
472 return CreateIconFromResourceEx16( bits, cbSize, bIcon, dwVersion, width, height, cFlag );
476 /**********************************************************************
477 * CURSORICON_Load16
479 * Load a cursor or icon from a 16-bit resource.
481 static HGLOBAL16 CURSORICON_Load16( HINSTANCE16 hInstance, SEGPTR name,
482 INT32 width, INT32 height, INT32 colors,
483 BOOL32 fCursor )
485 HGLOBAL16 handle;
486 HRSRC16 hRsrc;
487 CURSORICONDIRENTRY dirEntry;
489 if (!hInstance) /* OEM cursor/icon */
491 if (HIWORD(name)) /* Check for '#xxx' name */
493 char *ptr = PTR_SEG_TO_LIN( name );
494 if (ptr[0] != '#') return 0;
495 if (!(name = (SEGPTR)atoi( ptr + 1 ))) return 0;
497 return OBM_LoadCursorIcon( LOWORD(name), fCursor );
500 /* Find the best entry in the directory */
502 if ( !CURSORICON_LoadDirEntry16( hInstance, name, width, height,
503 colors, fCursor, &dirEntry ) ) return 0;
504 /* Load the resource */
506 if ( (hRsrc = FindResource16( hInstance,
507 MAKEINTRESOURCE( dirEntry.icon.wResId ),
508 fCursor ? RT_CURSOR : RT_ICON )) )
510 /* 16-bit icon or cursor resources are processed
511 * transparently by the LoadResource16() via custom
512 * resource handlers set by SetResourceHandler().
515 if ( (handle = LoadResource16( hInstance, hRsrc )) )
516 return handle;
518 return 0;
521 /**********************************************************************
522 * CURSORICON_Load32
524 * Load a cursor or icon from a 32-bit resource.
526 static HGLOBAL32 CURSORICON_Load32( HINSTANCE32 hInstance, LPCWSTR name,
527 int width, int height, int colors,
528 BOOL32 fCursor )
530 HANDLE32 handle;
531 HANDLE32 hRsrc;
532 CURSORICONDIRENTRY dirEntry;
534 if(!hInstance) /* OEM cursor/icon */
536 WORD resid;
537 if(HIWORD(name))
539 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
540 if( ansi[0]=='#') /*Check for '#xxx' name */
542 resid = atoi(ansi+1);
543 HeapFree( GetProcessHeap(), 0, ansi );
545 else
547 HeapFree( GetProcessHeap(), 0, ansi );
548 return 0;
551 else resid = LOWORD(name);
552 return OBM_LoadCursorIcon(resid, fCursor);
555 /* Find the best entry in the directory */
557 if ( !CURSORICON_LoadDirEntry32( hInstance, name, width, height,
558 colors, fCursor, &dirEntry ) ) return 0;
559 /* Load the resource */
561 if ( (hRsrc = FindResource32W( hInstance,
562 (LPWSTR) (DWORD) dirEntry.icon.wResId,
563 (LPWSTR) (fCursor ? RT_CURSOR : RT_ICON ))) )
565 HANDLE32 h = 0;
566 if ( (handle = LoadResource32( hInstance, hRsrc )) )
568 /* Hack to keep LoadCursor/Icon32() from spawning multiple
569 * copies of the same object.
571 #define pRsrcEntry ((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)
572 if( !pRsrcEntry->ResourceHandle )
574 LPBYTE bits = (LPBYTE)LockResource32( handle );
575 h = CURSORICON_CreateFromResource( hInstance, 0, bits, dirEntry.icon.dwBytesInRes,
576 !fCursor, 0x00030000, width, height, LR_DEFAULTCOLOR );
577 pRsrcEntry->ResourceHandle = h;
579 else h = pRsrcEntry->ResourceHandle;
580 #undef pRsrcEntry
582 return h;
584 return 0;
588 /***********************************************************************
589 * CURSORICON_Copy
591 * Make a copy of a cursor or icon.
593 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
595 char *ptrOld, *ptrNew;
596 int size;
597 HGLOBAL16 hNew;
599 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
600 if (!(hInstance = GetExePtr( hInstance ))) return 0;
601 size = GlobalSize16( handle );
602 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
603 FarSetOwner( hNew, hInstance );
604 ptrNew = (char *)GlobalLock16( hNew );
605 memcpy( ptrNew, ptrOld, size );
606 GlobalUnlock16( handle );
607 GlobalUnlock16( hNew );
608 return hNew;
611 /***********************************************************************
612 * CURSORICON_IconToCursor
614 * Converts bitmap to mono and truncates if icon is too large (should
615 * probably do StretchBlt() instead).
617 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL32 bSemiTransparent)
619 HCURSOR16 hRet = 0;
620 CURSORICONINFO *pIcon = NULL;
621 HTASK16 hTask = GetCurrentTask();
622 TDB* pTask = (TDB *)GlobalLock16(hTask);
624 if(hIcon && pTask)
625 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
626 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
627 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
628 else
630 BYTE pAndBits[128];
631 BYTE pXorBits[128];
632 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
633 BYTE* psPtr, *pxbPtr = pXorBits;
634 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
635 BYTE* pbc = NULL;
637 COLORREF col;
638 CURSORICONINFO cI;
640 dprintf_icon(stddeb, "IconToCursor:[%04x] %ix%i %ibpp (bogus %ibps)\n",
641 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
643 xor_width = BITMAP_GetBitsWidth( pIcon->nWidth, bpp );
644 and_width = BITMAP_GetBitsWidth( pIcon->nWidth, 1 );
645 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
647 memset(pXorBits, 0, 128);
648 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
649 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
650 cI.nWidth = 32; cI.nHeight = 32;
651 cI.nWidthBytes = 4; /* 32x1bpp */
653 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
654 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
656 for( iy = 0; iy < maxy; iy++ )
658 unsigned shift = iy % 2;
660 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
661 (and_width > 4) ? 4 : and_width );
662 for( ix = 0; ix < maxx; ix++ )
664 if( bSemiTransparent && ((ix+shift)%2) )
666 /* set AND bit, XOR bit stays 0 */
668 pbc = pAndBits + iy * 4 + ix/8;
669 *pbc |= 0x80 >> (ix%8);
671 else
673 /* keep AND bit, set XOR bit */
675 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
676 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
677 col = COLOR_ToLogical(val);
678 if( (GetRValue(col) + GetGValue(col) + GetBValue(col)) > 0x180 )
680 pbc = pxbPtr + ix/8;
681 *pbc |= 0x80 >> (ix%8);
685 psPtr += xor_width;
686 pxbPtr += 4;
689 hRet = CreateCursorIconIndirect( pTask->hInstance , &cI, pAndBits, pXorBits);
691 if( !hRet ) /* fall back on default drag cursor */
692 hRet = CURSORICON_Copy( pTask->hInstance ,
693 CURSORICON_Load16(0,MAKEINTRESOURCE(OCR_DRAGOBJECT),
694 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE) );
697 return hRet;
701 /***********************************************************************
702 * LoadCursor16 (USER.173)
704 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
706 if (HIWORD(name))
707 dprintf_cursor( stddeb, "LoadCursor16: %04x '%s'\n",
708 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
709 else
710 dprintf_cursor( stddeb, "LoadCursor16: %04x %04x\n",
711 hInstance, LOWORD(name) );
713 return CURSORICON_Load16( hInstance, name,
714 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
718 /***********************************************************************
719 * LoadIcon16 (USER.174)
721 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
723 if (HIWORD(name))
724 dprintf_icon( stddeb, "LoadIcon: %04x '%s'\n",
725 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
726 else
727 dprintf_icon( stddeb, "LoadIcon: %04x %04x\n",
728 hInstance, LOWORD(name) );
730 return CURSORICON_Load16( hInstance, name,
731 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
732 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE );
736 /***********************************************************************
737 * CreateCursor16 (USER.406)
739 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
740 INT16 xHotSpot, INT16 yHotSpot,
741 INT16 nWidth, INT16 nHeight,
742 LPCVOID lpANDbits, LPCVOID lpXORbits )
744 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
746 dprintf_cursor( stddeb, "CreateCursor: %dx%d spot=%d,%d xor=%p and=%p\n",
747 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
748 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
752 /***********************************************************************
753 * CreateCursor32 (USER32.66)
755 HCURSOR32 WINAPI CreateCursor32( HINSTANCE32 hInstance,
756 INT32 xHotSpot, INT32 yHotSpot,
757 INT32 nWidth, INT32 nHeight,
758 LPCVOID lpANDbits, LPCVOID lpXORbits )
760 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
762 dprintf_cursor( stddeb, "CreateCursor: %dx%d spot=%d,%d xor=%p and=%p\n",
763 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
764 return CreateCursorIconIndirect( MODULE_HANDLEtoHMODULE16( hInstance ),
765 &info, lpANDbits, lpXORbits );
769 /***********************************************************************
770 * CreateIcon16 (USER.407)
772 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
773 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
774 LPCVOID lpANDbits, LPCVOID lpXORbits )
776 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
778 dprintf_icon( stddeb, "CreateIcon: %dx%dx%d, xor=%p, and=%p\n",
779 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
780 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
784 /***********************************************************************
785 * CreateIcon32 (USER32.74)
787 HICON32 WINAPI CreateIcon32( HINSTANCE32 hInstance, INT32 nWidth,
788 INT32 nHeight, BYTE bPlanes, BYTE bBitsPixel,
789 LPCVOID lpANDbits, LPCVOID lpXORbits )
791 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
793 dprintf_icon( stddeb, "CreateIcon: %dx%dx%d, xor=%p, and=%p\n",
794 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
795 return CreateCursorIconIndirect( MODULE_HANDLEtoHMODULE16( hInstance ),
796 &info, lpANDbits, lpXORbits );
800 /***********************************************************************
801 * CreateCursorIconIndirect (USER.408)
803 HGLOBAL16 WINAPI CreateCursorIconIndirect( HINSTANCE16 hInstance,
804 CURSORICONINFO *info,
805 LPCVOID lpANDbits,
806 LPCVOID lpXORbits )
808 HGLOBAL16 handle;
809 char *ptr;
810 int sizeAnd, sizeXor;
812 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
813 if (!hInstance || !lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
814 info->nWidthBytes = BITMAP_WIDTH_BYTES(info->nWidth,info->bBitsPerPixel);
815 sizeXor = info->nHeight * info->nWidthBytes;
816 sizeAnd = info->nHeight * BITMAP_WIDTH_BYTES( info->nWidth, 1 );
817 if (!(handle = DirectResAlloc(hInstance, 0x10,
818 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
819 return 0;
820 ptr = (char *)GlobalLock16( handle );
821 memcpy( ptr, info, sizeof(*info) );
822 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
823 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
824 GlobalUnlock16( handle );
825 return handle;
829 /***********************************************************************
830 * CopyIcon16 (USER.368)
832 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
834 dprintf_icon( stddeb, "CopyIcon16: %04x %04x\n", hInstance, hIcon );
835 return CURSORICON_Copy( hInstance, hIcon );
839 /***********************************************************************
840 * CopyIcon32 (USER32.59)
842 HICON32 WINAPI CopyIcon32( HICON32 hIcon )
844 HTASK16 hTask = GetCurrentTask ();
845 TDB* pTask = (TDB *) GlobalLock16 (hTask);
846 dprintf_icon( stddeb, "CopyIcon32: %04x\n", hIcon );
847 return CURSORICON_Copy( pTask->hInstance, hIcon );
851 /***********************************************************************
852 * CopyCursor16 (USER.369)
854 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
856 dprintf_cursor( stddeb, "CopyCursor16: %04x %04x\n", hInstance, hCursor );
857 return CURSORICON_Copy( hInstance, hCursor );
861 /***********************************************************************
862 * DestroyIcon16 (USER.457)
864 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
866 return DestroyIcon32( hIcon );
870 /***********************************************************************
871 * DestroyIcon32 (USER32.132)
873 BOOL32 WINAPI DestroyIcon32( HICON32 hIcon )
875 dprintf_icon( stddeb, "DestroyIcon: %04x\n", hIcon );
876 /* FIXME: should check for OEM icon here */
877 return (FreeResource16( hIcon ) == 0);
881 /***********************************************************************
882 * DestroyCursor16 (USER.458)
884 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
886 return DestroyCursor32( hCursor );
890 /***********************************************************************
891 * DestroyCursor32 (USER32.131)
893 BOOL32 WINAPI DestroyCursor32( HCURSOR32 hCursor )
895 dprintf_cursor( stddeb, "DestroyCursor: %04x\n", hCursor );
896 /* FIXME: should check for OEM cursor here */
897 return (FreeResource16( hCursor ) == 0);
901 /***********************************************************************
902 * DrawIcon16 (USER.84)
904 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
906 return DrawIcon32( hdc, x, y, hIcon );
910 /***********************************************************************
911 * DrawIcon32 (USER32.158)
913 BOOL32 WINAPI DrawIcon32( HDC32 hdc, INT32 x, INT32 y, HICON32 hIcon )
915 CURSORICONINFO *ptr;
916 HDC32 hMemDC;
917 HBITMAP32 hXorBits, hAndBits;
918 COLORREF oldFg, oldBg;
920 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
921 if (!(hMemDC = CreateCompatibleDC32( hdc ))) return FALSE;
922 hAndBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, 1, 1,
923 (char *)(ptr+1) );
924 hXorBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
925 ptr->bBitsPerPixel, (char *)(ptr + 1)
926 + ptr->nHeight * BITMAP_WIDTH_BYTES(ptr->nWidth,1) );
927 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
928 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
930 if (hXorBits && hAndBits)
932 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
933 BitBlt32( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
934 SelectObject32( hMemDC, hXorBits );
935 BitBlt32(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
936 SelectObject32( hMemDC, hBitTemp );
938 DeleteDC32( hMemDC );
939 if (hXorBits) DeleteObject32( hXorBits );
940 if (hAndBits) DeleteObject32( hAndBits );
941 GlobalUnlock16( hIcon );
942 SetTextColor32( hdc, oldFg );
943 SetBkColor32( hdc, oldBg );
944 return TRUE;
948 /***********************************************************************
949 * DumpIcon (USER.459)
951 DWORD WINAPI DumpIcon( SEGPTR pInfo, WORD *lpLen,
952 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
954 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
955 int sizeAnd, sizeXor;
957 if (!info) return 0;
958 sizeXor = info->nHeight * info->nWidthBytes;
959 sizeAnd = info->nHeight * BITMAP_WIDTH_BYTES( info->nWidth, 1 );
960 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
961 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
962 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
963 return MAKELONG( sizeXor, sizeXor );
967 /***********************************************************************
968 * CURSORICON_SetCursor
970 * Change the X cursor. Helper function for SetCursor() and ShowCursor().
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 fprintf( stderr, "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 extern void _XInitImageFuncPtrs( XImage* );
1018 image->byte_order = MSBFirst;
1019 image->bitmap_bit_order = MSBFirst;
1020 image->bitmap_unit = 16;
1021 _XInitImageFuncPtrs(image);
1022 if (pixmapAll)
1023 XPutImage( display, pixmapAll, BITMAP_monoGC, image,
1024 0, 0, 0, 0, ptr->nWidth, ptr->nHeight * 2 );
1025 image->data = NULL;
1026 XDestroyImage( image );
1029 /* Now create the 2 pixmaps for bits and mask */
1031 pixmapBits = XCreatePixmap( display, rootWindow,
1032 ptr->nWidth, ptr->nHeight, 1 );
1033 pixmapMask = XCreatePixmap( display, rootWindow,
1034 ptr->nWidth, ptr->nHeight, 1 );
1036 /* Make sure everything went OK so far */
1038 if (pixmapBits && pixmapMask && pixmapAll)
1040 /* We have to do some magic here, as cursors are not fully
1041 * compatible between Windows and X11. Under X11, there
1042 * are only 3 possible color cursor: black, white and
1043 * masked. So we map the 4th Windows color (invert the
1044 * bits on the screen) to black. This require some boolean
1045 * arithmetic:
1047 * Windows | X11
1048 * Xor And Result | Bits Mask Result
1049 * 0 0 black | 0 1 background
1050 * 0 1 no change | X 0 no change
1051 * 1 0 white | 1 1 foreground
1052 * 1 1 inverted | 0 1 background
1054 * which gives:
1055 * Bits = 'Xor' and not 'And'
1056 * Mask = 'Xor' or not 'And'
1058 * FIXME: apparently some servers do support 'inverted' color.
1059 * I don't know if it's correct per the X spec, but maybe
1060 * we ought to take advantage of it. -- AJ
1062 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
1063 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
1064 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
1065 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
1066 XSetFunction( display, BITMAP_monoGC, GXandReverse );
1067 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
1068 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
1069 XSetFunction( display, BITMAP_monoGC, GXorReverse );
1070 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
1071 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
1072 XSetFunction( display, BITMAP_monoGC, GXcopy );
1073 fg.red = fg.green = fg.blue = 0xffff;
1074 bg.red = bg.green = bg.blue = 0x0000;
1075 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapMask,
1076 &fg, &bg, ptr->ptHotSpot.x, ptr->ptHotSpot.y );
1079 /* Now free everything */
1081 if (pixmapAll) XFreePixmap( display, pixmapAll );
1082 if (pixmapBits) XFreePixmap( display, pixmapBits );
1083 if (pixmapMask) XFreePixmap( display, pixmapMask );
1084 GlobalUnlock16( hCursor );
1087 if (cursor == None) return FALSE;
1088 if (CURSORICON_XCursor != None) XFreeCursor( display, CURSORICON_XCursor );
1089 CURSORICON_XCursor = cursor;
1091 if (rootWindow != DefaultRootWindow(display))
1093 /* Set the cursor on the desktop window */
1094 XDefineCursor( display, rootWindow, cursor );
1096 else
1098 /* Set the same cursor for all top-level windows */
1099 HWND32 hwnd = GetWindow32( GetDesktopWindow32(), GW_CHILD );
1100 while(hwnd)
1102 Window win = WIN_GetXWindow( hwnd );
1103 if (win) XDefineCursor( display, win, cursor );
1104 hwnd = GetWindow32( hwnd, GW_HWNDNEXT );
1107 return TRUE;
1111 /***********************************************************************
1112 * SetCursor16 (USER.69)
1114 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1116 return (HCURSOR16)SetCursor32( hCursor );
1120 /***********************************************************************
1121 * SetCursor32 (USER32.471)
1123 HCURSOR32 WINAPI SetCursor32( HCURSOR32 hCursor )
1125 HCURSOR32 hOldCursor;
1127 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1128 dprintf_cursor( stddeb, "SetCursor: %04x\n", hCursor );
1129 hOldCursor = hActiveCursor;
1130 hActiveCursor = hCursor;
1131 /* Change the cursor shape only if it is visible */
1132 if (CURSOR_ShowCount >= 0)
1133 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1134 return hOldCursor;
1138 /***********************************************************************
1139 * SetCursorPos16 (USER.70)
1141 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1143 SetCursorPos32( x, y );
1147 /***********************************************************************
1148 * SetCursorPos32 (USER32.473)
1150 BOOL32 WINAPI SetCursorPos32( INT32 x, INT32 y )
1152 dprintf_cursor( stddeb, "SetCursorPos: x=%d y=%d\n", x, y );
1153 XWarpPointer( display, rootWindow, rootWindow, 0, 0, 0, 0, x, y );
1154 return TRUE;
1158 /***********************************************************************
1159 * ShowCursor16 (USER.71)
1161 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1163 return ShowCursor32( bShow );
1167 /***********************************************************************
1168 * ShowCursor32 (USER32.529)
1170 INT32 WINAPI ShowCursor32( BOOL32 bShow )
1172 dprintf_cursor( stddeb, "ShowCursor: %d, count=%d\n",
1173 bShow, CURSOR_ShowCount );
1175 if (bShow)
1177 if (++CURSOR_ShowCount == 0) /* Show it */
1178 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1180 else
1182 if (--CURSOR_ShowCount == -1) /* Hide it */
1183 CALL_LARGE_STACK( CURSORICON_SetCursor, 0 );
1185 return CURSOR_ShowCount;
1189 /***********************************************************************
1190 * GetCursor16 (USER.247)
1192 HCURSOR16 WINAPI GetCursor16(void)
1194 return hActiveCursor;
1198 /***********************************************************************
1199 * GetCursor32 (USER32.226)
1201 HCURSOR32 WINAPI GetCursor32(void)
1203 return hActiveCursor;
1207 /***********************************************************************
1208 * ClipCursor16 (USER.16)
1210 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1212 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1213 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1214 return TRUE;
1218 /***********************************************************************
1219 * ClipCursor32 (USER32.52)
1221 BOOL32 WINAPI ClipCursor32( const RECT32 *rect )
1223 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1224 else CopyRect32( &CURSOR_ClipRect, rect );
1225 return TRUE;
1229 /***********************************************************************
1230 * GetCursorPos16 (USER.17)
1232 void WINAPI GetCursorPos16( POINT16 *pt )
1234 Window root, child;
1235 int rootX, rootY, childX, childY;
1236 unsigned int mousebut;
1238 if (!pt) return;
1239 if (!XQueryPointer( display, rootWindow, &root, &child,
1240 &rootX, &rootY, &childX, &childY, &mousebut ))
1241 pt->x = pt->y = 0;
1242 else
1244 pt->x = childX;
1245 pt->y = childY;
1247 dprintf_cursor(stddeb, "GetCursorPos: ret=%d,%d\n", pt->x, pt->y );
1251 /***********************************************************************
1252 * GetCursorPos32 (USER32.228)
1254 void WINAPI GetCursorPos32( POINT32 *pt )
1256 POINT16 pt16;
1257 GetCursorPos16( &pt16 );
1258 if (pt) CONV_POINT16TO32( &pt16, pt );
1262 /***********************************************************************
1263 * GetClipCursor16 (USER.309)
1265 void WINAPI GetClipCursor16( RECT16 *rect )
1267 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1271 /***********************************************************************
1272 * GetClipCursor32 (USER32.220)
1274 void WINAPI GetClipCursor32( RECT32 *rect )
1276 if (rect) CopyRect32( rect, &CURSOR_ClipRect );
1279 /**********************************************************************
1280 * LookupIconIdFromDirectoryEx16 (USER.364)
1282 * FIXME: exact parameter sizes
1284 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1285 INT16 width, INT16 height, UINT16 cFlag )
1287 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1288 UINT16 retVal = 0;
1289 if( dir && !dir->idReserved && (dir->idType & 3) )
1291 int colors = (cFlag == LR_MONOCHROME) ? 2 : COLOR_GetSystemPaletteSize();
1292 if( bIcon )
1294 ICONDIRENTRY* entry;
1295 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1296 if( entry ) retVal = entry->wResId;
1298 else
1300 CURSORDIRENTRY* entry;
1301 entry = CURSORICON_FindBestCursor( dir, width, height );
1302 if( entry ) retVal = entry->wResId;
1305 else dprintf_cursor(stddeb,"IconId: invalid resource directory\n");
1306 return retVal;
1309 /**********************************************************************
1310 * LookupIconIdFromDirectoryEx32 (USER32.379)
1312 INT32 WINAPI LookupIconIdFromDirectoryEx32( LPBYTE dir, BOOL32 bIcon,
1313 INT32 width, INT32 height, UINT32 cFlag )
1315 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1318 /**********************************************************************
1319 * LookupIconIdFromDirectory (USER.???)
1321 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1323 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1324 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1325 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1328 /**********************************************************************
1329 * LookupIconIdFromDirectory (USER32.378)
1331 INT32 WINAPI LookupIconIdFromDirectory32( LPBYTE dir, BOOL32 bIcon )
1333 return LookupIconIdFromDirectoryEx32( dir, bIcon,
1334 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1335 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1338 /**********************************************************************
1339 * GetIconID (USER.455)
1341 WORD WINAPI GetIconID( HGLOBAL16 hResource, DWORD resType )
1343 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1345 dprintf_cursor( stddeb, "GetIconID: hRes=%04x, entries=%i\n",
1346 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1348 switch(resType)
1350 case RT_CURSOR:
1351 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1352 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1353 case RT_ICON:
1354 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1355 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1356 default:
1357 fprintf( stderr, "GetIconID: invalid res type %ld\n", resType );
1359 return 0;
1362 /**********************************************************************
1363 * LoadCursorIconHandler (USER.336)
1365 * Supposed to load resources of Windows 2.x applications.
1367 HGLOBAL16 WINAPI LoadCursorIconHandler( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1369 fprintf(stderr,"hModule[%04x]: old 2.x resources are not supported!\n", hModule);
1370 return (HGLOBAL16)0;
1373 /**********************************************************************
1374 * LoadDIBIconHandler (USER.357)
1376 * RT_ICON resource loader, installed by USER_SignalProc when module
1377 * is initialized.
1379 HGLOBAL16 WINAPI LoadDIBIconHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1381 /* If hResource is zero we must allocate a new memory block, if it's
1382 * non-zero but GlobalLock() returns NULL then it was discarded and
1383 * we have to recommit some memory, otherwise we just need to check
1384 * the block size. See LoadProc() in 16-bit SDK for more.
1387 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1388 if( hMemObj )
1390 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1391 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1392 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1393 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1395 return hMemObj;
1398 /**********************************************************************
1399 * LoadDIBCursorHandler (USER.356)
1401 * RT_CURSOR resource loader. Same as above.
1403 HGLOBAL16 WINAPI LoadDIBCursorHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1405 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1406 if( hMemObj )
1408 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1409 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1410 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1411 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1413 return hMemObj;
1416 /**********************************************************************
1417 * LoadIconHandler (USER.456)
1419 HICON16 WINAPI LoadIconHandler( HGLOBAL16 hResource, BOOL16 bNew )
1421 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1423 dprintf_cursor(stddeb,"LoadIconHandler: hRes=%04x\n",hResource);
1425 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1426 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1429 /***********************************************************************
1430 * LoadCursorW (USER32.361)
1432 HCURSOR32 WINAPI LoadCursor32W(HINSTANCE32 hInstance, LPCWSTR name)
1434 return CURSORICON_Load32( hInstance, name,
1435 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
1438 /***********************************************************************
1439 * LoadCursorA (USER32.358)
1441 HCURSOR32 WINAPI LoadCursor32A(HINSTANCE32 hInstance, LPCSTR name)
1443 HCURSOR32 res=0;
1444 if(!HIWORD(name))
1445 return LoadCursor32W(hInstance,(LPCWSTR)name);
1446 else
1448 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1449 res = LoadCursor32W(hInstance, uni);
1450 HeapFree( GetProcessHeap(), 0, uni);
1452 return res;
1455 /***********************************************************************
1456 * LoadIconW (USER32.363)
1458 HICON32 WINAPI LoadIcon32W(HINSTANCE32 hInstance, LPCWSTR name)
1460 return CURSORICON_Load32( hInstance, name,
1461 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
1462 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE );
1465 /***********************************************************************
1466 * LoadIconA (USER32.362)
1468 HICON32 WINAPI LoadIcon32A(HINSTANCE32 hInstance, LPCSTR name)
1470 HICON32 res=0;
1472 if( !HIWORD(name) )
1473 return LoadIcon32W(hInstance, (LPCWSTR)name);
1474 else
1476 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1477 res = LoadIcon32W( hInstance, uni );
1478 HeapFree( GetProcessHeap(), 0, uni );
1480 return res;
1483 /**********************************************************************
1484 * GetIconInfo (USER32.241)
1486 BOOL32 WINAPI GetIconInfo(HICON32 hIcon,LPICONINFO iconinfo) {
1487 CURSORICONINFO *ciconinfo;
1489 ciconinfo = GlobalLock16(hIcon);
1490 if (!ciconinfo)
1491 return FALSE;
1492 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1493 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1494 iconinfo->fIcon = TRUE; /* hmm */
1495 /* FIXME ... add both bitmaps */
1496 return TRUE;
1499 /**********************************************************************
1500 * CreateIconIndirect (USER32.78)
1502 HICON32 WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1503 BITMAPOBJ *bmpXor,*bmpAnd;
1504 HICON32 hObj;
1505 int sizeXor,sizeAnd;
1507 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1508 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1510 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1511 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1513 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1514 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1515 if (hObj)
1517 CURSORICONINFO *info;
1519 info = (CURSORICONINFO *)GlobalLock16( hObj );
1520 info->ptHotSpot.x = iconinfo->xHotspot;
1521 info->ptHotSpot.y = iconinfo->yHotspot;
1522 info->nWidth = bmpXor->bitmap.bmWidth;
1523 info->nHeight = bmpXor->bitmap.bmHeight;
1524 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1525 info->bPlanes = bmpXor->bitmap.bmPlanes;
1526 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1528 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1530 GetBitmapBits32( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1531 GetBitmapBits32( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1532 GlobalUnlock16( hObj );
1534 return hObj;
1537 /**********************************************************************
1538 * DrawIconEx16 (USER.394)
1541 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1542 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1543 HBRUSH16 hbr, UINT16 flags)
1545 return DrawIconEx32 (hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1546 istep, hbr, flags);
1549 /**********************************************************************
1550 * DrawIconEx32 (USER32.160)
1553 BOOL32 WINAPI DrawIconEx32 (HDC32 hdc, INT32 x0, INT32 y0, HICON32 hIcon,
1554 INT32 cxWidth, INT32 cyWidth, UINT32 istep,
1555 HBRUSH32 hbr, UINT32 flags)
1557 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1558 HDC32 hMemDC = CreateCompatibleDC32 (hdc);
1559 BOOL32 result = FALSE;
1561 dprintf_icon (stddeb, "DrawIconEx32: part stub.\n");
1563 if (hMemDC && ptr)
1565 HBITMAP32 hXorBits, hAndBits;
1566 COLORREF oldFg, oldBg;
1568 /* Calculate the size of the destination image. */
1569 if (cxWidth == 0)
1570 if (flags & DI_DEFAULTSIZE)
1571 cxWidth = GetSystemMetrics32 (SM_CXICON);
1572 else
1573 cxWidth = ptr->nWidth;
1574 if (cyWidth == 0)
1575 if (flags & DI_DEFAULTSIZE)
1576 cyWidth = GetSystemMetrics32 (SM_CYICON);
1577 else
1578 cyWidth = ptr->nHeight;
1580 hXorBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
1581 ptr->bPlanes, ptr->bBitsPerPixel,
1582 (char *)(ptr + 1)
1583 + ptr->nHeight *
1584 BITMAP_WIDTH_BYTES(ptr->nWidth,1) );
1585 hAndBits = CreateBitmap32 ( cxWidth, cyWidth,
1586 1, 1, (char *)(ptr+1) );
1587 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
1588 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
1590 if (hXorBits && hAndBits)
1592 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
1593 if (flags & DI_MASK)
1594 BitBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1595 hMemDC, 0, 0, SRCAND);
1596 SelectObject32( hMemDC, hXorBits );
1597 if (flags & DI_IMAGE)
1598 BitBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1599 hMemDC, 0, 0, SRCPAINT);
1600 SelectObject32( hMemDC, hBitTemp );
1601 result = TRUE;
1604 SetTextColor32( hdc, oldFg );
1605 SetBkColor32( hdc, oldBg );
1606 if (hXorBits) DeleteObject32( hXorBits );
1607 if (hAndBits) DeleteObject32( hAndBits );
1609 if (hMemDC) DeleteDC32( hMemDC );
1610 GlobalUnlock16( hIcon );
1611 return result;