Release 980927
[wine.git] / objects / cursoricon.c
blobb7969c127da43f5ae10b4f73d1952b015c0e2f01
1 /*
2 * Cursor and icon support
4 * Copyright 1995 Alexandre Julliard
5 * 1996 Martin Von Loewis
6 * 1997 Alex Korobka
7 */
9 /*
10 * Theory:
12 * http://www.microsoft.com/win32dev/ui/icons.htm
14 * Cursors and icons are stored in a global heap block, with the
15 * following layout:
17 * CURSORICONINFO info;
18 * BYTE[] ANDbits;
19 * BYTE[] XORbits;
21 * The bits structures are in the format of a device-dependent bitmap.
23 * This layout is very sub-optimal, as the bitmap bits are stored in
24 * the X client instead of in the server like other bitmaps; however,
25 * some programs (notably Paint Brush) expect to be able to manipulate
26 * the bits directly :-(
29 #include <string.h>
30 #include <stdlib.h>
31 #include "heap.h"
32 #include "windows.h"
33 #include "peexe.h"
34 #include "color.h"
35 #include "bitmap.h"
36 #include "callback.h"
37 #include "cursoricon.h"
38 #include "sysmetrics.h"
39 #include "module.h"
40 #include "win.h"
41 #include "debug.h"
42 #include "task.h"
43 #include "user.h"
44 #include "keyboard.h"
45 #include "x11drv.h"
46 #include "winerror.h"
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 WARN(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 WARN(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_CURSOR16 : RT_GROUP_ICON16 )))
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 fCursor ? RT_GROUP_CURSOR32W : RT_GROUP_ICON32W )))
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( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
282 UINT32 cbSize, BOOL32 bIcon, DWORD dwVersion,
283 INT32 width, INT32 height, UINT32 cFlag )
285 int sizeAnd, sizeXor;
286 HBITMAP32 hAndBits = 0, hXorBits = 0; /* error condition for later */
287 BITMAPOBJ *bmpXor, *bmpAnd;
288 POINT16 hotspot = { 0 ,0 };
289 BITMAPINFO *bmi;
290 HDC32 hdc;
292 TRACE(cursor,"%08x (%u bytes), ver %08x, %ix%i %s %s\n",
293 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
294 bIcon ? "icon" : "cursor", cFlag ? "mono" : "" );
295 if (dwVersion == 0x00020000)
297 FIXME(cursor,"\t2.xx resources are not supported\n");
298 return 0;
301 if (bIcon)
302 bmi = (BITMAPINFO *)bits;
303 else /* get the hotspot */
305 POINT16 *pt = (POINT16 *)bits;
306 hotspot = *pt;
307 bmi = (BITMAPINFO *)(pt + 1);
310 /* Check bitmap header */
312 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
313 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
314 bmi->bmiHeader.biCompression != BI_RGB) )
316 WARN(cursor,"\tinvalid resource bitmap header.\n");
317 return 0;
320 if( (hdc = GetDC32( 0 )) )
322 BITMAPINFO* pInfo;
323 INT32 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
325 /* Make sure we have room for the monochrome bitmap later on.
326 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
327 * up to and including the biBitCount. In-memory icon resource
328 * format is as follows:
330 * BITMAPINFOHEADER icHeader // DIB header
331 * RGBQUAD icColors[] // Color table
332 * BYTE icXOR[] // DIB bits for XOR mask
333 * BYTE icAND[] // DIB bits for AND mask
336 if( (pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
337 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))) )
339 memcpy( pInfo, bmi, size );
340 pInfo->bmiHeader.biHeight /= 2;
342 /* Create the XOR bitmap */
344 hXorBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader, CBM_INIT,
345 (char*)bmi + size, pInfo, DIB_RGB_COLORS );
346 if( hXorBits )
348 char* bits = (char *)bmi + size + bmi->bmiHeader.biHeight *
349 DIB_GetDIBWidthBytes(bmi->bmiHeader.biWidth,
350 bmi->bmiHeader.biBitCount) / 2;
352 pInfo->bmiHeader.biBitCount = 1;
353 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
355 RGBQUAD *rgb = pInfo->bmiColors;
357 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
358 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
359 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
360 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
362 else
364 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
366 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
367 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
370 /* Create the AND bitmap */
372 hAndBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader, CBM_INIT,
373 bits, pInfo, DIB_RGB_COLORS );
374 if( !hAndBits ) DeleteObject32( hXorBits );
376 HeapFree( GetProcessHeap(), 0, pInfo );
378 ReleaseDC32( 0, hdc );
381 if( !hXorBits || !hAndBits )
383 WARN(cursor,"\tunable to create an icon bitmap.\n");
384 return 0;
387 /* Now create the CURSORICONINFO structure */
389 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
390 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
391 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
392 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
394 if (hObj) hObj = GlobalReAlloc16( hObj,
395 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
396 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
397 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
398 if (hObj)
400 CURSORICONINFO *info;
402 /* Make it owned by the module */
403 if (hInstance) FarSetOwner( hObj, GetExePtr(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.76)
445 * FIXME:
446 * bon@elektron.ikp.physik.tu-darmstadt.de 971130: Test with weditres
447 * showed only blank layout. Couldn't determine if this is a problem
448 * with CreateIconFromResource32 or the application. The application
449 * windows behaves strange (no redraw) before CreateIconFromResource32
451 HICON32 WINAPI CreateIconFromResource32( LPBYTE bits, UINT32 cbSize,
452 BOOL32 bIcon, DWORD dwVersion)
454 HICON32 ret;
455 ret = CreateIconFromResourceEx16( bits, cbSize, bIcon, dwVersion, 0,0,0);
456 FIXME(icon,"probably only a stub\n");
457 TRACE(icon, "%s at %p size %d winver %d return 0x%04x\n",
458 (bIcon)?"Icon":"Cursor",bits,cbSize,bIcon,ret);
459 return ret;
463 /**********************************************************************
464 * CreateIconFromResourceEx32 (USER32.77)
466 HICON32 WINAPI CreateIconFromResourceEx32( LPBYTE bits, UINT32 cbSize,
467 BOOL32 bIcon, DWORD dwVersion,
468 INT32 width, INT32 height,
469 UINT32 cFlag )
471 return CreateIconFromResourceEx16( bits, cbSize, bIcon, dwVersion, width, height, cFlag );
475 /**********************************************************************
476 * CURSORICON_Load16
478 * Load a cursor or icon from a 16-bit resource.
480 static HGLOBAL16 CURSORICON_Load16( HINSTANCE16 hInstance, SEGPTR name,
481 INT32 width, INT32 height, INT32 colors,
482 BOOL32 fCursor )
484 HGLOBAL16 handle;
485 HRSRC16 hRsrc;
486 CURSORICONDIRENTRY dirEntry;
488 if (!hInstance) /* OEM cursor/icon */
490 if (HIWORD(name)) /* Check for '#xxx' name */
492 char *ptr = PTR_SEG_TO_LIN( name );
493 if (ptr[0] != '#') return 0;
494 if (!(name = (SEGPTR)atoi( ptr + 1 ))) return 0;
496 return OBM_LoadCursorIcon( LOWORD(name), fCursor );
499 /* Find the best entry in the directory */
501 if ( !CURSORICON_LoadDirEntry16( hInstance, name, width, height,
502 colors, fCursor, &dirEntry ) ) return 0;
503 /* Load the resource */
505 if ( (hRsrc = FindResource16( hInstance,
506 MAKEINTRESOURCE16( dirEntry.icon.wResId ),
507 fCursor ? RT_CURSOR16 : RT_ICON16 )) )
509 /* 16-bit icon or cursor resources are processed
510 * transparently by the LoadResource16() via custom
511 * resource handlers set by SetResourceHandler().
514 if ( (handle = LoadResource16( hInstance, hRsrc )) )
515 return handle;
517 return 0;
520 /**********************************************************************
521 * CURSORICON_Load32
523 * Load a cursor or icon from a 32-bit resource.
525 static HGLOBAL32 CURSORICON_Load32( HINSTANCE32 hInstance, LPCWSTR name,
526 int width, int height, int colors,
527 BOOL32 fCursor )
529 HANDLE32 handle;
530 HANDLE32 hRsrc;
531 CURSORICONDIRENTRY dirEntry;
533 if(!hInstance) /* OEM cursor/icon */
535 WORD resid;
536 if(HIWORD(name))
538 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
539 if( ansi[0]=='#') /*Check for '#xxx' name */
541 resid = atoi(ansi+1);
542 HeapFree( GetProcessHeap(), 0, ansi );
544 else
546 HeapFree( GetProcessHeap(), 0, ansi );
547 return 0;
550 else resid = LOWORD(name);
551 return OBM_LoadCursorIcon(resid, fCursor);
554 /* Find the best entry in the directory */
556 if ( !CURSORICON_LoadDirEntry32( hInstance, name, width, height,
557 colors, fCursor, &dirEntry ) ) return 0;
558 /* Load the resource */
560 if ( (hRsrc = FindResource32W( hInstance,
561 MAKEINTRESOURCE32W( dirEntry.icon.wResId ),
562 fCursor ? RT_CURSOR32W : RT_ICON32W )) )
564 HANDLE32 h = 0;
565 if ( (handle = LoadResource32( hInstance, hRsrc )) )
567 /* Hack to keep LoadCursor/Icon32() from spawning multiple
568 * copies of the same object.
570 #define pRsrcEntry ((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)
571 if( !pRsrcEntry->ResourceHandle )
573 LPBYTE bits = (LPBYTE)LockResource32( handle );
574 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry.icon.dwBytesInRes,
575 !fCursor, 0x00030000, width, height, LR_DEFAULTCOLOR );
576 pRsrcEntry->ResourceHandle = h;
578 else h = pRsrcEntry->ResourceHandle;
579 #undef pRsrcEntry
581 return h;
583 return 0;
587 /***********************************************************************
588 * CURSORICON_Copy
590 * Make a copy of a cursor or icon.
592 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
594 char *ptrOld, *ptrNew;
595 int size;
596 HGLOBAL16 hNew;
598 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
599 if (!(hInstance = GetExePtr( hInstance ))) return 0;
600 size = GlobalSize16( handle );
601 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
602 FarSetOwner( hNew, hInstance );
603 ptrNew = (char *)GlobalLock16( hNew );
604 memcpy( ptrNew, ptrOld, size );
605 GlobalUnlock16( handle );
606 GlobalUnlock16( hNew );
607 return hNew;
610 /***********************************************************************
611 * CURSORICON_IconToCursor
613 * Converts bitmap to mono and truncates if icon is too large (should
614 * probably do StretchBlt() instead).
616 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL32 bSemiTransparent)
618 HCURSOR16 hRet = 0;
619 CURSORICONINFO *pIcon = NULL;
620 HTASK16 hTask = GetCurrentTask();
621 TDB* pTask = (TDB *)GlobalLock16(hTask);
623 if(hIcon && pTask)
624 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
625 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
626 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
627 else
629 BYTE pAndBits[128];
630 BYTE pXorBits[128];
631 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
632 BYTE* psPtr, *pxbPtr = pXorBits;
633 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
634 BYTE* pbc = NULL;
636 COLORREF col;
637 CURSORICONINFO cI;
639 TRACE(icon, "[%04x] %ix%i %ibpp (bogus %ibps)\n",
640 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
642 xor_width = BITMAP_GetBitsWidth( pIcon->nWidth, bpp );
643 and_width = BITMAP_GetBitsWidth( pIcon->nWidth, 1 );
644 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
646 memset(pXorBits, 0, 128);
647 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
648 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
649 cI.nWidth = 32; cI.nHeight = 32;
650 cI.nWidthBytes = 4; /* 32x1bpp */
652 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
653 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
655 for( iy = 0; iy < maxy; iy++ )
657 unsigned shift = iy % 2;
659 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
660 (and_width > 4) ? 4 : and_width );
661 for( ix = 0; ix < maxx; ix++ )
663 if( bSemiTransparent && ((ix+shift)%2) )
665 /* set AND bit, XOR bit stays 0 */
667 pbc = pAndBits + iy * 4 + ix/8;
668 *pbc |= 0x80 >> (ix%8);
670 else
672 /* keep AND bit, set XOR bit */
674 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
675 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
676 col = COLOR_ToLogical(val);
677 if( (GetRValue(col) + GetGValue(col) + GetBValue(col)) > 0x180 )
679 pbc = pxbPtr + ix/8;
680 *pbc |= 0x80 >> (ix%8);
684 psPtr += xor_width;
685 pxbPtr += 4;
688 hRet = CreateCursorIconIndirect( pTask->hInstance , &cI, pAndBits, pXorBits);
690 if( !hRet ) /* fall back on default drag cursor */
691 hRet = CURSORICON_Copy( pTask->hInstance ,
692 CURSORICON_Load16(0,MAKEINTRESOURCE16(OCR_DRAGOBJECT),
693 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE) );
696 return hRet;
700 /***********************************************************************
701 * LoadCursor16 (USER.173)
703 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
705 if (HIWORD(name))
706 TRACE(cursor, "%04x '%s'\n",
707 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
708 else
709 TRACE(cursor, "%04x %04x\n",
710 hInstance, LOWORD(name) );
712 return CURSORICON_Load16( hInstance, name,
713 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
717 /***********************************************************************
718 * LoadIcon16 (USER.174)
720 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
722 if (HIWORD(name))
723 TRACE(icon, "%04x '%s'\n",
724 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
725 else
726 TRACE(icon, "%04x %04x\n",
727 hInstance, LOWORD(name) );
729 return CURSORICON_Load16( hInstance, name,
730 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
731 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE );
735 /***********************************************************************
736 * CreateCursor16 (USER.406)
738 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
739 INT16 xHotSpot, INT16 yHotSpot,
740 INT16 nWidth, INT16 nHeight,
741 LPCVOID lpANDbits, LPCVOID lpXORbits )
743 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
745 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
746 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
747 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
751 /***********************************************************************
752 * CreateCursor32 (USER32.67)
754 HCURSOR32 WINAPI CreateCursor32( HINSTANCE32 hInstance,
755 INT32 xHotSpot, INT32 yHotSpot,
756 INT32 nWidth, INT32 nHeight,
757 LPCVOID lpANDbits, LPCVOID lpXORbits )
759 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
761 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
762 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
763 return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
767 /***********************************************************************
768 * CreateIcon16 (USER.407)
770 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
771 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
772 LPCVOID lpANDbits, LPCVOID lpXORbits )
774 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
776 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
777 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
778 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
782 /***********************************************************************
783 * CreateIcon32 (USER32.75)
785 HICON32 WINAPI CreateIcon32( HINSTANCE32 hInstance, INT32 nWidth,
786 INT32 nHeight, BYTE bPlanes, BYTE bBitsPixel,
787 LPCVOID lpANDbits, LPCVOID lpXORbits )
789 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
791 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
792 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
793 return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
797 /***********************************************************************
798 * CreateCursorIconIndirect (USER.408)
800 HGLOBAL16 WINAPI CreateCursorIconIndirect( HINSTANCE16 hInstance,
801 CURSORICONINFO *info,
802 LPCVOID lpANDbits,
803 LPCVOID lpXORbits )
805 HGLOBAL16 handle;
806 char *ptr;
807 int sizeAnd, sizeXor;
809 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
810 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
811 info->nWidthBytes = BITMAP_WIDTH_BYTES(info->nWidth,info->bBitsPerPixel);
812 sizeXor = info->nHeight * info->nWidthBytes;
813 sizeAnd = info->nHeight * BITMAP_WIDTH_BYTES( info->nWidth, 1 );
814 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
815 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
816 return 0;
817 if (hInstance) FarSetOwner( handle, hInstance );
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 TRACE(icon, "%04x %04x\n", hInstance, hIcon );
833 return CURSORICON_Copy( hInstance, hIcon );
837 /***********************************************************************
838 * CopyIcon32 (USER32.60)
840 HICON32 WINAPI CopyIcon32( HICON32 hIcon )
842 HTASK16 hTask = GetCurrentTask ();
843 TDB* pTask = (TDB *) GlobalLock16 (hTask);
844 TRACE(icon, "%04x\n", hIcon );
845 return CURSORICON_Copy( pTask->hInstance, hIcon );
849 /***********************************************************************
850 * CopyCursor16 (USER.369)
852 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
854 TRACE(cursor, "%04x %04x\n", hInstance, hCursor );
855 return CURSORICON_Copy( hInstance, hCursor );
859 /***********************************************************************
860 * DestroyIcon16 (USER.457)
862 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
864 TRACE(icon, "%04x\n", hIcon );
865 /* FIXME: should check for OEM/global heap icon here */
866 return (FreeResource16( hIcon ) == 0);
870 /***********************************************************************
871 * DestroyIcon32 (USER32.133)
873 BOOL32 WINAPI DestroyIcon32( HICON32 hIcon )
875 TRACE(icon, "%04x\n", hIcon );
876 /* FIXME: should check for OEM/global heap icon here */
877 /* Unlike DestroyIcon16, only icons created with CreateIcon32
878 are valid for DestroyIcon32, so don't use FreeResource32 */
879 return (GlobalFree16( hIcon ) == 0);
883 /***********************************************************************
884 * DestroyCursor16 (USER.458)
886 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
888 TRACE(cursor, "%04x\n", hCursor );
889 if (FreeResource16( hCursor ) == 0)
890 return TRUE;
891 else
892 /* I believe this very same line should be added for every function
893 where appears the comment:
895 "FIXME: should check for OEM/global heap cursor here"
897 which are most (all?) the ones that call FreeResource, at least
898 in this module. Maybe this should go to a wrapper to avoid
899 repetition. Or: couldn't it go to FreeResoutce itself?
901 I'll let this to someone savvy on the subject.
903 return (GlobalFree16 (hCursor) == 0);
907 /***********************************************************************
908 * DestroyCursor32 (USER32.132)
910 BOOL32 WINAPI DestroyCursor32( HCURSOR32 hCursor )
912 TRACE(cursor, "%04x\n", hCursor );
913 /* FIXME: should check for OEM/global heap cursor here */
914 /* Unlike DestroyCursor16, only cursors created with CreateCursor32
915 are valid for DestroyCursor32, so don't use FreeResource32 */
916 return (GlobalFree16( hCursor ) == 0);
920 /***********************************************************************
921 * DrawIcon16 (USER.84)
923 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
925 return DrawIcon32( hdc, x, y, hIcon );
929 /***********************************************************************
930 * DrawIcon32 (USER32.159)
932 BOOL32 WINAPI DrawIcon32( HDC32 hdc, INT32 x, INT32 y, HICON32 hIcon )
934 CURSORICONINFO *ptr;
935 HDC32 hMemDC;
936 HBITMAP32 hXorBits, hAndBits;
937 COLORREF oldFg, oldBg;
939 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
940 if (!(hMemDC = CreateCompatibleDC32( hdc ))) return FALSE;
941 hAndBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, 1, 1,
942 (char *)(ptr+1) );
943 hXorBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
944 ptr->bBitsPerPixel, (char *)(ptr + 1)
945 + ptr->nHeight * BITMAP_WIDTH_BYTES(ptr->nWidth,1) );
946 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
947 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
949 if (hXorBits && hAndBits)
951 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
952 BitBlt32( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
953 SelectObject32( hMemDC, hXorBits );
954 BitBlt32(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
955 SelectObject32( hMemDC, hBitTemp );
957 DeleteDC32( hMemDC );
958 if (hXorBits) DeleteObject32( hXorBits );
959 if (hAndBits) DeleteObject32( hAndBits );
960 GlobalUnlock16( hIcon );
961 SetTextColor32( hdc, oldFg );
962 SetBkColor32( hdc, oldBg );
963 return TRUE;
967 /***********************************************************************
968 * DumpIcon (USER.459)
970 DWORD WINAPI DumpIcon( SEGPTR pInfo, WORD *lpLen,
971 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
973 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
974 int sizeAnd, sizeXor;
976 if (!info) return 0;
977 sizeXor = info->nHeight * info->nWidthBytes;
978 sizeAnd = info->nHeight * BITMAP_WIDTH_BYTES( info->nWidth, 1 );
979 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
980 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
981 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
982 return MAKELONG( sizeXor, sizeXor );
986 /***********************************************************************
987 * CURSORICON_SetCursor
989 * Change the X cursor. Helper function for SetCursor() and ShowCursor().
990 * The Xlib critical section must be entered before calling this function.
992 static BOOL32 CURSORICON_SetCursor( HCURSOR16 hCursor )
994 Pixmap pixmapBits, pixmapMask, pixmapAll;
995 XColor fg, bg;
996 Cursor cursor = None;
998 if (!hCursor) /* Create an empty cursor */
1000 static const char data[] = { 0 };
1002 bg.red = bg.green = bg.blue = 0x0000;
1003 pixmapBits = XCreateBitmapFromData( display, rootWindow, data, 1, 1 );
1004 if (pixmapBits)
1006 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapBits,
1007 &bg, &bg, 0, 0 );
1008 XFreePixmap( display, pixmapBits );
1011 else /* Create the X cursor from the bits */
1013 CURSORICONINFO *ptr;
1014 XImage *image;
1016 if (!(ptr = (CURSORICONINFO*)GlobalLock16( hCursor ))) return FALSE;
1017 if (ptr->bPlanes * ptr->bBitsPerPixel != 1)
1019 WARN(cursor, "Cursor %04x has more than 1 bpp!\n", hCursor );
1020 return FALSE;
1023 /* Create a pixmap and transfer all the bits to it */
1025 /* NOTE: Following hack works, but only because XFree depth
1026 * 1 images really use 1 bit/pixel (and so the same layout
1027 * as the Windows cursor data). Perhaps use a more generic
1028 * algorithm here.
1030 pixmapAll = XCreatePixmap( display, rootWindow,
1031 ptr->nWidth, ptr->nHeight * 2, 1 );
1032 image = XCreateImage( display, DefaultVisualOfScreen(screen),
1033 1, ZPixmap, 0, (char *)(ptr + 1), ptr->nWidth,
1034 ptr->nHeight * 2, 16, ptr->nWidthBytes);
1035 if (image)
1037 image->byte_order = MSBFirst;
1038 image->bitmap_bit_order = MSBFirst;
1039 image->bitmap_unit = 16;
1040 _XInitImageFuncPtrs(image);
1041 if (pixmapAll)
1042 XPutImage( display, pixmapAll, BITMAP_monoGC, image,
1043 0, 0, 0, 0, ptr->nWidth, ptr->nHeight * 2 );
1044 image->data = NULL;
1045 XDestroyImage( image );
1048 /* Now create the 2 pixmaps for bits and mask */
1050 pixmapBits = XCreatePixmap( display, rootWindow,
1051 ptr->nWidth, ptr->nHeight, 1 );
1052 pixmapMask = XCreatePixmap( display, rootWindow,
1053 ptr->nWidth, ptr->nHeight, 1 );
1055 /* Make sure everything went OK so far */
1057 if (pixmapBits && pixmapMask && pixmapAll)
1059 /* We have to do some magic here, as cursors are not fully
1060 * compatible between Windows and X11. Under X11, there
1061 * are only 3 possible color cursor: black, white and
1062 * masked. So we map the 4th Windows color (invert the
1063 * bits on the screen) to black. This require some boolean
1064 * arithmetic:
1066 * Windows | X11
1067 * Xor And Result | Bits Mask Result
1068 * 0 0 black | 0 1 background
1069 * 0 1 no change | X 0 no change
1070 * 1 0 white | 1 1 foreground
1071 * 1 1 inverted | 0 1 background
1073 * which gives:
1074 * Bits = 'Xor' and not 'And'
1075 * Mask = 'Xor' or not 'And'
1077 * FIXME: apparently some servers do support 'inverted' color.
1078 * I don't know if it's correct per the X spec, but maybe
1079 * we ought to take advantage of it. -- AJ
1081 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
1082 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
1083 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
1084 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
1085 XSetFunction( display, BITMAP_monoGC, GXandReverse );
1086 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
1087 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
1088 XSetFunction( display, BITMAP_monoGC, GXorReverse );
1089 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
1090 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
1091 XSetFunction( display, BITMAP_monoGC, GXcopy );
1092 fg.red = fg.green = fg.blue = 0xffff;
1093 bg.red = bg.green = bg.blue = 0x0000;
1094 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapMask,
1095 &fg, &bg, ptr->ptHotSpot.x, ptr->ptHotSpot.y );
1098 /* Now free everything */
1100 if (pixmapAll) XFreePixmap( display, pixmapAll );
1101 if (pixmapBits) XFreePixmap( display, pixmapBits );
1102 if (pixmapMask) XFreePixmap( display, pixmapMask );
1103 GlobalUnlock16( hCursor );
1106 if (cursor == None) return FALSE;
1107 if (CURSORICON_XCursor != None) XFreeCursor( display, CURSORICON_XCursor );
1108 CURSORICON_XCursor = cursor;
1110 if (rootWindow != DefaultRootWindow(display))
1112 /* Set the cursor on the desktop window */
1113 XDefineCursor( display, rootWindow, cursor );
1115 else
1117 /* Set the same cursor for all top-level windows */
1118 HWND32 hwnd = GetWindow32( GetDesktopWindow32(), GW_CHILD );
1119 while(hwnd)
1121 Window win = WIN_GetXWindow( hwnd );
1122 if (win && win!=DefaultRootWindow(display))
1123 XDefineCursor( display, win, cursor );
1124 hwnd = GetWindow32( hwnd, GW_HWNDNEXT );
1127 return TRUE;
1131 /***********************************************************************
1132 * SetCursor16 (USER.69)
1134 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1136 return (HCURSOR16)SetCursor32( hCursor );
1140 /***********************************************************************
1141 * SetCursor32 (USER32.472)
1142 * RETURNS:
1143 * A handle to the previous cursor shape.
1145 HCURSOR32 WINAPI SetCursor32(
1146 HCURSOR32 hCursor /* Handle of cursor to show */
1148 HCURSOR32 hOldCursor;
1150 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1151 TRACE(cursor, "%04x\n", hCursor );
1152 hOldCursor = hActiveCursor;
1153 hActiveCursor = hCursor;
1154 /* Change the cursor shape only if it is visible */
1155 if (CURSOR_ShowCount >= 0)
1157 EnterCriticalSection( &X11DRV_CritSection );
1158 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1159 LeaveCriticalSection( &X11DRV_CritSection );
1161 return hOldCursor;
1165 /***********************************************************************
1166 * SetCursorPos16 (USER.70)
1168 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1170 SetCursorPos32( x, y );
1174 /***********************************************************************
1175 * SetCursorPos32 (USER32.474)
1177 BOOL32 WINAPI SetCursorPos32( INT32 x, INT32 y )
1179 TRACE(cursor, "x=%d y=%d\n", x, y );
1180 TSXWarpPointer( display, rootWindow, rootWindow, 0, 0, 0, 0, x, y );
1181 return TRUE;
1185 /***********************************************************************
1186 * ShowCursor16 (USER.71)
1188 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1190 return ShowCursor32( bShow );
1194 /***********************************************************************
1195 * ShowCursor32 (USER32.530)
1197 INT32 WINAPI ShowCursor32( BOOL32 bShow )
1199 TRACE(cursor, "%d, count=%d\n",
1200 bShow, CURSOR_ShowCount );
1202 EnterCriticalSection( &X11DRV_CritSection );
1203 if (bShow)
1205 if (++CURSOR_ShowCount == 0) /* Show it */
1206 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1208 else
1210 if (--CURSOR_ShowCount == -1) /* Hide it */
1211 CALL_LARGE_STACK( CURSORICON_SetCursor, 0 );
1213 LeaveCriticalSection( &X11DRV_CritSection );
1214 return CURSOR_ShowCount;
1218 /***********************************************************************
1219 * GetCursor16 (USER.247)
1221 HCURSOR16 WINAPI GetCursor16(void)
1223 return hActiveCursor;
1227 /***********************************************************************
1228 * GetCursor32 (USER32.227)
1230 HCURSOR32 WINAPI GetCursor32(void)
1232 return hActiveCursor;
1236 /***********************************************************************
1237 * ClipCursor16 (USER.16)
1239 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1241 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1242 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1243 return TRUE;
1247 /***********************************************************************
1248 * ClipCursor32 (USER32.53)
1250 BOOL32 WINAPI ClipCursor32( const RECT32 *rect )
1252 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1253 else CopyRect32( &CURSOR_ClipRect, rect );
1254 return TRUE;
1258 /***********************************************************************
1259 * GetCursorPos16 (USER.17)
1261 void WINAPI GetCursorPos16( POINT16 *pt )
1263 Window root, child;
1264 int rootX, rootY, childX, childY;
1265 unsigned int mousebut;
1267 if (!pt) return;
1268 if (!TSXQueryPointer( display, rootWindow, &root, &child,
1269 &rootX, &rootY, &childX, &childY, &mousebut ))
1270 pt->x = pt->y = 0;
1271 else
1273 pt->x = childX;
1274 pt->y = childY;
1275 if (mousebut & Button1Mask)
1276 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1277 else
1278 MouseButtonsStates[0] = FALSE;
1279 if (mousebut & Button2Mask)
1280 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1281 else
1282 MouseButtonsStates[1] = FALSE;
1283 if (mousebut & Button3Mask)
1284 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1285 else
1286 MouseButtonsStates[2] = FALSE;
1288 TRACE(cursor, "ret=%d,%d\n", pt->x, pt->y );
1292 /***********************************************************************
1293 * GetCursorPos32 (USER32.229)
1295 void WINAPI GetCursorPos32( POINT32 *pt )
1297 POINT16 pt16;
1298 GetCursorPos16( &pt16 );
1299 if (pt) CONV_POINT16TO32( &pt16, pt );
1303 /***********************************************************************
1304 * GetClipCursor16 (USER.309)
1306 void WINAPI GetClipCursor16( RECT16 *rect )
1308 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1312 /***********************************************************************
1313 * GetClipCursor32 (USER32.221)
1315 void WINAPI GetClipCursor32( RECT32 *rect )
1317 if (rect) CopyRect32( rect, &CURSOR_ClipRect );
1320 /**********************************************************************
1321 * LookupIconIdFromDirectoryEx16 (USER.364)
1323 * FIXME: exact parameter sizes
1325 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1326 INT16 width, INT16 height, UINT16 cFlag )
1328 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1329 UINT16 retVal = 0;
1330 if( dir && !dir->idReserved && (dir->idType & 3) )
1332 int colors = (cFlag == LR_MONOCHROME) ? 2 : COLOR_GetSystemPaletteSize();
1333 if( bIcon )
1335 ICONDIRENTRY* entry;
1336 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1337 if( entry ) retVal = entry->wResId;
1339 else
1341 CURSORDIRENTRY* entry;
1342 entry = CURSORICON_FindBestCursor( dir, width, height );
1343 if( entry ) retVal = entry->wResId;
1346 else WARN(cursor, "invalid resource directory\n");
1347 return retVal;
1350 /**********************************************************************
1351 * LookupIconIdFromDirectoryEx32 (USER32.380)
1353 INT32 WINAPI LookupIconIdFromDirectoryEx32( LPBYTE dir, BOOL32 bIcon,
1354 INT32 width, INT32 height, UINT32 cFlag )
1356 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1359 /**********************************************************************
1360 * LookupIconIdFromDirectory (USER.???)
1362 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1364 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1365 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1366 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1369 /**********************************************************************
1370 * LookupIconIdFromDirectory (USER32.379)
1372 INT32 WINAPI LookupIconIdFromDirectory32( LPBYTE dir, BOOL32 bIcon )
1374 return LookupIconIdFromDirectoryEx32( dir, bIcon,
1375 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1376 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1379 /**********************************************************************
1380 * GetIconID (USER.455)
1382 WORD WINAPI GetIconID( HGLOBAL16 hResource, DWORD resType )
1384 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1386 TRACE(cursor, "hRes=%04x, entries=%i\n",
1387 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1389 switch(resType)
1391 case RT_CURSOR16:
1392 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1393 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1394 case RT_ICON16:
1395 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1396 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1397 default:
1398 WARN(cursor, "invalid res type %ld\n", resType );
1400 return 0;
1403 /**********************************************************************
1404 * LoadCursorIconHandler (USER.336)
1406 * Supposed to load resources of Windows 2.x applications.
1408 HGLOBAL16 WINAPI LoadCursorIconHandler( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1410 FIXME(cursor,"(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1411 hResource, hModule, hRsrc);
1412 return (HGLOBAL16)0;
1415 /**********************************************************************
1416 * LoadDIBIconHandler (USER.357)
1418 * RT_ICON resource loader, installed by USER_SignalProc when module
1419 * is initialized.
1421 HGLOBAL16 WINAPI LoadDIBIconHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1423 /* If hResource is zero we must allocate a new memory block, if it's
1424 * non-zero but GlobalLock() returns NULL then it was discarded and
1425 * we have to recommit some memory, otherwise we just need to check
1426 * the block size. See LoadProc() in 16-bit SDK for more.
1429 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1430 if( hMemObj )
1432 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1433 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1434 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1435 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1437 return hMemObj;
1440 /**********************************************************************
1441 * LoadDIBCursorHandler (USER.356)
1443 * RT_CURSOR resource loader. Same as above.
1445 HGLOBAL16 WINAPI LoadDIBCursorHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1447 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1448 if( hMemObj )
1450 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1451 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1452 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1453 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1455 return hMemObj;
1458 /**********************************************************************
1459 * LoadIconHandler (USER.456)
1461 HICON16 WINAPI LoadIconHandler( HGLOBAL16 hResource, BOOL16 bNew )
1463 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1465 TRACE(cursor,"hRes=%04x\n",hResource);
1467 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1468 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1471 /***********************************************************************
1472 * LoadCursorW (USER32.362)
1474 HCURSOR32 WINAPI LoadCursor32W(HINSTANCE32 hInstance, LPCWSTR name)
1476 return CURSORICON_Load32( hInstance, name,
1477 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
1480 /***********************************************************************
1481 * LoadCursorA (USER32.359)
1483 HCURSOR32 WINAPI LoadCursor32A(HINSTANCE32 hInstance, LPCSTR name)
1485 HCURSOR32 res=0;
1486 if(!HIWORD(name))
1487 return LoadCursor32W(hInstance,(LPCWSTR)name);
1488 else
1490 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1491 res = LoadCursor32W(hInstance, uni);
1492 HeapFree( GetProcessHeap(), 0, uni);
1494 return res;
1496 /***********************************************************************
1497 * LoadCursorFromFile32W (USER32.361)
1499 HCURSOR32 WINAPI LoadCursorFromFile32W (LPCWSTR name)
1500 { FIXME(cursor, ":stub LoadCursorFromFile32W\n");
1501 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1502 return 0;
1505 /***********************************************************************
1506 * LoadCursorFromFile32A (USER32.360)
1508 HCURSOR32 WINAPI LoadCursorFromFile32A (LPCSTR name)
1509 { FIXME(cursor, ":stub LoadCursorFromFile32A %s\n", name);
1510 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1511 return 0;
1515 /***********************************************************************
1516 * LoadIconW (USER32.364)
1518 HICON32 WINAPI LoadIcon32W(HINSTANCE32 hInstance, LPCWSTR name)
1520 return CURSORICON_Load32( hInstance, name,
1521 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
1522 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE );
1525 /***********************************************************************
1526 * LoadIconA (USER32.363)
1528 HICON32 WINAPI LoadIcon32A(HINSTANCE32 hInstance, LPCSTR name)
1530 HICON32 res=0;
1532 if( !HIWORD(name) )
1533 return LoadIcon32W(hInstance, (LPCWSTR)name);
1534 else
1536 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1537 res = LoadIcon32W( hInstance, uni );
1538 HeapFree( GetProcessHeap(), 0, uni );
1540 return res;
1543 /**********************************************************************
1544 * GetIconInfo (USER32.242)
1546 BOOL32 WINAPI GetIconInfo(HICON32 hIcon,LPICONINFO iconinfo) {
1547 CURSORICONINFO *ciconinfo;
1549 ciconinfo = GlobalLock16(hIcon);
1550 if (!ciconinfo)
1551 return FALSE;
1552 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1553 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1554 iconinfo->fIcon = TRUE; /* hmm */
1556 iconinfo->hbmColor = CreateBitmap32 ( ciconinfo->nWidth, ciconinfo->nHeight,
1557 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1558 (char *)(ciconinfo + 1)
1559 + ciconinfo->nHeight *
1560 BITMAP_GetBitsWidth (ciconinfo->nWidth,1) );
1561 // BITMAP_WIDTH_BYTES(ciconinfo->nWidth,1) );
1562 iconinfo->hbmMask = CreateBitmap32 ( ciconinfo->nWidth, ciconinfo->nHeight,
1563 1, 1, (char *)(ciconinfo + 1));
1565 GlobalUnlock16(hIcon);
1567 return TRUE;
1570 /**********************************************************************
1571 * CreateIconIndirect (USER32.78)
1573 HICON32 WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1574 BITMAPOBJ *bmpXor,*bmpAnd;
1575 HICON32 hObj;
1576 int sizeXor,sizeAnd;
1578 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1579 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1581 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1582 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1584 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1585 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1586 if (hObj)
1588 CURSORICONINFO *info;
1590 info = (CURSORICONINFO *)GlobalLock16( hObj );
1591 info->ptHotSpot.x = iconinfo->xHotspot;
1592 info->ptHotSpot.y = iconinfo->yHotspot;
1593 info->nWidth = bmpXor->bitmap.bmWidth;
1594 info->nHeight = bmpXor->bitmap.bmHeight;
1595 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1596 info->bPlanes = bmpXor->bitmap.bmPlanes;
1597 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1599 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1601 GetBitmapBits32( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1602 GetBitmapBits32( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1603 GlobalUnlock16( hObj );
1605 return hObj;
1609 /**********************************************************************
1610 * DrawIconEx16 (USER.394)
1612 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1613 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1614 HBRUSH16 hbr, UINT16 flags)
1616 return DrawIconEx32(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1617 istep, hbr, flags);
1621 /******************************************************************************
1622 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1624 * NOTES
1625 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1627 * PARAMS
1628 * hdc [I] Handle to device context
1629 * x0 [I] X coordinate of upper left corner
1630 * y0 [I] Y coordinate of upper left corner
1631 * hIcon [I] Handle to icon to draw
1632 * cxWidth [I] Width of icon
1633 * cyWidth [I] Height of icon
1634 * istep [I] Index of frame in animated cursor
1635 * hbr [I] Handle to background brush
1636 * flags [I] Icon-drawing flags
1638 * RETURNS
1639 * Success: TRUE
1640 * Failure: FALSE
1642 BOOL32 WINAPI DrawIconEx32( HDC32 hdc, INT32 x0, INT32 y0, HICON32 hIcon,
1643 INT32 cxWidth, INT32 cyWidth, UINT32 istep,
1644 HBRUSH32 hbr, UINT32 flags )
1646 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1647 HDC32 hMemDC = CreateCompatibleDC32 (hdc);
1648 BOOL32 result = FALSE;
1650 if (istep)
1651 FIXME(icon, "Ignoring istep=%d\n", istep);
1652 if (hbr)
1653 FIXME(icon, "Ignoring hbr=%x\n", hbr);
1654 if (flags & DI_COMPAT)
1655 FIXME(icon, "Ignoring flag DI_COMPAT\n");
1657 if (hMemDC && ptr)
1659 HBITMAP32 hXorBits, hAndBits;
1660 COLORREF oldFg, oldBg;
1661 INT32 nStretchMode;
1663 /* Calculate the size of the destination image. */
1664 if (cxWidth == 0)
1665 if (flags & DI_DEFAULTSIZE)
1666 cxWidth = GetSystemMetrics32 (SM_CXICON);
1667 else
1668 cxWidth = ptr->nWidth;
1669 if (cyWidth == 0)
1670 if (flags & DI_DEFAULTSIZE)
1671 cyWidth = GetSystemMetrics32 (SM_CYICON);
1672 else
1673 cyWidth = ptr->nHeight;
1675 nStretchMode = SetStretchBltMode32 (hdc, STRETCH_DELETESCANS);
1677 hXorBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
1678 ptr->bPlanes, ptr->bBitsPerPixel,
1679 (char *)(ptr + 1)
1680 + ptr->nHeight *
1681 BITMAP_WIDTH_BYTES(ptr->nWidth,1) );
1682 hAndBits = CreateBitmap32 ( cxWidth, cyWidth,
1683 1, 1, (char *)(ptr+1) );
1684 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
1685 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
1687 if (hXorBits && hAndBits)
1689 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
1690 if (flags & DI_MASK)
1691 StretchBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1692 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1693 SelectObject32( hMemDC, hXorBits );
1694 if (flags & DI_IMAGE)
1695 StretchBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1696 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1697 SelectObject32( hMemDC, hBitTemp );
1698 result = TRUE;
1701 SetTextColor32( hdc, oldFg );
1702 SetBkColor32( hdc, oldBg );
1703 if (hXorBits) DeleteObject32( hXorBits );
1704 if (hAndBits) DeleteObject32( hAndBits );
1705 SetStretchBltMode32 (hdc, nStretchMode);
1707 if (hMemDC) DeleteDC32( hMemDC );
1708 GlobalUnlock16( hIcon );
1709 return result;