Release 971221
[wine.git] / objects / cursoricon.c
blobd77a5f772ab9a1d9e70c016b5f60861db60eb0d2
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( hInstance, &info, lpANDbits, lpXORbits );
768 /***********************************************************************
769 * CreateIcon16 (USER.407)
771 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
772 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
773 LPCVOID lpANDbits, LPCVOID lpXORbits )
775 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
777 dprintf_icon( stddeb, "CreateIcon: %dx%dx%d, xor=%p, and=%p\n",
778 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
779 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
783 /***********************************************************************
784 * CreateIcon32 (USER32.74)
786 HICON32 WINAPI CreateIcon32( HINSTANCE32 hInstance, INT32 nWidth,
787 INT32 nHeight, BYTE bPlanes, BYTE bBitsPixel,
788 LPCVOID lpANDbits, LPCVOID lpXORbits )
790 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
792 dprintf_icon( stddeb, "CreateIcon: %dx%dx%d, xor=%p, and=%p\n",
793 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
794 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
798 /***********************************************************************
799 * CreateCursorIconIndirect (USER.408)
801 HGLOBAL16 WINAPI CreateCursorIconIndirect( HINSTANCE16 hInstance,
802 CURSORICONINFO *info,
803 LPCVOID lpANDbits,
804 LPCVOID lpXORbits )
806 HGLOBAL16 handle;
807 char *ptr;
808 int sizeAnd, sizeXor;
810 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
811 if (!hInstance || !lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
812 info->nWidthBytes = BITMAP_WIDTH_BYTES(info->nWidth,info->bBitsPerPixel);
813 sizeXor = info->nHeight * info->nWidthBytes;
814 sizeAnd = info->nHeight * BITMAP_WIDTH_BYTES( info->nWidth, 1 );
815 if (!(handle = DirectResAlloc(hInstance, 0x10,
816 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
817 return 0;
818 ptr = (char *)GlobalLock16( handle );
819 memcpy( ptr, info, sizeof(*info) );
820 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
821 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
822 GlobalUnlock16( handle );
823 return handle;
827 /***********************************************************************
828 * CopyIcon16 (USER.368)
830 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
832 dprintf_icon( stddeb, "CopyIcon16: %04x %04x\n", hInstance, hIcon );
833 return CURSORICON_Copy( hInstance, hIcon );
837 /***********************************************************************
838 * CopyIcon32 (USER32.59)
840 HICON32 WINAPI CopyIcon32( HICON32 hIcon )
842 HTASK16 hTask = GetCurrentTask ();
843 TDB* pTask = (TDB *) GlobalLock16 (hTask);
844 dprintf_icon( stddeb, "CopyIcon32: %04x\n", hIcon );
845 return CURSORICON_Copy( pTask->hInstance, hIcon );
849 /***********************************************************************
850 * CopyCursor16 (USER.369)
852 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
854 dprintf_cursor( stddeb, "CopyCursor16: %04x %04x\n", hInstance, hCursor );
855 return CURSORICON_Copy( hInstance, hCursor );
859 /***********************************************************************
860 * DestroyIcon16 (USER.457)
862 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
864 return DestroyIcon32( hIcon );
868 /***********************************************************************
869 * DestroyIcon32 (USER32.132)
871 BOOL32 WINAPI DestroyIcon32( HICON32 hIcon )
873 dprintf_icon( stddeb, "DestroyIcon: %04x\n", hIcon );
874 /* FIXME: should check for OEM icon here */
875 return (FreeResource16( hIcon ) == 0);
879 /***********************************************************************
880 * DestroyCursor16 (USER.458)
882 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
884 return DestroyCursor32( hCursor );
888 /***********************************************************************
889 * DestroyCursor32 (USER32.131)
891 BOOL32 WINAPI DestroyCursor32( HCURSOR32 hCursor )
893 dprintf_cursor( stddeb, "DestroyCursor: %04x\n", hCursor );
894 /* FIXME: should check for OEM cursor here */
895 return (FreeResource16( hCursor ) != 0);
899 /***********************************************************************
900 * DrawIcon16 (USER.84)
902 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
904 return DrawIcon32( hdc, x, y, hIcon );
908 /***********************************************************************
909 * DrawIcon32 (USER32.158)
911 BOOL32 WINAPI DrawIcon32( HDC32 hdc, INT32 x, INT32 y, HICON32 hIcon )
913 CURSORICONINFO *ptr;
914 HDC32 hMemDC;
915 HBITMAP32 hXorBits, hAndBits;
916 COLORREF oldFg, oldBg;
918 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
919 if (!(hMemDC = CreateCompatibleDC32( hdc ))) return FALSE;
920 hAndBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, 1, 1,
921 (char *)(ptr+1) );
922 hXorBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
923 ptr->bBitsPerPixel, (char *)(ptr + 1)
924 + ptr->nHeight * BITMAP_WIDTH_BYTES(ptr->nWidth,1) );
925 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
926 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
928 if (hXorBits && hAndBits)
930 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
931 BitBlt32( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
932 SelectObject32( hMemDC, hXorBits );
933 BitBlt32(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
934 SelectObject32( hMemDC, hBitTemp );
936 DeleteDC32( hMemDC );
937 if (hXorBits) DeleteObject32( hXorBits );
938 if (hAndBits) DeleteObject32( hAndBits );
939 GlobalUnlock16( hIcon );
940 SetTextColor32( hdc, oldFg );
941 SetBkColor32( hdc, oldBg );
942 return TRUE;
946 /***********************************************************************
947 * DumpIcon (USER.459)
949 DWORD WINAPI DumpIcon( SEGPTR pInfo, WORD *lpLen,
950 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
952 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
953 int sizeAnd, sizeXor;
955 if (!info) return 0;
956 sizeXor = info->nHeight * info->nWidthBytes;
957 sizeAnd = info->nHeight * BITMAP_WIDTH_BYTES( info->nWidth, 1 );
958 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
959 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
960 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
961 return MAKELONG( sizeXor, sizeXor );
965 /***********************************************************************
966 * CURSORICON_SetCursor
968 * Change the X cursor. Helper function for SetCursor() and ShowCursor().
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 fprintf( stderr, "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 extern void _XInitImageFuncPtrs( XImage* );
1016 image->byte_order = MSBFirst;
1017 image->bitmap_bit_order = MSBFirst;
1018 image->bitmap_unit = 16;
1019 _XInitImageFuncPtrs(image);
1020 if (pixmapAll)
1021 XPutImage( display, pixmapAll, BITMAP_monoGC, image,
1022 0, 0, 0, 0, ptr->nWidth, ptr->nHeight * 2 );
1023 image->data = NULL;
1024 XDestroyImage( image );
1027 /* Now create the 2 pixmaps for bits and mask */
1029 pixmapBits = XCreatePixmap( display, rootWindow,
1030 ptr->nWidth, ptr->nHeight, 1 );
1031 pixmapMask = XCreatePixmap( display, rootWindow,
1032 ptr->nWidth, ptr->nHeight, 1 );
1034 /* Make sure everything went OK so far */
1036 if (pixmapBits && pixmapMask && pixmapAll)
1038 /* We have to do some magic here, as cursors are not fully
1039 * compatible between Windows and X11. Under X11, there
1040 * are only 3 possible color cursor: black, white and
1041 * masked. So we map the 4th Windows color (invert the
1042 * bits on the screen) to black. This require some boolean
1043 * arithmetic:
1045 * Windows | X11
1046 * Xor And Result | Bits Mask Result
1047 * 0 0 black | 0 1 background
1048 * 0 1 no change | X 0 no change
1049 * 1 0 white | 1 1 foreground
1050 * 1 1 inverted | 0 1 background
1052 * which gives:
1053 * Bits = 'Xor' and not 'And'
1054 * Mask = 'Xor' or not 'And'
1056 * FIXME: apparently some servers do support 'inverted' color.
1057 * I don't know if it's correct per the X spec, but maybe
1058 * we ought to take advantage of it. -- AJ
1060 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
1061 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
1062 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
1063 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
1064 XSetFunction( display, BITMAP_monoGC, GXandReverse );
1065 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
1066 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
1067 XSetFunction( display, BITMAP_monoGC, GXorReverse );
1068 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
1069 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
1070 XSetFunction( display, BITMAP_monoGC, GXcopy );
1071 fg.red = fg.green = fg.blue = 0xffff;
1072 bg.red = bg.green = bg.blue = 0x0000;
1073 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapMask,
1074 &fg, &bg, ptr->ptHotSpot.x, ptr->ptHotSpot.y );
1077 /* Now free everything */
1079 if (pixmapAll) XFreePixmap( display, pixmapAll );
1080 if (pixmapBits) XFreePixmap( display, pixmapBits );
1081 if (pixmapMask) XFreePixmap( display, pixmapMask );
1082 GlobalUnlock16( hCursor );
1085 if (cursor == None) return FALSE;
1086 if (CURSORICON_XCursor != None) XFreeCursor( display, CURSORICON_XCursor );
1087 CURSORICON_XCursor = cursor;
1089 if (rootWindow != DefaultRootWindow(display))
1091 /* Set the cursor on the desktop window */
1092 XDefineCursor( display, rootWindow, cursor );
1094 else
1096 /* Set the same cursor for all top-level windows */
1097 HWND32 hwnd = GetWindow32( GetDesktopWindow32(), GW_CHILD );
1098 while(hwnd)
1100 Window win = WIN_GetXWindow( hwnd );
1101 if (win) 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.471)
1121 HCURSOR32 WINAPI SetCursor32( HCURSOR32 hCursor )
1123 HCURSOR32 hOldCursor;
1125 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1126 dprintf_cursor( stddeb, "SetCursor: %04x\n", hCursor );
1127 hOldCursor = hActiveCursor;
1128 hActiveCursor = hCursor;
1129 /* Change the cursor shape only if it is visible */
1130 if (CURSOR_ShowCount >= 0)
1131 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1132 return hOldCursor;
1136 /***********************************************************************
1137 * SetCursorPos16 (USER.70)
1139 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1141 SetCursorPos32( x, y );
1145 /***********************************************************************
1146 * SetCursorPos32 (USER32.473)
1148 BOOL32 WINAPI SetCursorPos32( INT32 x, INT32 y )
1150 dprintf_cursor( stddeb, "SetCursorPos: x=%d y=%d\n", x, y );
1151 XWarpPointer( display, rootWindow, rootWindow, 0, 0, 0, 0, x, y );
1152 return TRUE;
1156 /***********************************************************************
1157 * ShowCursor16 (USER.71)
1159 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1161 return ShowCursor32( bShow );
1165 /***********************************************************************
1166 * ShowCursor32 (USER32.529)
1168 INT32 WINAPI ShowCursor32( BOOL32 bShow )
1170 dprintf_cursor( stddeb, "ShowCursor: %d, count=%d\n",
1171 bShow, CURSOR_ShowCount );
1173 if (bShow)
1175 if (++CURSOR_ShowCount == 0) /* Show it */
1176 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1178 else
1180 if (--CURSOR_ShowCount == -1) /* Hide it */
1181 CALL_LARGE_STACK( CURSORICON_SetCursor, 0 );
1183 return CURSOR_ShowCount;
1187 /***********************************************************************
1188 * GetCursor16 (USER.247)
1190 HCURSOR16 WINAPI GetCursor16(void)
1192 return hActiveCursor;
1196 /***********************************************************************
1197 * GetCursor32 (USER32.226)
1199 HCURSOR32 WINAPI GetCursor32(void)
1201 return hActiveCursor;
1205 /***********************************************************************
1206 * ClipCursor16 (USER.16)
1208 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1210 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1211 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1212 return TRUE;
1216 /***********************************************************************
1217 * ClipCursor32 (USER32.52)
1219 BOOL32 WINAPI ClipCursor32( const RECT32 *rect )
1221 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1222 else CopyRect32( &CURSOR_ClipRect, rect );
1223 return TRUE;
1227 /***********************************************************************
1228 * GetCursorPos16 (USER.17)
1230 void WINAPI GetCursorPos16( POINT16 *pt )
1232 Window root, child;
1233 int rootX, rootY, childX, childY;
1234 unsigned int mousebut;
1236 if (!pt) return;
1237 if (!XQueryPointer( display, rootWindow, &root, &child,
1238 &rootX, &rootY, &childX, &childY, &mousebut ))
1239 pt->x = pt->y = 0;
1240 else
1242 pt->x = childX;
1243 pt->y = childY;
1245 dprintf_cursor(stddeb, "GetCursorPos: ret=%d,%d\n", pt->x, pt->y );
1249 /***********************************************************************
1250 * GetCursorPos32 (USER32.228)
1252 void WINAPI GetCursorPos32( POINT32 *pt )
1254 POINT16 pt16;
1255 GetCursorPos16( &pt16 );
1256 if (pt) CONV_POINT16TO32( &pt16, pt );
1260 /***********************************************************************
1261 * GetClipCursor16 (USER.309)
1263 void WINAPI GetClipCursor16( RECT16 *rect )
1265 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1269 /***********************************************************************
1270 * GetClipCursor32 (USER32.220)
1272 void WINAPI GetClipCursor32( RECT32 *rect )
1274 if (rect) CopyRect32( rect, &CURSOR_ClipRect );
1277 /**********************************************************************
1278 * LookupIconIdFromDirectoryEx16 (USER.364)
1280 * FIXME: exact parameter sizes
1282 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1283 INT16 width, INT16 height, UINT16 cFlag )
1285 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1286 UINT16 retVal = 0;
1287 if( dir && !dir->idReserved && (dir->idType & 3) )
1289 int colors = (cFlag == LR_MONOCHROME) ? 2 : COLOR_GetSystemPaletteSize();
1290 if( bIcon )
1292 ICONDIRENTRY* entry;
1293 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1294 if( entry ) retVal = entry->wResId;
1296 else
1298 CURSORDIRENTRY* entry;
1299 entry = CURSORICON_FindBestCursor( dir, width, height );
1300 if( entry ) retVal = entry->wResId;
1303 else dprintf_cursor(stddeb,"IconId: invalid resource directory\n");
1304 return retVal;
1307 /**********************************************************************
1308 * LookupIconIdFromDirectoryEx32 (USER32.379)
1310 INT32 WINAPI LookupIconIdFromDirectoryEx32( LPBYTE dir, BOOL32 bIcon,
1311 INT32 width, INT32 height, UINT32 cFlag )
1313 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1316 /**********************************************************************
1317 * LookupIconIdFromDirectory (USER.???)
1319 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1321 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1322 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1323 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1326 /**********************************************************************
1327 * LookupIconIdFromDirectory (USER32.378)
1329 INT32 WINAPI LookupIconIdFromDirectory32( LPBYTE dir, BOOL32 bIcon )
1331 return LookupIconIdFromDirectoryEx32( dir, bIcon,
1332 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1333 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1336 /**********************************************************************
1337 * GetIconID (USER.455)
1339 WORD WINAPI GetIconID( HGLOBAL16 hResource, DWORD resType )
1341 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1343 dprintf_cursor( stddeb, "GetIconID: hRes=%04x, entries=%i\n",
1344 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1346 switch(resType)
1348 case RT_CURSOR:
1349 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1350 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1351 case RT_ICON:
1352 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1353 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1354 default:
1355 fprintf( stderr, "GetIconID: invalid res type %ld\n", resType );
1357 return 0;
1360 /**********************************************************************
1361 * LoadCursorIconHandler (USER.336)
1363 * Supposed to load resources of Windows 2.x applications.
1365 HGLOBAL16 WINAPI LoadCursorIconHandler( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1367 fprintf(stderr,"hModule[%04x]: old 2.x resources are not supported!\n", hModule);
1368 return (HGLOBAL16)0;
1371 /**********************************************************************
1372 * LoadDIBIconHandler (USER.357)
1374 * RT_ICON resource loader, installed by USER_SignalProc when module
1375 * is initialized.
1377 HGLOBAL16 WINAPI LoadDIBIconHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1379 /* If hResource is zero we must allocate a new memory block, if it's
1380 * non-zero but GlobalLock() returns NULL then it was discarded and
1381 * we have to recommit some memory, otherwise we just need to check
1382 * the block size. See LoadProc() in 16-bit SDK for more.
1385 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1386 if( hMemObj )
1388 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1389 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1390 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1391 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1393 return hMemObj;
1396 /**********************************************************************
1397 * LoadDIBCursorHandler (USER.356)
1399 * RT_CURSOR resource loader. Same as above.
1401 HGLOBAL16 WINAPI LoadDIBCursorHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1403 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1404 if( hMemObj )
1406 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1407 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1408 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1409 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1411 return hMemObj;
1414 /**********************************************************************
1415 * LoadIconHandler (USER.456)
1417 HICON16 WINAPI LoadIconHandler( HGLOBAL16 hResource, BOOL16 bNew )
1419 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1421 dprintf_cursor(stddeb,"LoadIconHandler: hRes=%04x\n",hResource);
1423 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1424 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1427 /***********************************************************************
1428 * LoadCursorW (USER32.361)
1430 HCURSOR32 WINAPI LoadCursor32W(HINSTANCE32 hInstance, LPCWSTR name)
1432 return CURSORICON_Load32( hInstance, name,
1433 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
1436 /***********************************************************************
1437 * LoadCursorA (USER32.358)
1439 HCURSOR32 WINAPI LoadCursor32A(HINSTANCE32 hInstance, LPCSTR name)
1441 HCURSOR32 res=0;
1442 if(!HIWORD(name))
1443 return LoadCursor32W(hInstance,(LPCWSTR)name);
1444 else
1446 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1447 res = LoadCursor32W(hInstance, uni);
1448 HeapFree( GetProcessHeap(), 0, uni);
1450 return res;
1453 /***********************************************************************
1454 * LoadIconW (USER32.363)
1456 HICON32 WINAPI LoadIcon32W(HINSTANCE32 hInstance, LPCWSTR name)
1458 return CURSORICON_Load32( hInstance, name,
1459 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
1460 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE );
1463 /***********************************************************************
1464 * LoadIconA (USER32.362)
1466 HICON32 WINAPI LoadIcon32A(HINSTANCE32 hInstance, LPCSTR name)
1468 HICON32 res=0;
1470 if( !HIWORD(name) )
1471 return LoadIcon32W(hInstance, (LPCWSTR)name);
1472 else
1474 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1475 res = LoadIcon32W( hInstance, uni );
1476 HeapFree( GetProcessHeap(), 0, uni );
1478 return res;
1481 /**********************************************************************
1482 * GetIconInfo (USER32.241)
1484 BOOL32 WINAPI GetIconInfo(HICON32 hIcon,LPICONINFO iconinfo) {
1485 CURSORICONINFO *ciconinfo;
1487 ciconinfo = GlobalLock16(hIcon);
1488 if (!ciconinfo)
1489 return FALSE;
1490 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1491 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1492 iconinfo->fIcon = TRUE; /* hmm */
1493 /* FIXME ... add both bitmaps */
1494 return TRUE;
1497 /**********************************************************************
1498 * CreateIconIndirect (USER32.78)
1500 HICON32 WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1501 BITMAPOBJ *bmpXor,*bmpAnd;
1502 HICON32 hObj;
1503 int sizeXor,sizeAnd;
1505 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1506 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1508 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1509 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1511 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1512 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1513 if (hObj)
1515 CURSORICONINFO *info;
1517 info = (CURSORICONINFO *)GlobalLock16( hObj );
1518 info->ptHotSpot.x = iconinfo->xHotspot;
1519 info->ptHotSpot.y = iconinfo->yHotspot;
1520 info->nWidth = bmpXor->bitmap.bmWidth;
1521 info->nHeight = bmpXor->bitmap.bmHeight;
1522 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1523 info->bPlanes = bmpXor->bitmap.bmPlanes;
1524 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1526 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1528 GetBitmapBits32( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1529 GetBitmapBits32( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1530 GlobalUnlock16( hObj );
1532 return hObj;
1535 /**********************************************************************
1536 * DrawIconEx16 (USER.394)
1539 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1540 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1541 HBRUSH16 hbr, UINT16 flags)
1543 return DrawIconEx32 (hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1544 istep, hbr, flags);
1547 /**********************************************************************
1548 * DrawIconEx32 (USER32.160)
1551 BOOL32 WINAPI DrawIconEx32 (HDC32 hdc, INT32 x0, INT32 y0, HICON32 hIcon,
1552 INT32 cxWidth, INT32 cyWidth, UINT32 istep,
1553 HBRUSH32 hbr, UINT32 flags)
1555 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1556 HDC32 hMemDC = CreateCompatibleDC32 (hdc);
1557 BOOL32 result = FALSE;
1559 dprintf_icon (stddeb, "DrawIconEx32: part stub.\n");
1561 if (hMemDC && ptr)
1563 HBITMAP32 hXorBits, hAndBits;
1564 COLORREF oldFg, oldBg;
1566 /* Calculate the size of the destination image. */
1567 if (cxWidth == 0)
1568 if (flags & DI_DEFAULTSIZE)
1569 cxWidth = GetSystemMetrics32 (SM_CXICON);
1570 else
1571 cxWidth = ptr->nWidth;
1572 if (cyWidth == 0)
1573 if (flags & DI_DEFAULTSIZE)
1574 cyWidth = GetSystemMetrics32 (SM_CYICON);
1575 else
1576 cyWidth = ptr->nHeight;
1578 hXorBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
1579 ptr->bPlanes, ptr->bBitsPerPixel,
1580 (char *)(ptr + 1)
1581 + ptr->nHeight *
1582 BITMAP_WIDTH_BYTES(ptr->nWidth,1) );
1583 hAndBits = CreateBitmap32 ( cxWidth, cyWidth,
1584 1, 1, (char *)(ptr+1) );
1585 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
1586 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
1588 if (hXorBits && hAndBits)
1590 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
1591 if (flags & DI_MASK)
1592 BitBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1593 hMemDC, 0, 0, SRCAND);
1594 SelectObject32( hMemDC, hXorBits );
1595 if (flags & DI_IMAGE)
1596 BitBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1597 hMemDC, 0, 0, SRCPAINT);
1598 SelectObject32( hMemDC, hBitTemp );
1599 result = TRUE;
1602 SetTextColor32( hdc, oldFg );
1603 SetBkColor32( hdc, oldBg );
1604 if (hXorBits) DeleteObject32( hXorBits );
1605 if (hAndBits) DeleteObject32( hAndBits );
1607 if (hMemDC) DeleteDC32( hMemDC );
1608 GlobalUnlock16( hIcon );
1609 return result;