Added implementations for InterlockedExchangeAdd() and
[wine/multimedia.git] / objects / cursoricon.c
blobb59be5bf411370cfffca873736316dfd4a554c0f
1 /*
2 * Cursor and icon support
4 * Copyright 1995 Alexandre Julliard
5 * 1996 Martin Von Loewis
6 * 1997 Alex Korobka
7 * 1998 Turchanov Sergey
8 */
11 * Theory:
13 * http://www.microsoft.com/win32dev/ui/icons.htm
15 * Cursors and icons are stored in a global heap block, with the
16 * following layout:
18 * CURSORICONINFO info;
19 * BYTE[] ANDbits;
20 * BYTE[] XORbits;
22 * The bits structures are in the format of a device-dependent bitmap.
24 * This layout is very sub-optimal, as the bitmap bits are stored in
25 * the X client instead of in the server like other bitmaps; however,
26 * some programs (notably Paint Brush) expect to be able to manipulate
27 * the bits directly :-(
29 * FIXME: what are we going to do with animation and color (bpp > 1) cursors ?!
32 #include <string.h>
33 #include <stdlib.h>
34 #include "heap.h"
35 #include "windows.h"
36 #include "peexe.h"
37 #include "color.h"
38 #include "bitmap.h"
39 #include "callback.h"
40 #include "cursoricon.h"
41 #include "sysmetrics.h"
42 #include "global.h"
43 #include "module.h"
44 #include "win.h"
45 #include "debug.h"
46 #include "task.h"
47 #include "user.h"
48 #include "input.h"
49 #include "x11drv.h"
50 #include "winerror.h"
52 Cursor CURSORICON_XCursor = None; /* Current X cursor */
53 static HCURSOR32 hActiveCursor = 0; /* Active cursor */
54 static INT32 CURSOR_ShowCount = 0; /* Cursor display count */
55 static RECT32 CURSOR_ClipRect; /* Cursor clipping rect */
57 /**********************************************************************
58 * CURSORICON_FindBestIcon
60 * Find the icon closest to the requested size and number of colors.
62 static ICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
63 int height, int colors )
65 int i, maxcolors, maxwidth, maxheight;
66 ICONDIRENTRY *entry, *bestEntry = NULL;
68 if (dir->idCount < 1)
70 WARN(icon, "Empty directory!\n" );
71 return NULL;
73 if (dir->idCount == 1) return &dir->idEntries[0].icon; /* No choice... */
75 /* First find the exact size with less colors */
77 maxcolors = 0;
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))
82 bestEntry = entry;
83 maxcolors = entry->bColorCount;
85 if (bestEntry) return bestEntry;
87 /* First find the exact size with more colors */
89 maxcolors = 255;
90 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
91 if ((entry->bWidth == width) && (entry->bHeight == height) &&
92 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
94 bestEntry = entry;
95 maxcolors = entry->bColorCount;
97 if (bestEntry) return bestEntry;
99 /* Now find a smaller one with less colors */
101 maxcolors = maxwidth = maxheight = 0;
102 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
103 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
104 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
105 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
107 bestEntry = entry;
108 maxwidth = entry->bWidth;
109 maxheight = entry->bHeight;
110 maxcolors = entry->bColorCount;
112 if (bestEntry) return bestEntry;
114 /* Now find a smaller one with more colors */
116 maxcolors = 255;
117 maxwidth = maxheight = 0;
118 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
119 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
120 (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 less colors */
132 maxcolors = 0;
133 maxwidth = maxheight = 255;
134 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
135 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
136 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
138 bestEntry = entry;
139 maxwidth = entry->bWidth;
140 maxheight = entry->bHeight;
141 maxcolors = entry->bColorCount;
143 if (bestEntry) return bestEntry;
145 /* Now find a larger one with more colors */
147 maxcolors = maxwidth = maxheight = 255;
148 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
149 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
150 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
152 bestEntry = entry;
153 maxwidth = entry->bWidth;
154 maxheight = entry->bHeight;
155 maxcolors = entry->bColorCount;
158 return bestEntry;
162 /**********************************************************************
163 * CURSORICON_FindBestCursor
165 * Find the cursor closest to the requested size.
166 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
167 * ignored too
169 static CURSORDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
170 int width, int height, int color)
172 int i, maxwidth, maxheight;
173 CURSORDIRENTRY *entry, *bestEntry = NULL;
175 if (dir->idCount < 1)
177 WARN(cursor, "Empty directory!\n" );
178 return NULL;
180 if (dir->idCount == 1) return &dir->idEntries[0].cursor; /* No choice... */
182 /* First find the largest one smaller than or equal to the requested size*/
184 maxwidth = maxheight = 0;
185 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
186 if ((entry->wWidth <= width) && (entry->wHeight <= height) &&
187 (entry->wWidth > maxwidth) && (entry->wHeight > maxheight) &&
188 (entry->wBitCount == 1))
190 bestEntry = entry;
191 maxwidth = entry->wWidth;
192 maxheight = entry->wHeight;
194 if (bestEntry) return bestEntry;
196 /* Now find the smallest one larger than the requested size */
198 maxwidth = maxheight = 255;
199 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
200 if ((entry->wWidth < maxwidth) && (entry->wHeight < maxheight) &&
201 (entry->wBitCount == 1))
203 bestEntry = entry;
204 maxwidth = entry->wWidth;
205 maxheight = entry->wHeight;
208 return bestEntry;
211 /*********************************************************************
212 * The main purpose of this function is to create fake resource directory
213 * and fake resource entries. There are several reasons for this:
214 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
215 * fields
216 * There are some "bad" cursor files which do not have
217 * bColorCount initialized but instead one must read this info
218 * directly from corresponding DIB sections
219 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
221 BOOL32 CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL32 fCursor,
222 CURSORICONDIR **res, LPBYTE **ptr)
224 LPBYTE _free;
225 CURSORICONFILEDIR *bits;
226 int entries, size, i;
228 *res = NULL;
229 *ptr = NULL;
230 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
231 if (!(entries = bits->idCount)) goto fail;
232 (int)_free = size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) *
233 (entries - 1);
234 for (i=0; i < entries; i++)
235 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
237 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
238 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
239 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
241 _free = (LPBYTE)(*res) + (int)_free;
242 memcpy((*res), bits, 6);
243 for (i=0; i<entries; i++)
245 ((LPBYTE*)(*ptr))[i] = _free;
246 if (fCursor) {
247 (*res)->idEntries[i].cursor.wWidth=bits->idEntries[i].bWidth;
248 (*res)->idEntries[i].cursor.wHeight=bits->idEntries[i].bHeight;
249 (*res)->idEntries[i].cursor.wPlanes=1;
250 (*res)->idEntries[i].cursor.wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
251 bits->idEntries[i].dwDIBOffset))->biBitCount;
252 (*res)->idEntries[i].cursor.dwBytesInRes = bits->idEntries[i].dwDIBSize;
253 (*res)->idEntries[i].cursor.wResId=i+1;
254 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
255 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
256 _free+=sizeof(POINT16);
257 } else {
258 (*res)->idEntries[i].icon.bWidth=bits->idEntries[i].bWidth;
259 (*res)->idEntries[i].icon.bHeight=bits->idEntries[i].bHeight;
260 (*res)->idEntries[i].icon.bColorCount = bits->idEntries[i].bColorCount;
261 (*res)->idEntries[i].icon.wPlanes=1;
262 (*res)->idEntries[i].icon.wBitCount= ((LPBITMAPINFOHEADER)((LPBYTE)bits +
263 bits->idEntries[i].dwDIBOffset))->biBitCount;
264 (*res)->idEntries[i].icon.dwBytesInRes = bits->idEntries[i].dwDIBSize;
265 (*res)->idEntries[i].icon.wResId=i+1;
267 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
268 (*res)->idEntries[i].icon.dwBytesInRes);
269 _free += (*res)->idEntries[i].icon.dwBytesInRes;
271 UnmapViewOfFile( bits );
272 return TRUE;
273 fail:
274 if (*res) HeapFree( GetProcessHeap(), 0, *res );
275 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
276 UnmapViewOfFile( bits );
277 return FALSE;
280 /**********************************************************************
281 * CURSORICON_LoadDirEntry16
283 * Load the icon/cursor directory for a given resource name and find the
284 * best matching entry.
286 static BOOL32 CURSORICON_LoadDirEntry16( HINSTANCE32 hInstance, SEGPTR name,
287 INT32 width, INT32 height, INT32 colors,
288 BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
290 HRSRC16 hRsrc;
291 HGLOBAL16 hMem;
292 CURSORICONDIR *dir;
293 CURSORICONDIRENTRY *entry = NULL;
295 if (!(hRsrc = FindResource16( hInstance, name,
296 fCursor ? RT_GROUP_CURSOR16 : RT_GROUP_ICON16 )))
297 return FALSE;
298 if (!(hMem = LoadResource16( hInstance, hRsrc ))) return FALSE;
299 if ((dir = (CURSORICONDIR *)LockResource16( hMem )))
301 if (fCursor)
302 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
303 width, height, 1);
304 else
305 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
306 width, height, colors );
307 if (entry) *dirEntry = *entry;
309 FreeResource16( hMem );
310 return (entry != NULL);
314 /**********************************************************************
315 * CURSORICON_LoadDirEntry32
317 * Load the icon/cursor directory for a given resource name and find the
318 * best matching entry.
320 static BOOL32 CURSORICON_LoadDirEntry32( HINSTANCE32 hInstance, LPCWSTR name,
321 INT32 width, INT32 height, INT32 colors,
322 BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
324 HANDLE32 hRsrc;
325 HANDLE32 hMem;
326 CURSORICONDIR *dir;
327 CURSORICONDIRENTRY *entry = NULL;
329 if (!(hRsrc = FindResource32W( hInstance, name,
330 fCursor ? RT_GROUP_CURSOR32W : RT_GROUP_ICON32W )))
331 return FALSE;
332 if (!(hMem = LoadResource32( hInstance, hRsrc ))) return FALSE;
333 if ((dir = (CURSORICONDIR*)LockResource32( hMem )))
335 if (fCursor)
336 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
337 width, height, 1);
338 else
339 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
340 width, height, colors );
341 if (entry) *dirEntry = *entry;
343 FreeResource32( hMem );
344 return (entry != NULL);
348 /**********************************************************************
349 * CURSORICON_CreateFromResource
351 * Create a cursor or icon from in-memory resource template.
353 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
354 * with cbSize parameter as well.
356 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
357 UINT32 cbSize, BOOL32 bIcon, DWORD dwVersion,
358 INT32 width, INT32 height, UINT32 loadflags )
360 int sizeAnd, sizeXor;
361 HBITMAP32 hAndBits = 0, hXorBits = 0; /* error condition for later */
362 BITMAPOBJ *bmpXor, *bmpAnd;
363 POINT16 hotspot = { 0 ,0 };
364 BITMAPINFO *bmi;
365 HDC32 hdc;
366 BOOL32 DoStretch;
367 INT32 size;
369 TRACE(cursor,"%08x (%u bytes), ver %08x, %ix%i %s %s\n",
370 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
371 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
372 if (dwVersion == 0x00020000)
374 FIXME(cursor,"\t2.xx resources are not supported\n");
375 return 0;
378 if (bIcon)
379 bmi = (BITMAPINFO *)bits;
380 else /* get the hotspot */
382 POINT16 *pt = (POINT16 *)bits;
383 hotspot = *pt;
384 bmi = (BITMAPINFO *)(pt + 1);
386 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
388 if (!width) width = bmi->bmiHeader.biWidth;
389 if (!height) height = bmi->bmiHeader.biHeight/2;
390 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
391 (bmi->bmiHeader.biWidth != width);
393 /* Check bitmap header */
395 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
396 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
397 bmi->bmiHeader.biCompression != BI_RGB) )
399 WARN(cursor,"\tinvalid resource bitmap header.\n");
400 return 0;
403 if( (hdc = GetDC32( 0 )) )
405 BITMAPINFO* pInfo;
407 /* Make sure we have room for the monochrome bitmap later on.
408 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
409 * up to and including the biBitCount. In-memory icon resource
410 * format is as follows:
412 * BITMAPINFOHEADER icHeader // DIB header
413 * RGBQUAD icColors[] // Color table
414 * BYTE icXOR[] // DIB bits for XOR mask
415 * BYTE icAND[] // DIB bits for AND mask
418 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
419 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
421 memcpy( pInfo, bmi, size );
422 pInfo->bmiHeader.biHeight /= 2;
424 /* Create the XOR bitmap */
426 if (DoStretch) {
427 if ((hXorBits = CreateCompatibleBitmap32(hdc, width, height))) {
428 HBITMAP32 hOld;
429 HDC32 hMem = CreateCompatibleDC32(hdc);
430 BOOL32 res;
432 if (hMem) {
433 hOld = SelectObject32(hMem, hXorBits);
434 res = StretchDIBits32(hMem, 0, 0, width, height, 0, 0,
435 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
436 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
437 SelectObject32(hMem, hOld);
438 DeleteDC32(hMem);
439 } else res = FALSE;
440 if (!res) { DeleteObject32(hXorBits); hXorBits = 0; }
442 } else hXorBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader,
443 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
444 if( hXorBits )
446 char* bits = (char *)bmi + size + bmi->bmiHeader.biHeight *
447 DIB_GetDIBWidthBytes(bmi->bmiHeader.biWidth,
448 bmi->bmiHeader.biBitCount) / 2;
450 pInfo->bmiHeader.biBitCount = 1;
451 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
453 RGBQUAD *rgb = pInfo->bmiColors;
455 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
456 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
457 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
458 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
460 else
462 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
464 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
465 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
468 /* Create the AND bitmap */
470 if (DoStretch) {
471 if ((hAndBits = CreateBitmap32(width, height, 1, 1, NULL))) {
472 HBITMAP32 hOld;
473 HDC32 hMem = CreateCompatibleDC32(hdc);
474 BOOL32 res;
476 if (hMem) {
477 hOld = SelectObject32(hMem, hAndBits);
478 res = StretchDIBits32(hMem, 0, 0, width, height, 0, 0,
479 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
480 bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
481 SelectObject32(hMem, hOld);
482 DeleteDC32(hMem);
483 } else res = FALSE;
484 if (!res) { DeleteObject32(hAndBits); hAndBits = 0; }
486 } else hAndBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader,
487 CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
489 if( !hAndBits ) DeleteObject32( hXorBits );
491 HeapFree( GetProcessHeap(), 0, pInfo );
493 ReleaseDC32( 0, hdc );
496 if( !hXorBits || !hAndBits )
498 WARN(cursor,"\tunable to create an icon bitmap.\n");
499 return 0;
502 /* Now create the CURSORICONINFO structure */
503 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
504 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
505 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
506 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
508 if (hObj) hObj = GlobalReAlloc16( hObj,
509 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
510 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
511 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
512 if (hObj)
514 CURSORICONINFO *info;
516 /* Make it owned by the module */
517 if (hInstance) FarSetOwner( hObj, GetExePtr(hInstance) );
519 info = (CURSORICONINFO *)GlobalLock16( hObj );
520 info->ptHotSpot.x = hotspot.x;
521 info->ptHotSpot.y = hotspot.y;
522 info->nWidth = bmpXor->bitmap.bmWidth;
523 info->nHeight = bmpXor->bitmap.bmHeight;
524 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
525 info->bPlanes = bmpXor->bitmap.bmPlanes;
526 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
528 /* Transfer the bitmap bits to the CURSORICONINFO structure */
530 GetBitmapBits32( hAndBits, sizeAnd, (char *)(info + 1) );
531 GetBitmapBits32( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
532 GlobalUnlock16( hObj );
535 DeleteObject32( hXorBits );
536 DeleteObject32( hAndBits );
537 return hObj;
541 /**********************************************************************
542 * CreateIconFromResourceEx16 (USER.450)
544 * FIXME: not sure about exact parameter types
546 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
547 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
549 return CreateIconFromResourceEx32(bits, cbSize, bIcon, dwVersion,
550 width, height, cFlag);
554 /**********************************************************************
555 * CreateIconFromResource (USER32.76)
557 HICON32 WINAPI CreateIconFromResource32( LPBYTE bits, UINT32 cbSize,
558 BOOL32 bIcon, DWORD dwVersion)
560 return CreateIconFromResourceEx32( bits, cbSize, bIcon, dwVersion, 0,0,0);
564 /**********************************************************************
565 * CreateIconFromResourceEx32 (USER32.77)
567 HICON32 WINAPI CreateIconFromResourceEx32( LPBYTE bits, UINT32 cbSize,
568 BOOL32 bIcon, DWORD dwVersion,
569 INT32 width, INT32 height,
570 UINT32 cFlag )
572 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
573 if( pTask )
574 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
575 width, height, cFlag );
576 return 0;
580 /**********************************************************************
581 * CURSORICON_Load16
583 * Load a cursor or icon from a 16-bit resource.
585 static HGLOBAL16 CURSORICON_Load16( HINSTANCE16 hInstance, SEGPTR name,
586 INT32 width, INT32 height, INT32 colors,
587 BOOL32 fCursor, UINT32 loadflags)
589 HGLOBAL16 handle;
590 HRSRC16 hRsrc;
591 CURSORICONDIRENTRY dirEntry;
593 if (!hInstance) /* OEM cursor/icon */
595 if (HIWORD(name)) /* Check for '#xxx' name */
597 char *ptr = PTR_SEG_TO_LIN( name );
598 if (ptr[0] != '#') return 0;
599 if (!(name = (SEGPTR)atoi( ptr + 1 ))) return 0;
601 return OBM_LoadCursorIcon( LOWORD(name), fCursor );
604 /* Find the best entry in the directory */
606 if ( !CURSORICON_LoadDirEntry16( hInstance, name, width, height,
607 colors, fCursor, &dirEntry ) ) return 0;
608 /* Load the resource */
610 if ( (hRsrc = FindResource16( hInstance,
611 MAKEINTRESOURCE16( dirEntry.icon.wResId ),
612 fCursor ? RT_CURSOR16 : RT_ICON16 )) )
614 /* 16-bit icon or cursor resources are processed
615 * transparently by the LoadResource16() via custom
616 * resource handlers set by SetResourceHandler().
619 if ( (handle = LoadResource16( hInstance, hRsrc )) )
620 return handle;
622 return 0;
625 /**********************************************************************
626 * CURSORICON_Load32
628 * Load a cursor or icon from a 32-bit resource.
630 HGLOBAL32 CURSORICON_Load32( HINSTANCE32 hInstance, LPCWSTR name,
631 int width, int height, int colors,
632 BOOL32 fCursor, UINT32 loadflags )
634 HANDLE32 handle, h = 0;
635 HANDLE32 hRsrc;
636 CURSORICONDIRENTRY dirEntry;
637 LPBYTE bits;
639 if (!(loadflags & LR_LOADFROMFILE))
641 if (!hInstance) /* OEM cursor/icon */
643 WORD resid;
644 if(HIWORD(name))
646 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
647 if( ansi[0]=='#') /*Check for '#xxx' name */
649 resid = atoi(ansi+1);
650 HeapFree( GetProcessHeap(), 0, ansi );
652 else
654 HeapFree( GetProcessHeap(), 0, ansi );
655 return 0;
658 else resid = LOWORD(name);
659 return OBM_LoadCursorIcon(resid, fCursor);
662 /* Find the best entry in the directory */
664 if (!CURSORICON_LoadDirEntry32( hInstance, name, width, height,
665 colors, fCursor, &dirEntry ) ) return 0;
666 /* Load the resource */
668 if (!(hRsrc = FindResource32W(hInstance,MAKEINTRESOURCE32W(dirEntry.icon.wResId),
669 fCursor ? RT_CURSOR32W : RT_ICON32W ))) return 0;
670 if (!(handle = LoadResource32( hInstance, hRsrc ))) return 0;
671 /* Hack to keep LoadCursor/Icon32() from spawning multiple
672 * copies of the same object.
674 #define pRsrcEntry ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)
675 if( pRsrcEntry->ResourceHandle ) return pRsrcEntry->ResourceHandle;
676 bits = (LPBYTE)LockResource32( handle );
677 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry.icon.dwBytesInRes,
678 !fCursor, 0x00030000, width, height, loadflags);
679 pRsrcEntry->ResourceHandle = h;
681 else
683 CURSORICONDIR *res;
684 LPBYTE *ptr;
685 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &res, &ptr))
686 return 0;
687 if (fCursor)
688 dirEntry = *(CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(res, width, height, 1);
689 else
690 dirEntry = *(CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(res, width, height, colors);
691 bits = ptr[dirEntry.icon.wResId-1];
692 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry.icon.dwBytesInRes,
693 !fCursor, 0x00030000, width, height, loadflags);
694 HeapFree( GetProcessHeap(), 0, res );
695 HeapFree( GetProcessHeap(), 0, ptr );
697 return h;
698 #undef pRsrcEntry
702 /***********************************************************************
703 * CURSORICON_Copy
705 * Make a copy of a cursor or icon.
707 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
709 char *ptrOld, *ptrNew;
710 int size;
711 HGLOBAL16 hNew;
713 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
714 if (!(hInstance = GetExePtr( hInstance ))) return 0;
715 size = GlobalSize16( handle );
716 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
717 FarSetOwner( hNew, hInstance );
718 ptrNew = (char *)GlobalLock16( hNew );
719 memcpy( ptrNew, ptrOld, size );
720 GlobalUnlock16( handle );
721 GlobalUnlock16( hNew );
722 return hNew;
725 /***********************************************************************
726 * CURSORICON_IconToCursor
728 * Converts bitmap to mono and truncates if icon is too large (should
729 * probably do StretchBlt() instead).
731 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL32 bSemiTransparent)
733 HCURSOR16 hRet = 0;
734 CURSORICONINFO *pIcon = NULL;
735 HTASK16 hTask = GetCurrentTask();
736 TDB* pTask = (TDB *)GlobalLock16(hTask);
738 if(hIcon && pTask)
739 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
740 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
741 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
742 else
744 BYTE pAndBits[128];
745 BYTE pXorBits[128];
746 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
747 BYTE* psPtr, *pxbPtr = pXorBits;
748 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
749 BYTE* pbc = NULL;
751 COLORREF col;
752 CURSORICONINFO cI;
754 TRACE(icon, "[%04x] %ix%i %ibpp (bogus %ibps)\n",
755 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
757 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
758 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
759 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
761 memset(pXorBits, 0, 128);
762 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
763 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
764 cI.nWidth = 32; cI.nHeight = 32;
765 cI.nWidthBytes = 4; /* 32x1bpp */
767 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
768 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
770 for( iy = 0; iy < maxy; iy++ )
772 unsigned shift = iy % 2;
774 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
775 (and_width > 4) ? 4 : and_width );
776 for( ix = 0; ix < maxx; ix++ )
778 if( bSemiTransparent && ((ix+shift)%2) )
780 /* set AND bit, XOR bit stays 0 */
782 pbc = pAndBits + iy * 4 + ix/8;
783 *pbc |= 0x80 >> (ix%8);
785 else
787 /* keep AND bit, set XOR bit */
789 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
790 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
791 col = COLOR_ToLogical(val);
792 if( (GetRValue(col) + GetGValue(col) + GetBValue(col)) > 0x180 )
794 pbc = pxbPtr + ix/8;
795 *pbc |= 0x80 >> (ix%8);
799 psPtr += xor_width;
800 pxbPtr += 4;
803 hRet = CreateCursorIconIndirect( pTask->hInstance , &cI, pAndBits, pXorBits);
805 if( !hRet ) /* fall back on default drag cursor */
806 hRet = CURSORICON_Copy( pTask->hInstance ,
807 CURSORICON_Load16(0,MAKEINTRESOURCE16(OCR_DRAGOBJECT),
808 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0) );
811 return hRet;
815 /***********************************************************************
816 * LoadCursor16 (USER.173)
818 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
820 if (HIWORD(name))
821 TRACE(cursor, "%04x '%s'\n",
822 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
823 else
824 TRACE(cursor, "%04x %04x\n",
825 hInstance, LOWORD(name) );
827 return CURSORICON_Load16( hInstance, name,
828 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0);
832 /***********************************************************************
833 * LoadIcon16 (USER.174)
835 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
837 if (HIWORD(name))
838 TRACE(icon, "%04x '%s'\n",
839 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
840 else
841 TRACE(icon, "%04x %04x\n",
842 hInstance, LOWORD(name) );
844 return CURSORICON_Load16( hInstance, name,
845 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
846 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE, 0);
850 /***********************************************************************
851 * CreateCursor16 (USER.406)
853 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
854 INT16 xHotSpot, INT16 yHotSpot,
855 INT16 nWidth, INT16 nHeight,
856 LPCVOID lpANDbits, LPCVOID lpXORbits )
858 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
860 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
861 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
862 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
866 /***********************************************************************
867 * CreateCursor32 (USER32.67)
869 HCURSOR32 WINAPI CreateCursor32( HINSTANCE32 hInstance,
870 INT32 xHotSpot, INT32 yHotSpot,
871 INT32 nWidth, INT32 nHeight,
872 LPCVOID lpANDbits, LPCVOID lpXORbits )
874 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
876 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
877 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
878 return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
882 /***********************************************************************
883 * CreateIcon16 (USER.407)
885 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
886 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
887 LPCVOID lpANDbits, LPCVOID lpXORbits )
889 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
891 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
892 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
893 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
897 /***********************************************************************
898 * CreateIcon32 (USER32.75)
900 HICON32 WINAPI CreateIcon32( HINSTANCE32 hInstance, INT32 nWidth,
901 INT32 nHeight, BYTE bPlanes, BYTE bBitsPixel,
902 LPCVOID lpANDbits, LPCVOID lpXORbits )
904 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
906 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
907 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
908 return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
912 /***********************************************************************
913 * CreateCursorIconIndirect (USER.408)
915 HGLOBAL16 WINAPI CreateCursorIconIndirect( HINSTANCE16 hInstance,
916 CURSORICONINFO *info,
917 LPCVOID lpANDbits,
918 LPCVOID lpXORbits )
920 HGLOBAL16 handle;
921 char *ptr;
922 int sizeAnd, sizeXor;
924 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
925 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
926 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
927 sizeXor = info->nHeight * info->nWidthBytes;
928 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
929 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
930 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
931 return 0;
932 if (hInstance) FarSetOwner( handle, hInstance );
933 ptr = (char *)GlobalLock16( handle );
934 memcpy( ptr, info, sizeof(*info) );
935 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
936 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
937 GlobalUnlock16( handle );
938 return handle;
942 /***********************************************************************
943 * CopyIcon16 (USER.368)
945 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
947 TRACE(icon, "%04x %04x\n", hInstance, hIcon );
948 return CURSORICON_Copy( hInstance, hIcon );
952 /***********************************************************************
953 * CopyIcon32 (USER32.60)
955 HICON32 WINAPI CopyIcon32( HICON32 hIcon )
957 HTASK16 hTask = GetCurrentTask ();
958 TDB* pTask = (TDB *) GlobalLock16 (hTask);
959 TRACE(icon, "%04x\n", hIcon );
960 return CURSORICON_Copy( pTask->hInstance, hIcon );
964 /***********************************************************************
965 * CopyCursor16 (USER.369)
967 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
969 TRACE(cursor, "%04x %04x\n", hInstance, hCursor );
970 return CURSORICON_Copy( hInstance, hCursor );
974 /***********************************************************************
975 * DestroyIcon16 (USER.457)
977 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
979 TRACE(icon, "%04x\n", hIcon );
980 /* FIXME: should check for OEM/global heap icon here */
981 return (FreeResource16( hIcon ) == 0);
985 /***********************************************************************
986 * DestroyIcon32 (USER32.133)
988 BOOL32 WINAPI DestroyIcon32( HICON32 hIcon )
990 TRACE(icon, "%04x\n", hIcon );
991 /* FIXME: should check for OEM/global heap icon here */
992 /* Unlike DestroyIcon16, only icons created with CreateIcon32
993 are valid for DestroyIcon32, so don't use FreeResource32 */
994 return (GlobalFree16( hIcon ) == 0);
998 /***********************************************************************
999 * DestroyCursor16 (USER.458)
1001 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1003 TRACE(cursor, "%04x\n", hCursor );
1004 if (FreeResource16( hCursor ) == 0)
1005 return TRUE;
1006 else
1007 /* I believe this very same line should be added for every function
1008 where appears the comment:
1010 "FIXME: should check for OEM/global heap cursor here"
1012 which are most (all?) the ones that call FreeResource, at least
1013 in this module. Maybe this should go to a wrapper to avoid
1014 repetition. Or: couldn't it go to FreeResoutce itself?
1016 I'll let this to someone savvy on the subject.
1018 return (GlobalFree16 (hCursor) == 0);
1022 /***********************************************************************
1023 * DestroyCursor32 (USER32.132)
1025 BOOL32 WINAPI DestroyCursor32( HCURSOR32 hCursor )
1027 TRACE(cursor, "%04x\n", hCursor );
1028 /* FIXME: should check for OEM/global heap cursor here */
1029 /* Unlike DestroyCursor16, only cursors created with CreateCursor32
1030 are valid for DestroyCursor32, so don't use FreeResource32 */
1031 return (GlobalFree16( hCursor ) == 0);
1035 /***********************************************************************
1036 * DrawIcon16 (USER.84)
1038 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1040 return DrawIcon32( hdc, x, y, hIcon );
1044 /***********************************************************************
1045 * DrawIcon32 (USER32.159)
1047 BOOL32 WINAPI DrawIcon32( HDC32 hdc, INT32 x, INT32 y, HICON32 hIcon )
1049 CURSORICONINFO *ptr;
1050 HDC32 hMemDC;
1051 HBITMAP32 hXorBits, hAndBits;
1052 COLORREF oldFg, oldBg;
1054 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1055 if (!(hMemDC = CreateCompatibleDC32( hdc ))) return FALSE;
1056 hAndBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, 1, 1,
1057 (char *)(ptr+1) );
1058 hXorBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1059 ptr->bBitsPerPixel, (char *)(ptr + 1)
1060 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1061 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
1062 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
1064 if (hXorBits && hAndBits)
1066 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
1067 BitBlt32( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1068 SelectObject32( hMemDC, hXorBits );
1069 BitBlt32(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1070 SelectObject32( hMemDC, hBitTemp );
1072 DeleteDC32( hMemDC );
1073 if (hXorBits) DeleteObject32( hXorBits );
1074 if (hAndBits) DeleteObject32( hAndBits );
1075 GlobalUnlock16( hIcon );
1076 SetTextColor32( hdc, oldFg );
1077 SetBkColor32( hdc, oldBg );
1078 return TRUE;
1082 /***********************************************************************
1083 * DumpIcon (USER.459)
1085 DWORD WINAPI DumpIcon( SEGPTR pInfo, WORD *lpLen,
1086 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1088 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1089 int sizeAnd, sizeXor;
1091 if (!info) return 0;
1092 sizeXor = info->nHeight * info->nWidthBytes;
1093 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1094 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1095 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1096 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1097 return MAKELONG( sizeXor, sizeXor );
1101 /***********************************************************************
1102 * CURSORICON_SetCursor
1104 * Change the X cursor. Helper function for SetCursor() and ShowCursor().
1105 * The Xlib critical section must be entered before calling this function.
1107 static BOOL32 CURSORICON_SetCursor( HCURSOR16 hCursor )
1109 Pixmap pixmapBits, pixmapMask, pixmapAll;
1110 XColor fg, bg;
1111 Cursor cursor = None;
1113 if (!hCursor) /* Create an empty cursor */
1115 static const char data[] = { 0 };
1117 bg.red = bg.green = bg.blue = 0x0000;
1118 pixmapBits = XCreateBitmapFromData( display, rootWindow, data, 1, 1 );
1119 if (pixmapBits)
1121 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapBits,
1122 &bg, &bg, 0, 0 );
1123 XFreePixmap( display, pixmapBits );
1126 else /* Create the X cursor from the bits */
1128 CURSORICONINFO *ptr;
1129 XImage *image;
1131 if (!(ptr = (CURSORICONINFO*)GlobalLock16( hCursor ))) return FALSE;
1132 if (ptr->bPlanes * ptr->bBitsPerPixel != 1)
1134 WARN(cursor, "Cursor %04x has more than 1 bpp!\n", hCursor );
1135 return FALSE;
1138 /* Create a pixmap and transfer all the bits to it */
1140 /* NOTE: Following hack works, but only because XFree depth
1141 * 1 images really use 1 bit/pixel (and so the same layout
1142 * as the Windows cursor data). Perhaps use a more generic
1143 * algorithm here.
1145 pixmapAll = XCreatePixmap( display, rootWindow,
1146 ptr->nWidth, ptr->nHeight * 2, 1 );
1147 image = XCreateImage( display, DefaultVisualOfScreen(screen),
1148 1, ZPixmap, 0, (char *)(ptr + 1), ptr->nWidth,
1149 ptr->nHeight * 2, 16, ptr->nWidthBytes);
1150 if (image)
1152 image->byte_order = MSBFirst;
1153 image->bitmap_bit_order = MSBFirst;
1154 image->bitmap_unit = 16;
1155 _XInitImageFuncPtrs(image);
1156 if (pixmapAll)
1157 XPutImage( display, pixmapAll, BITMAP_monoGC, image,
1158 0, 0, 0, 0, ptr->nWidth, ptr->nHeight * 2 );
1159 image->data = NULL;
1160 XDestroyImage( image );
1163 /* Now create the 2 pixmaps for bits and mask */
1165 pixmapBits = XCreatePixmap( display, rootWindow,
1166 ptr->nWidth, ptr->nHeight, 1 );
1167 pixmapMask = XCreatePixmap( display, rootWindow,
1168 ptr->nWidth, ptr->nHeight, 1 );
1170 /* Make sure everything went OK so far */
1172 if (pixmapBits && pixmapMask && pixmapAll)
1174 /* We have to do some magic here, as cursors are not fully
1175 * compatible between Windows and X11. Under X11, there
1176 * are only 3 possible color cursor: black, white and
1177 * masked. So we map the 4th Windows color (invert the
1178 * bits on the screen) to black. This require some boolean
1179 * arithmetic:
1181 * Windows | X11
1182 * Xor And Result | Bits Mask Result
1183 * 0 0 black | 0 1 background
1184 * 0 1 no change | X 0 no change
1185 * 1 0 white | 1 1 foreground
1186 * 1 1 inverted | 0 1 background
1188 * which gives:
1189 * Bits = 'Xor' and not 'And'
1190 * Mask = 'Xor' or not 'And'
1192 * FIXME: apparently some servers do support 'inverted' color.
1193 * I don't know if it's correct per the X spec, but maybe
1194 * we ought to take advantage of it. -- AJ
1196 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
1197 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
1198 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
1199 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
1200 XSetFunction( display, BITMAP_monoGC, GXandReverse );
1201 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
1202 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
1203 XSetFunction( display, BITMAP_monoGC, GXorReverse );
1204 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
1205 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
1206 XSetFunction( display, BITMAP_monoGC, GXcopy );
1207 fg.red = fg.green = fg.blue = 0xffff;
1208 bg.red = bg.green = bg.blue = 0x0000;
1209 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapMask,
1210 &fg, &bg, ptr->ptHotSpot.x, ptr->ptHotSpot.y );
1213 /* Now free everything */
1215 if (pixmapAll) XFreePixmap( display, pixmapAll );
1216 if (pixmapBits) XFreePixmap( display, pixmapBits );
1217 if (pixmapMask) XFreePixmap( display, pixmapMask );
1218 GlobalUnlock16( hCursor );
1221 if (cursor == None) return FALSE;
1222 if (CURSORICON_XCursor != None) XFreeCursor( display, CURSORICON_XCursor );
1223 CURSORICON_XCursor = cursor;
1225 if (rootWindow != DefaultRootWindow(display))
1227 /* Set the cursor on the desktop window */
1228 XDefineCursor( display, rootWindow, cursor );
1230 else
1232 /* Set the same cursor for all top-level windows */
1233 HWND32 hwnd = GetWindow32( GetDesktopWindow32(), GW_CHILD );
1234 while(hwnd)
1236 Window win = WIN_GetXWindow( hwnd );
1237 if (win && win!=DefaultRootWindow(display))
1238 XDefineCursor( display, win, cursor );
1239 hwnd = GetWindow32( hwnd, GW_HWNDNEXT );
1242 return TRUE;
1246 /***********************************************************************
1247 * SetCursor16 (USER.69)
1249 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1251 return (HCURSOR16)SetCursor32( hCursor );
1255 /***********************************************************************
1256 * SetCursor32 (USER32.472)
1257 * RETURNS:
1258 * A handle to the previous cursor shape.
1260 HCURSOR32 WINAPI SetCursor32(
1261 HCURSOR32 hCursor /* Handle of cursor to show */
1263 HCURSOR32 hOldCursor;
1265 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1266 TRACE(cursor, "%04x\n", hCursor );
1267 hOldCursor = hActiveCursor;
1268 hActiveCursor = hCursor;
1269 /* Change the cursor shape only if it is visible */
1270 if (CURSOR_ShowCount >= 0)
1272 EnterCriticalSection( &X11DRV_CritSection );
1273 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1274 LeaveCriticalSection( &X11DRV_CritSection );
1276 return hOldCursor;
1280 /***********************************************************************
1281 * SetCursorPos16 (USER.70)
1283 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1285 SetCursorPos32( x, y );
1289 /***********************************************************************
1290 * SetCursorPos32 (USER32.474)
1292 BOOL32 WINAPI SetCursorPos32( INT32 x, INT32 y )
1294 TRACE(cursor, "x=%d y=%d\n", x, y );
1295 TSXWarpPointer( display, rootWindow, rootWindow, 0, 0, 0, 0, x, y );
1296 return TRUE;
1300 /***********************************************************************
1301 * ShowCursor16 (USER.71)
1303 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1305 return ShowCursor32( bShow );
1309 /***********************************************************************
1310 * ShowCursor32 (USER32.530)
1312 INT32 WINAPI ShowCursor32( BOOL32 bShow )
1314 TRACE(cursor, "%d, count=%d\n",
1315 bShow, CURSOR_ShowCount );
1317 EnterCriticalSection( &X11DRV_CritSection );
1318 if (bShow)
1320 if (++CURSOR_ShowCount == 0) /* Show it */
1321 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1323 else
1325 if (--CURSOR_ShowCount == -1) /* Hide it */
1326 CALL_LARGE_STACK( CURSORICON_SetCursor, 0 );
1328 LeaveCriticalSection( &X11DRV_CritSection );
1329 return CURSOR_ShowCount;
1333 /***********************************************************************
1334 * GetCursor16 (USER.247)
1336 HCURSOR16 WINAPI GetCursor16(void)
1338 return hActiveCursor;
1342 /***********************************************************************
1343 * GetCursor32 (USER32.227)
1345 HCURSOR32 WINAPI GetCursor32(void)
1347 return hActiveCursor;
1351 /***********************************************************************
1352 * ClipCursor16 (USER.16)
1354 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1356 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1357 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1358 return TRUE;
1362 /***********************************************************************
1363 * ClipCursor32 (USER32.53)
1365 BOOL32 WINAPI ClipCursor32( const RECT32 *rect )
1367 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1368 else CopyRect32( &CURSOR_ClipRect, rect );
1369 return TRUE;
1373 /***********************************************************************
1374 * GetCursorPos16 (USER.17)
1376 void WINAPI GetCursorPos16( POINT16 *pt )
1378 Window root, child;
1379 int rootX, rootY, childX, childY;
1380 unsigned int mousebut;
1382 if (!pt) return;
1383 if (!TSXQueryPointer( display, rootWindow, &root, &child,
1384 &rootX, &rootY, &childX, &childY, &mousebut ))
1385 pt->x = pt->y = 0;
1386 else
1388 pt->x = childX;
1389 pt->y = childY;
1390 if (mousebut & Button1Mask)
1391 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1392 else
1393 MouseButtonsStates[0] = FALSE;
1394 if (mousebut & Button2Mask)
1395 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1396 else
1397 MouseButtonsStates[1] = FALSE;
1398 if (mousebut & Button3Mask)
1399 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1400 else
1401 MouseButtonsStates[2] = FALSE;
1403 TRACE(cursor, "ret=%d,%d\n", pt->x, pt->y );
1407 /***********************************************************************
1408 * GetCursorPos32 (USER32.229)
1410 void WINAPI GetCursorPos32( POINT32 *pt )
1412 POINT16 pt16;
1413 GetCursorPos16( &pt16 );
1414 if (pt) CONV_POINT16TO32( &pt16, pt );
1418 /***********************************************************************
1419 * GetClipCursor16 (USER.309)
1421 void WINAPI GetClipCursor16( RECT16 *rect )
1423 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1427 /***********************************************************************
1428 * GetClipCursor32 (USER32.221)
1430 void WINAPI GetClipCursor32( RECT32 *rect )
1432 if (rect) CopyRect32( rect, &CURSOR_ClipRect );
1435 /**********************************************************************
1436 * LookupIconIdFromDirectoryEx16 (USER.364)
1438 * FIXME: exact parameter sizes
1440 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1441 INT16 width, INT16 height, UINT16 cFlag )
1443 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1444 UINT16 retVal = 0;
1445 if( dir && !dir->idReserved && (dir->idType & 3) )
1447 int colors = (cFlag & LR_MONOCHROME) ? 2 : COLOR_GetSystemPaletteSize();
1448 if( bIcon )
1450 ICONDIRENTRY* entry;
1451 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1452 if( entry ) retVal = entry->wResId;
1454 else
1456 CURSORDIRENTRY* entry;
1457 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1458 if( entry ) retVal = entry->wResId;
1461 else WARN(cursor, "invalid resource directory\n");
1462 return retVal;
1465 /**********************************************************************
1466 * LookupIconIdFromDirectoryEx32 (USER32.380)
1468 INT32 WINAPI LookupIconIdFromDirectoryEx32( LPBYTE dir, BOOL32 bIcon,
1469 INT32 width, INT32 height, UINT32 cFlag )
1471 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1474 /**********************************************************************
1475 * LookupIconIdFromDirectory (USER.???)
1477 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1479 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1480 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1481 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1484 /**********************************************************************
1485 * LookupIconIdFromDirectory (USER32.379)
1487 INT32 WINAPI LookupIconIdFromDirectory32( LPBYTE dir, BOOL32 bIcon )
1489 return LookupIconIdFromDirectoryEx32( dir, bIcon,
1490 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1491 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1494 /**********************************************************************
1495 * GetIconID (USER.455)
1497 WORD WINAPI GetIconID( HGLOBAL16 hResource, DWORD resType )
1499 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1501 TRACE(cursor, "hRes=%04x, entries=%i\n",
1502 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1504 switch(resType)
1506 case RT_CURSOR16:
1507 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1508 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1509 case RT_ICON16:
1510 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1511 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1512 default:
1513 WARN(cursor, "invalid res type %ld\n", resType );
1515 return 0;
1518 /**********************************************************************
1519 * LoadCursorIconHandler (USER.336)
1521 * Supposed to load resources of Windows 2.x applications.
1523 HGLOBAL16 WINAPI LoadCursorIconHandler( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1525 FIXME(cursor,"(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1526 hResource, hModule, hRsrc);
1527 return (HGLOBAL16)0;
1530 /**********************************************************************
1531 * LoadDIBIconHandler (USER.357)
1533 * RT_ICON resource loader, installed by USER_SignalProc when module
1534 * is initialized.
1536 HGLOBAL16 WINAPI LoadDIBIconHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1538 /* If hResource is zero we must allocate a new memory block, if it's
1539 * non-zero but GlobalLock() returns NULL then it was discarded and
1540 * we have to recommit some memory, otherwise we just need to check
1541 * the block size. See LoadProc() in 16-bit SDK for more.
1544 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1545 if( hMemObj )
1547 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1548 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1549 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1550 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1552 return hMemObj;
1555 /**********************************************************************
1556 * LoadDIBCursorHandler (USER.356)
1558 * RT_CURSOR resource loader. Same as above.
1560 HGLOBAL16 WINAPI LoadDIBCursorHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1562 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1563 if( hMemObj )
1565 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1566 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1567 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1568 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1570 return hMemObj;
1573 /**********************************************************************
1574 * LoadIconHandler (USER.456)
1576 HICON16 WINAPI LoadIconHandler( HGLOBAL16 hResource, BOOL16 bNew )
1578 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1580 TRACE(cursor,"hRes=%04x\n",hResource);
1582 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1583 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1586 /***********************************************************************
1587 * LoadCursorW (USER32.362)
1589 HCURSOR32 WINAPI LoadCursor32W(HINSTANCE32 hInstance, LPCWSTR name)
1591 return CURSORICON_Load32( hInstance, name,
1592 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0);
1595 /***********************************************************************
1596 * LoadCursorA (USER32.359)
1598 HCURSOR32 WINAPI LoadCursor32A(HINSTANCE32 hInstance, LPCSTR name)
1600 HCURSOR32 res=0;
1601 if(!HIWORD(name))
1602 return LoadCursor32W(hInstance,(LPCWSTR)name);
1603 else
1605 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1606 res = LoadCursor32W(hInstance, uni);
1607 HeapFree( GetProcessHeap(), 0, uni);
1609 return res;
1611 /***********************************************************************
1612 * LoadCursorFromFile32W (USER32.361)
1614 HCURSOR32 WINAPI LoadCursorFromFile32W (LPCWSTR name)
1616 return LoadImage32W(0, name, IMAGE_CURSOR, SYSMETRICS_CXCURSOR,
1617 SYSMETRICS_CYCURSOR, LR_LOADFROMFILE);
1620 /***********************************************************************
1621 * LoadCursorFromFile32A (USER32.360)
1623 HCURSOR32 WINAPI LoadCursorFromFile32A (LPCSTR name)
1625 HCURSOR32 hcur;
1626 LPWSTR u_name = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1627 hcur = LoadCursorFromFile32W(u_name);
1628 HeapFree( GetProcessHeap(), 0, u_name );
1629 return hcur;
1632 /***********************************************************************
1633 * LoadIconW (USER32.364)
1635 HICON32 WINAPI LoadIcon32W(HINSTANCE32 hInstance, LPCWSTR name)
1637 return CURSORICON_Load32( hInstance, name,
1638 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
1639 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE, 0);
1642 /***********************************************************************
1643 * LoadIconA (USER32.363)
1645 HICON32 WINAPI LoadIcon32A(HINSTANCE32 hInstance, LPCSTR name)
1647 HICON32 res=0;
1649 if( !HIWORD(name) )
1650 return LoadIcon32W(hInstance, (LPCWSTR)name);
1651 else
1653 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1654 res = LoadIcon32W( hInstance, uni );
1655 HeapFree( GetProcessHeap(), 0, uni );
1657 return res;
1660 /**********************************************************************
1661 * GetIconInfo (USER32.242)
1663 BOOL32 WINAPI GetIconInfo(HICON32 hIcon,LPICONINFO iconinfo) {
1664 CURSORICONINFO *ciconinfo;
1666 ciconinfo = GlobalLock16(hIcon);
1667 if (!ciconinfo)
1668 return FALSE;
1669 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1670 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1671 iconinfo->fIcon = TRUE; /* hmm */
1673 iconinfo->hbmColor = CreateBitmap32 ( ciconinfo->nWidth, ciconinfo->nHeight,
1674 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1675 (char *)(ciconinfo + 1)
1676 + ciconinfo->nHeight *
1677 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1678 iconinfo->hbmMask = CreateBitmap32 ( ciconinfo->nWidth, ciconinfo->nHeight,
1679 1, 1, (char *)(ciconinfo + 1));
1681 GlobalUnlock16(hIcon);
1683 return TRUE;
1686 /**********************************************************************
1687 * CreateIconIndirect (USER32.78)
1689 HICON32 WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1690 BITMAPOBJ *bmpXor,*bmpAnd;
1691 HICON32 hObj;
1692 int sizeXor,sizeAnd;
1694 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1695 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1697 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1698 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1700 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1701 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1702 if (hObj)
1704 CURSORICONINFO *info;
1706 info = (CURSORICONINFO *)GlobalLock16( hObj );
1707 info->ptHotSpot.x = iconinfo->xHotspot;
1708 info->ptHotSpot.y = iconinfo->yHotspot;
1709 info->nWidth = bmpXor->bitmap.bmWidth;
1710 info->nHeight = bmpXor->bitmap.bmHeight;
1711 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1712 info->bPlanes = bmpXor->bitmap.bmPlanes;
1713 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1715 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1717 GetBitmapBits32( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1718 GetBitmapBits32( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1719 GlobalUnlock16( hObj );
1721 return hObj;
1725 /**********************************************************************
1727 DrawIconEx16 (USER.394)
1729 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1730 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1731 HBRUSH16 hbr, UINT16 flags)
1733 return DrawIconEx32(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1734 istep, hbr, flags);
1738 /******************************************************************************
1739 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1741 * NOTES
1742 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1744 * PARAMS
1745 * hdc [I] Handle to device context
1746 * x0 [I] X coordinate of upper left corner
1747 * y0 [I] Y coordinate of upper left corner
1748 * hIcon [I] Handle to icon to draw
1749 * cxWidth [I] Width of icon
1750 * cyWidth [I] Height of icon
1751 * istep [I] Index of frame in animated cursor
1752 * hbr [I] Handle to background brush
1753 * flags [I] Icon-drawing flags
1755 * RETURNS
1756 * Success: TRUE
1757 * Failure: FALSE
1759 BOOL32 WINAPI DrawIconEx32( HDC32 hdc, INT32 x0, INT32 y0, HICON32 hIcon,
1760 INT32 cxWidth, INT32 cyWidth, UINT32 istep,
1761 HBRUSH32 hbr, UINT32 flags )
1763 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1764 HDC32 hDC_off = 0, hMemDC = CreateCompatibleDC32 (hdc);
1765 BOOL32 result = FALSE, DoOffscreen = FALSE;
1766 HBITMAP32 hB_off = 0, hOld = 0;
1768 if (!ptr) return FALSE;
1770 if (istep)
1771 FIXME(icon, "Ignoring istep=%d\n", istep);
1772 if (flags & DI_COMPAT)
1773 FIXME(icon, "Ignoring flag DI_COMPAT\n");
1775 /* Calculate the size of the destination image. */
1776 if (cxWidth == 0)
1778 if (flags & DI_DEFAULTSIZE)
1779 cxWidth = GetSystemMetrics32 (SM_CXICON);
1780 else
1781 cxWidth = ptr->nWidth;
1783 if (cyWidth == 0)
1785 if (flags & DI_DEFAULTSIZE)
1786 cyWidth = GetSystemMetrics32 (SM_CYICON);
1787 else
1788 cyWidth = ptr->nHeight;
1791 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1792 STOCK_HOLLOW_BRUSH)))
1794 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1795 if (object)
1797 UINT16 magic = object->wMagic;
1798 GDI_HEAP_UNLOCK(hbr);
1799 DoOffscreen = magic == BRUSH_MAGIC;
1802 if (DoOffscreen) {
1803 RECT32 r = {0, 0, cxWidth, cxWidth};
1805 hDC_off = CreateCompatibleDC32(hdc);
1806 hB_off = CreateCompatibleBitmap32(hdc, cxWidth, cyWidth);
1807 if (hDC_off && hB_off) {
1808 hOld = SelectObject32(hDC_off, hB_off);
1809 FillRect32(hDC_off, &r, hbr);
1813 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1815 HBITMAP32 hXorBits, hAndBits;
1816 COLORREF oldFg, oldBg;
1817 INT32 nStretchMode;
1819 nStretchMode = SetStretchBltMode32 (hdc, STRETCH_DELETESCANS);
1821 hXorBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
1822 ptr->bPlanes, ptr->bBitsPerPixel,
1823 (char *)(ptr + 1)
1824 + ptr->nHeight *
1825 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1826 hAndBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
1827 1, 1, (char *)(ptr+1) );
1828 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
1829 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
1831 if (hXorBits && hAndBits)
1833 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
1834 if (flags & DI_MASK)
1836 if (DoOffscreen)
1837 StretchBlt32 (hDC_off, 0, 0, cxWidth, cyWidth,
1838 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1839 else
1840 StretchBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1841 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1843 SelectObject32( hMemDC, hXorBits );
1844 if (flags & DI_IMAGE)
1846 if (DoOffscreen)
1847 StretchBlt32 (hDC_off, 0, 0, cxWidth, cyWidth,
1848 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1849 else
1850 StretchBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1851 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1853 SelectObject32( hMemDC, hBitTemp );
1854 result = TRUE;
1857 SetTextColor32( hdc, oldFg );
1858 SetBkColor32( hdc, oldBg );
1859 if (hXorBits) DeleteObject32( hXorBits );
1860 if (hAndBits) DeleteObject32( hAndBits );
1861 SetStretchBltMode32 (hdc, nStretchMode);
1862 if (DoOffscreen) {
1863 BitBlt32(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
1864 SelectObject32(hDC_off, hOld);
1867 if (hMemDC) DeleteDC32( hMemDC );
1868 if (hDC_off) DeleteDC32(hDC_off);
1869 if (hB_off) DeleteObject32(hB_off);
1870 GlobalUnlock16( hIcon );
1871 return result;