2 * Cursor and icon support
4 * Copyright 1995 Alexandre Julliard
10 * Cursors and icons are stored in a global heap block, with the
13 * CURSORICONINFO info;
17 * The bits structures are in the format of a device-dependent bitmap.
19 * This layout is very sub-optimal, as the bitmap bits are stored in
20 * the X client instead of in the server like other bitmaps; however,
21 * some programs (notably Paint Brush) expect to be able to manipulate
22 * the bits directly :-(
31 #include "cursoricon.h"
32 #include "sysmetrics.h"
39 extern UINT16
COLOR_GetSystemPaletteSize();
41 Cursor CURSORICON_XCursor
= None
; /* Current X cursor */
42 static HCURSOR32 hActiveCursor
= 0; /* Active cursor */
43 static INT32 CURSOR_ShowCount
= 0; /* Cursor display count */
44 static RECT32 CURSOR_ClipRect
; /* Cursor clipping rect */
46 /**********************************************************************
47 * CURSORICON_FindBestIcon
49 * Find the icon closest to the requested size and number of colors.
51 static ICONDIRENTRY
*CURSORICON_FindBestIcon( CURSORICONDIR
*dir
, int width
,
52 int height
, int colors
)
54 int i
, maxcolors
, maxwidth
, maxheight
;
55 ICONDIRENTRY
*entry
, *bestEntry
= NULL
;
59 fprintf( stderr
, "Icon: empty directory!\n" );
62 if (dir
->idCount
== 1) return &dir
->idEntries
[0].icon
; /* No choice... */
64 /* First find the exact size with less colors */
67 for (i
= 0, entry
= &dir
->idEntries
[0].icon
; i
< dir
->idCount
; i
++,entry
++)
68 if ((entry
->bWidth
== width
) && (entry
->bHeight
== height
) &&
69 (entry
->bColorCount
<= colors
) && (entry
->bColorCount
> maxcolors
))
72 maxcolors
= entry
->bColorCount
;
74 if (bestEntry
) return bestEntry
;
76 /* First find the exact size with more colors */
79 for (i
= 0, entry
= &dir
->idEntries
[0].icon
; i
< dir
->idCount
; i
++,entry
++)
80 if ((entry
->bWidth
== width
) && (entry
->bHeight
== height
) &&
81 (entry
->bColorCount
> colors
) && (entry
->bColorCount
<= maxcolors
))
84 maxcolors
= entry
->bColorCount
;
86 if (bestEntry
) return bestEntry
;
88 /* Now find a smaller one with less colors */
90 maxcolors
= maxwidth
= maxheight
= 0;
91 for (i
= 0, entry
= &dir
->idEntries
[0].icon
; i
< dir
->idCount
; i
++,entry
++)
92 if ((entry
->bWidth
<= width
) && (entry
->bHeight
<= height
) &&
93 (entry
->bWidth
>= maxwidth
) && (entry
->bHeight
>= maxheight
) &&
94 (entry
->bColorCount
<= colors
) && (entry
->bColorCount
> maxcolors
))
97 maxwidth
= entry
->bWidth
;
98 maxheight
= entry
->bHeight
;
99 maxcolors
= entry
->bColorCount
;
101 if (bestEntry
) return bestEntry
;
103 /* Now find a smaller one with more colors */
106 maxwidth
= maxheight
= 0;
107 for (i
= 0, entry
= &dir
->idEntries
[0].icon
; i
< dir
->idCount
; i
++,entry
++)
108 if ((entry
->bWidth
<= width
) && (entry
->bHeight
<= height
) &&
109 (entry
->bWidth
>= maxwidth
) && (entry
->bHeight
>= maxheight
) &&
110 (entry
->bColorCount
> colors
) && (entry
->bColorCount
<= maxcolors
))
113 maxwidth
= entry
->bWidth
;
114 maxheight
= entry
->bHeight
;
115 maxcolors
= entry
->bColorCount
;
117 if (bestEntry
) return bestEntry
;
119 /* Now find a larger one with less colors */
122 maxwidth
= maxheight
= 255;
123 for (i
= 0, entry
= &dir
->idEntries
[0].icon
; i
< dir
->idCount
; i
++,entry
++)
124 if ((entry
->bWidth
<= maxwidth
) && (entry
->bHeight
<= maxheight
) &&
125 (entry
->bColorCount
<= colors
) && (entry
->bColorCount
> maxcolors
))
128 maxwidth
= entry
->bWidth
;
129 maxheight
= entry
->bHeight
;
130 maxcolors
= entry
->bColorCount
;
132 if (bestEntry
) return bestEntry
;
134 /* Now find a larger one with more colors */
136 maxcolors
= maxwidth
= maxheight
= 255;
137 for (i
= 0, entry
= &dir
->idEntries
[0].icon
; i
< dir
->idCount
; i
++,entry
++)
138 if ((entry
->bWidth
<= maxwidth
) && (entry
->bHeight
<= maxheight
) &&
139 (entry
->bColorCount
> colors
) && (entry
->bColorCount
<= maxcolors
))
142 maxwidth
= entry
->bWidth
;
143 maxheight
= entry
->bHeight
;
144 maxcolors
= entry
->bColorCount
;
151 /**********************************************************************
152 * CURSORICON_FindBestCursor
154 * Find the cursor closest to the requested size.
156 static CURSORDIRENTRY
*CURSORICON_FindBestCursor( CURSORICONDIR
*dir
,
157 int width
, int height
)
159 int i
, maxwidth
, maxheight
;
160 CURSORDIRENTRY
*entry
, *bestEntry
= NULL
;
162 if (dir
->idCount
< 1)
164 fprintf( stderr
, "Cursor: empty directory!\n" );
167 if (dir
->idCount
== 1) return &dir
->idEntries
[0].cursor
; /* No choice... */
169 /* First find the largest one smaller than or equal to the requested size*/
171 maxwidth
= maxheight
= 0;
172 for(i
= 0,entry
= &dir
->idEntries
[0].cursor
; i
< dir
->idCount
; i
++,entry
++)
173 if ((entry
->wWidth
<= width
) && (entry
->wHeight
<= height
) &&
174 (entry
->wWidth
> maxwidth
) && (entry
->wHeight
> maxheight
))
177 maxwidth
= entry
->wWidth
;
178 maxheight
= entry
->wHeight
;
180 if (bestEntry
) return bestEntry
;
182 /* Now find the smallest one larger than the requested size */
184 maxwidth
= maxheight
= 255;
185 for(i
= 0,entry
= &dir
->idEntries
[0].cursor
; i
< dir
->idCount
; i
++,entry
++)
186 if ((entry
->wWidth
< maxwidth
) && (entry
->wHeight
< maxheight
))
189 maxwidth
= entry
->wWidth
;
190 maxheight
= entry
->wHeight
;
197 /**********************************************************************
198 * CURSORICON_LoadDirEntry
200 * Load the icon/cursor directory for a given resource name and find the
201 * best matching entry.
203 static BOOL32
CURSORICON_LoadDirEntry( HINSTANCE32 hInstance
, SEGPTR name
,
204 INT32 width
, INT32 height
,
205 INT32 colors
, BOOL32 fCursor
,
206 CURSORICONDIRENTRY
*dirEntry
)
211 CURSORICONDIRENTRY
*entry
= NULL
;
213 if (!(hRsrc
= FindResource16( hInstance
, name
,
214 fCursor
? RT_GROUP_CURSOR
: RT_GROUP_ICON
)))
216 if (!(hMem
= LoadResource16( hInstance
, hRsrc
))) return FALSE
;
217 if ((dir
= (CURSORICONDIR
*)LockResource16( hMem
)))
220 entry
= (CURSORICONDIRENTRY
*)CURSORICON_FindBestCursor( dir
,
223 entry
= (CURSORICONDIRENTRY
*)CURSORICON_FindBestIcon( dir
,
224 width
, height
, colors
);
225 if (entry
) *dirEntry
= *entry
;
227 FreeResource16( hMem
);
228 return (entry
!= NULL
);
232 /**********************************************************************
233 * CURSORICON_LoadHandler
235 * Create a cursor or icon from a resource.
237 HGLOBAL16
CURSORICON_LoadHandler( HGLOBAL16 handle
, HINSTANCE16 hInstance
,
240 HBITMAP32 hAndBits
, hXorBits
;
242 int size
, sizeAnd
, sizeXor
;
243 POINT16 hotspot
= { 0 ,0 };
244 BITMAPOBJ
*bmpXor
, *bmpAnd
;
245 BITMAPINFO
*bmi
, *pInfo
;
246 CURSORICONINFO
*info
;
249 if (fCursor
) /* If cursor, get the hotspot */
251 POINT16
*pt
= (POINT16
*)LockResource16( handle
);
253 bmi
= (BITMAPINFO
*)(pt
+ 1);
255 else bmi
= (BITMAPINFO
*)LockResource16( handle
);
257 /* Create a copy of the bitmap header */
259 size
= DIB_BitmapInfoSize( bmi
, DIB_RGB_COLORS
);
260 /* Make sure we have room for the monochrome bitmap later on */
261 size
= MAX( size
, sizeof(BITMAPINFOHEADER
) + 2*sizeof(RGBQUAD
) );
262 pInfo
= (BITMAPINFO
*)xmalloc( size
);
263 memcpy( pInfo
, bmi
, size
);
265 if (pInfo
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
))
267 if (pInfo
->bmiHeader
.biCompression
!= BI_RGB
)
269 fprintf(stderr
,"Unknown size for compressed icon bitmap.\n");
273 pInfo
->bmiHeader
.biHeight
/= 2;
275 else if (pInfo
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
277 BITMAPCOREHEADER
*core
= (BITMAPCOREHEADER
*)pInfo
;
282 fprintf( stderr
, "CURSORICON_Load: Unknown bitmap length %ld!\n",
283 pInfo
->bmiHeader
.biSize
);
288 /* Create the XOR bitmap */
290 if (!(hdc
= GetDC32( 0 )))
296 hXorBits
= CreateDIBitmap32( hdc
, &pInfo
->bmiHeader
, CBM_INIT
,
297 (char*)bmi
+ size
, pInfo
, DIB_RGB_COLORS
);
300 ReleaseDC32( 0, hdc
);
304 /* Fix the bitmap header to load the monochrome mask */
306 if (pInfo
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
))
308 BITMAPINFOHEADER
*bih
= &pInfo
->bmiHeader
;
309 RGBQUAD
*rgb
= pInfo
->bmiColors
;
310 bits
= (char *)bmi
+ size
+
311 DIB_GetImageWidthBytes(bih
->biWidth
,bih
->biBitCount
)*bih
->biHeight
;
313 bih
->biClrUsed
= bih
->biClrImportant
= 2;
314 rgb
[0].rgbBlue
= rgb
[0].rgbGreen
= rgb
[0].rgbRed
= 0x00;
315 rgb
[1].rgbBlue
= rgb
[1].rgbGreen
= rgb
[1].rgbRed
= 0xff;
316 rgb
[0].rgbReserved
= rgb
[1].rgbReserved
= 0;
320 BITMAPCOREHEADER
*bch
= (BITMAPCOREHEADER
*)pInfo
;
321 RGBTRIPLE
*rgb
= (RGBTRIPLE
*)(bch
+ 1);
322 bits
= (char *)bmi
+ size
+
323 DIB_GetImageWidthBytes(bch
->bcWidth
,bch
->bcBitCount
)*bch
->bcHeight
;
325 rgb
[0].rgbtBlue
= rgb
[0].rgbtGreen
= rgb
[0].rgbtRed
= 0x00;
326 rgb
[1].rgbtBlue
= rgb
[1].rgbtGreen
= rgb
[1].rgbtRed
= 0xff;
329 /* Create the AND bitmap */
331 hAndBits
= CreateDIBitmap32( hdc
, &pInfo
->bmiHeader
, CBM_INIT
,
332 bits
, pInfo
, DIB_RGB_COLORS
);
333 ReleaseDC32( 0, hdc
);
335 DeleteObject32( hXorBits
);
340 /* Now create the CURSORICONINFO structure */
342 bmpXor
= (BITMAPOBJ
*) GDI_GetObjPtr( hXorBits
, BITMAP_MAGIC
);
343 bmpAnd
= (BITMAPOBJ
*) GDI_GetObjPtr( hAndBits
, BITMAP_MAGIC
);
344 sizeXor
= bmpXor
->bitmap
.bmHeight
* bmpXor
->bitmap
.bmWidthBytes
;
345 sizeAnd
= bmpAnd
->bitmap
.bmHeight
* bmpAnd
->bitmap
.bmWidthBytes
;
347 if (!(handle
= GlobalAlloc16( GMEM_MOVEABLE
,
348 sizeof(CURSORICONINFO
) + sizeXor
+ sizeAnd
)))
350 DeleteObject32( hXorBits
);
351 DeleteObject32( hAndBits
);
355 /* Make it owned by the module */
356 if (hInstance
) FarSetOwner( handle
, GetExePtr(hInstance
) );
358 info
= (CURSORICONINFO
*)GlobalLock16( handle
);
359 info
->ptHotSpot
.x
= hotspot
.x
;
360 info
->ptHotSpot
.y
= hotspot
.y
;
361 info
->nWidth
= bmpXor
->bitmap
.bmWidth
;
362 info
->nHeight
= bmpXor
->bitmap
.bmHeight
;
363 info
->nWidthBytes
= bmpXor
->bitmap
.bmWidthBytes
;
364 info
->bPlanes
= bmpXor
->bitmap
.bmPlanes
;
365 info
->bBitsPerPixel
= bmpXor
->bitmap
.bmBitsPixel
;
367 /* Transfer the bitmap bits to the CURSORICONINFO structure */
369 GetBitmapBits32( hAndBits
, sizeAnd
, (char *)(info
+ 1) );
370 GetBitmapBits32( hXorBits
, sizeXor
, (char *)(info
+ 1) + sizeAnd
);
371 DeleteObject32( hXorBits
);
372 DeleteObject32( hAndBits
);
373 GlobalUnlock16( handle
);
377 /**********************************************************************
380 * Load a cursor or icon.
382 static HGLOBAL16
CURSORICON_Load( HINSTANCE16 hInstance
, SEGPTR name
,
383 INT32 width
, INT32 height
, INT32 colors
,
386 HGLOBAL16 handle
, hRet
;
388 CURSORICONDIRENTRY dirEntry
;
390 if (!hInstance
) /* OEM cursor/icon */
392 if (HIWORD(name
)) /* Check for '#xxx' name */
394 char *ptr
= PTR_SEG_TO_LIN( name
);
395 if (ptr
[0] != '#') return 0;
396 if (!(name
= (SEGPTR
)atoi( ptr
+ 1 ))) return 0;
398 return OBM_LoadCursorIcon( LOWORD(name
), fCursor
);
401 /* Find the best entry in the directory */
403 if (!CURSORICON_LoadDirEntry( hInstance
, name
, width
, height
,
404 colors
, fCursor
, &dirEntry
)) return 0;
406 /* Load the resource */
408 if (!(hRsrc
= FindResource16( hInstance
,
409 MAKEINTRESOURCE( dirEntry
.icon
.wResId
),
410 fCursor
? RT_CURSOR
: RT_ICON
))) return 0;
411 if (!(handle
= LoadResource16( hInstance
, hRsrc
))) return 0;
413 hRet
= CURSORICON_LoadHandler( handle
, hInstance
, fCursor
);
414 FreeResource16(handle
);
419 /***********************************************************************
422 * Make a copy of a cursor or icon.
424 static HGLOBAL16
CURSORICON_Copy( HINSTANCE16 hInstance
, HGLOBAL16 handle
)
426 char *ptrOld
, *ptrNew
;
430 if (!(ptrOld
= (char *)GlobalLock16( handle
))) return 0;
431 if (!(hInstance
= GetExePtr( hInstance
))) return 0;
432 size
= GlobalSize16( handle
);
433 hNew
= GlobalAlloc16( GMEM_MOVEABLE
, size
);
434 FarSetOwner( hNew
, hInstance
);
435 ptrNew
= (char *)GlobalLock16( hNew
);
436 memcpy( ptrNew
, ptrOld
, size
);
437 GlobalUnlock16( handle
);
438 GlobalUnlock16( hNew
);
442 /***********************************************************************
443 * CURSORICON_IconToCursor
445 * Converts bitmap to mono and truncates if icon is too large
447 HCURSOR16
CURSORICON_IconToCursor(HICON16 hIcon
, BOOL32 bSemiTransparent
)
450 CURSORICONINFO
*ptr
= NULL
;
451 HTASK16 hTask
= GetCurrentTask();
452 TDB
* pTask
= (TDB
*)GlobalLock16(hTask
);
455 if (!(ptr
= (CURSORICONINFO
*)GlobalLock16( hIcon
))) return FALSE
;
456 if (ptr
->bPlanes
* ptr
->bBitsPerPixel
== 1)
457 hRet
= CURSORICON_Copy( pTask
->hInstance
, hIcon
);
462 int x
, y
, ix
, iy
, shift
;
463 int bpp
= (ptr
->bBitsPerPixel
>=24)?32:ptr
->bBitsPerPixel
; /* this sucks */
464 BYTE
* psPtr
= (BYTE
*)(ptr
+ 1) +
465 ptr
->nHeight
* BITMAP_WIDTH_BYTES(ptr
->nWidth
,1);
466 BYTE
* pxbPtr
= pXorBits
;
467 unsigned *psc
= NULL
, val
= 0;
468 unsigned val_base
= 0xffffffff >> (32 - bpp
);
476 memset(pXorBits
, 0, 128);
477 cI
.bBitsPerPixel
= 1; cI
.bPlanes
= 1;
478 cI
.ptHotSpot
.x
= cI
.ptHotSpot
.y
= 15;
479 cI
.nWidth
= 32; cI
.nHeight
= 32;
480 cI
.nWidthBytes
= 4; /* 1bpp */
482 x
= (ptr
->nWidth
> 32) ? 32 : ptr
->nWidth
;
483 y
= (ptr
->nHeight
> 32) ? 32 : ptr
->nHeight
;
485 for( iy
= 0; iy
< y
; iy
++ )
487 val
= BITMAP_WIDTH_BYTES( ptr
->nWidth
, 1 );
488 memcpy( pAndBits
+ iy
* 4,
489 (BYTE
*)(ptr
+ 1) + iy
* val
, (val
>4) ? 4 : val
);
492 for( ix
= 0; ix
< x
; ix
++ )
494 if( bSemiTransparent
&& ((ix
+shift
)%2) )
496 pbc
= pAndBits
+ iy
* 4 + ix
/8;
497 *pbc
|= 0x80 >> (ix
%8);
501 psc
= (unsigned*)(psPtr
+ (ix
* bpp
)/8);
502 val
= ((*psc
) >> (ix
* bpp
)%8) & val_base
;
503 col
= COLOR_ToLogical(val
);
504 if( GetRValue(col
) > 0xa0 ||
505 GetGValue(col
) > 0x80 ||
506 GetBValue(col
) > 0xa0 )
509 *pbc
|= 0x80 >> (ix
%8);
513 psPtr
+= ptr
->nWidthBytes
;
516 hRet
= CreateCursorIconIndirect( pTask
->hInstance
, &cI
, pAndBits
, pXorBits
);
518 if( !hRet
) /* fall back on default drag cursor */
519 hRet
= CURSORICON_Copy( pTask
->hInstance
,
520 CURSORICON_Load(0,MAKEINTRESOURCE(OCR_DRAGOBJECT
),
521 SYSMETRICS_CXCURSOR
, SYSMETRICS_CYCURSOR
, 1, TRUE
) );
528 /***********************************************************************
529 * LoadCursor16 (USER.173)
531 HCURSOR16
LoadCursor16( HINSTANCE16 hInstance
, SEGPTR name
)
534 dprintf_cursor( stddeb
, "LoadCursor16: %04x '%s'\n",
535 hInstance
, (char *)PTR_SEG_TO_LIN( name
) );
537 dprintf_cursor( stddeb
, "LoadCursor16: %04x %04x\n",
538 hInstance
, LOWORD(name
) );
540 return CURSORICON_Load( hInstance
, name
,
541 SYSMETRICS_CXCURSOR
, SYSMETRICS_CYCURSOR
, 1, TRUE
);
545 /***********************************************************************
546 * LoadIcon16 (USER.174)
548 HICON16
LoadIcon16( HINSTANCE16 hInstance
, SEGPTR name
)
551 dprintf_icon( stddeb
, "LoadIcon: %04x '%s'\n",
552 hInstance
, (char *)PTR_SEG_TO_LIN( name
) );
554 dprintf_icon( stddeb
, "LoadIcon: %04x %04x\n",
555 hInstance
, LOWORD(name
) );
557 return CURSORICON_Load( hInstance
, name
,
558 SYSMETRICS_CXICON
, SYSMETRICS_CYICON
,
559 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE
);
563 /***********************************************************************
564 * CreateCursor16 (USER.406)
566 HCURSOR16
CreateCursor16(HINSTANCE16 hInstance
, INT16 xHotSpot
, INT16 yHotSpot
,
567 INT16 nWidth
, INT16 nHeight
,
568 LPCVOID lpANDbits
, LPCVOID lpXORbits
)
570 CURSORICONINFO info
= { { xHotSpot
, yHotSpot
}, nWidth
, nHeight
, 0, 1, 1 };
572 dprintf_cursor( stddeb
, "CreateCursor: %dx%d spot=%d,%d xor=%p and=%p\n",
573 nWidth
, nHeight
, xHotSpot
, yHotSpot
, lpXORbits
, lpANDbits
);
574 return CreateCursorIconIndirect( hInstance
, &info
, lpANDbits
, lpXORbits
);
578 /***********************************************************************
579 * CreateCursor32 (USER32.66)
581 HCURSOR32
CreateCursor32(HINSTANCE32 hInstance
, INT32 xHotSpot
, INT32 yHotSpot
,
582 INT32 nWidth
, INT32 nHeight
,
583 LPCVOID lpANDbits
, LPCVOID lpXORbits
)
585 CURSORICONINFO info
= { { xHotSpot
, yHotSpot
}, nWidth
, nHeight
, 0, 1, 1 };
587 dprintf_cursor( stddeb
, "CreateCursor: %dx%d spot=%d,%d xor=%p and=%p\n",
588 nWidth
, nHeight
, xHotSpot
, yHotSpot
, lpXORbits
, lpANDbits
);
589 return CreateCursorIconIndirect( hInstance
, &info
, lpANDbits
, lpXORbits
);
593 /***********************************************************************
594 * CreateIcon16 (USER.407)
596 HICON16
CreateIcon16( HINSTANCE16 hInstance
, INT16 nWidth
, INT16 nHeight
,
597 BYTE bPlanes
, BYTE bBitsPixel
,
598 LPCVOID lpANDbits
, LPCVOID lpXORbits
)
600 CURSORICONINFO info
= { { 0, 0 }, nWidth
, nHeight
, 0, bPlanes
, bBitsPixel
};
602 dprintf_icon( stddeb
, "CreateIcon: %dx%dx%d, xor=%p, and=%p\n",
603 nWidth
, nHeight
, bPlanes
* bBitsPixel
, lpXORbits
, lpANDbits
);
604 return CreateCursorIconIndirect( hInstance
, &info
, lpANDbits
, lpXORbits
);
608 /***********************************************************************
609 * CreateIcon32 (USER32.74)
611 HICON32
CreateIcon32( HINSTANCE32 hInstance
, INT32 nWidth
, INT32 nHeight
,
612 BYTE bPlanes
, BYTE bBitsPixel
,
613 LPCVOID lpANDbits
, LPCVOID lpXORbits
)
615 CURSORICONINFO info
= { { 0, 0 }, nWidth
, nHeight
, 0, bPlanes
, bBitsPixel
};
617 dprintf_icon( stddeb
, "CreateIcon: %dx%dx%d, xor=%p, and=%p\n",
618 nWidth
, nHeight
, bPlanes
* bBitsPixel
, lpXORbits
, lpANDbits
);
619 return CreateCursorIconIndirect( hInstance
, &info
, lpANDbits
, lpXORbits
);
623 /***********************************************************************
624 * CreateCursorIconIndirect (USER.408)
626 HGLOBAL16
CreateCursorIconIndirect(HINSTANCE16 hInstance
, CURSORICONINFO
*info
,
627 LPCVOID lpANDbits
, LPCVOID lpXORbits
)
631 int sizeAnd
, sizeXor
;
633 hInstance
= GetExePtr( hInstance
); /* Make it a module handle */
634 if (!hInstance
|| !lpXORbits
|| !lpANDbits
|| info
->bPlanes
!= 1) return 0;
635 info
->nWidthBytes
= BITMAP_WIDTH_BYTES(info
->nWidth
,info
->bBitsPerPixel
);
636 sizeXor
= info
->nHeight
* info
->nWidthBytes
;
637 sizeAnd
= info
->nHeight
* BITMAP_WIDTH_BYTES( info
->nWidth
, 1 );
638 if (!(handle
= DirectResAlloc(hInstance
, 0x10,
639 sizeof(CURSORICONINFO
) + sizeXor
+ sizeAnd
)))
641 ptr
= (char *)GlobalLock16( handle
);
642 memcpy( ptr
, info
, sizeof(*info
) );
643 memcpy( ptr
+ sizeof(CURSORICONINFO
), lpANDbits
, sizeAnd
);
644 memcpy( ptr
+ sizeof(CURSORICONINFO
) + sizeAnd
, lpXORbits
, sizeXor
);
645 GlobalUnlock16( handle
);
650 /***********************************************************************
651 * CopyIcon16 (USER.368)
653 HICON16
CopyIcon16( HINSTANCE16 hInstance
, HICON16 hIcon
)
655 dprintf_icon( stddeb
, "CopyIcon16: %04x %04x\n", hInstance
, hIcon
);
656 return CURSORICON_Copy( hInstance
, hIcon
);
660 /***********************************************************************
661 * CopyIcon32 (USER32.59)
663 HICON32
CopyIcon32( HICON32 hIcon
)
665 dprintf_icon( stddeb
, "CopyIcon32: %04x\n", hIcon
);
666 return CURSORICON_Copy( 0, hIcon
);
670 /***********************************************************************
671 * CopyCursor16 (USER.369)
673 HCURSOR16
CopyCursor16( HINSTANCE16 hInstance
, HCURSOR16 hCursor
)
675 dprintf_cursor( stddeb
, "CopyCursor16: %04x %04x\n", hInstance
, hCursor
);
676 return CURSORICON_Copy( hInstance
, hCursor
);
680 /***********************************************************************
681 * DestroyIcon16 (USER.457)
683 BOOL16
DestroyIcon16( HICON16 hIcon
)
685 return DestroyIcon32( hIcon
);
689 /***********************************************************************
690 * DestroyIcon32 (USER32.132)
692 BOOL32
DestroyIcon32( HICON32 hIcon
)
694 dprintf_icon( stddeb
, "DestroyIcon: %04x\n", hIcon
);
695 /* FIXME: should check for OEM icon here */
696 return (GlobalFree16( hIcon
) != 0);
700 /***********************************************************************
701 * DestroyCursor16 (USER.458)
703 BOOL16
DestroyCursor16( HCURSOR16 hCursor
)
705 return DestroyCursor32( hCursor
);
709 /***********************************************************************
710 * DestroyCursor32 (USER32.131)
712 BOOL32
DestroyCursor32( HCURSOR32 hCursor
)
714 dprintf_cursor( stddeb
, "DestroyCursor: %04x\n", hCursor
);
715 /* FIXME: should check for OEM cursor here */
716 return (GlobalFree16( hCursor
) != 0);
720 /***********************************************************************
721 * DrawIcon16 (USER.84)
723 BOOL16
DrawIcon16( HDC16 hdc
, INT16 x
, INT16 y
, HICON16 hIcon
)
725 return DrawIcon32( hdc
, x
, y
, hIcon
);
729 /***********************************************************************
730 * DrawIcon32 (USER32.158)
732 BOOL32
DrawIcon32( HDC32 hdc
, INT32 x
, INT32 y
, HICON32 hIcon
)
736 HBITMAP32 hXorBits
, hAndBits
;
737 COLORREF oldFg
, oldBg
;
739 if (!(ptr
= (CURSORICONINFO
*)GlobalLock16( hIcon
))) return FALSE
;
740 if (!(hMemDC
= CreateCompatibleDC32( hdc
))) return FALSE
;
741 hAndBits
= CreateBitmap32( ptr
->nWidth
, ptr
->nHeight
, 1, 1,
743 hXorBits
= CreateBitmap32( ptr
->nWidth
, ptr
->nHeight
, ptr
->bPlanes
,
744 ptr
->bBitsPerPixel
, (char *)(ptr
+ 1)
745 + ptr
->nHeight
* BITMAP_WIDTH_BYTES(ptr
->nWidth
,1) );
746 oldFg
= SetTextColor32( hdc
, RGB(0,0,0) );
747 oldBg
= SetBkColor32( hdc
, RGB(255,255,255) );
749 if (hXorBits
&& hAndBits
)
751 HBITMAP32 hBitTemp
= SelectObject32( hMemDC
, hAndBits
);
752 BitBlt32( hdc
, x
, y
, ptr
->nWidth
, ptr
->nHeight
, hMemDC
, 0, 0, SRCAND
);
753 SelectObject32( hMemDC
, hXorBits
);
754 BitBlt32(hdc
, x
, y
, ptr
->nWidth
, ptr
->nHeight
, hMemDC
, 0, 0,SRCINVERT
);
755 SelectObject32( hMemDC
, hBitTemp
);
757 DeleteDC32( hMemDC
);
758 if (hXorBits
) DeleteObject32( hXorBits
);
759 if (hAndBits
) DeleteObject32( hAndBits
);
760 GlobalUnlock16( hIcon
);
761 SetTextColor32( hdc
, oldFg
);
762 SetBkColor32( hdc
, oldBg
);
767 /***********************************************************************
768 * DumpIcon (USER.459)
770 DWORD
DumpIcon( SEGPTR pInfo
, WORD
*lpLen
,
771 SEGPTR
*lpXorBits
, SEGPTR
*lpAndBits
)
773 CURSORICONINFO
*info
= PTR_SEG_TO_LIN( pInfo
);
774 int sizeAnd
, sizeXor
;
777 sizeXor
= info
->nHeight
* info
->nWidthBytes
;
778 sizeAnd
= info
->nHeight
* BITMAP_WIDTH_BYTES( info
->nWidth
, 1 );
779 if (lpAndBits
) *lpAndBits
= pInfo
+ sizeof(CURSORICONINFO
);
780 if (lpXorBits
) *lpXorBits
= pInfo
+ sizeof(CURSORICONINFO
) + sizeAnd
;
781 if (lpLen
) *lpLen
= sizeof(CURSORICONINFO
) + sizeAnd
+ sizeXor
;
782 return MAKELONG( sizeXor
, sizeXor
);
786 /***********************************************************************
787 * CURSORICON_SetCursor
789 * Change the X cursor. Helper function for SetCursor() and ShowCursor().
791 static BOOL32
CURSORICON_SetCursor( HCURSOR16 hCursor
)
793 Pixmap pixmapBits
, pixmapMask
, pixmapAll
;
795 Cursor cursor
= None
;
797 if (!hCursor
) /* Create an empty cursor */
799 static const char data
[] = { 0 };
801 bg
.red
= bg
.green
= bg
.blue
= 0x0000;
802 pixmapBits
= XCreateBitmapFromData( display
, rootWindow
, data
, 1, 1 );
805 cursor
= XCreatePixmapCursor( display
, pixmapBits
, pixmapBits
,
807 XFreePixmap( display
, pixmapBits
);
810 else /* Create the X cursor from the bits */
815 if (!(ptr
= (CURSORICONINFO
*)GlobalLock16( hCursor
))) return FALSE
;
816 if (ptr
->bPlanes
* ptr
->bBitsPerPixel
!= 1)
818 fprintf( stderr
, "Cursor %04x has more than 1 bpp!\n", hCursor
);
822 /* Create a pixmap and transfer all the bits to it */
824 pixmapAll
= XCreatePixmap( display
, rootWindow
,
825 ptr
->nWidth
, ptr
->nHeight
* 2, 1 );
826 image
= XCreateImage( display
, DefaultVisualOfScreen(screen
),
827 1, ZPixmap
, 0, (char *)(ptr
+ 1), ptr
->nWidth
,
828 ptr
->nHeight
* 2, 16, ptr
->nWidthBytes
);
831 extern void _XInitImageFuncPtrs( XImage
* );
832 image
->byte_order
= MSBFirst
;
833 image
->bitmap_bit_order
= MSBFirst
;
834 image
->bitmap_unit
= 16;
835 _XInitImageFuncPtrs(image
);
837 CallTo32_LargeStack( XPutImage
, 10,
838 display
, pixmapAll
, BITMAP_monoGC
, image
,
839 0, 0, 0, 0, ptr
->nWidth
, ptr
->nHeight
*2 );
841 XDestroyImage( image
);
844 /* Now create the 2 pixmaps for bits and mask */
846 pixmapBits
= XCreatePixmap( display
, rootWindow
,
847 ptr
->nWidth
, ptr
->nHeight
, 1 );
848 pixmapMask
= XCreatePixmap( display
, rootWindow
,
849 ptr
->nWidth
, ptr
->nHeight
, 1 );
851 /* Make sure everything went OK so far */
853 if (pixmapBits
&& pixmapMask
&& pixmapAll
)
855 /* We have to do some magic here, as cursors are not fully
856 * compatible between Windows and X11. Under X11, there
857 * are only 3 possible color cursor: black, white and
858 * masked. So we map the 4th Windows color (invert the
859 * bits on the screen) to black. This require some boolean
863 * Xor And Result | Bits Mask Result
864 * 0 0 black | 0 1 background
865 * 0 1 no change | X 0 no change
866 * 1 0 white | 1 1 foreground
867 * 1 1 inverted | 0 1 background
870 * Bits = 'Xor' and not 'And'
871 * Mask = 'Xor' or not 'And'
873 * FIXME: apparently some servers do support 'inverted' color.
874 * I don't know if it's correct per the X spec, but maybe
875 * we ought to take advantage of it. -- AJ
877 XCopyArea( display
, pixmapAll
, pixmapBits
, BITMAP_monoGC
,
878 0, 0, ptr
->nWidth
, ptr
->nHeight
, 0, 0 );
879 XCopyArea( display
, pixmapAll
, pixmapMask
, BITMAP_monoGC
,
880 0, 0, ptr
->nWidth
, ptr
->nHeight
, 0, 0 );
881 XSetFunction( display
, BITMAP_monoGC
, GXandReverse
);
882 XCopyArea( display
, pixmapAll
, pixmapBits
, BITMAP_monoGC
,
883 0, ptr
->nHeight
, ptr
->nWidth
, ptr
->nHeight
, 0, 0 );
884 XSetFunction( display
, BITMAP_monoGC
, GXorReverse
);
885 XCopyArea( display
, pixmapAll
, pixmapMask
, BITMAP_monoGC
,
886 0, ptr
->nHeight
, ptr
->nWidth
, ptr
->nHeight
, 0, 0 );
887 XSetFunction( display
, BITMAP_monoGC
, GXcopy
);
888 fg
.red
= fg
.green
= fg
.blue
= 0xffff;
889 bg
.red
= bg
.green
= bg
.blue
= 0x0000;
890 cursor
= XCreatePixmapCursor( display
, pixmapBits
, pixmapMask
,
891 &fg
, &bg
, ptr
->ptHotSpot
.x
, ptr
->ptHotSpot
.y
);
894 /* Now free everything */
896 if (pixmapAll
) XFreePixmap( display
, pixmapAll
);
897 if (pixmapBits
) XFreePixmap( display
, pixmapBits
);
898 if (pixmapMask
) XFreePixmap( display
, pixmapMask
);
899 GlobalUnlock16( hCursor
);
902 if (cursor
== None
) return FALSE
;
903 if (CURSORICON_XCursor
!= None
) XFreeCursor( display
, CURSORICON_XCursor
);
904 CURSORICON_XCursor
= cursor
;
906 if (rootWindow
!= DefaultRootWindow(display
))
908 /* Set the cursor on the desktop window */
909 XDefineCursor( display
, rootWindow
, cursor
);
913 /* Set the same cursor for all top-level windows */
914 HWND32 hwnd
= GetWindow32( GetDesktopWindow32(), GW_CHILD
);
917 Window win
= WIN_GetXWindow( hwnd
);
918 if (win
) XDefineCursor( display
, win
, cursor
);
919 hwnd
= GetWindow32( hwnd
, GW_HWNDNEXT
);
926 /***********************************************************************
927 * SetCursor16 (USER.69)
929 HCURSOR16
SetCursor16( HCURSOR16 hCursor
)
931 return (HCURSOR16
)SetCursor32( hCursor
);
935 /***********************************************************************
936 * SetCursor32 (USER32.471)
938 HCURSOR32
SetCursor32( HCURSOR32 hCursor
)
940 HCURSOR32 hOldCursor
;
942 if (hCursor
== hActiveCursor
) return hActiveCursor
; /* No change */
943 dprintf_cursor( stddeb
, "SetCursor: %04x\n", hCursor
);
944 hOldCursor
= hActiveCursor
;
945 hActiveCursor
= hCursor
;
946 /* Change the cursor shape only if it is visible */
947 if (CURSOR_ShowCount
>= 0) CURSORICON_SetCursor( hActiveCursor
);
952 /***********************************************************************
953 * SetCursorPos16 (USER.70)
955 void SetCursorPos16( INT16 x
, INT16 y
)
957 SetCursorPos32( x
, y
);
961 /***********************************************************************
962 * SetCursorPos32 (USER32.473)
964 BOOL32
SetCursorPos32( INT32 x
, INT32 y
)
966 dprintf_cursor( stddeb
, "SetCursorPos: x=%d y=%d\n", x
, y
);
967 XWarpPointer( display
, rootWindow
, rootWindow
, 0, 0, 0, 0, x
, y
);
972 /***********************************************************************
973 * ShowCursor16 (USER.71)
975 INT16
ShowCursor16( BOOL16 bShow
)
977 return ShowCursor32( bShow
);
981 /***********************************************************************
982 * ShowCursor32 (USER32.529)
984 INT32
ShowCursor32( BOOL32 bShow
)
986 dprintf_cursor( stddeb
, "ShowCursor: %d, count=%d\n",
987 bShow
, CURSOR_ShowCount
);
991 if (++CURSOR_ShowCount
== 0)
992 CURSORICON_SetCursor( hActiveCursor
); /* Show it */
996 if (--CURSOR_ShowCount
== -1)
997 CURSORICON_SetCursor( 0 ); /* Hide it */
999 return CURSOR_ShowCount
;
1003 /***********************************************************************
1004 * GetCursor16 (USER.247)
1006 HCURSOR16
GetCursor16(void)
1008 return hActiveCursor
;
1012 /***********************************************************************
1013 * GetCursor32 (USER32.226)
1015 HCURSOR32
GetCursor32(void)
1017 return hActiveCursor
;
1021 /***********************************************************************
1022 * ClipCursor16 (USER.16)
1024 BOOL16
ClipCursor16( const RECT16
*rect
)
1026 if (!rect
) SetRectEmpty32( &CURSOR_ClipRect
);
1027 else CONV_RECT16TO32( rect
, &CURSOR_ClipRect
);
1032 /***********************************************************************
1033 * ClipCursor32 (USER32.52)
1035 BOOL32
ClipCursor32( const RECT32
*rect
)
1037 if (!rect
) SetRectEmpty32( &CURSOR_ClipRect
);
1038 else CopyRect32( &CURSOR_ClipRect
, rect
);
1043 /***********************************************************************
1044 * GetCursorPos16 (USER.17)
1046 void GetCursorPos16( POINT16
*pt
)
1049 int rootX
, rootY
, childX
, childY
;
1050 unsigned int mousebut
;
1053 if (!XQueryPointer( display
, rootWindow
, &root
, &child
,
1054 &rootX
, &rootY
, &childX
, &childY
, &mousebut
))
1061 dprintf_cursor(stddeb
, "GetCursorPos: ret=%d,%d\n", pt
->x
, pt
->y
);
1065 /***********************************************************************
1066 * GetCursorPos32 (USER32.228)
1068 void GetCursorPos32( POINT32
*pt
)
1071 GetCursorPos16( &pt16
);
1072 if (pt
) CONV_POINT16TO32( &pt16
, pt
);
1076 /***********************************************************************
1077 * GetClipCursor16 (USER.309)
1079 void GetClipCursor16( RECT16
*rect
)
1081 if (rect
) CONV_RECT32TO16( &CURSOR_ClipRect
, rect
);
1085 /***********************************************************************
1086 * GetClipCursor32 (USER32.220)
1088 void GetClipCursor32( RECT32
*rect
)
1090 if (rect
) CopyRect32( rect
, &CURSOR_ClipRect
);
1094 /**********************************************************************
1095 * GetIconID (USER.455)
1097 WORD
GetIconID( HGLOBAL16 hResource
, DWORD resType
)
1099 CURSORICONDIR
*lpDir
= (CURSORICONDIR
*)GlobalLock16(hResource
);
1100 /* LockResource16(hResource); */
1102 if (!lpDir
|| lpDir
->idReserved
||
1103 ((lpDir
->idType
!= 1) && (lpDir
->idType
!= 2)))
1105 dprintf_cursor(stddeb
,"GetIconID: invalid resource directory\n");
1109 dprintf_cursor( stddeb
, "GetIconID: hRes=%04x, entries=%i\n",
1110 hResource
, lpDir
->idCount
);
1114 case 1: /* cursor */
1116 CURSORDIRENTRY
*entry
= CURSORICON_FindBestCursor( lpDir
,
1117 SYSMETRICS_CXCURSOR
, SYSMETRICS_CYCURSOR
);
1118 return entry
? entry
->wResId
: 0;
1122 ICONDIRENTRY
* entry
= CURSORICON_FindBestIcon( lpDir
,
1123 SYSMETRICS_CXICON
, SYSMETRICS_CYICON
,
1124 MIN( 16, COLOR_GetSystemPaletteSize() ) );
1125 return entry
? entry
->wResId
: 0;
1128 fprintf( stderr
, "GetIconID: invalid res type %ld\n", resType
);
1133 /**********************************************************************
1134 * LoadIconHandler (USER.456)
1136 HICON16
LoadIconHandler( HGLOBAL16 hResource
, BOOL16 bNew
)
1138 dprintf_cursor(stddeb
,"LoadIconHandler: hRes=%04x\n",hResource
);
1142 fprintf(stdnimp
,"LoadIconHandler: 2.xx resources are not supported\n");
1145 return CURSORICON_LoadHandler( hResource
, 0, FALSE
);