Bugfix: Bad jump generated in THUNK_AllocLSThunklet.
[wine/multimedia.git] / objects / cursoricon.c
blob060ac3a072daeae9a7725d793b4008f3b2039a83
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 "sysmetrics.h"
41 #include "global.h"
42 #include "module.h"
43 #include "win.h"
44 #include "debug.h"
45 #include "task.h"
46 #include "user.h"
47 #include "input.h"
48 #include "display.h"
49 #include "message.h"
50 #include "winerror.h"
52 static HCURSOR32 hActiveCursor = 0; /* Active cursor */
53 static INT32 CURSOR_ShowCount = 0; /* Cursor display count */
54 static RECT32 CURSOR_ClipRect; /* Cursor clipping rect */
56 /**********************************************************************
57 * CURSORICON_FindBestIcon
59 * Find the icon closest to the requested size and number of colors.
61 static ICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
62 int height, int colors )
64 int i, maxcolors, maxwidth, maxheight;
65 ICONDIRENTRY *entry, *bestEntry = NULL;
67 if (dir->idCount < 1)
69 WARN(icon, "Empty directory!\n" );
70 return NULL;
72 if (dir->idCount == 1) return &dir->idEntries[0].icon; /* No choice... */
74 /* First find the exact size with less colors */
76 maxcolors = 0;
77 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
78 if ((entry->bWidth == width) && (entry->bHeight == height) &&
79 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
81 bestEntry = entry;
82 maxcolors = entry->bColorCount;
84 if (bestEntry) return bestEntry;
86 /* First find the exact size with more colors */
88 maxcolors = 255;
89 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
90 if ((entry->bWidth == width) && (entry->bHeight == height) &&
91 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
93 bestEntry = entry;
94 maxcolors = entry->bColorCount;
96 if (bestEntry) return bestEntry;
98 /* Now find a smaller one with less colors */
100 maxcolors = maxwidth = maxheight = 0;
101 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
102 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
103 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
104 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
106 bestEntry = entry;
107 maxwidth = entry->bWidth;
108 maxheight = entry->bHeight;
109 maxcolors = entry->bColorCount;
111 if (bestEntry) return bestEntry;
113 /* Now find a smaller one with more colors */
115 maxcolors = 255;
116 maxwidth = maxheight = 0;
117 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
118 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
119 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
120 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
122 bestEntry = entry;
123 maxwidth = entry->bWidth;
124 maxheight = entry->bHeight;
125 maxcolors = entry->bColorCount;
127 if (bestEntry) return bestEntry;
129 /* Now find a larger one with less colors */
131 maxcolors = 0;
132 maxwidth = maxheight = 255;
133 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
134 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
135 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
137 bestEntry = entry;
138 maxwidth = entry->bWidth;
139 maxheight = entry->bHeight;
140 maxcolors = entry->bColorCount;
142 if (bestEntry) return bestEntry;
144 /* Now find a larger one with more colors */
146 maxcolors = maxwidth = maxheight = 255;
147 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
148 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
149 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
151 bestEntry = entry;
152 maxwidth = entry->bWidth;
153 maxheight = entry->bHeight;
154 maxcolors = entry->bColorCount;
157 return bestEntry;
161 /**********************************************************************
162 * CURSORICON_FindBestCursor
164 * Find the cursor closest to the requested size.
165 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
166 * ignored too
168 static CURSORDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
169 int width, int height, int color)
171 int i, maxwidth, maxheight;
172 CURSORDIRENTRY *entry, *bestEntry = NULL;
174 if (dir->idCount < 1)
176 WARN(cursor, "Empty directory!\n" );
177 return NULL;
179 if (dir->idCount == 1) return &dir->idEntries[0].cursor; /* No choice... */
181 /* First find the largest one smaller than or equal to the requested size*/
183 maxwidth = maxheight = 0;
184 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
185 if ((entry->wWidth <= width) && (entry->wHeight <= height) &&
186 (entry->wWidth > maxwidth) && (entry->wHeight > maxheight) &&
187 (entry->wBitCount == 1))
189 bestEntry = entry;
190 maxwidth = entry->wWidth;
191 maxheight = entry->wHeight;
193 if (bestEntry) return bestEntry;
195 /* Now find the smallest one larger than the requested size */
197 maxwidth = maxheight = 255;
198 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
199 if ((entry->wWidth < maxwidth) && (entry->wHeight < maxheight) &&
200 (entry->wBitCount == 1))
202 bestEntry = entry;
203 maxwidth = entry->wWidth;
204 maxheight = entry->wHeight;
207 return bestEntry;
210 /*********************************************************************
211 * The main purpose of this function is to create fake resource directory
212 * and fake resource entries. There are several reasons for this:
213 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
214 * fields
215 * There are some "bad" cursor files which do not have
216 * bColorCount initialized but instead one must read this info
217 * directly from corresponding DIB sections
218 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
220 BOOL32 CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL32 fCursor,
221 CURSORICONDIR **res, LPBYTE **ptr)
223 LPBYTE _free;
224 CURSORICONFILEDIR *bits;
225 int entries, size, i;
227 *res = NULL;
228 *ptr = NULL;
229 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
230 if (!(entries = bits->idCount)) goto fail;
231 (int)_free = size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) *
232 (entries - 1);
233 for (i=0; i < entries; i++)
234 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
236 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
237 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
238 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
240 _free = (LPBYTE)(*res) + (int)_free;
241 memcpy((*res), bits, 6);
242 for (i=0; i<entries; i++)
244 ((LPBYTE*)(*ptr))[i] = _free;
245 if (fCursor) {
246 (*res)->idEntries[i].cursor.wWidth=bits->idEntries[i].bWidth;
247 (*res)->idEntries[i].cursor.wHeight=bits->idEntries[i].bHeight;
248 (*res)->idEntries[i].cursor.wPlanes=1;
249 (*res)->idEntries[i].cursor.wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
250 bits->idEntries[i].dwDIBOffset))->biBitCount;
251 (*res)->idEntries[i].cursor.dwBytesInRes = bits->idEntries[i].dwDIBSize;
252 (*res)->idEntries[i].cursor.wResId=i+1;
253 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
254 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
255 _free+=sizeof(POINT16);
256 } else {
257 (*res)->idEntries[i].icon.bWidth=bits->idEntries[i].bWidth;
258 (*res)->idEntries[i].icon.bHeight=bits->idEntries[i].bHeight;
259 (*res)->idEntries[i].icon.bColorCount = bits->idEntries[i].bColorCount;
260 (*res)->idEntries[i].icon.wPlanes=1;
261 (*res)->idEntries[i].icon.wBitCount= ((LPBITMAPINFOHEADER)((LPBYTE)bits +
262 bits->idEntries[i].dwDIBOffset))->biBitCount;
263 (*res)->idEntries[i].icon.dwBytesInRes = bits->idEntries[i].dwDIBSize;
264 (*res)->idEntries[i].icon.wResId=i+1;
266 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
267 (*res)->idEntries[i].icon.dwBytesInRes);
268 _free += (*res)->idEntries[i].icon.dwBytesInRes;
270 UnmapViewOfFile( bits );
271 return TRUE;
272 fail:
273 if (*res) HeapFree( GetProcessHeap(), 0, *res );
274 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
275 UnmapViewOfFile( bits );
276 return FALSE;
279 /**********************************************************************
280 * CURSORICON_LoadDirEntry16
282 * Load the icon/cursor directory for a given resource name and find the
283 * best matching entry.
285 static BOOL32 CURSORICON_LoadDirEntry16( HINSTANCE32 hInstance, SEGPTR name,
286 INT32 width, INT32 height, INT32 colors,
287 BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
289 HRSRC16 hRsrc;
290 HGLOBAL16 hMem;
291 CURSORICONDIR *dir;
292 CURSORICONDIRENTRY *entry = NULL;
294 if (!(hRsrc = FindResource16( hInstance, name,
295 fCursor ? RT_GROUP_CURSOR16 : RT_GROUP_ICON16 )))
296 return FALSE;
297 if (!(hMem = LoadResource16( hInstance, hRsrc ))) return FALSE;
298 if ((dir = (CURSORICONDIR *)LockResource16( hMem )))
300 if (fCursor)
301 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
302 width, height, 1);
303 else
304 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
305 width, height, colors );
306 if (entry) *dirEntry = *entry;
308 FreeResource16( hMem );
309 return (entry != NULL);
313 /**********************************************************************
314 * CURSORICON_LoadDirEntry32
316 * Load the icon/cursor directory for a given resource name and find the
317 * best matching entry.
319 static BOOL32 CURSORICON_LoadDirEntry32( HINSTANCE32 hInstance, LPCWSTR name,
320 INT32 width, INT32 height, INT32 colors,
321 BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
323 HANDLE32 hRsrc;
324 HANDLE32 hMem;
325 CURSORICONDIR *dir;
326 CURSORICONDIRENTRY *entry = NULL;
328 if (!(hRsrc = FindResource32W( hInstance, name,
329 fCursor ? RT_GROUP_CURSOR32W : RT_GROUP_ICON32W )))
330 return FALSE;
331 if (!(hMem = LoadResource32( hInstance, hRsrc ))) return FALSE;
332 if ((dir = (CURSORICONDIR*)LockResource32( hMem )))
334 if (fCursor)
335 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
336 width, height, 1);
337 else
338 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
339 width, height, colors );
340 if (entry) *dirEntry = *entry;
342 FreeResource32( hMem );
343 return (entry != NULL);
347 /**********************************************************************
348 * CURSORICON_CreateFromResource
350 * Create a cursor or icon from in-memory resource template.
352 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
353 * with cbSize parameter as well.
355 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
356 UINT32 cbSize, BOOL32 bIcon, DWORD dwVersion,
357 INT32 width, INT32 height, UINT32 loadflags )
359 int sizeAnd, sizeXor;
360 HBITMAP32 hAndBits = 0, hXorBits = 0; /* error condition for later */
361 BITMAPOBJ *bmpXor, *bmpAnd;
362 POINT16 hotspot = { 0 ,0 };
363 BITMAPINFO *bmi;
364 HDC32 hdc;
365 BOOL32 DoStretch;
366 INT32 size;
368 TRACE(cursor,"%08x (%u bytes), ver %08x, %ix%i %s %s\n",
369 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
370 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
371 if (dwVersion == 0x00020000)
373 FIXME(cursor,"\t2.xx resources are not supported\n");
374 return 0;
377 if (bIcon)
378 bmi = (BITMAPINFO *)bits;
379 else /* get the hotspot */
381 POINT16 *pt = (POINT16 *)bits;
382 hotspot = *pt;
383 bmi = (BITMAPINFO *)(pt + 1);
385 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
387 if (!width) width = bmi->bmiHeader.biWidth;
388 if (!height) height = bmi->bmiHeader.biHeight/2;
389 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
390 (bmi->bmiHeader.biWidth != width);
392 /* Check bitmap header */
394 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
395 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
396 bmi->bmiHeader.biCompression != BI_RGB) )
398 WARN(cursor,"\tinvalid resource bitmap header.\n");
399 return 0;
402 if( (hdc = GetDC32( 0 )) )
404 BITMAPINFO* pInfo;
406 /* Make sure we have room for the monochrome bitmap later on.
407 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
408 * up to and including the biBitCount. In-memory icon resource
409 * format is as follows:
411 * BITMAPINFOHEADER icHeader // DIB header
412 * RGBQUAD icColors[] // Color table
413 * BYTE icXOR[] // DIB bits for XOR mask
414 * BYTE icAND[] // DIB bits for AND mask
417 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
418 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
420 memcpy( pInfo, bmi, size );
421 pInfo->bmiHeader.biHeight /= 2;
423 /* Create the XOR bitmap */
425 if (DoStretch) {
426 if ((hXorBits = CreateCompatibleBitmap32(hdc, width, height))) {
427 HBITMAP32 hOld;
428 HDC32 hMem = CreateCompatibleDC32(hdc);
429 BOOL32 res;
431 if (hMem) {
432 hOld = SelectObject32(hMem, hXorBits);
433 res = StretchDIBits32(hMem, 0, 0, width, height, 0, 0,
434 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
435 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
436 SelectObject32(hMem, hOld);
437 DeleteDC32(hMem);
438 } else res = FALSE;
439 if (!res) { DeleteObject32(hXorBits); hXorBits = 0; }
441 } else hXorBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader,
442 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
443 if( hXorBits )
445 char* bits = (char *)bmi + size + bmi->bmiHeader.biHeight *
446 DIB_GetDIBWidthBytes(bmi->bmiHeader.biWidth,
447 bmi->bmiHeader.biBitCount) / 2;
449 pInfo->bmiHeader.biBitCount = 1;
450 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
452 RGBQUAD *rgb = pInfo->bmiColors;
454 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
455 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
456 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
457 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
459 else
461 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
463 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
464 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
467 /* Create the AND bitmap */
469 if (DoStretch) {
470 if ((hAndBits = CreateBitmap32(width, height, 1, 1, NULL))) {
471 HBITMAP32 hOld;
472 HDC32 hMem = CreateCompatibleDC32(hdc);
473 BOOL32 res;
475 if (hMem) {
476 hOld = SelectObject32(hMem, hAndBits);
477 res = StretchDIBits32(hMem, 0, 0, width, height, 0, 0,
478 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
479 bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
480 SelectObject32(hMem, hOld);
481 DeleteDC32(hMem);
482 } else res = FALSE;
483 if (!res) { DeleteObject32(hAndBits); hAndBits = 0; }
485 } else hAndBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader,
486 CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
488 if( !hAndBits ) DeleteObject32( hXorBits );
490 HeapFree( GetProcessHeap(), 0, pInfo );
492 ReleaseDC32( 0, hdc );
495 if( !hXorBits || !hAndBits )
497 WARN(cursor,"\tunable to create an icon bitmap.\n");
498 return 0;
501 /* Now create the CURSORICONINFO structure */
502 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
503 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
504 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
505 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
507 if (hObj) hObj = GlobalReAlloc16( hObj,
508 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
509 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
510 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
511 if (hObj)
513 CURSORICONINFO *info;
515 /* Make it owned by the module */
516 if (hInstance) FarSetOwner( hObj, GetExePtr(hInstance) );
518 info = (CURSORICONINFO *)GlobalLock16( hObj );
519 info->ptHotSpot.x = hotspot.x;
520 info->ptHotSpot.y = hotspot.y;
521 info->nWidth = bmpXor->bitmap.bmWidth;
522 info->nHeight = bmpXor->bitmap.bmHeight;
523 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
524 info->bPlanes = bmpXor->bitmap.bmPlanes;
525 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
527 /* Transfer the bitmap bits to the CURSORICONINFO structure */
529 GetBitmapBits32( hAndBits, sizeAnd, (char *)(info + 1) );
530 GetBitmapBits32( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
531 GlobalUnlock16( hObj );
534 DeleteObject32( hXorBits );
535 DeleteObject32( hAndBits );
536 return hObj;
540 /**********************************************************************
541 * CreateIconFromResourceEx16 (USER.450)
543 * FIXME: not sure about exact parameter types
545 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
546 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
548 return CreateIconFromResourceEx32(bits, cbSize, bIcon, dwVersion,
549 width, height, cFlag);
553 /**********************************************************************
554 * CreateIconFromResource (USER32.76)
556 HICON32 WINAPI CreateIconFromResource32( LPBYTE bits, UINT32 cbSize,
557 BOOL32 bIcon, DWORD dwVersion)
559 return CreateIconFromResourceEx32( bits, cbSize, bIcon, dwVersion, 0,0,0);
563 /**********************************************************************
564 * CreateIconFromResourceEx32 (USER32.77)
566 HICON32 WINAPI CreateIconFromResourceEx32( LPBYTE bits, UINT32 cbSize,
567 BOOL32 bIcon, DWORD dwVersion,
568 INT32 width, INT32 height,
569 UINT32 cFlag )
571 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
572 if( pTask )
573 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
574 width, height, cFlag );
575 return 0;
579 /**********************************************************************
580 * CURSORICON_Load16
582 * Load a cursor or icon from a 16-bit resource.
584 static HGLOBAL16 CURSORICON_Load16( HINSTANCE16 hInstance, SEGPTR name,
585 INT32 width, INT32 height, INT32 colors,
586 BOOL32 fCursor, UINT32 loadflags)
588 HGLOBAL16 handle;
589 HRSRC16 hRsrc;
590 CURSORICONDIRENTRY dirEntry;
592 if (!hInstance) /* OEM cursor/icon */
594 if (HIWORD(name)) /* Check for '#xxx' name */
596 char *ptr = PTR_SEG_TO_LIN( name );
597 if (ptr[0] != '#') return 0;
598 if (!(name = (SEGPTR)atoi( ptr + 1 ))) return 0;
600 return OBM_LoadCursorIcon( LOWORD(name), fCursor );
603 /* Find the best entry in the directory */
605 if ( !CURSORICON_LoadDirEntry16( hInstance, name, width, height,
606 colors, fCursor, &dirEntry ) ) return 0;
607 /* Load the resource */
609 if ( (hRsrc = FindResource16( hInstance,
610 MAKEINTRESOURCE16( dirEntry.icon.wResId ),
611 fCursor ? RT_CURSOR16 : RT_ICON16 )) )
613 /* 16-bit icon or cursor resources are processed
614 * transparently by the LoadResource16() via custom
615 * resource handlers set by SetResourceHandler().
618 if ( (handle = LoadResource16( hInstance, hRsrc )) )
619 return handle;
621 return 0;
624 /**********************************************************************
625 * CURSORICON_Load32
627 * Load a cursor or icon from a 32-bit resource.
629 HGLOBAL32 CURSORICON_Load32( HINSTANCE32 hInstance, LPCWSTR name,
630 int width, int height, int colors,
631 BOOL32 fCursor, UINT32 loadflags )
633 HANDLE32 handle, h = 0;
634 HANDLE32 hRsrc;
635 CURSORICONDIRENTRY dirEntry;
636 LPBYTE bits;
638 if (!(loadflags & LR_LOADFROMFILE))
640 if (!hInstance) /* OEM cursor/icon */
642 WORD resid;
643 if(HIWORD(name))
645 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
646 if( ansi[0]=='#') /*Check for '#xxx' name */
648 resid = atoi(ansi+1);
649 HeapFree( GetProcessHeap(), 0, ansi );
651 else
653 HeapFree( GetProcessHeap(), 0, ansi );
654 return 0;
657 else resid = LOWORD(name);
658 return OBM_LoadCursorIcon(resid, fCursor);
661 /* Find the best entry in the directory */
663 if (!CURSORICON_LoadDirEntry32( hInstance, name, width, height,
664 colors, fCursor, &dirEntry ) ) return 0;
665 /* Load the resource */
667 if (!(hRsrc = FindResource32W(hInstance,MAKEINTRESOURCE32W(dirEntry.icon.wResId),
668 fCursor ? RT_CURSOR32W : RT_ICON32W ))) return 0;
669 if (!(handle = LoadResource32( hInstance, hRsrc ))) return 0;
670 /* Hack to keep LoadCursor/Icon32() from spawning multiple
671 * copies of the same object.
673 #define pRsrcEntry ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)
674 if( pRsrcEntry->ResourceHandle ) return pRsrcEntry->ResourceHandle;
675 bits = (LPBYTE)LockResource32( handle );
676 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry.icon.dwBytesInRes,
677 !fCursor, 0x00030000, width, height, loadflags);
678 pRsrcEntry->ResourceHandle = h;
680 else
682 CURSORICONDIR *res;
683 LPBYTE *ptr;
684 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &res, &ptr))
685 return 0;
686 if (fCursor)
687 dirEntry = *(CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(res, width, height, 1);
688 else
689 dirEntry = *(CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(res, width, height, colors);
690 bits = ptr[dirEntry.icon.wResId-1];
691 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry.icon.dwBytesInRes,
692 !fCursor, 0x00030000, width, height, loadflags);
693 HeapFree( GetProcessHeap(), 0, res );
694 HeapFree( GetProcessHeap(), 0, ptr );
696 return h;
697 #undef pRsrcEntry
701 /***********************************************************************
702 * CURSORICON_Copy
704 * Make a copy of a cursor or icon.
706 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
708 char *ptrOld, *ptrNew;
709 int size;
710 HGLOBAL16 hNew;
712 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
713 if (!(hInstance = GetExePtr( hInstance ))) return 0;
714 size = GlobalSize16( handle );
715 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
716 FarSetOwner( hNew, hInstance );
717 ptrNew = (char *)GlobalLock16( hNew );
718 memcpy( ptrNew, ptrOld, size );
719 GlobalUnlock16( handle );
720 GlobalUnlock16( hNew );
721 return hNew;
724 /***********************************************************************
725 * CURSORICON_IconToCursor
727 * Converts bitmap to mono and truncates if icon is too large (should
728 * probably do StretchBlt() instead).
730 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL32 bSemiTransparent)
732 HCURSOR16 hRet = 0;
733 CURSORICONINFO *pIcon = NULL;
734 HTASK16 hTask = GetCurrentTask();
735 TDB* pTask = (TDB *)GlobalLock16(hTask);
737 if(hIcon && pTask)
738 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
739 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
740 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
741 else
743 BYTE pAndBits[128];
744 BYTE pXorBits[128];
745 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
746 BYTE* psPtr, *pxbPtr = pXorBits;
747 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
748 BYTE* pbc = NULL;
750 COLORREF col;
751 CURSORICONINFO cI;
753 TRACE(icon, "[%04x] %ix%i %ibpp (bogus %ibps)\n",
754 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
756 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
757 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
758 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
760 memset(pXorBits, 0, 128);
761 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
762 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
763 cI.nWidth = 32; cI.nHeight = 32;
764 cI.nWidthBytes = 4; /* 32x1bpp */
766 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
767 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
769 for( iy = 0; iy < maxy; iy++ )
771 unsigned shift = iy % 2;
773 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
774 (and_width > 4) ? 4 : and_width );
775 for( ix = 0; ix < maxx; ix++ )
777 if( bSemiTransparent && ((ix+shift)%2) )
779 /* set AND bit, XOR bit stays 0 */
781 pbc = pAndBits + iy * 4 + ix/8;
782 *pbc |= 0x80 >> (ix%8);
784 else
786 /* keep AND bit, set XOR bit */
788 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
789 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
790 col = COLOR_ToLogical(val);
791 if( (GetRValue(col) + GetGValue(col) + GetBValue(col)) > 0x180 )
793 pbc = pxbPtr + ix/8;
794 *pbc |= 0x80 >> (ix%8);
798 psPtr += xor_width;
799 pxbPtr += 4;
802 hRet = CreateCursorIconIndirect( pTask->hInstance , &cI, pAndBits, pXorBits);
804 if( !hRet ) /* fall back on default drag cursor */
805 hRet = CURSORICON_Copy( pTask->hInstance ,
806 CURSORICON_Load16(0,MAKEINTRESOURCE16(OCR_DRAGOBJECT),
807 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0) );
810 return hRet;
814 /***********************************************************************
815 * LoadCursor16 (USER.173)
817 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
819 if (HIWORD(name))
820 TRACE(cursor, "%04x '%s'\n",
821 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
822 else
823 TRACE(cursor, "%04x %04x\n",
824 hInstance, LOWORD(name) );
826 return CURSORICON_Load16( hInstance, name,
827 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0);
831 /***********************************************************************
832 * LoadIcon16 (USER.174)
834 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
836 if (HIWORD(name))
837 TRACE(icon, "%04x '%s'\n",
838 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
839 else
840 TRACE(icon, "%04x %04x\n",
841 hInstance, LOWORD(name) );
843 return CURSORICON_Load16( hInstance, name,
844 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
845 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE, 0);
849 /***********************************************************************
850 * CreateCursor16 (USER.406)
852 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
853 INT16 xHotSpot, INT16 yHotSpot,
854 INT16 nWidth, INT16 nHeight,
855 LPCVOID lpANDbits, LPCVOID lpXORbits )
857 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
859 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
860 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
861 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
865 /***********************************************************************
866 * CreateCursor32 (USER32.67)
868 HCURSOR32 WINAPI CreateCursor32( HINSTANCE32 hInstance,
869 INT32 xHotSpot, INT32 yHotSpot,
870 INT32 nWidth, INT32 nHeight,
871 LPCVOID lpANDbits, LPCVOID lpXORbits )
873 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
875 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
876 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
877 return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
881 /***********************************************************************
882 * CreateIcon16 (USER.407)
884 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
885 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
886 LPCVOID lpANDbits, LPCVOID lpXORbits )
888 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
890 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
891 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
892 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
896 /***********************************************************************
897 * CreateIcon32 (USER32.75)
899 HICON32 WINAPI CreateIcon32( HINSTANCE32 hInstance, INT32 nWidth,
900 INT32 nHeight, BYTE bPlanes, BYTE bBitsPixel,
901 LPCVOID lpANDbits, LPCVOID lpXORbits )
903 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
905 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
906 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
907 return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
911 /***********************************************************************
912 * CreateCursorIconIndirect (USER.408)
914 HGLOBAL16 WINAPI CreateCursorIconIndirect( HINSTANCE16 hInstance,
915 CURSORICONINFO *info,
916 LPCVOID lpANDbits,
917 LPCVOID lpXORbits )
919 HGLOBAL16 handle;
920 char *ptr;
921 int sizeAnd, sizeXor;
923 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
924 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
925 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
926 sizeXor = info->nHeight * info->nWidthBytes;
927 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
928 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
929 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
930 return 0;
931 if (hInstance) FarSetOwner( handle, hInstance );
932 ptr = (char *)GlobalLock16( handle );
933 memcpy( ptr, info, sizeof(*info) );
934 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
935 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
936 GlobalUnlock16( handle );
937 return handle;
941 /***********************************************************************
942 * CopyIcon16 (USER.368)
944 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
946 TRACE(icon, "%04x %04x\n", hInstance, hIcon );
947 return CURSORICON_Copy( hInstance, hIcon );
951 /***********************************************************************
952 * CopyIcon32 (USER32.60)
954 HICON32 WINAPI CopyIcon32( HICON32 hIcon )
956 HTASK16 hTask = GetCurrentTask ();
957 TDB* pTask = (TDB *) GlobalLock16 (hTask);
958 TRACE(icon, "%04x\n", hIcon );
959 return CURSORICON_Copy( pTask->hInstance, hIcon );
963 /***********************************************************************
964 * CopyCursor16 (USER.369)
966 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
968 TRACE(cursor, "%04x %04x\n", hInstance, hCursor );
969 return CURSORICON_Copy( hInstance, hCursor );
973 /***********************************************************************
974 * DestroyIcon16 (USER.457)
976 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
978 TRACE(icon, "%04x\n", hIcon );
979 /* FIXME: should check for OEM/global heap icon here */
980 return (FreeResource16( hIcon ) == 0);
984 /***********************************************************************
985 * DestroyIcon32 (USER32.133)
987 BOOL32 WINAPI DestroyIcon32( HICON32 hIcon )
989 TRACE(icon, "%04x\n", hIcon );
990 /* FIXME: should check for OEM/global heap icon here */
991 /* Unlike DestroyIcon16, only icons created with CreateIcon32
992 are valid for DestroyIcon32, so don't use FreeResource32 */
993 return (GlobalFree16( hIcon ) == 0);
997 /***********************************************************************
998 * DestroyCursor16 (USER.458)
1000 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1002 TRACE(cursor, "%04x\n", hCursor );
1003 if (FreeResource16( hCursor ) == 0)
1004 return TRUE;
1005 else
1006 /* I believe this very same line should be added for every function
1007 where appears the comment:
1009 "FIXME: should check for OEM/global heap cursor here"
1011 which are most (all?) the ones that call FreeResource, at least
1012 in this module. Maybe this should go to a wrapper to avoid
1013 repetition. Or: couldn't it go to FreeResoutce itself?
1015 I'll let this to someone savvy on the subject.
1017 return (GlobalFree16 (hCursor) == 0);
1021 /***********************************************************************
1022 * DestroyCursor32 (USER32.132)
1024 BOOL32 WINAPI DestroyCursor32( HCURSOR32 hCursor )
1026 TRACE(cursor, "%04x\n", hCursor );
1027 /* FIXME: should check for OEM/global heap cursor here */
1028 /* Unlike DestroyCursor16, only cursors created with CreateCursor32
1029 are valid for DestroyCursor32, so don't use FreeResource32 */
1030 return (GlobalFree16( hCursor ) == 0);
1034 /***********************************************************************
1035 * DrawIcon16 (USER.84)
1037 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1039 return DrawIcon32( hdc, x, y, hIcon );
1043 /***********************************************************************
1044 * DrawIcon32 (USER32.159)
1046 BOOL32 WINAPI DrawIcon32( HDC32 hdc, INT32 x, INT32 y, HICON32 hIcon )
1048 CURSORICONINFO *ptr;
1049 HDC32 hMemDC;
1050 HBITMAP32 hXorBits, hAndBits;
1051 COLORREF oldFg, oldBg;
1053 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1054 if (!(hMemDC = CreateCompatibleDC32( hdc ))) return FALSE;
1055 hAndBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, 1, 1,
1056 (char *)(ptr+1) );
1057 hXorBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1058 ptr->bBitsPerPixel, (char *)(ptr + 1)
1059 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1060 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
1061 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
1063 if (hXorBits && hAndBits)
1065 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
1066 BitBlt32( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1067 SelectObject32( hMemDC, hXorBits );
1068 BitBlt32(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1069 SelectObject32( hMemDC, hBitTemp );
1071 DeleteDC32( hMemDC );
1072 if (hXorBits) DeleteObject32( hXorBits );
1073 if (hAndBits) DeleteObject32( hAndBits );
1074 GlobalUnlock16( hIcon );
1075 SetTextColor32( hdc, oldFg );
1076 SetBkColor32( hdc, oldBg );
1077 return TRUE;
1081 /***********************************************************************
1082 * DumpIcon (USER.459)
1084 DWORD WINAPI DumpIcon( SEGPTR pInfo, WORD *lpLen,
1085 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1087 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1088 int sizeAnd, sizeXor;
1090 if (!info) return 0;
1091 sizeXor = info->nHeight * info->nWidthBytes;
1092 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1093 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1094 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1095 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1096 return MAKELONG( sizeXor, sizeXor );
1100 /***********************************************************************
1101 * SetCursor16 (USER.69)
1103 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1105 return (HCURSOR16)SetCursor32( hCursor );
1109 /***********************************************************************
1110 * SetCursor32 (USER32.472)
1111 * RETURNS:
1112 * A handle to the previous cursor shape.
1114 HCURSOR32 WINAPI SetCursor32(
1115 HCURSOR32 hCursor /* Handle of cursor to show */
1117 HCURSOR32 hOldCursor;
1119 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1120 TRACE(cursor, "%04x\n", hCursor );
1121 hOldCursor = hActiveCursor;
1122 hActiveCursor = hCursor;
1123 /* Change the cursor shape only if it is visible */
1124 if (CURSOR_ShowCount >= 0)
1126 DISPLAY_SetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1127 GlobalUnlock16( hActiveCursor );
1129 return hOldCursor;
1133 /***********************************************************************
1134 * SetCursorPos16 (USER.70)
1136 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1138 SetCursorPos32( x, y );
1142 /***********************************************************************
1143 * SetCursorPos32 (USER32.474)
1145 BOOL32 WINAPI SetCursorPos32( INT32 x, INT32 y )
1147 DISPLAY_MoveCursor( x, y );
1148 return TRUE;
1152 /***********************************************************************
1153 * ShowCursor16 (USER.71)
1155 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1157 return ShowCursor32( bShow );
1161 /***********************************************************************
1162 * ShowCursor32 (USER32.530)
1164 INT32 WINAPI ShowCursor32( BOOL32 bShow )
1166 TRACE(cursor, "%d, count=%d\n",
1167 bShow, CURSOR_ShowCount );
1169 if (bShow)
1171 if (++CURSOR_ShowCount == 0) /* Show it */
1173 DISPLAY_SetCursor((CURSORICONINFO*)GlobalLock16( hActiveCursor ));
1174 GlobalUnlock16( hActiveCursor );
1177 else
1179 if (--CURSOR_ShowCount == -1) /* Hide it */
1180 DISPLAY_SetCursor( NULL );
1182 return CURSOR_ShowCount;
1186 /***********************************************************************
1187 * GetCursor16 (USER.247)
1189 HCURSOR16 WINAPI GetCursor16(void)
1191 return hActiveCursor;
1195 /***********************************************************************
1196 * GetCursor32 (USER32.227)
1198 HCURSOR32 WINAPI GetCursor32(void)
1200 return hActiveCursor;
1204 /***********************************************************************
1205 * ClipCursor16 (USER.16)
1207 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1209 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1210 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1211 return TRUE;
1215 /***********************************************************************
1216 * ClipCursor32 (USER32.53)
1218 BOOL32 WINAPI ClipCursor32( const RECT32 *rect )
1220 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1221 else CopyRect32( &CURSOR_ClipRect, rect );
1222 return TRUE;
1226 /***********************************************************************
1227 * GetCursorPos16 (USER.17)
1229 void WINAPI GetCursorPos16( POINT16 *pt )
1231 DWORD posX, posY, state;
1233 if (!pt) return;
1234 if (!EVENT_QueryPointer( &posX, &posY, &state ))
1235 pt->x = pt->y = 0;
1236 else
1238 pt->x = posX;
1239 pt->y = posY;
1240 if (state & MK_LBUTTON)
1241 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1242 else
1243 MouseButtonsStates[0] = FALSE;
1244 if (state & MK_MBUTTON)
1245 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1246 else
1247 MouseButtonsStates[1] = FALSE;
1248 if (state & MK_RBUTTON)
1249 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1250 else
1251 MouseButtonsStates[2] = FALSE;
1253 TRACE(cursor, "ret=%d,%d\n", pt->x, pt->y );
1257 /***********************************************************************
1258 * GetCursorPos32 (USER32.229)
1260 void WINAPI GetCursorPos32( POINT32 *pt )
1262 POINT16 pt16;
1263 GetCursorPos16( &pt16 );
1264 if (pt) CONV_POINT16TO32( &pt16, pt );
1268 /***********************************************************************
1269 * GetClipCursor16 (USER.309)
1271 void WINAPI GetClipCursor16( RECT16 *rect )
1273 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1277 /***********************************************************************
1278 * GetClipCursor32 (USER32.221)
1280 void WINAPI GetClipCursor32( RECT32 *rect )
1282 if (rect) CopyRect32( rect, &CURSOR_ClipRect );
1285 /**********************************************************************
1286 * LookupIconIdFromDirectoryEx16 (USER.364)
1288 * FIXME: exact parameter sizes
1290 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1291 INT16 width, INT16 height, UINT16 cFlag )
1293 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1294 UINT16 retVal = 0;
1295 if( dir && !dir->idReserved && (dir->idType & 3) )
1297 int colors = (cFlag & LR_MONOCHROME) ? 2 : COLOR_GetSystemPaletteSize();
1298 if( bIcon )
1300 ICONDIRENTRY* entry;
1301 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1302 if( entry ) retVal = entry->wResId;
1304 else
1306 CURSORDIRENTRY* entry;
1307 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1308 if( entry ) retVal = entry->wResId;
1311 else WARN(cursor, "invalid resource directory\n");
1312 return retVal;
1315 /**********************************************************************
1316 * LookupIconIdFromDirectoryEx32 (USER32.380)
1318 INT32 WINAPI LookupIconIdFromDirectoryEx32( LPBYTE dir, BOOL32 bIcon,
1319 INT32 width, INT32 height, UINT32 cFlag )
1321 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1324 /**********************************************************************
1325 * LookupIconIdFromDirectory (USER.???)
1327 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1329 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1330 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1331 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1334 /**********************************************************************
1335 * LookupIconIdFromDirectory (USER32.379)
1337 INT32 WINAPI LookupIconIdFromDirectory32( LPBYTE dir, BOOL32 bIcon )
1339 return LookupIconIdFromDirectoryEx32( dir, bIcon,
1340 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1341 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1344 /**********************************************************************
1345 * GetIconID (USER.455)
1347 WORD WINAPI GetIconID( HGLOBAL16 hResource, DWORD resType )
1349 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1351 TRACE(cursor, "hRes=%04x, entries=%i\n",
1352 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1354 switch(resType)
1356 case RT_CURSOR16:
1357 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1358 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1359 case RT_ICON16:
1360 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1361 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1362 default:
1363 WARN(cursor, "invalid res type %ld\n", resType );
1365 return 0;
1368 /**********************************************************************
1369 * LoadCursorIconHandler (USER.336)
1371 * Supposed to load resources of Windows 2.x applications.
1373 HGLOBAL16 WINAPI LoadCursorIconHandler( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1375 FIXME(cursor,"(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1376 hResource, hModule, hRsrc);
1377 return (HGLOBAL16)0;
1380 /**********************************************************************
1381 * LoadDIBIconHandler (USER.357)
1383 * RT_ICON resource loader, installed by USER_SignalProc when module
1384 * is initialized.
1386 HGLOBAL16 WINAPI LoadDIBIconHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1388 /* If hResource is zero we must allocate a new memory block, if it's
1389 * non-zero but GlobalLock() returns NULL then it was discarded and
1390 * we have to recommit some memory, otherwise we just need to check
1391 * the block size. See LoadProc() in 16-bit SDK for more.
1394 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1395 if( hMemObj )
1397 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1398 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1399 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1400 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1402 return hMemObj;
1405 /**********************************************************************
1406 * LoadDIBCursorHandler (USER.356)
1408 * RT_CURSOR resource loader. Same as above.
1410 HGLOBAL16 WINAPI LoadDIBCursorHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1412 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1413 if( hMemObj )
1415 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1416 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1417 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1418 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1420 return hMemObj;
1423 /**********************************************************************
1424 * LoadIconHandler (USER.456)
1426 HICON16 WINAPI LoadIconHandler( HGLOBAL16 hResource, BOOL16 bNew )
1428 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1430 TRACE(cursor,"hRes=%04x\n",hResource);
1432 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1433 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1436 /***********************************************************************
1437 * LoadCursorW (USER32.362)
1439 HCURSOR32 WINAPI LoadCursor32W(HINSTANCE32 hInstance, LPCWSTR name)
1441 return CURSORICON_Load32( hInstance, name,
1442 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0);
1445 /***********************************************************************
1446 * LoadCursorA (USER32.359)
1448 HCURSOR32 WINAPI LoadCursor32A(HINSTANCE32 hInstance, LPCSTR name)
1450 HCURSOR32 res=0;
1451 if(!HIWORD(name))
1452 return LoadCursor32W(hInstance,(LPCWSTR)name);
1453 else
1455 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1456 res = LoadCursor32W(hInstance, uni);
1457 HeapFree( GetProcessHeap(), 0, uni);
1459 return res;
1461 /***********************************************************************
1462 * LoadCursorFromFile32W (USER32.361)
1464 HCURSOR32 WINAPI LoadCursorFromFile32W (LPCWSTR name)
1466 return LoadImage32W(0, name, IMAGE_CURSOR, SYSMETRICS_CXCURSOR,
1467 SYSMETRICS_CYCURSOR, LR_LOADFROMFILE);
1470 /***********************************************************************
1471 * LoadCursorFromFile32A (USER32.360)
1473 HCURSOR32 WINAPI LoadCursorFromFile32A (LPCSTR name)
1475 HCURSOR32 hcur;
1476 LPWSTR u_name = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1477 hcur = LoadCursorFromFile32W(u_name);
1478 HeapFree( GetProcessHeap(), 0, u_name );
1479 return hcur;
1482 /***********************************************************************
1483 * LoadIconW (USER32.364)
1485 HICON32 WINAPI LoadIcon32W(HINSTANCE32 hInstance, LPCWSTR name)
1487 return CURSORICON_Load32( hInstance, name,
1488 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
1489 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE, 0);
1492 /***********************************************************************
1493 * LoadIconA (USER32.363)
1495 HICON32 WINAPI LoadIcon32A(HINSTANCE32 hInstance, LPCSTR name)
1497 HICON32 res=0;
1499 if( !HIWORD(name) )
1500 return LoadIcon32W(hInstance, (LPCWSTR)name);
1501 else
1503 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1504 res = LoadIcon32W( hInstance, uni );
1505 HeapFree( GetProcessHeap(), 0, uni );
1507 return res;
1510 /**********************************************************************
1511 * GetIconInfo (USER32.242)
1513 BOOL32 WINAPI GetIconInfo(HICON32 hIcon,LPICONINFO iconinfo) {
1514 CURSORICONINFO *ciconinfo;
1516 ciconinfo = GlobalLock16(hIcon);
1517 if (!ciconinfo)
1518 return FALSE;
1519 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1520 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1521 iconinfo->fIcon = TRUE; /* hmm */
1523 iconinfo->hbmColor = CreateBitmap32 ( ciconinfo->nWidth, ciconinfo->nHeight,
1524 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1525 (char *)(ciconinfo + 1)
1526 + ciconinfo->nHeight *
1527 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1528 iconinfo->hbmMask = CreateBitmap32 ( ciconinfo->nWidth, ciconinfo->nHeight,
1529 1, 1, (char *)(ciconinfo + 1));
1531 GlobalUnlock16(hIcon);
1533 return TRUE;
1536 /**********************************************************************
1537 * CreateIconIndirect (USER32.78)
1539 HICON32 WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1540 BITMAPOBJ *bmpXor,*bmpAnd;
1541 HICON32 hObj;
1542 int sizeXor,sizeAnd;
1544 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1545 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1547 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1548 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1550 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1551 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1552 if (hObj)
1554 CURSORICONINFO *info;
1556 info = (CURSORICONINFO *)GlobalLock16( hObj );
1557 info->ptHotSpot.x = iconinfo->xHotspot;
1558 info->ptHotSpot.y = iconinfo->yHotspot;
1559 info->nWidth = bmpXor->bitmap.bmWidth;
1560 info->nHeight = bmpXor->bitmap.bmHeight;
1561 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1562 info->bPlanes = bmpXor->bitmap.bmPlanes;
1563 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1565 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1567 GetBitmapBits32( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1568 GetBitmapBits32( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1569 GlobalUnlock16( hObj );
1571 return hObj;
1575 /**********************************************************************
1577 DrawIconEx16 (USER.394)
1579 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1580 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1581 HBRUSH16 hbr, UINT16 flags)
1583 return DrawIconEx32(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1584 istep, hbr, flags);
1588 /******************************************************************************
1589 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1591 * NOTES
1592 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1594 * PARAMS
1595 * hdc [I] Handle to device context
1596 * x0 [I] X coordinate of upper left corner
1597 * y0 [I] Y coordinate of upper left corner
1598 * hIcon [I] Handle to icon to draw
1599 * cxWidth [I] Width of icon
1600 * cyWidth [I] Height of icon
1601 * istep [I] Index of frame in animated cursor
1602 * hbr [I] Handle to background brush
1603 * flags [I] Icon-drawing flags
1605 * RETURNS
1606 * Success: TRUE
1607 * Failure: FALSE
1609 BOOL32 WINAPI DrawIconEx32( HDC32 hdc, INT32 x0, INT32 y0, HICON32 hIcon,
1610 INT32 cxWidth, INT32 cyWidth, UINT32 istep,
1611 HBRUSH32 hbr, UINT32 flags )
1613 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1614 HDC32 hDC_off = 0, hMemDC = CreateCompatibleDC32 (hdc);
1615 BOOL32 result = FALSE, DoOffscreen = FALSE;
1616 HBITMAP32 hB_off = 0, hOld = 0;
1618 if (!ptr) return FALSE;
1620 if (istep)
1621 FIXME(icon, "Ignoring istep=%d\n", istep);
1622 if (flags & DI_COMPAT)
1623 FIXME(icon, "Ignoring flag DI_COMPAT\n");
1625 /* Calculate the size of the destination image. */
1626 if (cxWidth == 0)
1628 if (flags & DI_DEFAULTSIZE)
1629 cxWidth = GetSystemMetrics32 (SM_CXICON);
1630 else
1631 cxWidth = ptr->nWidth;
1633 if (cyWidth == 0)
1635 if (flags & DI_DEFAULTSIZE)
1636 cyWidth = GetSystemMetrics32 (SM_CYICON);
1637 else
1638 cyWidth = ptr->nHeight;
1641 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1642 STOCK_HOLLOW_BRUSH)))
1644 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1645 if (object)
1647 UINT16 magic = object->wMagic;
1648 GDI_HEAP_UNLOCK(hbr);
1649 DoOffscreen = magic == BRUSH_MAGIC;
1652 if (DoOffscreen) {
1653 RECT32 r = {0, 0, cxWidth, cxWidth};
1655 hDC_off = CreateCompatibleDC32(hdc);
1656 hB_off = CreateCompatibleBitmap32(hdc, cxWidth, cyWidth);
1657 if (hDC_off && hB_off) {
1658 hOld = SelectObject32(hDC_off, hB_off);
1659 FillRect32(hDC_off, &r, hbr);
1663 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1665 HBITMAP32 hXorBits, hAndBits;
1666 COLORREF oldFg, oldBg;
1667 INT32 nStretchMode;
1669 nStretchMode = SetStretchBltMode32 (hdc, STRETCH_DELETESCANS);
1671 hXorBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
1672 ptr->bPlanes, ptr->bBitsPerPixel,
1673 (char *)(ptr + 1)
1674 + ptr->nHeight *
1675 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1676 hAndBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
1677 1, 1, (char *)(ptr+1) );
1678 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
1679 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
1681 if (hXorBits && hAndBits)
1683 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
1684 if (flags & DI_MASK)
1686 if (DoOffscreen)
1687 StretchBlt32 (hDC_off, 0, 0, cxWidth, cyWidth,
1688 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1689 else
1690 StretchBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1691 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1693 SelectObject32( hMemDC, hXorBits );
1694 if (flags & DI_IMAGE)
1696 if (DoOffscreen)
1697 StretchBlt32 (hDC_off, 0, 0, cxWidth, cyWidth,
1698 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1699 else
1700 StretchBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1701 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1703 SelectObject32( hMemDC, hBitTemp );
1704 result = TRUE;
1707 SetTextColor32( hdc, oldFg );
1708 SetBkColor32( hdc, oldBg );
1709 if (hXorBits) DeleteObject32( hXorBits );
1710 if (hAndBits) DeleteObject32( hAndBits );
1711 SetStretchBltMode32 (hdc, nStretchMode);
1712 if (DoOffscreen) {
1713 BitBlt32(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
1714 SelectObject32(hDC_off, hOld);
1717 if (hMemDC) DeleteDC32( hMemDC );
1718 if (hDC_off) DeleteDC32(hDC_off);
1719 if (hB_off) DeleteObject32(hB_off);
1720 GlobalUnlock16( hIcon );
1721 return result;