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