Release 951003
[wine/hacks.git] / objects / cursoricon.c
blob6cc3f2a24e21c8f277632a6ea086eba09a7ffd30
1 /*
2 * Cursor and icon support
4 * Copyright 1995 Alexandre Julliard
5 */
7 /*
8 * Theory:
10 * Cursors and icons are stored in a global heap block, with the
11 * following layout:
13 * CURSORICONINFO info;
14 * BYTE[] ANDbits;
15 * BYTE[] XORbits;
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 :-(
25 #include <string.h>
26 #include <stdlib.h>
27 #include "windows.h"
28 #include "bitmap.h"
29 #include "callback.h"
30 #include "cursoricon.h"
31 #include "sysmetrics.h"
32 #include "win.h"
33 #include "stddebug.h"
34 #include "debug.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;
53 if (dir->idCount < 1)
55 fprintf( stderr, "Icon: empty directory!\n" );
56 return NULL;
58 if (dir->idCount == 1) return &dir->idEntries[0].icon; /* No choice... */
60 /* First find the exact size with less colors */
62 maxcolors = 0;
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))
67 bestEntry = entry;
68 maxcolors = entry->bColorCount;
70 if (bestEntry) return bestEntry;
72 /* First find the exact size with more colors */
74 maxcolors = 255;
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 /* 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))
92 bestEntry = entry;
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 */
101 maxcolors = 255;
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))
108 bestEntry = entry;
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 */
117 maxcolors = 0;
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))
123 bestEntry = entry;
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))
137 bestEntry = entry;
138 maxwidth = entry->bWidth;
139 maxheight = entry->bHeight;
140 maxcolors = entry->bColorCount;
143 return bestEntry;
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" );
161 return NULL;
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))
172 bestEntry = entry;
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))
184 bestEntry = entry;
185 maxwidth = entry->wWidth;
186 maxheight = entry->wHeight;
189 return bestEntry;
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)
203 HRSRC hRsrc;
204 HANDLE hMem;
205 CURSORICONDIR *dir;
206 CURSORICONDIRENTRY *entry = NULL;
208 if (!(hRsrc = FindResource( hInstance, name,
209 fCursor ? RT_GROUP_CURSOR : RT_GROUP_ICON )))
210 return FALSE;
211 if (!(hMem = LoadResource( hInstance, hRsrc ))) return FALSE;
212 if ((dir = (CURSORICONDIR *)LockResource( hMem )))
214 if (fCursor)
215 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
216 width, height );
217 else
218 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
219 width, height, colors );
220 if (entry) *dirEntry = *entry;
222 FreeResource( hMem );
223 return (entry != NULL);
227 /**********************************************************************
228 * CURSORICON_Load
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;
236 HRSRC hRsrc;
237 HDC hdc;
238 int size, sizeAnd, sizeXor;
239 POINT hotspot = { 0 ,0 };
240 BITMAPOBJ *bmpXor, *bmpAnd;
241 BITMAPINFO *bmi, *pInfo;
242 CURSORICONINFO *info;
243 CURSORICONDIRENTRY dirEntry;
244 char *bits;
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 );
272 hotspot = *pt;
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 );
291 free( pInfo );
292 return 0;
294 pInfo->bmiHeader.biHeight /= 2;
296 else if (pInfo->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
298 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)pInfo;
299 core->bcHeight /= 2;
301 else
303 fprintf( stderr, "CURSORICON_Load: Unknown bitmap length %ld!\n",
304 pInfo->bmiHeader.biSize );
305 FreeResource( handle );
306 free( pInfo );
307 return 0;
310 /* Create the XOR bitmap */
312 if (!(hdc = GetDC( 0 )))
314 FreeResource( handle );
315 free( pInfo );
316 return 0;
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;
330 bih->biBitCount = 1;
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;
336 else
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;
342 bch->bcBitCount = 1;
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 );
351 ReleaseDC( 0, hdc );
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 );
366 return 0;
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 );
386 return handle;
390 /***********************************************************************
391 * CURSORICON_Copy
393 * Make a copy of a cursor or icon.
395 static HANDLE CURSORICON_Copy( HANDLE hInstance, HANDLE handle )
397 char *ptrOld, *ptrNew;
398 int size;
399 HANDLE hNew;
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 );
410 return hNew;
414 /***********************************************************************
415 * LoadCursor (USER.173)
417 HCURSOR LoadCursor( HANDLE hInstance, SEGPTR name )
419 if (HIWORD(name))
420 dprintf_cursor( stddeb, "LoadCursor: "NPFMT" '%s'\n",
421 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
422 else
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 )
436 if (HIWORD(name))
437 dprintf_icon( stddeb, "LoadIcon: "NPFMT" '%s'\n",
438 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
439 else
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 )
483 HANDLE handle;
484 char *ptr;
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)))
494 return 0;
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 );
500 return 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 /***********************************************************************
545 * DrawIcon (USER.84)
547 BOOL DrawIcon( HDC hdc, short x, short y, HICON hIcon )
549 CURSORICONINFO *ptr;
550 HDC hMemDC;
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 );
571 DeleteDC( hMemDC );
572 if (hXorBits) DeleteObject( hXorBits );
573 if (hAndBits) DeleteObject( hAndBits );
574 GlobalUnlock( hIcon );
575 SetTextColor( hdc, oldFg );
576 SetBkColor( hdc, oldBg );
577 return TRUE;
581 /***********************************************************************
582 * DumpIcon (USER.459)
584 DWORD DumpIcon( CURSORICONINFO *info, WORD *lpLen,
585 LPSTR *lpXorBits, LPSTR *lpAndBits )
587 int sizeAnd, sizeXor;
589 if (!info) return 0;
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;
607 XColor fg, bg;
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 );
616 if (pixmapBits)
618 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapBits,
619 &bg, &bg, 0, 0 );
620 XFreePixmap( display, pixmapBits );
623 else /* Create the X cursor from the bits */
625 CURSORICONINFO *ptr;
626 XImage *image;
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 );
632 return FALSE;
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);
642 if (image)
644 extern void _XInitImageFuncPtrs( XImage* );
645 image->byte_order = MSBFirst;
646 image->bitmap_bit_order = MSBFirst;
647 image->bitmap_unit = 16;
648 _XInitImageFuncPtrs(image);
649 if (pixmapAll)
650 CallTo32_LargeStack( XPutImage, 10,
651 display, pixmapAll, BITMAP_monoGC, image,
652 0, 0, 0, 0, ptr->nWidth, ptr->nHeight*2 );
653 image->data = NULL;
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
673 * arithmetic:
675 * Windows X11
676 * Xor And Result Bits Mask
677 * 0 0 black 0 1
678 * 0 1 no change X 0
679 * 1 0 white 1 1
680 * 1 1 inverted 0 1 (=black)
682 * which gives:
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 );
720 else
722 /* Set the same cursor for all top-level windows */
723 HWND hwnd = GetWindow( GetDesktopWindow(), GW_CHILD );
724 while(hwnd)
726 Window win = WIN_GetXWindow( hwnd );
727 if (win) XDefineCursor( display, win, cursor );
728 hwnd = GetWindow( hwnd, GW_HWNDNEXT );
731 return TRUE;
735 /***********************************************************************
736 * SetCursor (USER.69)
738 HCURSOR SetCursor( HCURSOR hCursor )
740 HCURSOR hOldCursor;
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 );
748 return hOldCursor;
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 );
770 if (bShow)
772 if (++CURSOR_ShowCount == 0)
773 CURSORICON_SetCursor( hActiveCursor ); /* Show it */
775 else
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 )
808 Window root, child;
809 int rootX, rootY, childX, childY;
810 unsigned int mousebut;
812 if (!pt) return;
813 if (!XQueryPointer( display, rootWindow, &root, &child,
814 &rootX, &rootY, &childX, &childY, &mousebut ))
815 pt->x = pt->y = 0;
816 else
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 );
841 return 0;
845 /**********************************************************************
846 * LoadIconHandler (USER.456)
848 HICON LoadIconHandler( HANDLE hResource, BOOL bNew )
850 fprintf( stderr, "LoadIconHandle(%04x,%d): empty stub!\n",
851 hResource, bNew );
852 return 0;