DOSFS_ToDosFCBFormat: fail if extension longer than 3 characters.
[wine/gsoc-2012-control.git] / windows / cursoricon.c
blob08b3b8aa021cbb876be549bd3d797c325510e7fd
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 "display.h"
52 #include "message.h"
53 #include "winerror.h"
55 DECLARE_DEBUG_CHANNEL(cursor);
56 DECLARE_DEBUG_CHANNEL(icon);
57 DECLARE_DEBUG_CHANNEL(resource);
59 static HCURSOR hActiveCursor = 0; /* Active cursor */
60 static INT CURSOR_ShowCount = 0; /* Cursor display count */
61 static RECT CURSOR_ClipRect; /* Cursor clipping rect */
64 /**********************************************************************
65 * ICONCACHE for cursors/icons loaded with LR_SHARED.
67 * FIXME: This should not be allocated on the system heap, but on a
68 * subsystem-global heap (i.e. one for all Win16 processes,
69 * and one each for every Win32 process).
71 typedef struct tagICONCACHE
73 struct tagICONCACHE *next;
75 HMODULE hModule;
76 HRSRC hRsrc;
77 HRSRC hGroupRsrc;
78 HANDLE handle;
80 INT count;
82 } ICONCACHE;
84 static ICONCACHE *IconAnchor = NULL;
85 static CRITICAL_SECTION IconCrst;
86 static DWORD ICON_HOTSPOT = 0x42424242;
88 /**********************************************************************
89 * CURSORICON_Init
91 void CURSORICON_Init( void )
93 InitializeCriticalSection( &IconCrst );
94 MakeCriticalSectionGlobal( &IconCrst );
97 /**********************************************************************
98 * CURSORICON_FindSharedIcon
100 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
102 HANDLE handle = 0;
103 ICONCACHE *ptr;
105 EnterCriticalSection( &IconCrst );
107 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
108 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
110 ptr->count++;
111 handle = ptr->handle;
112 break;
115 LeaveCriticalSection( &IconCrst );
117 return handle;
120 /*************************************************************************
121 * CURSORICON_FindCache
123 * Given a handle, find the coresponding cache element
125 * PARAMS
126 * Handle [I] handle to an Image
128 * RETURNS
129 * Success: The cache entry
130 * Failure: NULL
133 static ICONCACHE* CURSORICON_FindCache(HANDLE handle)
135 ICONCACHE *ptr;
136 ICONCACHE *pRet=NULL;
137 BOOL IsFound = FALSE;
138 int count;
140 EnterCriticalSection( &IconCrst );
142 for (count = 0, ptr = IconAnchor; ptr != NULL && !IsFound; ptr = ptr->next, count++ )
144 if ( handle == ptr->handle )
146 IsFound = TRUE;
147 pRet = ptr;
151 LeaveCriticalSection( &IconCrst );
153 return pRet;
156 /**********************************************************************
157 * CURSORICON_AddSharedIcon
159 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle )
161 ICONCACHE *ptr = HeapAlloc( SystemHeap, 0, sizeof(ICONCACHE) );
162 if ( !ptr ) return;
164 ptr->hModule = hModule;
165 ptr->hRsrc = hRsrc;
166 ptr->handle = handle;
167 ptr->hGroupRsrc = hGroupRsrc;
168 ptr->count = 1;
170 EnterCriticalSection( &IconCrst );
171 ptr->next = IconAnchor;
172 IconAnchor = ptr;
173 LeaveCriticalSection( &IconCrst );
176 /**********************************************************************
177 * CURSORICON_DelSharedIcon
179 static INT CURSORICON_DelSharedIcon( HANDLE handle )
181 INT count = -1;
182 ICONCACHE *ptr;
184 EnterCriticalSection( &IconCrst );
186 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
187 if ( ptr->handle == handle )
189 if ( ptr->count > 0 ) ptr->count--;
190 count = ptr->count;
191 break;
194 LeaveCriticalSection( &IconCrst );
196 return count;
199 /**********************************************************************
200 * CURSORICON_FreeModuleIcons
202 void CURSORICON_FreeModuleIcons( HMODULE hModule )
204 ICONCACHE **ptr = &IconAnchor;
206 if ( HIWORD( hModule ) )
207 hModule = MapHModuleLS( hModule );
208 else
209 hModule = GetExePtr( hModule );
211 EnterCriticalSection( &IconCrst );
213 while ( *ptr )
215 if ( (*ptr)->hModule == hModule )
217 ICONCACHE *freePtr = *ptr;
218 *ptr = freePtr->next;
220 GlobalFree16( freePtr->handle );
221 HeapFree( SystemHeap, 0, freePtr );
222 continue;
224 ptr = &(*ptr)->next;
227 LeaveCriticalSection( &IconCrst );
230 /**********************************************************************
231 * CURSORICON_FindBestIcon
233 * Find the icon closest to the requested size and number of colors.
235 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
236 int height, int colors )
238 int i;
239 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
240 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
241 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
243 if (dir->idCount < 1)
245 WARN_(icon)("Empty directory!\n" );
246 return NULL;
248 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
250 /* Find Best Fit */
251 iTotalDiff = 0xFFFFFFFF;
252 iColorDiff = 0xFFFFFFFF;
253 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
255 iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
256 iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
258 if(iTotalDiff > (iTempXDiff + iTempYDiff))
260 iXDiff = iTempXDiff;
261 iYDiff = iTempYDiff;
262 iTotalDiff = iXDiff + iYDiff;
266 /* Find Best Colors for Best Fit */
267 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
269 if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
270 abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
272 iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
273 if(iColorDiff > iTempColorDiff)
275 bestEntry = entry;
276 iColorDiff = iTempColorDiff;
281 return bestEntry;
285 /**********************************************************************
286 * CURSORICON_FindBestCursor
288 * Find the cursor closest to the requested size.
289 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
290 * ignored too
292 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
293 int width, int height, int color)
295 int i, maxwidth, maxheight;
296 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
298 if (dir->idCount < 1)
300 WARN_(cursor)("Empty directory!\n" );
301 return NULL;
303 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
305 /* Double height to account for AND and XOR masks */
307 height *= 2;
309 /* First find the largest one smaller than or equal to the requested size*/
311 maxwidth = maxheight = 0;
312 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
313 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
314 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
315 (entry->wBitCount == 1))
317 bestEntry = entry;
318 maxwidth = entry->ResInfo.cursor.wWidth;
319 maxheight = entry->ResInfo.cursor.wHeight;
321 if (bestEntry) return bestEntry;
323 /* Now find the smallest one larger than the requested size */
325 maxwidth = maxheight = 255;
326 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
327 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
328 (entry->wBitCount == 1))
330 bestEntry = entry;
331 maxwidth = entry->ResInfo.cursor.wWidth;
332 maxheight = entry->ResInfo.cursor.wHeight;
335 return bestEntry;
338 /*********************************************************************
339 * The main purpose of this function is to create fake resource directory
340 * and fake resource entries. There are several reasons for this:
341 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
342 * fields
343 * There are some "bad" cursor files which do not have
344 * bColorCount initialized but instead one must read this info
345 * directly from corresponding DIB sections
346 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
348 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
349 CURSORICONDIR **res, LPBYTE **ptr)
351 LPBYTE _free;
352 CURSORICONFILEDIR *bits;
353 int entries, size, i;
355 *res = NULL;
356 *ptr = NULL;
357 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
359 /* FIXME: test for inimated icons
360 * hack to load the first icon from the *.ani file
362 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
363 { LPBYTE pos = (LPBYTE) bits;
364 FIXME_(cursor)("Animated icons not correctly implemented! %p \n", bits);
366 for (;;)
367 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
368 { FIXME_(cursor)("icon entry found! %p\n", bits);
369 pos+=4;
370 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
371 { goto fail;
373 bits=(CURSORICONFILEDIR*)(pos+4);
374 FIXME_(cursor)("icon size ok. offset=%p \n", bits);
375 break;
377 pos+=2;
378 if (pos>=(LPBYTE)bits+766) goto fail;
381 if (!(entries = bits->idCount)) goto fail;
382 size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) * (entries - 1);
383 _free = (LPBYTE) size;
385 for (i=0; i < entries; i++)
386 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
388 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
389 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
390 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
392 _free = (LPBYTE)(*res) + (int)_free;
393 memcpy((*res), bits, 6);
394 for (i=0; i<entries; i++)
396 ((LPBYTE*)(*ptr))[i] = _free;
397 if (fCursor) {
398 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
399 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
400 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
401 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
402 _free+=sizeof(POINT16);
403 } else {
404 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
405 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
406 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
408 (*res)->idEntries[i].wPlanes=1;
409 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
410 bits->idEntries[i].dwDIBOffset))->biBitCount;
411 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
412 (*res)->idEntries[i].wResId=i+1;
414 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
415 (*res)->idEntries[i].dwBytesInRes);
416 _free += (*res)->idEntries[i].dwBytesInRes;
418 UnmapViewOfFile( bits );
419 return TRUE;
420 fail:
421 if (*res) HeapFree( GetProcessHeap(), 0, *res );
422 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
423 UnmapViewOfFile( bits );
424 return FALSE;
428 /**********************************************************************
429 * CURSORICON_CreateFromResource
431 * Create a cursor or icon from in-memory resource template.
433 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
434 * with cbSize parameter as well.
436 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
437 UINT cbSize, BOOL bIcon, DWORD dwVersion,
438 INT width, INT height, UINT loadflags )
440 int sizeAnd, sizeXor;
441 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
442 BITMAPOBJ *bmpXor, *bmpAnd;
443 POINT16 hotspot;
444 BITMAPINFO *bmi;
445 HDC hdc;
446 BOOL DoStretch;
447 INT size;
449 hotspot.x = ICON_HOTSPOT;
450 hotspot.y = ICON_HOTSPOT;
452 TRACE_(cursor)("%08x (%u bytes), ver %08x, %ix%i %s %s\n",
453 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
454 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
455 if (dwVersion == 0x00020000)
457 FIXME_(cursor)("\t2.xx resources are not supported\n");
458 return 0;
461 if (bIcon)
462 bmi = (BITMAPINFO *)bits;
463 else /* get the hotspot */
465 POINT16 *pt = (POINT16 *)bits;
466 hotspot = *pt;
467 bmi = (BITMAPINFO *)(pt + 1);
469 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
471 if (!width) width = bmi->bmiHeader.biWidth;
472 if (!height) height = bmi->bmiHeader.biHeight/2;
473 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
474 (bmi->bmiHeader.biWidth != width);
476 /* Check bitmap header */
478 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
479 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
480 bmi->bmiHeader.biCompression != BI_RGB) )
482 WARN_(cursor)("\tinvalid resource bitmap header.\n");
483 return 0;
486 if( (hdc = GetDC( 0 )) )
488 BITMAPINFO* pInfo;
490 /* Make sure we have room for the monochrome bitmap later on.
491 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
492 * up to and including the biBitCount. In-memory icon resource
493 * format is as follows:
495 * BITMAPINFOHEADER icHeader // DIB header
496 * RGBQUAD icColors[] // Color table
497 * BYTE icXOR[] // DIB bits for XOR mask
498 * BYTE icAND[] // DIB bits for AND mask
501 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
502 max(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
504 memcpy( pInfo, bmi, size );
505 pInfo->bmiHeader.biHeight /= 2;
507 /* Create the XOR bitmap */
509 if (DoStretch) {
510 if(bIcon)
512 hXorBits = CreateCompatibleBitmap(hdc, width, height);
514 else
516 hXorBits = CreateBitmap(width, height, 1, 1, NULL);
518 if(hXorBits)
520 HBITMAP hOld;
521 HDC hMem = CreateCompatibleDC(hdc);
522 BOOL res;
524 if (hMem) {
525 hOld = SelectObject(hMem, hXorBits);
526 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
527 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
528 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
529 SelectObject(hMem, hOld);
530 DeleteDC(hMem);
531 } else res = FALSE;
532 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
534 } else hXorBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
535 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
536 if( hXorBits )
538 char* bits = (char *)bmi + size +
539 DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
540 bmi->bmiHeader.biHeight,
541 bmi->bmiHeader.biBitCount) / 2;
543 pInfo->bmiHeader.biBitCount = 1;
544 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
546 RGBQUAD *rgb = pInfo->bmiColors;
548 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
549 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
550 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
551 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
553 else
555 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
557 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
558 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
561 /* Create the AND bitmap */
563 if (DoStretch) {
564 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
565 HBITMAP hOld;
566 HDC hMem = CreateCompatibleDC(hdc);
567 BOOL res;
569 if (hMem) {
570 hOld = SelectObject(hMem, hAndBits);
571 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
572 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
573 bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
574 SelectObject(hMem, hOld);
575 DeleteDC(hMem);
576 } else res = FALSE;
577 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
579 } else hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
580 CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
582 if( !hAndBits ) DeleteObject( hXorBits );
584 HeapFree( GetProcessHeap(), 0, pInfo );
586 ReleaseDC( 0, hdc );
589 if( !hXorBits || !hAndBits )
591 WARN_(cursor)("\tunable to create an icon bitmap.\n");
592 return 0;
595 /* Now create the CURSORICONINFO structure */
596 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
597 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
598 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
599 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
601 if (hObj) hObj = GlobalReAlloc16( hObj,
602 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
603 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
604 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
605 if (hObj)
607 CURSORICONINFO *info;
609 /* Make it owned by the module */
610 if (hInstance) FarSetOwner16( hObj, GetExePtr(hInstance) );
612 info = (CURSORICONINFO *)GlobalLock16( hObj );
613 info->ptHotSpot.x = hotspot.x;
614 info->ptHotSpot.y = hotspot.y;
615 info->nWidth = bmpXor->bitmap.bmWidth;
616 info->nHeight = bmpXor->bitmap.bmHeight;
617 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
618 info->bPlanes = bmpXor->bitmap.bmPlanes;
619 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
621 /* Transfer the bitmap bits to the CURSORICONINFO structure */
623 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
624 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
625 GlobalUnlock16( hObj );
628 DeleteObject( hXorBits );
629 DeleteObject( hAndBits );
630 return hObj;
634 /**********************************************************************
635 * CreateIconFromResourceEx16 (USER.450)
637 * FIXME: not sure about exact parameter types
639 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
640 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
642 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
643 width, height, cFlag);
647 /**********************************************************************
648 * CreateIconFromResource (USER32.76)
650 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
651 BOOL bIcon, DWORD dwVersion)
653 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
657 /**********************************************************************
658 * CreateIconFromResourceEx32 (USER32.77)
660 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
661 BOOL bIcon, DWORD dwVersion,
662 INT width, INT height,
663 UINT cFlag )
665 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
666 if( pTask )
667 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
668 width, height, cFlag );
669 return 0;
672 /**********************************************************************
673 * CURSORICON_Load
675 * Load a cursor or icon from resource or file.
677 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
678 INT width, INT height, INT colors,
679 BOOL fCursor, UINT loadflags )
681 HANDLE handle = 0, h = 0;
682 HANDLE hRsrc;
683 CURSORICONDIR *dir;
684 CURSORICONDIRENTRY *dirEntry;
685 LPBYTE bits;
687 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
689 LPBYTE *ptr;
690 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
691 return 0;
692 if (fCursor)
693 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
694 else
695 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
696 bits = ptr[dirEntry->wResId-1];
697 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
698 !fCursor, 0x00030000, width, height, loadflags);
699 HeapFree( GetProcessHeap(), 0, dir );
700 HeapFree( GetProcessHeap(), 0, ptr );
703 else if ( !hInstance ) /* Load OEM cursor/icon */
705 WORD resid;
706 HDC hdc;
708 if ( HIWORD(name) )
710 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
711 if( ansi[0]=='#') /*Check for '#xxx' name */
713 resid = atoi(ansi+1);
714 HeapFree( GetProcessHeap(), 0, ansi );
716 else
718 HeapFree( GetProcessHeap(), 0, ansi );
719 return 0;
722 else resid = LOWORD(name);
723 hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
724 if (hdc) {
725 DC *dc = DC_GetDCPtr( hdc );
726 if (dc->funcs->pLoadOEMResource)
727 h = dc->funcs->pLoadOEMResource( resid, fCursor ? OEM_CURSOR : OEM_ICON );
728 GDI_HEAP_UNLOCK( hdc );
729 DeleteDC( hdc );
733 else /* Load from resource */
735 HANDLE hGroupRsrc;
736 WORD wResId;
737 DWORD dwBytesInRes;
739 /* Normalize hInstance (must be uniquely represented for icon cache) */
741 if ( HIWORD( hInstance ) )
742 hInstance = MapHModuleLS( hInstance );
743 else
744 hInstance = GetExePtr( hInstance );
746 /* Get directory resource ID */
748 if (!(hRsrc = FindResourceW( hInstance, name,
749 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
750 return 0;
751 hGroupRsrc = hRsrc;
752 /* If shared icon, check whether it was already loaded */
754 if ( (loadflags & LR_SHARED)
755 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
756 return h;
758 /* Find the best entry in the directory */
760 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
761 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
762 if (fCursor)
763 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
764 width, height, 1);
765 else
766 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
767 width, height, colors );
768 if (!dirEntry) return 0;
769 wResId = dirEntry->wResId;
770 dwBytesInRes = dirEntry->dwBytesInRes;
771 FreeResource( handle );
773 /* Load the resource */
775 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
776 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
777 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
778 bits = (LPBYTE)LockResource( handle );
779 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
780 !fCursor, 0x00030000, width, height, loadflags);
781 FreeResource( handle );
783 /* If shared icon, add to icon cache */
785 if ( h && (loadflags & LR_SHARED) )
786 CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, h );
789 return h;
792 /***********************************************************************
793 * CURSORICON_Copy
795 * Make a copy of a cursor or icon.
797 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
799 char *ptrOld, *ptrNew;
800 int size;
801 HGLOBAL16 hNew;
803 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
804 if (!(hInstance = GetExePtr( hInstance ))) return 0;
805 size = GlobalSize16( handle );
806 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
807 FarSetOwner16( hNew, hInstance );
808 ptrNew = (char *)GlobalLock16( hNew );
809 memcpy( ptrNew, ptrOld, size );
810 GlobalUnlock16( handle );
811 GlobalUnlock16( hNew );
812 return hNew;
815 /*************************************************************************
816 * CURSORICON_ExtCopy
818 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified
820 * PARAMS
821 * Handle [I] handle to an Image
822 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)
823 * iDesiredCX [I] The Desired width of the Image
824 * iDesiredCY [I] The desired height of the Image
825 * nFlags [I] The flags from CopyImage
827 * RETURNS
828 * Success: The new handle of the Image
830 * NOTES
831 * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented.
832 * LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource.
833 * LR_COPYFROMRESOURCE will only work if the Image is in the Cache.
838 HGLOBAL CURSORICON_ExtCopy(HGLOBAL Handle, UINT nType,
839 INT iDesiredCX, INT iDesiredCY,
840 UINT nFlags)
842 HGLOBAL16 hNew=0;
844 TRACE_(icon)("Handle %u, uType %u, iDesiredCX %i, iDesiredCY %i, nFlags %u\n",
845 Handle, nType, iDesiredCX, iDesiredCY, nFlags);
847 if(Handle == 0)
849 return 0;
852 /* Best Fit or Monochrome */
853 if( (nFlags & LR_COPYFROMRESOURCE
854 && (iDesiredCX > 0 || iDesiredCY > 0))
855 || nFlags & LR_MONOCHROME)
857 ICONCACHE* pIconCache = CURSORICON_FindCache(Handle);
859 /* Not Found in Cache, then do a strait copy
861 if(pIconCache == NULL)
863 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
864 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
865 if(nFlags & LR_COPYFROMRESOURCE)
867 TRACE_(icon)("LR_COPYFROMRESOURCE: Failed to load from cache\n");
870 else
872 int iTargetCY = iDesiredCY, iTargetCX = iDesiredCX;
873 LPBYTE pBits;
874 HANDLE hMem;
875 HRSRC hRsrc;
876 DWORD dwBytesInRes;
877 WORD wResId;
878 CURSORICONDIR *pDir;
879 CURSORICONDIRENTRY *pDirEntry;
880 BOOL bIsIcon = (nType == IMAGE_ICON);
882 /* Completing iDesiredCX CY for Monochrome Bitmaps if needed
884 if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE))
885 || (iDesiredCX == 0 && iDesiredCY == 0))
887 iDesiredCY = GetSystemMetrics(bIsIcon ?
888 SM_CYICON : SM_CYCURSOR);
889 iDesiredCX = GetSystemMetrics(bIsIcon ?
890 SM_CXICON : SM_CXCURSOR);
893 /* Retreive the CURSORICONDIRENTRY
895 if (!(hMem = LoadResource( pIconCache->hModule ,
896 pIconCache->hGroupRsrc)))
898 return 0;
900 if (!(pDir = (CURSORICONDIR*)LockResource( hMem )))
902 return 0;
905 /* Find Best Fit
907 if(bIsIcon)
909 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(
910 pDir, iDesiredCX, iDesiredCY, 256);
912 else
914 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(
915 pDir, iDesiredCX, iDesiredCY, 1);
918 wResId = pDirEntry->wResId;
919 dwBytesInRes = pDirEntry->dwBytesInRes;
920 FreeResource(hMem);
922 TRACE_(icon)("ResID %u, BytesInRes %lu, Width %d, Height %d DX %d, DY %d\n",
923 wResId, dwBytesInRes, pDirEntry->ResInfo.icon.bWidth,
924 pDirEntry->ResInfo.icon.bHeight, iDesiredCX, iDesiredCY);
926 /* Get the Best Fit
928 if (!(hRsrc = FindResourceW(pIconCache->hModule ,
929 MAKEINTRESOURCEW(wResId), bIsIcon ? RT_ICONW : RT_CURSORW)))
931 return 0;
933 if (!(hMem = LoadResource( pIconCache->hModule , hRsrc )))
935 return 0;
938 pBits = (LPBYTE)LockResource( hMem );
940 if(nFlags & LR_DEFAULTSIZE)
942 iTargetCY = GetSystemMetrics(SM_CYICON);
943 iTargetCX = GetSystemMetrics(SM_CXICON);
946 /* Create a New Icon with the proper dimension
948 hNew = CURSORICON_CreateFromResource( 0, 0, pBits, dwBytesInRes,
949 bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
950 FreeResource(hMem);
953 else
955 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
956 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
958 return hNew;
961 /***********************************************************************
962 * CURSORICON_IconToCursor
964 * Converts bitmap to mono and truncates if icon is too large (should
965 * probably do StretchBlt() instead).
967 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
969 HCURSOR16 hRet = 0;
970 CURSORICONINFO *pIcon = NULL;
971 HTASK16 hTask = GetCurrentTask();
972 TDB* pTask = (TDB *)GlobalLock16(hTask);
974 if(hIcon && pTask)
975 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
976 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
978 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
981 pIcon = GlobalLock16(hRet);
983 pIcon->ptHotSpot.x = pIcon->ptHotSpot.y = 15;
985 GlobalUnlock16(hRet);
987 else
989 BYTE pAndBits[128];
990 BYTE pXorBits[128];
991 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
992 BYTE* psPtr, *pxbPtr = pXorBits;
993 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
994 BYTE* pbc = NULL;
996 CURSORICONINFO cI;
998 TRACE_(icon)("[%04x] %ix%i %ibpp (bogus %ibps)\n",
999 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
1001 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
1002 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
1003 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
1005 memset(pXorBits, 0, 128);
1006 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
1007 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
1008 cI.nWidth = 32; cI.nHeight = 32;
1009 cI.nWidthBytes = 4; /* 32x1bpp */
1011 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
1012 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
1014 for( iy = 0; iy < maxy; iy++ )
1016 unsigned shift = iy % 2;
1018 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
1019 (and_width > 4) ? 4 : and_width );
1020 for( ix = 0; ix < maxx; ix++ )
1022 if( bSemiTransparent && ((ix+shift)%2) )
1024 /* set AND bit, XOR bit stays 0 */
1026 pbc = pAndBits + iy * 4 + ix/8;
1027 *pbc |= 0x80 >> (ix%8);
1029 else
1031 /* keep AND bit, set XOR bit */
1033 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
1034 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
1035 if(!PALETTE_Driver->pIsDark(val))
1037 pbc = pxbPtr + ix/8;
1038 *pbc |= 0x80 >> (ix%8);
1042 psPtr += xor_width;
1043 pxbPtr += 4;
1046 hRet = CreateCursorIconIndirect16( pTask->hInstance , &cI, pAndBits, pXorBits);
1048 if( !hRet ) /* fall back on default drag cursor */
1049 hRet = CURSORICON_Copy( pTask->hInstance ,
1050 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
1051 GetSystemMetrics(SM_CXCURSOR),
1052 GetSystemMetrics(SM_CYCURSOR), 1, TRUE, 0) );
1055 return hRet;
1059 /***********************************************************************
1060 * LoadCursor16 (USER.173)
1062 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
1064 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1065 return LoadCursorA( hInstance, nameStr );
1069 /***********************************************************************
1070 * LoadIcon16 (USER.174)
1072 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
1074 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1075 return LoadIconA( hInstance, nameStr );
1079 /***********************************************************************
1080 * CreateCursor16 (USER.406)
1082 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
1083 INT16 xHotSpot, INT16 yHotSpot,
1084 INT16 nWidth, INT16 nHeight,
1085 LPCVOID lpANDbits, LPCVOID lpXORbits )
1087 CURSORICONINFO info;
1089 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1090 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1092 info.ptHotSpot.x = xHotSpot;
1093 info.ptHotSpot.y = yHotSpot;
1094 info.nWidth = nWidth;
1095 info.nHeight = nHeight;
1096 info.nWidthBytes = 0;
1097 info.bPlanes = 1;
1098 info.bBitsPerPixel = 1;
1100 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1104 /***********************************************************************
1105 * CreateCursor32 (USER32.67)
1107 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
1108 INT xHotSpot, INT yHotSpot,
1109 INT nWidth, INT nHeight,
1110 LPCVOID lpANDbits, LPCVOID lpXORbits )
1112 CURSORICONINFO info;
1114 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1115 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1117 info.ptHotSpot.x = xHotSpot;
1118 info.ptHotSpot.y = yHotSpot;
1119 info.nWidth = nWidth;
1120 info.nHeight = nHeight;
1121 info.nWidthBytes = 0;
1122 info.bPlanes = 1;
1123 info.bBitsPerPixel = 1;
1125 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1129 /***********************************************************************
1130 * CreateIcon16 (USER.407)
1132 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
1133 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
1134 LPCVOID lpANDbits, LPCVOID lpXORbits )
1136 CURSORICONINFO info;
1138 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1139 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1141 info.ptHotSpot.x = ICON_HOTSPOT;
1142 info.ptHotSpot.y = ICON_HOTSPOT;
1143 info.nWidth = nWidth;
1144 info.nHeight = nHeight;
1145 info.nWidthBytes = 0;
1146 info.bPlanes = bPlanes;
1147 info.bBitsPerPixel = bBitsPixel;
1149 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1153 /***********************************************************************
1154 * CreateIcon32 (USER32.75)
1156 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
1157 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
1158 LPCVOID lpANDbits, LPCVOID lpXORbits )
1160 CURSORICONINFO info;
1162 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1163 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1165 info.ptHotSpot.x = ICON_HOTSPOT;
1166 info.ptHotSpot.y = ICON_HOTSPOT;
1167 info.nWidth = nWidth;
1168 info.nHeight = nHeight;
1169 info.nWidthBytes = 0;
1170 info.bPlanes = bPlanes;
1171 info.bBitsPerPixel = bBitsPixel;
1173 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1177 /***********************************************************************
1178 * CreateCursorIconIndirect (USER.408)
1180 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
1181 CURSORICONINFO *info,
1182 LPCVOID lpANDbits,
1183 LPCVOID lpXORbits )
1185 HGLOBAL16 handle;
1186 char *ptr;
1187 int sizeAnd, sizeXor;
1189 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
1190 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
1191 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
1192 sizeXor = info->nHeight * info->nWidthBytes;
1193 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1194 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
1195 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1196 return 0;
1197 if (hInstance) FarSetOwner16( handle, hInstance );
1198 ptr = (char *)GlobalLock16( handle );
1199 memcpy( ptr, info, sizeof(*info) );
1200 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1201 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1202 GlobalUnlock16( handle );
1203 return handle;
1207 /***********************************************************************
1208 * CopyIcon16 (USER.368)
1210 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1212 TRACE_(icon)("%04x %04x\n", hInstance, hIcon );
1213 return CURSORICON_Copy( hInstance, hIcon );
1217 /***********************************************************************
1218 * CopyIcon32 (USER32.60)
1220 HICON WINAPI CopyIcon( HICON hIcon )
1222 HTASK16 hTask = GetCurrentTask ();
1223 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1224 TRACE_(icon)("%04x\n", hIcon );
1225 return CURSORICON_Copy( pTask->hInstance, hIcon );
1229 /***********************************************************************
1230 * CopyCursor16 (USER.369)
1232 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1234 TRACE_(cursor)("%04x %04x\n", hInstance, hCursor );
1235 return CURSORICON_Copy( hInstance, hCursor );
1238 /**********************************************************************
1239 * CURSORICON_Destroy (USER.610)
1241 * This routine is actually exported from Win95 USER under the name
1242 * DestroyIcon32 ... The behaviour implemented here should mimic
1243 * the Win95 one exactly, especially the return values, which
1244 * depend on the setting of various flags.
1246 WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1248 WORD retv;
1250 TRACE_(icon)("(%04x, %04x)\n", handle, flags );
1252 /* Check whether destroying active cursor */
1254 if ( hActiveCursor == handle )
1256 ERR_(cursor)("Destroying active cursor!\n" );
1257 SetCursor( 0 );
1260 /* Try shared cursor/icon first */
1262 if ( !(flags & CID_NONSHARED) )
1264 INT count = CURSORICON_DelSharedIcon( handle );
1266 if ( count != -1 )
1267 return (flags & CID_WIN32)? TRUE : (count == 0);
1269 /* FIXME: OEM cursors/icons should be recognized */
1272 /* Now assume non-shared cursor/icon */
1274 retv = GlobalFree16( handle );
1275 return (flags & CID_RESOURCE)? retv : TRUE;
1278 /***********************************************************************
1279 * DestroyIcon16 (USER.457)
1281 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1283 return CURSORICON_Destroy( hIcon, 0 );
1286 /***********************************************************************
1287 * DestroyIcon (USER32.133)
1289 BOOL WINAPI DestroyIcon( HICON hIcon )
1291 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1294 /***********************************************************************
1295 * DestroyCursor16 (USER.458)
1297 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1299 return CURSORICON_Destroy( hCursor, 0 );
1302 /***********************************************************************
1303 * DestroyCursor (USER32.132)
1305 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1307 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1311 /***********************************************************************
1312 * DrawIcon16 (USER.84)
1314 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1316 return DrawIcon( hdc, x, y, hIcon );
1320 /***********************************************************************
1321 * DrawIcon32 (USER32.159)
1323 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1325 CURSORICONINFO *ptr;
1326 HDC hMemDC;
1327 HBITMAP hXorBits, hAndBits;
1328 COLORREF oldFg, oldBg;
1330 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1331 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1332 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1333 (char *)(ptr+1) );
1334 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1335 ptr->bBitsPerPixel, (char *)(ptr + 1)
1336 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1337 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1338 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1340 if (hXorBits && hAndBits)
1342 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1343 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1344 SelectObject( hMemDC, hXorBits );
1345 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1346 SelectObject( hMemDC, hBitTemp );
1348 DeleteDC( hMemDC );
1349 if (hXorBits) DeleteObject( hXorBits );
1350 if (hAndBits) DeleteObject( hAndBits );
1351 GlobalUnlock16( hIcon );
1352 SetTextColor( hdc, oldFg );
1353 SetBkColor( hdc, oldBg );
1354 return TRUE;
1358 /***********************************************************************
1359 * DumpIcon (USER.459)
1361 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1362 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1364 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1365 int sizeAnd, sizeXor;
1367 if (!info) return 0;
1368 sizeXor = info->nHeight * info->nWidthBytes;
1369 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1370 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1371 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1372 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1373 return MAKELONG( sizeXor, sizeXor );
1377 /***********************************************************************
1378 * SetCursor16 (USER.69)
1380 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1382 return (HCURSOR16)SetCursor( hCursor );
1386 /***********************************************************************
1387 * SetCursor32 (USER32.472)
1388 * RETURNS:
1389 * A handle to the previous cursor shape.
1391 HCURSOR WINAPI SetCursor(
1392 HCURSOR hCursor /* Handle of cursor to show */
1394 HCURSOR hOldCursor;
1396 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1397 TRACE_(cursor)("%04x\n", hCursor );
1398 hOldCursor = hActiveCursor;
1399 hActiveCursor = hCursor;
1400 /* Change the cursor shape only if it is visible */
1401 if (CURSOR_ShowCount >= 0)
1403 DISPLAY_SetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1404 GlobalUnlock16( hActiveCursor );
1406 return hOldCursor;
1410 /***********************************************************************
1411 * SetCursorPos16 (USER.70)
1413 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1415 SetCursorPos( x, y );
1419 /***********************************************************************
1420 * SetCursorPos32 (USER32.474)
1422 BOOL WINAPI SetCursorPos( INT x, INT y )
1424 DISPLAY_MoveCursor( x, y );
1425 return TRUE;
1429 /***********************************************************************
1430 * ShowCursor16 (USER.71)
1432 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1434 return ShowCursor( bShow );
1438 /***********************************************************************
1439 * ShowCursor32 (USER32.530)
1441 INT WINAPI ShowCursor( BOOL bShow )
1443 TRACE_(cursor)("%d, count=%d\n",
1444 bShow, CURSOR_ShowCount );
1446 if (bShow)
1448 if (++CURSOR_ShowCount == 0) /* Show it */
1450 DISPLAY_SetCursor((CURSORICONINFO*)GlobalLock16( hActiveCursor ));
1451 GlobalUnlock16( hActiveCursor );
1454 else
1456 if (--CURSOR_ShowCount == -1) /* Hide it */
1457 DISPLAY_SetCursor( NULL );
1459 return CURSOR_ShowCount;
1463 /***********************************************************************
1464 * GetCursor16 (USER.247)
1466 HCURSOR16 WINAPI GetCursor16(void)
1468 return hActiveCursor;
1472 /***********************************************************************
1473 * GetCursor32 (USER32.227)
1475 HCURSOR WINAPI GetCursor(void)
1477 return hActiveCursor;
1481 /***********************************************************************
1482 * ClipCursor16 (USER.16)
1484 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1486 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1487 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1488 return TRUE;
1492 /***********************************************************************
1493 * ClipCursor32 (USER32.53)
1495 BOOL WINAPI ClipCursor( const RECT *rect )
1497 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1498 else CopyRect( &CURSOR_ClipRect, rect );
1499 return TRUE;
1503 /***********************************************************************
1504 * GetCursorPos16 (USER.17)
1506 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
1508 if (!pt) return 0;
1510 pt->x = PosX;
1511 pt->y = PosY;
1513 TRACE_(cursor)("ret=%d,%d\n", pt->x, pt->y );
1514 return 1;
1518 /***********************************************************************
1519 * GetCursorPos32 (USER32.229)
1521 BOOL WINAPI GetCursorPos( POINT *pt )
1523 BOOL ret;
1525 POINT16 pt16;
1526 ret = GetCursorPos16( &pt16 );
1527 if (pt) CONV_POINT16TO32( &pt16, pt );
1528 return ((pt) ? ret : 0);
1532 /***********************************************************************
1533 * GetClipCursor16 (USER.309)
1535 void WINAPI GetClipCursor16( RECT16 *rect )
1537 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1541 /***********************************************************************
1542 * GetClipCursor32 (USER32.221)
1544 BOOL WINAPI GetClipCursor( RECT *rect )
1546 if (rect)
1548 CopyRect( rect, &CURSOR_ClipRect );
1549 return TRUE;
1551 return FALSE;
1554 /**********************************************************************
1555 * LookupIconIdFromDirectoryEx16 (USER.364)
1557 * FIXME: exact parameter sizes
1559 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1560 INT16 width, INT16 height, UINT16 cFlag )
1562 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1563 UINT16 retVal = 0;
1564 if( dir && !dir->idReserved && (dir->idType & 3) )
1566 CURSORICONDIRENTRY* entry;
1567 HDC hdc;
1568 UINT palEnts;
1569 int colors;
1570 hdc = GetDC(0);
1571 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1572 if (palEnts == 0)
1573 palEnts = 256;
1574 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1576 ReleaseDC(0, hdc);
1578 if( bIcon )
1579 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1580 else
1581 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1583 if( entry ) retVal = entry->wResId;
1585 else WARN_(cursor)("invalid resource directory\n");
1586 return retVal;
1589 /**********************************************************************
1590 * LookupIconIdFromDirectoryEx32 (USER32.380)
1592 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1593 INT width, INT height, UINT cFlag )
1595 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1598 /**********************************************************************
1599 * LookupIconIdFromDirectory (USER.???)
1601 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1603 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1604 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1605 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1608 /**********************************************************************
1609 * LookupIconIdFromDirectory (USER32.379)
1611 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1613 return LookupIconIdFromDirectoryEx( dir, bIcon,
1614 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1615 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1618 /**********************************************************************
1619 * GetIconID (USER.455)
1621 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1623 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1625 TRACE_(cursor)("hRes=%04x, entries=%i\n",
1626 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1628 switch(resType)
1630 case RT_CURSOR16:
1631 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1632 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1633 case RT_ICON16:
1634 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1635 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0 );
1636 default:
1637 WARN_(cursor)("invalid res type %ld\n", resType );
1639 return 0;
1642 /**********************************************************************
1643 * LoadCursorIconHandler (USER.336)
1645 * Supposed to load resources of Windows 2.x applications.
1647 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1649 FIXME_(cursor)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1650 hResource, hModule, hRsrc);
1651 return (HGLOBAL16)0;
1654 /**********************************************************************
1655 * LoadDIBIconHandler (USER.357)
1657 * RT_ICON resource loader, installed by USER_SignalProc when module
1658 * is initialized.
1660 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1662 /* If hResource is zero we must allocate a new memory block, if it's
1663 * non-zero but GlobalLock() returns NULL then it was discarded and
1664 * we have to recommit some memory, otherwise we just need to check
1665 * the block size. See LoadProc() in 16-bit SDK for more.
1668 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1669 if( hMemObj )
1671 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1672 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1673 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1674 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR );
1676 return hMemObj;
1679 /**********************************************************************
1680 * LoadDIBCursorHandler (USER.356)
1682 * RT_CURSOR resource loader. Same as above.
1684 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1686 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1687 if( hMemObj )
1689 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1690 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1691 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1692 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1694 return hMemObj;
1697 /**********************************************************************
1698 * LoadIconHandler (USER.456)
1700 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1702 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1704 TRACE_(cursor)("hRes=%04x\n",hResource);
1706 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1707 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1710 /***********************************************************************
1711 * LoadCursorW (USER32.362)
1713 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1715 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1716 LR_SHARED | LR_DEFAULTSIZE );
1719 /***********************************************************************
1720 * LoadCursorA (USER32.359)
1722 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1724 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1725 LR_SHARED | LR_DEFAULTSIZE );
1728 /***********************************************************************
1729 * LoadCursorFromFileW (USER32.361)
1731 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1733 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1734 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1737 /***********************************************************************
1738 * LoadCursorFromFileA (USER32.360)
1740 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1742 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1743 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1746 /***********************************************************************
1747 * LoadIconW (USER32.364)
1749 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1751 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1752 LR_SHARED | LR_DEFAULTSIZE );
1755 /***********************************************************************
1756 * LoadIconA (USER32.363)
1758 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1760 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1761 LR_SHARED | LR_DEFAULTSIZE );
1764 /**********************************************************************
1765 * GetIconInfo16 (USER.395)
1767 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1769 ICONINFO ii32;
1770 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1772 iconinfo->fIcon = ii32.fIcon;
1773 iconinfo->xHotspot = ii32.xHotspot;
1774 iconinfo->yHotspot = ii32.yHotspot;
1775 iconinfo->hbmMask = ii32.hbmMask;
1776 iconinfo->hbmColor = ii32.hbmColor;
1777 return ret;
1780 /**********************************************************************
1781 * GetIconInfo32 (USER32.242)
1783 BOOL WINAPI GetIconInfo(HICON hIcon,LPICONINFO iconinfo) {
1784 CURSORICONINFO *ciconinfo;
1786 ciconinfo = GlobalLock16(hIcon);
1787 if (!ciconinfo)
1788 return FALSE;
1790 if ( (ciconinfo->ptHotSpot.x == ICON_HOTSPOT) &&
1791 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT) )
1793 iconinfo->fIcon = TRUE;
1794 iconinfo->xHotspot = 0;
1795 iconinfo->yHotspot = 0;
1797 else
1799 iconinfo->fIcon = FALSE;
1800 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1801 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1804 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1805 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1806 (char *)(ciconinfo + 1)
1807 + ciconinfo->nHeight *
1808 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1809 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1810 1, 1, (char *)(ciconinfo + 1));
1812 GlobalUnlock16(hIcon);
1814 return TRUE;
1817 /**********************************************************************
1818 * CreateIconIndirect (USER32.78)
1820 HICON WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1821 BITMAPOBJ *bmpXor,*bmpAnd;
1822 HICON hObj;
1823 int sizeXor,sizeAnd;
1825 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1826 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1828 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1829 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1831 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1832 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1833 if (hObj)
1835 CURSORICONINFO *info;
1837 info = (CURSORICONINFO *)GlobalLock16( hObj );
1839 /* If we are creating an icon, the hotspot is unused */
1840 if (iconinfo->fIcon)
1842 info->ptHotSpot.x = ICON_HOTSPOT;
1843 info->ptHotSpot.y = ICON_HOTSPOT;
1845 else
1847 info->ptHotSpot.x = iconinfo->xHotspot;
1848 info->ptHotSpot.y = iconinfo->yHotspot;
1851 info->nWidth = bmpXor->bitmap.bmWidth;
1852 info->nHeight = bmpXor->bitmap.bmHeight;
1853 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1854 info->bPlanes = bmpXor->bitmap.bmPlanes;
1855 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1857 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1859 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1860 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1861 GlobalUnlock16( hObj );
1863 return hObj;
1867 /**********************************************************************
1869 DrawIconEx16 (USER.394)
1871 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1872 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1873 HBRUSH16 hbr, UINT16 flags)
1875 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1876 istep, hbr, flags);
1880 /******************************************************************************
1881 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1883 * NOTES
1884 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1886 * PARAMS
1887 * hdc [I] Handle to device context
1888 * x0 [I] X coordinate of upper left corner
1889 * y0 [I] Y coordinate of upper left corner
1890 * hIcon [I] Handle to icon to draw
1891 * cxWidth [I] Width of icon
1892 * cyWidth [I] Height of icon
1893 * istep [I] Index of frame in animated cursor
1894 * hbr [I] Handle to background brush
1895 * flags [I] Icon-drawing flags
1897 * RETURNS
1898 * Success: TRUE
1899 * Failure: FALSE
1901 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1902 INT cxWidth, INT cyWidth, UINT istep,
1903 HBRUSH hbr, UINT flags )
1905 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1906 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1907 BOOL result = FALSE, DoOffscreen = FALSE;
1908 HBITMAP hB_off = 0, hOld = 0;
1910 if (!ptr) return FALSE;
1912 if (istep)
1913 FIXME_(icon)("Ignoring istep=%d\n", istep);
1914 if (flags & DI_COMPAT)
1915 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
1917 /* Calculate the size of the destination image. */
1918 if (cxWidth == 0)
1920 if (flags & DI_DEFAULTSIZE)
1921 cxWidth = GetSystemMetrics (SM_CXICON);
1922 else
1923 cxWidth = ptr->nWidth;
1925 if (cyWidth == 0)
1927 if (flags & DI_DEFAULTSIZE)
1928 cyWidth = GetSystemMetrics (SM_CYICON);
1929 else
1930 cyWidth = ptr->nHeight;
1933 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1934 STOCK_HOLLOW_BRUSH)))
1936 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1937 if (object)
1939 UINT16 magic = object->wMagic;
1940 GDI_HEAP_UNLOCK(hbr);
1941 DoOffscreen = magic == BRUSH_MAGIC;
1944 if (DoOffscreen) {
1945 RECT r;
1947 r.left = 0;
1948 r.top = 0;
1949 r.right = cxWidth;
1950 r.bottom = cxWidth;
1952 hDC_off = CreateCompatibleDC(hdc);
1953 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1954 if (hDC_off && hB_off) {
1955 hOld = SelectObject(hDC_off, hB_off);
1956 FillRect(hDC_off, &r, hbr);
1960 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1962 HBITMAP hXorBits, hAndBits;
1963 COLORREF oldFg, oldBg;
1964 INT nStretchMode;
1966 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1968 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1969 ptr->bPlanes, ptr->bBitsPerPixel,
1970 (char *)(ptr + 1)
1971 + ptr->nHeight *
1972 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1973 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1974 1, 1, (char *)(ptr+1) );
1975 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1976 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1978 if (hXorBits && hAndBits)
1980 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1981 if (flags & DI_MASK)
1983 if (DoOffscreen)
1984 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1985 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1986 else
1987 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1988 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1990 SelectObject( hMemDC, hXorBits );
1991 if (flags & DI_IMAGE)
1993 if (DoOffscreen)
1994 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1995 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1996 else
1997 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1998 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
2000 SelectObject( hMemDC, hBitTemp );
2001 result = TRUE;
2004 SetTextColor( hdc, oldFg );
2005 SetBkColor( hdc, oldBg );
2006 if (hXorBits) DeleteObject( hXorBits );
2007 if (hAndBits) DeleteObject( hAndBits );
2008 SetStretchBltMode (hdc, nStretchMode);
2009 if (DoOffscreen) {
2010 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
2011 SelectObject(hDC_off, hOld);
2014 if (hMemDC) DeleteDC( hMemDC );
2015 if (hDC_off) DeleteDC(hDC_off);
2016 if (hB_off) DeleteObject(hB_off);
2017 GlobalUnlock16( hIcon );
2018 return result;
2021 /**********************************************************************
2022 * BITMAP_Load
2024 static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
2026 HBITMAP hbitmap = 0;
2027 HDC hdc;
2028 HRSRC hRsrc;
2029 HGLOBAL handle;
2030 char *ptr = NULL;
2031 BITMAPINFO *info, *fix_info=NULL;
2032 HGLOBAL hFix;
2033 int size;
2035 if (!(loadflags & LR_LOADFROMFILE)) {
2036 if (!instance) /* OEM bitmap */
2038 HDC hdc;
2039 DC *dc;
2041 if (HIWORD((int)name)) return 0;
2042 hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
2043 dc = DC_GetDCPtr( hdc );
2044 if(dc->funcs->pLoadOEMResource)
2045 hbitmap = dc->funcs->pLoadOEMResource( LOWORD((int)name),
2046 OEM_BITMAP );
2047 GDI_HEAP_UNLOCK( hdc );
2048 DeleteDC( hdc );
2049 return hbitmap;
2052 if (!(hRsrc = FindResourceW( instance, name, RT_BITMAPW ))) return 0;
2053 if (!(handle = LoadResource( instance, hRsrc ))) return 0;
2055 if ((info = (BITMAPINFO *)LockResource( handle )) == NULL) return 0;
2057 else
2059 if (!(ptr = (char *)VIRTUAL_MapFileW( name ))) return 0;
2060 info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
2062 size = DIB_BitmapInfoSize(info, DIB_RGB_COLORS);
2063 if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
2064 if (fix_info) {
2065 BYTE pix;
2067 memcpy(fix_info, info, size);
2068 pix = *((LPBYTE)info+DIB_BitmapInfoSize(info, DIB_RGB_COLORS));
2069 DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
2070 if ((hdc = GetDC(0)) != 0) {
2071 char *bits = (char *)info + size;
2072 if (loadflags & LR_CREATEDIBSECTION) {
2073 DIBSECTION dib;
2074 hbitmap = CreateDIBSection(hdc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
2075 GetObjectA(hbitmap, sizeof(DIBSECTION), &dib);
2076 SetDIBits(hdc, hbitmap, 0, dib.dsBm.bmHeight, bits, info,
2077 DIB_RGB_COLORS);
2079 else {
2080 hbitmap = CreateDIBitmap( hdc, &fix_info->bmiHeader, CBM_INIT,
2081 bits, fix_info, DIB_RGB_COLORS );
2083 ReleaseDC( 0, hdc );
2085 GlobalUnlock(hFix);
2086 GlobalFree(hFix);
2088 if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
2089 return hbitmap;
2093 /***********************************************************************
2094 * LoadImage16 [USER.389]
2097 HANDLE16 WINAPI LoadImage16( HINSTANCE16 hinst, LPCSTR name, UINT16 type,
2098 INT16 desiredx, INT16 desiredy, UINT16 loadflags)
2100 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
2101 return LoadImageA( hinst, nameStr, type,
2102 desiredx, desiredy, loadflags );
2105 /**********************************************************************
2106 * LoadImageA (USER32.365)
2108 * FIXME: implementation lacks some features, see LR_ defines in windows.h
2111 HANDLE WINAPI LoadImageA( HINSTANCE hinst, LPCSTR name, UINT type,
2112 INT desiredx, INT desiredy, UINT loadflags)
2114 HANDLE res;
2115 LPWSTR u_name;
2117 if (HIWORD(name)) u_name = HEAP_strdupAtoW(GetProcessHeap(), 0, name);
2118 else u_name=(LPWSTR)name;
2119 res = LoadImageW(hinst, u_name, type, desiredx, desiredy, loadflags);
2120 if (HIWORD(name)) HeapFree(GetProcessHeap(), 0, u_name);
2121 return res;
2125 /******************************************************************************
2126 * LoadImageW [USER32.366] Loads an icon, cursor, or bitmap
2128 * PARAMS
2129 * hinst [I] Handle of instance that contains image
2130 * name [I] Name of image
2131 * type [I] Type of image
2132 * desiredx [I] Desired width
2133 * desiredy [I] Desired height
2134 * loadflags [I] Load flags
2136 * RETURNS
2137 * Success: Handle to newly loaded image
2138 * Failure: NULL
2140 * FIXME: Implementation lacks some features, see LR_ defines in windows.h
2142 HANDLE WINAPI LoadImageW( HINSTANCE hinst, LPCWSTR name, UINT type,
2143 INT desiredx, INT desiredy, UINT loadflags )
2145 if (HIWORD(name)) {
2146 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2147 hinst,name,type,desiredx,desiredy,loadflags);
2148 } else {
2149 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2150 hinst,name,type,desiredx,desiredy,loadflags);
2152 if (loadflags & LR_DEFAULTSIZE) {
2153 if (type == IMAGE_ICON) {
2154 if (!desiredx) desiredx = GetSystemMetrics(SM_CXICON);
2155 if (!desiredy) desiredy = GetSystemMetrics(SM_CYICON);
2156 } else if (type == IMAGE_CURSOR) {
2157 if (!desiredx) desiredx = GetSystemMetrics(SM_CXCURSOR);
2158 if (!desiredy) desiredy = GetSystemMetrics(SM_CYCURSOR);
2161 if (loadflags & LR_LOADFROMFILE) loadflags &= ~LR_SHARED;
2162 switch (type) {
2163 case IMAGE_BITMAP:
2164 return BITMAP_Load( hinst, name, loadflags );
2166 case IMAGE_ICON:
2168 HDC hdc = GetDC(0);
2169 UINT palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
2170 if (palEnts == 0)
2171 palEnts = 256;
2172 ReleaseDC(0, hdc);
2174 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2175 palEnts, FALSE, loadflags);
2178 case IMAGE_CURSOR:
2179 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2180 1, TRUE, loadflags);
2182 return 0;
2186 /******************************************************************************
2187 * CopyImage16 [USER.390] Creates new image and copies attributes to it
2190 HICON16 WINAPI CopyImage16( HANDLE16 hnd, UINT16 type, INT16 desiredx,
2191 INT16 desiredy, UINT16 flags )
2193 return (HICON16)CopyImage((HANDLE)hnd, (UINT)type, (INT)desiredx,
2194 (INT)desiredy, (UINT)flags);
2197 /******************************************************************************
2198 * CopyImage32 [USER32.61] Creates new image and copies attributes to it
2200 * PARAMS
2201 * hnd [I] Handle to image to copy
2202 * type [I] Type of image to copy
2203 * desiredx [I] Desired width of new image
2204 * desiredy [I] Desired height of new image
2205 * flags [I] Copy flags
2207 * RETURNS
2208 * Success: Handle to newly created image
2209 * Failure: NULL
2211 * FIXME: implementation still lacks nearly all features, see LR_*
2212 * defines in windows.h
2214 HICON WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
2215 INT desiredy, UINT flags )
2217 switch (type)
2219 case IMAGE_BITMAP:
2220 return BITMAP_CopyBitmap(hnd);
2221 case IMAGE_ICON:
2222 return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags);
2223 case IMAGE_CURSOR:
2224 /* Should call CURSORICON_ExtCopy but more testing
2225 * needs to be done before we change this
2227 return CopyCursor(hnd);
2229 return 0;
2233 /******************************************************************************
2234 * LoadBitmapW [USER32.358] Loads bitmap from the executable file
2236 * RETURNS
2237 * Success: Handle to specified bitmap
2238 * Failure: NULL
2240 HBITMAP WINAPI LoadBitmapW(
2241 HINSTANCE instance, /* [in] Handle to application instance */
2242 LPCWSTR name) /* [in] Address of bitmap resource name */
2244 return LoadImageW( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2247 /**********************************************************************
2248 * LoadBitmapA (USER32.357)
2250 HBITMAP WINAPI LoadBitmapA( HINSTANCE instance, LPCSTR name )
2252 return LoadImageA( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2255 /**********************************************************************
2256 * LoadBitmap16 (USER.175)
2258 HBITMAP16 WINAPI LoadBitmap16( HINSTANCE16 instance, SEGPTR name )
2260 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
2261 return LoadBitmapA( instance, nameStr );