Some warnings fixed, one useless VERSION warning removed (winelib).
[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 #include <string.h>
10 #include <fcntl.h>
11 #include "windows.h"
12 #include "gdi.h"
13 #include "bitmap.h"
14 #include "file.h"
15 #include "heap.h"
16 #include "metafile.h"
17 #include "metafiledrv.h"
18 #include "toolhelp.h"
19 #include "debug.h"
20
21 /******************************************************************
22  *         MF_AddHandle
23  *
24  *    Add a handle to an external handle table and return the index
25  */
26
27 static int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HGDIOBJ16 hobj)
28 {
29     int i;
30
31     for (i = 0; i < htlen; i++)
32     {
33         if (*(ht->objectHandle + i) == 0)
34         {
35             *(ht->objectHandle + i) = hobj;
36             return i;
37         }
38     }
39     return -1;
40 }
41
42
43 /******************************************************************
44  *         MF_AddHandleDC
45  *
46  * Note: this function assumes that we never delete objects.
47  * If we do someday, we'll need to maintain a table to re-use deleted
48  * handles.
49  */
50 static int MF_AddHandleDC( DC *dc )
51 {
52     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
53     physDev->mh->mtNoObjects++;
54     return physDev->nextHandle++;
55 }
56
57
58 /******************************************************************
59  *         GetMetaFile16   (GDI.124)
60  */
61 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
62 {
63     return GetMetaFile32A( lpFilename );
64 }
65
66
67 /******************************************************************
68  *         GetMetaFile32A   (GDI32.197)
69  *
70  *  Read a metafile from a file. Returns handle to a disk-based metafile.
71  */
72 HMETAFILE32 WINAPI GetMetaFile32A( 
73                                   LPCSTR lpFilename 
74                       /* pointer to string containing filename to read */
75 )
76 {
77   HMETAFILE16 hmf;
78   METAHEADER *mh;
79   HFILE32 hFile;
80   DWORD size;
81   
82   TRACE(metafile,"%s\n", lpFilename);
83
84   if (!lpFilename)
85     return 0;
86
87   hmf = GlobalAlloc16(GMEM_MOVEABLE, MFHEADERSIZE);
88   mh = (METAHEADER *)GlobalLock16(hmf);
89   
90   if (!mh)
91   {
92     GlobalFree16(hmf);
93     return 0;
94   }
95   
96   if ((hFile = _lopen32(lpFilename, OF_READ)) == HFILE_ERROR32)
97   {
98     GlobalFree16(hmf);
99     return 0;
100   }
101   
102   if (_lread32(hFile, (char *)mh, MFHEADERSIZE) == HFILE_ERROR32)
103   {
104     _lclose32( hFile );
105     GlobalFree16(hmf);
106     return 0;
107   }
108   
109   size = mh->mtSize * 2;         /* alloc memory for whole metafile */
110   GlobalUnlock16(hmf);
111   hmf = GlobalReAlloc16(hmf,size,GMEM_MOVEABLE);
112   mh = (METAHEADER *)GlobalLock16(hmf);
113   
114   if (!mh)
115   {
116     _lclose32( hFile );
117     GlobalFree16(hmf);
118     return 0;
119   }
120   
121   if (_lread32(hFile, (char*)mh + mh->mtHeaderSize * 2, 
122                 size - mh->mtHeaderSize * 2) == HFILE_ERROR32)
123   {
124     _lclose32( hFile );
125     GlobalFree16(hmf);
126     return 0;
127   }
128   
129   _lclose32(hFile);
130
131   if (mh->mtType != 1)
132   {
133     GlobalFree16(hmf);
134     return 0;
135   }
136   
137   GlobalUnlock16(hmf);
138   return hmf;
139
140 }
141
142
143 /******************************************************************
144  *         GetMetaFile32W   (GDI32.199)
145  */
146 HMETAFILE32 WINAPI GetMetaFile32W( LPCWSTR lpFilename )
147 {
148     LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
149     HMETAFILE32 ret = GetMetaFile32A( p );
150     HeapFree( GetProcessHeap(), 0, p );
151     return ret;
152 }
153
154
155 /******************************************************************
156  *         CopyMetaFile16   (GDI.151)
157  */
158
159 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename )
160 {
161     return CopyMetaFile32A( hSrcMetaFile, lpFilename );
162 }
163
164
165 /******************************************************************
166  *         CopyMetaFile32A   (GDI32.23)
167  *
168  *  Copies the metafile corresponding to hSrcMetaFile to either
169  *  a disk file, if a filename is given, or to a new memory based
170  *  metafile, if lpFileName is NULL.
171  *
172  * RETURNS
173  *
174  *  Handle to metafile copy on success, NULL on failure.
175  *
176  * BUGS
177  *
178  *  Copying to disk returns NULL even if successful.
179  */
180 HMETAFILE32 WINAPI CopyMetaFile32A(
181                    HMETAFILE32 hSrcMetaFile, /* handle of metafile to copy */
182                    LPCSTR lpFilename /* filename if copying to a file */
183 ) {
184     HMETAFILE16 handle = 0;
185     METAHEADER *mh;
186     METAHEADER *mh2;
187     HFILE32 hFile;
188     
189     TRACE(metafile,"(%08x,%s)\n", hSrcMetaFile, lpFilename);
190     
191     mh = (METAHEADER *)GlobalLock16(hSrcMetaFile);
192     
193     if (!mh)
194       return 0;
195     
196     if (lpFilename)          /* disk based metafile */
197         {
198         int i,j;
199         hFile = _lcreat32(lpFilename, 0);
200         j=mh->mtType;
201         mh->mtType=1;        /* disk file version stores 1 here */
202         i=_lwrite32(hFile, (char *)mh, mh->mtSize * 2) ;
203         mh->mtType=j;        /* restore old value  [0 or 1] */  
204         _lclose32(hFile);
205         if (i == -1)
206             return 0;
207         /* FIXME: return value */
208         }
209     else                     /* memory based metafile */
210         {
211         handle = GlobalAlloc16(GMEM_MOVEABLE,mh->mtSize * 2);
212         mh2 = (METAHEADER *)GlobalLock16(handle);
213         memcpy(mh2,mh, mh->mtSize * 2);
214         GlobalUnlock16(handle);
215         }
216
217     GlobalUnlock16(hSrcMetaFile);
218     return handle;
219 }
220
221
222 /******************************************************************
223  *         CopyMetaFile32W   (GDI32.24)
224  */
225 HMETAFILE32 WINAPI CopyMetaFile32W( HMETAFILE32 hSrcMetaFile,
226                                     LPCWSTR lpFilename )
227 {
228     LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
229     HMETAFILE32 ret = CopyMetaFile32A( hSrcMetaFile, p );
230     HeapFree( GetProcessHeap(), 0, p );
231     return ret;
232 }
233
234
235 /******************************************************************
236  *         IsValidMetaFile   (GDI.410)
237  *
238  *  Attempts to check if a given metafile is correctly formatted.
239  *  Currently, the only things verified are several properties of the
240  *  header.
241  *
242  * RETURNS
243  *  TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
244  *
245  * BUGS
246  *  This is not exactly what windows does, see _Undocumented_Windows_
247  *  for details.
248  */
249
250 BOOL16 WINAPI IsValidMetaFile(HMETAFILE16 hmf)
251 {
252     BOOL16 resu=FALSE;
253     METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
254     if (mh) {
255       if (mh->mtType == 1 || mh->mtType == 0) 
256         if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
257           if (mh->mtVersion == MFVERSION)
258             resu=TRUE;
259       GlobalUnlock16(hmf);
260     }
261     TRACE(metafile,"IsValidMetaFile %x => %d\n",hmf,resu);
262     return resu;         
263 }
264
265
266 /******************************************************************
267  *         PlayMetaFile16   (GDI.123)
268  *
269  */
270 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
271 {
272     return PlayMetaFile32( hdc, hmf );
273 }
274
275 /******************************************************************
276  *         PlayMetaFile32   (GDI32.265)
277  *
278  *  Renders the metafile specified by hmf in the DC specified by
279  *  hdc. Returns FALSE on failure, TRUE on success.
280  */
281 BOOL32 WINAPI PlayMetaFile32( 
282                              HDC32 hdc, /* handle of DC to render in */
283                              HMETAFILE32 hmf /* handle of metafile to render */
284 )
285 {
286     METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
287     METARECORD *mr;
288     HANDLETABLE16 *ht;
289     HGLOBAL16 hHT;
290     int offset = 0;
291     WORD i;
292     HPEN32 hPen;
293     HBRUSH32 hBrush;
294     HFONT32 hFont;
295     DC *dc;
296     
297     TRACE(metafile,"(%04x %04x)\n",hdc,hmf);
298     if (!mh) return FALSE;
299
300     /* save the current pen, brush and font */
301     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
302     hPen = dc->w.hPen;
303     hBrush = dc->w.hBrush;
304     hFont = dc->w.hFont;
305     GDI_HEAP_UNLOCK(hdc);
306     /* create the handle table */
307     hHT = GlobalAlloc16(GMEM_MOVEABLE|GMEM_ZEROINIT,
308                       sizeof(HANDLETABLE16) * mh->mtNoObjects);
309     ht = (HANDLETABLE16 *)GlobalLock16(hHT);
310
311     
312     /* loop through metafile playing records */
313     offset = mh->mtHeaderSize * 2;
314     while (offset < mh->mtSize * 2)
315     {
316         mr = (METARECORD *)((char *)mh + offset);
317         TRACE(metafile,"offset=%04x,size=%08lx\n",
318             offset, mr->rdSize);
319         if (!mr->rdSize) {
320             TRACE(metafile,"Entry got size 0 at offset %d, total mf length is %ld\n",
321                 offset,mh->mtSize*2);
322                 break; /* would loop endlessly otherwise */
323         }
324         offset += mr->rdSize * 2;
325         PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
326     }
327
328     SelectObject32(hdc, hBrush);
329     SelectObject32(hdc, hPen);
330     SelectObject32(hdc, hFont);
331
332     /* free objects in handle table */
333     for(i = 0; i < mh->mtNoObjects; i++)
334       if(*(ht->objectHandle + i) != 0)
335         DeleteObject32(*(ht->objectHandle + i));
336     
337     /* free handle table */
338     GlobalFree16(hHT);
339
340     return TRUE;
341 }
342
343
344 /******************************************************************
345  *            EnumMetaFile16   (GDI.175)
346  *
347  *  Loop through the metafile records in hmf, calling the user-specified
348  *  function for each one, stopping when the user's function returns FALSE
349  *  (which is considered to be failure)
350  *  or when no records are left (which is considered to be success). 
351  *
352  * RETURNS
353  *  TRUE on success, FALSE on failure.
354  * 
355  * HISTORY
356  *   Niels de carpentier, april 1996
357  */
358 BOOL16 WINAPI EnumMetaFile16( 
359                              HDC16 hdc, 
360                              HMETAFILE16 hmf,
361                              MFENUMPROC16 lpEnumFunc, 
362                              LPARAM lpData 
363 )
364 {
365     METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
366     METARECORD *mr;
367     HANDLETABLE16 *ht;
368     HGLOBAL16 hHT;
369     SEGPTR spht;
370     int offset = 0;
371     WORD i, seg;
372     HPEN32 hPen;
373     HBRUSH32 hBrush;
374     HFONT32 hFont;
375     DC *dc;
376     BOOL16 result = TRUE;
377     
378     TRACE(metafile,"(%04x, %04x, %08lx, %08lx)\n",
379                      hdc, hmf, (DWORD)lpEnumFunc, lpData);
380
381     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
382     hPen = dc->w.hPen;
383     hBrush = dc->w.hBrush;
384     hFont = dc->w.hFont;
385     GDI_HEAP_UNLOCK(hdc);
386
387     /* create the handle table */
388     
389     hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
390                      sizeof(HANDLETABLE16) * mh->mtNoObjects);
391     spht = WIN16_GlobalLock16(hHT);
392    
393     seg = GlobalHandleToSel(hmf);
394     offset = mh->mtHeaderSize * 2;
395     
396     /* loop through metafile records */
397     
398     while (offset < (mh->mtSize * 2))
399     {
400         mr = (METARECORD *)((char *)mh + offset);
401         if (!lpEnumFunc( hdc, (HANDLETABLE16 *)spht,
402                          (METARECORD *) PTR_SEG_OFF_TO_HUGEPTR(seg, offset),
403                          mh->mtNoObjects, (LONG)lpData ))
404         {
405             result = FALSE;
406             break;
407         }
408         
409
410         offset += (mr->rdSize * 2);
411     }
412
413     SelectObject32(hdc, hBrush);
414     SelectObject32(hdc, hPen);
415     SelectObject32(hdc, hFont);
416
417     ht = (HANDLETABLE16 *)GlobalLock16(hHT);
418
419     /* free objects in handle table */
420     for(i = 0; i < mh->mtNoObjects; i++)
421       if(*(ht->objectHandle + i) != 0)
422         DeleteObject32(*(ht->objectHandle + i));
423
424     /* free handle table */
425     GlobalFree16(hHT);
426     GlobalUnlock16(hmf);
427     return result;
428 }
429
430 BOOL32 WINAPI EnumMetaFile32( 
431                              HDC32 hdc, 
432                              HMETAFILE32 hmf,
433                              MFENUMPROC32 lpEnumFunc, 
434                              LPARAM lpData 
435 ) {
436     METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
437     METARECORD *mr;
438     HANDLETABLE32 *ht;
439     BOOL32 result = TRUE;
440     int i, offset = 0;
441     DC *dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
442     HPEN32 hPen;
443     HBRUSH32 hBrush;
444     HFONT32 hFont;
445
446     TRACE(metafile,"(%08x,%08x,%p,%p)\n",
447                      hdc, hmf, lpEnumFunc, (void*)lpData);
448     if (!mh) return 0;
449
450     /* save the current pen, brush and font */
451     if (!dc) return 0;
452     hPen = dc->w.hPen;
453     hBrush = dc->w.hBrush;
454     hFont = dc->w.hFont;
455     GDI_HEAP_UNLOCK(hdc);
456
457
458     ht = (HANDLETABLE32 *) GlobalAlloc32(GPTR, 
459                             sizeof(HANDLETABLE32) * mh->mtNoObjects);
460     
461     /* loop through metafile records */
462     offset = mh->mtHeaderSize * 2;
463     
464     while (offset < (mh->mtSize * 2))
465     {
466         mr = (METARECORD *)((char *)mh + offset);
467         if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
468         {
469             result = FALSE;
470             break;
471         }
472         
473         offset += (mr->rdSize * 2);
474     }
475
476     /* restore pen, brush and font */
477     SelectObject32(hdc, hBrush);
478     SelectObject32(hdc, hPen);
479     SelectObject32(hdc, hFont);
480
481     /* free objects in handle table */
482     for(i = 0; i < mh->mtNoObjects; i++)
483       if(*(ht->objectHandle + i) != 0)
484         DeleteObject32(*(ht->objectHandle + i));
485
486     /* free handle table */
487     GlobalFree32((HGLOBAL32)ht);
488     GlobalUnlock16(hmf);
489     return result;
490 }
491
492 static BOOL32 MF_Meta_CreateRegion( METARECORD *mr, HRGN32 hrgn );
493
494 /******************************************************************
495  *             PlayMetaFileRecord16   (GDI.176)
496  *
497  *   Render a single metafile record specified by *mr in the DC hdc, while
498  *   using the handle table *ht, of length nHandles, 
499  *   to store metafile objects.
500  *
501  * BUGS
502  *  The following metafile records are unimplemented:
503  *
504  *  FRAMEREGION, DRAWTEXT, SETDIBTODEV, ANIMATEPALETTE, SETPALENTRIES,
505  *  RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
506  *  ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
507  *
508  */
509 void WINAPI PlayMetaFileRecord16( 
510             HDC16 hdc, /* DC to render metafile into */
511             HANDLETABLE16 *ht, /* pointer to handle table for metafile objects */
512             METARECORD *mr, /* pointer to metafile record to render */
513             UINT16 nHandles /* size of handle table */
514 ) {
515     short s1;
516     HANDLE16 hndl;
517     char *ptr;
518     BITMAPINFOHEADER *infohdr;
519
520     TRACE(metafile,"(%04x %08lx %08lx %04x) function %04x\n",
521                  hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
522     
523     switch (mr->rdFunction)
524     {
525     case META_EOF:
526       break;
527
528     case META_DELETEOBJECT:
529       DeleteObject32(*(ht->objectHandle + *(mr->rdParm)));
530       *(ht->objectHandle + *(mr->rdParm)) = 0;
531       break;
532
533     case META_SETBKCOLOR:
534         SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
535         break;
536
537     case META_SETBKMODE:
538         SetBkMode16(hdc, *(mr->rdParm));
539         break;
540
541     case META_SETMAPMODE:
542         SetMapMode16(hdc, *(mr->rdParm));
543         break;
544
545     case META_SETROP2:
546         SetROP216(hdc, *(mr->rdParm));
547         break;
548
549     case META_SETRELABS:
550         SetRelAbs16(hdc, *(mr->rdParm));
551         break;
552
553     case META_SETPOLYFILLMODE:
554         SetPolyFillMode16(hdc, *(mr->rdParm));
555         break;
556
557     case META_SETSTRETCHBLTMODE:
558         SetStretchBltMode16(hdc, *(mr->rdParm));
559         break;
560
561     case META_SETTEXTCOLOR:
562         SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
563         break;
564
565     case META_SETWINDOWORG:
566         SetWindowOrg(hdc, *(mr->rdParm + 1), *(mr->rdParm));
567         break;
568
569     case META_SETWINDOWEXT:
570         SetWindowExt(hdc, *(mr->rdParm + 1), *(mr->rdParm));
571         break;
572
573     case META_SETVIEWPORTORG:
574         SetViewportOrg(hdc, *(mr->rdParm + 1), *(mr->rdParm));
575         break;
576
577     case META_SETVIEWPORTEXT:
578         SetViewportExt(hdc, *(mr->rdParm + 1), *(mr->rdParm));
579         break;
580
581     case META_OFFSETWINDOWORG:
582         OffsetWindowOrg(hdc, *(mr->rdParm + 1), *(mr->rdParm));
583         break;
584
585     case META_SCALEWINDOWEXT:
586         ScaleWindowExt(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
587                        *(mr->rdParm + 1), *(mr->rdParm));
588         break;
589
590     case META_OFFSETVIEWPORTORG:
591         OffsetViewportOrg(hdc, *(mr->rdParm + 1), *(mr->rdParm));
592         break;
593
594     case META_SCALEVIEWPORTEXT:
595         ScaleViewportExt(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
596                          *(mr->rdParm + 1), *(mr->rdParm));
597         break;
598
599     case META_LINETO:
600         LineTo32(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
601         break;
602
603     case META_MOVETO:
604         MoveTo(hdc, *(mr->rdParm + 1), *(mr->rdParm));
605         break;
606
607     case META_EXCLUDECLIPRECT:
608         ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
609                            *(mr->rdParm + 1), *(mr->rdParm) );
610         break;
611
612     case META_INTERSECTCLIPRECT:
613         IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
614                              *(mr->rdParm + 1), *(mr->rdParm) );
615         break;
616
617     case META_ARC:
618         Arc32(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
619               (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
620               (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
621              (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
622         break;
623
624     case META_ELLIPSE:
625         Ellipse32(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
626                   (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
627         break;
628
629     case META_FLOODFILL:
630         FloodFill32(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
631                     MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
632         break;
633
634     case META_PIE:
635         Pie32(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
636               (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
637               (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
638              (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
639         break;
640
641     case META_RECTANGLE:
642         Rectangle32(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
643                     (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
644         break;
645
646     case META_ROUNDRECT:
647         RoundRect32(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
648                     (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
649                     (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
650         break;
651
652     case META_PATBLT:
653         PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
654                  *(mr->rdParm + 3), *(mr->rdParm + 2),
655                  MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
656         break;
657
658     case META_SAVEDC:
659         SaveDC32(hdc);
660         break;
661
662     case META_SETPIXEL:
663         SetPixel32(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
664                    MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
665         break;
666
667     case META_OFFSETCLIPRGN:
668         OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
669         break;
670
671     case META_TEXTOUT:
672         s1 = *(mr->rdParm);
673         TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
674                   *(mr->rdParm + ((s1 + 1) >> 1) + 1), 
675                   (char *)(mr->rdParm + 1), s1);
676         break;
677
678     case META_POLYGON:
679         Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
680         break;
681
682     case META_POLYPOLYGON:
683       PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
684                     (LPINT16)(mr->rdParm + 1), *(mr->rdParm)); 
685       break;
686
687     case META_POLYLINE:
688         Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
689         break;
690
691     case META_RESTOREDC:
692         RestoreDC32(hdc, (INT16)*(mr->rdParm));
693         break;
694
695     case META_SELECTOBJECT:
696         SelectObject32(hdc, *(ht->objectHandle + *(mr->rdParm)));
697         break;
698
699     case META_CHORD:
700         Chord32(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
701                 (INT16)*(mr->rdParm+5), (INT16)*(mr->rdParm + 4),
702                 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
703                (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
704         break;
705
706     case META_CREATEPATTERNBRUSH:
707         switch (*(mr->rdParm))
708         {
709         case BS_PATTERN:
710             infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
711             MF_AddHandle(ht, nHandles,
712                          CreatePatternBrush32(CreateBitmap32(infohdr->biWidth, 
713                                       infohdr->biHeight, 
714                                       infohdr->biPlanes, 
715                                       infohdr->biBitCount,
716                                       (LPSTR)(mr->rdParm + 
717                                       (sizeof(BITMAPINFOHEADER) / 2) + 4))));
718             break;
719
720         case BS_DIBPATTERN:
721             s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
722             hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
723             ptr = GlobalLock16(hndl);
724             memcpy(ptr, mr->rdParm + 2, s1);
725             GlobalUnlock16(hndl);
726             MF_AddHandle(ht, nHandles,
727                          CreateDIBPatternBrush32(hndl, *(mr->rdParm + 1)));
728             GlobalFree16(hndl);
729         }
730         break;
731         
732     case META_CREATEPENINDIRECT:
733         MF_AddHandle(ht, nHandles, 
734                      CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
735         break;
736
737     case META_CREATEFONTINDIRECT:
738         MF_AddHandle(ht, nHandles, 
739                      CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
740         break;
741
742     case META_CREATEBRUSHINDIRECT:
743         MF_AddHandle(ht, nHandles, 
744                      CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
745         break;
746
747     /* W. Magro: Some new metafile operations.  Not all debugged. */
748     case META_CREATEPALETTE:
749         MF_AddHandle(ht, nHandles, 
750                      CreatePalette16((LPLOGPALETTE)mr->rdParm));
751         break;
752
753     case META_SETTEXTALIGN:
754         SetTextAlign16(hdc, *(mr->rdParm));
755         break;
756
757     case META_SELECTPALETTE:
758         SelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),*(mr->rdParm));
759         break;
760
761     case META_SETMAPPERFLAGS:
762         SetMapperFlags16(hdc, *(mr->rdParm));
763         break;
764
765     case META_REALIZEPALETTE:
766         RealizePalette16(hdc);
767         break;
768
769     case META_ESCAPE:
770         FIXME(metafile, "META_ESCAPE unimplemented.\n");
771         break;
772
773         /* --- Begin of fixed or new metafile operations. July 1996 ----*/
774     case META_EXTTEXTOUT:
775       {
776         LPINT16 dxx;
777         LPSTR sot; 
778         DWORD len;
779
780         s1 = mr->rdParm[2];                              /* String length */
781         len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
782          + sizeof(UINT16) +  (mr->rdParm[3] ? sizeof(RECT16) : 0);  /* rec len without dx array */
783
784         sot= (LPSTR)&mr->rdParm[4];                     /* start_of_text */
785         if (mr->rdParm[3])
786            sot+=sizeof(RECT16);                         /* there is a rectangle, so add offset */
787          
788         if (mr->rdSize == len / 2)
789           dxx = NULL;                                   /* determine if array present */
790         else 
791           if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
792             dxx = (LPINT16)(sot+(((s1+1)>>1)*2));          
793           else 
794           {
795            TRACE(metafile,"%s  len: %ld\n",
796              sot,mr->rdSize);
797            WARN(metafile,
798              "Please report: PlayMetaFile/ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
799                    len,s1,mr->rdSize,mr->rdParm[3]);
800            dxx = NULL; /* should't happen -- but if, we continue with NULL [for workaround] */
801           }
802         ExtTextOut16( hdc, mr->rdParm[1],              /* X position */
803                            mr->rdParm[0],              /* Y position */
804                            mr->rdParm[3],              /* options */
805                            mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL,  /* rectangle */
806                            sot,                         /* string */
807                            s1, dxx);                    /* length, dx array */
808         if (dxx)                      
809           TRACE(metafile,"%s  len: %ld  dx0: %d\n",
810             sot,mr->rdSize,dxx[0]);
811        }
812        break;
813     
814     case META_STRETCHDIB:
815       {
816        LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
817        LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
818        StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
819                        mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
820                        mr->rdParm[4],mr->rdParm[3],bits,info,
821                        mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
822       }
823       break;
824
825     case META_DIBSTRETCHBLT:
826       {
827        LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]); 
828        LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
829        StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
830                        mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
831                        mr->rdParm[3],mr->rdParm[2],bits,info,
832                        DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
833       }
834       break;              
835
836     case META_STRETCHBLT:
837       {
838        HDC16 hdcSrc=CreateCompatibleDC16(hdc);
839        HBITMAP32 hbitmap=CreateBitmap32(mr->rdParm[10], /*Width */
840                                         mr->rdParm[11], /*Height*/
841                                         mr->rdParm[13], /*Planes*/
842                                         mr->rdParm[14], /*BitsPixel*/
843                                         (LPSTR)&mr->rdParm[15]);  /*bits*/
844        SelectObject32(hdcSrc,hbitmap);
845        StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
846                     mr->rdParm[7],mr->rdParm[6],
847                     hdcSrc,mr->rdParm[5],mr->rdParm[4],
848                     mr->rdParm[3],mr->rdParm[2],
849                     MAKELONG(mr->rdParm[0],mr->rdParm[1]));
850        DeleteDC32(hdcSrc);                  
851       }
852       break;
853
854     case META_BITBLT:            /* <-- not yet debugged */
855       {
856        HDC16 hdcSrc=CreateCompatibleDC16(hdc);
857        HBITMAP32 hbitmap=CreateBitmap32(mr->rdParm[7]/*Width */,
858                                         mr->rdParm[8]/*Height*/,
859                                         mr->rdParm[10]/*Planes*/,
860                                         mr->rdParm[11]/*BitsPixel*/,
861                                         (LPSTR)&mr->rdParm[12]/*bits*/);
862        SelectObject32(hdcSrc,hbitmap);
863        BitBlt32(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
864                 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
865                 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
866                 MAKELONG(0,mr->rdParm[0]));
867        DeleteDC32(hdcSrc);                  
868       }
869       break;
870
871        /* --- Begin of new metafile operations. April, 1997 (ak) ----*/
872     case META_CREATEREGION:
873       {
874         HRGN32 hrgn = CreateRectRgn32(0,0,0,0);
875  
876         MF_Meta_CreateRegion(mr, hrgn);
877         MF_AddHandle(ht, nHandles, hrgn);
878       }
879       break;
880
881      case META_FILLREGION:
882         FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)),
883                        *(ht->objectHandle + *(mr->rdParm+1)));
884         break;
885
886      case META_INVERTREGION:
887         InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
888         break; 
889
890      case META_PAINTREGION:
891         PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
892         break;
893
894      case META_SELECTCLIPREGION:
895         SelectClipRgn32(hdc, *(ht->objectHandle + *(mr->rdParm)));
896         break;
897
898      case META_DIBCREATEPATTERNBRUSH:
899         /*  *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN: but there's no difference */
900         TRACE(metafile,"%d\n",*(mr->rdParm));
901         s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
902         hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
903         ptr = GlobalLock16(hndl);
904         memcpy(ptr, mr->rdParm + 2, s1);
905         GlobalUnlock16(hndl);
906         MF_AddHandle(ht, nHandles,CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
907         GlobalFree16(hndl);
908         break;
909
910      case META_DIBBITBLT:
911         {
912          LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
913          LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
914          StretchDIBits16(hdc,mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
915                        mr->rdParm[4],mr->rdParm[3],mr->rdParm[2],
916                        mr->rdParm[5],mr->rdParm[4],bits,info,
917                        DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
918         }
919         break;  
920        
921      case META_SETTEXTCHAREXTRA:
922             SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
923             break;
924
925      case META_SETTEXTJUSTIFICATION:
926         SetTextJustification32(hdc, *(mr->rdParm + 1), *(mr->rdParm));
927         break;
928
929 #define META_UNIMP(x) case x: FIXME(metafile, "PlayMetaFileRecord:record type "#x" not implemented.\n");break;
930     META_UNIMP(META_FRAMEREGION)
931     META_UNIMP(META_DRAWTEXT)
932     META_UNIMP(META_SETDIBTODEV)
933     META_UNIMP(META_ANIMATEPALETTE)
934     META_UNIMP(META_SETPALENTRIES)
935     META_UNIMP(META_RESIZEPALETTE)
936     META_UNIMP(META_EXTFLOODFILL)
937     META_UNIMP(META_RESETDC)
938     META_UNIMP(META_STARTDOC)
939     META_UNIMP(META_STARTPAGE)
940     META_UNIMP(META_ENDPAGE)
941     META_UNIMP(META_ABORTDOC)
942     META_UNIMP(META_ENDDOC)
943     META_UNIMP(META_CREATEBRUSH)
944     META_UNIMP(META_CREATEBITMAPINDIRECT)
945     META_UNIMP(META_CREATEBITMAP)
946 #undef META_UNIMP
947
948     default:
949         WARN(metafile, "PlayMetaFileRecord: Unknown record type %x\n",
950                                               mr->rdFunction);
951     }
952 }
953
954
955 BOOL32 WINAPI PlayMetaFileRecord32( 
956      HDC32 hdc, 
957      HANDLETABLE32 *handletable, 
958      METARECORD *metarecord, 
959      UINT32 handles  
960     )
961 {
962   HANDLETABLE16 * ht = (void *)GlobalAlloc32(GPTR, 
963                                handles*sizeof(HANDLETABLE16));
964   int i = 0;
965   TRACE(metafile, "(%08x,%p,%p,%d)\n", hdc, handletable, metarecord, handles); 
966   for (i=0; i<handles; i++)  
967     ht->objectHandle[i] =  handletable->objectHandle[i];
968   PlayMetaFileRecord16(hdc, ht, metarecord, handles);
969   for (i=0; i<handles; i++) 
970     handletable->objectHandle[i] = ht->objectHandle[i];
971   GlobalFree32((HGLOBAL32)ht);
972   return TRUE;
973 }
974
975 /******************************************************************
976  *         GetMetaFileBits   (GDI.159)
977  *
978  * Trade in a metafile object handle for a handle to the metafile memory.
979  *
980  */
981
982 HGLOBAL16 WINAPI GetMetaFileBits(
983                                  HMETAFILE16 hmf /* metafile handle */
984                                  )
985 {
986     TRACE(metafile,"hMem out: %04x\n", hmf);
987     return hmf;
988 }
989
990 /******************************************************************
991  *         SetMetaFileBits   (GDI.160)
992  *
993  * Trade in a metafile memory handle for a handle to a metafile object.
994  * The memory region should hold a proper metafile, otherwise
995  * problems will occur when it is used. Validity of the memory is not
996  * checked. The function is essentially just the identity function.
997  */
998 HMETAFILE16 WINAPI SetMetaFileBits( 
999                                    HGLOBAL16 hMem 
1000                         /* handle to a memory region holding a metafile */
1001 )
1002 {
1003     TRACE(metafile,"hmf out: %04x\n", hMem);
1004
1005     return hMem;
1006 }
1007
1008 /******************************************************************
1009  *         SetMetaFileBitsBetter   (GDI.196)
1010  *
1011  * Trade in a metafile memory handle for a handle to a metafile object,
1012  * making a cursory check (using IsValidMetaFile()) that the memory
1013  * handle points to a valid metafile.
1014  *
1015  * RETURNS
1016  *  Handle to a metafile on success, NULL on failure..
1017  */
1018 HMETAFILE16 WINAPI SetMetaFileBitsBetter( HMETAFILE16 hMeta )
1019 {
1020    if( IsValidMetaFile( hMeta ) )
1021        return (HMETAFILE16)GlobalReAlloc16( hMeta, 0, 
1022                            GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1023    return (HMETAFILE16)0;
1024 }
1025
1026 /******************************************************************
1027  *         SetMetaFileBitsEx    (GDI32.323)
1028  * 
1029  *  Create a metafile from raw data. No checking of the data is performed.
1030  *  Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1031  */
1032 HMETAFILE32 WINAPI SetMetaFileBitsEx( 
1033      UINT32 size, /* size of metafile, in bytes */
1034      const BYTE *lpData /* pointer to metafile data */  
1035     )
1036 {
1037   HMETAFILE32 hmf = GlobalAlloc16(GHND, size);
1038   BYTE *p = GlobalLock16(hmf) ;
1039   TRACE(metafile, "(%d,%p) returning %08x\n", size, lpData, hmf);
1040   if (!hmf || !p) return 0;
1041   memcpy(p, lpData, size);
1042   GlobalUnlock16(hmf);
1043   return hmf;
1044 }
1045
1046 /*****************************************************************
1047  *  GetMetaFileBitsEx     (GDI32.198)  Get raw metafile data
1048  * 
1049  *  Copies the data from metafile _hmf_ into the buffer _buf_.
1050  *  If _buf_ is zero, returns size of buffer required. Otherwise,
1051  *  returns number of bytes copied.
1052  */
1053 UINT32 WINAPI GetMetaFileBitsEx( 
1054      HMETAFILE32 hmf, /* metafile */
1055      UINT32 nSize, /* size of buf */ 
1056      LPVOID buf   /* buffer to receive raw metafile data */  
1057 ) {
1058   METAHEADER *h = GlobalLock16(hmf);
1059   UINT32 mfSize;
1060
1061   TRACE(metafile, "(%08x,%d,%p)\n", hmf, nSize, buf);
1062   if (!h) return 0;  /* FIXME: error code */
1063   mfSize = h->mtSize * 2;
1064   if (!buf) {
1065     GlobalUnlock16(hmf);
1066     TRACE(metafile,"returning size %d\n", mfSize);
1067     return mfSize;
1068   }
1069   if(mfSize > nSize) mfSize = nSize;
1070   memmove(buf, h, mfSize);
1071   GlobalUnlock16(hmf);
1072   return mfSize;
1073 }
1074
1075 /******************************************************************
1076  *         GetWinMetaFileBits [GDI32.241]
1077  */
1078 UINT32 WINAPI GetWinMetaFileBits(HENHMETAFILE32 hemf,
1079                                 UINT32 cbBuffer, LPBYTE lpbBuffer,
1080                                 INT32 fnMapMode, HDC32 hdcRef)
1081 {
1082   FIXME(metafile, "(%d,%d,%p,%d,%d): stub\n",
1083         hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1084   return 0;
1085 }
1086
1087 /******************************************************************
1088  *         MF_Meta_CreateRegion
1089  *
1090  *  Handles META_CREATEREGION for PlayMetaFileRecord().
1091  */
1092
1093 /*
1094  *      The layout of the record looks something like this:
1095  *       
1096  *       rdParm meaning
1097  *       0              Always 0?
1098  *       1              Always 6?
1099  *       2              Looks like a handle? - not constant
1100  *       3              0 or 1 ??
1101  *       4              Total number of bytes
1102  *       5              No. of seperate bands = n [see below]
1103  *       6              Largest number of x co-ords in a band
1104  *       7-10           Bounding box x1 y1 x2 y2
1105  *       11-...         n bands
1106  *
1107  *       Regions are divided into bands that are uniform in the
1108  *       y-direction. Each band consists of pairs of on/off x-coords and is
1109  *       written as
1110  *              m y0 y1 x1 x2 x3 ... xm m
1111  *       into successive rdParm[]s.
1112  *
1113  *       This is probably just a dump of the internal RGNOBJ?
1114  *
1115  *       HDMD - 18/12/97
1116  *
1117  */
1118
1119 static BOOL32 MF_Meta_CreateRegion( METARECORD *mr, HRGN32 hrgn )
1120 {
1121     WORD band, pair;
1122     WORD *start, *end;
1123     INT16 y0, y1;
1124     HRGN32 hrgn2 = CreateRectRgn32( 0, 0, 0, 0 );
1125
1126     for(band  = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1127                                                 band++, start = end + 1) {
1128         if(*start / 2 != (*start + 1) / 2) {
1129             WARN(metafile, "Delimiter not even.\n");
1130             DeleteObject32( hrgn2 );
1131             return FALSE;
1132         }
1133
1134         end = start + *start + 3;
1135         if(end > (WORD *)mr + mr->rdSize) {
1136             WARN(metafile, "End points outside record.\n");
1137             DeleteObject32( hrgn2 );
1138             return FALSE;
1139         }
1140
1141         if(*start != *end) {
1142             WARN(metafile, "Mismatched delimiters.\n");
1143             DeleteObject32( hrgn2 );
1144             return FALSE;
1145         }
1146
1147         y0 = *(INT16 *)(start + 1);
1148         y1 = *(INT16 *)(start + 2);
1149         for(pair = 0; pair < *start / 2; pair++) {
1150             SetRectRgn32( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1151                                  *(INT16 *)(start + 4 + 2*pair), y1 );
1152             CombineRgn32(hrgn, hrgn, hrgn2, RGN_OR);
1153         }
1154     }
1155     DeleteObject32( hrgn2 );
1156     return TRUE;
1157  }
1158  
1159
1160 /******************************************************************
1161  *         MF_WriteRecord
1162  *
1163  * Warning: this function can change the metafile handle.
1164  */
1165
1166 static BOOL32 MF_WriteRecord( DC *dc, METARECORD *mr, DWORD rlen)
1167 {
1168     DWORD len;
1169     METAHEADER *mh;
1170     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
1171
1172     switch(physDev->mh->mtType)
1173     {
1174     case METAFILE_MEMORY:
1175         len = physDev->mh->mtSize * 2 + rlen;
1176         mh = HeapReAlloc( SystemHeap, 0, physDev->mh, len );
1177         if (!mh) return FALSE;
1178         physDev->mh = mh;
1179         memcpy((WORD *)physDev->mh + physDev->mh->mtSize, mr, rlen);
1180         break;
1181     case METAFILE_DISK:
1182         TRACE(metafile,"Writing record to disk\n");
1183         if (_lwrite32(physDev->mh->mtNoParameters, (char *)mr, rlen) == -1)
1184             return FALSE;
1185         break;
1186     default:
1187         ERR(metafile, "Unknown metafile type %d\n", physDev->mh->mtType );
1188         return FALSE;
1189     }
1190
1191     physDev->mh->mtSize += rlen / 2;
1192     physDev->mh->mtMaxRecord = MAX(physDev->mh->mtMaxRecord, rlen / 2);
1193     return TRUE;
1194 }
1195
1196
1197 /******************************************************************
1198  *         MF_MetaParam0
1199  */
1200
1201 BOOL32 MF_MetaParam0(DC *dc, short func)
1202 {
1203     char buffer[8];
1204     METARECORD *mr = (METARECORD *)&buffer;
1205     
1206     mr->rdSize = 3;
1207     mr->rdFunction = func;
1208     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1209 }
1210
1211
1212 /******************************************************************
1213  *         MF_MetaParam1
1214  */
1215 BOOL32 MF_MetaParam1(DC *dc, short func, short param1)
1216 {
1217     char buffer[8];
1218     METARECORD *mr = (METARECORD *)&buffer;
1219     
1220     mr->rdSize = 4;
1221     mr->rdFunction = func;
1222     *(mr->rdParm) = param1;
1223     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1224 }
1225
1226
1227 /******************************************************************
1228  *         MF_MetaParam2
1229  */
1230 BOOL32 MF_MetaParam2(DC *dc, short func, short param1, short param2)
1231 {
1232     char buffer[10];
1233     METARECORD *mr = (METARECORD *)&buffer;
1234     
1235     mr->rdSize = 5;
1236     mr->rdFunction = func;
1237     *(mr->rdParm) = param2;
1238     *(mr->rdParm + 1) = param1;
1239     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1240 }
1241
1242
1243 /******************************************************************
1244  *         MF_MetaParam4
1245  */
1246
1247 BOOL32 MF_MetaParam4(DC *dc, short func, short param1, short param2, 
1248                    short param3, short param4)
1249 {
1250     char buffer[14];
1251     METARECORD *mr = (METARECORD *)&buffer;
1252     
1253     mr->rdSize = 7;
1254     mr->rdFunction = func;
1255     *(mr->rdParm) = param4;
1256     *(mr->rdParm + 1) = param3;
1257     *(mr->rdParm + 2) = param2;
1258     *(mr->rdParm + 3) = param1;
1259     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1260 }
1261
1262
1263 /******************************************************************
1264  *         MF_MetaParam6
1265  */
1266
1267 BOOL32 MF_MetaParam6(DC *dc, short func, short param1, short param2, 
1268                    short param3, short param4, short param5, short param6)
1269 {
1270     char buffer[18];
1271     METARECORD *mr = (METARECORD *)&buffer;
1272     
1273     mr->rdSize = 9;
1274     mr->rdFunction = func;
1275     *(mr->rdParm) = param6;
1276     *(mr->rdParm + 1) = param5;
1277     *(mr->rdParm + 2) = param4;
1278     *(mr->rdParm + 3) = param3;
1279     *(mr->rdParm + 4) = param2;
1280     *(mr->rdParm + 5) = param1;
1281     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1282 }
1283
1284
1285 /******************************************************************
1286  *         MF_MetaParam8
1287  */
1288 BOOL32 MF_MetaParam8(DC *dc, short func, short param1, short param2, 
1289                    short param3, short param4, short param5,
1290                    short param6, short param7, short param8)
1291 {
1292     char buffer[22];
1293     METARECORD *mr = (METARECORD *)&buffer;
1294     
1295     mr->rdSize = 11;
1296     mr->rdFunction = func;
1297     *(mr->rdParm) = param8;
1298     *(mr->rdParm + 1) = param7;
1299     *(mr->rdParm + 2) = param6;
1300     *(mr->rdParm + 3) = param5;
1301     *(mr->rdParm + 4) = param4;
1302     *(mr->rdParm + 5) = param3;
1303     *(mr->rdParm + 6) = param2;
1304     *(mr->rdParm + 7) = param1;
1305     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1306 }
1307
1308
1309 /******************************************************************
1310  *         MF_CreateBrushIndirect
1311  */
1312
1313 BOOL32 MF_CreateBrushIndirect(DC *dc, HBRUSH16 hBrush, LOGBRUSH16 *logbrush)
1314 {
1315     int index;
1316     char buffer[sizeof(METARECORD) - 2 + sizeof(*logbrush)];
1317     METARECORD *mr = (METARECORD *)&buffer;
1318
1319     mr->rdSize = (sizeof(METARECORD) + sizeof(*logbrush) - 2) / 2;
1320     mr->rdFunction = META_CREATEBRUSHINDIRECT;
1321     memcpy(&(mr->rdParm), logbrush, sizeof(*logbrush));
1322     if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1323
1324     mr->rdSize = sizeof(METARECORD) / 2;
1325     mr->rdFunction = META_SELECTOBJECT;
1326
1327     if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1328     *(mr->rdParm) = index;
1329     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1330 }
1331
1332
1333 /******************************************************************
1334  *         MF_CreatePatternBrush
1335  */
1336
1337 BOOL32 MF_CreatePatternBrush(DC *dc, HBRUSH16 hBrush, LOGBRUSH16 *logbrush)
1338 {
1339     DWORD len, bmSize, biSize;
1340     HGLOBAL16 hmr;
1341     METARECORD *mr;
1342     BITMAPOBJ *bmp;
1343     BITMAPINFO *info;
1344     BITMAPINFOHEADER *infohdr;
1345     int index;
1346     char buffer[sizeof(METARECORD)];
1347
1348     switch (logbrush->lbStyle)
1349     {
1350     case BS_PATTERN:
1351         bmp = (BITMAPOBJ *)GDI_GetObjPtr((HGDIOBJ16)logbrush->lbHatch, BITMAP_MAGIC);
1352         if (!bmp) return FALSE;
1353         len = sizeof(METARECORD) + sizeof(BITMAPINFOHEADER) + 
1354               (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 6;
1355         if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1356           {
1357             GDI_HEAP_UNLOCK((HGDIOBJ16)logbrush->lbHatch);
1358             return FALSE;
1359           }
1360         mr = (METARECORD *)GlobalLock16(hmr);
1361         memset(mr, 0, len);
1362         mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1363         mr->rdSize = len / 2;
1364         *(mr->rdParm) = logbrush->lbStyle;
1365         *(mr->rdParm + 1) = DIB_RGB_COLORS;
1366         infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
1367         infohdr->biSize = sizeof(BITMAPINFOHEADER);
1368         infohdr->biWidth = bmp->bitmap.bmWidth;
1369         infohdr->biHeight = bmp->bitmap.bmHeight;
1370         infohdr->biPlanes = bmp->bitmap.bmPlanes;
1371         infohdr->biBitCount = bmp->bitmap.bmBitsPixel;
1372         memcpy(mr->rdParm + (sizeof(BITMAPINFOHEADER) / 2) + 4,
1373                PTR_SEG_TO_LIN(bmp->bitmap.bmBits),
1374                bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes);
1375         GDI_HEAP_UNLOCK(logbrush->lbHatch);
1376         break;
1377
1378     case BS_DIBPATTERN:
1379         info = (BITMAPINFO *)GlobalLock16((HGLOBAL16)logbrush->lbHatch);
1380         if (info->bmiHeader.biCompression)
1381             bmSize = info->bmiHeader.biSizeImage;
1382         else
1383             bmSize = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount 
1384                     + 31) / 32 * 8 * info->bmiHeader.biHeight;
1385         biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush->lbColor)); 
1386         len = sizeof(METARECORD) + biSize + bmSize + 2;
1387         if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1388             return FALSE;
1389         mr = (METARECORD *)GlobalLock16(hmr);
1390         memset(mr, 0, len);
1391         mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1392         mr->rdSize = len / 2;
1393         *(mr->rdParm) = logbrush->lbStyle;
1394         *(mr->rdParm + 1) = LOWORD(logbrush->lbColor);
1395         memcpy(mr->rdParm + 2, info, biSize + bmSize);
1396         break;
1397     default:
1398         return FALSE;
1399     }
1400     if (!(MF_WriteRecord(dc, mr, len)))
1401     {
1402         GlobalFree16(hmr);
1403         return FALSE;
1404     }
1405
1406     GlobalFree16(hmr);
1407     
1408     mr = (METARECORD *)&buffer;
1409     mr->rdSize = sizeof(METARECORD) / 2;
1410     mr->rdFunction = META_SELECTOBJECT;
1411
1412     if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1413     *(mr->rdParm) = index;
1414     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1415 }
1416
1417
1418 /******************************************************************
1419  *         MF_CreatePenIndirect
1420  */
1421
1422 BOOL32 MF_CreatePenIndirect(DC *dc, HPEN16 hPen, LOGPEN16 *logpen)
1423 {
1424     int index;
1425     char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
1426     METARECORD *mr = (METARECORD *)&buffer;
1427
1428     mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
1429     mr->rdFunction = META_CREATEPENINDIRECT;
1430     memcpy(&(mr->rdParm), logpen, sizeof(*logpen));
1431     if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1432
1433     mr->rdSize = sizeof(METARECORD) / 2;
1434     mr->rdFunction = META_SELECTOBJECT;
1435
1436     if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1437     *(mr->rdParm) = index;
1438     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1439 }
1440
1441
1442 /******************************************************************
1443  *         MF_CreateFontIndirect
1444  */
1445
1446 BOOL32 MF_CreateFontIndirect(DC *dc, HFONT16 hFont, LOGFONT16 *logfont)
1447 {
1448     int index;
1449     char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
1450     METARECORD *mr = (METARECORD *)&buffer;
1451
1452     mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
1453     mr->rdFunction = META_CREATEFONTINDIRECT;
1454     memcpy(&(mr->rdParm), logfont, sizeof(LOGFONT16));
1455     if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1456
1457     mr->rdSize = sizeof(METARECORD) / 2;
1458     mr->rdFunction = META_SELECTOBJECT;
1459
1460     if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1461     *(mr->rdParm) = index;
1462     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1463 }
1464
1465
1466 /******************************************************************
1467  *         MF_TextOut
1468  */
1469 BOOL32 MF_TextOut(DC *dc, short x, short y, LPCSTR str, short count)
1470 {
1471     BOOL32 ret;
1472     DWORD len;
1473     HGLOBAL16 hmr;
1474     METARECORD *mr;
1475
1476     len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4;
1477     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1478         return FALSE;
1479     mr = (METARECORD *)GlobalLock16(hmr);
1480     memset(mr, 0, len);
1481
1482     mr->rdSize = len / 2;
1483     mr->rdFunction = META_TEXTOUT;
1484     *(mr->rdParm) = count;
1485     memcpy(mr->rdParm + 1, str, count);
1486     *(mr->rdParm + ((count + 1) >> 1) + 1) = y;
1487     *(mr->rdParm + ((count + 1) >> 1) + 2) = x;
1488     ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1489     GlobalFree16(hmr);
1490     return ret;
1491 }
1492
1493 /******************************************************************
1494  *         MF_ExtTextOut
1495  */
1496 BOOL32 MF_ExtTextOut(DC*dc, short x, short y, UINT16 flags, const RECT16 *rect,
1497                      LPCSTR str, short count, const INT16 *lpDx)
1498 {
1499     BOOL32 ret;
1500     DWORD len;
1501     HGLOBAL16 hmr;
1502     METARECORD *mr;
1503     
1504     if((!flags && rect) || (flags && !rect))
1505         WARN(metafile, "Inconsistent flags and rect\n");
1506     len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 2 * sizeof(short)
1507             + sizeof(UINT16);
1508     if(rect)
1509         len += sizeof(RECT16);
1510     if (lpDx)
1511      len+=count*sizeof(INT16);
1512     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1513         return FALSE;
1514     mr = (METARECORD *)GlobalLock16(hmr);
1515     memset(mr, 0, len);
1516
1517     mr->rdSize = len / 2;
1518     mr->rdFunction = META_EXTTEXTOUT;
1519     *(mr->rdParm) = y;
1520     *(mr->rdParm + 1) = x;
1521     *(mr->rdParm + 2) = count;
1522     *(mr->rdParm + 3) = flags;
1523     if (rect) memcpy(mr->rdParm + 4, rect, sizeof(RECT16));
1524     memcpy(mr->rdParm + (rect ? 8 : 4), str, count);
1525     if (lpDx)
1526      memcpy(mr->rdParm + (rect ? 8 : 4) + ((count + 1) >> 1),lpDx,
1527       count*sizeof(INT16));
1528     ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1529     GlobalFree16(hmr);
1530     return ret;
1531 }
1532
1533 /******************************************************************
1534  *         MF_MetaPoly - implements Polygon and Polyline
1535  */
1536 BOOL32 MF_MetaPoly(DC *dc, short func, LPPOINT16 pt, short count)
1537 {
1538     BOOL32 ret;
1539     DWORD len;
1540     HGLOBAL16 hmr;
1541     METARECORD *mr;
1542
1543     len = sizeof(METARECORD) + (count * 4); 
1544     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1545         return FALSE;
1546     mr = (METARECORD *)GlobalLock16(hmr);
1547     memset(mr, 0, len);
1548
1549     mr->rdSize = len / 2;
1550     mr->rdFunction = func;
1551     *(mr->rdParm) = count;
1552     memcpy(mr->rdParm + 1, pt, count * 4);
1553     ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1554     GlobalFree16(hmr);
1555     return ret;
1556 }
1557
1558
1559 /******************************************************************
1560  *         MF_BitBlt
1561  */
1562 BOOL32 MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
1563                  short height, DC *dcSrc, short xSrc, short ySrc, DWORD rop)
1564 {
1565     BOOL32 ret;
1566     DWORD len;
1567     HGLOBAL16 hmr;
1568     METARECORD *mr;
1569     BITMAP16  BM;
1570
1571     GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1572     len = sizeof(METARECORD) + 12 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1573     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1574         return FALSE;
1575     mr = (METARECORD *)GlobalLock16(hmr);
1576     mr->rdFunction = META_BITBLT;
1577     *(mr->rdParm + 7) = BM.bmWidth;
1578     *(mr->rdParm + 8) = BM.bmHeight;
1579     *(mr->rdParm + 9) = BM.bmWidthBytes;
1580     *(mr->rdParm +10) = BM.bmPlanes;
1581     *(mr->rdParm +11) = BM.bmBitsPixel;
1582     TRACE(metafile,"MF_StretchBlt->len = %ld  rop=%lx  \n",len,rop);
1583     if (GetBitmapBits32(dcSrc->w.hBitmap,BM.bmWidthBytes * BM.bmHeight,
1584                         mr->rdParm +12))
1585     {
1586       mr->rdSize = len / sizeof(INT16);
1587       *(mr->rdParm) = HIWORD(rop);
1588       *(mr->rdParm + 1) = ySrc;
1589       *(mr->rdParm + 2) = xSrc;
1590       *(mr->rdParm + 3) = height;
1591       *(mr->rdParm + 4) = width;
1592       *(mr->rdParm + 5) = yDest;
1593       *(mr->rdParm + 6) = xDest;
1594       ret = MF_WriteRecord( dcDest, mr, mr->rdSize * 2);
1595     }  
1596     else
1597         ret = FALSE;
1598     GlobalFree16(hmr);
1599     return ret;
1600 }
1601
1602
1603 /**********************************************************************
1604  *         MF_StretchBlt         
1605  * this function contains TWO ways for procesing StretchBlt in metafiles,
1606  * decide between rdFunction values  META_STRETCHBLT or META_DIBSTRETCHBLT
1607  * via #define STRETCH_VIA_DIB
1608  */
1609 #define STRETCH_VIA_DIB
1610 #undef  STRETCH_VIA_DIB
1611 BOOL32 MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
1612                      short heightDest, DC *dcSrc, short xSrc, short ySrc, 
1613                      short widthSrc, short heightSrc, DWORD rop)
1614 {
1615     BOOL32 ret;
1616     DWORD len;
1617     HGLOBAL16 hmr;
1618     METARECORD *mr;
1619     BITMAP16  BM;
1620 #ifdef STRETCH_VIA_DIB    
1621     LPBITMAPINFOHEADER lpBMI;
1622     WORD nBPP;
1623 #endif  
1624     GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1625 #ifdef STRETCH_VIA_DIB
1626     nBPP = BM.bmPlanes * BM.bmBitsPixel;
1627     len = sizeof(METARECORD) + 10 * sizeof(INT16) 
1628             + sizeof(BITMAPINFOHEADER) + (nBPP != 24 ? 1 << nBPP: 0) * sizeof(RGBQUAD) 
1629               + ((BM.bmWidth * nBPP + 31) / 32) * 4 * BM.bmHeight;
1630     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1631         return FALSE;
1632     mr = (METARECORD *)GlobalLock16(hmr);
1633     mr->rdFunction = META_DIBSTRETCHBLT;
1634     lpBMI=(LPBITMAPINFOHEADER)(mr->rdParm+10);
1635     lpBMI->biSize      = sizeof(BITMAPINFOHEADER);
1636     lpBMI->biWidth     = BM.bmWidth;
1637     lpBMI->biHeight    = BM.bmHeight;
1638     lpBMI->biPlanes    = 1;
1639     lpBMI->biBitCount  = nBPP;                              /* 1,4,8 or 24 */
1640     lpBMI->biClrUsed   = nBPP != 24 ? 1 << nBPP : 0;
1641     lpBMI->biSizeImage = ((lpBMI->biWidth * nBPP + 31) / 32) * 4 * lpBMI->biHeight;
1642     lpBMI->biCompression = BI_RGB;
1643     lpBMI->biXPelsPerMeter = MulDiv32(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSX),3937,100);
1644     lpBMI->biYPelsPerMeter = MulDiv32(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSY),3937,100);
1645     lpBMI->biClrImportant  = 0;                          /* 1 meter  = 39.37 inch */
1646
1647     TRACE(metafile,"MF_StretchBltViaDIB->len = %ld  rop=%lx  PixYPM=%ld Caps=%d\n",
1648                len,rop,lpBMI->biYPelsPerMeter,GetDeviceCaps(hdcSrc,LOGPIXELSY));
1649     if (GetDIBits(hdcSrc,dcSrc->w.hBitmap,0,(UINT32)lpBMI->biHeight,
1650                   (LPSTR)lpBMI + DIB_BitmapInfoSize( (BITMAPINFO *)lpBMI,
1651                                                      DIB_RGB_COLORS ),
1652                   (LPBITMAPINFO)lpBMI, DIB_RGB_COLORS))
1653 #else
1654     len = sizeof(METARECORD) + 15 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1655     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1656         return FALSE;
1657     mr = (METARECORD *)GlobalLock16(hmr);
1658     mr->rdFunction = META_STRETCHBLT;
1659     *(mr->rdParm +10) = BM.bmWidth;
1660     *(mr->rdParm +11) = BM.bmHeight;
1661     *(mr->rdParm +12) = BM.bmWidthBytes;
1662     *(mr->rdParm +13) = BM.bmPlanes;
1663     *(mr->rdParm +14) = BM.bmBitsPixel;
1664     TRACE(metafile,"MF_StretchBlt->len = %ld  rop=%lx  \n",len,rop);
1665     if (GetBitmapBits32( dcSrc->w.hBitmap, BM.bmWidthBytes * BM.bmHeight,
1666                          mr->rdParm +15))
1667 #endif    
1668     {
1669       mr->rdSize = len / sizeof(INT16);
1670       *(mr->rdParm) = LOWORD(rop);
1671       *(mr->rdParm + 1) = HIWORD(rop);
1672       *(mr->rdParm + 2) = heightSrc;
1673       *(mr->rdParm + 3) = widthSrc;
1674       *(mr->rdParm + 4) = ySrc;
1675       *(mr->rdParm + 5) = xSrc;
1676       *(mr->rdParm + 6) = heightDest;
1677       *(mr->rdParm + 7) = widthDest;
1678       *(mr->rdParm + 8) = yDest;
1679       *(mr->rdParm + 9) = xDest;
1680       ret = MF_WriteRecord( dcDest, mr, mr->rdSize * 2);
1681     }  
1682     else
1683         ret = FALSE;
1684     GlobalFree16(hmr);
1685     return ret;
1686 }
1687
1688
1689 /******************************************************************
1690  *         MF_CreateRegion
1691  */
1692 INT16 MF_CreateRegion(DC *dc, HRGN32 hrgn)
1693 {
1694     DWORD len;
1695     METARECORD *mr;
1696     RGNDATA *rgndata;
1697     RECT32 *pCurRect, *pEndRect;
1698     WORD Bands = 0, MaxBands = 0;
1699     WORD *Param, *StartBand;
1700     BOOL32 ret;
1701
1702     len = GetRegionData32( hrgn, 0, NULL );
1703     if( !(rgndata = HeapAlloc( SystemHeap, 0, len )) ) {
1704         WARN(metafile, "MF_CreateRegion: can't alloc rgndata buffer\n");
1705         return -1;
1706     }
1707     GetRegionData32( hrgn, len, rgndata );
1708
1709     /* Overestimate of length:
1710      * Assume every rect is a separate band -> 6 WORDs per rect
1711      */
1712     len = sizeof(METARECORD) + 20 + (rgndata->rdh.nCount * 12);
1713     if( !(mr = HeapAlloc( SystemHeap, 0, len )) ) {
1714         WARN(metafile, "MF_CreateRegion: can't alloc METARECORD buffer\n");
1715         HeapFree( SystemHeap, 0, rgndata );
1716         return -1;
1717     }
1718
1719     memset(mr, 0, len);
1720         
1721     Param = mr->rdParm + 11;
1722     StartBand = NULL;
1723
1724     pEndRect = (RECT32 *)rgndata->Buffer + rgndata->rdh.nCount;
1725     for(pCurRect = (RECT32 *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
1726     {
1727         if( StartBand && pCurRect->top == *(StartBand + 1) )
1728         {
1729             *Param++ = pCurRect->left;
1730             *Param++ = pCurRect->right;
1731         }
1732         else
1733         {
1734             if(StartBand)
1735             {
1736                 *StartBand = Param - StartBand - 3;
1737                 *Param++ = *StartBand;
1738                 if(*StartBand > MaxBands)
1739                     MaxBands = *StartBand;
1740                 Bands++;
1741             }
1742             StartBand = Param++;
1743             *Param++ = pCurRect->top;
1744             *Param++ = pCurRect->bottom;
1745             *Param++ = pCurRect->left;
1746             *Param++ = pCurRect->right;
1747         }
1748     }
1749     len = Param - (WORD *)mr;
1750     
1751     mr->rdParm[0] = 0;
1752     mr->rdParm[1] = 6;
1753     mr->rdParm[2] = 0x1234;
1754     mr->rdParm[3] = 0;
1755     mr->rdParm[4] = len * 2;
1756     mr->rdParm[5] = Bands;
1757     mr->rdParm[6] = MaxBands;
1758     mr->rdParm[7] = rgndata->rdh.rcBound.left;
1759     mr->rdParm[8] = rgndata->rdh.rcBound.top;
1760     mr->rdParm[9] = rgndata->rdh.rcBound.right;
1761     mr->rdParm[10] = rgndata->rdh.rcBound.bottom;
1762     mr->rdFunction = META_CREATEREGION;
1763     mr->rdSize = len / 2;
1764     ret = MF_WriteRecord( dc, mr, mr->rdSize * 2 );     
1765     HeapFree( SystemHeap, 0, mr );
1766     HeapFree( SystemHeap, 0, rgndata );
1767     if(!ret) 
1768     {
1769         WARN(metafile, "MF_CreateRegion: MF_WriteRecord failed\n");
1770         return -1;
1771     }
1772     return MF_AddHandleDC( dc );
1773 }