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 :-(
30 #include "cursoricon.h"
31 #include "sysmetrics.h"
37 Cursor CURSORICON_XCursor
= None
; /* Current X cursor */
38 static HCURSOR hActiveCursor
= 0; /* Active cursor */
39 static int CURSOR_ShowCount
= 0; /* Cursor display count */
40 static RECT CURSOR_ClipRect
; /* Cursor clipping rect */
42 /**********************************************************************
43 * CURSORICON_FindBestIcon
45 * Find the icon closest to the requested size and number of colors.
47 static ICONDIRENTRY
*CURSORICON_FindBestIcon( CURSORICONDIR
*dir
, int width
,
48 int height
, int colors
)
50 int i
, maxcolors
, maxwidth
, maxheight
;
51 ICONDIRENTRY
*entry
, *bestEntry
= NULL
;
55 fprintf( stderr
, "Icon: empty directory!\n" );
58 if (dir
->idCount
== 1) return &dir
->idEntries
[0].icon
; /* No choice... */
60 /* First find the exact size with less colors */
63 for (i
= 0, entry
= &dir
->idEntries
[0].icon
; i
< dir
->idCount
; i
++,entry
++)
64 if ((entry
->bWidth
== width
) && (entry
->bHeight
== height
) &&
65 (entry
->bColorCount
<= colors
) && (entry
->bColorCount
> maxcolors
))
68 maxcolors
= entry
->bColorCount
;
70 if (bestEntry
) return bestEntry
;
72 /* First find the exact size with more colors */
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
))
80 maxcolors
= entry
->bColorCount
;
82 if (bestEntry
) return bestEntry
;
84 /* Now find a smaller one with less colors */
86 maxcolors
= maxwidth
= maxheight
= 0;
87 for (i
= 0, entry
= &dir
->idEntries
[0].icon
; i
< dir
->idCount
; i
++,entry
++)
88 if ((entry
->bWidth
<= width
) && (entry
->bHeight
<= height
) &&
89 (entry
->bWidth
>= maxwidth
) && (entry
->bHeight
>= maxheight
) &&
90 (entry
->bColorCount
<= colors
) && (entry
->bColorCount
> maxcolors
))
93 maxwidth
= entry
->bWidth
;
94 maxheight
= entry
->bHeight
;
95 maxcolors
= entry
->bColorCount
;
97 if (bestEntry
) return bestEntry
;
99 /* Now find a smaller one with more colors */
102 maxwidth
= maxheight
= 0;
103 for (i
= 0, entry
= &dir
->idEntries
[0].icon
; i
< dir
->idCount
; i
++,entry
++)
104 if ((entry
->bWidth
<= width
) && (entry
->bHeight
<= height
) &&
105 (entry
->bWidth
>= maxwidth
) && (entry
->bHeight
>= maxheight
) &&
106 (entry
->bColorCount
> colors
) && (entry
->bColorCount
<= maxcolors
))
109 maxwidth
= entry
->bWidth
;
110 maxheight
= entry
->bHeight
;
111 maxcolors
= entry
->bColorCount
;
113 if (bestEntry
) return bestEntry
;
115 /* Now find a larger one with less colors */
118 maxwidth
= maxheight
= 255;
119 for (i
= 0, entry
= &dir
->idEntries
[0].icon
; i
< dir
->idCount
; i
++,entry
++)
120 if ((entry
->bWidth
<= maxwidth
) && (entry
->bHeight
<= maxheight
) &&
121 (entry
->bColorCount
<= colors
) && (entry
->bColorCount
> maxcolors
))
124 maxwidth
= entry
->bWidth
;
125 maxheight
= entry
->bHeight
;
126 maxcolors
= entry
->bColorCount
;
128 if (bestEntry
) return bestEntry
;
130 /* Now find a larger one with more colors */
132 maxcolors
= maxwidth
= maxheight
= 255;
133 for (i
= 0, entry
= &dir
->idEntries
[0].icon
; i
< dir
->idCount
; i
++,entry
++)
134 if ((entry
->bWidth
<= maxwidth
) && (entry
->bHeight
<= maxheight
) &&
135 (entry
->bColorCount
> colors
) && (entry
->bColorCount
<= maxcolors
))
138 maxwidth
= entry
->bWidth
;
139 maxheight
= entry
->bHeight
;
140 maxcolors
= entry
->bColorCount
;
147 /**********************************************************************
148 * CURSORICON_FindBestCursor
150 * Find the cursor closest to the requested size.
152 static CURSORDIRENTRY
*CURSORICON_FindBestCursor( CURSORICONDIR
*dir
,
153 int width
, int height
)
155 int i
, maxwidth
, maxheight
;
156 CURSORDIRENTRY
*entry
, *bestEntry
= NULL
;
158 if (dir
->idCount
< 1)
160 fprintf( stderr
, "Cursor: empty directory!\n" );
163 if (dir
->idCount
== 1) return &dir
->idEntries
[0].cursor
; /* No choice... */
165 /* First find the largest one smaller than or equal to the requested size*/
167 maxwidth
= maxheight
= 0;
168 for(i
= 0,entry
= &dir
->idEntries
[0].cursor
; i
< dir
->idCount
; i
++,entry
++)
169 if ((entry
->wWidth
<= width
) && (entry
->wHeight
<= height
) &&
170 (entry
->wWidth
> maxwidth
) && (entry
->wHeight
> maxheight
))
173 maxwidth
= entry
->wWidth
;
174 maxheight
= entry
->wHeight
;
176 if (bestEntry
) return bestEntry
;
178 /* Now find the smallest one larger than the requested size */
180 maxwidth
= maxheight
= 255;
181 for(i
= 0,entry
= &dir
->idEntries
[0].cursor
; i
< dir
->idCount
; i
++,entry
++)
182 if ((entry
->wWidth
< maxwidth
) && (entry
->wHeight
< maxheight
))
185 maxwidth
= entry
->wWidth
;
186 maxheight
= entry
->wHeight
;
193 /**********************************************************************
194 * CURSORICON_LoadDirEntry
196 * Load the icon/cursor directory for a given resource name and find the
197 * best matching entry.
199 static BOOL
CURSORICON_LoadDirEntry(HANDLE hInstance
, SEGPTR name
,
200 int width
, int height
, int colors
,
201 BOOL fCursor
, CURSORICONDIRENTRY
*dirEntry
)
206 CURSORICONDIRENTRY
*entry
= NULL
;
208 if (!(hRsrc
= FindResource( hInstance
, name
,
209 fCursor
? RT_GROUP_CURSOR
: RT_GROUP_ICON
)))
211 if (!(hMem
= LoadResource( hInstance
, hRsrc
))) return FALSE
;
212 if ((dir
= (CURSORICONDIR
*)LockResource( hMem
)))
215 entry
= (CURSORICONDIRENTRY
*)CURSORICON_FindBestCursor( dir
,
218 entry
= (CURSORICONDIRENTRY
*)CURSORICON_FindBestIcon( dir
,
219 width
, height
, colors
);
220 if (entry
) *dirEntry
= *entry
;
222 FreeResource( hMem
);
223 return (entry
!= NULL
);
227 /**********************************************************************
230 * Load a cursor or icon.
232 static HANDLE
CURSORICON_Load( HANDLE hInstance
, SEGPTR name
, int width
,
233 int height
, int colors
, BOOL fCursor
)
235 HANDLE handle
, hAndBits
, hXorBits
;
238 int size
, sizeAnd
, sizeXor
;
239 POINT hotspot
= { 0 ,0 };
240 BITMAPOBJ
*bmpXor
, *bmpAnd
;
241 BITMAPINFO
*bmi
, *pInfo
;
242 CURSORICONINFO
*info
;
243 CURSORICONDIRENTRY dirEntry
;
246 if (!hInstance
) /* OEM cursor/icon */
248 if (HIWORD(name
)) /* Check for '#xxx' name */
250 char *ptr
= PTR_SEG_TO_LIN( name
);
251 if (ptr
[0] != '#') return 0;
252 if (!(name
= (SEGPTR
)atoi( ptr
+ 1 ))) return 0;
254 return OBM_LoadCursorIcon( LOWORD(name
), fCursor
);
257 /* Find the best entry in the directory */
259 if (!CURSORICON_LoadDirEntry( hInstance
, name
, width
, height
,
260 colors
, fCursor
, &dirEntry
)) return 0;
262 /* Load the resource */
264 if (!(hRsrc
= FindResource( hInstance
,
265 MAKEINTRESOURCE( dirEntry
.icon
.wResId
),
266 fCursor
? RT_CURSOR
: RT_ICON
))) return 0;
267 if (!(handle
= LoadResource( hInstance
, hRsrc
))) return 0;
269 if (fCursor
) /* If cursor, get the hotspot */
271 POINT
*pt
= (POINT
*)LockResource( handle
);
273 bmi
= (BITMAPINFO
*)(pt
+ 1);
275 else bmi
= (BITMAPINFO
*)LockResource( handle
);
277 /* Create a copy of the bitmap header */
279 size
= DIB_BitmapInfoSize( bmi
, DIB_RGB_COLORS
);
280 /* Make sure we have room for the monochrome bitmap later on */
281 size
= max( size
, sizeof(BITMAPINFOHEADER
) + 2*sizeof(RGBQUAD
) );
282 pInfo
= (BITMAPINFO
*)malloc( size
);
283 memcpy( pInfo
, bmi
, size
);
285 if (pInfo
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
))
287 if (pInfo
->bmiHeader
.biCompression
!= BI_RGB
)
289 fprintf(stderr
,"Unknown size for compressed icon bitmap.\n");
290 FreeResource( handle
);
294 pInfo
->bmiHeader
.biHeight
/= 2;
296 else if (pInfo
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
298 BITMAPCOREHEADER
*core
= (BITMAPCOREHEADER
*)pInfo
;
303 fprintf( stderr
, "CURSORICON_Load: Unknown bitmap length %ld!\n",
304 pInfo
->bmiHeader
.biSize
);
305 FreeResource( handle
);
310 /* Create the XOR bitmap */
312 if (!(hdc
= GetDC( 0 )))
314 FreeResource( handle
);
319 hXorBits
= CreateDIBitmap( hdc
, &pInfo
->bmiHeader
, CBM_INIT
,
320 (char*)bmi
+ size
, pInfo
, DIB_RGB_COLORS
);
322 /* Fix the bitmap header to load the monochrome mask */
324 if (pInfo
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
))
326 BITMAPINFOHEADER
*bih
= &pInfo
->bmiHeader
;
327 RGBQUAD
*rgb
= pInfo
->bmiColors
;
328 bits
= (char *)bmi
+ size
+
329 DIB_GetImageWidthBytes(bih
->biWidth
,bih
->biBitCount
)*bih
->biHeight
;
331 bih
->biClrUsed
= bih
->biClrImportant
= 2;
332 rgb
[0].rgbBlue
= rgb
[0].rgbGreen
= rgb
[0].rgbRed
= 0x00;
333 rgb
[1].rgbBlue
= rgb
[1].rgbGreen
= rgb
[1].rgbRed
= 0xff;
334 rgb
[0].rgbReserved
= rgb
[1].rgbReserved
= 0;
338 BITMAPCOREHEADER
*bch
= (BITMAPCOREHEADER
*)pInfo
;
339 RGBTRIPLE
*rgb
= (RGBTRIPLE
*)(bch
+ 1);
340 bits
= (char *)bmi
+ size
+
341 DIB_GetImageWidthBytes(bch
->bcWidth
,bch
->bcBitCount
)*bch
->bcHeight
;
343 rgb
[0].rgbtBlue
= rgb
[0].rgbtGreen
= rgb
[0].rgbtRed
= 0x00;
344 rgb
[1].rgbtBlue
= rgb
[1].rgbtGreen
= rgb
[1].rgbtRed
= 0xff;
347 /* Create the AND bitmap */
349 hAndBits
= CreateDIBitmap( hdc
, &pInfo
->bmiHeader
, CBM_INIT
,
350 bits
, pInfo
, DIB_RGB_COLORS
);
352 FreeResource( handle
);
354 /* Now create the CURSORICONINFO structure */
356 bmpXor
= (BITMAPOBJ
*) GDI_GetObjPtr( hXorBits
, BITMAP_MAGIC
);
357 bmpAnd
= (BITMAPOBJ
*) GDI_GetObjPtr( hAndBits
, BITMAP_MAGIC
);
358 sizeXor
= bmpXor
->bitmap
.bmHeight
* bmpXor
->bitmap
.bmWidthBytes
;
359 sizeAnd
= bmpAnd
->bitmap
.bmHeight
* bmpAnd
->bitmap
.bmWidthBytes
;
361 if (!(handle
= GlobalAlloc( GMEM_MOVEABLE
,
362 sizeof(CURSORICONINFO
) + sizeXor
+ sizeAnd
)))
364 DeleteObject( hXorBits
);
365 DeleteObject( hAndBits
);
368 /* Make it owned by the module */
369 FarSetOwner( handle
, GetExePtr( hInstance
) );
370 info
= (CURSORICONINFO
*)GlobalLock( handle
);
371 info
->ptHotSpot
.x
= hotspot
.x
;
372 info
->ptHotSpot
.y
= hotspot
.y
;
373 info
->nWidth
= bmpXor
->bitmap
.bmWidth
;
374 info
->nHeight
= bmpXor
->bitmap
.bmHeight
;
375 info
->nWidthBytes
= bmpXor
->bitmap
.bmWidthBytes
;
376 info
->bPlanes
= bmpXor
->bitmap
.bmPlanes
;
377 info
->bBitsPerPixel
= bmpXor
->bitmap
.bmBitsPixel
;
379 /* Transfer the bitmap bits to the CURSORICONINFO structure */
381 GetBitmapBits( hAndBits
, sizeAnd
, (char *)(info
+ 1) );
382 GetBitmapBits( hXorBits
, sizeXor
, (char *)(info
+ 1) + sizeAnd
);
383 DeleteObject( hXorBits
);
384 DeleteObject( hAndBits
);
385 GlobalUnlock( handle
);
390 /***********************************************************************
393 * Make a copy of a cursor or icon.
395 static HANDLE
CURSORICON_Copy( HANDLE hInstance
, HANDLE handle
)
397 char *ptrOld
, *ptrNew
;
401 if (!(ptrOld
= (char *)GlobalLock( handle
))) return 0;
402 if (!(hInstance
= GetExePtr( hInstance
))) return 0;
403 size
= GlobalSize( handle
);
404 hNew
= GlobalAlloc( GMEM_MOVEABLE
, size
);
405 FarSetOwner( hNew
, hInstance
);
406 ptrNew
= (char *)GlobalLock( hNew
);
407 memcpy( ptrNew
, ptrOld
, size
);
408 GlobalUnlock( handle
);
409 GlobalUnlock( hNew
);
414 /***********************************************************************
415 * LoadCursor (USER.173)
417 HCURSOR
LoadCursor( HANDLE hInstance
, SEGPTR name
)
420 dprintf_cursor( stddeb
, "LoadCursor: "NPFMT
" '%s'\n",
421 hInstance
, (char *)PTR_SEG_TO_LIN( name
) );
423 dprintf_cursor( stddeb
, "LoadCursor: "NPFMT
" %04x\n",
424 hInstance
, LOWORD(name
) );
426 return CURSORICON_Load( hInstance
, name
,
427 SYSMETRICS_CXCURSOR
, SYSMETRICS_CYCURSOR
, 1, TRUE
);
431 /***********************************************************************
432 * LoadIcon (USER.174)
434 HICON
LoadIcon( HANDLE hInstance
, SEGPTR name
)
437 dprintf_icon( stddeb
, "LoadIcon: "NPFMT
" '%s'\n",
438 hInstance
, (char *)PTR_SEG_TO_LIN( name
) );
440 dprintf_icon( stddeb
, "LoadIcon: "NPFMT
" %04x\n",
441 hInstance
, LOWORD(name
) );
443 return CURSORICON_Load( hInstance
, name
,
444 SYSMETRICS_CXICON
, SYSMETRICS_CYICON
,
445 min( 16, 1 << screenDepth
), FALSE
);
449 /***********************************************************************
450 * CreateCursor (USER.406)
452 HICON
CreateCursor( HANDLE hInstance
, INT xHotSpot
, INT yHotSpot
,
453 INT nWidth
, INT nHeight
, LPSTR lpANDbits
, LPSTR lpXORbits
)
455 CURSORICONINFO info
= { { xHotSpot
, yHotSpot
}, nWidth
, nHeight
, 1, 1 };
457 dprintf_cursor( stddeb
, "CreateCursor: %dx%d spot=%d,%d xor=%p and=%p\n",
458 nWidth
, nHeight
, xHotSpot
, yHotSpot
, lpXORbits
, lpANDbits
);
459 return CreateCursorIconIndirect( hInstance
, &info
, lpANDbits
, lpXORbits
);
463 /***********************************************************************
464 * CreateIcon (USER.407)
466 HICON
CreateIcon( HANDLE hInstance
, INT nWidth
, INT nHeight
, BYTE bPlanes
,
467 BYTE bBitsPixel
, LPSTR lpANDbits
, LPSTR lpXORbits
)
469 CURSORICONINFO info
= { { 0, 0 }, nWidth
, nHeight
, bPlanes
, bBitsPixel
};
471 dprintf_icon( stddeb
, "CreateIcon: %dx%dx%d, xor=%p, and=%p\n",
472 nWidth
, nHeight
, bPlanes
* bBitsPixel
, lpXORbits
, lpANDbits
);
473 return CreateCursorIconIndirect( hInstance
, &info
, lpANDbits
, lpXORbits
);
477 /***********************************************************************
478 * CreateCursorIconIndirect (USER.408)
480 HANDLE
CreateCursorIconIndirect( HANDLE hInstance
, CURSORICONINFO
*info
,
481 LPSTR lpANDbits
, LPSTR lpXORbits
)
485 int sizeAnd
, sizeXor
;
487 hInstance
= GetExePtr( hInstance
); /* Make it a module handle */
488 if (!hInstance
|| !lpXORbits
|| !lpANDbits
|| info
->bPlanes
!= 1) return 0;
489 info
->nWidthBytes
= (info
->nWidth
* info
->bBitsPerPixel
+ 15) / 16 * 2;
490 sizeXor
= info
->nHeight
* info
->nWidthBytes
;
491 sizeAnd
= info
->nHeight
* ((info
->nWidth
+ 15) / 16 * 2);
492 if (!(handle
= DirectResAlloc(hInstance
, 0x10,
493 sizeof(CURSORICONINFO
) + sizeXor
+ sizeAnd
)))
495 ptr
= (char *)GlobalLock( handle
);
496 memcpy( ptr
, info
, sizeof(*info
) );
497 memcpy( ptr
+ sizeof(CURSORICONINFO
), lpANDbits
, sizeAnd
);
498 memcpy( ptr
+ sizeof(CURSORICONINFO
) + sizeAnd
, lpXORbits
, sizeXor
);
499 GlobalUnlock( handle
);
504 /***********************************************************************
505 * CopyIcon (USER.368)
507 HICON
CopyIcon( HANDLE hInstance
, HICON hIcon
)
509 dprintf_icon( stddeb
, "CopyIcon: %04x %04x\n", hInstance
, hIcon
);
510 return CURSORICON_Copy( hInstance
, hIcon
);
514 /***********************************************************************
515 * CopyCursor (USER.369)
517 HCURSOR
CopyCursor( HANDLE hInstance
, HCURSOR hCursor
)
519 dprintf_cursor( stddeb
, "CopyCursor: %04x %04x\n", hInstance
, hCursor
);
520 return CURSORICON_Copy( hInstance
, hCursor
);
524 /***********************************************************************
525 * DestroyIcon (USER.457)
527 BOOL
DestroyIcon( HICON hIcon
)
529 dprintf_icon( stddeb
, "DestroyIcon: %04x\n", hIcon
);
530 return GlobalFree( hIcon
);
534 /***********************************************************************
535 * DestroyCursor (USER.458)
537 BOOL
DestroyCursor( HCURSOR hCursor
)
539 dprintf_cursor( stddeb
, "DestroyCursor: %04x\n", hCursor
);
540 return GlobalFree( hCursor
);
544 /***********************************************************************
547 BOOL
DrawIcon( HDC hdc
, short x
, short y
, HICON hIcon
)
551 HBITMAP hXorBits
, hAndBits
;
552 COLORREF oldFg
, oldBg
;
554 if (!(ptr
= (CURSORICONINFO
*)GlobalLock( hIcon
))) return FALSE
;
555 if (!(hMemDC
= CreateCompatibleDC( hdc
))) return FALSE
;
556 hAndBits
= CreateBitmap( ptr
->nWidth
, ptr
->nHeight
, 1, 1, (char *)(ptr
+1));
557 hXorBits
= CreateBitmap( ptr
->nWidth
, ptr
->nHeight
, ptr
->bPlanes
,
558 ptr
->bBitsPerPixel
, (char *)(ptr
+ 1)
559 + ptr
->nHeight
* ((ptr
->nWidth
+ 15) / 16 * 2) );
560 oldFg
= SetTextColor( hdc
, RGB(0,0,0) );
561 oldBg
= SetBkColor( hdc
, RGB(255,255,255) );
563 if (hXorBits
&& hAndBits
)
565 HBITMAP hBitTemp
= SelectObject( hMemDC
, hAndBits
);
566 BitBlt( hdc
, x
, y
, ptr
->nWidth
, ptr
->nHeight
, hMemDC
, 0, 0, SRCAND
);
567 SelectObject( hMemDC
, hXorBits
);
568 BitBlt( hdc
, x
, y
, ptr
->nWidth
, ptr
->nHeight
, hMemDC
, 0, 0, SRCINVERT
);
569 SelectObject( hMemDC
, hBitTemp
);
572 if (hXorBits
) DeleteObject( hXorBits
);
573 if (hAndBits
) DeleteObject( hAndBits
);
574 GlobalUnlock( hIcon
);
575 SetTextColor( hdc
, oldFg
);
576 SetBkColor( hdc
, oldBg
);
581 /***********************************************************************
582 * DumpIcon (USER.459)
584 DWORD
DumpIcon( CURSORICONINFO
*info
, WORD
*lpLen
,
585 LPSTR
*lpXorBits
, LPSTR
*lpAndBits
)
587 int sizeAnd
, sizeXor
;
590 sizeXor
= info
->nHeight
* info
->nWidthBytes
;
591 sizeAnd
= info
->nHeight
* ((info
->nWidth
+ 15) / 16 * 2);
592 if (lpAndBits
) *lpAndBits
= (LPSTR
)(info
+ 1);
593 if (lpXorBits
) *lpXorBits
= (LPSTR
)(info
+ 1) + sizeAnd
;
594 if (lpLen
) *lpLen
= sizeof(CURSORICONINFO
) + sizeAnd
+ sizeXor
;
595 return MAKELONG( sizeXor
, sizeXor
);
599 /***********************************************************************
600 * CURSORICON_SetCursor
602 * Change the X cursor. Helper function for SetCursor() and ShowCursor().
604 static BOOL
CURSORICON_SetCursor( HCURSOR hCursor
)
606 Pixmap pixmapBits
, pixmapMask
, pixmapAll
;
608 Cursor cursor
= None
;
610 if (!hCursor
) /* Create an empty cursor */
612 static const char data
[] = { 0 };
614 bg
.red
= bg
.green
= bg
.blue
= 0x0000;
615 pixmapBits
= XCreateBitmapFromData( display
, rootWindow
, data
, 1, 1 );
618 cursor
= XCreatePixmapCursor( display
, pixmapBits
, pixmapBits
,
620 XFreePixmap( display
, pixmapBits
);
623 else /* Create the X cursor from the bits */
628 if (!(ptr
= (CURSORICONINFO
*)GlobalLock( hCursor
))) return FALSE
;
629 if (ptr
->bPlanes
* ptr
->bBitsPerPixel
!= 1)
631 fprintf( stderr
, "Cursor %04x has more than 1 bpp!\n", hCursor
);
635 /* Create a pixmap and transfer all the bits to it */
637 pixmapAll
= XCreatePixmap( display
, rootWindow
,
638 ptr
->nWidth
, ptr
->nHeight
* 2, 1 );
639 image
= XCreateImage( display
, DefaultVisualOfScreen(screen
),
640 1, ZPixmap
, 0, (char *)(ptr
+ 1), ptr
->nWidth
,
641 ptr
->nHeight
* 2, 16, ptr
->nWidthBytes
);
644 extern void _XInitImageFuncPtrs( XImage
* );
645 image
->byte_order
= MSBFirst
;
646 image
->bitmap_bit_order
= MSBFirst
;
647 image
->bitmap_unit
= 16;
648 _XInitImageFuncPtrs(image
);
650 CallTo32_LargeStack( XPutImage
, 10,
651 display
, pixmapAll
, BITMAP_monoGC
, image
,
652 0, 0, 0, 0, ptr
->nWidth
, ptr
->nHeight
*2 );
654 XDestroyImage( image
);
657 /* Now create the 2 pixmaps for bits and mask */
659 pixmapBits
= XCreatePixmap( display
, rootWindow
,
660 ptr
->nWidth
, ptr
->nHeight
, 1 );
661 pixmapMask
= XCreatePixmap( display
, rootWindow
,
662 ptr
->nWidth
, ptr
->nHeight
, 1 );
664 /* Make sure everything went OK so far */
666 if (pixmapBits
&& pixmapMask
&& pixmapAll
)
668 /* We have to do some magic here, as cursors are not fully
669 * compatible between Windows and X11. Under X11, there
670 * are only 3 possible color cursor: black, white and
671 * masked. So we map the 4th Windows color (invert the
672 * bits on the screen) to black. This require some boolean
676 * Xor And Result Bits Mask
680 * 1 1 inverted 0 1 (=black)
683 * Bits = 'Xor' xor 'And'
684 * Mask = 'Xor' or not 'And'
686 XCopyArea( display
, pixmapAll
, pixmapBits
, BITMAP_monoGC
,
687 0, 0, ptr
->nWidth
, ptr
->nHeight
, 0, 0 );
688 XCopyArea( display
, pixmapAll
, pixmapMask
, BITMAP_monoGC
,
689 0, 0, ptr
->nWidth
, ptr
->nHeight
, 0, 0 );
690 XSetFunction( display
, BITMAP_monoGC
, GXxor
);
691 XCopyArea( display
, pixmapAll
, pixmapBits
, BITMAP_monoGC
,
692 0, ptr
->nHeight
, ptr
->nWidth
, ptr
->nHeight
, 0, 0 );
693 XSetFunction( display
, BITMAP_monoGC
, GXorReverse
);
694 XCopyArea( display
, pixmapAll
, pixmapMask
, BITMAP_monoGC
,
695 0, ptr
->nHeight
, ptr
->nWidth
, ptr
->nHeight
, 0, 0 );
696 XSetFunction( display
, BITMAP_monoGC
, GXcopy
);
697 fg
.red
= fg
.green
= fg
.blue
= 0xffff;
698 bg
.red
= bg
.green
= bg
.blue
= 0x0000;
699 cursor
= XCreatePixmapCursor( display
, pixmapBits
, pixmapMask
,
700 &fg
, &bg
, ptr
->ptHotSpot
.x
, ptr
->ptHotSpot
.y
);
703 /* Now free everything */
705 if (pixmapAll
) XFreePixmap( display
, pixmapAll
);
706 if (pixmapBits
) XFreePixmap( display
, pixmapBits
);
707 if (pixmapMask
) XFreePixmap( display
, pixmapMask
);
708 GlobalUnlock( hCursor
);
711 if (cursor
== None
) return FALSE
;
712 if (CURSORICON_XCursor
!= None
) XFreeCursor( display
, CURSORICON_XCursor
);
713 CURSORICON_XCursor
= cursor
;
715 if (rootWindow
!= DefaultRootWindow(display
))
717 /* Set the cursor on the desktop window */
718 XDefineCursor( display
, rootWindow
, cursor
);
722 /* Set the same cursor for all top-level windows */
723 HWND hwnd
= GetWindow( GetDesktopWindow(), GW_CHILD
);
726 Window win
= WIN_GetXWindow( hwnd
);
727 if (win
) XDefineCursor( display
, win
, cursor
);
728 hwnd
= GetWindow( hwnd
, GW_HWNDNEXT
);
735 /***********************************************************************
736 * SetCursor (USER.69)
738 HCURSOR
SetCursor( HCURSOR hCursor
)
742 if (hCursor
== hActiveCursor
) return hActiveCursor
; /* No change */
743 dprintf_cursor( stddeb
, "SetCursor: %04x\n", hCursor
);
744 hOldCursor
= hActiveCursor
;
745 hActiveCursor
= hCursor
;
746 /* Change the cursor shape only if it is visible */
747 if (CURSOR_ShowCount
>= 0) CURSORICON_SetCursor( hActiveCursor
);
752 /***********************************************************************
753 * SetCursorPos (USER.70)
755 void SetCursorPos( short x
, short y
)
757 dprintf_cursor( stddeb
, "SetCursorPos: x=%d y=%d\n", x
, y
);
758 XWarpPointer( display
, None
, rootWindow
, 0, 0, 0, 0, x
, y
);
762 /***********************************************************************
763 * ShowCursor (USER.71)
765 int ShowCursor( BOOL bShow
)
767 dprintf_cursor( stddeb
, "ShowCursor: %d, count=%d\n",
768 bShow
, CURSOR_ShowCount
);
772 if (++CURSOR_ShowCount
== 0)
773 CURSORICON_SetCursor( hActiveCursor
); /* Show it */
777 if (--CURSOR_ShowCount
== -1)
778 CURSORICON_SetCursor( 0 ); /* Hide it */
780 return CURSOR_ShowCount
;
784 /***********************************************************************
785 * GetCursor (USER.247)
787 HCURSOR
GetCursor(void)
789 return hActiveCursor
;
793 /***********************************************************************
794 * ClipCursor (USER.16)
796 void ClipCursor( RECT
*rect
)
798 if (!rect
) SetRectEmpty( &CURSOR_ClipRect
);
799 else CopyRect( &CURSOR_ClipRect
, rect
);
803 /***********************************************************************
804 * GetCursorPos (USER.17)
806 void GetCursorPos( POINT
*pt
)
809 int rootX
, rootY
, childX
, childY
;
810 unsigned int mousebut
;
813 if (!XQueryPointer( display
, rootWindow
, &root
, &child
,
814 &rootX
, &rootY
, &childX
, &childY
, &mousebut
))
818 pt
->x
= rootX
+ desktopX
;
819 pt
->y
= rootY
+ desktopY
;
821 dprintf_cursor(stddeb
, "GetCursorPos: ret=%d,%d\n", pt
->x
, pt
->y
);
825 /***********************************************************************
826 * GetClipCursor (USER.309)
828 void GetClipCursor( RECT
*rect
)
830 if (rect
) CopyRect( rect
, &CURSOR_ClipRect
);
834 /**********************************************************************
835 * GetIconID (USER.455)
837 WORD
GetIconID( HANDLE hResource
, DWORD resType
)
839 fprintf( stderr
, "GetIconId(%04x,%ld): empty stub!\n",
840 hResource
, resType
);
845 /**********************************************************************
846 * LoadIconHandler (USER.456)
848 HICON
LoadIconHandler( HANDLE hResource
, BOOL bNew
)
850 fprintf( stderr
, "LoadIconHandle(%04x,%d): empty stub!\n",