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"
38 extern UINT16
COLOR_GetSystemPaletteSize();
40 Cursor CURSORICON_XCursor
= None
; /* Current X cursor */
41 static HCURSOR hActiveCursor
= 0; /* Active cursor */
42 static int CURSOR_ShowCount
= 0; /* Cursor display count */
43 static RECT32 CURSOR_ClipRect
; /* Cursor clipping rect */
45 /**********************************************************************
46 * CURSORICON_FindBestIcon
48 * Find the icon closest to the requested size and number of colors.
50 static ICONDIRENTRY
*CURSORICON_FindBestIcon( CURSORICONDIR
*dir
, int width
,
51 int height
, int colors
)
53 int i
, maxcolors
, maxwidth
, maxheight
;
54 ICONDIRENTRY
*entry
, *bestEntry
= NULL
;
58 fprintf( stderr
, "Icon: empty directory!\n" );
61 if (dir
->idCount
== 1) return &dir
->idEntries
[0].icon
; /* No choice... */
63 /* First find the exact size with less colors */
66 for (i
= 0, entry
= &dir
->idEntries
[0].icon
; i
< dir
->idCount
; i
++,entry
++)
67 if ((entry
->bWidth
== width
) && (entry
->bHeight
== height
) &&
68 (entry
->bColorCount
<= colors
) && (entry
->bColorCount
> maxcolors
))
71 maxcolors
= entry
->bColorCount
;
73 if (bestEntry
) return bestEntry
;
75 /* First find the exact size with more colors */
78 for (i
= 0, entry
= &dir
->idEntries
[0].icon
; i
< dir
->idCount
; i
++,entry
++)
79 if ((entry
->bWidth
== width
) && (entry
->bHeight
== height
) &&
80 (entry
->bColorCount
> colors
) && (entry
->bColorCount
<= maxcolors
))
83 maxcolors
= entry
->bColorCount
;
85 if (bestEntry
) return bestEntry
;
87 /* Now find a smaller one with less colors */
89 maxcolors
= maxwidth
= maxheight
= 0;
90 for (i
= 0, entry
= &dir
->idEntries
[0].icon
; i
< dir
->idCount
; i
++,entry
++)
91 if ((entry
->bWidth
<= width
) && (entry
->bHeight
<= height
) &&
92 (entry
->bWidth
>= maxwidth
) && (entry
->bHeight
>= maxheight
) &&
93 (entry
->bColorCount
<= colors
) && (entry
->bColorCount
> maxcolors
))
96 maxwidth
= entry
->bWidth
;
97 maxheight
= entry
->bHeight
;
98 maxcolors
= entry
->bColorCount
;
100 if (bestEntry
) return bestEntry
;
102 /* Now find a smaller one with more colors */
105 maxwidth
= maxheight
= 0;
106 for (i
= 0, entry
= &dir
->idEntries
[0].icon
; i
< dir
->idCount
; i
++,entry
++)
107 if ((entry
->bWidth
<= width
) && (entry
->bHeight
<= height
) &&
108 (entry
->bWidth
>= maxwidth
) && (entry
->bHeight
>= maxheight
) &&
109 (entry
->bColorCount
> colors
) && (entry
->bColorCount
<= maxcolors
))
112 maxwidth
= entry
->bWidth
;
113 maxheight
= entry
->bHeight
;
114 maxcolors
= entry
->bColorCount
;
116 if (bestEntry
) return bestEntry
;
118 /* Now find a larger one with less colors */
121 maxwidth
= maxheight
= 255;
122 for (i
= 0, entry
= &dir
->idEntries
[0].icon
; i
< dir
->idCount
; i
++,entry
++)
123 if ((entry
->bWidth
<= maxwidth
) && (entry
->bHeight
<= maxheight
) &&
124 (entry
->bColorCount
<= colors
) && (entry
->bColorCount
> maxcolors
))
127 maxwidth
= entry
->bWidth
;
128 maxheight
= entry
->bHeight
;
129 maxcolors
= entry
->bColorCount
;
131 if (bestEntry
) return bestEntry
;
133 /* Now find a larger one with more colors */
135 maxcolors
= maxwidth
= maxheight
= 255;
136 for (i
= 0, entry
= &dir
->idEntries
[0].icon
; i
< dir
->idCount
; i
++,entry
++)
137 if ((entry
->bWidth
<= maxwidth
) && (entry
->bHeight
<= maxheight
) &&
138 (entry
->bColorCount
> colors
) && (entry
->bColorCount
<= maxcolors
))
141 maxwidth
= entry
->bWidth
;
142 maxheight
= entry
->bHeight
;
143 maxcolors
= entry
->bColorCount
;
150 /**********************************************************************
151 * CURSORICON_FindBestCursor
153 * Find the cursor closest to the requested size.
155 static CURSORDIRENTRY
*CURSORICON_FindBestCursor( CURSORICONDIR
*dir
,
156 int width
, int height
)
158 int i
, maxwidth
, maxheight
;
159 CURSORDIRENTRY
*entry
, *bestEntry
= NULL
;
161 if (dir
->idCount
< 1)
163 fprintf( stderr
, "Cursor: empty directory!\n" );
166 if (dir
->idCount
== 1) return &dir
->idEntries
[0].cursor
; /* No choice... */
168 /* First find the largest one smaller than or equal to the requested size*/
170 maxwidth
= maxheight
= 0;
171 for(i
= 0,entry
= &dir
->idEntries
[0].cursor
; i
< dir
->idCount
; i
++,entry
++)
172 if ((entry
->wWidth
<= width
) && (entry
->wHeight
<= height
) &&
173 (entry
->wWidth
> maxwidth
) && (entry
->wHeight
> maxheight
))
176 maxwidth
= entry
->wWidth
;
177 maxheight
= entry
->wHeight
;
179 if (bestEntry
) return bestEntry
;
181 /* Now find the smallest one larger than the requested size */
183 maxwidth
= maxheight
= 255;
184 for(i
= 0,entry
= &dir
->idEntries
[0].cursor
; i
< dir
->idCount
; i
++,entry
++)
185 if ((entry
->wWidth
< maxwidth
) && (entry
->wHeight
< maxheight
))
188 maxwidth
= entry
->wWidth
;
189 maxheight
= entry
->wHeight
;
196 /**********************************************************************
197 * CURSORICON_LoadDirEntry
199 * Load the icon/cursor directory for a given resource name and find the
200 * best matching entry.
202 static BOOL
CURSORICON_LoadDirEntry(HINSTANCE32 hInstance
, SEGPTR name
,
203 int width
, int height
, int colors
,
204 BOOL fCursor
, CURSORICONDIRENTRY
*dirEntry
)
209 CURSORICONDIRENTRY
*entry
= NULL
;
211 if (!(hRsrc
= FindResource16( hInstance
, name
,
212 fCursor
? RT_GROUP_CURSOR
: RT_GROUP_ICON
)))
214 if (!(hMem
= LoadResource16( hInstance
, hRsrc
))) return FALSE
;
215 if ((dir
= (CURSORICONDIR
*)LockResource16( hMem
)))
218 entry
= (CURSORICONDIRENTRY
*)CURSORICON_FindBestCursor( dir
,
221 entry
= (CURSORICONDIRENTRY
*)CURSORICON_FindBestIcon( dir
,
222 width
, height
, colors
);
223 if (entry
) *dirEntry
= *entry
;
225 FreeResource16( hMem
);
226 return (entry
!= NULL
);
230 /**********************************************************************
231 * CURSORICON_LoadHandler
233 * Create a cursor or icon from a resource.
235 HANDLE
CURSORICON_LoadHandler( HANDLE handle
, HINSTANCE hInstance
,
238 HANDLE hAndBits
, hXorBits
;
240 int size
, sizeAnd
, sizeXor
;
241 POINT16 hotspot
= { 0 ,0 };
242 BITMAPOBJ
*bmpXor
, *bmpAnd
;
243 BITMAPINFO
*bmi
, *pInfo
;
244 CURSORICONINFO
*info
;
247 if (fCursor
) /* If cursor, get the hotspot */
249 POINT16
*pt
= (POINT16
*)LockResource16( handle
);
251 bmi
= (BITMAPINFO
*)(pt
+ 1);
253 else bmi
= (BITMAPINFO
*)LockResource16( handle
);
255 /* Create a copy of the bitmap header */
257 size
= DIB_BitmapInfoSize( bmi
, DIB_RGB_COLORS
);
258 /* Make sure we have room for the monochrome bitmap later on */
259 size
= MAX( size
, sizeof(BITMAPINFOHEADER
) + 2*sizeof(RGBQUAD
) );
260 pInfo
= (BITMAPINFO
*)xmalloc( size
);
261 memcpy( pInfo
, bmi
, size
);
263 if (pInfo
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
))
265 if (pInfo
->bmiHeader
.biCompression
!= BI_RGB
)
267 fprintf(stderr
,"Unknown size for compressed icon bitmap.\n");
271 pInfo
->bmiHeader
.biHeight
/= 2;
273 else if (pInfo
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
275 BITMAPCOREHEADER
*core
= (BITMAPCOREHEADER
*)pInfo
;
280 fprintf( stderr
, "CURSORICON_Load: Unknown bitmap length %ld!\n",
281 pInfo
->bmiHeader
.biSize
);
286 /* Create the XOR bitmap */
288 if (!(hdc
= GetDC( 0 )))
294 hXorBits
= CreateDIBitmap( hdc
, &pInfo
->bmiHeader
, CBM_INIT
,
295 (char*)bmi
+ size
, pInfo
, DIB_RGB_COLORS
);
297 /* Fix the bitmap header to load the monochrome mask */
299 if (pInfo
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
))
301 BITMAPINFOHEADER
*bih
= &pInfo
->bmiHeader
;
302 RGBQUAD
*rgb
= pInfo
->bmiColors
;
303 bits
= (char *)bmi
+ size
+
304 DIB_GetImageWidthBytes(bih
->biWidth
,bih
->biBitCount
)*bih
->biHeight
;
306 bih
->biClrUsed
= bih
->biClrImportant
= 2;
307 rgb
[0].rgbBlue
= rgb
[0].rgbGreen
= rgb
[0].rgbRed
= 0x00;
308 rgb
[1].rgbBlue
= rgb
[1].rgbGreen
= rgb
[1].rgbRed
= 0xff;
309 rgb
[0].rgbReserved
= rgb
[1].rgbReserved
= 0;
313 BITMAPCOREHEADER
*bch
= (BITMAPCOREHEADER
*)pInfo
;
314 RGBTRIPLE
*rgb
= (RGBTRIPLE
*)(bch
+ 1);
315 bits
= (char *)bmi
+ size
+
316 DIB_GetImageWidthBytes(bch
->bcWidth
,bch
->bcBitCount
)*bch
->bcHeight
;
318 rgb
[0].rgbtBlue
= rgb
[0].rgbtGreen
= rgb
[0].rgbtRed
= 0x00;
319 rgb
[1].rgbtBlue
= rgb
[1].rgbtGreen
= rgb
[1].rgbtRed
= 0xff;
322 /* Create the AND bitmap */
324 hAndBits
= CreateDIBitmap( hdc
, &pInfo
->bmiHeader
, CBM_INIT
,
325 bits
, pInfo
, DIB_RGB_COLORS
);
328 /* Now create the CURSORICONINFO structure */
330 bmpXor
= (BITMAPOBJ
*) GDI_GetObjPtr( hXorBits
, BITMAP_MAGIC
);
331 bmpAnd
= (BITMAPOBJ
*) GDI_GetObjPtr( hAndBits
, BITMAP_MAGIC
);
332 sizeXor
= bmpXor
->bitmap
.bmHeight
* bmpXor
->bitmap
.bmWidthBytes
;
333 sizeAnd
= bmpAnd
->bitmap
.bmHeight
* bmpAnd
->bitmap
.bmWidthBytes
;
335 if (!(handle
= GlobalAlloc16( GMEM_MOVEABLE
,
336 sizeof(CURSORICONINFO
) + sizeXor
+ sizeAnd
)))
338 DeleteObject( hXorBits
);
339 DeleteObject( hAndBits
);
343 /* Make it owned by the module */
344 if (hInstance
) FarSetOwner( handle
, GetExePtr(hInstance
) );
346 info
= (CURSORICONINFO
*)GlobalLock16( handle
);
347 info
->ptHotSpot
.x
= hotspot
.x
;
348 info
->ptHotSpot
.y
= hotspot
.y
;
349 info
->nWidth
= bmpXor
->bitmap
.bmWidth
;
350 info
->nHeight
= bmpXor
->bitmap
.bmHeight
;
351 info
->nWidthBytes
= bmpXor
->bitmap
.bmWidthBytes
;
352 info
->bPlanes
= bmpXor
->bitmap
.bmPlanes
;
353 info
->bBitsPerPixel
= bmpXor
->bitmap
.bmBitsPixel
;
355 /* Transfer the bitmap bits to the CURSORICONINFO structure */
357 GetBitmapBits( hAndBits
, sizeAnd
, (char *)(info
+ 1) );
358 GetBitmapBits( hXorBits
, sizeXor
, (char *)(info
+ 1) + sizeAnd
);
359 DeleteObject( hXorBits
);
360 DeleteObject( hAndBits
);
361 GlobalUnlock16( handle
);
365 /**********************************************************************
368 * Load a cursor or icon.
370 static HANDLE
CURSORICON_Load( HANDLE hInstance
, SEGPTR name
, int width
,
371 int height
, int colors
, BOOL fCursor
)
375 CURSORICONDIRENTRY dirEntry
;
377 if (!hInstance
) /* OEM cursor/icon */
379 if (HIWORD(name
)) /* Check for '#xxx' name */
381 char *ptr
= PTR_SEG_TO_LIN( name
);
382 if (ptr
[0] != '#') return 0;
383 if (!(name
= (SEGPTR
)atoi( ptr
+ 1 ))) return 0;
385 return OBM_LoadCursorIcon( LOWORD(name
), fCursor
);
388 /* Find the best entry in the directory */
390 if (!CURSORICON_LoadDirEntry( hInstance
, name
, width
, height
,
391 colors
, fCursor
, &dirEntry
)) return 0;
393 /* Load the resource */
395 if (!(hRsrc
= FindResource16( hInstance
,
396 MAKEINTRESOURCE( dirEntry
.icon
.wResId
),
397 fCursor
? RT_CURSOR
: RT_ICON
))) return 0;
398 if (!(handle
= LoadResource16( hInstance
, hRsrc
))) return 0;
400 hRet
= CURSORICON_LoadHandler( handle
, hInstance
, fCursor
);
401 FreeResource16(handle
);
406 /***********************************************************************
409 * Make a copy of a cursor or icon.
411 static HANDLE
CURSORICON_Copy( HANDLE hInstance
, HANDLE handle
)
413 char *ptrOld
, *ptrNew
;
417 if (!(ptrOld
= (char *)GlobalLock16( handle
))) return 0;
418 if (!(hInstance
= GetExePtr( hInstance
))) return 0;
419 size
= GlobalSize16( handle
);
420 hNew
= GlobalAlloc16( GMEM_MOVEABLE
, size
);
421 FarSetOwner( hNew
, hInstance
);
422 ptrNew
= (char *)GlobalLock16( hNew
);
423 memcpy( ptrNew
, ptrOld
, size
);
424 GlobalUnlock16( handle
);
425 GlobalUnlock16( hNew
);
429 /***********************************************************************
430 * CURSORICON_IconToCursor
432 * Should convert bitmap to mono and truncate if too large
433 * FIXME: if icon is passed returns a copy of OCR_DRAGOBJECT cursor
434 * but should actually convert icon to cursor.
436 HCURSOR
CURSORICON_IconToCursor(HICON hIcon
)
438 CURSORICONINFO
*ptr
= NULL
;
441 if (!(ptr
= (CURSORICONINFO
*)GlobalLock16( hIcon
))) return FALSE
;
442 if (ptr
->bPlanes
* ptr
->bBitsPerPixel
== 1)
444 return hIcon
; /* assuming it's a cursor */
450 HTASK hTask
= GetCurrentTask();
451 TDB
* pTask
= (TDB
*)GlobalLock16(hTask
);
455 fprintf( stdnimp
, "IconToCursor: Icons are not supported, returning default!\n");
456 return CURSORICON_Copy( pTask
->hInstance
,
457 CURSORICON_Load(0,MAKEINTRESOURCE(OCR_DRAGOBJECT
),
458 SYSMETRICS_CXCURSOR
, SYSMETRICS_CYCURSOR
, 1, TRUE
) );
464 /***********************************************************************
465 * LoadCursor (USER.173)
467 HCURSOR16
LoadCursor16( HINSTANCE16 hInstance
, SEGPTR name
)
470 dprintf_cursor( stddeb
, "LoadCursor16: %04x '%s'\n",
471 hInstance
, (char *)PTR_SEG_TO_LIN( name
) );
473 dprintf_cursor( stddeb
, "LoadCursor16: %04x %04x\n",
474 hInstance
, LOWORD(name
) );
476 return CURSORICON_Load( hInstance
, name
,
477 SYSMETRICS_CXCURSOR
, SYSMETRICS_CYCURSOR
, 1, TRUE
);
481 /***********************************************************************
482 * LoadIcon (USER.174)
484 HICON16
LoadIcon16(HINSTANCE16 hInstance
,SEGPTR name
)
487 dprintf_icon( stddeb
, "LoadIcon: %04x '%s'\n",
488 hInstance
, (char *)PTR_SEG_TO_LIN( name
) );
490 dprintf_icon( stddeb
, "LoadIcon: %04x %04x\n",
491 hInstance
, LOWORD(name
) );
493 return CURSORICON_Load( hInstance
, name
,
494 SYSMETRICS_CXICON
, SYSMETRICS_CYICON
,
495 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE
);
499 /***********************************************************************
500 * CreateCursor (USER.406)
502 HCURSOR
CreateCursor( HINSTANCE hInstance
, INT xHotSpot
, INT yHotSpot
,
503 INT nWidth
, INT nHeight
,
504 const BYTE
*lpANDbits
, const BYTE
*lpXORbits
)
506 CURSORICONINFO info
= { { xHotSpot
, yHotSpot
}, nWidth
, nHeight
, 0, 1, 1 };
508 dprintf_cursor( stddeb
, "CreateCursor: %dx%d spot=%d,%d xor=%p and=%p\n",
509 nWidth
, nHeight
, xHotSpot
, yHotSpot
, lpXORbits
, lpANDbits
);
510 return CreateCursorIconIndirect( hInstance
, &info
, lpANDbits
, lpXORbits
);
514 /***********************************************************************
515 * CreateIcon (USER.407)
517 HICON
CreateIcon( HINSTANCE hInstance
, INT nWidth
, INT nHeight
, BYTE bPlanes
,
518 BYTE bBitsPixel
, const BYTE
* lpANDbits
, const BYTE
* lpXORbits
)
520 CURSORICONINFO info
= { { 0, 0 }, nWidth
, nHeight
, 0, bPlanes
, bBitsPixel
};
522 dprintf_icon( stddeb
, "CreateIcon: %dx%dx%d, xor=%p, and=%p\n",
523 nWidth
, nHeight
, bPlanes
* bBitsPixel
, lpXORbits
, lpANDbits
);
524 return CreateCursorIconIndirect( hInstance
, &info
, lpANDbits
, lpXORbits
);
528 /***********************************************************************
529 * CreateCursorIconIndirect (USER.408)
531 HANDLE
CreateCursorIconIndirect( HANDLE hInstance
, CURSORICONINFO
*info
,
532 const BYTE
*lpANDbits
, const BYTE
*lpXORbits
)
536 int sizeAnd
, sizeXor
;
538 hInstance
= GetExePtr( hInstance
); /* Make it a module handle */
539 if (!hInstance
|| !lpXORbits
|| !lpANDbits
|| info
->bPlanes
!= 1) return 0;
540 info
->nWidthBytes
= BITMAP_WIDTH_BYTES(info
->nWidth
,info
->bBitsPerPixel
);
541 sizeXor
= info
->nHeight
* info
->nWidthBytes
;
542 sizeAnd
= info
->nHeight
* BITMAP_WIDTH_BYTES( info
->nWidth
, 1 );
543 if (!(handle
= DirectResAlloc(hInstance
, 0x10,
544 sizeof(CURSORICONINFO
) + sizeXor
+ sizeAnd
)))
546 ptr
= (char *)GlobalLock16( handle
);
547 memcpy( ptr
, info
, sizeof(*info
) );
548 memcpy( ptr
+ sizeof(CURSORICONINFO
), lpANDbits
, sizeAnd
);
549 memcpy( ptr
+ sizeof(CURSORICONINFO
) + sizeAnd
, lpXORbits
, sizeXor
);
550 GlobalUnlock16( handle
);
555 /***********************************************************************
556 * CopyIcon16 (USER.368)
558 HICON16
CopyIcon16( HINSTANCE16 hInstance
, HICON16 hIcon
)
560 dprintf_icon( stddeb
, "CopyIcon16: %04x %04x\n", hInstance
, hIcon
);
561 return CURSORICON_Copy( hInstance
, hIcon
);
565 /***********************************************************************
566 * CopyIcon32 (USER32.59)
568 HICON32
CopyIcon32( HICON32 hIcon
)
570 dprintf_icon( stddeb
, "CopyIcon32: %04x\n", hIcon
);
571 return CURSORICON_Copy( 0, hIcon
);
575 /***********************************************************************
576 * CopyCursor16 (USER.369)
578 HCURSOR16
CopyCursor16( HINSTANCE16 hInstance
, HCURSOR16 hCursor
)
580 dprintf_cursor( stddeb
, "CopyCursor16: %04x %04x\n", hInstance
, hCursor
);
581 return CURSORICON_Copy( hInstance
, hCursor
);
585 /***********************************************************************
586 * DestroyIcon (USER.457)
588 BOOL
DestroyIcon( HICON hIcon
)
590 dprintf_icon( stddeb
, "DestroyIcon: %04x\n", hIcon
);
591 /* FIXME: should check for OEM icon here */
592 return (GlobalFree16( hIcon
) != 0);
596 /***********************************************************************
597 * DestroyCursor (USER.458)
599 BOOL
DestroyCursor( HCURSOR hCursor
)
601 dprintf_cursor( stddeb
, "DestroyCursor: %04x\n", hCursor
);
602 /* FIXME: should check for OEM cursor here */
603 return (GlobalFree16( hCursor
) != 0);
607 /***********************************************************************
610 BOOL
DrawIcon( HDC hdc
, INT x
, INT y
, HICON hIcon
)
614 HBITMAP hXorBits
, hAndBits
;
615 COLORREF oldFg
, oldBg
;
617 if (!(ptr
= (CURSORICONINFO
*)GlobalLock16( hIcon
))) return FALSE
;
618 if (!(hMemDC
= CreateCompatibleDC( hdc
))) return FALSE
;
619 hAndBits
= CreateBitmap( ptr
->nWidth
, ptr
->nHeight
, 1, 1, (char *)(ptr
+1));
620 hXorBits
= CreateBitmap( ptr
->nWidth
, ptr
->nHeight
, ptr
->bPlanes
,
621 ptr
->bBitsPerPixel
, (char *)(ptr
+ 1)
622 + ptr
->nHeight
* BITMAP_WIDTH_BYTES(ptr
->nWidth
,1) );
623 oldFg
= SetTextColor( hdc
, RGB(0,0,0) );
624 oldBg
= SetBkColor( hdc
, RGB(255,255,255) );
626 if (hXorBits
&& hAndBits
)
628 HBITMAP hBitTemp
= SelectObject( hMemDC
, hAndBits
);
629 BitBlt( hdc
, x
, y
, ptr
->nWidth
, ptr
->nHeight
, hMemDC
, 0, 0, SRCAND
);
630 SelectObject( hMemDC
, hXorBits
);
631 BitBlt( hdc
, x
, y
, ptr
->nWidth
, ptr
->nHeight
, hMemDC
, 0, 0, SRCINVERT
);
632 SelectObject( hMemDC
, hBitTemp
);
635 if (hXorBits
) DeleteObject( hXorBits
);
636 if (hAndBits
) DeleteObject( hAndBits
);
637 GlobalUnlock16( hIcon
);
638 SetTextColor( hdc
, oldFg
);
639 SetBkColor( hdc
, oldBg
);
644 /***********************************************************************
645 * DumpIcon (USER.459)
647 DWORD
DumpIcon( SEGPTR pInfo
, WORD
*lpLen
,
648 SEGPTR
*lpXorBits
, SEGPTR
*lpAndBits
)
650 CURSORICONINFO
*info
= PTR_SEG_TO_LIN( pInfo
);
651 int sizeAnd
, sizeXor
;
654 sizeXor
= info
->nHeight
* info
->nWidthBytes
;
655 sizeAnd
= info
->nHeight
* BITMAP_WIDTH_BYTES( info
->nWidth
, 1 );
656 if (lpAndBits
) *lpAndBits
= pInfo
+ sizeof(CURSORICONINFO
);
657 if (lpXorBits
) *lpXorBits
= pInfo
+ sizeof(CURSORICONINFO
) + sizeAnd
;
658 if (lpLen
) *lpLen
= sizeof(CURSORICONINFO
) + sizeAnd
+ sizeXor
;
659 return MAKELONG( sizeXor
, sizeXor
);
663 /***********************************************************************
664 * CURSORICON_SetCursor
666 * Change the X cursor. Helper function for SetCursor() and ShowCursor().
668 static BOOL
CURSORICON_SetCursor( HCURSOR hCursor
)
670 Pixmap pixmapBits
, pixmapMask
, pixmapAll
;
672 Cursor cursor
= None
;
674 if (!hCursor
) /* Create an empty cursor */
676 static const char data
[] = { 0 };
678 bg
.red
= bg
.green
= bg
.blue
= 0x0000;
679 pixmapBits
= XCreateBitmapFromData( display
, rootWindow
, data
, 1, 1 );
682 cursor
= XCreatePixmapCursor( display
, pixmapBits
, pixmapBits
,
684 XFreePixmap( display
, pixmapBits
);
687 else /* Create the X cursor from the bits */
692 if (!(ptr
= (CURSORICONINFO
*)GlobalLock16( hCursor
))) return FALSE
;
693 if (ptr
->bPlanes
* ptr
->bBitsPerPixel
!= 1)
695 fprintf( stderr
, "Cursor %04x has more than 1 bpp!\n", hCursor
);
699 /* Create a pixmap and transfer all the bits to it */
701 pixmapAll
= XCreatePixmap( display
, rootWindow
,
702 ptr
->nWidth
, ptr
->nHeight
* 2, 1 );
703 image
= XCreateImage( display
, DefaultVisualOfScreen(screen
),
704 1, ZPixmap
, 0, (char *)(ptr
+ 1), ptr
->nWidth
,
705 ptr
->nHeight
* 2, 16, ptr
->nWidthBytes
);
708 extern void _XInitImageFuncPtrs( XImage
* );
709 image
->byte_order
= MSBFirst
;
710 image
->bitmap_bit_order
= MSBFirst
;
711 image
->bitmap_unit
= 16;
712 _XInitImageFuncPtrs(image
);
714 CallTo32_LargeStack( XPutImage
, 10,
715 display
, pixmapAll
, BITMAP_monoGC
, image
,
716 0, 0, 0, 0, ptr
->nWidth
, ptr
->nHeight
*2 );
718 XDestroyImage( image
);
721 /* Now create the 2 pixmaps for bits and mask */
723 pixmapBits
= XCreatePixmap( display
, rootWindow
,
724 ptr
->nWidth
, ptr
->nHeight
, 1 );
725 pixmapMask
= XCreatePixmap( display
, rootWindow
,
726 ptr
->nWidth
, ptr
->nHeight
, 1 );
728 /* Make sure everything went OK so far */
730 if (pixmapBits
&& pixmapMask
&& pixmapAll
)
732 /* We have to do some magic here, as cursors are not fully
733 * compatible between Windows and X11. Under X11, there
734 * are only 3 possible color cursor: black, white and
735 * masked. So we map the 4th Windows color (invert the
736 * bits on the screen) to black. This require some boolean
740 * Xor And Result | Bits Mask Result
741 * 0 0 black | 0 1 background
742 * 0 1 no change | X 0 no change
743 * 1 0 white | 1 1 foreground
744 * 1 1 inverted | 0 1 background
747 * Bits = 'Xor' and not 'And'
748 * Mask = 'Xor' or not 'And'
750 * FIXME: apparently some servers do support 'inverted' color.
751 * I don't know if it's correct per the X spec, but maybe
752 * we ought to take advantage of it. -- AJ
754 XCopyArea( display
, pixmapAll
, pixmapBits
, BITMAP_monoGC
,
755 0, 0, ptr
->nWidth
, ptr
->nHeight
, 0, 0 );
756 XCopyArea( display
, pixmapAll
, pixmapMask
, BITMAP_monoGC
,
757 0, 0, ptr
->nWidth
, ptr
->nHeight
, 0, 0 );
758 XSetFunction( display
, BITMAP_monoGC
, GXandReverse
);
759 XCopyArea( display
, pixmapAll
, pixmapBits
, BITMAP_monoGC
,
760 0, ptr
->nHeight
, ptr
->nWidth
, ptr
->nHeight
, 0, 0 );
761 XSetFunction( display
, BITMAP_monoGC
, GXorReverse
);
762 XCopyArea( display
, pixmapAll
, pixmapMask
, BITMAP_monoGC
,
763 0, ptr
->nHeight
, ptr
->nWidth
, ptr
->nHeight
, 0, 0 );
764 XSetFunction( display
, BITMAP_monoGC
, GXcopy
);
765 fg
.red
= fg
.green
= fg
.blue
= 0xffff;
766 bg
.red
= bg
.green
= bg
.blue
= 0x0000;
767 cursor
= XCreatePixmapCursor( display
, pixmapBits
, pixmapMask
,
768 &fg
, &bg
, ptr
->ptHotSpot
.x
, ptr
->ptHotSpot
.y
);
771 /* Now free everything */
773 if (pixmapAll
) XFreePixmap( display
, pixmapAll
);
774 if (pixmapBits
) XFreePixmap( display
, pixmapBits
);
775 if (pixmapMask
) XFreePixmap( display
, pixmapMask
);
776 GlobalUnlock16( hCursor
);
779 if (cursor
== None
) return FALSE
;
780 if (CURSORICON_XCursor
!= None
) XFreeCursor( display
, CURSORICON_XCursor
);
781 CURSORICON_XCursor
= cursor
;
783 if (rootWindow
!= DefaultRootWindow(display
))
785 /* Set the cursor on the desktop window */
786 XDefineCursor( display
, rootWindow
, cursor
);
790 /* Set the same cursor for all top-level windows */
791 HWND hwnd
= GetWindow( GetDesktopWindow(), GW_CHILD
);
794 Window win
= WIN_GetXWindow( hwnd
);
795 if (win
) XDefineCursor( display
, win
, cursor
);
796 hwnd
= GetWindow( hwnd
, GW_HWNDNEXT
);
803 /***********************************************************************
804 * SetCursor (USER.69)
806 HCURSOR
SetCursor( HCURSOR hCursor
)
810 if (hCursor
== hActiveCursor
) return hActiveCursor
; /* No change */
811 dprintf_cursor( stddeb
, "SetCursor: %04x\n", hCursor
);
812 hOldCursor
= hActiveCursor
;
813 hActiveCursor
= hCursor
;
814 /* Change the cursor shape only if it is visible */
815 if (CURSOR_ShowCount
>= 0) CURSORICON_SetCursor( hActiveCursor
);
820 /***********************************************************************
821 * SetCursorPos (USER.70)
823 void SetCursorPos( short x
, short y
)
825 dprintf_cursor( stddeb
, "SetCursorPos: x=%d y=%d\n", x
, y
);
826 XWarpPointer( display
, rootWindow
, rootWindow
, 0, 0, 0, 0, x
, y
);
830 /***********************************************************************
831 * ShowCursor (USER.71)
833 int ShowCursor( BOOL bShow
)
835 dprintf_cursor( stddeb
, "ShowCursor: %d, count=%d\n",
836 bShow
, CURSOR_ShowCount
);
840 if (++CURSOR_ShowCount
== 0)
841 CURSORICON_SetCursor( hActiveCursor
); /* Show it */
845 if (--CURSOR_ShowCount
== -1)
846 CURSORICON_SetCursor( 0 ); /* Hide it */
848 return CURSOR_ShowCount
;
852 /***********************************************************************
853 * GetCursor (USER.247)
855 HCURSOR
GetCursor(void)
857 return hActiveCursor
;
861 /***********************************************************************
862 * ClipCursor16 (USER.16)
864 BOOL16
ClipCursor16( const RECT16
*rect
)
866 if (!rect
) SetRectEmpty32( &CURSOR_ClipRect
);
867 else CONV_RECT16TO32( rect
, &CURSOR_ClipRect
);
872 /***********************************************************************
873 * ClipCursor32 (USER32.52)
875 BOOL32
ClipCursor32( const RECT32
*rect
)
877 if (!rect
) SetRectEmpty32( &CURSOR_ClipRect
);
878 else CopyRect32( &CURSOR_ClipRect
, rect
);
883 /***********************************************************************
884 * GetCursorPos16 (USER.17)
886 void GetCursorPos16( POINT16
*pt
)
889 int rootX
, rootY
, childX
, childY
;
890 unsigned int mousebut
;
893 if (!XQueryPointer( display
, rootWindow
, &root
, &child
,
894 &rootX
, &rootY
, &childX
, &childY
, &mousebut
))
898 pt
->x
= rootX
+ desktopX
;
899 pt
->y
= rootY
+ desktopY
;
901 dprintf_cursor(stddeb
, "GetCursorPos: ret=%d,%d\n", pt
->x
, pt
->y
);
905 /***********************************************************************
906 * GetCursorPos32 (USER32.228)
908 void GetCursorPos32( POINT32
*pt
)
911 GetCursorPos16( &pt16
);
912 if (pt
) CONV_POINT16TO32( &pt16
, pt
);
916 /***********************************************************************
917 * GetClipCursor16 (USER.309)
919 void GetClipCursor16( RECT16
*rect
)
921 if (rect
) CONV_RECT32TO16( &CURSOR_ClipRect
, rect
);
925 /***********************************************************************
926 * GetClipCursor32 (USER32.220)
928 void GetClipCursor32( RECT32
*rect
)
930 if (rect
) CopyRect32( rect
, &CURSOR_ClipRect
);
934 /**********************************************************************
935 * GetIconID (USER.455)
937 WORD
GetIconID( HANDLE hResource
, DWORD resType
)
939 CURSORICONDIR
*lpDir
= (CURSORICONDIR
*)GlobalLock16(hResource
);
940 /* LockResource16(hResource); */
942 if (!lpDir
|| lpDir
->idReserved
||
943 ((lpDir
->idType
!= 1) && (lpDir
->idType
!= 2)))
945 dprintf_cursor(stddeb
,"GetIconID: invalid resource directory\n");
949 dprintf_cursor( stddeb
, "GetIconID: hRes=%04x, entries=%i\n",
950 hResource
, lpDir
->idCount
);
956 CURSORDIRENTRY
*entry
= CURSORICON_FindBestCursor( lpDir
,
957 SYSMETRICS_CXCURSOR
, SYSMETRICS_CYCURSOR
);
958 return entry
? entry
->wResId
: 0;
962 ICONDIRENTRY
* entry
= CURSORICON_FindBestIcon( lpDir
,
963 SYSMETRICS_CXICON
, SYSMETRICS_CYICON
,
964 MIN( 16, COLOR_GetSystemPaletteSize() ) );
965 return entry
? entry
->wResId
: 0;
968 fprintf( stderr
, "GetIconID: invalid res type %ld\n", resType
);
973 /**********************************************************************
974 * LoadIconHandler (USER.456)
976 HICON
LoadIconHandler( HANDLE hResource
, BOOL bNew
)
978 dprintf_cursor(stddeb
,"LoadIconHandler: hRes=%04x\n",hResource
);
982 fprintf(stdnimp
,"LoadIconHandler: 2.xx resources are not supported\n");
985 return CURSORICON_LoadHandler( hResource
, 0, FALSE
);