Implemented CreateHalftonePalette.
[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   TRACE(metafile, "(%08x,%d,%p)\n", hmf, nSize, buf);
1060   if (!h) return 0;  /* FIXME: error code */
1061   if (!buf) {
1062     GlobalUnlock16(hmf);
1063     TRACE(metafile,"returning size %ld\n", h->mtSize);
1064     return h->mtSize;
1065   }
1066   memmove(buf, h, MIN(nSize, h->mtSize));
1067   GlobalUnlock16(hmf);
1068   return MIN(nSize, h->mtSize);
1069 }
1070
1071 /******************************************************************
1072  *         GetWinMetaFileBits [GDI32.241]
1073  */
1074 UINT32 WINAPI GetWinMetaFileBits(HENHMETAFILE32 hemf,
1075                                 UINT32 cbBuffer, LPBYTE lpbBuffer,
1076                                 INT32 fnMapMode, HDC32 hdcRef)
1077 {
1078   FIXME(metafile, "(%d,%d,%p,%d,%d): stub\n",
1079         hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1080   return 0;
1081 }
1082
1083 /******************************************************************
1084  *         MF_Meta_CreateRegion
1085  *
1086  *  Handles META_CREATEREGION for PlayMetaFileRecord().
1087  */
1088
1089 /*
1090  *      The layout of the record looks something like this:
1091  *       
1092  *       rdParm meaning
1093  *       0              Always 0?
1094  *       1              Always 6?
1095  *       2              Looks like a handle? - not constant
1096  *       3              0 or 1 ??
1097  *       4              Total number of bytes
1098  *       5              No. of seperate bands = n [see below]
1099  *       6              Largest number of x co-ords in a band
1100  *       7-10           Bounding box x1 y1 x2 y2
1101  *       11-...         n bands
1102  *
1103  *       Regions are divided into bands that are uniform in the
1104  *       y-direction. Each band consists of pairs of on/off x-coords and is
1105  *       written as
1106  *              m y0 y1 x1 x2 x3 ... xm m
1107  *       into successive rdParm[]s.
1108  *
1109  *       This is probably just a dump of the internal RGNOBJ?
1110  *
1111  *       HDMD - 18/12/97
1112  *
1113  */
1114
1115 static BOOL32 MF_Meta_CreateRegion( METARECORD *mr, HRGN32 hrgn )
1116 {
1117     WORD band, pair;
1118     WORD *start, *end;
1119     INT16 y0, y1;
1120     HRGN32 hrgn2 = CreateRectRgn32( 0, 0, 0, 0 );
1121
1122     for(band  = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1123                                                 band++, start = end + 1) {
1124         if(*start / 2 != (*start + 1) / 2) {
1125             WARN(metafile, "Delimiter not even.\n");
1126             DeleteObject32( hrgn2 );
1127             return FALSE;
1128         }
1129
1130         end = start + *start + 3;
1131         if(end > (WORD *)mr + mr->rdSize) {
1132             WARN(metafile, "End points outside record.\n");
1133             DeleteObject32( hrgn2 );
1134             return FALSE;
1135         }
1136
1137         if(*start != *end) {
1138             WARN(metafile, "Mismatched delimiters.\n");
1139             DeleteObject32( hrgn2 );
1140             return FALSE;
1141         }
1142
1143         y0 = *(INT16 *)(start + 1);
1144         y1 = *(INT16 *)(start + 2);
1145         for(pair = 0; pair < *start / 2; pair++) {
1146             SetRectRgn32( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1147                                  *(INT16 *)(start + 4 + 2*pair), y1 );
1148             CombineRgn32(hrgn, hrgn, hrgn2, RGN_OR);
1149         }
1150     }
1151     DeleteObject32( hrgn2 );
1152     return TRUE;
1153  }
1154  
1155
1156 /******************************************************************
1157  *         MF_WriteRecord
1158  *
1159  * Warning: this function can change the metafile handle.
1160  */
1161
1162 static BOOL32 MF_WriteRecord( DC *dc, METARECORD *mr, DWORD rlen)
1163 {
1164     DWORD len;
1165     METAHEADER *mh;
1166     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
1167
1168     switch(physDev->mh->mtType)
1169     {
1170     case METAFILE_MEMORY:
1171         len = physDev->mh->mtSize * 2 + rlen;
1172         mh = HeapReAlloc( SystemHeap, 0, physDev->mh, len );
1173         if (!mh) return FALSE;
1174         physDev->mh = mh;
1175         memcpy((WORD *)physDev->mh + physDev->mh->mtSize, mr, rlen);
1176         break;
1177     case METAFILE_DISK:
1178         TRACE(metafile,"Writing record to disk\n");
1179         if (_lwrite32(physDev->mh->mtNoParameters, (char *)mr, rlen) == -1)
1180             return FALSE;
1181         break;
1182     default:
1183         ERR(metafile, "Unknown metafile type %d\n", physDev->mh->mtType );
1184         return FALSE;
1185     }
1186
1187     physDev->mh->mtSize += rlen / 2;
1188     physDev->mh->mtMaxRecord = MAX(physDev->mh->mtMaxRecord, rlen / 2);
1189     return TRUE;
1190 }
1191
1192
1193 /******************************************************************
1194  *         MF_MetaParam0
1195  */
1196
1197 BOOL32 MF_MetaParam0(DC *dc, short func)
1198 {
1199     char buffer[8];
1200     METARECORD *mr = (METARECORD *)&buffer;
1201     
1202     mr->rdSize = 3;
1203     mr->rdFunction = func;
1204     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1205 }
1206
1207
1208 /******************************************************************
1209  *         MF_MetaParam1
1210  */
1211 BOOL32 MF_MetaParam1(DC *dc, short func, short param1)
1212 {
1213     char buffer[8];
1214     METARECORD *mr = (METARECORD *)&buffer;
1215     
1216     mr->rdSize = 4;
1217     mr->rdFunction = func;
1218     *(mr->rdParm) = param1;
1219     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1220 }
1221
1222
1223 /******************************************************************
1224  *         MF_MetaParam2
1225  */
1226 BOOL32 MF_MetaParam2(DC *dc, short func, short param1, short param2)
1227 {
1228     char buffer[10];
1229     METARECORD *mr = (METARECORD *)&buffer;
1230     
1231     mr->rdSize = 5;
1232     mr->rdFunction = func;
1233     *(mr->rdParm) = param2;
1234     *(mr->rdParm + 1) = param1;
1235     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1236 }
1237
1238
1239 /******************************************************************
1240  *         MF_MetaParam4
1241  */
1242
1243 BOOL32 MF_MetaParam4(DC *dc, short func, short param1, short param2, 
1244                    short param3, short param4)
1245 {
1246     char buffer[14];
1247     METARECORD *mr = (METARECORD *)&buffer;
1248     
1249     mr->rdSize = 7;
1250     mr->rdFunction = func;
1251     *(mr->rdParm) = param4;
1252     *(mr->rdParm + 1) = param3;
1253     *(mr->rdParm + 2) = param2;
1254     *(mr->rdParm + 3) = param1;
1255     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1256 }
1257
1258
1259 /******************************************************************
1260  *         MF_MetaParam6
1261  */
1262
1263 BOOL32 MF_MetaParam6(DC *dc, short func, short param1, short param2, 
1264                    short param3, short param4, short param5, short param6)
1265 {
1266     char buffer[18];
1267     METARECORD *mr = (METARECORD *)&buffer;
1268     
1269     mr->rdSize = 9;
1270     mr->rdFunction = func;
1271     *(mr->rdParm) = param6;
1272     *(mr->rdParm + 1) = param5;
1273     *(mr->rdParm + 2) = param4;
1274     *(mr->rdParm + 3) = param3;
1275     *(mr->rdParm + 4) = param2;
1276     *(mr->rdParm + 5) = param1;
1277     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1278 }
1279
1280
1281 /******************************************************************
1282  *         MF_MetaParam8
1283  */
1284 BOOL32 MF_MetaParam8(DC *dc, short func, short param1, short param2, 
1285                    short param3, short param4, short param5,
1286                    short param6, short param7, short param8)
1287 {
1288     char buffer[22];
1289     METARECORD *mr = (METARECORD *)&buffer;
1290     
1291     mr->rdSize = 11;
1292     mr->rdFunction = func;
1293     *(mr->rdParm) = param8;
1294     *(mr->rdParm + 1) = param7;
1295     *(mr->rdParm + 2) = param6;
1296     *(mr->rdParm + 3) = param5;
1297     *(mr->rdParm + 4) = param4;
1298     *(mr->rdParm + 5) = param3;
1299     *(mr->rdParm + 6) = param2;
1300     *(mr->rdParm + 7) = param1;
1301     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1302 }
1303
1304
1305 /******************************************************************
1306  *         MF_CreateBrushIndirect
1307  */
1308
1309 BOOL32 MF_CreateBrushIndirect(DC *dc, HBRUSH16 hBrush, LOGBRUSH16 *logbrush)
1310 {
1311     int index;
1312     char buffer[sizeof(METARECORD) - 2 + sizeof(*logbrush)];
1313     METARECORD *mr = (METARECORD *)&buffer;
1314
1315     mr->rdSize = (sizeof(METARECORD) + sizeof(*logbrush) - 2) / 2;
1316     mr->rdFunction = META_CREATEBRUSHINDIRECT;
1317     memcpy(&(mr->rdParm), logbrush, sizeof(*logbrush));
1318     if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1319
1320     mr->rdSize = sizeof(METARECORD) / 2;
1321     mr->rdFunction = META_SELECTOBJECT;
1322
1323     if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1324     *(mr->rdParm) = index;
1325     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1326 }
1327
1328
1329 /******************************************************************
1330  *         MF_CreatePatternBrush
1331  */
1332
1333 BOOL32 MF_CreatePatternBrush(DC *dc, HBRUSH16 hBrush, LOGBRUSH16 *logbrush)
1334 {
1335     DWORD len, bmSize, biSize;
1336     HGLOBAL16 hmr;
1337     METARECORD *mr;
1338     BITMAPOBJ *bmp;
1339     BITMAPINFO *info;
1340     BITMAPINFOHEADER *infohdr;
1341     int index;
1342     char buffer[sizeof(METARECORD)];
1343
1344     switch (logbrush->lbStyle)
1345     {
1346     case BS_PATTERN:
1347         bmp = (BITMAPOBJ *)GDI_GetObjPtr((HGDIOBJ16)logbrush->lbHatch, BITMAP_MAGIC);
1348         if (!bmp) return FALSE;
1349         len = sizeof(METARECORD) + sizeof(BITMAPINFOHEADER) + 
1350               (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 6;
1351         if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1352           {
1353             GDI_HEAP_UNLOCK((HGDIOBJ16)logbrush->lbHatch);
1354             return FALSE;
1355           }
1356         mr = (METARECORD *)GlobalLock16(hmr);
1357         memset(mr, 0, len);
1358         mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1359         mr->rdSize = len / 2;
1360         *(mr->rdParm) = logbrush->lbStyle;
1361         *(mr->rdParm + 1) = DIB_RGB_COLORS;
1362         infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
1363         infohdr->biSize = sizeof(BITMAPINFOHEADER);
1364         infohdr->biWidth = bmp->bitmap.bmWidth;
1365         infohdr->biHeight = bmp->bitmap.bmHeight;
1366         infohdr->biPlanes = bmp->bitmap.bmPlanes;
1367         infohdr->biBitCount = bmp->bitmap.bmBitsPixel;
1368         memcpy(mr->rdParm + (sizeof(BITMAPINFOHEADER) / 2) + 4,
1369                PTR_SEG_TO_LIN(bmp->bitmap.bmBits),
1370                bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes);
1371         GDI_HEAP_UNLOCK(logbrush->lbHatch);
1372         break;
1373
1374     case BS_DIBPATTERN:
1375         info = (BITMAPINFO *)GlobalLock16((HGLOBAL16)logbrush->lbHatch);
1376         if (info->bmiHeader.biCompression)
1377             bmSize = info->bmiHeader.biSizeImage;
1378         else
1379             bmSize = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount 
1380                     + 31) / 32 * 8 * info->bmiHeader.biHeight;
1381         biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush->lbColor)); 
1382         len = sizeof(METARECORD) + biSize + bmSize + 2;
1383         if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1384             return FALSE;
1385         mr = (METARECORD *)GlobalLock16(hmr);
1386         memset(mr, 0, len);
1387         mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1388         mr->rdSize = len / 2;
1389         *(mr->rdParm) = logbrush->lbStyle;
1390         *(mr->rdParm + 1) = LOWORD(logbrush->lbColor);
1391         memcpy(mr->rdParm + 2, info, biSize + bmSize);
1392         break;
1393     default:
1394         return FALSE;
1395     }
1396     if (!(MF_WriteRecord(dc, mr, len)))
1397     {
1398         GlobalFree16(hmr);
1399         return FALSE;
1400     }
1401
1402     GlobalFree16(hmr);
1403     
1404     mr = (METARECORD *)&buffer;
1405     mr->rdSize = sizeof(METARECORD) / 2;
1406     mr->rdFunction = META_SELECTOBJECT;
1407
1408     if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1409     *(mr->rdParm) = index;
1410     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1411 }
1412
1413
1414 /******************************************************************
1415  *         MF_CreatePenIndirect
1416  */
1417
1418 BOOL32 MF_CreatePenIndirect(DC *dc, HPEN16 hPen, LOGPEN16 *logpen)
1419 {
1420     int index;
1421     char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
1422     METARECORD *mr = (METARECORD *)&buffer;
1423
1424     mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
1425     mr->rdFunction = META_CREATEPENINDIRECT;
1426     memcpy(&(mr->rdParm), logpen, sizeof(*logpen));
1427     if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1428
1429     mr->rdSize = sizeof(METARECORD) / 2;
1430     mr->rdFunction = META_SELECTOBJECT;
1431
1432     if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1433     *(mr->rdParm) = index;
1434     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1435 }
1436
1437
1438 /******************************************************************
1439  *         MF_CreateFontIndirect
1440  */
1441
1442 BOOL32 MF_CreateFontIndirect(DC *dc, HFONT16 hFont, LOGFONT16 *logfont)
1443 {
1444     int index;
1445     char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
1446     METARECORD *mr = (METARECORD *)&buffer;
1447
1448     mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
1449     mr->rdFunction = META_CREATEFONTINDIRECT;
1450     memcpy(&(mr->rdParm), logfont, sizeof(LOGFONT16));
1451     if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1452
1453     mr->rdSize = sizeof(METARECORD) / 2;
1454     mr->rdFunction = META_SELECTOBJECT;
1455
1456     if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1457     *(mr->rdParm) = index;
1458     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1459 }
1460
1461
1462 /******************************************************************
1463  *         MF_TextOut
1464  */
1465 BOOL32 MF_TextOut(DC *dc, short x, short y, LPCSTR str, short count)
1466 {
1467     BOOL32 ret;
1468     DWORD len;
1469     HGLOBAL16 hmr;
1470     METARECORD *mr;
1471
1472     len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4;
1473     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1474         return FALSE;
1475     mr = (METARECORD *)GlobalLock16(hmr);
1476     memset(mr, 0, len);
1477
1478     mr->rdSize = len / 2;
1479     mr->rdFunction = META_TEXTOUT;
1480     *(mr->rdParm) = count;
1481     memcpy(mr->rdParm + 1, str, count);
1482     *(mr->rdParm + ((count + 1) >> 1) + 1) = y;
1483     *(mr->rdParm + ((count + 1) >> 1) + 2) = x;
1484     ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1485     GlobalFree16(hmr);
1486     return ret;
1487 }
1488
1489 /******************************************************************
1490  *         MF_ExtTextOut
1491  */
1492 BOOL32 MF_ExtTextOut(DC*dc, short x, short y, UINT16 flags, const RECT16 *rect,
1493                      LPCSTR str, short count, const INT16 *lpDx)
1494 {
1495     BOOL32 ret;
1496     DWORD len;
1497     HGLOBAL16 hmr;
1498     METARECORD *mr;
1499     
1500     if((!flags && rect) || (flags && !rect))
1501         WARN(metafile, "Inconsistent flags and rect\n");
1502     len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 2 * sizeof(short)
1503             + sizeof(UINT16);
1504     if(rect)
1505         len += sizeof(RECT16);
1506     if (lpDx)
1507      len+=count*sizeof(INT16);
1508     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1509         return FALSE;
1510     mr = (METARECORD *)GlobalLock16(hmr);
1511     memset(mr, 0, len);
1512
1513     mr->rdSize = len / 2;
1514     mr->rdFunction = META_EXTTEXTOUT;
1515     *(mr->rdParm) = y;
1516     *(mr->rdParm + 1) = x;
1517     *(mr->rdParm + 2) = count;
1518     *(mr->rdParm + 3) = flags;
1519     if (rect) memcpy(mr->rdParm + 4, rect, sizeof(RECT16));
1520     memcpy(mr->rdParm + (rect ? 8 : 4), str, count);
1521     if (lpDx)
1522      memcpy(mr->rdParm + (rect ? 8 : 4) + ((count + 1) >> 1),lpDx,
1523       count*sizeof(INT16));
1524     ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1525     GlobalFree16(hmr);
1526     return ret;
1527 }
1528
1529 /******************************************************************
1530  *         MF_MetaPoly - implements Polygon and Polyline
1531  */
1532 BOOL32 MF_MetaPoly(DC *dc, short func, LPPOINT16 pt, short count)
1533 {
1534     BOOL32 ret;
1535     DWORD len;
1536     HGLOBAL16 hmr;
1537     METARECORD *mr;
1538
1539     len = sizeof(METARECORD) + (count * 4); 
1540     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1541         return FALSE;
1542     mr = (METARECORD *)GlobalLock16(hmr);
1543     memset(mr, 0, len);
1544
1545     mr->rdSize = len / 2;
1546     mr->rdFunction = func;
1547     *(mr->rdParm) = count;
1548     memcpy(mr->rdParm + 1, pt, count * 4);
1549     ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1550     GlobalFree16(hmr);
1551     return ret;
1552 }
1553
1554
1555 /******************************************************************
1556  *         MF_BitBlt
1557  */
1558 BOOL32 MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
1559                  short height, DC *dcSrc, short xSrc, short ySrc, DWORD rop)
1560 {
1561     BOOL32 ret;
1562     DWORD len;
1563     HGLOBAL16 hmr;
1564     METARECORD *mr;
1565     BITMAP16  BM;
1566
1567     GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1568     len = sizeof(METARECORD) + 12 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1569     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1570         return FALSE;
1571     mr = (METARECORD *)GlobalLock16(hmr);
1572     mr->rdFunction = META_BITBLT;
1573     *(mr->rdParm + 7) = BM.bmWidth;
1574     *(mr->rdParm + 8) = BM.bmHeight;
1575     *(mr->rdParm + 9) = BM.bmWidthBytes;
1576     *(mr->rdParm +10) = BM.bmPlanes;
1577     *(mr->rdParm +11) = BM.bmBitsPixel;
1578     TRACE(metafile,"MF_StretchBlt->len = %ld  rop=%lx  \n",len,rop);
1579     if (GetBitmapBits32(dcSrc->w.hBitmap,BM.bmWidthBytes * BM.bmHeight,
1580                         mr->rdParm +12))
1581     {
1582       mr->rdSize = len / sizeof(INT16);
1583       *(mr->rdParm) = HIWORD(rop);
1584       *(mr->rdParm + 1) = ySrc;
1585       *(mr->rdParm + 2) = xSrc;
1586       *(mr->rdParm + 3) = height;
1587       *(mr->rdParm + 4) = width;
1588       *(mr->rdParm + 5) = yDest;
1589       *(mr->rdParm + 6) = xDest;
1590       ret = MF_WriteRecord( dcDest, mr, mr->rdSize * 2);
1591     }  
1592     else
1593         ret = FALSE;
1594     GlobalFree16(hmr);
1595     return ret;
1596 }
1597
1598
1599 /**********************************************************************
1600  *         MF_StretchBlt         
1601  * this function contains TWO ways for procesing StretchBlt in metafiles,
1602  * decide between rdFunction values  META_STRETCHBLT or META_DIBSTRETCHBLT
1603  * via #define STRETCH_VIA_DIB
1604  */
1605 #define STRETCH_VIA_DIB
1606 #undef  STRETCH_VIA_DIB
1607 BOOL32 MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
1608                      short heightDest, DC *dcSrc, short xSrc, short ySrc, 
1609                      short widthSrc, short heightSrc, DWORD rop)
1610 {
1611     BOOL32 ret;
1612     DWORD len;
1613     HGLOBAL16 hmr;
1614     METARECORD *mr;
1615     BITMAP16  BM;
1616 #ifdef STRETCH_VIA_DIB    
1617     LPBITMAPINFOHEADER lpBMI;
1618     WORD nBPP;
1619 #endif  
1620     GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1621 #ifdef STRETCH_VIA_DIB
1622     nBPP = BM.bmPlanes * BM.bmBitsPixel;
1623     len = sizeof(METARECORD) + 10 * sizeof(INT16) 
1624             + sizeof(BITMAPINFOHEADER) + (nBPP != 24 ? 1 << nBPP: 0) * sizeof(RGBQUAD) 
1625               + ((BM.bmWidth * nBPP + 31) / 32) * 4 * BM.bmHeight;
1626     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1627         return FALSE;
1628     mr = (METARECORD *)GlobalLock16(hmr);
1629     mr->rdFunction = META_DIBSTRETCHBLT;
1630     lpBMI=(LPBITMAPINFOHEADER)(mr->rdParm+10);
1631     lpBMI->biSize      = sizeof(BITMAPINFOHEADER);
1632     lpBMI->biWidth     = BM.bmWidth;
1633     lpBMI->biHeight    = BM.bmHeight;
1634     lpBMI->biPlanes    = 1;
1635     lpBMI->biBitCount  = nBPP;                              /* 1,4,8 or 24 */
1636     lpBMI->biClrUsed   = nBPP != 24 ? 1 << nBPP : 0;
1637     lpBMI->biSizeImage = ((lpBMI->biWidth * nBPP + 31) / 32) * 4 * lpBMI->biHeight;
1638     lpBMI->biCompression = BI_RGB;
1639     lpBMI->biXPelsPerMeter = MulDiv32(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSX),3937,100);
1640     lpBMI->biYPelsPerMeter = MulDiv32(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSY),3937,100);
1641     lpBMI->biClrImportant  = 0;                          /* 1 meter  = 39.37 inch */
1642
1643     TRACE(metafile,"MF_StretchBltViaDIB->len = %ld  rop=%lx  PixYPM=%ld Caps=%d\n",
1644                len,rop,lpBMI->biYPelsPerMeter,GetDeviceCaps(hdcSrc,LOGPIXELSY));
1645     if (GetDIBits(hdcSrc,dcSrc->w.hBitmap,0,(UINT32)lpBMI->biHeight,
1646                   (LPSTR)lpBMI + DIB_BitmapInfoSize( (BITMAPINFO *)lpBMI,
1647                                                      DIB_RGB_COLORS ),
1648                   (LPBITMAPINFO)lpBMI, DIB_RGB_COLORS))
1649 #else
1650     len = sizeof(METARECORD) + 15 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1651     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1652         return FALSE;
1653     mr = (METARECORD *)GlobalLock16(hmr);
1654     mr->rdFunction = META_STRETCHBLT;
1655     *(mr->rdParm +10) = BM.bmWidth;
1656     *(mr->rdParm +11) = BM.bmHeight;
1657     *(mr->rdParm +12) = BM.bmWidthBytes;
1658     *(mr->rdParm +13) = BM.bmPlanes;
1659     *(mr->rdParm +14) = BM.bmBitsPixel;
1660     TRACE(metafile,"MF_StretchBlt->len = %ld  rop=%lx  \n",len,rop);
1661     if (GetBitmapBits32( dcSrc->w.hBitmap, BM.bmWidthBytes * BM.bmHeight,
1662                          mr->rdParm +15))
1663 #endif    
1664     {
1665       mr->rdSize = len / sizeof(INT16);
1666       *(mr->rdParm) = LOWORD(rop);
1667       *(mr->rdParm + 1) = HIWORD(rop);
1668       *(mr->rdParm + 2) = heightSrc;
1669       *(mr->rdParm + 3) = widthSrc;
1670       *(mr->rdParm + 4) = ySrc;
1671       *(mr->rdParm + 5) = xSrc;
1672       *(mr->rdParm + 6) = heightDest;
1673       *(mr->rdParm + 7) = widthDest;
1674       *(mr->rdParm + 8) = yDest;
1675       *(mr->rdParm + 9) = xDest;
1676       ret = MF_WriteRecord( dcDest, mr, mr->rdSize * 2);
1677     }  
1678     else
1679         ret = FALSE;
1680     GlobalFree16(hmr);
1681     return ret;
1682 }
1683
1684
1685 /******************************************************************
1686  *         MF_CreateRegion
1687  */
1688 INT16 MF_CreateRegion(DC *dc, HRGN32 hrgn)
1689 {
1690     DWORD len;
1691     METARECORD *mr;
1692     RGNDATA *rgndata;
1693     RECT32 *pCurRect, *pEndRect;
1694     WORD Bands = 0, MaxBands = 0;
1695     WORD *Param, *StartBand;
1696     BOOL32 ret;
1697
1698     len = GetRegionData32( hrgn, 0, NULL );
1699     if( !(rgndata = HeapAlloc( SystemHeap, 0, len )) ) {
1700         WARN(metafile, "MF_CreateRegion: can't alloc rgndata buffer\n");
1701         return -1;
1702     }
1703     GetRegionData32( hrgn, len, rgndata );
1704
1705     /* Overestimate of length:
1706      * Assume every rect is a separate band -> 6 WORDs per rect
1707      */
1708     len = sizeof(METARECORD) + 20 + (rgndata->rdh.nCount * 12);
1709     if( !(mr = HeapAlloc( SystemHeap, 0, len )) ) {
1710         WARN(metafile, "MF_CreateRegion: can't alloc METARECORD buffer\n");
1711         HeapFree( SystemHeap, 0, rgndata );
1712         return -1;
1713     }
1714
1715     memset(mr, 0, len);
1716         
1717     Param = mr->rdParm + 11;
1718     StartBand = NULL;
1719
1720     pEndRect = (RECT32 *)rgndata->Buffer + rgndata->rdh.nCount;
1721     for(pCurRect = (RECT32 *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
1722     {
1723         if( StartBand && pCurRect->top == *(StartBand + 1) )
1724         {
1725             *Param++ = pCurRect->left;
1726             *Param++ = pCurRect->right;
1727         }
1728         else
1729         {
1730             if(StartBand)
1731             {
1732                 *StartBand = Param - StartBand - 3;
1733                 *Param++ = *StartBand;
1734                 if(*StartBand > MaxBands)
1735                     MaxBands = *StartBand;
1736                 Bands++;
1737             }
1738             StartBand = Param++;
1739             *Param++ = pCurRect->top;
1740             *Param++ = pCurRect->bottom;
1741             *Param++ = pCurRect->left;
1742             *Param++ = pCurRect->right;
1743         }
1744     }
1745     len = Param - (WORD *)mr;
1746     
1747     mr->rdParm[0] = 0;
1748     mr->rdParm[1] = 6;
1749     mr->rdParm[2] = 0x1234;
1750     mr->rdParm[3] = 0;
1751     mr->rdParm[4] = len * 2;
1752     mr->rdParm[5] = Bands;
1753     mr->rdParm[6] = MaxBands;
1754     mr->rdParm[7] = rgndata->rdh.rcBound.left;
1755     mr->rdParm[8] = rgndata->rdh.rcBound.top;
1756     mr->rdParm[9] = rgndata->rdh.rcBound.right;
1757     mr->rdParm[10] = rgndata->rdh.rcBound.bottom;
1758     mr->rdFunction = META_CREATEREGION;
1759     mr->rdSize = len / 2;
1760     ret = MF_WriteRecord( dc, mr, mr->rdSize * 2 );     
1761     HeapFree( SystemHeap, 0, mr );
1762     HeapFree( SystemHeap, 0, rgndata );
1763     if(!ret) 
1764     {
1765         WARN(metafile, "MF_CreateRegion: MF_WriteRecord failed\n");
1766         return -1;
1767     }
1768     return MF_AddHandleDC( dc );
1769 }