Release 980215
[wine.git] / objects / cursoricon.c
blob888e95eb981a1b873b111f27ddc1b3bd500fb5b7
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().
972 * The Xlib critical section must be entered before calling this function.
974 static BOOL32 CURSORICON_SetCursor( HCURSOR16 hCursor )
976 Pixmap pixmapBits, pixmapMask, pixmapAll;
977 XColor fg, bg;
978 Cursor cursor = None;
980 if (!hCursor) /* Create an empty cursor */
982 static const char data[] = { 0 };
984 bg.red = bg.green = bg.blue = 0x0000;
985 pixmapBits = XCreateBitmapFromData( display, rootWindow, data, 1, 1 );
986 if (pixmapBits)
988 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapBits,
989 &bg, &bg, 0, 0 );
990 XFreePixmap( display, pixmapBits );
993 else /* Create the X cursor from the bits */
995 CURSORICONINFO *ptr;
996 XImage *image;
998 if (!(ptr = (CURSORICONINFO*)GlobalLock16( hCursor ))) return FALSE;
999 if (ptr->bPlanes * ptr->bBitsPerPixel != 1)
1001 fprintf( stderr, "Cursor %04x has more than 1 bpp!\n", hCursor );
1002 return FALSE;
1005 /* Create a pixmap and transfer all the bits to it */
1007 /* NOTE: Following hack works, but only because XFree depth
1008 * 1 images really use 1 bit/pixel (and so the same layout
1009 * as the Windows cursor data). Perhaps use a more generic
1010 * algorithm here.
1012 pixmapAll = XCreatePixmap( display, rootWindow,
1013 ptr->nWidth, ptr->nHeight * 2, 1 );
1014 image = XCreateImage( display, DefaultVisualOfScreen(screen),
1015 1, ZPixmap, 0, (char *)(ptr + 1), ptr->nWidth,
1016 ptr->nHeight * 2, 16, ptr->nWidthBytes);
1017 if (image)
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)
1135 EnterCriticalSection( &X11DRV_CritSection );
1136 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1137 LeaveCriticalSection( &X11DRV_CritSection );
1139 return hOldCursor;
1143 /***********************************************************************
1144 * SetCursorPos16 (USER.70)
1146 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1148 SetCursorPos32( x, y );
1152 /***********************************************************************
1153 * SetCursorPos32 (USER32.473)
1155 BOOL32 WINAPI SetCursorPos32( INT32 x, INT32 y )
1157 dprintf_cursor( stddeb, "SetCursorPos: x=%d y=%d\n", x, y );
1158 TSXWarpPointer( display, rootWindow, rootWindow, 0, 0, 0, 0, x, y );
1159 return TRUE;
1163 /***********************************************************************
1164 * ShowCursor16 (USER.71)
1166 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1168 return ShowCursor32( bShow );
1172 /***********************************************************************
1173 * ShowCursor32 (USER32.529)
1175 INT32 WINAPI ShowCursor32( BOOL32 bShow )
1177 dprintf_cursor( stddeb, "ShowCursor: %d, count=%d\n",
1178 bShow, CURSOR_ShowCount );
1180 EnterCriticalSection( &X11DRV_CritSection );
1181 if (bShow)
1183 if (++CURSOR_ShowCount == 0) /* Show it */
1184 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1186 else
1188 if (--CURSOR_ShowCount == -1) /* Hide it */
1189 CALL_LARGE_STACK( CURSORICON_SetCursor, 0 );
1191 LeaveCriticalSection( &X11DRV_CritSection );
1192 return CURSOR_ShowCount;
1196 /***********************************************************************
1197 * GetCursor16 (USER.247)
1199 HCURSOR16 WINAPI GetCursor16(void)
1201 return hActiveCursor;
1205 /***********************************************************************
1206 * GetCursor32 (USER32.226)
1208 HCURSOR32 WINAPI GetCursor32(void)
1210 return hActiveCursor;
1214 /***********************************************************************
1215 * ClipCursor16 (USER.16)
1217 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1219 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1220 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1221 return TRUE;
1225 /***********************************************************************
1226 * ClipCursor32 (USER32.52)
1228 BOOL32 WINAPI ClipCursor32( const RECT32 *rect )
1230 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1231 else CopyRect32( &CURSOR_ClipRect, rect );
1232 return TRUE;
1236 /***********************************************************************
1237 * GetCursorPos16 (USER.17)
1239 void WINAPI GetCursorPos16( POINT16 *pt )
1241 Window root, child;
1242 int rootX, rootY, childX, childY;
1243 unsigned int mousebut;
1245 if (!pt) return;
1246 if (!TSXQueryPointer( display, rootWindow, &root, &child,
1247 &rootX, &rootY, &childX, &childY, &mousebut ))
1248 pt->x = pt->y = 0;
1249 else
1251 pt->x = childX;
1252 pt->y = childY;
1253 if (mousebut & Button1Mask)
1254 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1255 else
1256 MouseButtonsStates[0] = FALSE;
1257 if (mousebut & Button2Mask)
1258 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1259 else
1260 MouseButtonsStates[1] = FALSE;
1261 if (mousebut & Button3Mask)
1262 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1263 else
1264 MouseButtonsStates[2] = FALSE;
1266 dprintf_cursor(stddeb, "GetCursorPos: ret=%d,%d\n", pt->x, pt->y );
1270 /***********************************************************************
1271 * GetCursorPos32 (USER32.228)
1273 void WINAPI GetCursorPos32( POINT32 *pt )
1275 POINT16 pt16;
1276 GetCursorPos16( &pt16 );
1277 if (pt) CONV_POINT16TO32( &pt16, pt );
1281 /***********************************************************************
1282 * GetClipCursor16 (USER.309)
1284 void WINAPI GetClipCursor16( RECT16 *rect )
1286 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1290 /***********************************************************************
1291 * GetClipCursor32 (USER32.220)
1293 void WINAPI GetClipCursor32( RECT32 *rect )
1295 if (rect) CopyRect32( rect, &CURSOR_ClipRect );
1298 /**********************************************************************
1299 * LookupIconIdFromDirectoryEx16 (USER.364)
1301 * FIXME: exact parameter sizes
1303 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1304 INT16 width, INT16 height, UINT16 cFlag )
1306 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1307 UINT16 retVal = 0;
1308 if( dir && !dir->idReserved && (dir->idType & 3) )
1310 int colors = (cFlag == LR_MONOCHROME) ? 2 : COLOR_GetSystemPaletteSize();
1311 if( bIcon )
1313 ICONDIRENTRY* entry;
1314 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1315 if( entry ) retVal = entry->wResId;
1317 else
1319 CURSORDIRENTRY* entry;
1320 entry = CURSORICON_FindBestCursor( dir, width, height );
1321 if( entry ) retVal = entry->wResId;
1324 else dprintf_cursor(stddeb,"IconId: invalid resource directory\n");
1325 return retVal;
1328 /**********************************************************************
1329 * LookupIconIdFromDirectoryEx32 (USER32.379)
1331 INT32 WINAPI LookupIconIdFromDirectoryEx32( LPBYTE dir, BOOL32 bIcon,
1332 INT32 width, INT32 height, UINT32 cFlag )
1334 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1337 /**********************************************************************
1338 * LookupIconIdFromDirectory (USER.???)
1340 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1342 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1343 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1344 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1347 /**********************************************************************
1348 * LookupIconIdFromDirectory (USER32.378)
1350 INT32 WINAPI LookupIconIdFromDirectory32( LPBYTE dir, BOOL32 bIcon )
1352 return LookupIconIdFromDirectoryEx32( dir, bIcon,
1353 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1354 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1357 /**********************************************************************
1358 * GetIconID (USER.455)
1360 WORD WINAPI GetIconID( HGLOBAL16 hResource, DWORD resType )
1362 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1364 dprintf_cursor( stddeb, "GetIconID: hRes=%04x, entries=%i\n",
1365 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1367 switch(resType)
1369 case RT_CURSOR:
1370 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1371 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1372 case RT_ICON:
1373 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1374 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1375 default:
1376 fprintf( stderr, "GetIconID: invalid res type %ld\n", resType );
1378 return 0;
1381 /**********************************************************************
1382 * LoadCursorIconHandler (USER.336)
1384 * Supposed to load resources of Windows 2.x applications.
1386 HGLOBAL16 WINAPI LoadCursorIconHandler( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1388 fprintf(stderr,"hModule[%04x]: old 2.x resources are not supported!\n", hModule);
1389 return (HGLOBAL16)0;
1392 /**********************************************************************
1393 * LoadDIBIconHandler (USER.357)
1395 * RT_ICON resource loader, installed by USER_SignalProc when module
1396 * is initialized.
1398 HGLOBAL16 WINAPI LoadDIBIconHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1400 /* If hResource is zero we must allocate a new memory block, if it's
1401 * non-zero but GlobalLock() returns NULL then it was discarded and
1402 * we have to recommit some memory, otherwise we just need to check
1403 * the block size. See LoadProc() in 16-bit SDK for more.
1406 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1407 if( hMemObj )
1409 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1410 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1411 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1412 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1414 return hMemObj;
1417 /**********************************************************************
1418 * LoadDIBCursorHandler (USER.356)
1420 * RT_CURSOR resource loader. Same as above.
1422 HGLOBAL16 WINAPI LoadDIBCursorHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1424 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1425 if( hMemObj )
1427 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1428 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1429 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1430 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1432 return hMemObj;
1435 /**********************************************************************
1436 * LoadIconHandler (USER.456)
1438 HICON16 WINAPI LoadIconHandler( HGLOBAL16 hResource, BOOL16 bNew )
1440 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1442 dprintf_cursor(stddeb,"LoadIconHandler: hRes=%04x\n",hResource);
1444 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1445 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1448 /***********************************************************************
1449 * LoadCursorW (USER32.361)
1451 HCURSOR32 WINAPI LoadCursor32W(HINSTANCE32 hInstance, LPCWSTR name)
1453 return CURSORICON_Load32( hInstance, name,
1454 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
1457 /***********************************************************************
1458 * LoadCursorA (USER32.358)
1460 HCURSOR32 WINAPI LoadCursor32A(HINSTANCE32 hInstance, LPCSTR name)
1462 HCURSOR32 res=0;
1463 if(!HIWORD(name))
1464 return LoadCursor32W(hInstance,(LPCWSTR)name);
1465 else
1467 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1468 res = LoadCursor32W(hInstance, uni);
1469 HeapFree( GetProcessHeap(), 0, uni);
1471 return res;
1474 /***********************************************************************
1475 * LoadIconW (USER32.363)
1477 HICON32 WINAPI LoadIcon32W(HINSTANCE32 hInstance, LPCWSTR name)
1479 return CURSORICON_Load32( hInstance, name,
1480 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
1481 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE );
1484 /***********************************************************************
1485 * LoadIconA (USER32.362)
1487 HICON32 WINAPI LoadIcon32A(HINSTANCE32 hInstance, LPCSTR name)
1489 HICON32 res=0;
1491 if( !HIWORD(name) )
1492 return LoadIcon32W(hInstance, (LPCWSTR)name);
1493 else
1495 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1496 res = LoadIcon32W( hInstance, uni );
1497 HeapFree( GetProcessHeap(), 0, uni );
1499 return res;
1502 /**********************************************************************
1503 * GetIconInfo (USER32.241)
1505 BOOL32 WINAPI GetIconInfo(HICON32 hIcon,LPICONINFO iconinfo) {
1506 CURSORICONINFO *ciconinfo;
1508 ciconinfo = GlobalLock16(hIcon);
1509 if (!ciconinfo)
1510 return FALSE;
1511 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1512 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1513 iconinfo->fIcon = TRUE; /* hmm */
1514 /* FIXME ... add both bitmaps */
1515 return TRUE;
1518 /**********************************************************************
1519 * CreateIconIndirect (USER32.78)
1521 HICON32 WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1522 BITMAPOBJ *bmpXor,*bmpAnd;
1523 HICON32 hObj;
1524 int sizeXor,sizeAnd;
1526 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1527 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1529 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1530 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1532 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1533 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1534 if (hObj)
1536 CURSORICONINFO *info;
1538 info = (CURSORICONINFO *)GlobalLock16( hObj );
1539 info->ptHotSpot.x = iconinfo->xHotspot;
1540 info->ptHotSpot.y = iconinfo->yHotspot;
1541 info->nWidth = bmpXor->bitmap.bmWidth;
1542 info->nHeight = bmpXor->bitmap.bmHeight;
1543 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1544 info->bPlanes = bmpXor->bitmap.bmPlanes;
1545 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1547 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1549 GetBitmapBits32( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1550 GetBitmapBits32( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1551 GlobalUnlock16( hObj );
1553 return hObj;
1556 /**********************************************************************
1557 * DrawIconEx16 (USER.394)
1560 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1561 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1562 HBRUSH16 hbr, UINT16 flags)
1564 return DrawIconEx32 (hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1565 istep, hbr, flags);
1568 /**********************************************************************
1569 * DrawIconEx32 (USER32.160)
1572 BOOL32 WINAPI DrawIconEx32 (HDC32 hdc, INT32 x0, INT32 y0, HICON32 hIcon,
1573 INT32 cxWidth, INT32 cyWidth, UINT32 istep,
1574 HBRUSH32 hbr, UINT32 flags)
1576 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1577 HDC32 hMemDC = CreateCompatibleDC32 (hdc);
1578 BOOL32 result = FALSE;
1580 dprintf_icon (stddeb, "DrawIconEx32: part stub.\n");
1582 if (hMemDC && ptr)
1584 HBITMAP32 hXorBits, hAndBits;
1585 COLORREF oldFg, oldBg;
1587 /* Calculate the size of the destination image. */
1588 if (cxWidth == 0)
1589 if (flags & DI_DEFAULTSIZE)
1590 cxWidth = GetSystemMetrics32 (SM_CXICON);
1591 else
1592 cxWidth = ptr->nWidth;
1593 if (cyWidth == 0)
1594 if (flags & DI_DEFAULTSIZE)
1595 cyWidth = GetSystemMetrics32 (SM_CYICON);
1596 else
1597 cyWidth = ptr->nHeight;
1599 hXorBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
1600 ptr->bPlanes, ptr->bBitsPerPixel,
1601 (char *)(ptr + 1)
1602 + ptr->nHeight *
1603 BITMAP_WIDTH_BYTES(ptr->nWidth,1) );
1604 hAndBits = CreateBitmap32 ( cxWidth, cyWidth,
1605 1, 1, (char *)(ptr+1) );
1606 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
1607 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
1609 if (hXorBits && hAndBits)
1611 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
1612 if (flags & DI_MASK)
1613 BitBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1614 hMemDC, 0, 0, SRCAND);
1615 SelectObject32( hMemDC, hXorBits );
1616 if (flags & DI_IMAGE)
1617 BitBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1618 hMemDC, 0, 0, SRCPAINT);
1619 SelectObject32( hMemDC, hBitTemp );
1620 result = TRUE;
1623 SetTextColor32( hdc, oldFg );
1624 SetBkColor32( hdc, oldBg );
1625 if (hXorBits) DeleteObject32( hXorBits );
1626 if (hAndBits) DeleteObject32( hAndBits );
1628 if (hMemDC) DeleteDC32( hMemDC );
1629 GlobalUnlock16( hIcon );
1630 return result;