Fixes for upside-down DIBs.
[wine/dcerpc.git] / objects / cursoricon.c
blob7509af6c1b0a2974111e6829679786e4bbc4b932
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>
35 #include "wine/winbase16.h"
36 #include "wine/winuser16.h"
37 #include "heap.h"
38 #include "color.h"
39 #include "bitmap.h"
40 #include "cursoricon.h"
41 #include "dc.h"
42 #include "gdi.h"
43 #include "sysmetrics.h"
44 #include "global.h"
45 #include "module.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 HCURSOR hActiveCursor = 0; /* Active cursor */
55 static INT CURSOR_ShowCount = 0; /* Cursor display count */
56 static RECT CURSOR_ClipRect; /* Cursor clipping rect */
59 /**********************************************************************
60 * ICONCACHE for cursors/icons loaded with LR_SHARED.
62 * FIXME: This should not be allocated on the system heap, but on a
63 * subsystem-global heap (i.e. one for all Win16 processes,
64 * and one each for every Win32 process).
66 typedef struct tagICONCACHE
68 struct tagICONCACHE *next;
70 HMODULE hModule;
71 HRSRC hRsrc;
72 HANDLE handle;
74 INT count;
76 } ICONCACHE;
78 static ICONCACHE *IconAnchor = NULL;
79 static CRITICAL_SECTION IconCrst;
81 /**********************************************************************
82 * CURSORICON_Init
84 void CURSORICON_Init( void )
86 InitializeCriticalSection( &IconCrst );
87 MakeCriticalSectionGlobal( &IconCrst );
90 /**********************************************************************
91 * CURSORICON_FindSharedIcon
93 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
95 HANDLE handle = 0;
96 ICONCACHE *ptr;
98 EnterCriticalSection( &IconCrst );
100 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
101 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
103 ptr->count++;
104 handle = ptr->handle;
105 break;
108 LeaveCriticalSection( &IconCrst );
110 return handle;
113 /**********************************************************************
114 * CURSORICON_AddSharedIcon
116 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HANDLE handle )
118 ICONCACHE *ptr = HeapAlloc( SystemHeap, 0, sizeof(ICONCACHE) );
119 if ( !ptr ) return;
121 ptr->hModule = hModule;
122 ptr->hRsrc = hRsrc;
123 ptr->handle = handle;
124 ptr->count = 1;
126 EnterCriticalSection( &IconCrst );
127 ptr->next = IconAnchor;
128 IconAnchor = ptr;
129 LeaveCriticalSection( &IconCrst );
132 /**********************************************************************
133 * CURSORICON_DelSharedIcon
135 static INT CURSORICON_DelSharedIcon( HANDLE handle )
137 INT count = -1;
138 ICONCACHE *ptr;
140 EnterCriticalSection( &IconCrst );
142 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
143 if ( ptr->handle == handle )
145 if ( ptr->count > 0 ) ptr->count--;
146 count = ptr->count;
147 break;
150 LeaveCriticalSection( &IconCrst );
152 return count;
155 /**********************************************************************
156 * CURSORICON_FreeModuleIcons
158 void CURSORICON_FreeModuleIcons( HMODULE hModule )
160 ICONCACHE **ptr = &IconAnchor;
162 if ( HIWORD( hModule ) )
163 hModule = MapHModuleLS( hModule );
164 else
165 hModule = GetExePtr( hModule );
167 EnterCriticalSection( &IconCrst );
169 while ( *ptr )
171 if ( (*ptr)->hModule == hModule )
173 ICONCACHE *freePtr = *ptr;
174 *ptr = freePtr->next;
176 GlobalFree16( freePtr->handle );
177 HeapFree( SystemHeap, 0, freePtr );
178 continue;
180 ptr = &(*ptr)->next;
183 LeaveCriticalSection( &IconCrst );
186 /**********************************************************************
187 * CURSORICON_FindBestIcon
189 * Find the icon closest to the requested size and number of colors.
191 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
192 int height, int colors )
194 int i, maxcolors, maxwidth, maxheight;
195 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
197 if (dir->idCount < 1)
199 WARN(icon, "Empty directory!\n" );
200 return NULL;
202 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
204 /* First find the exact size with less colors */
206 maxcolors = 0;
207 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
208 if ((entry->ResInfo.icon.bWidth == width) && (entry->ResInfo.icon.bHeight == height) &&
209 (entry->ResInfo.icon.bColorCount <= colors) && (entry->ResInfo.icon.bColorCount > maxcolors))
211 bestEntry = entry;
212 maxcolors = entry->ResInfo.icon.bColorCount;
214 if (bestEntry) return bestEntry;
216 /* First find the exact size with more colors */
218 maxcolors = 255;
219 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
220 if ((entry->ResInfo.icon.bWidth == width) && (entry->ResInfo.icon.bHeight == height) &&
221 (entry->ResInfo.icon.bColorCount > colors) && (entry->ResInfo.icon.bColorCount <= maxcolors))
223 bestEntry = entry;
224 maxcolors = entry->ResInfo.icon.bColorCount;
226 if (bestEntry) return bestEntry;
228 /* Now find a smaller one with less colors */
230 maxcolors = maxwidth = maxheight = 0;
231 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
232 if ((entry->ResInfo.icon.bWidth <= width) && (entry->ResInfo.icon.bHeight <= height) &&
233 (entry->ResInfo.icon.bWidth >= maxwidth) && (entry->ResInfo.icon.bHeight >= maxheight) &&
234 (entry->ResInfo.icon.bColorCount <= colors) && (entry->ResInfo.icon.bColorCount > maxcolors))
236 bestEntry = entry;
237 maxwidth = entry->ResInfo.icon.bWidth;
238 maxheight = entry->ResInfo.icon.bHeight;
239 maxcolors = entry->ResInfo.icon.bColorCount;
241 if (bestEntry) return bestEntry;
243 /* Now find a smaller one with more colors */
245 maxcolors = 255;
246 maxwidth = maxheight = 0;
247 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
248 if ((entry->ResInfo.icon.bWidth <= width) && (entry->ResInfo.icon.bHeight <= height) &&
249 (entry->ResInfo.icon.bWidth >= maxwidth) && (entry->ResInfo.icon.bHeight >= maxheight) &&
250 (entry->ResInfo.icon.bColorCount > colors) && (entry->ResInfo.icon.bColorCount <= maxcolors))
252 bestEntry = entry;
253 maxwidth = entry->ResInfo.icon.bWidth;
254 maxheight = entry->ResInfo.icon.bHeight;
255 maxcolors = entry->ResInfo.icon.bColorCount;
257 if (bestEntry) return bestEntry;
259 /* Now find a larger one with less colors */
261 maxcolors = 0;
262 maxwidth = maxheight = 255;
263 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
264 if ((entry->ResInfo.icon.bWidth <= maxwidth) && (entry->ResInfo.icon.bHeight <= maxheight) &&
265 (entry->ResInfo.icon.bColorCount <= colors) && (entry->ResInfo.icon.bColorCount > maxcolors))
267 bestEntry = entry;
268 maxwidth = entry->ResInfo.icon.bWidth;
269 maxheight = entry->ResInfo.icon.bHeight;
270 maxcolors = entry->ResInfo.icon.bColorCount;
272 if (bestEntry) return bestEntry;
274 /* Now find a larger one with more colors */
276 maxcolors = maxwidth = maxheight = 255;
277 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
278 if ((entry->ResInfo.icon.bWidth <= maxwidth) && (entry->ResInfo.icon.bHeight <= maxheight) &&
279 (entry->ResInfo.icon.bColorCount > colors) && (entry->ResInfo.icon.bColorCount <= maxcolors))
281 bestEntry = entry;
282 maxwidth = entry->ResInfo.icon.bWidth;
283 maxheight = entry->ResInfo.icon.bHeight;
284 maxcolors = entry->ResInfo.icon.bColorCount;
287 return bestEntry;
291 /**********************************************************************
292 * CURSORICON_FindBestCursor
294 * Find the cursor closest to the requested size.
295 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
296 * ignored too
298 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
299 int width, int height, int color)
301 int i, maxwidth, maxheight;
302 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
304 if (dir->idCount < 1)
306 WARN(cursor, "Empty directory!\n" );
307 return NULL;
309 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
311 /* First find the largest one smaller than or equal to the requested size*/
313 maxwidth = maxheight = 0;
314 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
315 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
316 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
317 (entry->wBitCount == 1))
319 bestEntry = entry;
320 maxwidth = entry->ResInfo.cursor.wWidth;
321 maxheight = entry->ResInfo.cursor.wHeight;
323 if (bestEntry) return bestEntry;
325 /* Now find the smallest one larger than the requested size */
327 maxwidth = maxheight = 255;
328 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
329 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
330 (entry->wBitCount == 1))
332 bestEntry = entry;
333 maxwidth = entry->ResInfo.cursor.wWidth;
334 maxheight = entry->ResInfo.cursor.wHeight;
337 return bestEntry;
340 /*********************************************************************
341 * The main purpose of this function is to create fake resource directory
342 * and fake resource entries. There are several reasons for this:
343 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
344 * fields
345 * There are some "bad" cursor files which do not have
346 * bColorCount initialized but instead one must read this info
347 * directly from corresponding DIB sections
348 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
350 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
351 CURSORICONDIR **res, LPBYTE **ptr)
353 LPBYTE _free;
354 CURSORICONFILEDIR *bits;
355 int entries, size, i;
357 *res = NULL;
358 *ptr = NULL;
359 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
361 /* FIXME: test for inimated icons
362 * hack to load the first icon from the *.ani file
364 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
365 { LPBYTE pos = (LPBYTE) bits;
366 FIXME (cursor,"Animated icons not correctly implemented! %p \n", bits);
368 for (;;)
369 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
370 { FIXME (cursor,"icon entry found! %p\n", bits);
371 pos+=4;
372 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
373 { goto fail;
375 bits+=2;
376 FIXME (cursor,"icon size ok %p \n", bits);
377 break;
379 pos+=2;
380 if (pos>=(LPBYTE)bits+766) goto fail;
383 if (!(entries = bits->idCount)) goto fail;
384 (int)_free = size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) *
385 (entries - 1);
386 for (i=0; i < entries; i++)
387 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
389 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
390 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
391 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
393 _free = (LPBYTE)(*res) + (int)_free;
394 memcpy((*res), bits, 6);
395 for (i=0; i<entries; i++)
397 ((LPBYTE*)(*ptr))[i] = _free;
398 if (fCursor) {
399 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
400 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
401 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
402 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
403 _free+=sizeof(POINT16);
404 } else {
405 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
406 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
407 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
409 (*res)->idEntries[i].wPlanes=1;
410 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
411 bits->idEntries[i].dwDIBOffset))->biBitCount;
412 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
413 (*res)->idEntries[i].wResId=i+1;
415 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
416 (*res)->idEntries[i].dwBytesInRes);
417 _free += (*res)->idEntries[i].dwBytesInRes;
419 UnmapViewOfFile( bits );
420 return TRUE;
421 fail:
422 if (*res) HeapFree( GetProcessHeap(), 0, *res );
423 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
424 UnmapViewOfFile( bits );
425 return FALSE;
429 /**********************************************************************
430 * CURSORICON_CreateFromResource
432 * Create a cursor or icon from in-memory resource template.
434 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
435 * with cbSize parameter as well.
437 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
438 UINT cbSize, BOOL bIcon, DWORD dwVersion,
439 INT width, INT height, UINT loadflags )
441 int sizeAnd, sizeXor;
442 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
443 BITMAPOBJ *bmpXor, *bmpAnd;
444 POINT16 hotspot = { 0 ,0 };
445 BITMAPINFO *bmi;
446 HDC hdc;
447 BOOL DoStretch;
448 INT size;
450 TRACE(cursor,"%08x (%u bytes), ver %08x, %ix%i %s %s\n",
451 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
452 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
453 if (dwVersion == 0x00020000)
455 FIXME(cursor,"\t2.xx resources are not supported\n");
456 return 0;
459 if (bIcon)
460 bmi = (BITMAPINFO *)bits;
461 else /* get the hotspot */
463 POINT16 *pt = (POINT16 *)bits;
464 hotspot = *pt;
465 bmi = (BITMAPINFO *)(pt + 1);
467 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
469 if (!width) width = bmi->bmiHeader.biWidth;
470 if (!height) height = bmi->bmiHeader.biHeight/2;
471 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
472 (bmi->bmiHeader.biWidth != width);
474 /* Check bitmap header */
476 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
477 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
478 bmi->bmiHeader.biCompression != BI_RGB) )
480 WARN(cursor,"\tinvalid resource bitmap header.\n");
481 return 0;
484 if( (hdc = GetDC( 0 )) )
486 BITMAPINFO* pInfo;
488 /* Make sure we have room for the monochrome bitmap later on.
489 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
490 * up to and including the biBitCount. In-memory icon resource
491 * format is as follows:
493 * BITMAPINFOHEADER icHeader // DIB header
494 * RGBQUAD icColors[] // Color table
495 * BYTE icXOR[] // DIB bits for XOR mask
496 * BYTE icAND[] // DIB bits for AND mask
499 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
500 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
502 memcpy( pInfo, bmi, size );
503 pInfo->bmiHeader.biHeight /= 2;
505 /* Create the XOR bitmap */
507 if (DoStretch) {
508 if ((hXorBits = CreateCompatibleBitmap(hdc, width, height))) {
509 HBITMAP hOld;
510 HDC hMem = CreateCompatibleDC(hdc);
511 BOOL res;
513 if (hMem) {
514 hOld = SelectObject(hMem, hXorBits);
515 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
516 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
517 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
518 SelectObject(hMem, hOld);
519 DeleteDC(hMem);
520 } else res = FALSE;
521 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
523 } else hXorBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
524 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
525 if( hXorBits )
527 char* bits = (char *)bmi + size +
528 DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
529 bmi->bmiHeader.biHeight,
530 bmi->bmiHeader.biBitCount) / 2;
532 pInfo->bmiHeader.biBitCount = 1;
533 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
535 RGBQUAD *rgb = pInfo->bmiColors;
537 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
538 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
539 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
540 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
542 else
544 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
546 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
547 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
550 /* Create the AND bitmap */
552 if (DoStretch) {
553 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
554 HBITMAP hOld;
555 HDC hMem = CreateCompatibleDC(hdc);
556 BOOL res;
558 if (hMem) {
559 hOld = SelectObject(hMem, hAndBits);
560 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
561 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
562 bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
563 SelectObject(hMem, hOld);
564 DeleteDC(hMem);
565 } else res = FALSE;
566 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
568 } else hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
569 CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
571 if( !hAndBits ) DeleteObject( hXorBits );
573 HeapFree( GetProcessHeap(), 0, pInfo );
575 ReleaseDC( 0, hdc );
578 if( !hXorBits || !hAndBits )
580 WARN(cursor,"\tunable to create an icon bitmap.\n");
581 return 0;
584 /* Now create the CURSORICONINFO structure */
585 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
586 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
587 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
588 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
590 if (hObj) hObj = GlobalReAlloc16( hObj,
591 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
592 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
593 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
594 if (hObj)
596 CURSORICONINFO *info;
598 /* Make it owned by the module */
599 if (hInstance) FarSetOwner16( hObj, GetExePtr(hInstance) );
601 info = (CURSORICONINFO *)GlobalLock16( hObj );
602 info->ptHotSpot.x = hotspot.x;
603 info->ptHotSpot.y = hotspot.y;
604 info->nWidth = bmpXor->bitmap.bmWidth;
605 info->nHeight = bmpXor->bitmap.bmHeight;
606 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
607 info->bPlanes = bmpXor->bitmap.bmPlanes;
608 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
610 /* Transfer the bitmap bits to the CURSORICONINFO structure */
612 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
613 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
614 GlobalUnlock16( hObj );
617 DeleteObject( hXorBits );
618 DeleteObject( hAndBits );
619 return hObj;
623 /**********************************************************************
624 * CreateIconFromResourceEx16 (USER.450)
626 * FIXME: not sure about exact parameter types
628 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
629 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
631 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
632 width, height, cFlag);
636 /**********************************************************************
637 * CreateIconFromResource (USER32.76)
639 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
640 BOOL bIcon, DWORD dwVersion)
642 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
646 /**********************************************************************
647 * CreateIconFromResourceEx32 (USER32.77)
649 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
650 BOOL bIcon, DWORD dwVersion,
651 INT width, INT height,
652 UINT cFlag )
654 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
655 if( pTask )
656 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
657 width, height, cFlag );
658 return 0;
661 /**********************************************************************
662 * CURSORICON_Load
664 * Load a cursor or icon from resource or file.
666 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
667 INT width, INT height, INT colors,
668 BOOL fCursor, UINT loadflags )
670 HANDLE handle = 0, h = 0;
671 HANDLE hRsrc;
672 CURSORICONDIR *dir;
673 CURSORICONDIRENTRY *dirEntry;
674 LPBYTE bits;
676 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
678 LPBYTE *ptr;
679 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
680 return 0;
681 if (fCursor)
682 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
683 else
684 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
685 bits = ptr[dirEntry->wResId-1];
686 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
687 !fCursor, 0x00030000, width, height, loadflags);
688 HeapFree( GetProcessHeap(), 0, dir );
689 HeapFree( GetProcessHeap(), 0, ptr );
692 else if ( !hInstance ) /* Load OEM cursor/icon */
694 WORD resid;
695 HDC hdc;
696 DC *dc;
698 if ( HIWORD(name) )
700 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
701 if( ansi[0]=='#') /*Check for '#xxx' name */
703 resid = atoi(ansi+1);
704 HeapFree( GetProcessHeap(), 0, ansi );
706 else
708 HeapFree( GetProcessHeap(), 0, ansi );
709 return 0;
712 else resid = LOWORD(name);
713 hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
714 dc = DC_GetDCPtr( hdc );
715 if (dc->funcs->pLoadOEMResource)
716 h = dc->funcs->pLoadOEMResource( resid, fCursor ?
717 OEM_CURSOR : OEM_ICON );
718 GDI_HEAP_UNLOCK( hdc );
719 DeleteDC( hdc );
722 else /* Load from resource */
724 WORD wResId;
725 DWORD dwBytesInRes;
727 /* Normalize hInstance (must be uniquely represented for icon cache) */
729 if ( HIWORD( hInstance ) )
730 hInstance = MapHModuleLS( hInstance );
731 else
732 hInstance = GetExePtr( hInstance );
734 /* Get directory resource ID */
736 if (!(hRsrc = FindResourceW( hInstance, name,
737 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
738 return 0;
740 /* If shared icon, check whether it was already loaded */
742 if ( (loadflags & LR_SHARED)
743 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
744 return h;
746 /* Find the best entry in the directory */
748 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
749 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
750 if (fCursor)
751 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
752 width, height, 1);
753 else
754 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
755 width, height, colors );
756 if (!dirEntry) return 0;
757 wResId = dirEntry->wResId;
758 dwBytesInRes = dirEntry->dwBytesInRes;
759 FreeResource( handle );
761 /* Load the resource */
763 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
764 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
765 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
766 bits = (LPBYTE)LockResource( handle );
767 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
768 !fCursor, 0x00030000, width, height, loadflags);
769 FreeResource( handle );
771 /* If shared icon, add to icon cache */
773 if ( h && (loadflags & LR_SHARED) )
774 CURSORICON_AddSharedIcon( hInstance, hRsrc, h );
777 return h;
780 /***********************************************************************
781 * CURSORICON_Copy
783 * Make a copy of a cursor or icon.
785 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
787 char *ptrOld, *ptrNew;
788 int size;
789 HGLOBAL16 hNew;
791 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
792 if (!(hInstance = GetExePtr( hInstance ))) return 0;
793 size = GlobalSize16( handle );
794 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
795 FarSetOwner16( hNew, hInstance );
796 ptrNew = (char *)GlobalLock16( hNew );
797 memcpy( ptrNew, ptrOld, size );
798 GlobalUnlock16( handle );
799 GlobalUnlock16( hNew );
800 return hNew;
803 /***********************************************************************
804 * CURSORICON_IconToCursor
806 * Converts bitmap to mono and truncates if icon is too large (should
807 * probably do StretchBlt() instead).
809 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
811 HCURSOR16 hRet = 0;
812 CURSORICONINFO *pIcon = NULL;
813 HTASK16 hTask = GetCurrentTask();
814 TDB* pTask = (TDB *)GlobalLock16(hTask);
816 if(hIcon && pTask)
817 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
818 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
819 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
820 else
822 BYTE pAndBits[128];
823 BYTE pXorBits[128];
824 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
825 BYTE* psPtr, *pxbPtr = pXorBits;
826 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
827 BYTE* pbc = NULL;
829 CURSORICONINFO cI;
831 TRACE(icon, "[%04x] %ix%i %ibpp (bogus %ibps)\n",
832 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
834 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
835 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
836 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
838 memset(pXorBits, 0, 128);
839 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
840 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
841 cI.nWidth = 32; cI.nHeight = 32;
842 cI.nWidthBytes = 4; /* 32x1bpp */
844 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
845 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
847 for( iy = 0; iy < maxy; iy++ )
849 unsigned shift = iy % 2;
851 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
852 (and_width > 4) ? 4 : and_width );
853 for( ix = 0; ix < maxx; ix++ )
855 if( bSemiTransparent && ((ix+shift)%2) )
857 /* set AND bit, XOR bit stays 0 */
859 pbc = pAndBits + iy * 4 + ix/8;
860 *pbc |= 0x80 >> (ix%8);
862 else
864 /* keep AND bit, set XOR bit */
866 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
867 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
868 if(!PALETTE_Driver->pIsDark(val))
870 pbc = pxbPtr + ix/8;
871 *pbc |= 0x80 >> (ix%8);
875 psPtr += xor_width;
876 pxbPtr += 4;
879 hRet = CreateCursorIconIndirect16( pTask->hInstance , &cI, pAndBits, pXorBits);
881 if( !hRet ) /* fall back on default drag cursor */
882 hRet = CURSORICON_Copy( pTask->hInstance ,
883 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
884 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0) );
887 return hRet;
891 /***********************************************************************
892 * LoadCursor16 (USER.173)
894 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
896 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
897 return LoadCursorA( hInstance, nameStr );
901 /***********************************************************************
902 * LoadIcon16 (USER.174)
904 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
906 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
907 return LoadIconA( hInstance, nameStr );
911 /***********************************************************************
912 * CreateCursor16 (USER.406)
914 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
915 INT16 xHotSpot, INT16 yHotSpot,
916 INT16 nWidth, INT16 nHeight,
917 LPCVOID lpANDbits, LPCVOID lpXORbits )
919 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
921 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
922 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
923 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
927 /***********************************************************************
928 * CreateCursor32 (USER32.67)
930 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
931 INT xHotSpot, INT yHotSpot,
932 INT nWidth, INT nHeight,
933 LPCVOID lpANDbits, LPCVOID lpXORbits )
935 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
937 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
938 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
939 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
943 /***********************************************************************
944 * CreateIcon16 (USER.407)
946 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
947 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
948 LPCVOID lpANDbits, LPCVOID lpXORbits )
950 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
952 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
953 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
954 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
958 /***********************************************************************
959 * CreateIcon32 (USER32.75)
961 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
962 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
963 LPCVOID lpANDbits, LPCVOID lpXORbits )
965 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
967 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
968 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
969 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
973 /***********************************************************************
974 * CreateCursorIconIndirect (USER.408)
976 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
977 CURSORICONINFO *info,
978 LPCVOID lpANDbits,
979 LPCVOID lpXORbits )
981 HGLOBAL16 handle;
982 char *ptr;
983 int sizeAnd, sizeXor;
985 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
986 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
987 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
988 sizeXor = info->nHeight * info->nWidthBytes;
989 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
990 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
991 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
992 return 0;
993 if (hInstance) FarSetOwner16( handle, hInstance );
994 ptr = (char *)GlobalLock16( handle );
995 memcpy( ptr, info, sizeof(*info) );
996 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
997 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
998 GlobalUnlock16( handle );
999 return handle;
1003 /***********************************************************************
1004 * CopyIcon16 (USER.368)
1006 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1008 TRACE(icon, "%04x %04x\n", hInstance, hIcon );
1009 return CURSORICON_Copy( hInstance, hIcon );
1013 /***********************************************************************
1014 * CopyIcon32 (USER32.60)
1016 HICON WINAPI CopyIcon( HICON hIcon )
1018 HTASK16 hTask = GetCurrentTask ();
1019 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1020 TRACE(icon, "%04x\n", hIcon );
1021 return CURSORICON_Copy( pTask->hInstance, hIcon );
1025 /***********************************************************************
1026 * CopyCursor16 (USER.369)
1028 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1030 TRACE(cursor, "%04x %04x\n", hInstance, hCursor );
1031 return CURSORICON_Copy( hInstance, hCursor );
1034 /**********************************************************************
1035 * CURSORICON_Destroy (USER.610)
1037 * This routine is actually exported from Win95 USER under the name
1038 * DestroyIcon32 ... The behaviour implemented here should mimic
1039 * the Win95 one exactly, especially the return values, which
1040 * depend on the setting of various flags.
1042 WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1044 WORD retv;
1046 TRACE( icon, "(%04x, %04x)\n", handle, flags );
1048 /* Check whether destroying active cursor */
1050 if ( hActiveCursor == handle )
1052 ERR( cursor, "Destroying active cursor!\n" );
1053 SetCursor( 0 );
1056 /* Try shared cursor/icon first */
1058 if ( !(flags & CID_NONSHARED) )
1060 INT count = CURSORICON_DelSharedIcon( handle );
1062 if ( count != -1 )
1063 return (flags & CID_WIN32)? TRUE : (count == 0);
1065 /* FIXME: OEM cursors/icons should be recognized */
1068 /* Now assume non-shared cursor/icon */
1070 retv = GlobalFree16( handle );
1071 return (flags & CID_RESOURCE)? retv : TRUE;
1074 /***********************************************************************
1075 * DestroyIcon16 (USER.457)
1077 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1079 return CURSORICON_Destroy( hIcon, 0 );
1082 /***********************************************************************
1083 * DestroyIcon (USER32.133)
1085 BOOL WINAPI DestroyIcon( HICON hIcon )
1087 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1090 /***********************************************************************
1091 * DestroyCursor16 (USER.458)
1093 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1095 return CURSORICON_Destroy( hCursor, 0 );
1098 /***********************************************************************
1099 * DestroyCursor (USER32.132)
1101 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1103 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1107 /***********************************************************************
1108 * DrawIcon16 (USER.84)
1110 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1112 return DrawIcon( hdc, x, y, hIcon );
1116 /***********************************************************************
1117 * DrawIcon32 (USER32.159)
1119 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1121 CURSORICONINFO *ptr;
1122 HDC hMemDC;
1123 HBITMAP hXorBits, hAndBits;
1124 COLORREF oldFg, oldBg;
1126 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1127 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1128 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1129 (char *)(ptr+1) );
1130 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1131 ptr->bBitsPerPixel, (char *)(ptr + 1)
1132 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1133 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1134 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1136 if (hXorBits && hAndBits)
1138 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1139 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1140 SelectObject( hMemDC, hXorBits );
1141 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1142 SelectObject( hMemDC, hBitTemp );
1144 DeleteDC( hMemDC );
1145 if (hXorBits) DeleteObject( hXorBits );
1146 if (hAndBits) DeleteObject( hAndBits );
1147 GlobalUnlock16( hIcon );
1148 SetTextColor( hdc, oldFg );
1149 SetBkColor( hdc, oldBg );
1150 return TRUE;
1154 /***********************************************************************
1155 * DumpIcon (USER.459)
1157 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1158 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1160 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1161 int sizeAnd, sizeXor;
1163 if (!info) return 0;
1164 sizeXor = info->nHeight * info->nWidthBytes;
1165 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1166 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1167 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1168 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1169 return MAKELONG( sizeXor, sizeXor );
1173 /***********************************************************************
1174 * SetCursor16 (USER.69)
1176 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1178 return (HCURSOR16)SetCursor( hCursor );
1182 /***********************************************************************
1183 * SetCursor32 (USER32.472)
1184 * RETURNS:
1185 * A handle to the previous cursor shape.
1187 HCURSOR WINAPI SetCursor(
1188 HCURSOR hCursor /* Handle of cursor to show */
1190 HCURSOR hOldCursor;
1192 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1193 TRACE(cursor, "%04x\n", hCursor );
1194 hOldCursor = hActiveCursor;
1195 hActiveCursor = hCursor;
1196 /* Change the cursor shape only if it is visible */
1197 if (CURSOR_ShowCount >= 0)
1199 DISPLAY_SetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1200 GlobalUnlock16( hActiveCursor );
1202 return hOldCursor;
1206 /***********************************************************************
1207 * SetCursorPos16 (USER.70)
1209 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1211 SetCursorPos( x, y );
1215 /***********************************************************************
1216 * SetCursorPos32 (USER32.474)
1218 BOOL WINAPI SetCursorPos( INT x, INT y )
1220 DISPLAY_MoveCursor( x, y );
1221 return TRUE;
1225 /***********************************************************************
1226 * ShowCursor16 (USER.71)
1228 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1230 return ShowCursor( bShow );
1234 /***********************************************************************
1235 * ShowCursor32 (USER32.530)
1237 INT WINAPI ShowCursor( BOOL bShow )
1239 TRACE(cursor, "%d, count=%d\n",
1240 bShow, CURSOR_ShowCount );
1242 if (bShow)
1244 if (++CURSOR_ShowCount == 0) /* Show it */
1246 DISPLAY_SetCursor((CURSORICONINFO*)GlobalLock16( hActiveCursor ));
1247 GlobalUnlock16( hActiveCursor );
1250 else
1252 if (--CURSOR_ShowCount == -1) /* Hide it */
1253 DISPLAY_SetCursor( NULL );
1255 return CURSOR_ShowCount;
1259 /***********************************************************************
1260 * GetCursor16 (USER.247)
1262 HCURSOR16 WINAPI GetCursor16(void)
1264 return hActiveCursor;
1268 /***********************************************************************
1269 * GetCursor32 (USER32.227)
1271 HCURSOR WINAPI GetCursor(void)
1273 return hActiveCursor;
1277 /***********************************************************************
1278 * ClipCursor16 (USER.16)
1280 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1282 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1283 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1284 return TRUE;
1288 /***********************************************************************
1289 * ClipCursor32 (USER32.53)
1291 BOOL WINAPI ClipCursor( const RECT *rect )
1293 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1294 else CopyRect( &CURSOR_ClipRect, rect );
1295 return TRUE;
1299 /***********************************************************************
1300 * GetCursorPos16 (USER.17)
1302 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
1304 DWORD posX, posY, state;
1306 if (!pt) return 0;
1307 if (!EVENT_QueryPointer( &posX, &posY, &state ))
1308 pt->x = pt->y = 0;
1309 else
1311 pt->x = posX;
1312 pt->y = posY;
1313 if (state & MK_LBUTTON)
1314 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1315 else
1316 MouseButtonsStates[0] = FALSE;
1317 if (state & MK_MBUTTON)
1318 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1319 else
1320 MouseButtonsStates[1] = FALSE;
1321 if (state & MK_RBUTTON)
1322 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1323 else
1324 MouseButtonsStates[2] = FALSE;
1326 TRACE(cursor, "ret=%d,%d\n", pt->x, pt->y );
1327 return 1;
1331 /***********************************************************************
1332 * GetCursorPos32 (USER32.229)
1334 BOOL WINAPI GetCursorPos( POINT *pt )
1336 BOOL ret;
1338 POINT16 pt16;
1339 ret = GetCursorPos16( &pt16 );
1340 if (pt) CONV_POINT16TO32( &pt16, pt );
1341 return ((pt) ? ret : 0);
1345 /***********************************************************************
1346 * GetClipCursor16 (USER.309)
1348 void WINAPI GetClipCursor16( RECT16 *rect )
1350 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1354 /***********************************************************************
1355 * GetClipCursor32 (USER32.221)
1357 BOOL WINAPI GetClipCursor( RECT *rect )
1359 if (rect)
1361 CopyRect( rect, &CURSOR_ClipRect );
1362 return TRUE;
1364 return FALSE;
1367 /**********************************************************************
1368 * LookupIconIdFromDirectoryEx16 (USER.364)
1370 * FIXME: exact parameter sizes
1372 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1373 INT16 width, INT16 height, UINT16 cFlag )
1375 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1376 UINT16 retVal = 0;
1377 if( dir && !dir->idReserved && (dir->idType & 3) )
1379 CURSORICONDIRENTRY* entry;
1380 HDC hdc;
1381 UINT palEnts;
1382 int colors;
1383 hdc = GetDC(0);
1384 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1385 if (palEnts == 0)
1386 palEnts = 256;
1387 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1389 ReleaseDC(0, hdc);
1391 if( bIcon )
1392 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1393 else
1394 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1396 if( entry ) retVal = entry->wResId;
1398 else WARN(cursor, "invalid resource directory\n");
1399 return retVal;
1402 /**********************************************************************
1403 * LookupIconIdFromDirectoryEx32 (USER32.380)
1405 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1406 INT width, INT height, UINT cFlag )
1408 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1411 /**********************************************************************
1412 * LookupIconIdFromDirectory (USER.???)
1414 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1416 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1417 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1418 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1421 /**********************************************************************
1422 * LookupIconIdFromDirectory (USER32.379)
1424 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1426 return LookupIconIdFromDirectoryEx( dir, bIcon,
1427 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1428 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1431 /**********************************************************************
1432 * GetIconID (USER.455)
1434 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1436 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1438 TRACE(cursor, "hRes=%04x, entries=%i\n",
1439 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1441 switch(resType)
1443 case RT_CURSOR16:
1444 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1445 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1446 case RT_ICON16:
1447 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1448 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1449 default:
1450 WARN(cursor, "invalid res type %ld\n", resType );
1452 return 0;
1455 /**********************************************************************
1456 * LoadCursorIconHandler (USER.336)
1458 * Supposed to load resources of Windows 2.x applications.
1460 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1462 FIXME(cursor,"(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1463 hResource, hModule, hRsrc);
1464 return (HGLOBAL16)0;
1467 /**********************************************************************
1468 * LoadDIBIconHandler (USER.357)
1470 * RT_ICON resource loader, installed by USER_SignalProc when module
1471 * is initialized.
1473 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1475 /* If hResource is zero we must allocate a new memory block, if it's
1476 * non-zero but GlobalLock() returns NULL then it was discarded and
1477 * we have to recommit some memory, otherwise we just need to check
1478 * the block size. See LoadProc() in 16-bit SDK for more.
1481 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1482 if( hMemObj )
1484 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1485 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1486 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1487 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1489 return hMemObj;
1492 /**********************************************************************
1493 * LoadDIBCursorHandler (USER.356)
1495 * RT_CURSOR resource loader. Same as above.
1497 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1499 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1500 if( hMemObj )
1502 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1503 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1504 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1505 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1507 return hMemObj;
1510 /**********************************************************************
1511 * LoadIconHandler (USER.456)
1513 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1515 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1517 TRACE(cursor,"hRes=%04x\n",hResource);
1519 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1520 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1523 /***********************************************************************
1524 * LoadCursorW (USER32.362)
1526 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1528 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1529 LR_SHARED | LR_DEFAULTSIZE );
1532 /***********************************************************************
1533 * LoadCursorA (USER32.359)
1535 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1537 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1538 LR_SHARED | LR_DEFAULTSIZE );
1541 /***********************************************************************
1542 * LoadCursorFromFileW (USER32.361)
1544 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1546 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1547 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1550 /***********************************************************************
1551 * LoadCursorFromFileA (USER32.360)
1553 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1555 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1556 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1559 /***********************************************************************
1560 * LoadIconW (USER32.364)
1562 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1564 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1565 LR_SHARED | LR_DEFAULTSIZE );
1568 /***********************************************************************
1569 * LoadIconA (USER32.363)
1571 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1573 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1574 LR_SHARED | LR_DEFAULTSIZE );
1577 /**********************************************************************
1578 * GetIconInfo16 (USER.395)
1580 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1582 ICONINFO ii32;
1583 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1585 iconinfo->fIcon = ii32.fIcon;
1586 iconinfo->xHotspot = ii32.xHotspot;
1587 iconinfo->yHotspot = ii32.yHotspot;
1588 iconinfo->hbmMask = ii32.hbmMask;
1589 iconinfo->hbmColor = ii32.hbmColor;
1590 return ret;
1593 /**********************************************************************
1594 * GetIconInfo32 (USER32.242)
1596 BOOL WINAPI GetIconInfo(HICON hIcon,LPICONINFO iconinfo) {
1597 CURSORICONINFO *ciconinfo;
1599 ciconinfo = GlobalLock16(hIcon);
1600 if (!ciconinfo)
1601 return FALSE;
1602 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1603 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1604 iconinfo->fIcon = TRUE; /* hmm */
1606 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1607 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1608 (char *)(ciconinfo + 1)
1609 + ciconinfo->nHeight *
1610 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1611 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1612 1, 1, (char *)(ciconinfo + 1));
1614 GlobalUnlock16(hIcon);
1616 return TRUE;
1619 /**********************************************************************
1620 * CreateIconIndirect (USER32.78)
1622 HICON WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1623 BITMAPOBJ *bmpXor,*bmpAnd;
1624 HICON hObj;
1625 int sizeXor,sizeAnd;
1627 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1628 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1630 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1631 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1633 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1634 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1635 if (hObj)
1637 CURSORICONINFO *info;
1639 info = (CURSORICONINFO *)GlobalLock16( hObj );
1640 info->ptHotSpot.x = iconinfo->xHotspot;
1641 info->ptHotSpot.y = iconinfo->yHotspot;
1642 info->nWidth = bmpXor->bitmap.bmWidth;
1643 info->nHeight = bmpXor->bitmap.bmHeight;
1644 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1645 info->bPlanes = bmpXor->bitmap.bmPlanes;
1646 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1648 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1650 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1651 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1652 GlobalUnlock16( hObj );
1654 return hObj;
1658 /**********************************************************************
1660 DrawIconEx16 (USER.394)
1662 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1663 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1664 HBRUSH16 hbr, UINT16 flags)
1666 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1667 istep, hbr, flags);
1671 /******************************************************************************
1672 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1674 * NOTES
1675 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1677 * PARAMS
1678 * hdc [I] Handle to device context
1679 * x0 [I] X coordinate of upper left corner
1680 * y0 [I] Y coordinate of upper left corner
1681 * hIcon [I] Handle to icon to draw
1682 * cxWidth [I] Width of icon
1683 * cyWidth [I] Height of icon
1684 * istep [I] Index of frame in animated cursor
1685 * hbr [I] Handle to background brush
1686 * flags [I] Icon-drawing flags
1688 * RETURNS
1689 * Success: TRUE
1690 * Failure: FALSE
1692 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1693 INT cxWidth, INT cyWidth, UINT istep,
1694 HBRUSH hbr, UINT flags )
1696 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1697 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1698 BOOL result = FALSE, DoOffscreen = FALSE;
1699 HBITMAP hB_off = 0, hOld = 0;
1701 if (!ptr) return FALSE;
1703 if (istep)
1704 FIXME(icon, "Ignoring istep=%d\n", istep);
1705 if (flags & DI_COMPAT)
1706 FIXME(icon, "Ignoring flag DI_COMPAT\n");
1708 /* Calculate the size of the destination image. */
1709 if (cxWidth == 0)
1711 if (flags & DI_DEFAULTSIZE)
1712 cxWidth = GetSystemMetrics (SM_CXICON);
1713 else
1714 cxWidth = ptr->nWidth;
1716 if (cyWidth == 0)
1718 if (flags & DI_DEFAULTSIZE)
1719 cyWidth = GetSystemMetrics (SM_CYICON);
1720 else
1721 cyWidth = ptr->nHeight;
1724 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1725 STOCK_HOLLOW_BRUSH)))
1727 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1728 if (object)
1730 UINT16 magic = object->wMagic;
1731 GDI_HEAP_UNLOCK(hbr);
1732 DoOffscreen = magic == BRUSH_MAGIC;
1735 if (DoOffscreen) {
1736 RECT r = {0, 0, cxWidth, cxWidth};
1738 hDC_off = CreateCompatibleDC(hdc);
1739 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1740 if (hDC_off && hB_off) {
1741 hOld = SelectObject(hDC_off, hB_off);
1742 FillRect(hDC_off, &r, hbr);
1746 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1748 HBITMAP hXorBits, hAndBits;
1749 COLORREF oldFg, oldBg;
1750 INT nStretchMode;
1752 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1754 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1755 ptr->bPlanes, ptr->bBitsPerPixel,
1756 (char *)(ptr + 1)
1757 + ptr->nHeight *
1758 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1759 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1760 1, 1, (char *)(ptr+1) );
1761 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1762 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1764 if (hXorBits && hAndBits)
1766 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1767 if (flags & DI_MASK)
1769 if (DoOffscreen)
1770 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1771 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1772 else
1773 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1774 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1776 SelectObject( hMemDC, hXorBits );
1777 if (flags & DI_IMAGE)
1779 if (DoOffscreen)
1780 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1781 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1782 else
1783 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1784 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1786 SelectObject( hMemDC, hBitTemp );
1787 result = TRUE;
1790 SetTextColor( hdc, oldFg );
1791 SetBkColor( hdc, oldBg );
1792 if (hXorBits) DeleteObject( hXorBits );
1793 if (hAndBits) DeleteObject( hAndBits );
1794 SetStretchBltMode (hdc, nStretchMode);
1795 if (DoOffscreen) {
1796 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
1797 SelectObject(hDC_off, hOld);
1800 if (hMemDC) DeleteDC( hMemDC );
1801 if (hDC_off) DeleteDC(hDC_off);
1802 if (hB_off) DeleteObject(hB_off);
1803 GlobalUnlock16( hIcon );
1804 return result;