Release 980118
[wine/multimedia.git] / objects / cursoricon.c
bloba7e77c4da708d734de23a1f9e7ced3647de8c054
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"
45 #include "keyboard.h"
47 extern UINT16 COLOR_GetSystemPaletteSize();
49 Cursor CURSORICON_XCursor = None; /* Current X cursor */
50 static HCURSOR32 hActiveCursor = 0; /* Active cursor */
51 static INT32 CURSOR_ShowCount = 0; /* Cursor display count */
52 static RECT32 CURSOR_ClipRect; /* Cursor clipping rect */
54 /**********************************************************************
55 * CURSORICON_FindBestIcon
57 * Find the icon closest to the requested size and number of colors.
59 static ICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
60 int height, int colors )
62 int i, maxcolors, maxwidth, maxheight;
63 ICONDIRENTRY *entry, *bestEntry = NULL;
65 if (dir->idCount < 1)
67 fprintf( stderr, "Icon: empty directory!\n" );
68 return NULL;
70 if (dir->idCount == 1) return &dir->idEntries[0].icon; /* No choice... */
72 /* First find the exact size with less colors */
74 maxcolors = 0;
75 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
76 if ((entry->bWidth == width) && (entry->bHeight == height) &&
77 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
79 bestEntry = entry;
80 maxcolors = entry->bColorCount;
82 if (bestEntry) return bestEntry;
84 /* First find the exact size with more colors */
86 maxcolors = 255;
87 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
88 if ((entry->bWidth == width) && (entry->bHeight == height) &&
89 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
91 bestEntry = entry;
92 maxcolors = entry->bColorCount;
94 if (bestEntry) return bestEntry;
96 /* Now find a smaller one with less colors */
98 maxcolors = maxwidth = maxheight = 0;
99 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
100 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
101 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
102 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
104 bestEntry = entry;
105 maxwidth = entry->bWidth;
106 maxheight = entry->bHeight;
107 maxcolors = entry->bColorCount;
109 if (bestEntry) return bestEntry;
111 /* Now find a smaller one with more colors */
113 maxcolors = 255;
114 maxwidth = maxheight = 0;
115 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
116 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
117 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
118 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
120 bestEntry = entry;
121 maxwidth = entry->bWidth;
122 maxheight = entry->bHeight;
123 maxcolors = entry->bColorCount;
125 if (bestEntry) return bestEntry;
127 /* Now find a larger one with less colors */
129 maxcolors = 0;
130 maxwidth = maxheight = 255;
131 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
132 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
133 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
135 bestEntry = entry;
136 maxwidth = entry->bWidth;
137 maxheight = entry->bHeight;
138 maxcolors = entry->bColorCount;
140 if (bestEntry) return bestEntry;
142 /* Now find a larger one with more colors */
144 maxcolors = maxwidth = maxheight = 255;
145 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
146 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
147 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
149 bestEntry = entry;
150 maxwidth = entry->bWidth;
151 maxheight = entry->bHeight;
152 maxcolors = entry->bColorCount;
155 return bestEntry;
159 /**********************************************************************
160 * CURSORICON_FindBestCursor
162 * Find the cursor closest to the requested size.
164 static CURSORDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
165 int width, int height )
167 int i, maxwidth, maxheight;
168 CURSORDIRENTRY *entry, *bestEntry = NULL;
170 if (dir->idCount < 1)
172 fprintf( stderr, "Cursor: empty directory!\n" );
173 return NULL;
175 if (dir->idCount == 1) return &dir->idEntries[0].cursor; /* No choice... */
177 /* First find the largest one smaller than or equal to the requested size*/
179 maxwidth = maxheight = 0;
180 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
181 if ((entry->wWidth <= width) && (entry->wHeight <= height) &&
182 (entry->wWidth > maxwidth) && (entry->wHeight > maxheight))
184 bestEntry = entry;
185 maxwidth = entry->wWidth;
186 maxheight = entry->wHeight;
188 if (bestEntry) return bestEntry;
190 /* Now find the smallest one larger than the requested size */
192 maxwidth = maxheight = 255;
193 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
194 if ((entry->wWidth < maxwidth) && (entry->wHeight < maxheight))
196 bestEntry = entry;
197 maxwidth = entry->wWidth;
198 maxheight = entry->wHeight;
201 return bestEntry;
205 /**********************************************************************
206 * CURSORICON_LoadDirEntry16
208 * Load the icon/cursor directory for a given resource name and find the
209 * best matching entry.
211 static BOOL32 CURSORICON_LoadDirEntry16( HINSTANCE32 hInstance, SEGPTR name,
212 INT32 width, INT32 height, INT32 colors,
213 BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
215 HRSRC16 hRsrc;
216 HGLOBAL16 hMem;
217 CURSORICONDIR *dir;
218 CURSORICONDIRENTRY *entry = NULL;
220 if (!(hRsrc = FindResource16( hInstance, name,
221 fCursor ? RT_GROUP_CURSOR : RT_GROUP_ICON )))
222 return FALSE;
223 if (!(hMem = LoadResource16( hInstance, hRsrc ))) return FALSE;
224 if ((dir = (CURSORICONDIR *)LockResource16( hMem )))
226 if (fCursor)
227 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
228 width, height );
229 else
230 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
231 width, height, colors );
232 if (entry) *dirEntry = *entry;
234 FreeResource16( hMem );
235 return (entry != NULL);
239 /**********************************************************************
240 * CURSORICON_LoadDirEntry32
242 * Load the icon/cursor directory for a given resource name and find the
243 * best matching entry.
245 static BOOL32 CURSORICON_LoadDirEntry32( HINSTANCE32 hInstance, LPCWSTR name,
246 INT32 width, INT32 height, INT32 colors,
247 BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
249 HANDLE32 hRsrc;
250 HANDLE32 hMem;
251 CURSORICONDIR *dir;
252 CURSORICONDIRENTRY *entry = NULL;
254 if (!(hRsrc = FindResource32W( hInstance, name,
255 (LPCWSTR)(fCursor ? RT_GROUP_CURSOR : RT_GROUP_ICON) )))
256 return FALSE;
257 if (!(hMem = LoadResource32( hInstance, hRsrc ))) return FALSE;
258 if ((dir = (CURSORICONDIR*)LockResource32( hMem )))
260 if (fCursor)
261 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
262 width, height );
263 else
264 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
265 width, height, colors );
266 if (entry) *dirEntry = *entry;
268 FreeResource32( hMem );
269 return (entry != NULL);
273 /**********************************************************************
274 * CURSORICON_CreateFromResource
276 * Create a cursor or icon from in-memory resource template.
278 * FIXME: Adjust icon size when width and height are nonzero (stretchblt).
279 * Convert to mono when cFlag is LR_MONOCHROME. Do something
280 * with cbSize parameter as well.
282 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE32 hInstance, HGLOBAL16 hObj, LPBYTE bits,
283 UINT32 cbSize, BOOL32 bIcon, DWORD dwVersion,
284 INT32 width, INT32 height, UINT32 cFlag )
286 int sizeAnd, sizeXor;
287 HBITMAP32 hAndBits = 0, hXorBits = 0; /* error condition for later */
288 BITMAPOBJ *bmpXor, *bmpAnd;
289 POINT16 hotspot = { 0 ,0 };
290 BITMAPINFO *bmi;
291 HDC32 hdc;
293 dprintf_cursor(stddeb,"CreateFromResource: %08x (%u bytes), ver %08x, %ix%i %s %s\n",
294 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
295 bIcon ? "icon" : "cursor", cFlag ? "mono" : "" );
296 if (dwVersion == 0x00020000)
298 fprintf(stdnimp,"\t2.xx resources are not supported\n");
299 return 0;
302 if (bIcon)
303 bmi = (BITMAPINFO *)bits;
304 else /* get the hotspot */
306 POINT16 *pt = (POINT16 *)bits;
307 hotspot = *pt;
308 bmi = (BITMAPINFO *)(pt + 1);
311 /* Check bitmap header */
313 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
314 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
315 bmi->bmiHeader.biCompression != BI_RGB) )
317 fprintf(stderr,"\tinvalid resource bitmap header.\n");
318 return 0;
321 if( (hdc = GetDC32( 0 )) )
323 BITMAPINFO* pInfo;
324 INT32 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
326 /* Make sure we have room for the monochrome bitmap later on.
327 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
328 * up to and including the biBitCount. In-memory icon resource
329 * format is as follows:
331 * BITMAPINFOHEADER icHeader // DIB header
332 * RGBQUAD icColors[] // Color table
333 * BYTE icXOR[] // DIB bits for XOR mask
334 * BYTE icAND[] // DIB bits for AND mask
337 if( (pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
338 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))) )
340 memcpy( pInfo, bmi, size );
341 pInfo->bmiHeader.biHeight /= 2;
343 /* Create the XOR bitmap */
345 hXorBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader, CBM_INIT,
346 (char*)bmi + size, pInfo, DIB_RGB_COLORS );
347 if( hXorBits )
349 char* bits = (char *)bmi + size + bmi->bmiHeader.biHeight *
350 DIB_GetDIBWidthBytes(bmi->bmiHeader.biWidth,
351 bmi->bmiHeader.biBitCount) / 2;
353 pInfo->bmiHeader.biBitCount = 1;
354 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
356 RGBQUAD *rgb = pInfo->bmiColors;
358 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
359 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
360 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
361 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
363 else
365 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
367 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
368 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
371 /* Create the AND bitmap */
373 hAndBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader, CBM_INIT,
374 bits, pInfo, DIB_RGB_COLORS );
375 if( !hAndBits ) DeleteObject32( hXorBits );
377 HeapFree( GetProcessHeap(), 0, pInfo );
379 ReleaseDC32( 0, hdc );
382 if( !hXorBits || !hAndBits )
384 fprintf(stderr,"\tunable to create an icon bitmap.\n");
385 return 0;
388 /* Now create the CURSORICONINFO structure */
390 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
391 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
392 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
393 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
395 if (hObj) hObj = GlobalReAlloc16( hObj,
396 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
397 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
398 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
399 if (hObj)
401 CURSORICONINFO *info;
403 /* Make it owned by the module */
404 if (hInstance) FarSetOwner( hObj, MODULE_HANDLEtoHMODULE16(hInstance));
406 info = (CURSORICONINFO *)GlobalLock16( hObj );
407 info->ptHotSpot.x = hotspot.x;
408 info->ptHotSpot.y = hotspot.y;
409 info->nWidth = bmpXor->bitmap.bmWidth;
410 info->nHeight = bmpXor->bitmap.bmHeight;
411 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
412 info->bPlanes = bmpXor->bitmap.bmPlanes;
413 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
415 /* Transfer the bitmap bits to the CURSORICONINFO structure */
417 GetBitmapBits32( hAndBits, sizeAnd, (char *)(info + 1) );
418 GetBitmapBits32( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
419 GlobalUnlock16( hObj );
422 DeleteObject32( hXorBits );
423 DeleteObject32( hAndBits );
424 return hObj;
428 /**********************************************************************
429 * CreateIconFromResourceEx16 (USER.450)
431 * FIXME: not sure about exact parameter types
433 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
434 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
436 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
437 if( pTask )
438 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
439 width, height, cFlag );
440 return 0;
444 /**********************************************************************
445 * CreateIconFromResource (USER32)
447 HICON32 WINAPI CreateIconFromResource32( LPBYTE bits, UINT32 cbSize,
448 BOOL32 bIcon, DWORD dwVersion)
449 /*FIXME: bon@elektron.ikp.physik.tu-darmstadt.de 971130: Test with weditres
450 showed only blank layout. Couldn't determine if this is a problem
451 with CreateIconFromResource32 or the application. The application
452 windows behaves strange (no redraw) before CreateIconFromResource32
455 HICON32 ret;
456 ret = CreateIconFromResourceEx16( bits, cbSize, bIcon, dwVersion, 0,0,0);
457 fprintf(stdnimp,"CreateIconFromResource3 probably only a stub\n");
458 dprintf_icon(stddeb,
459 "CreateIconFromResource32 %s at %p size %d winver %d return 0x%04x\n",
460 (bIcon)?"Icon":"Cursor",bits,cbSize,bIcon,ret);
461 return ret;
465 /**********************************************************************
466 * CreateIconFromResourceEx32 (USER32.76)
468 HICON32 WINAPI CreateIconFromResourceEx32( LPBYTE bits, UINT32 cbSize,
469 BOOL32 bIcon, DWORD dwVersion,
470 INT32 width, INT32 height,
471 UINT32 cFlag )
473 return CreateIconFromResourceEx16( bits, cbSize, bIcon, dwVersion, width, height, cFlag );
477 /**********************************************************************
478 * CURSORICON_Load16
480 * Load a cursor or icon from a 16-bit resource.
482 static HGLOBAL16 CURSORICON_Load16( HINSTANCE16 hInstance, SEGPTR name,
483 INT32 width, INT32 height, INT32 colors,
484 BOOL32 fCursor )
486 HGLOBAL16 handle;
487 HRSRC16 hRsrc;
488 CURSORICONDIRENTRY dirEntry;
490 if (!hInstance) /* OEM cursor/icon */
492 if (HIWORD(name)) /* Check for '#xxx' name */
494 char *ptr = PTR_SEG_TO_LIN( name );
495 if (ptr[0] != '#') return 0;
496 if (!(name = (SEGPTR)atoi( ptr + 1 ))) return 0;
498 return OBM_LoadCursorIcon( LOWORD(name), fCursor );
501 /* Find the best entry in the directory */
503 if ( !CURSORICON_LoadDirEntry16( hInstance, name, width, height,
504 colors, fCursor, &dirEntry ) ) return 0;
505 /* Load the resource */
507 if ( (hRsrc = FindResource16( hInstance,
508 MAKEINTRESOURCE( dirEntry.icon.wResId ),
509 fCursor ? RT_CURSOR : RT_ICON )) )
511 /* 16-bit icon or cursor resources are processed
512 * transparently by the LoadResource16() via custom
513 * resource handlers set by SetResourceHandler().
516 if ( (handle = LoadResource16( hInstance, hRsrc )) )
517 return handle;
519 return 0;
522 /**********************************************************************
523 * CURSORICON_Load32
525 * Load a cursor or icon from a 32-bit resource.
527 static HGLOBAL32 CURSORICON_Load32( HINSTANCE32 hInstance, LPCWSTR name,
528 int width, int height, int colors,
529 BOOL32 fCursor )
531 HANDLE32 handle;
532 HANDLE32 hRsrc;
533 CURSORICONDIRENTRY dirEntry;
535 if(!hInstance) /* OEM cursor/icon */
537 WORD resid;
538 if(HIWORD(name))
540 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
541 if( ansi[0]=='#') /*Check for '#xxx' name */
543 resid = atoi(ansi+1);
544 HeapFree( GetProcessHeap(), 0, ansi );
546 else
548 HeapFree( GetProcessHeap(), 0, ansi );
549 return 0;
552 else resid = LOWORD(name);
553 return OBM_LoadCursorIcon(resid, fCursor);
556 /* Find the best entry in the directory */
558 if ( !CURSORICON_LoadDirEntry32( hInstance, name, width, height,
559 colors, fCursor, &dirEntry ) ) return 0;
560 /* Load the resource */
562 if ( (hRsrc = FindResource32W( hInstance,
563 (LPWSTR) (DWORD) dirEntry.icon.wResId,
564 (LPWSTR) (fCursor ? RT_CURSOR : RT_ICON ))) )
566 HANDLE32 h = 0;
567 if ( (handle = LoadResource32( hInstance, hRsrc )) )
569 /* Hack to keep LoadCursor/Icon32() from spawning multiple
570 * copies of the same object.
572 #define pRsrcEntry ((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)
573 if( !pRsrcEntry->ResourceHandle )
575 LPBYTE bits = (LPBYTE)LockResource32( handle );
576 h = CURSORICON_CreateFromResource( hInstance, 0, bits, dirEntry.icon.dwBytesInRes,
577 !fCursor, 0x00030000, width, height, LR_DEFAULTCOLOR );
578 pRsrcEntry->ResourceHandle = h;
580 else h = pRsrcEntry->ResourceHandle;
581 #undef pRsrcEntry
583 return h;
585 return 0;
589 /***********************************************************************
590 * CURSORICON_Copy
592 * Make a copy of a cursor or icon.
594 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
596 char *ptrOld, *ptrNew;
597 int size;
598 HGLOBAL16 hNew;
600 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
601 if (!(hInstance = GetExePtr( hInstance ))) return 0;
602 size = GlobalSize16( handle );
603 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
604 FarSetOwner( hNew, hInstance );
605 ptrNew = (char *)GlobalLock16( hNew );
606 memcpy( ptrNew, ptrOld, size );
607 GlobalUnlock16( handle );
608 GlobalUnlock16( hNew );
609 return hNew;
612 /***********************************************************************
613 * CURSORICON_IconToCursor
615 * Converts bitmap to mono and truncates if icon is too large (should
616 * probably do StretchBlt() instead).
618 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL32 bSemiTransparent)
620 HCURSOR16 hRet = 0;
621 CURSORICONINFO *pIcon = NULL;
622 HTASK16 hTask = GetCurrentTask();
623 TDB* pTask = (TDB *)GlobalLock16(hTask);
625 if(hIcon && pTask)
626 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
627 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
628 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
629 else
631 BYTE pAndBits[128];
632 BYTE pXorBits[128];
633 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
634 BYTE* psPtr, *pxbPtr = pXorBits;
635 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
636 BYTE* pbc = NULL;
638 COLORREF col;
639 CURSORICONINFO cI;
641 dprintf_icon(stddeb, "IconToCursor:[%04x] %ix%i %ibpp (bogus %ibps)\n",
642 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
644 xor_width = BITMAP_GetBitsWidth( pIcon->nWidth, bpp );
645 and_width = BITMAP_GetBitsWidth( pIcon->nWidth, 1 );
646 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
648 memset(pXorBits, 0, 128);
649 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
650 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
651 cI.nWidth = 32; cI.nHeight = 32;
652 cI.nWidthBytes = 4; /* 32x1bpp */
654 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
655 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
657 for( iy = 0; iy < maxy; iy++ )
659 unsigned shift = iy % 2;
661 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
662 (and_width > 4) ? 4 : and_width );
663 for( ix = 0; ix < maxx; ix++ )
665 if( bSemiTransparent && ((ix+shift)%2) )
667 /* set AND bit, XOR bit stays 0 */
669 pbc = pAndBits + iy * 4 + ix/8;
670 *pbc |= 0x80 >> (ix%8);
672 else
674 /* keep AND bit, set XOR bit */
676 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
677 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
678 col = COLOR_ToLogical(val);
679 if( (GetRValue(col) + GetGValue(col) + GetBValue(col)) > 0x180 )
681 pbc = pxbPtr + ix/8;
682 *pbc |= 0x80 >> (ix%8);
686 psPtr += xor_width;
687 pxbPtr += 4;
690 hRet = CreateCursorIconIndirect( pTask->hInstance , &cI, pAndBits, pXorBits);
692 if( !hRet ) /* fall back on default drag cursor */
693 hRet = CURSORICON_Copy( pTask->hInstance ,
694 CURSORICON_Load16(0,MAKEINTRESOURCE(OCR_DRAGOBJECT),
695 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE) );
698 return hRet;
702 /***********************************************************************
703 * LoadCursor16 (USER.173)
705 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
707 if (HIWORD(name))
708 dprintf_cursor( stddeb, "LoadCursor16: %04x '%s'\n",
709 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
710 else
711 dprintf_cursor( stddeb, "LoadCursor16: %04x %04x\n",
712 hInstance, LOWORD(name) );
714 return CURSORICON_Load16( hInstance, name,
715 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
719 /***********************************************************************
720 * LoadIcon16 (USER.174)
722 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
724 if (HIWORD(name))
725 dprintf_icon( stddeb, "LoadIcon: %04x '%s'\n",
726 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
727 else
728 dprintf_icon( stddeb, "LoadIcon: %04x %04x\n",
729 hInstance, LOWORD(name) );
731 return CURSORICON_Load16( hInstance, name,
732 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
733 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE );
737 /***********************************************************************
738 * CreateCursor16 (USER.406)
740 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
741 INT16 xHotSpot, INT16 yHotSpot,
742 INT16 nWidth, INT16 nHeight,
743 LPCVOID lpANDbits, LPCVOID lpXORbits )
745 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
747 dprintf_cursor( stddeb, "CreateCursor: %dx%d spot=%d,%d xor=%p and=%p\n",
748 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
749 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
753 /***********************************************************************
754 * CreateCursor32 (USER32.66)
756 HCURSOR32 WINAPI CreateCursor32( HINSTANCE32 hInstance,
757 INT32 xHotSpot, INT32 yHotSpot,
758 INT32 nWidth, INT32 nHeight,
759 LPCVOID lpANDbits, LPCVOID lpXORbits )
761 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
763 dprintf_cursor( stddeb, "CreateCursor: %dx%d spot=%d,%d xor=%p and=%p\n",
764 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
765 return CreateCursorIconIndirect( MODULE_HANDLEtoHMODULE16( hInstance ),
766 &info, lpANDbits, lpXORbits );
770 /***********************************************************************
771 * CreateIcon16 (USER.407)
773 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
774 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
775 LPCVOID lpANDbits, LPCVOID lpXORbits )
777 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
779 dprintf_icon( stddeb, "CreateIcon: %dx%dx%d, xor=%p, and=%p\n",
780 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
781 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
785 /***********************************************************************
786 * CreateIcon32 (USER32.74)
788 HICON32 WINAPI CreateIcon32( HINSTANCE32 hInstance, INT32 nWidth,
789 INT32 nHeight, BYTE bPlanes, BYTE bBitsPixel,
790 LPCVOID lpANDbits, LPCVOID lpXORbits )
792 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
794 dprintf_icon( stddeb, "CreateIcon: %dx%dx%d, xor=%p, and=%p\n",
795 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
796 return CreateCursorIconIndirect( MODULE_HANDLEtoHMODULE16( hInstance ),
797 &info, lpANDbits, lpXORbits );
801 /***********************************************************************
802 * CreateCursorIconIndirect (USER.408)
804 HGLOBAL16 WINAPI CreateCursorIconIndirect( HINSTANCE16 hInstance,
805 CURSORICONINFO *info,
806 LPCVOID lpANDbits,
807 LPCVOID lpXORbits )
809 HGLOBAL16 handle;
810 char *ptr;
811 int sizeAnd, sizeXor;
813 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
814 if (!hInstance || !lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
815 info->nWidthBytes = BITMAP_WIDTH_BYTES(info->nWidth,info->bBitsPerPixel);
816 sizeXor = info->nHeight * info->nWidthBytes;
817 sizeAnd = info->nHeight * BITMAP_WIDTH_BYTES( info->nWidth, 1 );
818 if (!(handle = DirectResAlloc(hInstance, 0x10,
819 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
820 return 0;
821 ptr = (char *)GlobalLock16( handle );
822 memcpy( ptr, info, sizeof(*info) );
823 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
824 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
825 GlobalUnlock16( handle );
826 return handle;
830 /***********************************************************************
831 * CopyIcon16 (USER.368)
833 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
835 dprintf_icon( stddeb, "CopyIcon16: %04x %04x\n", hInstance, hIcon );
836 return CURSORICON_Copy( hInstance, hIcon );
840 /***********************************************************************
841 * CopyIcon32 (USER32.59)
843 HICON32 WINAPI CopyIcon32( HICON32 hIcon )
845 HTASK16 hTask = GetCurrentTask ();
846 TDB* pTask = (TDB *) GlobalLock16 (hTask);
847 dprintf_icon( stddeb, "CopyIcon32: %04x\n", hIcon );
848 return CURSORICON_Copy( pTask->hInstance, hIcon );
852 /***********************************************************************
853 * CopyCursor16 (USER.369)
855 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
857 dprintf_cursor( stddeb, "CopyCursor16: %04x %04x\n", hInstance, hCursor );
858 return CURSORICON_Copy( hInstance, hCursor );
862 /***********************************************************************
863 * DestroyIcon16 (USER.457)
865 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
867 return DestroyIcon32( hIcon );
871 /***********************************************************************
872 * DestroyIcon32 (USER32.132)
874 BOOL32 WINAPI DestroyIcon32( HICON32 hIcon )
876 dprintf_icon( stddeb, "DestroyIcon: %04x\n", hIcon );
877 /* FIXME: should check for OEM icon here */
878 return (FreeResource16( hIcon ) == 0);
882 /***********************************************************************
883 * DestroyCursor16 (USER.458)
885 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
887 return DestroyCursor32( hCursor );
891 /***********************************************************************
892 * DestroyCursor32 (USER32.131)
894 BOOL32 WINAPI DestroyCursor32( HCURSOR32 hCursor )
896 dprintf_cursor( stddeb, "DestroyCursor: %04x\n", hCursor );
897 /* FIXME: should check for OEM cursor here */
898 return (FreeResource16( hCursor ) == 0);
902 /***********************************************************************
903 * DrawIcon16 (USER.84)
905 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
907 return DrawIcon32( hdc, x, y, hIcon );
911 /***********************************************************************
912 * DrawIcon32 (USER32.158)
914 BOOL32 WINAPI DrawIcon32( HDC32 hdc, INT32 x, INT32 y, HICON32 hIcon )
916 CURSORICONINFO *ptr;
917 HDC32 hMemDC;
918 HBITMAP32 hXorBits, hAndBits;
919 COLORREF oldFg, oldBg;
921 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
922 if (!(hMemDC = CreateCompatibleDC32( hdc ))) return FALSE;
923 hAndBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, 1, 1,
924 (char *)(ptr+1) );
925 hXorBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
926 ptr->bBitsPerPixel, (char *)(ptr + 1)
927 + ptr->nHeight * BITMAP_WIDTH_BYTES(ptr->nWidth,1) );
928 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
929 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
931 if (hXorBits && hAndBits)
933 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
934 BitBlt32( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
935 SelectObject32( hMemDC, hXorBits );
936 BitBlt32(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
937 SelectObject32( hMemDC, hBitTemp );
939 DeleteDC32( hMemDC );
940 if (hXorBits) DeleteObject32( hXorBits );
941 if (hAndBits) DeleteObject32( hAndBits );
942 GlobalUnlock16( hIcon );
943 SetTextColor32( hdc, oldFg );
944 SetBkColor32( hdc, oldBg );
945 return TRUE;
949 /***********************************************************************
950 * DumpIcon (USER.459)
952 DWORD WINAPI DumpIcon( SEGPTR pInfo, WORD *lpLen,
953 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
955 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
956 int sizeAnd, sizeXor;
958 if (!info) return 0;
959 sizeXor = info->nHeight * info->nWidthBytes;
960 sizeAnd = info->nHeight * BITMAP_WIDTH_BYTES( info->nWidth, 1 );
961 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
962 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
963 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
964 return MAKELONG( sizeXor, sizeXor );
968 /***********************************************************************
969 * CURSORICON_SetCursor
971 * Change the X cursor. Helper function for SetCursor() and ShowCursor().
973 static BOOL32 CURSORICON_SetCursor( HCURSOR16 hCursor )
975 Pixmap pixmapBits, pixmapMask, pixmapAll;
976 XColor fg, bg;
977 Cursor cursor = None;
979 if (!hCursor) /* Create an empty cursor */
981 static const char data[] = { 0 };
983 bg.red = bg.green = bg.blue = 0x0000;
984 pixmapBits = XCreateBitmapFromData( display, rootWindow, data, 1, 1 );
985 if (pixmapBits)
987 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapBits,
988 &bg, &bg, 0, 0 );
989 XFreePixmap( display, pixmapBits );
992 else /* Create the X cursor from the bits */
994 CURSORICONINFO *ptr;
995 XImage *image;
997 if (!(ptr = (CURSORICONINFO*)GlobalLock16( hCursor ))) return FALSE;
998 if (ptr->bPlanes * ptr->bBitsPerPixel != 1)
1000 fprintf( stderr, "Cursor %04x has more than 1 bpp!\n", hCursor );
1001 return FALSE;
1004 /* Create a pixmap and transfer all the bits to it */
1006 /* NOTE: Following hack works, but only because XFree depth
1007 * 1 images really use 1 bit/pixel (and so the same layout
1008 * as the Windows cursor data). Perhaps use a more generic
1009 * algorithm here.
1011 pixmapAll = XCreatePixmap( display, rootWindow,
1012 ptr->nWidth, ptr->nHeight * 2, 1 );
1013 image = XCreateImage( display, DefaultVisualOfScreen(screen),
1014 1, ZPixmap, 0, (char *)(ptr + 1), ptr->nWidth,
1015 ptr->nHeight * 2, 16, ptr->nWidthBytes);
1016 if (image)
1018 extern void _XInitImageFuncPtrs( XImage* );
1019 image->byte_order = MSBFirst;
1020 image->bitmap_bit_order = MSBFirst;
1021 image->bitmap_unit = 16;
1022 _XInitImageFuncPtrs(image);
1023 if (pixmapAll)
1024 XPutImage( display, pixmapAll, BITMAP_monoGC, image,
1025 0, 0, 0, 0, ptr->nWidth, ptr->nHeight * 2 );
1026 image->data = NULL;
1027 XDestroyImage( image );
1030 /* Now create the 2 pixmaps for bits and mask */
1032 pixmapBits = XCreatePixmap( display, rootWindow,
1033 ptr->nWidth, ptr->nHeight, 1 );
1034 pixmapMask = XCreatePixmap( display, rootWindow,
1035 ptr->nWidth, ptr->nHeight, 1 );
1037 /* Make sure everything went OK so far */
1039 if (pixmapBits && pixmapMask && pixmapAll)
1041 /* We have to do some magic here, as cursors are not fully
1042 * compatible between Windows and X11. Under X11, there
1043 * are only 3 possible color cursor: black, white and
1044 * masked. So we map the 4th Windows color (invert the
1045 * bits on the screen) to black. This require some boolean
1046 * arithmetic:
1048 * Windows | X11
1049 * Xor And Result | Bits Mask Result
1050 * 0 0 black | 0 1 background
1051 * 0 1 no change | X 0 no change
1052 * 1 0 white | 1 1 foreground
1053 * 1 1 inverted | 0 1 background
1055 * which gives:
1056 * Bits = 'Xor' and not 'And'
1057 * Mask = 'Xor' or not 'And'
1059 * FIXME: apparently some servers do support 'inverted' color.
1060 * I don't know if it's correct per the X spec, but maybe
1061 * we ought to take advantage of it. -- AJ
1063 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
1064 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
1065 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
1066 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
1067 XSetFunction( display, BITMAP_monoGC, GXandReverse );
1068 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
1069 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
1070 XSetFunction( display, BITMAP_monoGC, GXorReverse );
1071 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
1072 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
1073 XSetFunction( display, BITMAP_monoGC, GXcopy );
1074 fg.red = fg.green = fg.blue = 0xffff;
1075 bg.red = bg.green = bg.blue = 0x0000;
1076 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapMask,
1077 &fg, &bg, ptr->ptHotSpot.x, ptr->ptHotSpot.y );
1080 /* Now free everything */
1082 if (pixmapAll) XFreePixmap( display, pixmapAll );
1083 if (pixmapBits) XFreePixmap( display, pixmapBits );
1084 if (pixmapMask) XFreePixmap( display, pixmapMask );
1085 GlobalUnlock16( hCursor );
1088 if (cursor == None) return FALSE;
1089 if (CURSORICON_XCursor != None) XFreeCursor( display, CURSORICON_XCursor );
1090 CURSORICON_XCursor = cursor;
1092 if (rootWindow != DefaultRootWindow(display))
1094 /* Set the cursor on the desktop window */
1095 XDefineCursor( display, rootWindow, cursor );
1097 else
1099 /* Set the same cursor for all top-level windows */
1100 HWND32 hwnd = GetWindow32( GetDesktopWindow32(), GW_CHILD );
1101 while(hwnd)
1103 Window win = WIN_GetXWindow( hwnd );
1104 if (win) XDefineCursor( display, win, cursor );
1105 hwnd = GetWindow32( hwnd, GW_HWNDNEXT );
1108 return TRUE;
1112 /***********************************************************************
1113 * SetCursor16 (USER.69)
1115 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1117 return (HCURSOR16)SetCursor32( hCursor );
1121 /***********************************************************************
1122 * SetCursor32 (USER32.471)
1124 HCURSOR32 WINAPI SetCursor32( HCURSOR32 hCursor )
1126 HCURSOR32 hOldCursor;
1128 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1129 dprintf_cursor( stddeb, "SetCursor: %04x\n", hCursor );
1130 hOldCursor = hActiveCursor;
1131 hActiveCursor = hCursor;
1132 /* Change the cursor shape only if it is visible */
1133 if (CURSOR_ShowCount >= 0)
1134 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1135 return hOldCursor;
1139 /***********************************************************************
1140 * SetCursorPos16 (USER.70)
1142 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1144 SetCursorPos32( x, y );
1148 /***********************************************************************
1149 * SetCursorPos32 (USER32.473)
1151 BOOL32 WINAPI SetCursorPos32( INT32 x, INT32 y )
1153 dprintf_cursor( stddeb, "SetCursorPos: x=%d y=%d\n", x, y );
1154 XWarpPointer( display, rootWindow, rootWindow, 0, 0, 0, 0, x, y );
1155 return TRUE;
1159 /***********************************************************************
1160 * ShowCursor16 (USER.71)
1162 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1164 return ShowCursor32( bShow );
1168 /***********************************************************************
1169 * ShowCursor32 (USER32.529)
1171 INT32 WINAPI ShowCursor32( BOOL32 bShow )
1173 dprintf_cursor( stddeb, "ShowCursor: %d, count=%d\n",
1174 bShow, CURSOR_ShowCount );
1176 if (bShow)
1178 if (++CURSOR_ShowCount == 0) /* Show it */
1179 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1181 else
1183 if (--CURSOR_ShowCount == -1) /* Hide it */
1184 CALL_LARGE_STACK( CURSORICON_SetCursor, 0 );
1186 return CURSOR_ShowCount;
1190 /***********************************************************************
1191 * GetCursor16 (USER.247)
1193 HCURSOR16 WINAPI GetCursor16(void)
1195 return hActiveCursor;
1199 /***********************************************************************
1200 * GetCursor32 (USER32.226)
1202 HCURSOR32 WINAPI GetCursor32(void)
1204 return hActiveCursor;
1208 /***********************************************************************
1209 * ClipCursor16 (USER.16)
1211 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1213 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1214 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1215 return TRUE;
1219 /***********************************************************************
1220 * ClipCursor32 (USER32.52)
1222 BOOL32 WINAPI ClipCursor32( const RECT32 *rect )
1224 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1225 else CopyRect32( &CURSOR_ClipRect, rect );
1226 return TRUE;
1230 /***********************************************************************
1231 * GetCursorPos16 (USER.17)
1233 void WINAPI GetCursorPos16( POINT16 *pt )
1235 Window root, child;
1236 int rootX, rootY, childX, childY;
1237 unsigned int mousebut;
1239 if (!pt) return;
1240 if (!XQueryPointer( display, rootWindow, &root, &child,
1241 &rootX, &rootY, &childX, &childY, &mousebut ))
1242 pt->x = pt->y = 0;
1243 else
1245 pt->x = childX;
1246 pt->y = childY;
1247 if (mousebut & Button1Mask)
1248 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1249 else
1250 MouseButtonsStates[0] = FALSE;
1251 if (mousebut & Button2Mask)
1252 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1253 else
1254 MouseButtonsStates[1] = FALSE;
1255 if (mousebut & Button3Mask)
1256 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1257 else
1258 MouseButtonsStates[2] = FALSE;
1260 dprintf_cursor(stddeb, "GetCursorPos: ret=%d,%d\n", pt->x, pt->y );
1264 /***********************************************************************
1265 * GetCursorPos32 (USER32.228)
1267 void WINAPI GetCursorPos32( POINT32 *pt )
1269 POINT16 pt16;
1270 GetCursorPos16( &pt16 );
1271 if (pt) CONV_POINT16TO32( &pt16, pt );
1275 /***********************************************************************
1276 * GetClipCursor16 (USER.309)
1278 void WINAPI GetClipCursor16( RECT16 *rect )
1280 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1284 /***********************************************************************
1285 * GetClipCursor32 (USER32.220)
1287 void WINAPI GetClipCursor32( RECT32 *rect )
1289 if (rect) CopyRect32( rect, &CURSOR_ClipRect );
1292 /**********************************************************************
1293 * LookupIconIdFromDirectoryEx16 (USER.364)
1295 * FIXME: exact parameter sizes
1297 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1298 INT16 width, INT16 height, UINT16 cFlag )
1300 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1301 UINT16 retVal = 0;
1302 if( dir && !dir->idReserved && (dir->idType & 3) )
1304 int colors = (cFlag == LR_MONOCHROME) ? 2 : COLOR_GetSystemPaletteSize();
1305 if( bIcon )
1307 ICONDIRENTRY* entry;
1308 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1309 if( entry ) retVal = entry->wResId;
1311 else
1313 CURSORDIRENTRY* entry;
1314 entry = CURSORICON_FindBestCursor( dir, width, height );
1315 if( entry ) retVal = entry->wResId;
1318 else dprintf_cursor(stddeb,"IconId: invalid resource directory\n");
1319 return retVal;
1322 /**********************************************************************
1323 * LookupIconIdFromDirectoryEx32 (USER32.379)
1325 INT32 WINAPI LookupIconIdFromDirectoryEx32( LPBYTE dir, BOOL32 bIcon,
1326 INT32 width, INT32 height, UINT32 cFlag )
1328 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1331 /**********************************************************************
1332 * LookupIconIdFromDirectory (USER.???)
1334 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1336 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1337 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1338 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1341 /**********************************************************************
1342 * LookupIconIdFromDirectory (USER32.378)
1344 INT32 WINAPI LookupIconIdFromDirectory32( LPBYTE dir, BOOL32 bIcon )
1346 return LookupIconIdFromDirectoryEx32( dir, bIcon,
1347 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1348 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1351 /**********************************************************************
1352 * GetIconID (USER.455)
1354 WORD WINAPI GetIconID( HGLOBAL16 hResource, DWORD resType )
1356 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1358 dprintf_cursor( stddeb, "GetIconID: hRes=%04x, entries=%i\n",
1359 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1361 switch(resType)
1363 case RT_CURSOR:
1364 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1365 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1366 case RT_ICON:
1367 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1368 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1369 default:
1370 fprintf( stderr, "GetIconID: invalid res type %ld\n", resType );
1372 return 0;
1375 /**********************************************************************
1376 * LoadCursorIconHandler (USER.336)
1378 * Supposed to load resources of Windows 2.x applications.
1380 HGLOBAL16 WINAPI LoadCursorIconHandler( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1382 fprintf(stderr,"hModule[%04x]: old 2.x resources are not supported!\n", hModule);
1383 return (HGLOBAL16)0;
1386 /**********************************************************************
1387 * LoadDIBIconHandler (USER.357)
1389 * RT_ICON resource loader, installed by USER_SignalProc when module
1390 * is initialized.
1392 HGLOBAL16 WINAPI LoadDIBIconHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1394 /* If hResource is zero we must allocate a new memory block, if it's
1395 * non-zero but GlobalLock() returns NULL then it was discarded and
1396 * we have to recommit some memory, otherwise we just need to check
1397 * the block size. See LoadProc() in 16-bit SDK for more.
1400 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1401 if( hMemObj )
1403 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1404 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1405 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1406 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1408 return hMemObj;
1411 /**********************************************************************
1412 * LoadDIBCursorHandler (USER.356)
1414 * RT_CURSOR resource loader. Same as above.
1416 HGLOBAL16 WINAPI LoadDIBCursorHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1418 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1419 if( hMemObj )
1421 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1422 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1423 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1424 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1426 return hMemObj;
1429 /**********************************************************************
1430 * LoadIconHandler (USER.456)
1432 HICON16 WINAPI LoadIconHandler( HGLOBAL16 hResource, BOOL16 bNew )
1434 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1436 dprintf_cursor(stddeb,"LoadIconHandler: hRes=%04x\n",hResource);
1438 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1439 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1442 /***********************************************************************
1443 * LoadCursorW (USER32.361)
1445 HCURSOR32 WINAPI LoadCursor32W(HINSTANCE32 hInstance, LPCWSTR name)
1447 return CURSORICON_Load32( hInstance, name,
1448 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
1451 /***********************************************************************
1452 * LoadCursorA (USER32.358)
1454 HCURSOR32 WINAPI LoadCursor32A(HINSTANCE32 hInstance, LPCSTR name)
1456 HCURSOR32 res=0;
1457 if(!HIWORD(name))
1458 return LoadCursor32W(hInstance,(LPCWSTR)name);
1459 else
1461 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1462 res = LoadCursor32W(hInstance, uni);
1463 HeapFree( GetProcessHeap(), 0, uni);
1465 return res;
1468 /***********************************************************************
1469 * LoadIconW (USER32.363)
1471 HICON32 WINAPI LoadIcon32W(HINSTANCE32 hInstance, LPCWSTR name)
1473 return CURSORICON_Load32( hInstance, name,
1474 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
1475 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE );
1478 /***********************************************************************
1479 * LoadIconA (USER32.362)
1481 HICON32 WINAPI LoadIcon32A(HINSTANCE32 hInstance, LPCSTR name)
1483 HICON32 res=0;
1485 if( !HIWORD(name) )
1486 return LoadIcon32W(hInstance, (LPCWSTR)name);
1487 else
1489 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1490 res = LoadIcon32W( hInstance, uni );
1491 HeapFree( GetProcessHeap(), 0, uni );
1493 return res;
1496 /**********************************************************************
1497 * GetIconInfo (USER32.241)
1499 BOOL32 WINAPI GetIconInfo(HICON32 hIcon,LPICONINFO iconinfo) {
1500 CURSORICONINFO *ciconinfo;
1502 ciconinfo = GlobalLock16(hIcon);
1503 if (!ciconinfo)
1504 return FALSE;
1505 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1506 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1507 iconinfo->fIcon = TRUE; /* hmm */
1508 /* FIXME ... add both bitmaps */
1509 return TRUE;
1512 /**********************************************************************
1513 * CreateIconIndirect (USER32.78)
1515 HICON32 WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1516 BITMAPOBJ *bmpXor,*bmpAnd;
1517 HICON32 hObj;
1518 int sizeXor,sizeAnd;
1520 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1521 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1523 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1524 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1526 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1527 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1528 if (hObj)
1530 CURSORICONINFO *info;
1532 info = (CURSORICONINFO *)GlobalLock16( hObj );
1533 info->ptHotSpot.x = iconinfo->xHotspot;
1534 info->ptHotSpot.y = iconinfo->yHotspot;
1535 info->nWidth = bmpXor->bitmap.bmWidth;
1536 info->nHeight = bmpXor->bitmap.bmHeight;
1537 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1538 info->bPlanes = bmpXor->bitmap.bmPlanes;
1539 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1541 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1543 GetBitmapBits32( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1544 GetBitmapBits32( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1545 GlobalUnlock16( hObj );
1547 return hObj;
1550 /**********************************************************************
1551 * DrawIconEx16 (USER.394)
1554 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1555 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1556 HBRUSH16 hbr, UINT16 flags)
1558 return DrawIconEx32 (hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1559 istep, hbr, flags);
1562 /**********************************************************************
1563 * DrawIconEx32 (USER32.160)
1566 BOOL32 WINAPI DrawIconEx32 (HDC32 hdc, INT32 x0, INT32 y0, HICON32 hIcon,
1567 INT32 cxWidth, INT32 cyWidth, UINT32 istep,
1568 HBRUSH32 hbr, UINT32 flags)
1570 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1571 HDC32 hMemDC = CreateCompatibleDC32 (hdc);
1572 BOOL32 result = FALSE;
1574 dprintf_icon (stddeb, "DrawIconEx32: part stub.\n");
1576 if (hMemDC && ptr)
1578 HBITMAP32 hXorBits, hAndBits;
1579 COLORREF oldFg, oldBg;
1581 /* Calculate the size of the destination image. */
1582 if (cxWidth == 0)
1583 if (flags & DI_DEFAULTSIZE)
1584 cxWidth = GetSystemMetrics32 (SM_CXICON);
1585 else
1586 cxWidth = ptr->nWidth;
1587 if (cyWidth == 0)
1588 if (flags & DI_DEFAULTSIZE)
1589 cyWidth = GetSystemMetrics32 (SM_CYICON);
1590 else
1591 cyWidth = ptr->nHeight;
1593 hXorBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
1594 ptr->bPlanes, ptr->bBitsPerPixel,
1595 (char *)(ptr + 1)
1596 + ptr->nHeight *
1597 BITMAP_WIDTH_BYTES(ptr->nWidth,1) );
1598 hAndBits = CreateBitmap32 ( cxWidth, cyWidth,
1599 1, 1, (char *)(ptr+1) );
1600 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
1601 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
1603 if (hXorBits && hAndBits)
1605 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
1606 if (flags & DI_MASK)
1607 BitBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1608 hMemDC, 0, 0, SRCAND);
1609 SelectObject32( hMemDC, hXorBits );
1610 if (flags & DI_IMAGE)
1611 BitBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1612 hMemDC, 0, 0, SRCPAINT);
1613 SelectObject32( hMemDC, hBitTemp );
1614 result = TRUE;
1617 SetTextColor32( hdc, oldFg );
1618 SetBkColor32( hdc, oldBg );
1619 if (hXorBits) DeleteObject32( hXorBits );
1620 if (hAndBits) DeleteObject32( hAndBits );
1622 if (hMemDC) DeleteDC32( hMemDC );
1623 GlobalUnlock16( hIcon );
1624 return result;