Commit | Line | Data |
---|---|---|
5819953c AJ |
1 | /* |
2 | * Metafile functions | |
3 | * | |
4 | * Copyright David W. Metcalfe, 1994 | |
396ee740 DP |
5 | * Copyright Niels de Carpentier, 1996 |
6 | * Copyright Albrecht Kleine, 1996 | |
7 | * Copyright Huw Davies, 1996 | |
234bc24d | 8 | * |
0799c1a7 AJ |
9 | * This library is free software; you can redistribute it and/or |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
360a3f91 | 21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
396ee740 DP |
22 | * |
23 | * NOTES | |
24 | * | |
b94e4330 HD |
25 | * These functions are primarily involved with metafile playback or anything |
26 | * that touches a HMETAFILE. | |
27 | * For recording of metafiles look in graphics/metafiledrv/ | |
28 | * | |
9a624916 | 29 | * Note that (32 bit) HMETAFILEs are GDI objects, while HMETAFILE16s are |
b94e4330 HD |
30 | * global memory handles so these cannot be interchanged. |
31 | * | |
32 | * Memory-based metafiles are just stored as a continuous block of memory with | |
33 | * a METAHEADER at the head with METARECORDs appended to it. mtType is | |
34 | * METAFILE_MEMORY (1). Note this is indentical to the disk image of a | |
35 | * disk-based metafile - even mtType is METAFILE_MEMORY. | |
36 | * 16bit HMETAFILE16s are global handles to this block | |
37 | * 32bit HMETAFILEs are GDI handles METAFILEOBJs, which contains a ptr to | |
38 | * the memory. | |
39 | * Disk-based metafiles are rather different. HMETAFILE16s point to a | |
40 | * METAHEADER which has mtType equal to METAFILE_DISK (2). Following the 9 | |
41 | * WORDs of the METAHEADER there are a further 3 WORDs of 0, 1 of 0x117, 1 | |
42 | * more 0, then 2 which may be a time stamp of the file and then the path of | |
43 | * the file (METAHEADERDISK). I've copied this for 16bit compatibility. | |
44 | * | |
45 | * HDMD - 14/4/1999 | |
9a624916 | 46 | */ |
b94e4330 | 47 | |
33929be4 | 48 | #include "config.h" |
b94e4330 | 49 | |
aca05783 | 50 | #include <string.h> |
ade697e8 | 51 | #include <fcntl.h> |
33929be4 | 52 | |
05df86a3 | 53 | #include "gdi.h" |
506ab8bc VB |
54 | #include "winreg.h" |
55 | #include "winternl.h" | |
6ec42c0c | 56 | #include "gdi_private.h" |
0799c1a7 | 57 | #include "wine/debug.h" |
5819953c | 58 | |
0799c1a7 | 59 | WINE_DEFAULT_DEBUG_CHANNEL(metafile); |
b4b9fae6 | 60 | |
f899ef07 AJ |
61 | #include "pshpack1.h" |
62 | typedef struct | |
63 | { | |
64 | DWORD dw1, dw2, dw3; | |
65 | WORD w4; | |
66 | CHAR filename[0x100]; | |
67 | } METAHEADERDISK; | |
68 | #include "poppack.h" | |
69 | ||
78b041cf AJ |
70 | typedef struct |
71 | { | |
72 | GDIOBJHDR header; | |
73 | METAHEADER *mh; | |
74 | } METAFILEOBJ; | |
75 | ||
ed29c905 | 76 | |
bf9130af AJ |
77 | /****************************************************************** |
78 | * MF_AddHandle | |
79 | * | |
80 | * Add a handle to an external handle table and return the index | |
81 | */ | |
15b9ed9f | 82 | static int MF_AddHandle(HANDLETABLE *ht, UINT htlen, HGDIOBJ hobj) |
bf9130af AJ |
83 | { |
84 | int i; | |
85 | ||
86 | for (i = 0; i < htlen; i++) | |
87 | { | |
88 | if (*(ht->objectHandle + i) == 0) | |
89 | { | |
90 | *(ht->objectHandle + i) = hobj; | |
91 | return i; | |
92 | } | |
93 | } | |
94 | return -1; | |
95 | } | |
96 | ||
97 | ||
98 | /****************************************************************** | |
b94e4330 HD |
99 | * MF_Create_HMETATFILE |
100 | * | |
101 | * Creates a (32 bit) HMETAFILE object from a METAHEADER | |
102 | * | |
103 | * HMETAFILEs are GDI objects. | |
104 | */ | |
105 | HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh) | |
106 | { | |
2a2321bb | 107 | HMETAFILE hmf = 0; |
28a632a8 MS |
108 | METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC, |
109 | (HGDIOBJ *)&hmf, NULL ); | |
2a2321bb AJ |
110 | if (metaObj) |
111 | { | |
396ee740 | 112 | metaObj->mh = mh; |
2a2321bb AJ |
113 | GDI_ReleaseObj( hmf ); |
114 | } | |
b94e4330 HD |
115 | return hmf; |
116 | } | |
117 | ||
b94e4330 HD |
118 | /****************************************************************** |
119 | * MF_GetMetaHeader | |
120 | * | |
121 | * Returns ptr to METAHEADER associated with HMETAFILE | |
b94e4330 HD |
122 | */ |
123 | static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf ) | |
124 | { | |
8af0eda7 | 125 | METAHEADER *ret = NULL; |
a904e16f | 126 | METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC ); |
8af0eda7 AJ |
127 | if (metaObj) |
128 | { | |
129 | ret = metaObj->mh; | |
130 | GDI_ReleaseObj( hmf ); | |
131 | } | |
132 | return ret; | |
b94e4330 HD |
133 | } |
134 | ||
15b9ed9f AJ |
135 | /****************************************************************** |
136 | * convert_points | |
137 | * | |
138 | * Convert an array of POINT16 to an array of POINT. | |
139 | * Result must be freed by caller. | |
140 | */ | |
141 | static POINT *convert_points( UINT count, POINT16 *pt16 ) | |
142 | { | |
143 | UINT i; | |
144 | POINT *ret = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*ret) ); | |
145 | if (ret) | |
146 | { | |
147 | for (i = 0; i < count; i++) | |
148 | { | |
149 | ret[i].x = pt16[i].x; | |
150 | ret[i].y = pt16[i].y; | |
151 | } | |
152 | } | |
153 | return ret; | |
154 | } | |
155 | ||
b94e4330 | 156 | /****************************************************************** |
d0a41774 | 157 | * DeleteMetaFile (GDI32.@) |
b94e4330 HD |
158 | * |
159 | * Delete a memory-based metafile. | |
160 | */ | |
161 | ||
162 | BOOL WINAPI DeleteMetaFile( HMETAFILE hmf ) | |
163 | { | |
2a2321bb AJ |
164 | METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC ); |
165 | if (!metaObj) return FALSE; | |
166 | HeapFree( GetProcessHeap(), 0, metaObj->mh ); | |
167 | GDI_FreeObject( hmf, metaObj ); | |
b94e4330 HD |
168 | return TRUE; |
169 | } | |
170 | ||
171 | /****************************************************************** | |
172 | * MF_ReadMetaFile | |
173 | * | |
174 | * Returns a pointer to a memory based METAHEADER read in from file HFILE | |
175 | * | |
176 | */ | |
f824852b | 177 | METAHEADER *MF_ReadMetaFile(HANDLE hfile) |
b94e4330 HD |
178 | { |
179 | METAHEADER *mh; | |
180 | DWORD BytesRead, size; | |
181 | ||
182 | size = sizeof(METAHEADER); | |
90476d6b | 183 | mh = HeapAlloc( GetProcessHeap(), 0, size ); |
b94e4330 HD |
184 | if(!mh) return NULL; |
185 | if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 || | |
186 | BytesRead != size) { | |
90476d6b | 187 | HeapFree( GetProcessHeap(), 0, mh ); |
b94e4330 HD |
188 | return NULL; |
189 | } | |
5f2bf16d DT |
190 | if (mh->mtType != METAFILE_MEMORY || mh->mtVersion != MFVERSION || |
191 | mh->mtHeaderSize != size / 2) | |
192 | { | |
82977c14 HD |
193 | HeapFree( GetProcessHeap(), 0, mh ); |
194 | return NULL; | |
195 | } | |
b94e4330 | 196 | size = mh->mtSize * 2; |
90476d6b | 197 | mh = HeapReAlloc( GetProcessHeap(), 0, mh, size ); |
b94e4330 HD |
198 | if(!mh) return NULL; |
199 | size -= sizeof(METAHEADER); | |
200 | if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead, | |
201 | NULL) == 0 || | |
202 | BytesRead != size) { | |
90476d6b | 203 | HeapFree( GetProcessHeap(), 0, mh ); |
b94e4330 HD |
204 | return NULL; |
205 | } | |
206 | ||
207 | if (mh->mtType != METAFILE_MEMORY) { | |
15657090 | 208 | WARN("Disk metafile had mtType = %04x\n", mh->mtType); |
b94e4330 HD |
209 | mh->mtType = METAFILE_MEMORY; |
210 | } | |
211 | return mh; | |
212 | } | |
213 | ||
f0cbfa0c | 214 | /****************************************************************** |
d0a41774 | 215 | * GetMetaFileA (GDI32.@) |
60ce85c9 | 216 | * |
b94e4330 | 217 | * Read a metafile from a file. Returns handle to a memory-based metafile. |
f0cbfa0c | 218 | */ |
b94e4330 | 219 | HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename ) |
234bc24d | 220 | { |
b94e4330 | 221 | METAHEADER *mh; |
da2b6a9f | 222 | HANDLE hFile; |
9a624916 | 223 | |
15657090 | 224 | TRACE("%s\n", lpFilename); |
b94e4330 HD |
225 | |
226 | if(!lpFilename) | |
227 | return 0; | |
902da699 | 228 | |
e987634c | 229 | if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL, |
da2b6a9f | 230 | OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) |
b94e4330 HD |
231 | return 0; |
232 | ||
233 | mh = MF_ReadMetaFile(hFile); | |
234 | CloseHandle(hFile); | |
235 | if(!mh) return 0; | |
236 | return MF_Create_HMETAFILE( mh ); | |
234bc24d AJ |
237 | } |
238 | ||
cdcdede2 | 239 | /****************************************************************** |
d0a41774 | 240 | * GetMetaFileW (GDI32.@) |
f0cbfa0c | 241 | */ |
a3960292 | 242 | HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename ) |
f0cbfa0c | 243 | { |
b94e4330 | 244 | METAHEADER *mh; |
da2b6a9f | 245 | HANDLE hFile; |
9a624916 | 246 | |
15657090 | 247 | TRACE("%s\n", debugstr_w(lpFilename)); |
b94e4330 HD |
248 | |
249 | if(!lpFilename) | |
250 | return 0; | |
251 | ||
e987634c | 252 | if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL, |
da2b6a9f | 253 | OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) |
b94e4330 HD |
254 | return 0; |
255 | ||
256 | mh = MF_ReadMetaFile(hFile); | |
257 | CloseHandle(hFile); | |
258 | if(!mh) return 0; | |
259 | return MF_Create_HMETAFILE( mh ); | |
f0cbfa0c AJ |
260 | } |
261 | ||
262 | ||
263 | /****************************************************************** | |
b94e4330 HD |
264 | * MF_LoadDiskBasedMetaFile |
265 | * | |
266 | * Creates a new memory-based metafile from a disk-based one. | |
cdcdede2 | 267 | */ |
f824852b | 268 | METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh) |
b94e4330 HD |
269 | { |
270 | METAHEADERDISK *mhd; | |
da2b6a9f | 271 | HANDLE hfile; |
b94e4330 | 272 | METAHEADER *mh2; |
cdcdede2 | 273 | |
b94e4330 | 274 | if(mh->mtType != METAFILE_DISK) { |
15657090 | 275 | ERR("Not a disk based metafile\n"); |
b94e4330 HD |
276 | return NULL; |
277 | } | |
278 | mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER)); | |
279 | ||
e987634c | 280 | if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL, |
da2b6a9f | 281 | OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) { |
15657090 | 282 | WARN("Can't open file of disk based metafile\n"); |
b94e4330 HD |
283 | return NULL; |
284 | } | |
285 | mh2 = MF_ReadMetaFile(hfile); | |
286 | CloseHandle(hfile); | |
287 | return mh2; | |
288 | } | |
289 | ||
290 | /****************************************************************** | |
291 | * MF_CreateMetaHeaderDisk | |
292 | * | |
293 | * Take a memory based METAHEADER and change it to a disk based METAHEADER | |
9a624916 | 294 | * assosiated with filename. Note: Trashes contents of old one. |
b94e4330 | 295 | */ |
4eaf41b5 | 296 | METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCVOID filename, BOOL uni ) |
f0cbfa0c | 297 | { |
b94e4330 | 298 | METAHEADERDISK *mhd; |
b94e4330 | 299 | |
90476d6b | 300 | mh = HeapReAlloc( GetProcessHeap(), 0, mh, |
b94e4330 HD |
301 | sizeof(METAHEADER) + sizeof(METAHEADERDISK)); |
302 | mh->mtType = METAFILE_DISK; | |
b94e4330 | 303 | mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER)); |
4eaf41b5 MM |
304 | |
305 | if( uni ) | |
306 | WideCharToMultiByte(CP_ACP, 0, filename, -1, | |
307 | mhd->filename, sizeof mhd->filename, NULL, NULL); | |
308 | else | |
309 | lstrcpynA( mhd->filename, filename, sizeof mhd->filename ); | |
b94e4330 HD |
310 | return mh; |
311 | } | |
312 | ||
f0cbfa0c | 313 | /****************************************************************** |
506ab8bc | 314 | * CopyMetaFileW (GDI32.@) |
60ce85c9 AJ |
315 | * |
316 | * Copies the metafile corresponding to hSrcMetaFile to either | |
317 | * a disk file, if a filename is given, or to a new memory based | |
318 | * metafile, if lpFileName is NULL. | |
319 | * | |
396ee740 DP |
320 | * PARAMS |
321 | * hSrcMetaFile [I] handle of metafile to copy | |
322 | * lpFilename [I] filename if copying to a file | |
60ce85c9 | 323 | * |
396ee740 | 324 | * RETURNS |
60ce85c9 AJ |
325 | * Handle to metafile copy on success, NULL on failure. |
326 | * | |
327 | * BUGS | |
60ce85c9 | 328 | * Copying to disk returns NULL even if successful. |
f0cbfa0c | 329 | */ |
396ee740 | 330 | HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile, LPCWSTR lpFilename ) |
783a3954 | 331 | { |
b94e4330 HD |
332 | METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile ); |
333 | METAHEADER *mh2 = NULL; | |
da2b6a9f | 334 | HANDLE hFile; |
b94e4330 | 335 | |
506ab8bc | 336 | TRACE("(%p,%s)\n", hSrcMetaFile, debugstr_w(lpFilename)); |
9a624916 | 337 | |
b94e4330 | 338 | if(!mh) return 0; |
9a624916 | 339 | |
b94e4330 HD |
340 | if(mh->mtType == METAFILE_DISK) |
341 | mh2 = MF_LoadDiskBasedMetaFile(mh); | |
342 | else { | |
90476d6b | 343 | mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 ); |
b94e4330 HD |
344 | memcpy( mh2, mh, mh->mtSize * 2 ); |
345 | } | |
b94e4330 HD |
346 | |
347 | if(lpFilename) { /* disk based metafile */ | |
bcfa5b09 | 348 | DWORD w; |
506ab8bc | 349 | if((hFile = CreateFileW(lpFilename, GENERIC_WRITE, 0, NULL, |
da2b6a9f | 350 | CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) { |
90476d6b | 351 | HeapFree( GetProcessHeap(), 0, mh2 ); |
cdcdede2 | 352 | return 0; |
b94e4330 | 353 | } |
bcfa5b09 | 354 | WriteFile(hFile, mh2, mh2->mtSize * 2, &w, NULL); |
b94e4330 | 355 | CloseHandle(hFile); |
b94e4330 | 356 | } |
46ea8b3f | 357 | |
b94e4330 | 358 | return MF_Create_HMETAFILE( mh2 ); |
cdcdede2 AJ |
359 | } |
360 | ||
f0cbfa0c AJ |
361 | |
362 | /****************************************************************** | |
506ab8bc | 363 | * CopyMetaFileA (GDI32.@) |
79e3a1be MA |
364 | * |
365 | * See CopyMetaFileW. | |
f0cbfa0c | 366 | */ |
396ee740 | 367 | HMETAFILE WINAPI CopyMetaFileA( HMETAFILE hSrcMetaFile, LPCSTR lpFilename ) |
f0cbfa0c | 368 | { |
506ab8bc | 369 | UNICODE_STRING lpFilenameW; |
193cf50a | 370 | HMETAFILE ret = 0; |
193cf50a | 371 | |
506ab8bc VB |
372 | if (lpFilename) RtlCreateUnicodeStringFromAsciiz(&lpFilenameW, lpFilename); |
373 | else lpFilenameW.Buffer = NULL; | |
374 | ||
766315e1 HD |
375 | ret = CopyMetaFileW( hSrcMetaFile, lpFilenameW.Buffer ); |
376 | if (lpFilenameW.Buffer) | |
377 | RtlFreeUnicodeString(&lpFilenameW); | |
f0cbfa0c AJ |
378 | return ret; |
379 | } | |
380 | ||
b94e4330 HD |
381 | /******************************************************************* |
382 | * MF_PlayMetaFile | |
60ce85c9 | 383 | * |
b94e4330 | 384 | * Helper for PlayMetaFile |
5819953c | 385 | */ |
f824852b | 386 | BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh) |
5819953c | 387 | { |
5819953c | 388 | |
36ca1368 | 389 | METARECORD *mr; |
15b9ed9f | 390 | HANDLETABLE *ht; |
4d75640d | 391 | unsigned int offset = 0; |
2ace16ac | 392 | WORD i; |
a3960292 AJ |
393 | HPEN hPen; |
394 | HBRUSH hBrush; | |
395 | HFONT hFont; | |
b94e4330 HD |
396 | BOOL loaded = FALSE; |
397 | ||
491502b9 | 398 | if (!mh) return FALSE; |
2a2321bb | 399 | if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */ |
b94e4330 HD |
400 | mh = MF_LoadDiskBasedMetaFile(mh); |
401 | if(!mh) return FALSE; | |
402 | loaded = TRUE; | |
403 | } | |
46ea8b3f AJ |
404 | |
405 | /* save the current pen, brush and font */ | |
7c57a72c HD |
406 | hPen = GetCurrentObject(hdc, OBJ_PEN); |
407 | hBrush = GetCurrentObject(hdc, OBJ_BRUSH); | |
408 | hFont = GetCurrentObject(hdc, OBJ_FONT); | |
409 | ||
36ca1368 | 410 | /* create the handle table */ |
90476d6b | 411 | ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, |
15b9ed9f | 412 | sizeof(HANDLETABLE) * mh->mtNoObjects); |
b94e4330 | 413 | if(!ht) return FALSE; |
9a624916 | 414 | |
36ca1368 | 415 | /* loop through metafile playing records */ |
cdcdede2 AJ |
416 | offset = mh->mtHeaderSize * 2; |
417 | while (offset < mh->mtSize * 2) | |
36ca1368 | 418 | { |
0623a6f3 | 419 | mr = (METARECORD *)((char *)mh + offset); |
15657090 | 420 | TRACE("offset=%04x,size=%08lx\n", |
46ea8b3f | 421 | offset, mr->rdSize); |
d6d64196 MM |
422 | if (mr->rdSize < 3) { /* catch illegal record sizes */ |
423 | TRACE("Entry got size %ld at offset %d, total mf length is %ld\n", | |
424 | mr->rdSize,offset,mh->mtSize*2); | |
425 | break; | |
44ed71f5 | 426 | } |
cdcdede2 | 427 | offset += mr->rdSize * 2; |
15b9ed9f | 428 | PlayMetaFileRecord( hdc, ht, mr, mh->mtNoObjects ); |
36ca1368 AJ |
429 | } |
430 | ||
a3960292 AJ |
431 | SelectObject(hdc, hBrush); |
432 | SelectObject(hdc, hPen); | |
433 | SelectObject(hdc, hFont); | |
349a9531 | 434 | |
2ace16ac AJ |
435 | /* free objects in handle table */ |
436 | for(i = 0; i < mh->mtNoObjects; i++) | |
437 | if(*(ht->objectHandle + i) != 0) | |
a3960292 | 438 | DeleteObject(*(ht->objectHandle + i)); |
9a624916 | 439 | |
cdcdede2 | 440 | /* free handle table */ |
90476d6b | 441 | HeapFree( GetProcessHeap(), 0, ht ); |
b94e4330 | 442 | if(loaded) |
90476d6b | 443 | HeapFree( GetProcessHeap(), 0, mh ); |
cdcdede2 AJ |
444 | return TRUE; |
445 | } | |
446 | ||
b94e4330 | 447 | /****************************************************************** |
d0a41774 | 448 | * PlayMetaFile (GDI32.@) |
60ce85c9 | 449 | * |
b94e4330 HD |
450 | * Renders the metafile specified by hmf in the DC specified by |
451 | * hdc. Returns FALSE on failure, TRUE on success. | |
396ee740 DP |
452 | * |
453 | * PARAMS | |
454 | * hdc [I] handle of DC to render in | |
455 | * hmf [I] handle of metafile to render | |
79e3a1be MA |
456 | * |
457 | * RETURNS | |
458 | * Success: TRUE | |
459 | * Failure: FALSE | |
cdcdede2 | 460 | */ |
396ee740 | 461 | BOOL WINAPI PlayMetaFile( HDC hdc, HMETAFILE hmf ) |
cdcdede2 | 462 | { |
b94e4330 | 463 | METAHEADER *mh = MF_GetMetaHeader( hmf ); |
8af0eda7 | 464 | return MF_PlayMetaFile( hdc, mh ); |
b94e4330 HD |
465 | } |
466 | ||
b94e4330 | 467 | /****************************************************************** |
d0a41774 | 468 | * EnumMetaFile (GDI32.@) |
b94e4330 HD |
469 | * |
470 | * Loop through the metafile records in hmf, calling the user-specified | |
471 | * function for each one, stopping when the user's function returns FALSE | |
472 | * (which is considered to be failure) | |
9a624916 | 473 | * or when no records are left (which is considered to be success). |
b94e4330 HD |
474 | * |
475 | * RETURNS | |
476 | * TRUE on success, FALSE on failure. | |
b94e4330 | 477 | */ |
396ee740 | 478 | BOOL WINAPI EnumMetaFile(HDC hdc, HMETAFILE hmf, MFENUMPROC lpEnumFunc, LPARAM lpData) |
783a3954 | 479 | { |
ab86a9e5 | 480 | METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf); |
46ea8b3f | 481 | METARECORD *mr; |
a3960292 | 482 | HANDLETABLE *ht; |
ab86a9e5 | 483 | BOOL result = TRUE; |
4d75640d JM |
484 | int i; |
485 | unsigned int offset = 0; | |
a3960292 AJ |
486 | HPEN hPen; |
487 | HBRUSH hBrush; | |
488 | HFONT hFont; | |
46ea8b3f | 489 | |
547cdc2b | 490 | TRACE("(%p,%p,%p,%p)\n", hdc, hmf, lpEnumFunc, (void*)lpData); |
46ea8b3f | 491 | if (!mh) return 0; |
8af0eda7 | 492 | if(mh->mtType == METAFILE_DISK) |
ab86a9e5 | 493 | { |
8af0eda7 AJ |
494 | /* Create a memory-based copy */ |
495 | if (!(mhTemp = MF_LoadDiskBasedMetaFile(mh))) return FALSE; | |
ab86a9e5 AJ |
496 | mh = mhTemp; |
497 | } | |
8af0eda7 | 498 | |
46ea8b3f | 499 | /* save the current pen, brush and font */ |
7c57a72c HD |
500 | hPen = GetCurrentObject(hdc, OBJ_PEN); |
501 | hBrush = GetCurrentObject(hdc, OBJ_BRUSH); | |
502 | hFont = GetCurrentObject(hdc, OBJ_FONT); | |
46ea8b3f | 503 | |
9a624916 | 504 | ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, |
a3960292 | 505 | sizeof(HANDLETABLE) * mh->mtNoObjects); |
b94e4330 | 506 | |
46ea8b3f AJ |
507 | /* loop through metafile records */ |
508 | offset = mh->mtHeaderSize * 2; | |
9a624916 | 509 | |
46ea8b3f AJ |
510 | while (offset < (mh->mtSize * 2)) |
511 | { | |
512 | mr = (METARECORD *)((char *)mh + offset); | |
43ff7d2d HD |
513 | if(mr->rdFunction == META_EOF) { |
514 | TRACE("Got META_EOF so stopping\n"); | |
515 | break; | |
516 | } | |
15657090 | 517 | TRACE("Calling EnumFunc with record type %x\n", |
56166a6f | 518 | mr->rdFunction); |
46ea8b3f AJ |
519 | if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData )) |
520 | { | |
521 | result = FALSE; | |
522 | break; | |
523 | } | |
9a624916 | 524 | |
46ea8b3f AJ |
525 | offset += (mr->rdSize * 2); |
526 | } | |
527 | ||
528 | /* restore pen, brush and font */ | |
a3960292 AJ |
529 | SelectObject(hdc, hBrush); |
530 | SelectObject(hdc, hPen); | |
531 | SelectObject(hdc, hFont); | |
46ea8b3f AJ |
532 | |
533 | /* free objects in handle table */ | |
534 | for(i = 0; i < mh->mtNoObjects; i++) | |
535 | if(*(ht->objectHandle + i) != 0) | |
a3960292 | 536 | DeleteObject(*(ht->objectHandle + i)); |
46ea8b3f AJ |
537 | |
538 | /* free handle table */ | |
90476d6b | 539 | HeapFree( GetProcessHeap(), 0, ht); |
ab86a9e5 | 540 | /* free a copy of metafile */ |
5ad7d858 | 541 | HeapFree( GetProcessHeap(), 0, mhTemp ); |
46ea8b3f AJ |
542 | return result; |
543 | } | |
544 | ||
b94e4330 | 545 | static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn ); |
15b9ed9f | 546 | static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr); |
36ca1368 | 547 | /****************************************************************** |
15b9ed9f | 548 | * PlayMetaFileRecord (GDI32.@) |
60ce85c9 AJ |
549 | * |
550 | * Render a single metafile record specified by *mr in the DC hdc, while | |
15b9ed9f | 551 | * using the handle table *ht, of length handles, |
60ce85c9 AJ |
552 | * to store metafile objects. |
553 | * | |
554 | * BUGS | |
555 | * The following metafile records are unimplemented: | |
556 | * | |
7603deae | 557 | * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES, |
60ce85c9 AJ |
558 | * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE, |
559 | * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP. | |
36ca1368 | 560 | */ |
15b9ed9f AJ |
561 | BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *ht, METARECORD *mr, UINT handles ) |
562 | { | |
36ca1368 | 563 | short s1; |
15b9ed9f | 564 | POINT *pt; |
36ca1368 AJ |
565 | BITMAPINFOHEADER *infohdr; |
566 | ||
547cdc2b | 567 | TRACE("(%p %p %p %u) function %04x\n", hdc, ht, mr, handles, mr->rdFunction); |
9a624916 | 568 | |
36ca1368 AJ |
569 | switch (mr->rdFunction) |
570 | { | |
234bc24d | 571 | case META_EOF: |
56166a6f | 572 | break; |
234bc24d AJ |
573 | |
574 | case META_DELETEOBJECT: | |
15b9ed9f AJ |
575 | DeleteObject(*(ht->objectHandle + mr->rdParm[0])); |
576 | *(ht->objectHandle + mr->rdParm[0]) = 0; | |
577 | break; | |
234bc24d | 578 | |
36ca1368 | 579 | case META_SETBKCOLOR: |
15b9ed9f AJ |
580 | SetBkColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1])); |
581 | break; | |
36ca1368 AJ |
582 | |
583 | case META_SETBKMODE: | |
15b9ed9f AJ |
584 | SetBkMode(hdc, mr->rdParm[0]); |
585 | break; | |
36ca1368 AJ |
586 | |
587 | case META_SETMAPMODE: | |
15b9ed9f AJ |
588 | SetMapMode(hdc, mr->rdParm[0]); |
589 | break; | |
36ca1368 AJ |
590 | |
591 | case META_SETROP2: | |
15b9ed9f AJ |
592 | SetROP2(hdc, mr->rdParm[0]); |
593 | break; | |
36ca1368 AJ |
594 | |
595 | case META_SETRELABS: | |
15b9ed9f AJ |
596 | SetRelAbs(hdc, mr->rdParm[0]); |
597 | break; | |
36ca1368 AJ |
598 | |
599 | case META_SETPOLYFILLMODE: | |
15b9ed9f AJ |
600 | SetPolyFillMode(hdc, mr->rdParm[0]); |
601 | break; | |
36ca1368 AJ |
602 | |
603 | case META_SETSTRETCHBLTMODE: | |
15b9ed9f AJ |
604 | SetStretchBltMode(hdc, mr->rdParm[0]); |
605 | break; | |
0623a6f3 | 606 | |
36ca1368 | 607 | case META_SETTEXTCOLOR: |
15b9ed9f AJ |
608 | SetTextColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1])); |
609 | break; | |
36ca1368 AJ |
610 | |
611 | case META_SETWINDOWORG: | |
15b9ed9f AJ |
612 | SetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL); |
613 | break; | |
36ca1368 AJ |
614 | |
615 | case META_SETWINDOWEXT: | |
15b9ed9f AJ |
616 | SetWindowExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL); |
617 | break; | |
36ca1368 AJ |
618 | |
619 | case META_SETVIEWPORTORG: | |
15b9ed9f AJ |
620 | SetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL); |
621 | break; | |
36ca1368 AJ |
622 | |
623 | case META_SETVIEWPORTEXT: | |
15b9ed9f AJ |
624 | SetViewportExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL); |
625 | break; | |
36ca1368 AJ |
626 | |
627 | case META_OFFSETWINDOWORG: | |
15b9ed9f AJ |
628 | OffsetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL); |
629 | break; | |
36ca1368 AJ |
630 | |
631 | case META_SCALEWINDOWEXT: | |
15b9ed9f AJ |
632 | ScaleWindowExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], |
633 | (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL); | |
634 | break; | |
36ca1368 AJ |
635 | |
636 | case META_OFFSETVIEWPORTORG: | |
15b9ed9f AJ |
637 | OffsetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL); |
638 | break; | |
36ca1368 AJ |
639 | |
640 | case META_SCALEVIEWPORTEXT: | |
15b9ed9f AJ |
641 | ScaleViewportExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], |
642 | (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL); | |
643 | break; | |
36ca1368 AJ |
644 | |
645 | case META_LINETO: | |
15b9ed9f AJ |
646 | LineTo(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]); |
647 | break; | |
36ca1368 AJ |
648 | |
649 | case META_MOVETO: | |
15b9ed9f AJ |
650 | MoveToEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL); |
651 | break; | |
36ca1368 AJ |
652 | |
653 | case META_EXCLUDECLIPRECT: | |
15b9ed9f AJ |
654 | ExcludeClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], |
655 | (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] ); | |
656 | break; | |
36ca1368 AJ |
657 | |
658 | case META_INTERSECTCLIPRECT: | |
15b9ed9f AJ |
659 | IntersectClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], |
660 | (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] ); | |
661 | break; | |
36ca1368 AJ |
662 | |
663 | case META_ARC: | |
15b9ed9f AJ |
664 | Arc(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], |
665 | (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], | |
666 | (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], | |
667 | (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]); | |
668 | break; | |
36ca1368 AJ |
669 | |
670 | case META_ELLIPSE: | |
15b9ed9f AJ |
671 | Ellipse(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], |
672 | (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]); | |
673 | break; | |
36ca1368 AJ |
674 | |
675 | case META_FLOODFILL: | |
15b9ed9f AJ |
676 | FloodFill(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], |
677 | MAKELONG(mr->rdParm[0], mr->rdParm[1])); | |
678 | break; | |
36ca1368 AJ |
679 | |
680 | case META_PIE: | |
15b9ed9f AJ |
681 | Pie(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], |
682 | (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], | |
683 | (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], | |
684 | (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]); | |
685 | break; | |
36ca1368 AJ |
686 | |
687 | case META_RECTANGLE: | |
15b9ed9f AJ |
688 | Rectangle(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], |
689 | (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]); | |
690 | break; | |
36ca1368 AJ |
691 | |
692 | case META_ROUNDRECT: | |
15b9ed9f AJ |
693 | RoundRect(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], |
694 | (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], | |
695 | (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]); | |
696 | break; | |
36ca1368 AJ |
697 | |
698 | case META_PATBLT: | |
15b9ed9f AJ |
699 | PatBlt(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], |
700 | (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], | |
701 | MAKELONG(mr->rdParm[0], mr->rdParm[1])); | |
702 | break; | |
36ca1368 AJ |
703 | |
704 | case META_SAVEDC: | |
15b9ed9f AJ |
705 | SaveDC(hdc); |
706 | break; | |
36ca1368 AJ |
707 | |
708 | case META_SETPIXEL: | |
15b9ed9f AJ |
709 | SetPixel(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], |
710 | MAKELONG(mr->rdParm[0], mr->rdParm[1])); | |
711 | break; | |
36ca1368 AJ |
712 | |
713 | case META_OFFSETCLIPRGN: | |
15b9ed9f AJ |
714 | OffsetClipRgn( hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] ); |
715 | break; | |
36ca1368 AJ |
716 | |
717 | case META_TEXTOUT: | |
15b9ed9f AJ |
718 | s1 = mr->rdParm[0]; |
719 | TextOutA(hdc, (SHORT)mr->rdParm[((s1 + 1) >> 1) + 2], | |
720 | (SHORT)mr->rdParm[((s1 + 1) >> 1) + 1], | |
721 | (char *)(mr->rdParm + 1), s1); | |
722 | break; | |
36ca1368 AJ |
723 | |
724 | case META_POLYGON: | |
15b9ed9f AJ |
725 | if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1)))) |
726 | { | |
727 | Polygon(hdc, pt, mr->rdParm[0]); | |
728 | HeapFree( GetProcessHeap(), 0, pt ); | |
729 | } | |
730 | break; | |
36ca1368 | 731 | |
234bc24d | 732 | case META_POLYPOLYGON: |
15b9ed9f AJ |
733 | { |
734 | UINT i, total; | |
735 | SHORT *counts = (SHORT *)(mr->rdParm + 1); | |
736 | ||
737 | for (i = total = 0; i < mr->rdParm[0]; i++) total += counts[i]; | |
738 | pt = convert_points( total, (LPPOINT16)(counts + mr->rdParm[0]) ); | |
739 | if (pt) | |
740 | { | |
741 | INT *cnt32 = HeapAlloc( GetProcessHeap(), 0, mr->rdParm[0] * sizeof(*cnt32) ); | |
742 | if (cnt32) | |
743 | { | |
744 | for (i = 0; i < mr->rdParm[0]; i++) cnt32[i] = counts[i]; | |
745 | PolyPolygon( hdc, pt, cnt32, mr->rdParm[0]); | |
746 | HeapFree( GetProcessHeap(), 0, cnt32 ); | |
747 | } | |
748 | } | |
749 | HeapFree( GetProcessHeap(), 0, pt ); | |
750 | } | |
751 | break; | |
234bc24d | 752 | |
36ca1368 | 753 | case META_POLYLINE: |
15b9ed9f AJ |
754 | if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1)))) |
755 | { | |
756 | Polyline( hdc, pt, mr->rdParm[0] ); | |
757 | HeapFree( GetProcessHeap(), 0, pt ); | |
758 | } | |
759 | break; | |
36ca1368 AJ |
760 | |
761 | case META_RESTOREDC: | |
15b9ed9f AJ |
762 | RestoreDC(hdc, (SHORT)mr->rdParm[0]); |
763 | break; | |
36ca1368 AJ |
764 | |
765 | case META_SELECTOBJECT: | |
15b9ed9f AJ |
766 | SelectObject(hdc, *(ht->objectHandle + mr->rdParm[0])); |
767 | break; | |
36ca1368 AJ |
768 | |
769 | case META_CHORD: | |
15b9ed9f AJ |
770 | Chord(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], |
771 | (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], | |
772 | (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], | |
773 | (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]); | |
774 | break; | |
36ca1368 AJ |
775 | |
776 | case META_CREATEPATTERNBRUSH: | |
15b9ed9f AJ |
777 | switch (mr->rdParm[0]) |
778 | { | |
779 | case BS_PATTERN: | |
780 | infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2); | |
781 | MF_AddHandle(ht, handles, | |
782 | CreatePatternBrush(CreateBitmap(infohdr->biWidth, | |
783 | infohdr->biHeight, | |
784 | infohdr->biPlanes, | |
785 | infohdr->biBitCount, | |
786 | (LPSTR)(mr->rdParm + | |
787 | (sizeof(BITMAPINFOHEADER) / 2) + 4)))); | |
788 | break; | |
789 | ||
790 | case BS_DIBPATTERN: | |
791 | infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2); | |
792 | MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( infohdr, mr->rdParm[1] )); | |
793 | break; | |
794 | ||
795 | default: | |
796 | ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n", | |
797 | mr->rdParm[0]); | |
798 | break; | |
799 | } | |
800 | break; | |
9a624916 | 801 | |
36ca1368 | 802 | case META_CREATEPENINDIRECT: |
15b9ed9f AJ |
803 | { |
804 | LOGPEN pen; | |
805 | pen.lopnStyle = mr->rdParm[0]; | |
806 | pen.lopnWidth.x = (SHORT)mr->rdParm[1]; | |
807 | pen.lopnWidth.y = (SHORT)mr->rdParm[2]; | |
808 | pen.lopnColor = MAKELONG( mr->rdParm[3], mr->rdParm[4] ); | |
809 | MF_AddHandle(ht, handles, CreatePenIndirect( &pen )); | |
810 | } | |
811 | break; | |
36ca1368 | 812 | |
988ca977 | 813 | case META_CREATEFONTINDIRECT: |
15b9ed9f AJ |
814 | { |
815 | LOGFONTA font; | |
816 | font.lfHeight = (SHORT)mr->rdParm[0]; | |
817 | font.lfWidth = (SHORT)mr->rdParm[1]; | |
818 | font.lfEscapement = (SHORT)mr->rdParm[2]; | |
819 | font.lfOrientation = (SHORT)mr->rdParm[3]; | |
820 | font.lfWeight = (SHORT)mr->rdParm[4]; | |
821 | font.lfItalic = LOBYTE(mr->rdParm[5]); | |
822 | font.lfUnderline = HIBYTE(mr->rdParm[5]); | |
823 | font.lfStrikeOut = LOBYTE(mr->rdParm[6]); | |
824 | font.lfCharSet = HIBYTE(mr->rdParm[6]); | |
825 | font.lfOutPrecision = LOBYTE(mr->rdParm[7]); | |
826 | font.lfClipPrecision = HIBYTE(mr->rdParm[7]); | |
827 | font.lfQuality = LOBYTE(mr->rdParm[8]); | |
828 | font.lfPitchAndFamily = HIBYTE(mr->rdParm[8]); | |
829 | memcpy( font.lfFaceName, mr->rdParm + 9, LF_FACESIZE ); | |
830 | MF_AddHandle(ht, handles, CreateFontIndirectA( &font )); | |
831 | } | |
832 | break; | |
988ca977 | 833 | |
36ca1368 | 834 | case META_CREATEBRUSHINDIRECT: |
15b9ed9f AJ |
835 | { |
836 | LOGBRUSH brush; | |
837 | brush.lbStyle = mr->rdParm[0]; | |
838 | brush.lbColor = MAKELONG( mr->rdParm[1], mr->rdParm[2] ); | |
839 | brush.lbHatch = mr->rdParm[3]; | |
840 | MF_AddHandle(ht, handles, CreateBrushIndirect( &brush )); | |
841 | } | |
842 | break; | |
36ca1368 | 843 | |
902da699 | 844 | case META_CREATEPALETTE: |
15b9ed9f AJ |
845 | MF_AddHandle(ht, handles, CreatePalette((LPLOGPALETTE)mr->rdParm)); |
846 | break; | |
902da699 AJ |
847 | |
848 | case META_SETTEXTALIGN: | |
15b9ed9f AJ |
849 | SetTextAlign(hdc, mr->rdParm[0]); |
850 | break; | |
902da699 AJ |
851 | |
852 | case META_SELECTPALETTE: | |
15b9ed9f AJ |
853 | GDISelectPalette(hdc, *(ht->objectHandle + mr->rdParm[1]), mr->rdParm[0]); |
854 | break; | |
902da699 AJ |
855 | |
856 | case META_SETMAPPERFLAGS: | |
15b9ed9f AJ |
857 | SetMapperFlags(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1])); |
858 | break; | |
902da699 AJ |
859 | |
860 | case META_REALIZEPALETTE: | |
15b9ed9f AJ |
861 | GDIRealizePalette(hdc); |
862 | break; | |
902da699 AJ |
863 | |
864 | case META_ESCAPE: | |
b49a1de1 MM |
865 | switch (mr->rdParm[0]) { |
866 | case GETSCALINGFACTOR: /* get function ... would just NULL dereference */ | |
bde68851 AJ |
867 | case GETPHYSPAGESIZE: |
868 | case GETPRINTINGOFFSET: | |
b49a1de1 MM |
869 | return FALSE; |
870 | case SETABORTPROC: | |
871 | FIXME("Filtering Escape(SETABORTPROC), possible virus?\n"); | |
872 | return FALSE; | |
873 | } | |
187c2b41 | 874 | Escape(hdc, mr->rdParm[0], mr->rdParm[1], (LPCSTR)&mr->rdParm[2], NULL); |
902da699 AJ |
875 | break; |
876 | ||
f1aa3030 | 877 | case META_EXTTEXTOUT: |
56166a6f | 878 | MF_Play_MetaExtTextOut( hdc, mr ); |
15b9ed9f | 879 | break; |
9a624916 | 880 | |
cdcdede2 AJ |
881 | case META_STRETCHDIB: |
882 | { | |
15b9ed9f AJ |
883 | LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]); |
884 | LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] ); | |
885 | StretchDIBits( hdc, (SHORT)mr->rdParm[10], (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8], | |
886 | (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5], | |
887 | (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], bits, info, | |
8da12c43 | 888 | mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1])); |
cdcdede2 AJ |
889 | } |
890 | break; | |
f1aa3030 AJ |
891 | |
892 | case META_DIBSTRETCHBLT: | |
893 | { | |
15b9ed9f AJ |
894 | LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]); |
895 | LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] ); | |
896 | StretchDIBits( hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7], | |
897 | (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], | |
898 | (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], bits, info, | |
8da12c43 | 899 | DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1])); |
f1aa3030 | 900 | } |
9a624916 | 901 | break; |
f1aa3030 AJ |
902 | |
903 | case META_STRETCHBLT: | |
904 | { | |
15b9ed9f AJ |
905 | HDC hdcSrc = CreateCompatibleDC(hdc); |
906 | HBITMAP hbitmap = CreateBitmap(mr->rdParm[10], /*Width */ | |
907 | mr->rdParm[11], /*Height*/ | |
908 | mr->rdParm[13], /*Planes*/ | |
909 | mr->rdParm[14], /*BitsPixel*/ | |
910 | (LPSTR)&mr->rdParm[15]); /*bits*/ | |
911 | SelectObject(hdcSrc,hbitmap); | |
912 | StretchBlt(hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8], | |
913 | (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], | |
914 | hdcSrc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], | |
915 | (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], | |
916 | MAKELONG(mr->rdParm[0],mr->rdParm[1])); | |
917 | DeleteDC(hdcSrc); | |
f1aa3030 AJ |
918 | } |
919 | break; | |
920 | ||
b94e4330 | 921 | case META_BITBLT: |
f1aa3030 | 922 | { |
15b9ed9f AJ |
923 | HDC hdcSrc = CreateCompatibleDC(hdc); |
924 | HBITMAP hbitmap = CreateBitmap(mr->rdParm[7]/*Width */, | |
8da12c43 AJ |
925 | mr->rdParm[8]/*Height*/, |
926 | mr->rdParm[10]/*Planes*/, | |
927 | mr->rdParm[11]/*BitsPixel*/, | |
928 | (LPSTR)&mr->rdParm[12]/*bits*/); | |
15b9ed9f AJ |
929 | SelectObject(hdcSrc,hbitmap); |
930 | BitBlt(hdc,(SHORT)mr->rdParm[6],(SHORT)mr->rdParm[5], | |
931 | (SHORT)mr->rdParm[4],(SHORT)mr->rdParm[3], | |
932 | hdcSrc, (SHORT)mr->rdParm[2],(SHORT)mr->rdParm[1], | |
8da12c43 | 933 | MAKELONG(0,mr->rdParm[0])); |
15b9ed9f | 934 | DeleteDC(hdcSrc); |
f1aa3030 AJ |
935 | } |
936 | break; | |
889f7424 | 937 | |
889f7424 | 938 | case META_CREATEREGION: |
0623a6f3 | 939 | { |
15b9ed9f | 940 | HRGN hrgn = CreateRectRgn(0,0,0,0); |
9a624916 | 941 | |
15b9ed9f AJ |
942 | MF_Play_MetaCreateRegion(mr, hrgn); |
943 | MF_AddHandle(ht, handles, hrgn); | |
0623a6f3 AJ |
944 | } |
945 | break; | |
889f7424 | 946 | |
b94e4330 | 947 | case META_FILLREGION: |
15b9ed9f AJ |
948 | FillRgn(hdc, *(ht->objectHandle + mr->rdParm[1]), |
949 | *(ht->objectHandle + mr->rdParm[0])); | |
7603deae HD |
950 | break; |
951 | ||
952 | case META_FRAMEREGION: | |
15b9ed9f AJ |
953 | FrameRgn(hdc, *(ht->objectHandle + mr->rdParm[3]), |
954 | *(ht->objectHandle + mr->rdParm[2]), | |
955 | (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]); | |
889f7424 AJ |
956 | break; |
957 | ||
b94e4330 | 958 | case META_INVERTREGION: |
15b9ed9f | 959 | InvertRgn(hdc, *(ht->objectHandle + mr->rdParm[0])); |
9a624916 | 960 | break; |
889f7424 | 961 | |
b94e4330 | 962 | case META_PAINTREGION: |
15b9ed9f | 963 | PaintRgn(hdc, *(ht->objectHandle + mr->rdParm[0])); |
889f7424 AJ |
964 | break; |
965 | ||
b94e4330 | 966 | case META_SELECTCLIPREGION: |
f4f7689c UC |
967 | { |
968 | HRGN hrgn = 0; | |
969 | ||
970 | if (mr->rdParm[0]) hrgn = *(ht->objectHandle + mr->rdParm[0]); | |
971 | SelectClipRgn(hdc, hrgn); | |
972 | } | |
15b9ed9f | 973 | break; |
889f7424 | 974 | |
b94e4330 | 975 | case META_DIBCREATEPATTERNBRUSH: |
15b9ed9f AJ |
976 | /* mr->rdParm[0] may be BS_PATTERN or BS_DIBPATTERN: |
977 | but there's no difference */ | |
978 | MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( mr->rdParm + 2, mr->rdParm[1] )); | |
979 | break; | |
84c70f55 | 980 | |
56166a6f HD |
981 | case META_DIBBITBLT: |
982 | /* In practice I've found that there are two layouts for | |
15b9ed9f AJ |
983 | META_DIBBITBLT, one (the first here) is the usual one when a src |
984 | dc is actually passed to it, the second occurs when the src dc is | |
985 | passed in as NULL to the creating BitBlt. As the second case has | |
986 | no dib, a size check will suffice to distinguish. | |
56166a6f | 987 | |
15b9ed9f | 988 | Caolan.McNamara@ul.ie */ |
56166a6f HD |
989 | |
990 | if (mr->rdSize > 12) { | |
15b9ed9f AJ |
991 | LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]); |
992 | LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]); | |
993 | ||
994 | StretchDIBits(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5], | |
995 | (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], | |
996 | (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], bits, info, | |
997 | DIB_RGB_COLORS, MAKELONG(mr->rdParm[0], mr->rdParm[1])); | |
998 | } | |
999 | else /* equivalent to a PatBlt */ | |
1000 | PatBlt(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7], | |
1001 | (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5], | |
1002 | MAKELONG(mr->rdParm[0], mr->rdParm[1])); | |
1003 | break; | |
9a624916 | 1004 | |
b94e4330 | 1005 | case META_SETTEXTCHAREXTRA: |
15b9ed9f AJ |
1006 | SetTextCharacterExtra(hdc, (SHORT)mr->rdParm[0]); |
1007 | break; | |
491502b9 | 1008 | |
b94e4330 | 1009 | case META_SETTEXTJUSTIFICATION: |
15b9ed9f AJ |
1010 | SetTextJustification(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]); |
1011 | break; | |
7ff1c415 | 1012 | |
ae8a748a | 1013 | case META_EXTFLOODFILL: |
15b9ed9f AJ |
1014 | ExtFloodFill(hdc, (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], |
1015 | MAKELONG(mr->rdParm[1], mr->rdParm[2]), | |
1016 | mr->rdParm[0]); | |
ae8a748a CM |
1017 | break; |
1018 | ||
56166a6f | 1019 | case META_SETDIBTODEV: |
15b9ed9f AJ |
1020 | { |
1021 | BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]); | |
1022 | char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] ); | |
1023 | SetDIBitsToDevice(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7], | |
1024 | (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5], | |
1025 | (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], | |
1026 | mr->rdParm[2], mr->rdParm[1], bits, info, | |
1027 | mr->rdParm[0]); | |
1028 | break; | |
1029 | } | |
56166a6f HD |
1030 | |
1031 | #define META_UNIMP(x) case x: \ | |
15657090 | 1032 | FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \ |
56166a6f | 1033 | break; |
c6c09442 | 1034 | META_UNIMP(META_DRAWTEXT) |
c6c09442 AJ |
1035 | META_UNIMP(META_ANIMATEPALETTE) |
1036 | META_UNIMP(META_SETPALENTRIES) | |
1037 | META_UNIMP(META_RESIZEPALETTE) | |
c6c09442 AJ |
1038 | META_UNIMP(META_RESETDC) |
1039 | META_UNIMP(META_STARTDOC) | |
1040 | META_UNIMP(META_STARTPAGE) | |
1041 | META_UNIMP(META_ENDPAGE) | |
1042 | META_UNIMP(META_ABORTDOC) | |
1043 | META_UNIMP(META_ENDDOC) | |
1044 | META_UNIMP(META_CREATEBRUSH) | |
1045 | META_UNIMP(META_CREATEBITMAPINDIRECT) | |
1046 | META_UNIMP(META_CREATEBITMAP) | |
1047 | #undef META_UNIMP | |
f1aa3030 | 1048 | |
36ca1368 | 1049 | default: |
15b9ed9f AJ |
1050 | WARN("PlayMetaFileRecord: Unknown record type %x\n", mr->rdFunction); |
1051 | return FALSE; | |
36ca1368 | 1052 | } |
b94e4330 | 1053 | return TRUE; |
54c2711f AJ |
1054 | } |
1055 | ||
54c2711f | 1056 | /****************************************************************** |
d0a41774 | 1057 | * SetMetaFileBitsEx (GDI32.@) |
9a624916 | 1058 | * |
c7c217b3 | 1059 | * Create a metafile from raw data. No checking of the data is performed. |
396ee740 DP |
1060 | * Use GetMetaFileBitsEx() to get raw data from a metafile. |
1061 | * | |
1062 | * PARAMS | |
1063 | * size [I] size of metafile, in bytes | |
1064 | * lpData [I] pointer to metafile data | |
79e3a1be MA |
1065 | * |
1066 | * RETURNS | |
1067 | * Success: Handle to metafile. | |
1068 | * Failure: NULL. | |
54c2711f | 1069 | */ |
396ee740 | 1070 | HMETAFILE WINAPI SetMetaFileBitsEx( UINT size, const BYTE *lpData ) |
54c2711f | 1071 | { |
5f2bf16d DT |
1072 | METAHEADER *mh = (METAHEADER *)lpData; |
1073 | ||
1074 | if (size & 1) return 0; | |
1075 | ||
1076 | if (!size || mh->mtType != METAFILE_MEMORY || mh->mtVersion != MFVERSION || | |
1077 | mh->mtHeaderSize != sizeof(METAHEADER) / 2) | |
1078 | { | |
1079 | SetLastError(ERROR_INVALID_DATA); | |
1080 | return 0; | |
1081 | } | |
1082 | ||
1083 | mh = HeapAlloc( GetProcessHeap(), 0, size ); | |
1084 | if (!mh) | |
1085 | { | |
1086 | SetLastError(ERROR_NOT_ENOUGH_MEMORY); | |
1087 | return 0; | |
1088 | } | |
1089 | ||
b94e4330 | 1090 | memcpy(mh, lpData, size); |
5f2bf16d | 1091 | mh->mtSize = size / 2; |
b94e4330 | 1092 | return MF_Create_HMETAFILE(mh); |
54c2711f AJ |
1093 | } |
1094 | ||
46ea8b3f | 1095 | /***************************************************************** |
783a3954 JG |
1096 | * GetMetaFileBitsEx (GDI32.@) |
1097 | * | |
1098 | * Get raw metafile data. | |
9a624916 | 1099 | * |
46ea8b3f | 1100 | * Copies the data from metafile _hmf_ into the buffer _buf_. |
396ee740 DP |
1101 | * |
1102 | * PARAMS | |
1103 | * hmf [I] metafile | |
1104 | * nSize [I] size of buf | |
1105 | * buf [O] buffer to receive raw metafile data | |
79e3a1be MA |
1106 | * |
1107 | * RETURNS | |
1108 | * If _buf_ is zero, returns size of buffer required. Otherwise, | |
1109 | * returns number of bytes copied. | |
46ea8b3f | 1110 | */ |
396ee740 | 1111 | UINT WINAPI GetMetaFileBitsEx( HMETAFILE hmf, UINT nSize, LPVOID buf ) |
783a3954 | 1112 | { |
b94e4330 HD |
1113 | METAHEADER *mh = MF_GetMetaHeader(hmf); |
1114 | UINT mfSize; | |
1115 | ||
547cdc2b | 1116 | TRACE("(%p,%d,%p)\n", hmf, nSize, buf); |
b94e4330 HD |
1117 | if (!mh) return 0; /* FIXME: error code */ |
1118 | if(mh->mtType == METAFILE_DISK) | |
15657090 | 1119 | FIXME("Disk-based metafile?\n"); |
b94e4330 HD |
1120 | mfSize = mh->mtSize * 2; |
1121 | if (!buf) { | |
15657090 | 1122 | TRACE("returning size %d\n", mfSize); |
b94e4330 HD |
1123 | return mfSize; |
1124 | } | |
1125 | if(mfSize > nSize) mfSize = nSize; | |
1126 | memmove(buf, mh, mfSize); | |
7bb6fd1d | 1127 | return mfSize; |
46ea8b3f AJ |
1128 | } |
1129 | ||
0c0e3beb | 1130 | /****************************************************************** |
d0a41774 | 1131 | * GetWinMetaFileBits [GDI32.@] |
0c0e3beb | 1132 | */ |
a3960292 AJ |
1133 | UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf, |
1134 | UINT cbBuffer, LPBYTE lpbBuffer, | |
1135 | INT fnMapMode, HDC hdcRef) | |
0c0e3beb | 1136 | { |
b482e9ac HD |
1137 | HDC hdcmf; |
1138 | HMETAFILE hmf; | |
1139 | UINT ret; | |
6cc56740 UC |
1140 | RECT rc; |
1141 | INT oldMapMode; | |
1142 | ||
1143 | GetClipBox(hdcRef, &rc); | |
1144 | oldMapMode = SetMapMode(hdcRef, fnMapMode); | |
1145 | ||
1146 | TRACE("(%p,%d,%p,%d,%p) rc=%s\n", hemf, cbBuffer, lpbBuffer, | |
1147 | fnMapMode, hdcRef, wine_dbgstr_rect(&rc)); | |
b482e9ac | 1148 | |
b482e9ac | 1149 | hdcmf = CreateMetaFileA(NULL); |
6cc56740 | 1150 | PlayEnhMetaFile(hdcmf, hemf, &rc); |
b482e9ac HD |
1151 | hmf = CloseMetaFile(hdcmf); |
1152 | ret = GetMetaFileBitsEx(hmf, cbBuffer, lpbBuffer); | |
1153 | DeleteMetaFile(hmf); | |
6cc56740 UC |
1154 | |
1155 | SetMapMode(hdcRef, oldMapMode); | |
1156 | ||
b482e9ac | 1157 | return ret; |
0c0e3beb | 1158 | } |
46ea8b3f | 1159 | |
0623a6f3 | 1160 | /****************************************************************** |
b94e4330 | 1161 | * MF_Play_MetaCreateRegion |
0623a6f3 AJ |
1162 | * |
1163 | * Handles META_CREATEREGION for PlayMetaFileRecord(). | |
396ee740 | 1164 | * |
0623a6f3 | 1165 | * The layout of the record looks something like this: |
9a624916 | 1166 | * |
8da12c43 | 1167 | * rdParm meaning |
0623a6f3 AJ |
1168 | * 0 Always 0? |
1169 | * 1 Always 6? | |
1170 | * 2 Looks like a handle? - not constant | |
1171 | * 3 0 or 1 ?? | |
1172 | * 4 Total number of bytes | |
282f7270 | 1173 | * 5 No. of separate bands = n [see below] |
0623a6f3 AJ |
1174 | * 6 Largest number of x co-ords in a band |
1175 | * 7-10 Bounding box x1 y1 x2 y2 | |
1176 | * 11-... n bands | |
1177 | * | |
1178 | * Regions are divided into bands that are uniform in the | |
1179 | * y-direction. Each band consists of pairs of on/off x-coords and is | |
1180 | * written as | |
1181 | * m y0 y1 x1 x2 x3 ... xm m | |
8da12c43 | 1182 | * into successive rdParm[]s. |
0623a6f3 AJ |
1183 | * |
1184 | * This is probably just a dump of the internal RGNOBJ? | |
1185 | * | |
1186 | * HDMD - 18/12/97 | |
1187 | * | |
1188 | */ | |
1189 | ||
b94e4330 | 1190 | static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn ) |
0623a6f3 AJ |
1191 | { |
1192 | WORD band, pair; | |
1193 | WORD *start, *end; | |
1194 | INT16 y0, y1; | |
a3960292 | 1195 | HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 ); |
0623a6f3 | 1196 | |
8da12c43 | 1197 | for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5]; |
0623a6f3 AJ |
1198 | band++, start = end + 1) { |
1199 | if(*start / 2 != (*start + 1) / 2) { | |
15657090 | 1200 | WARN("Delimiter not even.\n"); |
a3960292 | 1201 | DeleteObject( hrgn2 ); |
0623a6f3 AJ |
1202 | return FALSE; |
1203 | } | |
1204 | ||
1205 | end = start + *start + 3; | |
1206 | if(end > (WORD *)mr + mr->rdSize) { | |
15657090 | 1207 | WARN("End points outside record.\n"); |
a3960292 | 1208 | DeleteObject( hrgn2 ); |
0623a6f3 AJ |
1209 | return FALSE; |
1210 | } | |
1211 | ||
1212 | if(*start != *end) { | |
15657090 | 1213 | WARN("Mismatched delimiters.\n"); |
a3960292 | 1214 | DeleteObject( hrgn2 ); |
0623a6f3 AJ |
1215 | return FALSE; |
1216 | } | |
1217 | ||
1218 | y0 = *(INT16 *)(start + 1); | |
1219 | y1 = *(INT16 *)(start + 2); | |
1220 | for(pair = 0; pair < *start / 2; pair++) { | |
a3960292 | 1221 | SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0, |
0623a6f3 | 1222 | *(INT16 *)(start + 4 + 2*pair), y1 ); |
a3960292 | 1223 | CombineRgn(hrgn, hrgn, hrgn2, RGN_OR); |
0623a6f3 AJ |
1224 | } |
1225 | } | |
a3960292 | 1226 | DeleteObject( hrgn2 ); |
0623a6f3 AJ |
1227 | return TRUE; |
1228 | } | |
9a624916 | 1229 | |
0623a6f3 | 1230 | |
56166a6f HD |
1231 | /****************************************************************** |
1232 | * MF_Play_MetaExtTextOut | |
1233 | * | |
1234 | * Handles META_EXTTEXTOUT for PlayMetaFileRecord(). | |
36ca1368 | 1235 | */ |
56166a6f | 1236 | |
15b9ed9f | 1237 | static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr) |
56166a6f | 1238 | { |
15b9ed9f AJ |
1239 | INT *dx = NULL; |
1240 | int i; | |
56166a6f | 1241 | LPINT16 dxx; |
9a624916 | 1242 | LPSTR sot; |
56166a6f HD |
1243 | DWORD len; |
1244 | WORD s1; | |
15b9ed9f | 1245 | RECT rect; |
b482e9ac | 1246 | BOOL isrect = mr->rdParm[3] & (ETO_OPAQUE | ETO_CLIPPED); |
56166a6f HD |
1247 | |
1248 | s1 = mr->rdParm[2]; /* String length */ | |
1249 | len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short) | |
b482e9ac | 1250 | + sizeof(UINT16) + (isrect ? sizeof(RECT16) : 0); |
56166a6f HD |
1251 | /* rec len without dx array */ |
1252 | ||
1253 | sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */ | |
b482e9ac | 1254 | if (isrect) |
15b9ed9f AJ |
1255 | { |
1256 | rect.left = (SHORT)mr->rdParm[4]; | |
1257 | rect.top = (SHORT)mr->rdParm[5]; | |
1258 | rect.right = (SHORT)mr->rdParm[6]; | |
1259 | rect.bottom = (SHORT)mr->rdParm[7]; | |
56166a6f | 1260 | sot += sizeof(RECT16); /* there is a rectangle, so add offset */ |
15b9ed9f | 1261 | } |
9a624916 | 1262 | |
56166a6f HD |
1263 | if (mr->rdSize == len / 2) |
1264 | dxx = NULL; /* determine if array present */ | |
9a624916 | 1265 | else |
56166a6f | 1266 | if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2) |
15b9ed9f AJ |
1267 | { |
1268 | dxx = (LPINT16)(sot+(((s1+1)>>1)*2)); | |
1269 | dx = HeapAlloc( GetProcessHeap(), 0, s1*sizeof(INT)); | |
1270 | if (dx) for (i = 0; i < s1; i++) dx[i] = (SHORT)dxx[i]; | |
1271 | } | |
56166a6f | 1272 | else { |
15657090 | 1273 | TRACE("%s len: %ld\n", sot, mr->rdSize); |
396ee740 | 1274 | WARN("Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n", |
56166a6f HD |
1275 | len, s1, mr->rdSize, mr->rdParm[3]); |
1276 | dxx = NULL; /* should't happen -- but if, we continue with NULL */ | |
1277 | } | |
15b9ed9f AJ |
1278 | ExtTextOutA( hdc, |
1279 | (SHORT)mr->rdParm[1], /* X position */ | |
1280 | (SHORT)mr->rdParm[0], /* Y position */ | |
1281 | mr->rdParm[3], /* options */ | |
1282 | &rect, /* rectangle */ | |
1283 | sot, /* string */ | |
396ee740 | 1284 | s1, dx); /* length, dx array */ |
15b9ed9f AJ |
1285 | if (dx) |
1286 | { | |
1287 | TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dx[0]); | |
1288 | HeapFree( GetProcessHeap(), 0, dx ); | |
1289 | } | |
56166a6f HD |
1290 | return TRUE; |
1291 | } |