Fixed some warnings.
[wine.git] / windows / cursoricon.c
blob0a33e82721e6b6af12c2a0723c0dec5ea69ffd92
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 "windef.h"
36 #include "wingdi.h"
37 #include "wine/winbase16.h"
38 #include "wine/winuser16.h"
39 #include "heap.h"
40 #include "color.h"
41 #include "bitmap.h"
42 #include "cursoricon.h"
43 #include "dc.h"
44 #include "gdi.h"
45 #include "global.h"
46 #include "module.h"
47 #include "debugtools.h"
48 #include "task.h"
49 #include "user.h"
50 #include "input.h"
51 #include "message.h"
52 #include "winerror.h"
54 DECLARE_DEBUG_CHANNEL(cursor);
55 DECLARE_DEBUG_CHANNEL(icon);
56 DECLARE_DEBUG_CHANNEL(resource);
58 static HCURSOR hActiveCursor = 0; /* Active cursor */
59 static INT CURSOR_ShowCount = 0; /* Cursor display count */
60 static RECT CURSOR_ClipRect; /* Cursor clipping rect */
63 /**********************************************************************
64 * ICONCACHE for cursors/icons loaded with LR_SHARED.
66 * FIXME: This should not be allocated on the system heap, but on a
67 * subsystem-global heap (i.e. one for all Win16 processes,
68 * and one each for every Win32 process).
70 typedef struct tagICONCACHE
72 struct tagICONCACHE *next;
74 HMODULE hModule;
75 HRSRC hRsrc;
76 HRSRC hGroupRsrc;
77 HANDLE handle;
79 INT count;
81 } ICONCACHE;
83 static ICONCACHE *IconAnchor = NULL;
84 static CRITICAL_SECTION IconCrst = CRITICAL_SECTION_INIT;
85 static DWORD ICON_HOTSPOT = 0x42424242;
87 /**********************************************************************
88 * CURSORICON_FindSharedIcon
90 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
92 HANDLE handle = 0;
93 ICONCACHE *ptr;
95 EnterCriticalSection( &IconCrst );
97 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
98 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
100 ptr->count++;
101 handle = ptr->handle;
102 break;
105 LeaveCriticalSection( &IconCrst );
107 return handle;
110 /*************************************************************************
111 * CURSORICON_FindCache
113 * Given a handle, find the coresponding cache element
115 * PARAMS
116 * Handle [I] handle to an Image
118 * RETURNS
119 * Success: The cache entry
120 * Failure: NULL
123 static ICONCACHE* CURSORICON_FindCache(HANDLE handle)
125 ICONCACHE *ptr;
126 ICONCACHE *pRet=NULL;
127 BOOL IsFound = FALSE;
128 int count;
130 EnterCriticalSection( &IconCrst );
132 for (count = 0, ptr = IconAnchor; ptr != NULL && !IsFound; ptr = ptr->next, count++ )
134 if ( handle == ptr->handle )
136 IsFound = TRUE;
137 pRet = ptr;
141 LeaveCriticalSection( &IconCrst );
143 return pRet;
146 /**********************************************************************
147 * CURSORICON_AddSharedIcon
149 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle )
151 ICONCACHE *ptr = HeapAlloc( SystemHeap, 0, sizeof(ICONCACHE) );
152 if ( !ptr ) return;
154 ptr->hModule = hModule;
155 ptr->hRsrc = hRsrc;
156 ptr->handle = handle;
157 ptr->hGroupRsrc = hGroupRsrc;
158 ptr->count = 1;
160 EnterCriticalSection( &IconCrst );
161 ptr->next = IconAnchor;
162 IconAnchor = ptr;
163 LeaveCriticalSection( &IconCrst );
166 /**********************************************************************
167 * CURSORICON_DelSharedIcon
169 static INT CURSORICON_DelSharedIcon( HANDLE handle )
171 INT count = -1;
172 ICONCACHE *ptr;
174 EnterCriticalSection( &IconCrst );
176 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
177 if ( ptr->handle == handle )
179 if ( ptr->count > 0 ) ptr->count--;
180 count = ptr->count;
181 break;
184 LeaveCriticalSection( &IconCrst );
186 return count;
189 /**********************************************************************
190 * CURSORICON_FreeModuleIcons
192 void CURSORICON_FreeModuleIcons( HMODULE hModule )
194 ICONCACHE **ptr = &IconAnchor;
196 if ( HIWORD( hModule ) )
197 hModule = MapHModuleLS( hModule );
198 else
199 hModule = GetExePtr( hModule );
201 EnterCriticalSection( &IconCrst );
203 while ( *ptr )
205 if ( (*ptr)->hModule == hModule )
207 ICONCACHE *freePtr = *ptr;
208 *ptr = freePtr->next;
210 GlobalFree16( freePtr->handle );
211 HeapFree( SystemHeap, 0, freePtr );
212 continue;
214 ptr = &(*ptr)->next;
217 LeaveCriticalSection( &IconCrst );
220 /**********************************************************************
221 * CURSORICON_FindBestIcon
223 * Find the icon closest to the requested size and number of colors.
225 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
226 int height, int colors )
228 int i;
229 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
230 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
231 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
233 if (dir->idCount < 1)
235 WARN_(icon)("Empty directory!\n" );
236 return NULL;
238 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
240 /* Find Best Fit */
241 iTotalDiff = 0xFFFFFFFF;
242 iColorDiff = 0xFFFFFFFF;
243 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
245 iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
246 iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
248 if(iTotalDiff > (iTempXDiff + iTempYDiff))
250 iXDiff = iTempXDiff;
251 iYDiff = iTempYDiff;
252 iTotalDiff = iXDiff + iYDiff;
256 /* Find Best Colors for Best Fit */
257 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
259 if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
260 abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
262 iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
263 if(iColorDiff > iTempColorDiff)
265 bestEntry = entry;
266 iColorDiff = iTempColorDiff;
271 return bestEntry;
275 /**********************************************************************
276 * CURSORICON_FindBestCursor
278 * Find the cursor closest to the requested size.
279 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
280 * ignored too
282 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
283 int width, int height, int color)
285 int i, maxwidth, maxheight;
286 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
288 if (dir->idCount < 1)
290 WARN_(cursor)("Empty directory!\n" );
291 return NULL;
293 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
295 /* Double height to account for AND and XOR masks */
297 height *= 2;
299 /* First find the largest one smaller than or equal to the requested size*/
301 maxwidth = maxheight = 0;
302 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
303 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
304 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
305 (entry->wBitCount == 1))
307 bestEntry = entry;
308 maxwidth = entry->ResInfo.cursor.wWidth;
309 maxheight = entry->ResInfo.cursor.wHeight;
311 if (bestEntry) return bestEntry;
313 /* Now find the smallest one larger than the requested size */
315 maxwidth = maxheight = 255;
316 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
317 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
318 (entry->wBitCount == 1))
320 bestEntry = entry;
321 maxwidth = entry->ResInfo.cursor.wWidth;
322 maxheight = entry->ResInfo.cursor.wHeight;
325 return bestEntry;
328 /*********************************************************************
329 * The main purpose of this function is to create fake resource directory
330 * and fake resource entries. There are several reasons for this:
331 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
332 * fields
333 * There are some "bad" cursor files which do not have
334 * bColorCount initialized but instead one must read this info
335 * directly from corresponding DIB sections
336 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
338 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
339 CURSORICONDIR **res, LPBYTE **ptr)
341 LPBYTE _free;
342 CURSORICONFILEDIR *bits;
343 int entries, size, i;
345 *res = NULL;
346 *ptr = NULL;
347 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
349 /* FIXME: test for inimated icons
350 * hack to load the first icon from the *.ani file
352 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
353 { LPBYTE pos = (LPBYTE) bits;
354 FIXME_(cursor)("Animated icons not correctly implemented! %p \n", bits);
356 for (;;)
357 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
358 { FIXME_(cursor)("icon entry found! %p\n", bits);
359 pos+=4;
360 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
361 { goto fail;
363 bits=(CURSORICONFILEDIR*)(pos+4);
364 FIXME_(cursor)("icon size ok. offset=%p \n", bits);
365 break;
367 pos+=2;
368 if (pos>=(LPBYTE)bits+766) goto fail;
371 if (!(entries = bits->idCount)) goto fail;
372 size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) * (entries - 1);
373 _free = (LPBYTE) size;
375 for (i=0; i < entries; i++)
376 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
378 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
379 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
380 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
382 _free = (LPBYTE)(*res) + (int)_free;
383 memcpy((*res), bits, 6);
384 for (i=0; i<entries; i++)
386 ((LPBYTE*)(*ptr))[i] = _free;
387 if (fCursor) {
388 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
389 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
390 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
391 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
392 _free+=sizeof(POINT16);
393 } else {
394 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
395 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
396 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
398 (*res)->idEntries[i].wPlanes=1;
399 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
400 bits->idEntries[i].dwDIBOffset))->biBitCount;
401 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
402 (*res)->idEntries[i].wResId=i+1;
404 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
405 (*res)->idEntries[i].dwBytesInRes);
406 _free += (*res)->idEntries[i].dwBytesInRes;
408 UnmapViewOfFile( bits );
409 return TRUE;
410 fail:
411 if (*res) HeapFree( GetProcessHeap(), 0, *res );
412 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
413 UnmapViewOfFile( bits );
414 return FALSE;
418 /**********************************************************************
419 * CURSORICON_CreateFromResource
421 * Create a cursor or icon from in-memory resource template.
423 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
424 * with cbSize parameter as well.
426 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
427 UINT cbSize, BOOL bIcon, DWORD dwVersion,
428 INT width, INT height, UINT loadflags )
430 int sizeAnd, sizeXor;
431 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
432 BITMAPOBJ *bmpXor, *bmpAnd;
433 POINT16 hotspot;
434 BITMAPINFO *bmi;
435 HDC hdc;
436 BOOL DoStretch;
437 INT size;
439 hotspot.x = ICON_HOTSPOT;
440 hotspot.y = ICON_HOTSPOT;
442 TRACE_(cursor)("%08x (%u bytes), ver %08x, %ix%i %s %s\n",
443 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
444 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
445 if (dwVersion == 0x00020000)
447 FIXME_(cursor)("\t2.xx resources are not supported\n");
448 return 0;
451 if (bIcon)
452 bmi = (BITMAPINFO *)bits;
453 else /* get the hotspot */
455 POINT16 *pt = (POINT16 *)bits;
456 hotspot = *pt;
457 bmi = (BITMAPINFO *)(pt + 1);
459 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
461 if (!width) width = bmi->bmiHeader.biWidth;
462 if (!height) height = bmi->bmiHeader.biHeight/2;
463 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
464 (bmi->bmiHeader.biWidth != width);
466 /* Check bitmap header */
468 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
469 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
470 bmi->bmiHeader.biCompression != BI_RGB) )
472 WARN_(cursor)("\tinvalid resource bitmap header.\n");
473 return 0;
476 if( (hdc = GetDC( 0 )) )
478 BITMAPINFO* pInfo;
480 /* Make sure we have room for the monochrome bitmap later on.
481 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
482 * up to and including the biBitCount. In-memory icon resource
483 * format is as follows:
485 * BITMAPINFOHEADER icHeader // DIB header
486 * RGBQUAD icColors[] // Color table
487 * BYTE icXOR[] // DIB bits for XOR mask
488 * BYTE icAND[] // DIB bits for AND mask
491 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
492 max(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
494 memcpy( pInfo, bmi, size );
495 pInfo->bmiHeader.biHeight /= 2;
497 /* Create the XOR bitmap */
499 if (DoStretch) {
500 if(bIcon)
502 hXorBits = CreateCompatibleBitmap(hdc, width, height);
504 else
506 hXorBits = CreateBitmap(width, height, 1, 1, NULL);
508 if(hXorBits)
510 HBITMAP hOld;
511 HDC hMem = CreateCompatibleDC(hdc);
512 BOOL res;
514 if (hMem) {
515 hOld = SelectObject(hMem, hXorBits);
516 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
517 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
518 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
519 SelectObject(hMem, hOld);
520 DeleteDC(hMem);
521 } else res = FALSE;
522 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
524 } else hXorBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
525 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
526 if( hXorBits )
528 char* bits = (char *)bmi + size +
529 DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
530 bmi->bmiHeader.biHeight,
531 bmi->bmiHeader.biBitCount) / 2;
533 pInfo->bmiHeader.biBitCount = 1;
534 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
536 RGBQUAD *rgb = pInfo->bmiColors;
538 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
539 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
540 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
541 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
543 else
545 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
547 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
548 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
551 /* Create the AND bitmap */
553 if (DoStretch) {
554 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
555 HBITMAP hOld;
556 HDC hMem = CreateCompatibleDC(hdc);
557 BOOL res;
559 if (hMem) {
560 hOld = SelectObject(hMem, hAndBits);
561 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
562 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
563 bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
564 SelectObject(hMem, hOld);
565 DeleteDC(hMem);
566 } else res = FALSE;
567 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
569 } else hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
570 CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
572 if( !hAndBits ) DeleteObject( hXorBits );
574 HeapFree( GetProcessHeap(), 0, pInfo );
576 ReleaseDC( 0, hdc );
579 if( !hXorBits || !hAndBits )
581 WARN_(cursor)("\tunable to create an icon bitmap.\n");
582 return 0;
585 /* Now create the CURSORICONINFO structure */
586 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
587 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
588 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
589 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
591 if (hObj) hObj = GlobalReAlloc16( hObj,
592 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
593 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
594 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
595 if (hObj)
597 CURSORICONINFO *info;
599 /* Make it owned by the module */
600 if (hInstance) FarSetOwner16( hObj, GetExePtr(hInstance) );
602 info = (CURSORICONINFO *)GlobalLock16( hObj );
603 info->ptHotSpot.x = hotspot.x;
604 info->ptHotSpot.y = hotspot.y;
605 info->nWidth = bmpXor->bitmap.bmWidth;
606 info->nHeight = bmpXor->bitmap.bmHeight;
607 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
608 info->bPlanes = bmpXor->bitmap.bmPlanes;
609 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
611 /* Transfer the bitmap bits to the CURSORICONINFO structure */
613 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
614 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
615 GlobalUnlock16( hObj );
618 DeleteObject( hXorBits );
619 DeleteObject( hAndBits );
620 return hObj;
624 /**********************************************************************
625 * CreateIconFromResourceEx16 (USER.450)
627 * FIXME: not sure about exact parameter types
629 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
630 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
632 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
633 width, height, cFlag);
637 /**********************************************************************
638 * CreateIconFromResource (USER32.76)
640 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
641 BOOL bIcon, DWORD dwVersion)
643 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
647 /**********************************************************************
648 * CreateIconFromResourceEx (USER32.77)
650 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
651 BOOL bIcon, DWORD dwVersion,
652 INT width, INT height,
653 UINT cFlag )
655 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
656 if( pTask )
657 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
658 width, height, cFlag );
659 return 0;
662 /**********************************************************************
663 * CURSORICON_Load
665 * Load a cursor or icon from resource or file.
667 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
668 INT width, INT height, INT colors,
669 BOOL fCursor, UINT loadflags )
671 HANDLE handle = 0, h = 0;
672 HANDLE hRsrc;
673 CURSORICONDIR *dir;
674 CURSORICONDIRENTRY *dirEntry;
675 LPBYTE bits;
677 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
679 LPBYTE *ptr;
680 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
681 return 0;
682 if (fCursor)
683 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
684 else
685 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
686 bits = ptr[dirEntry->wResId-1];
687 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
688 !fCursor, 0x00030000, width, height, loadflags);
689 HeapFree( GetProcessHeap(), 0, dir );
690 HeapFree( GetProcessHeap(), 0, ptr );
693 else if ( !hInstance ) /* Load OEM cursor/icon */
695 WORD resid;
696 HDC hdc;
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 if (hdc) {
715 DC *dc = DC_GetDCPtr( hdc );
716 if (dc->funcs->pLoadOEMResource)
717 h = dc->funcs->pLoadOEMResource( resid, fCursor ? OEM_CURSOR : OEM_ICON );
718 GDI_HEAP_UNLOCK( hdc );
719 DeleteDC( hdc );
723 else /* Load from resource */
725 HANDLE hGroupRsrc;
726 WORD wResId;
727 DWORD dwBytesInRes;
729 /* Normalize hInstance (must be uniquely represented for icon cache) */
731 if ( HIWORD( hInstance ) )
732 hInstance = MapHModuleLS( hInstance );
733 else
734 hInstance = GetExePtr( hInstance );
736 /* Get directory resource ID */
738 if (!(hRsrc = FindResourceW( hInstance, name,
739 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
740 return 0;
741 hGroupRsrc = hRsrc;
742 /* If shared icon, check whether it was already loaded */
744 if ( (loadflags & LR_SHARED)
745 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
746 return h;
748 /* Find the best entry in the directory */
750 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
751 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
752 if (fCursor)
753 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
754 width, height, 1);
755 else
756 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
757 width, height, colors );
758 if (!dirEntry) return 0;
759 wResId = dirEntry->wResId;
760 dwBytesInRes = dirEntry->dwBytesInRes;
761 FreeResource( handle );
763 /* Load the resource */
765 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
766 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
767 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
768 bits = (LPBYTE)LockResource( handle );
769 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
770 !fCursor, 0x00030000, width, height, loadflags);
771 FreeResource( handle );
773 /* If shared icon, add to icon cache */
775 if ( h && (loadflags & LR_SHARED) )
776 CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, h );
779 return h;
782 /***********************************************************************
783 * CURSORICON_Copy
785 * Make a copy of a cursor or icon.
787 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
789 char *ptrOld, *ptrNew;
790 int size;
791 HGLOBAL16 hNew;
793 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
794 if (!(hInstance = GetExePtr( hInstance ))) return 0;
795 size = GlobalSize16( handle );
796 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
797 FarSetOwner16( hNew, hInstance );
798 ptrNew = (char *)GlobalLock16( hNew );
799 memcpy( ptrNew, ptrOld, size );
800 GlobalUnlock16( handle );
801 GlobalUnlock16( hNew );
802 return hNew;
805 /*************************************************************************
806 * CURSORICON_ExtCopy
808 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified
810 * PARAMS
811 * Handle [I] handle to an Image
812 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)
813 * iDesiredCX [I] The Desired width of the Image
814 * iDesiredCY [I] The desired height of the Image
815 * nFlags [I] The flags from CopyImage
817 * RETURNS
818 * Success: The new handle of the Image
820 * NOTES
821 * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented.
822 * LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource.
823 * LR_COPYFROMRESOURCE will only work if the Image is in the Cache.
828 HGLOBAL CURSORICON_ExtCopy(HGLOBAL Handle, UINT nType,
829 INT iDesiredCX, INT iDesiredCY,
830 UINT nFlags)
832 HGLOBAL16 hNew=0;
834 TRACE_(icon)("Handle %u, uType %u, iDesiredCX %i, iDesiredCY %i, nFlags %u\n",
835 Handle, nType, iDesiredCX, iDesiredCY, nFlags);
837 if(Handle == 0)
839 return 0;
842 /* Best Fit or Monochrome */
843 if( (nFlags & LR_COPYFROMRESOURCE
844 && (iDesiredCX > 0 || iDesiredCY > 0))
845 || nFlags & LR_MONOCHROME)
847 ICONCACHE* pIconCache = CURSORICON_FindCache(Handle);
849 /* Not Found in Cache, then do a strait copy
851 if(pIconCache == NULL)
853 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
854 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
855 if(nFlags & LR_COPYFROMRESOURCE)
857 TRACE_(icon)("LR_COPYFROMRESOURCE: Failed to load from cache\n");
860 else
862 int iTargetCY = iDesiredCY, iTargetCX = iDesiredCX;
863 LPBYTE pBits;
864 HANDLE hMem;
865 HRSRC hRsrc;
866 DWORD dwBytesInRes;
867 WORD wResId;
868 CURSORICONDIR *pDir;
869 CURSORICONDIRENTRY *pDirEntry;
870 BOOL bIsIcon = (nType == IMAGE_ICON);
872 /* Completing iDesiredCX CY for Monochrome Bitmaps if needed
874 if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE))
875 || (iDesiredCX == 0 && iDesiredCY == 0))
877 iDesiredCY = GetSystemMetrics(bIsIcon ?
878 SM_CYICON : SM_CYCURSOR);
879 iDesiredCX = GetSystemMetrics(bIsIcon ?
880 SM_CXICON : SM_CXCURSOR);
883 /* Retreive the CURSORICONDIRENTRY
885 if (!(hMem = LoadResource( pIconCache->hModule ,
886 pIconCache->hGroupRsrc)))
888 return 0;
890 if (!(pDir = (CURSORICONDIR*)LockResource( hMem )))
892 return 0;
895 /* Find Best Fit
897 if(bIsIcon)
899 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(
900 pDir, iDesiredCX, iDesiredCY, 256);
902 else
904 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(
905 pDir, iDesiredCX, iDesiredCY, 1);
908 wResId = pDirEntry->wResId;
909 dwBytesInRes = pDirEntry->dwBytesInRes;
910 FreeResource(hMem);
912 TRACE_(icon)("ResID %u, BytesInRes %lu, Width %d, Height %d DX %d, DY %d\n",
913 wResId, dwBytesInRes, pDirEntry->ResInfo.icon.bWidth,
914 pDirEntry->ResInfo.icon.bHeight, iDesiredCX, iDesiredCY);
916 /* Get the Best Fit
918 if (!(hRsrc = FindResourceW(pIconCache->hModule ,
919 MAKEINTRESOURCEW(wResId), bIsIcon ? RT_ICONW : RT_CURSORW)))
921 return 0;
923 if (!(hMem = LoadResource( pIconCache->hModule , hRsrc )))
925 return 0;
928 pBits = (LPBYTE)LockResource( hMem );
930 if(nFlags & LR_DEFAULTSIZE)
932 iTargetCY = GetSystemMetrics(SM_CYICON);
933 iTargetCX = GetSystemMetrics(SM_CXICON);
936 /* Create a New Icon with the proper dimension
938 hNew = CURSORICON_CreateFromResource( 0, 0, pBits, dwBytesInRes,
939 bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
940 FreeResource(hMem);
943 else
945 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
946 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
948 return hNew;
951 /***********************************************************************
952 * CURSORICON_IconToCursor
954 * Converts bitmap to mono and truncates if icon is too large (should
955 * probably do StretchBlt() instead).
957 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
959 HCURSOR16 hRet = 0;
960 CURSORICONINFO *pIcon = NULL;
961 HTASK16 hTask = GetCurrentTask();
962 TDB* pTask = (TDB *)GlobalLock16(hTask);
964 if(hIcon && pTask)
965 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
966 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
968 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
971 pIcon = GlobalLock16(hRet);
973 pIcon->ptHotSpot.x = pIcon->ptHotSpot.y = 15;
975 GlobalUnlock16(hRet);
977 else
979 BYTE pAndBits[128];
980 BYTE pXorBits[128];
981 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
982 BYTE* psPtr, *pxbPtr = pXorBits;
983 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
984 BYTE* pbc = NULL;
986 CURSORICONINFO cI;
988 TRACE_(icon)("[%04x] %ix%i %ibpp (bogus %ibps)\n",
989 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
991 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
992 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
993 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
995 memset(pXorBits, 0, 128);
996 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
997 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
998 cI.nWidth = 32; cI.nHeight = 32;
999 cI.nWidthBytes = 4; /* 32x1bpp */
1001 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
1002 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
1004 for( iy = 0; iy < maxy; iy++ )
1006 unsigned shift = iy % 2;
1008 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
1009 (and_width > 4) ? 4 : and_width );
1010 for( ix = 0; ix < maxx; ix++ )
1012 if( bSemiTransparent && ((ix+shift)%2) )
1014 /* set AND bit, XOR bit stays 0 */
1016 pbc = pAndBits + iy * 4 + ix/8;
1017 *pbc |= 0x80 >> (ix%8);
1019 else
1021 /* keep AND bit, set XOR bit */
1023 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
1024 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
1025 if(!PALETTE_Driver->pIsDark(val))
1027 pbc = pxbPtr + ix/8;
1028 *pbc |= 0x80 >> (ix%8);
1032 psPtr += xor_width;
1033 pxbPtr += 4;
1036 hRet = CreateCursorIconIndirect16( pTask->hInstance , &cI, pAndBits, pXorBits);
1038 if( !hRet ) /* fall back on default drag cursor */
1039 hRet = CURSORICON_Copy( pTask->hInstance ,
1040 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
1041 GetSystemMetrics(SM_CXCURSOR),
1042 GetSystemMetrics(SM_CYCURSOR), 1, TRUE, 0) );
1045 return hRet;
1049 /***********************************************************************
1050 * LoadCursor16 (USER.173)
1052 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
1054 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1055 return LoadCursorA( hInstance, nameStr );
1059 /***********************************************************************
1060 * LoadIcon16 (USER.174)
1062 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
1064 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1065 return LoadIconA( hInstance, nameStr );
1069 /***********************************************************************
1070 * CreateCursor16 (USER.406)
1072 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
1073 INT16 xHotSpot, INT16 yHotSpot,
1074 INT16 nWidth, INT16 nHeight,
1075 LPCVOID lpANDbits, LPCVOID lpXORbits )
1077 CURSORICONINFO info;
1079 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1080 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1082 info.ptHotSpot.x = xHotSpot;
1083 info.ptHotSpot.y = yHotSpot;
1084 info.nWidth = nWidth;
1085 info.nHeight = nHeight;
1086 info.nWidthBytes = 0;
1087 info.bPlanes = 1;
1088 info.bBitsPerPixel = 1;
1090 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1094 /***********************************************************************
1095 * CreateCursor (USER32.67)
1097 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
1098 INT xHotSpot, INT yHotSpot,
1099 INT nWidth, INT nHeight,
1100 LPCVOID lpANDbits, LPCVOID lpXORbits )
1102 CURSORICONINFO info;
1104 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1105 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1107 info.ptHotSpot.x = xHotSpot;
1108 info.ptHotSpot.y = yHotSpot;
1109 info.nWidth = nWidth;
1110 info.nHeight = nHeight;
1111 info.nWidthBytes = 0;
1112 info.bPlanes = 1;
1113 info.bBitsPerPixel = 1;
1115 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1119 /***********************************************************************
1120 * CreateIcon16 (USER.407)
1122 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
1123 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
1124 LPCVOID lpANDbits, LPCVOID lpXORbits )
1126 CURSORICONINFO info;
1128 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1129 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1131 info.ptHotSpot.x = ICON_HOTSPOT;
1132 info.ptHotSpot.y = ICON_HOTSPOT;
1133 info.nWidth = nWidth;
1134 info.nHeight = nHeight;
1135 info.nWidthBytes = 0;
1136 info.bPlanes = bPlanes;
1137 info.bBitsPerPixel = bBitsPixel;
1139 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1143 /***********************************************************************
1144 * CreateIcon (USER32.75)
1146 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
1147 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
1148 LPCVOID lpANDbits, LPCVOID lpXORbits )
1150 CURSORICONINFO info;
1152 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1153 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1155 info.ptHotSpot.x = ICON_HOTSPOT;
1156 info.ptHotSpot.y = ICON_HOTSPOT;
1157 info.nWidth = nWidth;
1158 info.nHeight = nHeight;
1159 info.nWidthBytes = 0;
1160 info.bPlanes = bPlanes;
1161 info.bBitsPerPixel = bBitsPixel;
1163 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1167 /***********************************************************************
1168 * CreateCursorIconIndirect (USER.408)
1170 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
1171 CURSORICONINFO *info,
1172 LPCVOID lpANDbits,
1173 LPCVOID lpXORbits )
1175 HGLOBAL16 handle;
1176 char *ptr;
1177 int sizeAnd, sizeXor;
1179 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
1180 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
1181 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
1182 sizeXor = info->nHeight * info->nWidthBytes;
1183 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1184 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
1185 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1186 return 0;
1187 if (hInstance) FarSetOwner16( handle, hInstance );
1188 ptr = (char *)GlobalLock16( handle );
1189 memcpy( ptr, info, sizeof(*info) );
1190 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1191 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1192 GlobalUnlock16( handle );
1193 return handle;
1197 /***********************************************************************
1198 * CopyIcon16 (USER.368)
1200 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1202 TRACE_(icon)("%04x %04x\n", hInstance, hIcon );
1203 return CURSORICON_Copy( hInstance, hIcon );
1207 /***********************************************************************
1208 * CopyIcon (USER32.60)
1210 HICON WINAPI CopyIcon( HICON hIcon )
1212 HTASK16 hTask = GetCurrentTask ();
1213 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1214 TRACE_(icon)("%04x\n", hIcon );
1215 return CURSORICON_Copy( pTask->hInstance, hIcon );
1219 /***********************************************************************
1220 * CopyCursor16 (USER.369)
1222 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1224 TRACE_(cursor)("%04x %04x\n", hInstance, hCursor );
1225 return CURSORICON_Copy( hInstance, hCursor );
1228 /**********************************************************************
1229 * CURSORICON_Destroy (USER.610)
1231 * This routine is actually exported from Win95 USER under the name
1232 * DestroyIcon32 ... The behaviour implemented here should mimic
1233 * the Win95 one exactly, especially the return values, which
1234 * depend on the setting of various flags.
1236 WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1238 WORD retv;
1240 TRACE_(icon)("(%04x, %04x)\n", handle, flags );
1242 /* Check whether destroying active cursor */
1244 if ( hActiveCursor == handle )
1246 ERR_(cursor)("Destroying active cursor!\n" );
1247 SetCursor( 0 );
1250 /* Try shared cursor/icon first */
1252 if ( !(flags & CID_NONSHARED) )
1254 INT count = CURSORICON_DelSharedIcon( handle );
1256 if ( count != -1 )
1257 return (flags & CID_WIN32)? TRUE : (count == 0);
1259 /* FIXME: OEM cursors/icons should be recognized */
1262 /* Now assume non-shared cursor/icon */
1264 retv = GlobalFree16( handle );
1265 return (flags & CID_RESOURCE)? retv : TRUE;
1268 /***********************************************************************
1269 * DestroyIcon16 (USER.457)
1271 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1273 return CURSORICON_Destroy( hIcon, 0 );
1276 /***********************************************************************
1277 * DestroyIcon (USER32.133)
1279 BOOL WINAPI DestroyIcon( HICON hIcon )
1281 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1284 /***********************************************************************
1285 * DestroyCursor16 (USER.458)
1287 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1289 return CURSORICON_Destroy( hCursor, 0 );
1292 /***********************************************************************
1293 * DestroyCursor (USER32.132)
1295 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1297 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1301 /***********************************************************************
1302 * DrawIcon16 (USER.84)
1304 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1306 return DrawIcon( hdc, x, y, hIcon );
1310 /***********************************************************************
1311 * DrawIcon (USER32.159)
1313 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1315 CURSORICONINFO *ptr;
1316 HDC hMemDC;
1317 HBITMAP hXorBits, hAndBits;
1318 COLORREF oldFg, oldBg;
1320 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1321 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1322 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1323 (char *)(ptr+1) );
1324 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1325 ptr->bBitsPerPixel, (char *)(ptr + 1)
1326 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1327 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1328 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1330 if (hXorBits && hAndBits)
1332 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1333 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1334 SelectObject( hMemDC, hXorBits );
1335 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1336 SelectObject( hMemDC, hBitTemp );
1338 DeleteDC( hMemDC );
1339 if (hXorBits) DeleteObject( hXorBits );
1340 if (hAndBits) DeleteObject( hAndBits );
1341 GlobalUnlock16( hIcon );
1342 SetTextColor( hdc, oldFg );
1343 SetBkColor( hdc, oldBg );
1344 return TRUE;
1348 /***********************************************************************
1349 * DumpIcon (USER.459)
1351 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1352 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1354 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1355 int sizeAnd, sizeXor;
1357 if (!info) return 0;
1358 sizeXor = info->nHeight * info->nWidthBytes;
1359 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1360 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1361 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1362 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1363 return MAKELONG( sizeXor, sizeXor );
1367 /***********************************************************************
1368 * SetCursor16 (USER.69)
1370 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1372 return (HCURSOR16)SetCursor( hCursor );
1376 /***********************************************************************
1377 * SetCursor (USER32.472)
1378 * RETURNS:
1379 * A handle to the previous cursor shape.
1381 HCURSOR WINAPI SetCursor(
1382 HCURSOR hCursor /* Handle of cursor to show */
1384 HCURSOR hOldCursor;
1386 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1387 TRACE_(cursor)("%04x\n", hCursor );
1388 hOldCursor = hActiveCursor;
1389 hActiveCursor = hCursor;
1390 /* Change the cursor shape only if it is visible */
1391 if (CURSOR_ShowCount >= 0)
1393 USER_Driver->pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1394 GlobalUnlock16( hActiveCursor );
1396 return hOldCursor;
1400 /***********************************************************************
1401 * SetCursorPos16 (USER.70)
1403 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1405 SetCursorPos( x, y );
1409 /***********************************************************************
1410 * SetCursorPos (USER32.474)
1412 BOOL WINAPI SetCursorPos( INT x, INT y )
1414 USER_Driver->pMoveCursor( x, y );
1415 return TRUE;
1419 /***********************************************************************
1420 * ShowCursor16 (USER.71)
1422 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1424 return ShowCursor( bShow );
1428 /***********************************************************************
1429 * ShowCursor (USER32.530)
1431 INT WINAPI ShowCursor( BOOL bShow )
1433 TRACE_(cursor)("%d, count=%d\n",
1434 bShow, CURSOR_ShowCount );
1436 if (bShow)
1438 if (++CURSOR_ShowCount == 0) /* Show it */
1440 USER_Driver->pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1441 GlobalUnlock16( hActiveCursor );
1444 else
1446 if (--CURSOR_ShowCount == -1) /* Hide it */
1447 USER_Driver->pSetCursor( NULL );
1449 return CURSOR_ShowCount;
1453 /***********************************************************************
1454 * GetCursor16 (USER.247)
1456 HCURSOR16 WINAPI GetCursor16(void)
1458 return hActiveCursor;
1462 /***********************************************************************
1463 * GetCursor (USER32.227)
1465 HCURSOR WINAPI GetCursor(void)
1467 return hActiveCursor;
1471 /***********************************************************************
1472 * ClipCursor16 (USER.16)
1474 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1476 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1477 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1478 return TRUE;
1482 /***********************************************************************
1483 * ClipCursor (USER32.53)
1485 BOOL WINAPI ClipCursor( const RECT *rect )
1487 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1488 else CopyRect( &CURSOR_ClipRect, rect );
1489 return TRUE;
1493 /***********************************************************************
1494 * GetCursorPos16 (USER.17)
1496 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
1498 if (!pt) return 0;
1500 pt->x = PosX;
1501 pt->y = PosY;
1503 TRACE_(cursor)("ret=%d,%d\n", pt->x, pt->y );
1504 return 1;
1508 /***********************************************************************
1509 * GetCursorPos (USER32.229)
1511 BOOL WINAPI GetCursorPos( POINT *pt )
1513 BOOL ret;
1515 POINT16 pt16;
1516 ret = GetCursorPos16( &pt16 );
1517 if (pt) CONV_POINT16TO32( &pt16, pt );
1518 return ((pt) ? ret : 0);
1522 /***********************************************************************
1523 * GetClipCursor16 (USER.309)
1525 void WINAPI GetClipCursor16( RECT16 *rect )
1527 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1531 /***********************************************************************
1532 * GetClipCursor (USER32.221)
1534 BOOL WINAPI GetClipCursor( RECT *rect )
1536 if (rect)
1538 CopyRect( rect, &CURSOR_ClipRect );
1539 return TRUE;
1541 return FALSE;
1544 /**********************************************************************
1545 * LookupIconIdFromDirectoryEx16 (USER.364)
1547 * FIXME: exact parameter sizes
1549 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1550 INT16 width, INT16 height, UINT16 cFlag )
1552 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1553 UINT16 retVal = 0;
1554 if( dir && !dir->idReserved && (dir->idType & 3) )
1556 CURSORICONDIRENTRY* entry;
1557 HDC hdc;
1558 UINT palEnts;
1559 int colors;
1560 hdc = GetDC(0);
1561 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1562 if (palEnts == 0)
1563 palEnts = 256;
1564 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1566 ReleaseDC(0, hdc);
1568 if( bIcon )
1569 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1570 else
1571 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1573 if( entry ) retVal = entry->wResId;
1575 else WARN_(cursor)("invalid resource directory\n");
1576 return retVal;
1579 /**********************************************************************
1580 * LookupIconIdFromDirectoryEx (USER32.380)
1582 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1583 INT width, INT height, UINT cFlag )
1585 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1588 /**********************************************************************
1589 * LookupIconIdFromDirectory (USER.???)
1591 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1593 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1594 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1595 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1598 /**********************************************************************
1599 * LookupIconIdFromDirectory (USER32.379)
1601 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1603 return LookupIconIdFromDirectoryEx( dir, bIcon,
1604 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1605 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1608 /**********************************************************************
1609 * GetIconID (USER.455)
1611 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1613 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1615 TRACE_(cursor)("hRes=%04x, entries=%i\n",
1616 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1618 switch(resType)
1620 case RT_CURSOR16:
1621 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1622 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1623 case RT_ICON16:
1624 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1625 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0 );
1626 default:
1627 WARN_(cursor)("invalid res type %ld\n", resType );
1629 return 0;
1632 /**********************************************************************
1633 * LoadCursorIconHandler (USER.336)
1635 * Supposed to load resources of Windows 2.x applications.
1637 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1639 FIXME_(cursor)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1640 hResource, hModule, hRsrc);
1641 return (HGLOBAL16)0;
1644 /**********************************************************************
1645 * LoadDIBIconHandler (USER.357)
1647 * RT_ICON resource loader, installed by USER_SignalProc when module
1648 * is initialized.
1650 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1652 /* If hResource is zero we must allocate a new memory block, if it's
1653 * non-zero but GlobalLock() returns NULL then it was discarded and
1654 * we have to recommit some memory, otherwise we just need to check
1655 * the block size. See LoadProc() in 16-bit SDK for more.
1658 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1659 if( hMemObj )
1661 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1662 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1663 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1664 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR );
1666 return hMemObj;
1669 /**********************************************************************
1670 * LoadDIBCursorHandler (USER.356)
1672 * RT_CURSOR resource loader. Same as above.
1674 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1676 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1677 if( hMemObj )
1679 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1680 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1681 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1682 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1684 return hMemObj;
1687 /**********************************************************************
1688 * LoadIconHandler (USER.456)
1690 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1692 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1694 TRACE_(cursor)("hRes=%04x\n",hResource);
1696 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1697 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1700 /***********************************************************************
1701 * LoadCursorW (USER32.362)
1703 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1705 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1706 LR_SHARED | LR_DEFAULTSIZE );
1709 /***********************************************************************
1710 * LoadCursorA (USER32.359)
1712 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1714 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1715 LR_SHARED | LR_DEFAULTSIZE );
1718 /***********************************************************************
1719 * LoadCursorFromFileW (USER32.361)
1721 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1723 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1724 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1727 /***********************************************************************
1728 * LoadCursorFromFileA (USER32.360)
1730 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1732 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1733 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1736 /***********************************************************************
1737 * LoadIconW (USER32.364)
1739 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1741 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1742 LR_SHARED | LR_DEFAULTSIZE );
1745 /***********************************************************************
1746 * LoadIconA (USER32.363)
1748 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1750 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1751 LR_SHARED | LR_DEFAULTSIZE );
1754 /**********************************************************************
1755 * GetIconInfo16 (USER.395)
1757 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1759 ICONINFO ii32;
1760 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1762 iconinfo->fIcon = ii32.fIcon;
1763 iconinfo->xHotspot = ii32.xHotspot;
1764 iconinfo->yHotspot = ii32.yHotspot;
1765 iconinfo->hbmMask = ii32.hbmMask;
1766 iconinfo->hbmColor = ii32.hbmColor;
1767 return ret;
1770 /**********************************************************************
1771 * GetIconInfo (USER32.242)
1773 BOOL WINAPI GetIconInfo(HICON hIcon,LPICONINFO iconinfo) {
1774 CURSORICONINFO *ciconinfo;
1776 ciconinfo = GlobalLock16(hIcon);
1777 if (!ciconinfo)
1778 return FALSE;
1780 if ( (ciconinfo->ptHotSpot.x == ICON_HOTSPOT) &&
1781 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT) )
1783 iconinfo->fIcon = TRUE;
1784 iconinfo->xHotspot = 0;
1785 iconinfo->yHotspot = 0;
1787 else
1789 iconinfo->fIcon = FALSE;
1790 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1791 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1794 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1795 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1796 (char *)(ciconinfo + 1)
1797 + ciconinfo->nHeight *
1798 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1799 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1800 1, 1, (char *)(ciconinfo + 1));
1802 GlobalUnlock16(hIcon);
1804 return TRUE;
1807 /**********************************************************************
1808 * CreateIconIndirect (USER32.78)
1810 HICON WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1811 BITMAPOBJ *bmpXor,*bmpAnd;
1812 HICON hObj;
1813 int sizeXor,sizeAnd;
1815 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1816 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1818 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1819 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1821 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1822 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1823 if (hObj)
1825 CURSORICONINFO *info;
1827 info = (CURSORICONINFO *)GlobalLock16( hObj );
1829 /* If we are creating an icon, the hotspot is unused */
1830 if (iconinfo->fIcon)
1832 info->ptHotSpot.x = ICON_HOTSPOT;
1833 info->ptHotSpot.y = ICON_HOTSPOT;
1835 else
1837 info->ptHotSpot.x = iconinfo->xHotspot;
1838 info->ptHotSpot.y = iconinfo->yHotspot;
1841 info->nWidth = bmpXor->bitmap.bmWidth;
1842 info->nHeight = bmpXor->bitmap.bmHeight;
1843 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1844 info->bPlanes = bmpXor->bitmap.bmPlanes;
1845 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1847 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1849 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1850 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1851 GlobalUnlock16( hObj );
1853 return hObj;
1857 /**********************************************************************
1859 DrawIconEx16 (USER.394)
1861 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1862 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1863 HBRUSH16 hbr, UINT16 flags)
1865 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1866 istep, hbr, flags);
1870 /******************************************************************************
1871 * DrawIconEx [USER32.160] Draws an icon or cursor on device context
1873 * NOTES
1874 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1876 * PARAMS
1877 * hdc [I] Handle to device context
1878 * x0 [I] X coordinate of upper left corner
1879 * y0 [I] Y coordinate of upper left corner
1880 * hIcon [I] Handle to icon to draw
1881 * cxWidth [I] Width of icon
1882 * cyWidth [I] Height of icon
1883 * istep [I] Index of frame in animated cursor
1884 * hbr [I] Handle to background brush
1885 * flags [I] Icon-drawing flags
1887 * RETURNS
1888 * Success: TRUE
1889 * Failure: FALSE
1891 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1892 INT cxWidth, INT cyWidth, UINT istep,
1893 HBRUSH hbr, UINT flags )
1895 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1896 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1897 BOOL result = FALSE, DoOffscreen = FALSE;
1898 HBITMAP hB_off = 0, hOld = 0;
1900 if (!ptr) return FALSE;
1902 if (istep)
1903 FIXME_(icon)("Ignoring istep=%d\n", istep);
1904 if (flags & DI_COMPAT)
1905 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
1907 /* Calculate the size of the destination image. */
1908 if (cxWidth == 0)
1910 if (flags & DI_DEFAULTSIZE)
1911 cxWidth = GetSystemMetrics (SM_CXICON);
1912 else
1913 cxWidth = ptr->nWidth;
1915 if (cyWidth == 0)
1917 if (flags & DI_DEFAULTSIZE)
1918 cyWidth = GetSystemMetrics (SM_CYICON);
1919 else
1920 cyWidth = ptr->nHeight;
1923 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1924 STOCK_HOLLOW_BRUSH)))
1926 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1927 if (object)
1929 UINT16 magic = object->wMagic;
1930 GDI_HEAP_UNLOCK(hbr);
1931 DoOffscreen = magic == BRUSH_MAGIC;
1934 if (DoOffscreen) {
1935 RECT r;
1937 r.left = 0;
1938 r.top = 0;
1939 r.right = cxWidth;
1940 r.bottom = cxWidth;
1942 hDC_off = CreateCompatibleDC(hdc);
1943 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1944 if (hDC_off && hB_off) {
1945 hOld = SelectObject(hDC_off, hB_off);
1946 FillRect(hDC_off, &r, hbr);
1950 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1952 HBITMAP hXorBits, hAndBits;
1953 COLORREF oldFg, oldBg;
1954 INT nStretchMode;
1956 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1958 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1959 ptr->bPlanes, ptr->bBitsPerPixel,
1960 (char *)(ptr + 1)
1961 + ptr->nHeight *
1962 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1963 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1964 1, 1, (char *)(ptr+1) );
1965 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1966 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1968 if (hXorBits && hAndBits)
1970 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1971 if (flags & DI_MASK)
1973 if (DoOffscreen)
1974 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1975 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1976 else
1977 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1978 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1980 SelectObject( hMemDC, hXorBits );
1981 if (flags & DI_IMAGE)
1983 if (DoOffscreen)
1984 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1985 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1986 else
1987 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1988 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1990 SelectObject( hMemDC, hBitTemp );
1991 result = TRUE;
1994 SetTextColor( hdc, oldFg );
1995 SetBkColor( hdc, oldBg );
1996 if (hXorBits) DeleteObject( hXorBits );
1997 if (hAndBits) DeleteObject( hAndBits );
1998 SetStretchBltMode (hdc, nStretchMode);
1999 if (DoOffscreen) {
2000 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
2001 SelectObject(hDC_off, hOld);
2004 if (hMemDC) DeleteDC( hMemDC );
2005 if (hDC_off) DeleteDC(hDC_off);
2006 if (hB_off) DeleteObject(hB_off);
2007 GlobalUnlock16( hIcon );
2008 return result;
2011 /***********************************************************************
2012 * DIB_FixColorsToLoadflags
2014 * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
2015 * are in loadflags
2017 static void DIB_FixColorsToLoadflags(BITMAPINFO * bmi, UINT loadflags, BYTE pix)
2019 int colors;
2020 COLORREF c_W, c_S, c_F, c_L, c_C;
2021 int incr,i;
2022 RGBQUAD *ptr;
2024 if (bmi->bmiHeader.biBitCount > 8) return;
2025 if (bmi->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) incr = 4;
2026 else if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) incr = 3;
2027 else {
2028 WARN_(resource)("Wrong bitmap header size!\n");
2029 return;
2031 colors = bmi->bmiHeader.biClrUsed;
2032 if (!colors && (bmi->bmiHeader.biBitCount <= 8))
2033 colors = 1 << bmi->bmiHeader.biBitCount;
2034 c_W = GetSysColor(COLOR_WINDOW);
2035 c_S = GetSysColor(COLOR_3DSHADOW);
2036 c_F = GetSysColor(COLOR_3DFACE);
2037 c_L = GetSysColor(COLOR_3DLIGHT);
2038 if (loadflags & LR_LOADTRANSPARENT) {
2039 switch (bmi->bmiHeader.biBitCount) {
2040 case 1: pix = pix >> 7; break;
2041 case 4: pix = pix >> 4; break;
2042 case 8: break;
2043 default:
2044 WARN_(resource)("(%d): Unsupported depth\n", bmi->bmiHeader.biBitCount);
2045 return;
2047 if (pix >= colors) {
2048 WARN_(resource)("pixel has color index greater than biClrUsed!\n");
2049 return;
2051 if (loadflags & LR_LOADMAP3DCOLORS) c_W = c_F;
2052 ptr = (RGBQUAD*)((char*)bmi->bmiColors+pix*incr);
2053 ptr->rgbBlue = GetBValue(c_W);
2054 ptr->rgbGreen = GetGValue(c_W);
2055 ptr->rgbRed = GetRValue(c_W);
2057 if (loadflags & LR_LOADMAP3DCOLORS)
2058 for (i=0; i<colors; i++) {
2059 ptr = (RGBQUAD*)((char*)bmi->bmiColors+i*incr);
2060 c_C = RGB(ptr->rgbRed, ptr->rgbGreen, ptr->rgbBlue);
2061 if (c_C == RGB(128, 128, 128)) {
2062 ptr->rgbRed = GetRValue(c_S);
2063 ptr->rgbGreen = GetGValue(c_S);
2064 ptr->rgbBlue = GetBValue(c_S);
2065 } else if (c_C == RGB(192, 192, 192)) {
2066 ptr->rgbRed = GetRValue(c_F);
2067 ptr->rgbGreen = GetGValue(c_F);
2068 ptr->rgbBlue = GetBValue(c_F);
2069 } else if (c_C == RGB(223, 223, 223)) {
2070 ptr->rgbRed = GetRValue(c_L);
2071 ptr->rgbGreen = GetGValue(c_L);
2072 ptr->rgbBlue = GetBValue(c_L);
2078 /**********************************************************************
2079 * BITMAP_Load
2081 static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
2083 HBITMAP hbitmap = 0;
2084 HDC hdc;
2085 HRSRC hRsrc;
2086 HGLOBAL handle;
2087 char *ptr = NULL;
2088 BITMAPINFO *info, *fix_info=NULL;
2089 HGLOBAL hFix;
2090 int size;
2092 if (!(loadflags & LR_LOADFROMFILE)) {
2093 if (!instance) /* OEM bitmap */
2095 HDC hdc;
2096 DC *dc;
2098 if (HIWORD((int)name)) return 0;
2099 hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
2100 dc = DC_GetDCPtr( hdc );
2101 if(dc->funcs->pLoadOEMResource)
2102 hbitmap = dc->funcs->pLoadOEMResource( LOWORD((int)name),
2103 OEM_BITMAP );
2104 GDI_HEAP_UNLOCK( hdc );
2105 DeleteDC( hdc );
2106 return hbitmap;
2109 if (!(hRsrc = FindResourceW( instance, name, RT_BITMAPW ))) return 0;
2110 if (!(handle = LoadResource( instance, hRsrc ))) return 0;
2112 if ((info = (BITMAPINFO *)LockResource( handle )) == NULL) return 0;
2114 else
2116 if (!(ptr = (char *)VIRTUAL_MapFileW( name ))) return 0;
2117 info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
2119 size = DIB_BitmapInfoSize(info, DIB_RGB_COLORS);
2120 if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
2121 if (fix_info) {
2122 BYTE pix;
2124 memcpy(fix_info, info, size);
2125 pix = *((LPBYTE)info+DIB_BitmapInfoSize(info, DIB_RGB_COLORS));
2126 DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
2127 if ((hdc = GetDC(0)) != 0) {
2128 char *bits = (char *)info + size;
2129 if (loadflags & LR_CREATEDIBSECTION) {
2130 DIBSECTION dib;
2131 hbitmap = CreateDIBSection(hdc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
2132 GetObjectA(hbitmap, sizeof(DIBSECTION), &dib);
2133 SetDIBits(hdc, hbitmap, 0, dib.dsBm.bmHeight, bits, info,
2134 DIB_RGB_COLORS);
2136 else {
2137 hbitmap = CreateDIBitmap( hdc, &fix_info->bmiHeader, CBM_INIT,
2138 bits, fix_info, DIB_RGB_COLORS );
2140 ReleaseDC( 0, hdc );
2142 GlobalUnlock(hFix);
2143 GlobalFree(hFix);
2145 if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
2146 return hbitmap;
2150 /***********************************************************************
2151 * LoadImage16 [USER.389]
2154 HANDLE16 WINAPI LoadImage16( HINSTANCE16 hinst, LPCSTR name, UINT16 type,
2155 INT16 desiredx, INT16 desiredy, UINT16 loadflags)
2157 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
2158 return LoadImageA( hinst, nameStr, type,
2159 desiredx, desiredy, loadflags );
2162 /**********************************************************************
2163 * LoadImageA (USER32.365)
2165 * FIXME: implementation lacks some features, see LR_ defines in windows.h
2168 HANDLE WINAPI LoadImageA( HINSTANCE hinst, LPCSTR name, UINT type,
2169 INT desiredx, INT desiredy, UINT loadflags)
2171 HANDLE res;
2172 LPWSTR u_name;
2174 if (HIWORD(name)) u_name = HEAP_strdupAtoW(GetProcessHeap(), 0, name);
2175 else u_name=(LPWSTR)name;
2176 res = LoadImageW(hinst, u_name, type, desiredx, desiredy, loadflags);
2177 if (HIWORD(name)) HeapFree(GetProcessHeap(), 0, u_name);
2178 return res;
2182 /******************************************************************************
2183 * LoadImageW [USER32.366] Loads an icon, cursor, or bitmap
2185 * PARAMS
2186 * hinst [I] Handle of instance that contains image
2187 * name [I] Name of image
2188 * type [I] Type of image
2189 * desiredx [I] Desired width
2190 * desiredy [I] Desired height
2191 * loadflags [I] Load flags
2193 * RETURNS
2194 * Success: Handle to newly loaded image
2195 * Failure: NULL
2197 * FIXME: Implementation lacks some features, see LR_ defines in windows.h
2199 HANDLE WINAPI LoadImageW( HINSTANCE hinst, LPCWSTR name, UINT type,
2200 INT desiredx, INT desiredy, UINT loadflags )
2202 if (HIWORD(name)) {
2203 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2204 hinst,name,type,desiredx,desiredy,loadflags);
2205 } else {
2206 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2207 hinst,name,type,desiredx,desiredy,loadflags);
2209 if (loadflags & LR_DEFAULTSIZE) {
2210 if (type == IMAGE_ICON) {
2211 if (!desiredx) desiredx = GetSystemMetrics(SM_CXICON);
2212 if (!desiredy) desiredy = GetSystemMetrics(SM_CYICON);
2213 } else if (type == IMAGE_CURSOR) {
2214 if (!desiredx) desiredx = GetSystemMetrics(SM_CXCURSOR);
2215 if (!desiredy) desiredy = GetSystemMetrics(SM_CYCURSOR);
2218 if (loadflags & LR_LOADFROMFILE) loadflags &= ~LR_SHARED;
2219 switch (type) {
2220 case IMAGE_BITMAP:
2221 return BITMAP_Load( hinst, name, loadflags );
2223 case IMAGE_ICON:
2225 HDC hdc = GetDC(0);
2226 UINT palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
2227 if (palEnts == 0)
2228 palEnts = 256;
2229 ReleaseDC(0, hdc);
2231 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2232 palEnts, FALSE, loadflags);
2235 case IMAGE_CURSOR:
2236 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2237 1, TRUE, loadflags);
2239 return 0;
2243 /******************************************************************************
2244 * CopyImage16 [USER.390] Creates new image and copies attributes to it
2247 HICON16 WINAPI CopyImage16( HANDLE16 hnd, UINT16 type, INT16 desiredx,
2248 INT16 desiredy, UINT16 flags )
2250 return (HICON16)CopyImage((HANDLE)hnd, (UINT)type, (INT)desiredx,
2251 (INT)desiredy, (UINT)flags);
2254 /******************************************************************************
2255 * CopyImage [USER32.61] Creates new image and copies attributes to it
2257 * PARAMS
2258 * hnd [I] Handle to image to copy
2259 * type [I] Type of image to copy
2260 * desiredx [I] Desired width of new image
2261 * desiredy [I] Desired height of new image
2262 * flags [I] Copy flags
2264 * RETURNS
2265 * Success: Handle to newly created image
2266 * Failure: NULL
2268 * FIXME: implementation still lacks nearly all features, see LR_*
2269 * defines in windows.h
2271 HICON WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
2272 INT desiredy, UINT flags )
2274 switch (type)
2276 case IMAGE_BITMAP:
2277 return BITMAP_CopyBitmap(hnd);
2278 case IMAGE_ICON:
2279 return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags);
2280 case IMAGE_CURSOR:
2281 /* Should call CURSORICON_ExtCopy but more testing
2282 * needs to be done before we change this
2284 return CopyCursor(hnd);
2286 return 0;
2290 /******************************************************************************
2291 * LoadBitmapW [USER32.358] Loads bitmap from the executable file
2293 * RETURNS
2294 * Success: Handle to specified bitmap
2295 * Failure: NULL
2297 HBITMAP WINAPI LoadBitmapW(
2298 HINSTANCE instance, /* [in] Handle to application instance */
2299 LPCWSTR name) /* [in] Address of bitmap resource name */
2301 return LoadImageW( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2304 /**********************************************************************
2305 * LoadBitmapA (USER32.357)
2307 HBITMAP WINAPI LoadBitmapA( HINSTANCE instance, LPCSTR name )
2309 return LoadImageA( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2312 /**********************************************************************
2313 * LoadBitmap16 (USER.175)
2315 HBITMAP16 WINAPI LoadBitmap16( HINSTANCE16 instance, SEGPTR name )
2317 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
2318 return LoadBitmapA( instance, nameStr );