Fixed CDROM_Audio_Seek for non-linux systems.
[wine] / objects / metafile.c
1 /*
2  * Metafile functions
3  *
4  * Copyright  David W. Metcalfe, 1994
5  *            Niels de Carpentier, Albrecht Kleine, Huw Davies 1996
6  *
7  */
8
9 /*
10  * These functions are primarily involved with metafile playback or anything
11  * that touches a HMETAFILE.
12  * For recording of metafiles look in graphics/metafiledrv/
13  *
14  * Note that (32 bit) HMETAFILEs are GDI objects, while HMETAFILE16s are 
15  * global memory handles so these cannot be interchanged.
16  *
17  * Memory-based metafiles are just stored as a continuous block of memory with
18  * a METAHEADER at the head with METARECORDs appended to it.  mtType is
19  * METAFILE_MEMORY (1).  Note this is indentical to the disk image of a
20  * disk-based metafile - even mtType is METAFILE_MEMORY.
21  * 16bit HMETAFILE16s are global handles to this block
22  * 32bit HMETAFILEs are GDI handles METAFILEOBJs, which contains a ptr to
23  * the memory.
24  * Disk-based metafiles are rather different. HMETAFILE16s point to a
25  * METAHEADER which has mtType equal to METAFILE_DISK (2).  Following the 9
26  * WORDs of the METAHEADER there are a further 3 WORDs of 0, 1 of 0x117, 1
27  * more 0, then 2 which may be a time stamp of the file and then the path of
28  * the file (METAHEADERDISK). I've copied this for 16bit compatibility.
29  *
30  * HDMD - 14/4/1999
31  */  
32
33
34 #include <string.h>
35 #include <fcntl.h>
36 #include "wine/winbase16.h"
37 #include "metafile.h"
38 #include "bitmap.h"
39 #include "heap.h"
40 #include "toolhelp.h"
41 #include "debugtools.h"
42 #include "global.h"
43
44 DEFAULT_DEBUG_CHANNEL(metafile)
45
46 /******************************************************************
47  *         MF_AddHandle
48  *
49  *    Add a handle to an external handle table and return the index
50  */
51 static int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HGDIOBJ16 hobj)
52 {
53     int i;
54
55     for (i = 0; i < htlen; i++)
56     {
57         if (*(ht->objectHandle + i) == 0)
58         {
59             *(ht->objectHandle + i) = hobj;
60             return i;
61         }
62     }
63     return -1;
64 }
65
66
67 /******************************************************************
68  *         MF_Create_HMETATFILE
69  *
70  * Creates a (32 bit) HMETAFILE object from a METAHEADER
71  *
72  * HMETAFILEs are GDI objects.
73  */
74 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
75 {
76     HMETAFILE hmf = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC );
77     METAFILEOBJ *metaObj = (METAFILEOBJ *)GDI_HEAP_LOCK( hmf );
78     metaObj->mh = mh;
79     GDI_HEAP_UNLOCK( hmf );
80     return hmf;
81 }
82
83 /******************************************************************
84  *         MF_Create_HMETATFILE16
85  *
86  * Creates a HMETAFILE16 object from a METAHEADER
87  *
88  * HMETAFILE16s are Global memory handles.
89  */
90 HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
91 {
92     HMETAFILE16 hmf;
93     DWORD size;
94
95     if(mh->mtType == METAFILE_MEMORY)
96         size = mh->mtSize * sizeof(WORD);
97     else
98         size = sizeof(METAHEADER) + sizeof(METAHEADERDISK);
99
100     hmf = GLOBAL_CreateBlock( GMEM_MOVEABLE, mh, mh->mtSize * sizeof(WORD),
101                               GetCurrentPDB16(), FALSE, FALSE, FALSE, NULL );
102     return hmf;
103 }
104
105 /******************************************************************
106  *         MF_GetMetaHeader
107  *
108  * Returns ptr to METAHEADER associated with HMETAFILE
109  * Should be followed by call to MF_ReleaseMetaHeader
110  */
111 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
112 {
113     METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
114     return metaObj ? metaObj->mh : 0;
115 }
116
117 /******************************************************************
118  *         MF_GetMetaHeader16
119  *
120  * Returns ptr to METAHEADER associated with HMETAFILE16
121  * Should be followed by call to MF_ReleaseMetaHeader16
122  */
123 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
124 {
125     return GlobalLock16(hmf);
126 }
127
128 /******************************************************************
129  *         MF_ReleaseMetaHeader
130  *
131  * Releases METAHEADER associated with HMETAFILE
132  */
133 static BOOL MF_ReleaseMetaHeader( HMETAFILE hmf )
134 {
135     return GDI_HEAP_UNLOCK( hmf );
136 }
137
138 /******************************************************************
139  *         MF_ReleaseMetaHeader16
140  *
141  * Releases METAHEADER associated with HMETAFILE16
142  */
143 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
144 {
145     return GlobalUnlock16( hmf );
146 }
147
148
149 /******************************************************************
150  *           DeleteMetaFile16   (GDI.127)
151  */
152 BOOL16 WINAPI DeleteMetaFile16(  HMETAFILE16 hmf )
153 {
154     return !GlobalFree16( hmf );
155 }
156
157 /******************************************************************
158  *          DeleteMetaFile  (GDI32.69)
159  *
160  *  Delete a memory-based metafile.
161  */
162
163 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
164 {
165     METAHEADER *mh = MF_GetMetaHeader( hmf );
166
167     if(!mh) return FALSE;
168     HeapFree( SystemHeap, 0, mh );
169     GDI_FreeObject( hmf );
170     return TRUE;
171 }
172
173 /******************************************************************
174  *         MF_ReadMetaFile
175  *
176  * Returns a pointer to a memory based METAHEADER read in from file HFILE
177  *
178  */
179 static METAHEADER *MF_ReadMetaFile(HFILE hfile)
180 {
181     METAHEADER *mh;
182     DWORD BytesRead, size;
183
184     size = sizeof(METAHEADER);
185     mh = HeapAlloc( SystemHeap, 0, size );
186     if(!mh) return NULL;
187     if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
188        BytesRead != size) {
189         HeapFree( SystemHeap, 0, mh );
190         return NULL;
191     }
192     size = mh->mtSize * 2;
193     mh = HeapReAlloc( SystemHeap, 0, mh, size );
194     if(!mh) return NULL;
195     size -= sizeof(METAHEADER);
196     if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
197                  NULL) == 0 ||
198        BytesRead != size) {
199         HeapFree( SystemHeap, 0, mh );
200         return NULL;
201     }
202
203     if (mh->mtType != METAFILE_MEMORY) {
204         WARN("Disk metafile had mtType = %04x\n", mh->mtType);
205         mh->mtType = METAFILE_MEMORY;
206     }
207     return mh;
208 }
209
210 /******************************************************************
211  *         GetMetaFile16   (GDI.124)
212  */
213 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
214 {
215     METAHEADER *mh;
216     HFILE hFile;
217  
218     TRACE("%s\n", lpFilename);
219
220     if(!lpFilename)
221         return 0;
222
223     if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
224                             OPEN_EXISTING, 0, -1)) == HFILE_ERROR)
225         return 0;
226
227     mh = MF_ReadMetaFile(hFile);
228     CloseHandle(hFile);
229     if(!mh) return 0;
230     return MF_Create_HMETAFILE16( mh );
231 }
232
233 /******************************************************************
234  *         GetMetaFileA   (GDI32.197)
235  *
236  *  Read a metafile from a file. Returns handle to a memory-based metafile.
237  */
238 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
239 {
240     METAHEADER *mh;
241     HFILE hFile;
242  
243     TRACE("%s\n", lpFilename);
244
245     if(!lpFilename)
246         return 0;
247
248     if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
249                             OPEN_EXISTING, 0, -1)) == HFILE_ERROR)
250         return 0;
251
252     mh = MF_ReadMetaFile(hFile);
253     CloseHandle(hFile);
254     if(!mh) return 0;
255     return MF_Create_HMETAFILE( mh );
256 }
257
258
259
260 /******************************************************************
261  *         GetMetaFileW   (GDI32.199)
262  */
263 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
264 {
265     METAHEADER *mh;
266     HFILE hFile;
267  
268     TRACE("%s\n", debugstr_w(lpFilename));
269
270     if(!lpFilename)
271         return 0;
272
273     if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
274                             OPEN_EXISTING, 0, -1)) == HFILE_ERROR)
275         return 0;
276
277     mh = MF_ReadMetaFile(hFile);
278     CloseHandle(hFile);
279     if(!mh) return 0;
280     return MF_Create_HMETAFILE( mh );
281 }
282
283
284 /******************************************************************
285  *         MF_LoadDiskBasedMetaFile
286  *
287  * Creates a new memory-based metafile from a disk-based one.
288  */
289 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
290 {
291     METAHEADERDISK *mhd;
292     HFILE hfile;
293     METAHEADER *mh2;
294
295     if(mh->mtType != METAFILE_DISK) {
296         ERR("Not a disk based metafile\n");
297         return NULL;
298     }
299     mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
300
301     if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
302                             OPEN_EXISTING, 0, -1)) == HFILE_ERROR) {
303         WARN("Can't open file of disk based metafile\n");
304         return NULL;
305     }
306     mh2 = MF_ReadMetaFile(hfile);
307     CloseHandle(hfile);
308     return mh2;
309 }
310
311 /******************************************************************
312  *         MF_CreateMetaHeaderDisk
313  *
314  * Take a memory based METAHEADER and change it to a disk based METAHEADER
315  * assosiated with filename.  Note: Trashes contents of old one. 
316  */
317 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCSTR filename)
318 {
319     METAHEADERDISK *mhd;
320     DWORD size;
321
322     mh = HeapReAlloc( SystemHeap, 0, mh,
323                       sizeof(METAHEADER) + sizeof(METAHEADERDISK));
324     mh->mtType = METAFILE_DISK;
325     size = HeapSize( SystemHeap, 0, mh );
326     mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
327     strcpy(mhd->filename, filename);
328     return mh;
329 }
330
331 /******************************************************************
332  *         CopyMetaFile16   (GDI.151)
333  */
334 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
335 {
336     METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
337     METAHEADER *mh2 = NULL;
338     HFILE hFile;
339
340     TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
341     
342     if(!mh) return 0;
343     
344     if(mh->mtType == METAFILE_DISK)
345         mh2 = MF_LoadDiskBasedMetaFile(mh);
346     else {
347         mh2 = HeapAlloc( SystemHeap, 0, mh->mtSize * 2 );
348         memcpy( mh2, mh, mh->mtSize * 2 );
349     }
350     MF_ReleaseMetaHeader16( hSrcMetaFile );
351
352     if(lpFilename) {         /* disk based metafile */
353         if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
354                                 CREATE_ALWAYS, 0, -1)) == HFILE_ERROR) {
355             HeapFree( SystemHeap, 0, mh2 );
356             return 0;
357         }
358         WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
359         CloseHandle(hFile);
360         mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
361     }
362
363     return MF_Create_HMETAFILE16( mh2 );
364 }
365
366
367 /******************************************************************
368  *         CopyMetaFileA   (GDI32.23)
369  *
370  *  Copies the metafile corresponding to hSrcMetaFile to either
371  *  a disk file, if a filename is given, or to a new memory based
372  *  metafile, if lpFileName is NULL.
373  *
374  * RETURNS
375  *
376  *  Handle to metafile copy on success, NULL on failure.
377  *
378  * BUGS
379  *
380  *  Copying to disk returns NULL even if successful.
381  */
382 HMETAFILE WINAPI CopyMetaFileA(
383                    HMETAFILE hSrcMetaFile, /* handle of metafile to copy */
384                    LPCSTR lpFilename /* filename if copying to a file */
385 ) {
386     METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
387     METAHEADER *mh2 = NULL;
388     HFILE hFile;
389
390     TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
391     
392     if(!mh) return 0;
393     
394     if(mh->mtType == METAFILE_DISK)
395         mh2 = MF_LoadDiskBasedMetaFile(mh);
396     else {
397         mh2 = HeapAlloc( SystemHeap, 0, mh->mtSize * 2 );
398         memcpy( mh2, mh, mh->mtSize * 2 );
399     }
400     MF_ReleaseMetaHeader( hSrcMetaFile );
401
402     if(lpFilename) {         /* disk based metafile */
403         if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
404                                 CREATE_ALWAYS, 0, -1)) == HFILE_ERROR) {
405             HeapFree( SystemHeap, 0, mh2 );
406             return 0;
407         }
408         WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
409         CloseHandle(hFile);
410         mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
411     }
412
413     return MF_Create_HMETAFILE( mh2 );
414 }
415
416
417 /******************************************************************
418  *         CopyMetaFileW   (GDI32.24)
419  */
420 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
421                                     LPCWSTR lpFilename )
422 {
423     LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
424     HMETAFILE ret = CopyMetaFileA( hSrcMetaFile, p );
425     HeapFree( GetProcessHeap(), 0, p );
426     return ret;
427 }
428
429
430 /******************************************************************
431  *         IsValidMetaFile   (GDI.410)
432  *
433  *  Attempts to check if a given metafile is correctly formatted.
434  *  Currently, the only things verified are several properties of the
435  *  header.
436  *
437  * RETURNS
438  *  TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
439  *
440  * BUGS
441  *  This is not exactly what windows does, see _Undocumented_Windows_
442  *  for details.
443  */
444 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
445 {
446     BOOL16 res=FALSE;
447     METAHEADER *mh = MF_GetMetaHeader16(hmf);
448     if (mh) {
449         if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK) 
450             if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
451                 if (mh->mtVersion == MFVERSION)
452                     res=TRUE;
453         MF_ReleaseMetaHeader16(hmf);
454     }
455     TRACE("IsValidMetaFile %x => %d\n",hmf,res);
456     return res;         
457 }
458
459
460 /*******************************************************************
461  *         MF_PlayMetaFile
462  *
463  * Helper for PlayMetaFile
464  */
465 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
466 {
467
468     METARECORD *mr;
469     HANDLETABLE16 *ht;
470     int offset = 0;
471     WORD i;
472     HPEN hPen;
473     HBRUSH hBrush;
474     HFONT hFont;
475     BOOL loaded = FALSE;
476
477     if (!mh) return FALSE;
478     if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
479         mh = MF_LoadDiskBasedMetaFile(mh);
480         if(!mh) return FALSE;
481         loaded = TRUE;
482     }
483
484     /* save the current pen, brush and font */
485     hPen = GetCurrentObject(hdc, OBJ_PEN);
486     hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
487     hFont = GetCurrentObject(hdc, OBJ_FONT);
488
489     /* create the handle table */
490     ht = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY,
491                     sizeof(HANDLETABLE16) * mh->mtNoObjects);
492     if(!ht) return FALSE;
493     
494     /* loop through metafile playing records */
495     offset = mh->mtHeaderSize * 2;
496     while (offset < mh->mtSize * 2)
497     {
498         mr = (METARECORD *)((char *)mh + offset);
499         TRACE("offset=%04x,size=%08lx\n",
500             offset, mr->rdSize);
501         if (!mr->rdSize) {
502             TRACE(
503                   "Entry got size 0 at offset %d, total mf length is %ld\n",
504                   offset,mh->mtSize*2);
505                 break; /* would loop endlessly otherwise */
506         }
507         offset += mr->rdSize * 2;
508         PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
509     }
510
511     SelectObject(hdc, hBrush);
512     SelectObject(hdc, hPen);
513     SelectObject(hdc, hFont);
514
515     /* free objects in handle table */
516     for(i = 0; i < mh->mtNoObjects; i++)
517       if(*(ht->objectHandle + i) != 0)
518         DeleteObject(*(ht->objectHandle + i));
519     
520     /* free handle table */
521     HeapFree( SystemHeap, 0, ht );
522     if(loaded)
523         HeapFree( SystemHeap, 0, mh );
524     return TRUE;
525 }
526
527 /******************************************************************
528  *         PlayMetaFile16   (GDI.123)
529  *
530  */
531 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
532 {
533     BOOL16 ret;
534     METAHEADER *mh = MF_GetMetaHeader16( hmf );
535     ret = MF_PlayMetaFile( hdc, mh );
536     MF_ReleaseMetaHeader16( hmf );
537     return ret;
538 }
539
540 /******************************************************************
541  *         PlayMetaFile   (GDI32.265)
542  *
543  *  Renders the metafile specified by hmf in the DC specified by
544  *  hdc. Returns FALSE on failure, TRUE on success.
545  */
546 BOOL WINAPI PlayMetaFile( 
547                              HDC hdc, /* handle of DC to render in */
548                              HMETAFILE hmf /* handle of metafile to render */
549 )
550 {
551     BOOL ret;
552     METAHEADER *mh = MF_GetMetaHeader( hmf );
553     ret = MF_PlayMetaFile( hdc, mh );
554     MF_ReleaseMetaHeader( hmf );
555     return ret;
556 }
557
558
559 /******************************************************************
560  *            EnumMetaFile16   (GDI.175)
561  *
562  */
563 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
564                               MFENUMPROC16 lpEnumFunc, LPARAM lpData )
565 {
566     METAHEADER *mh = MF_GetMetaHeader16(hmf);
567     METARECORD *mr;
568     HANDLETABLE16 *ht;
569     HGLOBAL16 hHT;
570     SEGPTR spht;
571     int offset = 0;
572     WORD i, seg;
573     HPEN hPen;
574     HBRUSH hBrush;
575     HFONT hFont;
576     BOOL16 result = TRUE, loaded = FALSE;
577
578     TRACE("(%04x, %04x, %08lx, %08lx)\n",
579                      hdc, hmf, (DWORD)lpEnumFunc, lpData);
580
581
582     if(!mh) return FALSE;
583     if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
584         mh = MF_LoadDiskBasedMetaFile(mh);
585         if(!mh) return FALSE;
586         loaded = TRUE;
587     }
588
589     /* save the current pen, brush and font */
590     hPen = GetCurrentObject(hdc, OBJ_PEN);
591     hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
592     hFont = GetCurrentObject(hdc, OBJ_FONT);
593
594     /* create the handle table */
595     
596     hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
597                      sizeof(HANDLETABLE16) * mh->mtNoObjects);
598     spht = WIN16_GlobalLock16(hHT);
599    
600     seg = GlobalHandleToSel16(hmf);
601     offset = mh->mtHeaderSize * 2;
602     
603     /* loop through metafile records */
604     
605     while (offset < (mh->mtSize * 2))
606     {
607         mr = (METARECORD *)((char *)mh + offset);
608         if (!lpEnumFunc( hdc, (HANDLETABLE16 *)spht,
609                          (METARECORD *) PTR_SEG_OFF_TO_HUGEPTR(seg, offset),
610                          mh->mtNoObjects, (LONG)lpData ))
611         {
612             result = FALSE;
613             break;
614         }
615         
616
617         offset += (mr->rdSize * 2);
618     }
619
620     SelectObject(hdc, hBrush);
621     SelectObject(hdc, hPen);
622     SelectObject(hdc, hFont);
623
624     ht = (HANDLETABLE16 *)GlobalLock16(hHT);
625
626     /* free objects in handle table */
627     for(i = 0; i < mh->mtNoObjects; i++)
628       if(*(ht->objectHandle + i) != 0)
629         DeleteObject(*(ht->objectHandle + i));
630
631     /* free handle table */
632     GlobalFree16(hHT);
633     if(loaded)
634         HeapFree( SystemHeap, 0, mh );
635     MF_ReleaseMetaHeader16(hmf);
636     return result;
637 }
638
639 /******************************************************************
640  *            EnumMetaFile   (GDI32.88)
641  *
642  *  Loop through the metafile records in hmf, calling the user-specified
643  *  function for each one, stopping when the user's function returns FALSE
644  *  (which is considered to be failure)
645  *  or when no records are left (which is considered to be success). 
646  *
647  * RETURNS
648  *  TRUE on success, FALSE on failure.
649  * 
650  * HISTORY
651  *   Niels de carpentier, april 1996
652  */
653 BOOL WINAPI EnumMetaFile( 
654                              HDC hdc, 
655                              HMETAFILE hmf,
656                              MFENUMPROC lpEnumFunc, 
657                              LPARAM lpData 
658 ) {
659     METAHEADER *mh = MF_GetMetaHeader(hmf);
660     METARECORD *mr;
661     HANDLETABLE *ht;
662     BOOL result = TRUE, loaded = FALSE;
663     int i, offset = 0;
664     HPEN hPen;
665     HBRUSH hBrush;
666     HFONT hFont;
667
668     TRACE("(%08x,%08x,%p,%p)\n",
669                      hdc, hmf, lpEnumFunc, (void*)lpData);
670     if (!mh) return 0;
671     if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
672         mh = MF_LoadDiskBasedMetaFile(mh);
673         if(!mh) return 0;
674         loaded = TRUE;
675     }
676     
677     /* save the current pen, brush and font */
678     hPen = GetCurrentObject(hdc, OBJ_PEN);
679     hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
680     hFont = GetCurrentObject(hdc, OBJ_FONT);
681
682     ht = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, 
683                             sizeof(HANDLETABLE) * mh->mtNoObjects);
684
685     /* loop through metafile records */
686     offset = mh->mtHeaderSize * 2;
687     
688     while (offset < (mh->mtSize * 2))
689     {
690         mr = (METARECORD *)((char *)mh + offset);
691         TRACE("Calling EnumFunc with record type %x\n",
692               mr->rdFunction);
693         if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
694         {
695             result = FALSE;
696             break;
697         }
698         
699         offset += (mr->rdSize * 2);
700     }
701
702     /* restore pen, brush and font */
703     SelectObject(hdc, hBrush);
704     SelectObject(hdc, hPen);
705     SelectObject(hdc, hFont);
706
707     /* free objects in handle table */
708     for(i = 0; i < mh->mtNoObjects; i++)
709       if(*(ht->objectHandle + i) != 0)
710         DeleteObject(*(ht->objectHandle + i));
711
712     /* free handle table */
713     HeapFree( SystemHeap, 0, ht);
714     if(loaded)
715         HeapFree( SystemHeap, 0, mh );
716     MF_ReleaseMetaHeader(hmf);
717     return result;
718 }
719
720 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
721 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr);
722 /******************************************************************
723  *             PlayMetaFileRecord16   (GDI.176)
724  *
725  *   Render a single metafile record specified by *mr in the DC hdc, while
726  *   using the handle table *ht, of length nHandles, 
727  *   to store metafile objects.
728  *
729  * BUGS
730  *  The following metafile records are unimplemented:
731  *
732  *  DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
733  *  RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
734  *  ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
735  *
736  */
737 void WINAPI PlayMetaFileRecord16( 
738           HDC16 hdc, /* DC to render metafile into */
739           HANDLETABLE16 *ht, /* pointer to handle table for metafile objects */
740           METARECORD *mr, /* pointer to metafile record to render */
741           UINT16 nHandles /* size of handle table */
742 ) {
743     short s1;
744     HANDLE16 hndl;
745     char *ptr;
746     BITMAPINFOHEADER *infohdr;
747
748     TRACE("(%04x %08lx %08lx %04x) function %04x\n",
749                  hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
750     
751     switch (mr->rdFunction)
752     {
753     case META_EOF:
754         break;
755
756     case META_DELETEOBJECT:
757         DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
758         *(ht->objectHandle + *(mr->rdParm)) = 0;
759         break;
760
761     case META_SETBKCOLOR:
762         SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
763         break;
764
765     case META_SETBKMODE:
766         SetBkMode16(hdc, *(mr->rdParm));
767         break;
768
769     case META_SETMAPMODE:
770         SetMapMode16(hdc, *(mr->rdParm));
771         break;
772
773     case META_SETROP2:
774         SetROP216(hdc, *(mr->rdParm));
775         break;
776
777     case META_SETRELABS:
778         SetRelAbs16(hdc, *(mr->rdParm));
779         break;
780
781     case META_SETPOLYFILLMODE:
782         SetPolyFillMode16(hdc, *(mr->rdParm));
783         break;
784
785     case META_SETSTRETCHBLTMODE:
786         SetStretchBltMode16(hdc, *(mr->rdParm));
787         break;
788
789     case META_SETTEXTCOLOR:
790         SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
791         break;
792
793     case META_SETWINDOWORG:
794         SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
795         break;
796
797     case META_SETWINDOWEXT:
798         SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
799         break;
800
801     case META_SETVIEWPORTORG:
802         SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
803         break;
804
805     case META_SETVIEWPORTEXT:
806         SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
807         break;
808
809     case META_OFFSETWINDOWORG:
810         OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
811         break;
812
813     case META_SCALEWINDOWEXT:
814         ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
815                        *(mr->rdParm + 1), *(mr->rdParm));
816         break;
817
818     case META_OFFSETVIEWPORTORG:
819         OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
820         break;
821
822     case META_SCALEVIEWPORTEXT:
823         ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
824                          *(mr->rdParm + 1), *(mr->rdParm));
825         break;
826
827     case META_LINETO:
828         LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
829         break;
830
831     case META_MOVETO:
832         MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
833         break;
834
835     case META_EXCLUDECLIPRECT:
836         ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
837                            *(mr->rdParm + 1), *(mr->rdParm) );
838         break;
839
840     case META_INTERSECTCLIPRECT:
841         IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
842                              *(mr->rdParm + 1), *(mr->rdParm) );
843         break;
844
845     case META_ARC:
846         Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
847                  (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
848                  (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
849                  (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
850         break;
851
852     case META_ELLIPSE:
853         Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
854                      (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
855         break;
856
857     case META_FLOODFILL:
858         FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
859                     MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
860         break;
861
862     case META_PIE:
863         Pie(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
864                  (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
865                  (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
866                  (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
867         break;
868
869     case META_RECTANGLE:
870         Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
871                        (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
872         break;
873
874     case META_ROUNDRECT:
875         RoundRect(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
876                        (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
877                        (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
878         break;
879
880     case META_PATBLT:
881         PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
882                  *(mr->rdParm + 3), *(mr->rdParm + 2),
883                  MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
884         break;
885
886     case META_SAVEDC:
887         SaveDC(hdc);
888         break;
889
890     case META_SETPIXEL:
891         SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
892                    MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
893         break;
894
895     case META_OFFSETCLIPRGN:
896         OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
897         break;
898
899     case META_TEXTOUT:
900         s1 = *(mr->rdParm);
901         TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
902                   *(mr->rdParm + ((s1 + 1) >> 1) + 1), 
903                   (char *)(mr->rdParm + 1), s1);
904         break;
905
906     case META_POLYGON:
907         Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
908         break;
909
910     case META_POLYPOLYGON:
911       PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
912                     (LPINT16)(mr->rdParm + 1), *(mr->rdParm)); 
913       break;
914
915     case META_POLYLINE:
916         Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
917         break;
918
919     case META_RESTOREDC:
920         RestoreDC(hdc, (INT16)*(mr->rdParm));
921         break;
922
923     case META_SELECTOBJECT:
924         SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
925         break;
926
927     case META_CHORD:
928         Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
929                    (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
930                    (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
931                    (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
932         break;
933
934     case META_CREATEPATTERNBRUSH:
935         switch (*(mr->rdParm))
936         {
937         case BS_PATTERN:
938             infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
939             MF_AddHandle(ht, nHandles,
940                          CreatePatternBrush(CreateBitmap(infohdr->biWidth, 
941                                       infohdr->biHeight, 
942                                       infohdr->biPlanes, 
943                                       infohdr->biBitCount,
944                                       (LPSTR)(mr->rdParm + 
945                                       (sizeof(BITMAPINFOHEADER) / 2) + 4))));
946             break;
947
948         case BS_DIBPATTERN:
949             s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
950             hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
951             ptr = GlobalLock16(hndl);
952             memcpy(ptr, mr->rdParm + 2, s1);
953             GlobalUnlock16(hndl);
954             MF_AddHandle(ht, nHandles,
955                          CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
956             GlobalFree16(hndl);
957             break;
958
959         default:
960             ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
961                 mr->rdParm[0]);
962             break;
963         }
964         break;
965         
966     case META_CREATEPENINDIRECT:
967         MF_AddHandle(ht, nHandles, 
968                      CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
969         break;
970
971     case META_CREATEFONTINDIRECT:
972         MF_AddHandle(ht, nHandles, 
973                      CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
974         break;
975
976     case META_CREATEBRUSHINDIRECT:
977         MF_AddHandle(ht, nHandles, 
978                      CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
979         break;
980
981     case META_CREATEPALETTE:
982         MF_AddHandle(ht, nHandles, 
983                      CreatePalette16((LPLOGPALETTE)mr->rdParm));
984         break;
985
986     case META_SETTEXTALIGN:
987         SetTextAlign16(hdc, *(mr->rdParm));
988         break;
989
990     case META_SELECTPALETTE:
991         SelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
992                         *(mr->rdParm));
993         break;
994
995     case META_SETMAPPERFLAGS:
996         SetMapperFlags16(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
997         break;
998
999     case META_REALIZEPALETTE:
1000         RealizePalette16(hdc);
1001         break;
1002
1003     case META_ESCAPE:
1004         FIXME("META_ESCAPE unimplemented.\n");
1005         break;
1006
1007     case META_EXTTEXTOUT:
1008         MF_Play_MetaExtTextOut( hdc, mr );
1009         break;
1010     
1011     case META_STRETCHDIB:
1012       {
1013         LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1014         LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1015         StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
1016                        mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
1017                        mr->rdParm[4],mr->rdParm[3],bits,info,
1018                        mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1019       }
1020       break;
1021
1022     case META_DIBSTRETCHBLT:
1023       {
1024         LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]); 
1025         LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1026         StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
1027                        mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
1028                        mr->rdParm[3],mr->rdParm[2],bits,info,
1029                        DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1030       }
1031       break;              
1032
1033     case META_STRETCHBLT:
1034       {
1035         HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1036         HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
1037                                         mr->rdParm[11], /*Height*/
1038                                         mr->rdParm[13], /*Planes*/
1039                                         mr->rdParm[14], /*BitsPixel*/
1040                                         (LPSTR)&mr->rdParm[15]);  /*bits*/
1041         SelectObject(hdcSrc,hbitmap);
1042         StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
1043                     mr->rdParm[7],mr->rdParm[6],
1044                     hdcSrc,mr->rdParm[5],mr->rdParm[4],
1045                     mr->rdParm[3],mr->rdParm[2],
1046                     MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1047         DeleteDC(hdcSrc);                   
1048       }
1049       break;
1050
1051     case META_BITBLT:
1052       {
1053         HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1054         HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
1055                                         mr->rdParm[8]/*Height*/,
1056                                         mr->rdParm[10]/*Planes*/,
1057                                         mr->rdParm[11]/*BitsPixel*/,
1058                                         (LPSTR)&mr->rdParm[12]/*bits*/);
1059         SelectObject(hdcSrc,hbitmap);
1060         BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
1061                 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
1062                 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
1063                 MAKELONG(0,mr->rdParm[0]));
1064         DeleteDC(hdcSrc);                   
1065       }
1066       break;
1067
1068     case META_CREATEREGION:
1069       {
1070         HRGN hrgn = CreateRectRgn(0,0,0,0);
1071  
1072         MF_Play_MetaCreateRegion(mr, hrgn);
1073         MF_AddHandle(ht, nHandles, hrgn);
1074       }
1075       break;
1076
1077     case META_FILLREGION:
1078         FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1079                        *(ht->objectHandle + *(mr->rdParm)));
1080         break;
1081
1082     case META_FRAMEREGION:
1083         FrameRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+3)),
1084                         *(ht->objectHandle + *(mr->rdParm+2)),
1085                         *(mr->rdParm+1), *(mr->rdParm));
1086         break;
1087
1088     case META_INVERTREGION:
1089         InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1090         break; 
1091
1092     case META_PAINTREGION:
1093         PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1094         break;
1095
1096     case META_SELECTCLIPREGION:
1097         SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
1098         break;
1099
1100     case META_DIBCREATEPATTERNBRUSH:
1101         /*  *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN:
1102             but there's no difference */
1103
1104         TRACE("%d\n",*(mr->rdParm));
1105         s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
1106         hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
1107         ptr = GlobalLock16(hndl);
1108         memcpy(ptr, mr->rdParm + 2, s1);
1109         GlobalUnlock16(hndl);
1110         MF_AddHandle(ht, nHandles,
1111                      CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
1112         GlobalFree16(hndl);
1113         break;
1114
1115     case META_DIBBITBLT:
1116       /* In practice I've found that there are two layouts for
1117          META_DIBBITBLT, one (the first here) is the usual one when a src
1118          dc is actually passed to it, the second occurs when the src dc is
1119          passed in as NULL to the creating BitBlt. As the second case has
1120          no dib, a size check will suffice to distinguish.
1121
1122          Caolan.McNamara@ul.ie */
1123
1124         if (mr->rdSize > 12) {
1125             LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1126             LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1127
1128             StretchDIBits16(hdc, mr->rdParm[7], mr->rdParm[6], mr->rdParm[5],
1129                                  mr->rdParm[4], mr->rdParm[3], mr->rdParm[2],
1130                                  mr->rdParm[5], mr->rdParm[4], bits, info,
1131                                  DIB_RGB_COLORS,
1132                                  MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1133         } else { /* equivalent to a PatBlt */
1134             PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
1135                           mr->rdParm[6], mr->rdParm[5],
1136                           MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1137         }
1138         break;  
1139        
1140     case META_SETTEXTCHAREXTRA:
1141         SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
1142         break;
1143
1144     case META_SETTEXTJUSTIFICATION:
1145         SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
1146         break;
1147
1148     case META_EXTFLOODFILL:
1149         ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
1150                      MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),
1151                      *(mr->rdParm));
1152         break;
1153
1154     case META_SETDIBTODEV:
1155       {
1156         BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1157         char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1158         SetDIBitsToDevice(hdc, (INT16)mr->rdParm[8], (INT16)mr->rdParm[7],
1159                           (INT16)mr->rdParm[6], (INT16)mr->rdParm[5],
1160                           (INT16)mr->rdParm[4], (INT16)mr->rdParm[3],
1161                           mr->rdParm[2], mr->rdParm[1], bits, info,
1162                           mr->rdParm[0]);
1163         break;
1164       }
1165
1166 #define META_UNIMP(x) case x: \
1167 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1168 break;
1169     META_UNIMP(META_DRAWTEXT)
1170     META_UNIMP(META_ANIMATEPALETTE)
1171     META_UNIMP(META_SETPALENTRIES)
1172     META_UNIMP(META_RESIZEPALETTE)
1173     META_UNIMP(META_RESETDC)
1174     META_UNIMP(META_STARTDOC)
1175     META_UNIMP(META_STARTPAGE)
1176     META_UNIMP(META_ENDPAGE)
1177     META_UNIMP(META_ABORTDOC)
1178     META_UNIMP(META_ENDDOC)
1179     META_UNIMP(META_CREATEBRUSH)
1180     META_UNIMP(META_CREATEBITMAPINDIRECT)
1181     META_UNIMP(META_CREATEBITMAP)
1182 #undef META_UNIMP
1183
1184     default:
1185         WARN("PlayMetaFileRecord: Unknown record type %x\n",
1186                                               mr->rdFunction);
1187     }
1188 }
1189
1190 /******************************************************************
1191  *         PlayMetaFileRecord   (GDI32.266)
1192  */
1193 BOOL WINAPI PlayMetaFileRecord( HDC hdc,  HANDLETABLE *handletable, 
1194                                 METARECORD *metarecord, UINT handles )
1195 {
1196     HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR, 
1197                                              handles*sizeof(HANDLETABLE16));
1198     int i = 0;
1199     TRACE("(%08x,%p,%p,%d)\n", hdc, handletable, metarecord,
1200           handles); 
1201     for (i=0; i<handles; i++)  
1202         ht->objectHandle[i] =  handletable->objectHandle[i];
1203     PlayMetaFileRecord16(hdc, ht, metarecord, handles);
1204     for (i=0; i<handles; i++) 
1205         handletable->objectHandle[i] = ht->objectHandle[i];
1206     GlobalFree((HGLOBAL)ht);
1207     return TRUE;
1208 }
1209
1210 /******************************************************************
1211  *         GetMetaFileBits   (GDI.159)
1212  *
1213  * Trade in a metafile object handle for a handle to the metafile memory.
1214  *
1215  */
1216
1217 HGLOBAL16 WINAPI GetMetaFileBits16(
1218                                  HMETAFILE16 hmf /* metafile handle */
1219                                  )
1220 {
1221     TRACE("hMem out: %04x\n", hmf);
1222     return hmf;
1223 }
1224
1225 /******************************************************************
1226  *         SetMetaFileBits   (GDI.160)
1227  *
1228  * Trade in a metafile memory handle for a handle to a metafile object.
1229  * The memory region should hold a proper metafile, otherwise
1230  * problems will occur when it is used. Validity of the memory is not
1231  * checked. The function is essentially just the identity function.
1232  */
1233 HMETAFILE16 WINAPI SetMetaFileBits16( 
1234                                    HGLOBAL16 hMem 
1235                         /* handle to a memory region holding a metafile */
1236 )
1237 {
1238     TRACE("hmf out: %04x\n", hMem);
1239
1240     return hMem;
1241 }
1242
1243 /******************************************************************
1244  *         SetMetaFileBitsBetter   (GDI.196)
1245  *
1246  * Trade in a metafile memory handle for a handle to a metafile object,
1247  * making a cursory check (using IsValidMetaFile()) that the memory
1248  * handle points to a valid metafile.
1249  *
1250  * RETURNS
1251  *  Handle to a metafile on success, NULL on failure..
1252  */
1253 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1254 {
1255     if( IsValidMetaFile16( hMeta ) )
1256         return (HMETAFILE16)GlobalReAlloc16( hMeta, 0, 
1257                            GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1258     return (HMETAFILE16)0;
1259 }
1260
1261 /******************************************************************
1262  *         SetMetaFileBitsEx    (GDI32.323)
1263  * 
1264  *  Create a metafile from raw data. No checking of the data is performed.
1265  *  Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1266  */
1267 HMETAFILE WINAPI SetMetaFileBitsEx( 
1268      UINT size, /* size of metafile, in bytes */
1269      const BYTE *lpData /* pointer to metafile data */  
1270     )
1271 {
1272     METAHEADER *mh = HeapAlloc( SystemHeap, 0, size );
1273     if (!mh) return 0;
1274     memcpy(mh, lpData, size);
1275     return MF_Create_HMETAFILE(mh);
1276 }
1277
1278 /*****************************************************************
1279  *  GetMetaFileBitsEx     (GDI32.198)  Get raw metafile data
1280  * 
1281  *  Copies the data from metafile _hmf_ into the buffer _buf_.
1282  *  If _buf_ is zero, returns size of buffer required. Otherwise,
1283  *  returns number of bytes copied.
1284  */
1285 UINT WINAPI GetMetaFileBitsEx( 
1286      HMETAFILE hmf, /* metafile */
1287      UINT nSize, /* size of buf */ 
1288      LPVOID buf   /* buffer to receive raw metafile data */  
1289 ) {
1290     METAHEADER *mh = MF_GetMetaHeader(hmf);
1291     UINT mfSize;
1292
1293     TRACE("(%08x,%d,%p)\n", hmf, nSize, buf);
1294     if (!mh) return 0;  /* FIXME: error code */
1295     if(mh->mtType == METAFILE_DISK)
1296         FIXME("Disk-based metafile?\n");
1297     mfSize = mh->mtSize * 2;
1298     if (!buf) {
1299         MF_ReleaseMetaHeader(hmf);
1300         TRACE("returning size %d\n", mfSize);
1301         return mfSize;
1302     }
1303     if(mfSize > nSize) mfSize = nSize;
1304     memmove(buf, mh, mfSize);
1305     MF_ReleaseMetaHeader(hmf);
1306     return mfSize;
1307 }
1308
1309 /******************************************************************
1310  *         GetWinMetaFileBits [GDI32.241]
1311  */
1312 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1313                                 UINT cbBuffer, LPBYTE lpbBuffer,
1314                                 INT fnMapMode, HDC hdcRef)
1315 {
1316     FIXME("(%d,%d,%p,%d,%d): stub\n",
1317           hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1318     return 0;
1319 }
1320
1321 /******************************************************************
1322  *         MF_Play_MetaCreateRegion
1323  *
1324  *  Handles META_CREATEREGION for PlayMetaFileRecord().
1325  */
1326
1327 /*
1328  *      The layout of the record looks something like this:
1329  *       
1330  *       rdParm meaning
1331  *       0              Always 0?
1332  *       1              Always 6?
1333  *       2              Looks like a handle? - not constant
1334  *       3              0 or 1 ??
1335  *       4              Total number of bytes
1336  *       5              No. of seperate bands = n [see below]
1337  *       6              Largest number of x co-ords in a band
1338  *       7-10           Bounding box x1 y1 x2 y2
1339  *       11-...         n bands
1340  *
1341  *       Regions are divided into bands that are uniform in the
1342  *       y-direction. Each band consists of pairs of on/off x-coords and is
1343  *       written as
1344  *              m y0 y1 x1 x2 x3 ... xm m
1345  *       into successive rdParm[]s.
1346  *
1347  *       This is probably just a dump of the internal RGNOBJ?
1348  *
1349  *       HDMD - 18/12/97
1350  *
1351  */
1352
1353 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1354 {
1355     WORD band, pair;
1356     WORD *start, *end;
1357     INT16 y0, y1;
1358     HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1359
1360     for(band  = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1361                                                 band++, start = end + 1) {
1362         if(*start / 2 != (*start + 1) / 2) {
1363             WARN("Delimiter not even.\n");
1364             DeleteObject( hrgn2 );
1365             return FALSE;
1366         }
1367
1368         end = start + *start + 3;
1369         if(end > (WORD *)mr + mr->rdSize) {
1370             WARN("End points outside record.\n");
1371             DeleteObject( hrgn2 );
1372             return FALSE;
1373         }
1374
1375         if(*start != *end) {
1376             WARN("Mismatched delimiters.\n");
1377             DeleteObject( hrgn2 );
1378             return FALSE;
1379         }
1380
1381         y0 = *(INT16 *)(start + 1);
1382         y1 = *(INT16 *)(start + 2);
1383         for(pair = 0; pair < *start / 2; pair++) {
1384             SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1385                                  *(INT16 *)(start + 4 + 2*pair), y1 );
1386             CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1387         }
1388     }
1389     DeleteObject( hrgn2 );
1390     return TRUE;
1391  }
1392  
1393
1394 /******************************************************************
1395  *         MF_Play_MetaExtTextOut
1396  *
1397  *  Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1398  */
1399
1400 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr)
1401 {
1402     LPINT16 dxx;
1403     LPSTR sot; 
1404     DWORD len;
1405     WORD s1;
1406
1407     s1 = mr->rdParm[2];                              /* String length */
1408     len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1409       + sizeof(UINT16) +  (mr->rdParm[3] ? sizeof(RECT16) : 0); 
1410                                            /* rec len without dx array */
1411
1412     sot = (LPSTR)&mr->rdParm[4];                      /* start_of_text */
1413     if (mr->rdParm[3])
1414         sot += sizeof(RECT16);  /* there is a rectangle, so add offset */
1415          
1416     if (mr->rdSize == len / 2)
1417         dxx = NULL;                      /* determine if array present */
1418     else 
1419         if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1420             dxx = (LPINT16)(sot+(((s1+1)>>1)*2));          
1421         else {
1422             TRACE("%s  len: %ld\n",  sot, mr->rdSize);
1423             WARN(
1424              "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1425                  len, s1, mr->rdSize, mr->rdParm[3]);
1426             dxx = NULL; /* should't happen -- but if, we continue with NULL */
1427         }
1428     ExtTextOut16( hdc, mr->rdParm[1],              /* X position */
1429                        mr->rdParm[0],              /* Y position */
1430                        mr->rdParm[3],              /* options */
1431                        mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL,  
1432                                                    /* rectangle */
1433                        sot,                            /* string */
1434                        s1, dxx);                   /* length, dx array */
1435     if (dxx)                      
1436         TRACE("%s  len: %ld  dx0: %d\n", sot, mr->rdSize, dxx[0]);
1437     return TRUE;
1438 }