Moved more things to the X11 driver.
[wine/multimedia.git] / objects / cursoricon.c
blob79022f28ae165df339d641ea64df59c8480a4aa0
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 "cursoricon.h"
40 #include "dc.h"
41 #include "gdi.h"
42 #include "sysmetrics.h"
43 #include "global.h"
44 #include "module.h"
45 #include "win.h"
46 #include "debug.h"
47 #include "task.h"
48 #include "user.h"
49 #include "input.h"
50 #include "display.h"
51 #include "message.h"
52 #include "winerror.h"
54 static HCURSOR32 hActiveCursor = 0; /* Active cursor */
55 static INT32 CURSOR_ShowCount = 0; /* Cursor display count */
56 static RECT32 CURSOR_ClipRect; /* Cursor clipping rect */
58 /**********************************************************************
59 * CURSORICON_FindBestIcon
61 * Find the icon closest to the requested size and number of colors.
63 static ICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
64 int height, int colors )
66 int i, maxcolors, maxwidth, maxheight;
67 ICONDIRENTRY *entry, *bestEntry = NULL;
69 if (dir->idCount < 1)
71 WARN(icon, "Empty directory!\n" );
72 return NULL;
74 if (dir->idCount == 1) return &dir->idEntries[0].icon; /* No choice... */
76 /* First find the exact size with less colors */
78 maxcolors = 0;
79 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
80 if ((entry->bWidth == width) && (entry->bHeight == height) &&
81 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
83 bestEntry = entry;
84 maxcolors = entry->bColorCount;
86 if (bestEntry) return bestEntry;
88 /* First find the exact size with more colors */
90 maxcolors = 255;
91 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
92 if ((entry->bWidth == width) && (entry->bHeight == height) &&
93 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
95 bestEntry = entry;
96 maxcolors = entry->bColorCount;
98 if (bestEntry) return bestEntry;
100 /* Now find a smaller one with less colors */
102 maxcolors = 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 smaller one with more colors */
117 maxcolors = 255;
118 maxwidth = maxheight = 0;
119 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
120 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
121 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
122 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
124 bestEntry = entry;
125 maxwidth = entry->bWidth;
126 maxheight = entry->bHeight;
127 maxcolors = entry->bColorCount;
129 if (bestEntry) return bestEntry;
131 /* Now find a larger one with less colors */
133 maxcolors = 0;
134 maxwidth = maxheight = 255;
135 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
136 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
137 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
139 bestEntry = entry;
140 maxwidth = entry->bWidth;
141 maxheight = entry->bHeight;
142 maxcolors = entry->bColorCount;
144 if (bestEntry) return bestEntry;
146 /* Now find a larger one with more colors */
148 maxcolors = maxwidth = maxheight = 255;
149 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
150 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
151 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
153 bestEntry = entry;
154 maxwidth = entry->bWidth;
155 maxheight = entry->bHeight;
156 maxcolors = entry->bColorCount;
159 return bestEntry;
163 /**********************************************************************
164 * CURSORICON_FindBestCursor
166 * Find the cursor closest to the requested size.
167 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
168 * ignored too
170 static CURSORDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
171 int width, int height, int color)
173 int i, maxwidth, maxheight;
174 CURSORDIRENTRY *entry, *bestEntry = NULL;
176 if (dir->idCount < 1)
178 WARN(cursor, "Empty directory!\n" );
179 return NULL;
181 if (dir->idCount == 1) return &dir->idEntries[0].cursor; /* No choice... */
183 /* First find the largest one smaller than or equal to the requested size*/
185 maxwidth = maxheight = 0;
186 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
187 if ((entry->wWidth <= width) && (entry->wHeight <= height) &&
188 (entry->wWidth > maxwidth) && (entry->wHeight > maxheight) &&
189 (entry->wBitCount == 1))
191 bestEntry = entry;
192 maxwidth = entry->wWidth;
193 maxheight = entry->wHeight;
195 if (bestEntry) return bestEntry;
197 /* Now find the smallest one larger than the requested size */
199 maxwidth = maxheight = 255;
200 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
201 if ((entry->wWidth < maxwidth) && (entry->wHeight < maxheight) &&
202 (entry->wBitCount == 1))
204 bestEntry = entry;
205 maxwidth = entry->wWidth;
206 maxheight = entry->wHeight;
209 return bestEntry;
212 /*********************************************************************
213 * The main purpose of this function is to create fake resource directory
214 * and fake resource entries. There are several reasons for this:
215 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
216 * fields
217 * There are some "bad" cursor files which do not have
218 * bColorCount initialized but instead one must read this info
219 * directly from corresponding DIB sections
220 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
222 BOOL32 CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL32 fCursor,
223 CURSORICONDIR **res, LPBYTE **ptr)
225 LPBYTE _free;
226 CURSORICONFILEDIR *bits;
227 int entries, size, i;
229 *res = NULL;
230 *ptr = NULL;
231 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
233 /* FIXME: test for inimated icons
234 * hack to load the first icon from the *.ani file
236 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
237 { LPBYTE pos = (LPBYTE) bits;
238 FIXME (cursor,"Animated icons not correctly implemented! %p \n", bits);
240 for (;;)
241 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
242 { FIXME (cursor,"icon entry found! %p\n", bits);
243 pos+=4;
244 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
245 { goto fail;
247 bits+=2;
248 FIXME (cursor,"icon size ok %p \n", bits);
249 break;
251 pos+=2;
252 if (pos>=(LPBYTE)bits+766) goto fail;
255 if (!(entries = bits->idCount)) goto fail;
256 (int)_free = size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) *
257 (entries - 1);
258 for (i=0; i < entries; i++)
259 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
261 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
262 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
263 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
265 _free = (LPBYTE)(*res) + (int)_free;
266 memcpy((*res), bits, 6);
267 for (i=0; i<entries; i++)
269 ((LPBYTE*)(*ptr))[i] = _free;
270 if (fCursor) {
271 (*res)->idEntries[i].cursor.wWidth=bits->idEntries[i].bWidth;
272 (*res)->idEntries[i].cursor.wHeight=bits->idEntries[i].bHeight;
273 (*res)->idEntries[i].cursor.wPlanes=1;
274 (*res)->idEntries[i].cursor.wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
275 bits->idEntries[i].dwDIBOffset))->biBitCount;
276 (*res)->idEntries[i].cursor.dwBytesInRes = bits->idEntries[i].dwDIBSize;
277 (*res)->idEntries[i].cursor.wResId=i+1;
278 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
279 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
280 _free+=sizeof(POINT16);
281 } else {
282 (*res)->idEntries[i].icon.bWidth=bits->idEntries[i].bWidth;
283 (*res)->idEntries[i].icon.bHeight=bits->idEntries[i].bHeight;
284 (*res)->idEntries[i].icon.bColorCount = bits->idEntries[i].bColorCount;
285 (*res)->idEntries[i].icon.wPlanes=1;
286 (*res)->idEntries[i].icon.wBitCount= ((LPBITMAPINFOHEADER)((LPBYTE)bits +
287 bits->idEntries[i].dwDIBOffset))->biBitCount;
288 (*res)->idEntries[i].icon.dwBytesInRes = bits->idEntries[i].dwDIBSize;
289 (*res)->idEntries[i].icon.wResId=i+1;
291 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
292 (*res)->idEntries[i].icon.dwBytesInRes);
293 _free += (*res)->idEntries[i].icon.dwBytesInRes;
295 UnmapViewOfFile( bits );
296 return TRUE;
297 fail:
298 if (*res) HeapFree( GetProcessHeap(), 0, *res );
299 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
300 UnmapViewOfFile( bits );
301 return FALSE;
304 /**********************************************************************
305 * CURSORICON_LoadDirEntry16
307 * Load the icon/cursor directory for a given resource name and find the
308 * best matching entry.
310 static BOOL32 CURSORICON_LoadDirEntry16( HINSTANCE32 hInstance, SEGPTR name,
311 INT32 width, INT32 height, INT32 colors,
312 BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
314 HRSRC16 hRsrc;
315 HGLOBAL16 hMem;
316 CURSORICONDIR *dir;
317 CURSORICONDIRENTRY *entry = NULL;
319 if (!(hRsrc = FindResource16( hInstance, name,
320 fCursor ? RT_GROUP_CURSOR16 : RT_GROUP_ICON16 )))
321 return FALSE;
322 if (!(hMem = LoadResource16( hInstance, hRsrc ))) return FALSE;
323 if ((dir = (CURSORICONDIR *)LockResource16( hMem )))
325 if (fCursor)
326 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
327 width, height, 1);
328 else
329 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
330 width, height, colors );
331 if (entry) *dirEntry = *entry;
333 FreeResource16( hMem );
334 return (entry != NULL);
338 /**********************************************************************
339 * CURSORICON_LoadDirEntry32
341 * Load the icon/cursor directory for a given resource name and find the
342 * best matching entry.
344 static BOOL32 CURSORICON_LoadDirEntry32( HINSTANCE32 hInstance, LPCWSTR name,
345 INT32 width, INT32 height, INT32 colors,
346 BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
348 HANDLE32 hRsrc;
349 HANDLE32 hMem;
350 CURSORICONDIR *dir;
351 CURSORICONDIRENTRY *entry = NULL;
353 if (!(hRsrc = FindResource32W( hInstance, name,
354 fCursor ? RT_GROUP_CURSOR32W : RT_GROUP_ICON32W )))
355 return FALSE;
356 if (!(hMem = LoadResource32( hInstance, hRsrc ))) return FALSE;
357 if ((dir = (CURSORICONDIR*)LockResource32( hMem )))
359 if (fCursor)
360 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
361 width, height, 1);
362 else
363 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
364 width, height, colors );
365 if (entry) *dirEntry = *entry;
367 FreeResource32( hMem );
368 return (entry != NULL);
372 /**********************************************************************
373 * CURSORICON_CreateFromResource
375 * Create a cursor or icon from in-memory resource template.
377 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
378 * with cbSize parameter as well.
380 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
381 UINT32 cbSize, BOOL32 bIcon, DWORD dwVersion,
382 INT32 width, INT32 height, UINT32 loadflags )
384 int sizeAnd, sizeXor;
385 HBITMAP32 hAndBits = 0, hXorBits = 0; /* error condition for later */
386 BITMAPOBJ *bmpXor, *bmpAnd;
387 POINT16 hotspot = { 0 ,0 };
388 BITMAPINFO *bmi;
389 HDC32 hdc;
390 BOOL32 DoStretch;
391 INT32 size;
393 TRACE(cursor,"%08x (%u bytes), ver %08x, %ix%i %s %s\n",
394 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
395 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
396 if (dwVersion == 0x00020000)
398 FIXME(cursor,"\t2.xx resources are not supported\n");
399 return 0;
402 if (bIcon)
403 bmi = (BITMAPINFO *)bits;
404 else /* get the hotspot */
406 POINT16 *pt = (POINT16 *)bits;
407 hotspot = *pt;
408 bmi = (BITMAPINFO *)(pt + 1);
410 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
412 if (!width) width = bmi->bmiHeader.biWidth;
413 if (!height) height = bmi->bmiHeader.biHeight/2;
414 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
415 (bmi->bmiHeader.biWidth != width);
417 /* Check bitmap header */
419 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
420 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
421 bmi->bmiHeader.biCompression != BI_RGB) )
423 WARN(cursor,"\tinvalid resource bitmap header.\n");
424 return 0;
427 if( (hdc = GetDC32( 0 )) )
429 BITMAPINFO* pInfo;
431 /* Make sure we have room for the monochrome bitmap later on.
432 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
433 * up to and including the biBitCount. In-memory icon resource
434 * format is as follows:
436 * BITMAPINFOHEADER icHeader // DIB header
437 * RGBQUAD icColors[] // Color table
438 * BYTE icXOR[] // DIB bits for XOR mask
439 * BYTE icAND[] // DIB bits for AND mask
442 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
443 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
445 memcpy( pInfo, bmi, size );
446 pInfo->bmiHeader.biHeight /= 2;
448 /* Create the XOR bitmap */
450 if (DoStretch) {
451 if ((hXorBits = CreateCompatibleBitmap32(hdc, width, height))) {
452 HBITMAP32 hOld;
453 HDC32 hMem = CreateCompatibleDC32(hdc);
454 BOOL32 res;
456 if (hMem) {
457 hOld = SelectObject32(hMem, hXorBits);
458 res = StretchDIBits32(hMem, 0, 0, width, height, 0, 0,
459 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
460 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
461 SelectObject32(hMem, hOld);
462 DeleteDC32(hMem);
463 } else res = FALSE;
464 if (!res) { DeleteObject32(hXorBits); hXorBits = 0; }
466 } else hXorBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader,
467 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
468 if( hXorBits )
470 char* bits = (char *)bmi + size + bmi->bmiHeader.biHeight *
471 DIB_GetDIBWidthBytes(bmi->bmiHeader.biWidth,
472 bmi->bmiHeader.biBitCount) / 2;
474 pInfo->bmiHeader.biBitCount = 1;
475 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
477 RGBQUAD *rgb = pInfo->bmiColors;
479 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
480 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
481 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
482 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
484 else
486 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
488 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
489 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
492 /* Create the AND bitmap */
494 if (DoStretch) {
495 if ((hAndBits = CreateBitmap32(width, height, 1, 1, NULL))) {
496 HBITMAP32 hOld;
497 HDC32 hMem = CreateCompatibleDC32(hdc);
498 BOOL32 res;
500 if (hMem) {
501 hOld = SelectObject32(hMem, hAndBits);
502 res = StretchDIBits32(hMem, 0, 0, width, height, 0, 0,
503 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
504 bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
505 SelectObject32(hMem, hOld);
506 DeleteDC32(hMem);
507 } else res = FALSE;
508 if (!res) { DeleteObject32(hAndBits); hAndBits = 0; }
510 } else hAndBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader,
511 CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
513 if( !hAndBits ) DeleteObject32( hXorBits );
515 HeapFree( GetProcessHeap(), 0, pInfo );
517 ReleaseDC32( 0, hdc );
520 if( !hXorBits || !hAndBits )
522 WARN(cursor,"\tunable to create an icon bitmap.\n");
523 return 0;
526 /* Now create the CURSORICONINFO structure */
527 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
528 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
529 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
530 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
532 if (hObj) hObj = GlobalReAlloc16( hObj,
533 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
534 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
535 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
536 if (hObj)
538 CURSORICONINFO *info;
540 /* Make it owned by the module */
541 if (hInstance) FarSetOwner( hObj, GetExePtr(hInstance) );
543 info = (CURSORICONINFO *)GlobalLock16( hObj );
544 info->ptHotSpot.x = hotspot.x;
545 info->ptHotSpot.y = hotspot.y;
546 info->nWidth = bmpXor->bitmap.bmWidth;
547 info->nHeight = bmpXor->bitmap.bmHeight;
548 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
549 info->bPlanes = bmpXor->bitmap.bmPlanes;
550 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
552 /* Transfer the bitmap bits to the CURSORICONINFO structure */
554 GetBitmapBits32( hAndBits, sizeAnd, (char *)(info + 1) );
555 GetBitmapBits32( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
556 GlobalUnlock16( hObj );
559 DeleteObject32( hXorBits );
560 DeleteObject32( hAndBits );
561 return hObj;
565 /**********************************************************************
566 * CreateIconFromResourceEx16 (USER.450)
568 * FIXME: not sure about exact parameter types
570 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
571 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
573 return CreateIconFromResourceEx32(bits, cbSize, bIcon, dwVersion,
574 width, height, cFlag);
578 /**********************************************************************
579 * CreateIconFromResource (USER32.76)
581 HICON32 WINAPI CreateIconFromResource32( LPBYTE bits, UINT32 cbSize,
582 BOOL32 bIcon, DWORD dwVersion)
584 return CreateIconFromResourceEx32( bits, cbSize, bIcon, dwVersion, 0,0,0);
588 /**********************************************************************
589 * CreateIconFromResourceEx32 (USER32.77)
591 HICON32 WINAPI CreateIconFromResourceEx32( LPBYTE bits, UINT32 cbSize,
592 BOOL32 bIcon, DWORD dwVersion,
593 INT32 width, INT32 height,
594 UINT32 cFlag )
596 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
597 if( pTask )
598 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
599 width, height, cFlag );
600 return 0;
604 /**********************************************************************
605 * CURSORICON_Load16
607 * Load a cursor or icon from a 16-bit resource.
609 static HGLOBAL16 CURSORICON_Load16( HINSTANCE16 hInstance, SEGPTR name,
610 INT32 width, INT32 height, INT32 colors,
611 BOOL32 fCursor, UINT32 loadflags)
613 HGLOBAL16 handle = 0;
614 HRSRC16 hRsrc;
615 CURSORICONDIRENTRY dirEntry;
617 if (!hInstance) /* OEM cursor/icon */
619 HDC32 hdc;
620 DC *dc;
622 if (HIWORD(name)) /* Check for '#xxx' name */
624 char *ptr = PTR_SEG_TO_LIN( name );
625 if (ptr[0] != '#') return 0;
626 if (!(name = (SEGPTR)atoi( ptr + 1 ))) return 0;
628 hdc = CreateDC32A( "DISPLAY", NULL, NULL, NULL );
629 dc = DC_GetDCPtr( hdc );
630 if(dc->funcs->pLoadOEMResource)
631 handle = dc->funcs->pLoadOEMResource( LOWORD(name), fCursor ?
632 OEM_CURSOR : OEM_ICON);
633 GDI_HEAP_UNLOCK( hdc );
634 DeleteDC32( hdc );
635 return handle;
638 /* Find the best entry in the directory */
640 if ( !CURSORICON_LoadDirEntry16( hInstance, name, width, height,
641 colors, fCursor, &dirEntry ) ) return 0;
642 /* Load the resource */
644 if ( (hRsrc = FindResource16( hInstance,
645 MAKEINTRESOURCE16( dirEntry.icon.wResId ),
646 fCursor ? RT_CURSOR16 : RT_ICON16 )) )
648 /* 16-bit icon or cursor resources are processed
649 * transparently by the LoadResource16() via custom
650 * resource handlers set by SetResourceHandler().
653 if ( (handle = LoadResource16( hInstance, hRsrc )) )
654 return handle;
656 return 0;
659 /**********************************************************************
660 * CURSORICON_Load32
662 * Load a cursor or icon from a 32-bit resource.
664 HGLOBAL32 CURSORICON_Load32( HINSTANCE32 hInstance, LPCWSTR name,
665 int width, int height, int colors,
666 BOOL32 fCursor, UINT32 loadflags )
668 HANDLE32 handle = 0, h = 0;
669 HANDLE32 hRsrc;
670 CURSORICONDIRENTRY dirEntry;
671 LPBYTE bits;
673 if (!(loadflags & LR_LOADFROMFILE))
675 if (!hInstance) /* OEM cursor/icon */
677 WORD resid;
678 HDC32 hdc;
679 DC *dc;
681 if(HIWORD(name))
683 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
684 if( ansi[0]=='#') /*Check for '#xxx' name */
686 resid = atoi(ansi+1);
687 HeapFree( GetProcessHeap(), 0, ansi );
689 else
691 HeapFree( GetProcessHeap(), 0, ansi );
692 return 0;
695 else resid = LOWORD(name);
696 hdc = CreateDC32A( "DISPLAY", NULL, NULL, NULL );
697 dc = DC_GetDCPtr( hdc );
698 if(dc->funcs->pLoadOEMResource)
699 handle = dc->funcs->pLoadOEMResource( resid, fCursor ?
700 OEM_CURSOR : OEM_ICON );
701 GDI_HEAP_UNLOCK( hdc );
702 DeleteDC32( hdc );
703 return handle;
706 /* Find the best entry in the directory */
708 if (!CURSORICON_LoadDirEntry32( hInstance, name, width, height,
709 colors, fCursor, &dirEntry ) ) return 0;
710 /* Load the resource */
712 if (!(hRsrc = FindResource32W(hInstance,MAKEINTRESOURCE32W(dirEntry.icon.wResId),
713 fCursor ? RT_CURSOR32W : RT_ICON32W ))) return 0;
714 if (!(handle = LoadResource32( hInstance, hRsrc ))) return 0;
715 /* Hack to keep LoadCursor/Icon32() from spawning multiple
716 * copies of the same object.
718 #define pRsrcEntry ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)
719 if( pRsrcEntry->ResourceHandle ) return pRsrcEntry->ResourceHandle;
720 bits = (LPBYTE)LockResource32( handle );
721 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry.icon.dwBytesInRes,
722 !fCursor, 0x00030000, width, height, loadflags);
723 pRsrcEntry->ResourceHandle = h;
725 else
727 CURSORICONDIR *res;
728 LPBYTE *ptr;
729 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &res, &ptr))
730 return 0;
731 if (fCursor)
732 dirEntry = *(CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(res, width, height, 1);
733 else
734 dirEntry = *(CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(res, width, height, colors);
735 bits = ptr[dirEntry.icon.wResId-1];
736 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry.icon.dwBytesInRes,
737 !fCursor, 0x00030000, width, height, loadflags);
738 HeapFree( GetProcessHeap(), 0, res );
739 HeapFree( GetProcessHeap(), 0, ptr );
741 return h;
742 #undef pRsrcEntry
746 /***********************************************************************
747 * CURSORICON_Copy
749 * Make a copy of a cursor or icon.
751 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
753 char *ptrOld, *ptrNew;
754 int size;
755 HGLOBAL16 hNew;
757 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
758 if (!(hInstance = GetExePtr( hInstance ))) return 0;
759 size = GlobalSize16( handle );
760 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
761 FarSetOwner( hNew, hInstance );
762 ptrNew = (char *)GlobalLock16( hNew );
763 memcpy( ptrNew, ptrOld, size );
764 GlobalUnlock16( handle );
765 GlobalUnlock16( hNew );
766 return hNew;
769 /***********************************************************************
770 * CURSORICON_IconToCursor
772 * Converts bitmap to mono and truncates if icon is too large (should
773 * probably do StretchBlt() instead).
775 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL32 bSemiTransparent)
777 HCURSOR16 hRet = 0;
778 CURSORICONINFO *pIcon = NULL;
779 HTASK16 hTask = GetCurrentTask();
780 TDB* pTask = (TDB *)GlobalLock16(hTask);
782 if(hIcon && pTask)
783 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
784 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
785 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
786 else
788 BYTE pAndBits[128];
789 BYTE pXorBits[128];
790 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
791 BYTE* psPtr, *pxbPtr = pXorBits;
792 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
793 BYTE* pbc = NULL;
795 COLORREF col;
796 CURSORICONINFO cI;
798 TRACE(icon, "[%04x] %ix%i %ibpp (bogus %ibps)\n",
799 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
801 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
802 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
803 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
805 memset(pXorBits, 0, 128);
806 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
807 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
808 cI.nWidth = 32; cI.nHeight = 32;
809 cI.nWidthBytes = 4; /* 32x1bpp */
811 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
812 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
814 for( iy = 0; iy < maxy; iy++ )
816 unsigned shift = iy % 2;
818 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
819 (and_width > 4) ? 4 : and_width );
820 for( ix = 0; ix < maxx; ix++ )
822 if( bSemiTransparent && ((ix+shift)%2) )
824 /* set AND bit, XOR bit stays 0 */
826 pbc = pAndBits + iy * 4 + ix/8;
827 *pbc |= 0x80 >> (ix%8);
829 else
831 /* keep AND bit, set XOR bit */
833 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
834 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
835 col = COLOR_ToLogical(val);
836 if( (GetRValue(col) + GetGValue(col) + GetBValue(col)) > 0x180 )
838 pbc = pxbPtr + ix/8;
839 *pbc |= 0x80 >> (ix%8);
843 psPtr += xor_width;
844 pxbPtr += 4;
847 hRet = CreateCursorIconIndirect( pTask->hInstance , &cI, pAndBits, pXorBits);
849 if( !hRet ) /* fall back on default drag cursor */
850 hRet = CURSORICON_Copy( pTask->hInstance ,
851 CURSORICON_Load16(0,MAKEINTRESOURCE16(OCR_DRAGOBJECT),
852 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0) );
855 return hRet;
859 /***********************************************************************
860 * LoadCursor16 (USER.173)
862 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
864 if (HIWORD(name))
865 TRACE(cursor, "%04x '%s'\n",
866 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
867 else
868 TRACE(cursor, "%04x %04x\n",
869 hInstance, LOWORD(name) );
871 return CURSORICON_Load16( hInstance, name,
872 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0);
876 /***********************************************************************
877 * LoadIcon16 (USER.174)
879 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
881 HDC32 hdc = GetDC32(0);
882 UINT32 palEnts = GetSystemPaletteEntries32(hdc, 0, 0, NULL);
883 ReleaseDC32(0, hdc);
885 if (HIWORD(name))
886 TRACE(icon, "%04x '%s'\n",
887 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
888 else
889 TRACE(icon, "%04x %04x\n",
890 hInstance, LOWORD(name) );
892 return CURSORICON_Load16( hInstance, name,
893 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
894 MIN(16, palEnts), FALSE, 0);
898 /***********************************************************************
899 * CreateCursor16 (USER.406)
901 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
902 INT16 xHotSpot, INT16 yHotSpot,
903 INT16 nWidth, INT16 nHeight,
904 LPCVOID lpANDbits, LPCVOID lpXORbits )
906 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
908 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
909 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
910 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
914 /***********************************************************************
915 * CreateCursor32 (USER32.67)
917 HCURSOR32 WINAPI CreateCursor32( HINSTANCE32 hInstance,
918 INT32 xHotSpot, INT32 yHotSpot,
919 INT32 nWidth, INT32 nHeight,
920 LPCVOID lpANDbits, LPCVOID lpXORbits )
922 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
924 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
925 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
926 return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
930 /***********************************************************************
931 * CreateIcon16 (USER.407)
933 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
934 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
935 LPCVOID lpANDbits, LPCVOID lpXORbits )
937 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
939 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
940 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
941 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
945 /***********************************************************************
946 * CreateIcon32 (USER32.75)
948 HICON32 WINAPI CreateIcon32( HINSTANCE32 hInstance, INT32 nWidth,
949 INT32 nHeight, BYTE bPlanes, BYTE bBitsPixel,
950 LPCVOID lpANDbits, LPCVOID lpXORbits )
952 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
954 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
955 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
956 return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
960 /***********************************************************************
961 * CreateCursorIconIndirect (USER.408)
963 HGLOBAL16 WINAPI CreateCursorIconIndirect( HINSTANCE16 hInstance,
964 CURSORICONINFO *info,
965 LPCVOID lpANDbits,
966 LPCVOID lpXORbits )
968 HGLOBAL16 handle;
969 char *ptr;
970 int sizeAnd, sizeXor;
972 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
973 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
974 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
975 sizeXor = info->nHeight * info->nWidthBytes;
976 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
977 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
978 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
979 return 0;
980 if (hInstance) FarSetOwner( handle, hInstance );
981 ptr = (char *)GlobalLock16( handle );
982 memcpy( ptr, info, sizeof(*info) );
983 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
984 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
985 GlobalUnlock16( handle );
986 return handle;
990 /***********************************************************************
991 * CopyIcon16 (USER.368)
993 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
995 TRACE(icon, "%04x %04x\n", hInstance, hIcon );
996 return CURSORICON_Copy( hInstance, hIcon );
1000 /***********************************************************************
1001 * CopyIcon32 (USER32.60)
1003 HICON32 WINAPI CopyIcon32( HICON32 hIcon )
1005 HTASK16 hTask = GetCurrentTask ();
1006 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1007 TRACE(icon, "%04x\n", hIcon );
1008 return CURSORICON_Copy( pTask->hInstance, hIcon );
1012 /***********************************************************************
1013 * CopyCursor16 (USER.369)
1015 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1017 TRACE(cursor, "%04x %04x\n", hInstance, hCursor );
1018 return CURSORICON_Copy( hInstance, hCursor );
1022 /***********************************************************************
1023 * DestroyIcon16 (USER.457)
1025 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1027 TRACE(icon, "%04x\n", hIcon );
1028 /* FIXME: should check for OEM/global heap icon here */
1029 return (FreeResource16( hIcon ) == 0);
1033 /***********************************************************************
1034 * DestroyIcon32 (USER32.133)
1036 BOOL32 WINAPI DestroyIcon32( HICON32 hIcon )
1038 TRACE(icon, "%04x\n", hIcon );
1039 /* FIXME: should check for OEM/global heap icon here */
1040 /* Unlike DestroyIcon16, only icons created with CreateIcon32
1041 are valid for DestroyIcon32, so don't use FreeResource32 */
1042 return (GlobalFree16( hIcon ) == 0);
1046 /***********************************************************************
1047 * DestroyCursor16 (USER.458)
1049 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1051 TRACE(cursor, "%04x\n", hCursor );
1052 if (FreeResource16( hCursor ) == 0)
1053 return TRUE;
1054 else
1055 /* I believe this very same line should be added for every function
1056 where appears the comment:
1058 "FIXME: should check for OEM/global heap cursor here"
1060 which are most (all?) the ones that call FreeResource, at least
1061 in this module. Maybe this should go to a wrapper to avoid
1062 repetition. Or: couldn't it go to FreeResoutce itself?
1064 I'll let this to someone savvy on the subject.
1066 return (GlobalFree16 (hCursor) == 0);
1070 /***********************************************************************
1071 * DestroyCursor32 (USER32.132)
1073 BOOL32 WINAPI DestroyCursor32( HCURSOR32 hCursor )
1075 TRACE(cursor, "%04x\n", hCursor );
1076 /* FIXME: should check for OEM/global heap cursor here */
1077 /* Unlike DestroyCursor16, only cursors created with CreateCursor32
1078 are valid for DestroyCursor32, so don't use FreeResource32 */
1079 return (GlobalFree16( hCursor ) == 0);
1083 /***********************************************************************
1084 * DrawIcon16 (USER.84)
1086 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1088 return DrawIcon32( hdc, x, y, hIcon );
1092 /***********************************************************************
1093 * DrawIcon32 (USER32.159)
1095 BOOL32 WINAPI DrawIcon32( HDC32 hdc, INT32 x, INT32 y, HICON32 hIcon )
1097 CURSORICONINFO *ptr;
1098 HDC32 hMemDC;
1099 HBITMAP32 hXorBits, hAndBits;
1100 COLORREF oldFg, oldBg;
1102 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1103 if (!(hMemDC = CreateCompatibleDC32( hdc ))) return FALSE;
1104 hAndBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, 1, 1,
1105 (char *)(ptr+1) );
1106 hXorBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1107 ptr->bBitsPerPixel, (char *)(ptr + 1)
1108 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1109 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
1110 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
1112 if (hXorBits && hAndBits)
1114 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
1115 BitBlt32( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1116 SelectObject32( hMemDC, hXorBits );
1117 BitBlt32(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1118 SelectObject32( hMemDC, hBitTemp );
1120 DeleteDC32( hMemDC );
1121 if (hXorBits) DeleteObject32( hXorBits );
1122 if (hAndBits) DeleteObject32( hAndBits );
1123 GlobalUnlock16( hIcon );
1124 SetTextColor32( hdc, oldFg );
1125 SetBkColor32( hdc, oldBg );
1126 return TRUE;
1130 /***********************************************************************
1131 * DumpIcon (USER.459)
1133 DWORD WINAPI DumpIcon( SEGPTR pInfo, WORD *lpLen,
1134 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1136 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1137 int sizeAnd, sizeXor;
1139 if (!info) return 0;
1140 sizeXor = info->nHeight * info->nWidthBytes;
1141 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1142 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1143 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1144 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1145 return MAKELONG( sizeXor, sizeXor );
1149 /***********************************************************************
1150 * SetCursor16 (USER.69)
1152 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1154 return (HCURSOR16)SetCursor32( hCursor );
1158 /***********************************************************************
1159 * SetCursor32 (USER32.472)
1160 * RETURNS:
1161 * A handle to the previous cursor shape.
1163 HCURSOR32 WINAPI SetCursor32(
1164 HCURSOR32 hCursor /* Handle of cursor to show */
1166 HCURSOR32 hOldCursor;
1168 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1169 TRACE(cursor, "%04x\n", hCursor );
1170 hOldCursor = hActiveCursor;
1171 hActiveCursor = hCursor;
1172 /* Change the cursor shape only if it is visible */
1173 if (CURSOR_ShowCount >= 0)
1175 DISPLAY_SetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1176 GlobalUnlock16( hActiveCursor );
1178 return hOldCursor;
1182 /***********************************************************************
1183 * SetCursorPos16 (USER.70)
1185 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1187 SetCursorPos32( x, y );
1191 /***********************************************************************
1192 * SetCursorPos32 (USER32.474)
1194 BOOL32 WINAPI SetCursorPos32( INT32 x, INT32 y )
1196 DISPLAY_MoveCursor( x, y );
1197 return TRUE;
1201 /***********************************************************************
1202 * ShowCursor16 (USER.71)
1204 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1206 return ShowCursor32( bShow );
1210 /***********************************************************************
1211 * ShowCursor32 (USER32.530)
1213 INT32 WINAPI ShowCursor32( BOOL32 bShow )
1215 TRACE(cursor, "%d, count=%d\n",
1216 bShow, CURSOR_ShowCount );
1218 if (bShow)
1220 if (++CURSOR_ShowCount == 0) /* Show it */
1222 DISPLAY_SetCursor((CURSORICONINFO*)GlobalLock16( hActiveCursor ));
1223 GlobalUnlock16( hActiveCursor );
1226 else
1228 if (--CURSOR_ShowCount == -1) /* Hide it */
1229 DISPLAY_SetCursor( NULL );
1231 return CURSOR_ShowCount;
1235 /***********************************************************************
1236 * GetCursor16 (USER.247)
1238 HCURSOR16 WINAPI GetCursor16(void)
1240 return hActiveCursor;
1244 /***********************************************************************
1245 * GetCursor32 (USER32.227)
1247 HCURSOR32 WINAPI GetCursor32(void)
1249 return hActiveCursor;
1253 /***********************************************************************
1254 * ClipCursor16 (USER.16)
1256 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1258 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1259 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1260 return TRUE;
1264 /***********************************************************************
1265 * ClipCursor32 (USER32.53)
1267 BOOL32 WINAPI ClipCursor32( const RECT32 *rect )
1269 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1270 else CopyRect32( &CURSOR_ClipRect, rect );
1271 return TRUE;
1275 /***********************************************************************
1276 * GetCursorPos16 (USER.17)
1278 void WINAPI GetCursorPos16( POINT16 *pt )
1280 DWORD posX, posY, state;
1282 if (!pt) return;
1283 if (!EVENT_QueryPointer( &posX, &posY, &state ))
1284 pt->x = pt->y = 0;
1285 else
1287 pt->x = posX;
1288 pt->y = posY;
1289 if (state & MK_LBUTTON)
1290 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1291 else
1292 MouseButtonsStates[0] = FALSE;
1293 if (state & MK_MBUTTON)
1294 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1295 else
1296 MouseButtonsStates[1] = FALSE;
1297 if (state & MK_RBUTTON)
1298 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1299 else
1300 MouseButtonsStates[2] = FALSE;
1302 TRACE(cursor, "ret=%d,%d\n", pt->x, pt->y );
1306 /***********************************************************************
1307 * GetCursorPos32 (USER32.229)
1309 void WINAPI GetCursorPos32( POINT32 *pt )
1311 POINT16 pt16;
1312 GetCursorPos16( &pt16 );
1313 if (pt) CONV_POINT16TO32( &pt16, pt );
1317 /***********************************************************************
1318 * GetClipCursor16 (USER.309)
1320 void WINAPI GetClipCursor16( RECT16 *rect )
1322 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1326 /***********************************************************************
1327 * GetClipCursor32 (USER32.221)
1329 void WINAPI GetClipCursor32( RECT32 *rect )
1331 if (rect) CopyRect32( rect, &CURSOR_ClipRect );
1334 /**********************************************************************
1335 * LookupIconIdFromDirectoryEx16 (USER.364)
1337 * FIXME: exact parameter sizes
1339 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1340 INT16 width, INT16 height, UINT16 cFlag )
1342 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1343 UINT16 retVal = 0;
1344 if( dir && !dir->idReserved && (dir->idType & 3) )
1346 HDC32 hdc = GetDC32(0);
1347 UINT32 palEnts = GetSystemPaletteEntries32(hdc, 0, 0, NULL);
1348 int colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1349 ReleaseDC32(0, hdc);
1351 if( bIcon )
1353 ICONDIRENTRY* entry;
1354 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1355 if( entry ) retVal = entry->wResId;
1357 else
1359 CURSORDIRENTRY* entry;
1360 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1361 if( entry ) retVal = entry->wResId;
1364 else WARN(cursor, "invalid resource directory\n");
1365 return retVal;
1368 /**********************************************************************
1369 * LookupIconIdFromDirectoryEx32 (USER32.380)
1371 INT32 WINAPI LookupIconIdFromDirectoryEx32( LPBYTE dir, BOOL32 bIcon,
1372 INT32 width, INT32 height, UINT32 cFlag )
1374 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1377 /**********************************************************************
1378 * LookupIconIdFromDirectory (USER.???)
1380 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1382 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1383 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1384 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1387 /**********************************************************************
1388 * LookupIconIdFromDirectory (USER32.379)
1390 INT32 WINAPI LookupIconIdFromDirectory32( LPBYTE dir, BOOL32 bIcon )
1392 return LookupIconIdFromDirectoryEx32( dir, bIcon,
1393 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1394 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1397 /**********************************************************************
1398 * GetIconID (USER.455)
1400 WORD WINAPI GetIconID( HGLOBAL16 hResource, DWORD resType )
1402 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1404 TRACE(cursor, "hRes=%04x, entries=%i\n",
1405 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1407 switch(resType)
1409 case RT_CURSOR16:
1410 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1411 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1412 case RT_ICON16:
1413 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1414 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1415 default:
1416 WARN(cursor, "invalid res type %ld\n", resType );
1418 return 0;
1421 /**********************************************************************
1422 * LoadCursorIconHandler (USER.336)
1424 * Supposed to load resources of Windows 2.x applications.
1426 HGLOBAL16 WINAPI LoadCursorIconHandler( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1428 FIXME(cursor,"(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1429 hResource, hModule, hRsrc);
1430 return (HGLOBAL16)0;
1433 /**********************************************************************
1434 * LoadDIBIconHandler (USER.357)
1436 * RT_ICON resource loader, installed by USER_SignalProc when module
1437 * is initialized.
1439 HGLOBAL16 WINAPI LoadDIBIconHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1441 /* If hResource is zero we must allocate a new memory block, if it's
1442 * non-zero but GlobalLock() returns NULL then it was discarded and
1443 * we have to recommit some memory, otherwise we just need to check
1444 * the block size. See LoadProc() in 16-bit SDK for more.
1447 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1448 if( hMemObj )
1450 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1451 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1452 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1453 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1455 return hMemObj;
1458 /**********************************************************************
1459 * LoadDIBCursorHandler (USER.356)
1461 * RT_CURSOR resource loader. Same as above.
1463 HGLOBAL16 WINAPI LoadDIBCursorHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1465 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1466 if( hMemObj )
1468 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1469 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1470 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1471 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1473 return hMemObj;
1476 /**********************************************************************
1477 * LoadIconHandler (USER.456)
1479 HICON16 WINAPI LoadIconHandler( HGLOBAL16 hResource, BOOL16 bNew )
1481 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1483 TRACE(cursor,"hRes=%04x\n",hResource);
1485 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1486 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1489 /***********************************************************************
1490 * LoadCursorW (USER32.362)
1492 HCURSOR32 WINAPI LoadCursor32W(HINSTANCE32 hInstance, LPCWSTR name)
1494 return CURSORICON_Load32( hInstance, name,
1495 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0);
1498 /***********************************************************************
1499 * LoadCursorA (USER32.359)
1501 HCURSOR32 WINAPI LoadCursor32A(HINSTANCE32 hInstance, LPCSTR name)
1503 HCURSOR32 res=0;
1504 if(!HIWORD(name))
1505 return LoadCursor32W(hInstance,(LPCWSTR)name);
1506 else
1508 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1509 res = LoadCursor32W(hInstance, uni);
1510 HeapFree( GetProcessHeap(), 0, uni);
1512 return res;
1514 /***********************************************************************
1515 * LoadCursorFromFile32W (USER32.361)
1517 HCURSOR32 WINAPI LoadCursorFromFile32W (LPCWSTR name)
1519 return LoadImage32W(0, name, IMAGE_CURSOR, SYSMETRICS_CXCURSOR,
1520 SYSMETRICS_CYCURSOR, LR_LOADFROMFILE);
1523 /***********************************************************************
1524 * LoadCursorFromFile32A (USER32.360)
1526 HCURSOR32 WINAPI LoadCursorFromFile32A (LPCSTR name)
1528 HCURSOR32 hcur;
1529 LPWSTR u_name = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1530 hcur = LoadCursorFromFile32W(u_name);
1531 HeapFree( GetProcessHeap(), 0, u_name );
1532 return hcur;
1535 /***********************************************************************
1536 * LoadIconW (USER32.364)
1538 HICON32 WINAPI LoadIcon32W(HINSTANCE32 hInstance, LPCWSTR name)
1540 HDC32 hdc = GetDC32(0);
1541 UINT32 palEnts = GetSystemPaletteEntries32(hdc, 0, 0, NULL);
1542 ReleaseDC32(0, hdc);
1544 return CURSORICON_Load32( hInstance, name,
1545 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
1546 MIN( 16, palEnts ), FALSE, 0);
1549 /***********************************************************************
1550 * LoadIconA (USER32.363)
1552 HICON32 WINAPI LoadIcon32A(HINSTANCE32 hInstance, LPCSTR name)
1554 HICON32 res=0;
1556 if( !HIWORD(name) )
1557 return LoadIcon32W(hInstance, (LPCWSTR)name);
1558 else
1560 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1561 res = LoadIcon32W( hInstance, uni );
1562 HeapFree( GetProcessHeap(), 0, uni );
1564 return res;
1567 /**********************************************************************
1568 * GetIconInfo (USER32.242)
1570 BOOL32 WINAPI GetIconInfo(HICON32 hIcon,LPICONINFO iconinfo) {
1571 CURSORICONINFO *ciconinfo;
1573 ciconinfo = GlobalLock16(hIcon);
1574 if (!ciconinfo)
1575 return FALSE;
1576 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1577 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1578 iconinfo->fIcon = TRUE; /* hmm */
1580 iconinfo->hbmColor = CreateBitmap32 ( ciconinfo->nWidth, ciconinfo->nHeight,
1581 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1582 (char *)(ciconinfo + 1)
1583 + ciconinfo->nHeight *
1584 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1585 iconinfo->hbmMask = CreateBitmap32 ( ciconinfo->nWidth, ciconinfo->nHeight,
1586 1, 1, (char *)(ciconinfo + 1));
1588 GlobalUnlock16(hIcon);
1590 return TRUE;
1593 /**********************************************************************
1594 * CreateIconIndirect (USER32.78)
1596 HICON32 WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1597 BITMAPOBJ *bmpXor,*bmpAnd;
1598 HICON32 hObj;
1599 int sizeXor,sizeAnd;
1601 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1602 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1604 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1605 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1607 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1608 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1609 if (hObj)
1611 CURSORICONINFO *info;
1613 info = (CURSORICONINFO *)GlobalLock16( hObj );
1614 info->ptHotSpot.x = iconinfo->xHotspot;
1615 info->ptHotSpot.y = iconinfo->yHotspot;
1616 info->nWidth = bmpXor->bitmap.bmWidth;
1617 info->nHeight = bmpXor->bitmap.bmHeight;
1618 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1619 info->bPlanes = bmpXor->bitmap.bmPlanes;
1620 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1622 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1624 GetBitmapBits32( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1625 GetBitmapBits32( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1626 GlobalUnlock16( hObj );
1628 return hObj;
1632 /**********************************************************************
1634 DrawIconEx16 (USER.394)
1636 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1637 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1638 HBRUSH16 hbr, UINT16 flags)
1640 return DrawIconEx32(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1641 istep, hbr, flags);
1645 /******************************************************************************
1646 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1648 * NOTES
1649 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1651 * PARAMS
1652 * hdc [I] Handle to device context
1653 * x0 [I] X coordinate of upper left corner
1654 * y0 [I] Y coordinate of upper left corner
1655 * hIcon [I] Handle to icon to draw
1656 * cxWidth [I] Width of icon
1657 * cyWidth [I] Height of icon
1658 * istep [I] Index of frame in animated cursor
1659 * hbr [I] Handle to background brush
1660 * flags [I] Icon-drawing flags
1662 * RETURNS
1663 * Success: TRUE
1664 * Failure: FALSE
1666 BOOL32 WINAPI DrawIconEx32( HDC32 hdc, INT32 x0, INT32 y0, HICON32 hIcon,
1667 INT32 cxWidth, INT32 cyWidth, UINT32 istep,
1668 HBRUSH32 hbr, UINT32 flags )
1670 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1671 HDC32 hDC_off = 0, hMemDC = CreateCompatibleDC32 (hdc);
1672 BOOL32 result = FALSE, DoOffscreen = FALSE;
1673 HBITMAP32 hB_off = 0, hOld = 0;
1675 if (!ptr) return FALSE;
1677 if (istep)
1678 FIXME(icon, "Ignoring istep=%d\n", istep);
1679 if (flags & DI_COMPAT)
1680 FIXME(icon, "Ignoring flag DI_COMPAT\n");
1682 /* Calculate the size of the destination image. */
1683 if (cxWidth == 0)
1685 if (flags & DI_DEFAULTSIZE)
1686 cxWidth = GetSystemMetrics32 (SM_CXICON);
1687 else
1688 cxWidth = ptr->nWidth;
1690 if (cyWidth == 0)
1692 if (flags & DI_DEFAULTSIZE)
1693 cyWidth = GetSystemMetrics32 (SM_CYICON);
1694 else
1695 cyWidth = ptr->nHeight;
1698 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1699 STOCK_HOLLOW_BRUSH)))
1701 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1702 if (object)
1704 UINT16 magic = object->wMagic;
1705 GDI_HEAP_UNLOCK(hbr);
1706 DoOffscreen = magic == BRUSH_MAGIC;
1709 if (DoOffscreen) {
1710 RECT32 r = {0, 0, cxWidth, cxWidth};
1712 hDC_off = CreateCompatibleDC32(hdc);
1713 hB_off = CreateCompatibleBitmap32(hdc, cxWidth, cyWidth);
1714 if (hDC_off && hB_off) {
1715 hOld = SelectObject32(hDC_off, hB_off);
1716 FillRect32(hDC_off, &r, hbr);
1720 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1722 HBITMAP32 hXorBits, hAndBits;
1723 COLORREF oldFg, oldBg;
1724 INT32 nStretchMode;
1726 nStretchMode = SetStretchBltMode32 (hdc, STRETCH_DELETESCANS);
1728 hXorBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
1729 ptr->bPlanes, ptr->bBitsPerPixel,
1730 (char *)(ptr + 1)
1731 + ptr->nHeight *
1732 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1733 hAndBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
1734 1, 1, (char *)(ptr+1) );
1735 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
1736 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
1738 if (hXorBits && hAndBits)
1740 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
1741 if (flags & DI_MASK)
1743 if (DoOffscreen)
1744 StretchBlt32 (hDC_off, 0, 0, cxWidth, cyWidth,
1745 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1746 else
1747 StretchBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1748 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1750 SelectObject32( hMemDC, hXorBits );
1751 if (flags & DI_IMAGE)
1753 if (DoOffscreen)
1754 StretchBlt32 (hDC_off, 0, 0, cxWidth, cyWidth,
1755 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1756 else
1757 StretchBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1758 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1760 SelectObject32( hMemDC, hBitTemp );
1761 result = TRUE;
1764 SetTextColor32( hdc, oldFg );
1765 SetBkColor32( hdc, oldBg );
1766 if (hXorBits) DeleteObject32( hXorBits );
1767 if (hAndBits) DeleteObject32( hAndBits );
1768 SetStretchBltMode32 (hdc, nStretchMode);
1769 if (DoOffscreen) {
1770 BitBlt32(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
1771 SelectObject32(hDC_off, hOld);
1774 if (hMemDC) DeleteDC32( hMemDC );
1775 if (hDC_off) DeleteDC32(hDC_off);
1776 if (hB_off) DeleteObject32(hB_off);
1777 GlobalUnlock16( hIcon );
1778 return result;