* added _DISABLE_TIDENTS macro to disable any ANSI/UNICODE ambiguous elements from...
[reactos.git] / reactos / lib / user32 / windows / bitmap.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id: bitmap.c,v 1.12 2003/08/07 04:03:24 royce Exp $
20 *
21 * PROJECT: ReactOS user32.dll
22 * FILE: lib/user32/windows/input.c
23 * PURPOSE: Input
24 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
25 * UPDATE HISTORY:
26 * 09-05-2001 CSH Created
27 */
28
29 /* INCLUDES ******************************************************************/
30
31 #include <string.h>
32 #include <windows.h>
33 #include <user32.h>
34 #include <debug.h>
35 #include <stdlib.h>
36
37 /*forward declerations... actualy in user32\windows\icon.c but usful here****/
38 HICON ICON_CreateIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired);
39 CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width, int height, int colors);
40
41
42 /* FUNCTIONS *****************************************************************/
43
44 /*
45 * @implemented
46 */
47 HANDLE STDCALL
48 LoadImageA(HINSTANCE hinst,
49 LPCSTR lpszName,
50 UINT uType,
51 int cxDesired,
52 int cyDesired,
53 UINT fuLoad)
54 {
55 LPWSTR lpszWName;
56 HANDLE Handle;
57 UNICODE_STRING NameString;
58
59 if (HIWORD(lpszName))
60 {
61 RtlCreateUnicodeStringFromAsciiz(&NameString, (LPSTR)lpszName);
62 lpszWName = NameString.Buffer;
63 Handle = LoadImageW(hinst, lpszWName, uType, cxDesired,
64 cyDesired, fuLoad);
65 RtlFreeUnicodeString(&NameString);
66 }
67 else
68 {
69 Handle = LoadImageW(hinst, (LPCWSTR)lpszName, uType, cxDesired,
70 cyDesired, fuLoad);
71 }
72 return(Handle);
73 }
74
75
76 HANDLE STATIC
77 LoadCursorImage(HINSTANCE hinst, LPCWSTR lpszName, UINT fuLoad)
78 {
79 DbgPrint("FIXME: Need support for loading cursor images.\n");
80 return(NULL);
81 }
82
83
84 HANDLE STATIC
85 LoadIconImage(HINSTANCE hinst, LPCWSTR lpszName, INT width, INT height, UINT fuLoad)
86 {
87 HANDLE hResource;
88 HANDLE h2Resource;
89 HANDLE hFile;
90 HANDLE hSection;
91 CURSORICONDIR* IconDIR;
92 HDC hScreenDc;
93 HANDLE hIcon;
94 ULONG HeaderSize;
95 ULONG ColourCount;
96 PVOID Data;
97 CURSORICONDIRENTRY* dirEntry;
98 ICONIMAGE* SafeIconImage;
99 GRPICONDIR* IconResDir;
100 INT id;
101 ICONIMAGE *ResIcon;
102
103 if (fuLoad & LR_SHARED)
104 DbgPrint("FIXME: need LR_SHARED support Loading icon images\n");
105
106 if (!(fuLoad & LR_LOADFROMFILE))
107 {
108 if (hinst == NULL)
109 {
110 hinst = GetModuleHandleW(L"USER32");
111 }
112 hResource = FindResourceW(hinst, lpszName, RT_GROUP_ICON);
113 if (hResource == NULL)
114 {
115 return(NULL);
116 }
117
118 hResource = LoadResource(hinst, hResource);
119 if (hResource == NULL)
120 {
121 return(NULL);
122 }
123 IconResDir = LockResource(hResource);
124 if (IconResDir == NULL)
125 {
126 return(NULL);
127 }
128
129 //find the best fitting in the IconResDir for this resolution
130 id = LookupIconIdFromDirectoryEx((PBYTE) IconResDir, TRUE,
131 width, height, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
132
133 h2Resource = FindResourceW(hinst,
134 MAKEINTRESOURCEW(id),
135 MAKEINTRESOURCEW(RT_ICON));
136
137 hResource = LoadResource(hinst, h2Resource);
138 if (hResource == NULL)
139 {
140 return(NULL);
141 }
142
143 ResIcon = LockResource(hResource);
144 if (ResIcon == NULL)
145 {
146 return(NULL);
147 }
148 return CreateIconFromResourceEx((PBYTE) ResIcon,
149 SizeofResource(hinst, h2Resource), TRUE, 0x00030000,
150 width, height, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
151 }
152 else
153 {
154 hFile = CreateFileW(lpszName,
155 GENERIC_READ,
156 FILE_SHARE_READ,
157 NULL,
158 OPEN_EXISTING,
159 0,
160 NULL);
161 if (hFile == NULL)
162 {
163 return(NULL);
164 }
165
166 hSection = CreateFileMappingW(hFile,
167 NULL,
168 PAGE_READONLY,
169 0,
170 0,
171 NULL);
172
173 CloseHandle(hFile);
174 if (hSection == NULL)
175 {
176 return(NULL);
177 }
178 IconDIR = MapViewOfFile(hSection,
179 FILE_MAP_READ,
180 0,
181 0,
182 0);
183
184 CloseHandle(hSection);
185 if (IconDIR == NULL)
186 {
187 return(NULL);
188 }
189
190 //pick the best size.
191 dirEntry = (CURSORICONDIRENTRY *) CURSORICON_FindBestIcon( IconDIR, width, height, 1);
192
193
194 if (!dirEntry)
195 {
196 if (fuLoad & LR_LOADFROMFILE)
197 {
198 UnmapViewOfFile(IconDIR);
199 }
200 return(NULL);
201 }
202
203 SafeIconImage = RtlAllocateHeap(RtlGetProcessHeap(), 0, dirEntry->dwBytesInRes);
204
205 memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwImageOffset, dirEntry->dwBytesInRes);
206 }
207
208 //at this point we have a copy of the icon image to play with
209
210 SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2;
211
212 if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER))
213 {
214 BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage;
215 ColourCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
216 HeaderSize = sizeof(BITMAPCOREHEADER) + ColourCount * sizeof(RGBTRIPLE);
217 }
218 else
219 {
220 ColourCount = SafeIconImage->icHeader.biClrUsed;
221 if (ColourCount == 0 && SafeIconImage->icHeader.biBitCount <= 8)
222 {
223 ColourCount = 1 << SafeIconImage->icHeader.biBitCount;
224 }
225 HeaderSize = sizeof(BITMAPINFOHEADER) + ColourCount * sizeof(RGBQUAD);
226 }
227
228 //make data point to the start of the XOR image data
229 Data = (PBYTE)SafeIconImage + HeaderSize;
230
231
232 //get a handle to the screen dc, the icon we create is going to be compatable with this
233 hScreenDc = CreateDCW(L"DISPLAY", NULL, NULL, NULL);
234 if (hScreenDc == NULL)
235 {
236 if (fuLoad & LR_LOADFROMFILE)
237 {
238 RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);
239 UnmapViewOfFile(IconDIR);
240 }
241 return(NULL);
242 }
243
244 hIcon = ICON_CreateIconFromData(hScreenDc, Data, SafeIconImage, width, height);
245 RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);
246 return hIcon;
247 }
248
249
250 HANDLE STATIC
251 LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)
252 {
253 HANDLE hResource;
254 HANDLE hFile;
255 HANDLE hSection;
256 BITMAPINFO* BitmapInfo;
257 BITMAPINFO* PrivateInfo;
258 HDC hScreenDc;
259 HANDLE hBitmap;
260 ULONG HeaderSize;
261 ULONG ColourCount;
262 PVOID Data;
263
264 if (!(fuLoad & LR_LOADFROMFILE))
265 {
266 if (hInstance == NULL)
267 {
268 hInstance = GetModuleHandleW(L"USER32");
269 }
270 hResource = FindResourceW(hInstance, lpszName, RT_BITMAP);
271 if (hResource == NULL)
272 {
273 return(NULL);
274 }
275 hResource = LoadResource(hInstance, hResource);
276 if (hResource == NULL)
277 {
278 return(NULL);
279 }
280 BitmapInfo = LockResource(hResource);
281 if (BitmapInfo == NULL)
282 {
283 return(NULL);
284 }
285 }
286 else
287 {
288 hFile = CreateFileW(lpszName,
289 GENERIC_READ,
290 FILE_SHARE_READ,
291 NULL,
292 OPEN_EXISTING,
293 0,
294 NULL);
295 if (hFile == NULL)
296 {
297 return(NULL);
298 }
299 hSection = CreateFileMappingW(hFile,
300 NULL,
301 PAGE_READONLY,
302 0,
303 0,
304 NULL);
305 CloseHandle(hFile);
306 if (hSection == NULL)
307 {
308 return(NULL);
309 }
310 BitmapInfo = MapViewOfFile(hSection,
311 FILE_MAP_READ,
312 0,
313 0,
314 0);
315 CloseHandle(hSection);
316 if (BitmapInfo == NULL)
317 {
318 return(NULL);
319 }
320 /* offset BitmapInfo by 14 bytes to acount for the size of BITMAPFILEHEADER
321 unfortunatly sizeof(BITMAPFILEHEADER) = 16, but the acutal size should be 14!
322 */
323 BitmapInfo = (BITMAPINFO*)(((PBYTE)BitmapInfo) + 14);
324 }
325
326 if (BitmapInfo->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
327 {
328 BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)BitmapInfo;
329 ColourCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
330 HeaderSize = sizeof(BITMAPCOREHEADER) + ColourCount * sizeof(RGBTRIPLE);
331 }
332 else
333 {
334 ColourCount = BitmapInfo->bmiHeader.biClrUsed;
335 if (ColourCount == 0 && BitmapInfo->bmiHeader.biBitCount <= 8)
336 {
337 ColourCount = 1 << BitmapInfo->bmiHeader.biBitCount;
338 }
339 HeaderSize = sizeof(BITMAPINFOHEADER) + ColourCount * sizeof(RGBQUAD);
340 }
341 Data = (PVOID)BitmapInfo + HeaderSize;
342
343 PrivateInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, HeaderSize);
344 if (PrivateInfo == NULL)
345 {
346 if (fuLoad & LR_LOADFROMFILE)
347 {
348 UnmapViewOfFile(BitmapInfo);
349 }
350 return(NULL);
351 }
352 memcpy(PrivateInfo, BitmapInfo, HeaderSize);
353
354 /* FIXME: Handle colour conversion and transparency. */
355
356 hScreenDc = CreateDCW(L"DISPLAY", NULL, NULL, NULL);
357 if (hScreenDc == NULL)
358 {
359 if (fuLoad & LR_LOADFROMFILE)
360 {
361 UnmapViewOfFile(BitmapInfo);
362 }
363 return(NULL);
364 }
365
366 if (fuLoad & LR_CREATEDIBSECTION)
367 {
368 DIBSECTION Dib;
369
370 hBitmap = CreateDIBSection(hScreenDc, PrivateInfo, DIB_RGB_COLORS, NULL,
371 0, 0);
372 GetObjectA(hBitmap, sizeof(DIBSECTION), &Dib);
373 SetDIBits(hScreenDc, hBitmap, 0, Dib.dsBm.bmHeight, Data, BitmapInfo,
374 DIB_RGB_COLORS);
375 }
376 else
377 {
378 hBitmap = CreateDIBitmap(hScreenDc, &PrivateInfo->bmiHeader, CBM_INIT,
379 Data, PrivateInfo, DIB_RGB_COLORS);
380 }
381
382 RtlFreeHeap(RtlGetProcessHeap(), 0, PrivateInfo);
383 /*DeleteDC(hScreenDc);*/
384 if (fuLoad & LR_LOADFROMFILE)
385 {
386 UnmapViewOfFile(BitmapInfo);
387 }
388 return(hBitmap);
389 }
390
391 HANDLE STDCALL
392 LoadImageW(HINSTANCE hinst,
393 LPCWSTR lpszName,
394 UINT uType,
395 int cxDesired,
396 int cyDesired,
397 UINT fuLoad)
398 {
399 if (fuLoad & LR_DEFAULTSIZE)
400 {
401 if (uType == IMAGE_ICON)
402 {
403 if (cxDesired == 0)
404 {
405 cxDesired = GetSystemMetrics(SM_CXICON);
406 }
407 if (cyDesired == 0)
408 {
409 cyDesired = GetSystemMetrics(SM_CYICON);
410 }
411 }
412 else if (uType == IMAGE_CURSOR)
413 {
414 if (cxDesired == 0)
415 {
416 cxDesired = GetSystemMetrics(SM_CXCURSOR);
417 }
418 if (cyDesired == 0)
419 {
420 cyDesired = GetSystemMetrics(SM_CYCURSOR);
421 }
422 }
423 }
424
425 switch (uType)
426 {
427 case IMAGE_BITMAP:
428 {
429 return(LoadBitmapImage(hinst, lpszName, fuLoad));
430 }
431 case IMAGE_CURSOR:
432 {
433 return(LoadCursorImage(hinst, lpszName, fuLoad));
434 }
435 case IMAGE_ICON:
436 {
437 return(LoadIconImage(hinst, lpszName, cxDesired, cyDesired, fuLoad));
438 }
439 default:
440 DbgBreakPoint();
441 break;
442 }
443 return(NULL);
444 }
445
446
447 /*
448 * @implemented
449 */
450 HBITMAP STDCALL
451 LoadBitmapA(HINSTANCE hInstance, LPCSTR lpBitmapName)
452 {
453 return(LoadImageA(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 0));
454 }
455
456
457 /*
458 * @implemented
459 */
460 HBITMAP STDCALL
461 LoadBitmapW(HINSTANCE hInstance, LPCWSTR lpBitmapName)
462 {
463 return(LoadImageW(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 0));
464 }