Release 970804
[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 "gdi.h"
12 #include "bitmap.h"
13 #include "file.h"
14 #include "heap.h"
15 #include "metafile.h"
16 #include "metafiledrv.h"
17 #include "stddebug.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 GetMetaFile16( LPCSTR lpFilename )
61 {
62     return GetMetaFile32A( lpFilename );
63 }
64
65
66 /******************************************************************
67  *         GetMetafile32A   (GDI32.197)
68  */
69 HMETAFILE32 GetMetaFile32A( LPCSTR lpFilename )
70 {
71   HMETAFILE16 hmf;
72   METAHEADER *mh;
73   HFILE32 hFile;
74   DWORD size;
75   
76   dprintf_metafile(stddeb,"GetMetaFile: %s\n", lpFilename);
77
78   if (!lpFilename)
79     return 0;
80
81   hmf = GlobalAlloc16(GMEM_MOVEABLE, MFHEADERSIZE);
82   mh = (METAHEADER *)GlobalLock16(hmf);
83   
84   if (!mh)
85   {
86     GlobalFree16(hmf);
87     return 0;
88   }
89   
90   if ((hFile = _lopen32(lpFilename, OF_READ)) == HFILE_ERROR32)
91   {
92     GlobalFree16(hmf);
93     return 0;
94   }
95   
96   if (_lread32(hFile, (char *)mh, MFHEADERSIZE) == HFILE_ERROR32)
97   {
98     _lclose32( hFile );
99     GlobalFree16(hmf);
100     return 0;
101   }
102   
103   size = mh->mtSize * 2;         /* alloc memory for whole metafile */
104   GlobalUnlock16(hmf);
105   hmf = GlobalReAlloc16(hmf,size,GMEM_MOVEABLE);
106   mh = (METAHEADER *)GlobalLock16(hmf);
107   
108   if (!mh)
109   {
110     _lclose32( hFile );
111     GlobalFree16(hmf);
112     return 0;
113   }
114   
115   if (_lread32(hFile, (char*)mh + mh->mtHeaderSize * 2, 
116                 size - mh->mtHeaderSize * 2) == HFILE_ERROR32)
117   {
118     _lclose32( hFile );
119     GlobalFree16(hmf);
120     return 0;
121   }
122   
123   _lclose32(hFile);
124
125   if (mh->mtType != 1)
126   {
127     GlobalFree16(hmf);
128     return 0;
129   }
130   
131   GlobalUnlock16(hmf);
132   return hmf;
133
134 }
135
136
137 /******************************************************************
138  *         GetMetafile32W   (GDI32.199)
139  */
140 HMETAFILE32 GetMetaFile32W( LPCWSTR lpFilename )
141 {
142     LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
143     HMETAFILE32 ret = GetMetaFile32A( p );
144     HeapFree( GetProcessHeap(), 0, p );
145     return ret;
146 }
147
148
149 /******************************************************************
150  *         CopyMetaFile16   (GDI.151)
151  */
152
153 HMETAFILE16 CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename )
154 {
155     return CopyMetaFile32A( hSrcMetaFile, lpFilename );
156 }
157
158
159 /******************************************************************
160  *         CopyMetaFile32A   (GDI32.23)
161  */
162 HMETAFILE32 CopyMetaFile32A( HMETAFILE32 hSrcMetaFile, LPCSTR lpFilename )
163 {
164     HMETAFILE16 handle = 0;
165     METAHEADER *mh;
166     METAHEADER *mh2;
167     HFILE32 hFile;
168     
169     dprintf_metafile(stddeb,"CopyMetaFile: %s\n", lpFilename);
170     
171     mh = (METAHEADER *)GlobalLock16(hSrcMetaFile);
172     
173     if (!mh)
174       return 0;
175     
176     if (lpFilename)          /* disk based metafile */
177         {
178         int i,j;
179         hFile = _lcreat32(lpFilename, 0);
180         j=mh->mtType;
181         mh->mtType=1;        /* disk file version stores 1 here */
182         i=_lwrite32(hFile, (char *)mh, mh->mtSize * 2) ;
183         mh->mtType=j;        /* restore old value  [0 or 1] */  
184         _lclose32(hFile);
185         if (i == -1)
186             return 0;
187         /* FIXME: return value */
188         }
189     else                     /* memory based metafile */
190         {
191         handle = GlobalAlloc16(GMEM_MOVEABLE,mh->mtSize * 2);
192         mh2 = (METAHEADER *)GlobalLock16(handle);
193         memcpy(mh2,mh, mh->mtSize * 2);
194         GlobalUnlock16(handle);
195         }
196     
197     return handle;
198 }
199
200
201 /******************************************************************
202  *         CopyMetaFile32W   (GDI32.24)
203  */
204 HMETAFILE32 CopyMetaFile32W( HMETAFILE32 hSrcMetaFile, LPCWSTR lpFilename )
205 {
206     LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
207     HMETAFILE32 ret = CopyMetaFile32A( hSrcMetaFile, p );
208     HeapFree( GetProcessHeap(), 0, p );
209     return ret;
210 }
211
212
213 /******************************************************************
214  *         IsValidMetaFile   (GDI.410)
215  *         (This is not exactly what windows does, see "Undoc Win")
216  */
217
218 BOOL16 IsValidMetaFile(HMETAFILE16 hmf)
219 {
220     BOOL16 resu=FALSE;
221     METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
222     if (mh) {
223       if (mh->mtType == 1 || mh->mtType == 0) 
224         if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
225           if (mh->mtVersion == MFVERSION)
226             resu=TRUE;
227       GlobalUnlock16(hmf);
228     }
229     dprintf_metafile(stddeb,"IsValidMetaFile %x => %d\n",hmf,resu);
230     return resu;         
231 }
232
233
234 /******************************************************************
235  *         PlayMetafile16   (GDI.123)
236  */
237 BOOL16 PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
238 {
239     return PlayMetaFile32( hdc, hmf );
240 }
241
242
243 /******************************************************************
244  *         PlayMetafile32   (GDI32.265)
245  */
246 BOOL32 PlayMetaFile32( HDC32 hdc, HMETAFILE32 hmf )
247 {
248     METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
249     METARECORD *mr;
250     HANDLETABLE16 *ht;
251     HGLOBAL16 hHT;
252     int offset = 0;
253     WORD i;
254     HPEN32 hPen;
255     HBRUSH32 hBrush;
256     HFONT32 hFont;
257     DC *dc;
258
259     dprintf_metafile(stddeb,"PlayMetaFile(%04x %04x)\n",hdc,hmf);
260
261     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
262     hPen = dc->w.hPen;
263     hBrush = dc->w.hBrush;
264     hFont = dc->w.hFont;
265
266     /* create the handle table */
267     hHT = GlobalAlloc16(GMEM_MOVEABLE|GMEM_ZEROINIT,
268                       sizeof(HANDLETABLE16) * mh->mtNoObjects);
269     ht = (HANDLETABLE16 *)GlobalLock16(hHT);
270
271     /* loop through metafile playing records */
272     offset = mh->mtHeaderSize * 2;
273     while (offset < mh->mtSize * 2)
274     {
275         mr = (METARECORD *)((char *)mh + offset);
276         dprintf_metafile(stddeb,"offset = %04x size = %08lx function = %04x\n",
277                          offset,mr->rdSize,mr->rdFunction);
278         offset += mr->rdSize * 2;
279         PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
280     }
281
282     SelectObject32(hdc, hBrush);
283     SelectObject32(hdc, hPen);
284     SelectObject32(hdc, hFont);
285
286     /* free objects in handle table */
287     for(i = 0; i < mh->mtNoObjects; i++)
288       if(*(ht->objectHandle + i) != 0)
289         DeleteObject32(*(ht->objectHandle + i));
290     
291     /* free handle table */
292     GlobalFree16(hHT);
293
294     return TRUE;
295 }
296
297
298 /******************************************************************
299  *            EnumMetaFile16   (GDI.175)
300  *                                    Niels de carpentier, april 1996
301  */
302 BOOL16 EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf, MFENUMPROC16 lpEnumFunc,
303                        LPARAM lpData )
304 {
305     METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
306     METARECORD *mr;
307     HANDLETABLE16 *ht;
308     HGLOBAL16 hHT;
309     SEGPTR spht, spRecord;
310     int offset = 0;
311     WORD i;
312     HPEN32 hPen;
313     HBRUSH32 hBrush;
314     HFONT32 hFont;
315     DC *dc;
316     
317     dprintf_metafile(stddeb,"EnumMetaFile(%04x, %04x, %08lx, %08lx)\n",
318                      hdc, hmf, (DWORD)lpEnumFunc, lpData);
319
320     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
321     hPen = dc->w.hPen;
322     hBrush = dc->w.hBrush;
323     hFont = dc->w.hFont;
324    
325     /* create the handle table */
326     
327     hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
328                      sizeof(HANDLETABLE16) * mh->mtNoObjects);
329     spht = WIN16_GlobalLock16(hHT);
330    
331     offset = mh->mtHeaderSize * 2;
332     
333     /* loop through metafile records */
334     
335     spRecord = WIN16_GlobalLock16(hmf);
336     while (offset < (mh->mtSize * 2))
337     {
338         mr = (METARECORD *)((char *)mh + offset);
339         if (!lpEnumFunc( hdc, (HANDLETABLE16 *)spht,
340                          (METARECORD *)((UINT32)spRecord + offset),
341                          mh->mtNoObjects, (LONG)lpData))
342             break;
343
344         offset += (mr->rdSize * 2);
345     }
346
347     SelectObject32(hdc, hBrush);
348     SelectObject32(hdc, hPen);
349     SelectObject32(hdc, hFont);
350
351     ht = (HANDLETABLE16 *)GlobalLock16(hHT);
352
353     /* free objects in handle table */
354     for(i = 0; i < mh->mtNoObjects; i++)
355       if(*(ht->objectHandle + i) != 0)
356         DeleteObject32(*(ht->objectHandle + i));
357
358     /* free handle table */
359     GlobalFree16(hHT);
360
361     return TRUE;
362 }
363
364
365 /******************************************************************
366  *             PlayMetaFileRecord16   (GDI.176)
367  */
368 void PlayMetaFileRecord16( HDC16 hdc, HANDLETABLE16 *ht, METARECORD *mr,
369                            UINT16 nHandles )
370 {
371     short s1;
372     HANDLE16 hndl;
373     char *ptr;
374     BITMAPINFOHEADER *infohdr;
375
376     dprintf_metafile(stddeb,"PlayMetaFileRecord(%04x %08lx %08lx %04x)\n",
377                      hdc,(LONG)ht, (LONG)mr, nHandles);
378     
379     switch (mr->rdFunction)
380     {
381     case META_EOF:
382       break;
383
384     case META_DELETEOBJECT:
385       DeleteObject32(*(ht->objectHandle + *(mr->rdParam)));
386       *(ht->objectHandle + *(mr->rdParam)) = 0;
387       break;
388
389     case META_SETBKCOLOR:
390         SetBkColor16(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
391         break;
392
393     case META_SETBKMODE:
394         SetBkMode16(hdc, *(mr->rdParam));
395         break;
396
397     case META_SETMAPMODE:
398         SetMapMode16(hdc, *(mr->rdParam));
399         break;
400
401     case META_SETROP2:
402         SetROP216(hdc, *(mr->rdParam));
403         break;
404
405     case META_SETRELABS:
406         SetRelAbs16(hdc, *(mr->rdParam));
407         break;
408
409     case META_SETPOLYFILLMODE:
410         SetPolyFillMode16(hdc, *(mr->rdParam));
411         break;
412
413     case META_SETSTRETCHBLTMODE:
414         SetStretchBltMode16(hdc, *(mr->rdParam));
415         break;
416     case META_SETTEXTCOLOR:
417         SetTextColor16(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
418         break;
419
420     case META_SETWINDOWORG:
421         SetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
422         break;
423
424     case META_SETWINDOWEXT:
425         SetWindowExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
426         break;
427
428     case META_SETVIEWPORTORG:
429         SetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
430         break;
431
432     case META_SETVIEWPORTEXT:
433         SetViewportExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
434         break;
435
436     case META_OFFSETWINDOWORG:
437         OffsetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
438         break;
439
440     case META_SCALEWINDOWEXT:
441         ScaleWindowExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
442                        *(mr->rdParam + 1), *(mr->rdParam));
443         break;
444
445     case META_OFFSETVIEWPORTORG:
446         OffsetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
447         break;
448
449     case META_SCALEVIEWPORTEXT:
450         ScaleViewportExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
451                          *(mr->rdParam + 1), *(mr->rdParam));
452         break;
453
454     case META_LINETO:
455         LineTo32(hdc, (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
456         break;
457
458     case META_MOVETO:
459         MoveTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
460         break;
461
462     case META_EXCLUDECLIPRECT:
463         ExcludeClipRect16( hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
464                            *(mr->rdParam + 1), *(mr->rdParam) );
465         break;
466
467     case META_INTERSECTCLIPRECT:
468         IntersectClipRect16( hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
469                              *(mr->rdParam + 1), *(mr->rdParam) );
470         break;
471
472     case META_ARC:
473         Arc32(hdc, (INT16)*(mr->rdParam + 7), (INT16)*(mr->rdParam + 6),
474               (INT16)*(mr->rdParam + 5), (INT16)*(mr->rdParam + 4),
475               (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
476              (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
477         break;
478
479     case META_ELLIPSE:
480         Ellipse32(hdc, (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
481                   (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
482         break;
483
484     case META_FLOODFILL:
485         FloodFill32(hdc, (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
486                     MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
487         break;
488
489     case META_PIE:
490         Pie32(hdc, (INT16)*(mr->rdParam + 7), (INT16)*(mr->rdParam + 6),
491               (INT16)*(mr->rdParam + 5), (INT16)*(mr->rdParam + 4),
492               (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
493              (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
494         break;
495
496     case META_RECTANGLE:
497         Rectangle32(hdc, (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
498                     (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
499         break;
500
501     case META_ROUNDRECT:
502         RoundRect32(hdc, (INT16)*(mr->rdParam + 5), (INT16)*(mr->rdParam + 4),
503                     (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
504                     (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
505         break;
506
507     case META_PATBLT:
508         PatBlt16(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
509                  *(mr->rdParam + 3), *(mr->rdParam + 2),
510                  MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
511         break;
512
513     case META_SAVEDC:
514         SaveDC32(hdc);
515         break;
516
517     case META_SETPIXEL:
518         SetPixel32(hdc, (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
519                    MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
520         break;
521
522     case META_OFFSETCLIPRGN:
523         OffsetClipRgn16( hdc, *(mr->rdParam + 1), *(mr->rdParam) );
524         break;
525
526     case META_TEXTOUT:
527         s1 = *(mr->rdParam);
528         TextOut16(hdc, *(mr->rdParam + ((s1 + 1) >> 1) + 2),
529                   *(mr->rdParam + ((s1 + 1) >> 1) + 1), 
530                   (char *)(mr->rdParam + 1), s1);
531         break;
532
533     case META_POLYGON:
534         Polygon16(hdc, (LPPOINT16)(mr->rdParam + 1), *(mr->rdParam));
535         break;
536
537     case META_POLYPOLYGON:
538       PolyPolygon16(hdc, (LPPOINT16)(mr->rdParam + *(mr->rdParam) + 1),
539                     (LPINT16)(mr->rdParam + 1), *(mr->rdParam)); 
540       break;
541
542     case META_POLYLINE:
543         Polyline16(hdc, (LPPOINT16)(mr->rdParam + 1), *(mr->rdParam));
544         break;
545
546     case META_RESTOREDC:
547         RestoreDC32(hdc, (INT16)*(mr->rdParam));
548         break;
549
550     case META_SELECTOBJECT:
551         SelectObject32(hdc, *(ht->objectHandle + *(mr->rdParam)));
552         break;
553
554     case META_CHORD:
555         Chord32(hdc, (INT16)*(mr->rdParam + 7), (INT16)*(mr->rdParam + 6),
556                 (INT16)*(mr->rdParam+5), (INT16)*(mr->rdParam + 4),
557                 (INT16)*(mr->rdParam + 3), (INT16)*(mr->rdParam + 2),
558                (INT16)*(mr->rdParam + 1), (INT16)*(mr->rdParam));
559         break;
560
561     case META_CREATEPATTERNBRUSH:
562         switch (*(mr->rdParam))
563         {
564         case BS_PATTERN:
565             infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
566             MF_AddHandle(ht, nHandles,
567                          CreatePatternBrush32(CreateBitmap32(infohdr->biWidth, 
568                                       infohdr->biHeight, 
569                                       infohdr->biPlanes, 
570                                       infohdr->biBitCount,
571                                       (LPSTR)(mr->rdParam + 
572                                       (sizeof(BITMAPINFOHEADER) / 2) + 4))));
573             break;
574
575         case BS_DIBPATTERN:
576             s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
577             hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
578             ptr = GlobalLock16(hndl);
579             memcpy(ptr, mr->rdParam + 2, s1);
580             GlobalUnlock16(hndl);
581             MF_AddHandle(ht, nHandles,
582                          CreateDIBPatternBrush32(hndl, *(mr->rdParam + 1)));
583             GlobalFree16(hndl);
584         }
585         break;
586         
587     case META_CREATEPENINDIRECT:
588         MF_AddHandle(ht, nHandles, 
589                      CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParam))));
590         break;
591
592     case META_CREATEFONTINDIRECT:
593         MF_AddHandle(ht, nHandles, 
594                      CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParam))));
595         break;
596
597     case META_CREATEBRUSHINDIRECT:
598         MF_AddHandle(ht, nHandles, 
599                      CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParam))));
600         break;
601
602     /* W. Magro: Some new metafile operations.  Not all debugged. */
603     case META_CREATEPALETTE:
604         MF_AddHandle(ht, nHandles, 
605                      CreatePalette16((LPLOGPALETTE)mr->rdParam));
606         break;
607
608     case META_SETTEXTALIGN:
609         SetTextAlign16(hdc, *(mr->rdParam));
610         break;
611
612     case META_SELECTPALETTE:
613         SelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParam+1)),*(mr->rdParam));
614         break;
615
616     case META_SETMAPPERFLAGS:
617         SetMapperFlags16(hdc, *(mr->rdParam));
618         break;
619
620     case META_REALIZEPALETTE:
621         RealizePalette16(hdc);
622         break;
623
624     case META_ESCAPE:
625         dprintf_metafile(stddeb,"PlayMetaFileRecord: META_ESCAPE unimplemented.\n");
626         break;
627
628         /* --- Begin of fixed or new metafile operations. July 1996 ----*/
629     case META_EXTTEXTOUT:
630       {
631         LPINT16 dxx;
632         LPSTR sot; 
633         DWORD len;
634
635         s1 = mr->rdParam[2];                              /* String length */
636         len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
637          + sizeof(UINT16) +  (mr->rdParam[3] ? sizeof(RECT16) : 0);  /* rec len without dx array */
638
639         sot= (LPSTR)&mr->rdParam[4];                    /* start_of_text */
640         if (mr->rdParam[3])
641            sot+=sizeof(RECT16);                         /* there is a rectangle, so add offset */
642          
643         if (mr->rdSize == len / 2)
644           dxx = NULL;                                   /* determine if array present */
645         else 
646           if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
647             dxx = (LPINT16)(sot+(((s1+1)>>1)*2));          
648           else 
649           {
650            fprintf(stderr,
651              "Please report: PlayMetaFile/ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
652                    len,s1,mr->rdSize,mr->rdParam[3]);
653            dxx = NULL; /* should't happen -- but if, we continue with NULL [for workaround] */
654           }
655         ExtTextOut16( hdc, mr->rdParam[1],              /* X position */
656                            mr->rdParam[0],              /* Y position */
657                            mr->rdParam[3],              /* options */
658                            mr->rdParam[3] ? (LPRECT16) &mr->rdParam[4]:NULL,  /* rectangle */
659                            sot,                         /* string */
660                            s1, dxx);                    /* length, dx array */
661         if (dxx)                      
662           dprintf_metafile(stddeb,"EXTTEXTOUT: %s  len: %ld  dx0: %d\n",
663             sot,mr->rdSize,dxx[0]);
664        }
665        break;
666     
667     case META_STRETCHDIB:
668       {
669        LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[11]);
670        LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParam[2] );
671        StretchDIBits16(hdc,mr->rdParam[10],mr->rdParam[9],mr->rdParam[8],
672                        mr->rdParam[7],mr->rdParam[6],mr->rdParam[5],
673                        mr->rdParam[4],mr->rdParam[3],bits,info,
674                        mr->rdParam[2],MAKELONG(mr->rdParam[0],mr->rdParam[1]));
675       }
676       break;
677
678     case META_DIBSTRETCHBLT:
679       {
680        LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[10]); 
681        LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParam[2] );
682        StretchDIBits16(hdc,mr->rdParam[9],mr->rdParam[8],mr->rdParam[7],
683                        mr->rdParam[6],mr->rdParam[5],mr->rdParam[4],
684                        mr->rdParam[3],mr->rdParam[2],bits,info,
685                        DIB_RGB_COLORS,MAKELONG(mr->rdParam[0],mr->rdParam[1]));
686       }
687       break;              
688
689     case META_STRETCHBLT:
690       {
691        HDC16 hdcSrc=CreateCompatibleDC16(hdc);
692        HBITMAP32 hbitmap=CreateBitmap32(mr->rdParam[10], /*Width */
693                                         mr->rdParam[11], /*Height*/
694                                         mr->rdParam[13], /*Planes*/
695                                         mr->rdParam[14], /*BitsPixel*/
696                                         (LPSTR)&mr->rdParam[15]);  /*bits*/
697        SelectObject32(hdcSrc,hbitmap);
698        StretchBlt16(hdc,mr->rdParam[9],mr->rdParam[8],
699                     mr->rdParam[7],mr->rdParam[6],
700                     hdcSrc,mr->rdParam[5],mr->rdParam[4],
701                     mr->rdParam[3],mr->rdParam[2],
702                     MAKELONG(mr->rdParam[0],mr->rdParam[1]));
703        DeleteDC32(hdcSrc);                  
704       }
705       break;
706
707     case META_BITBLT:            /* <-- not yet debugged */
708       {
709        HDC16 hdcSrc=CreateCompatibleDC16(hdc);
710        HBITMAP32 hbitmap=CreateBitmap32(mr->rdParam[7]/*Width */,
711                                         mr->rdParam[8]/*Height*/,
712                                         mr->rdParam[10]/*Planes*/,
713                                         mr->rdParam[11]/*BitsPixel*/,
714                                         (LPSTR)&mr->rdParam[12]/*bits*/);
715        SelectObject32(hdcSrc,hbitmap);
716        BitBlt32(hdc,(INT16)mr->rdParam[6],(INT16)mr->rdParam[5],
717                 (INT16)mr->rdParam[4],(INT16)mr->rdParam[3],
718                 hdcSrc, (INT16)mr->rdParam[2],(INT16)mr->rdParam[1],
719                 MAKELONG(0,mr->rdParam[0]));
720        DeleteDC32(hdcSrc);                  
721       }
722       break;
723
724        /* --- Begin of new metafile operations. April, 1997 (ak) ----*/
725     case META_CREATEREGION:
726          {
727             int i;
728             HRGN32 h1,h2,hrgn=CreateRectRgn32(mr->rdParam[7],mr->rdParam[8],
729                                               mr->rdParam[9],mr->rdParam[10]);
730             for (i=0,h1=CreateRectRgn32(0,0,0,0);i<mr->rdParam[5];i++)
731             {
732              if (mr->rdParam[11+i*6]==2)
733              { 
734                h2=CreateRectRgn32(mr->rdParam[14+i*6],mr->rdParam[12+i*6],
735                                   mr->rdParam[15+i*6],mr->rdParam[13+i*6]);
736                CombineRgn32(hrgn,h1,h2,mr->rdParam[16+i*6]);    /* e.g. RGN_OR */
737                h1=hrgn;
738              }
739             }
740             MF_AddHandle(ht, nHandles,hrgn);
741          }
742        break;
743
744      case META_FILLREGION:
745         FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParam)),
746                        *(ht->objectHandle + *(mr->rdParam+1)));
747         break;
748
749      case META_INVERTREGION:
750         InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParam)));
751         break; 
752
753      case META_PAINTREGION:
754         PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParam)));
755         break;
756
757      case META_SELECTCLIPREGION:
758         SelectClipRgn32(hdc, *(ht->objectHandle + *(mr->rdParam)));
759         break;
760
761      case META_DIBCREATEPATTERNBRUSH:
762         /*  *(mr->rdParam) may be BS_PATTERN or BS_DIBPATTERN: but there's no difference */
763         dprintf_metafile(stddeb,"META_DIBCREATEPATTERNBRUSH: %d\n",*(mr->rdParam));
764         s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
765         hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
766         ptr = GlobalLock16(hndl);
767         memcpy(ptr, mr->rdParam + 2, s1);
768         GlobalUnlock16(hndl);
769         MF_AddHandle(ht, nHandles,CreateDIBPatternBrush16(hndl, *(mr->rdParam + 1)));
770         GlobalFree16(hndl);
771         break;
772
773      case META_DIBBITBLT:
774         {
775          LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[8]);
776          LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParam[0] );
777          StretchDIBits16(hdc,mr->rdParam[7],mr->rdParam[6],mr->rdParam[5],
778                        mr->rdParam[4],mr->rdParam[3],mr->rdParam[2],
779                        mr->rdParam[5],mr->rdParam[4],bits,info,
780                        DIB_RGB_COLORS,MAKELONG(mr->rdParam[0],mr->rdParam[1]));
781         }
782         break;  
783        
784      case META_SETTEXTJUSTIFICATION:
785         SetTextJustification32(hdc, *(mr->rdParam + 1), *(mr->rdParam));
786         break;
787
788 #define META_UNIMP(x) case x: fprintf(stderr,"PlayMetaFileRecord:record type "#x" not implemented.\n");break;
789     META_UNIMP(META_SETTEXTCHAREXTRA)
790     META_UNIMP(META_FRAMEREGION)
791     META_UNIMP(META_DRAWTEXT)
792     META_UNIMP(META_SETDIBTODEV)
793     META_UNIMP(META_ANIMATEPALETTE)
794     META_UNIMP(META_SETPALENTRIES)
795     META_UNIMP(META_RESIZEPALETTE)
796     META_UNIMP(META_EXTFLOODFILL)
797     META_UNIMP(META_RESETDC)
798     META_UNIMP(META_STARTDOC)
799     META_UNIMP(META_STARTPAGE)
800     META_UNIMP(META_ENDPAGE)
801     META_UNIMP(META_ABORTDOC)
802     META_UNIMP(META_ENDDOC)
803     META_UNIMP(META_CREATEBRUSH)
804     META_UNIMP(META_CREATEBITMAPINDIRECT)
805     META_UNIMP(META_CREATEBITMAP)
806 #undef META_UNIMP
807
808     default:
809         fprintf(stddeb,"PlayMetaFileRecord: Unknown record type %x\n",
810                                               mr->rdFunction);
811     }
812 }
813
814
815 /******************************************************************
816  *         GetMetaFileBits   (GDI.159)
817  *
818  * Trade in a meta file object handle for a handle to the meta file memory
819  */
820
821 HGLOBAL16 GetMetaFileBits(HMETAFILE16 hmf)
822 {
823     dprintf_metafile(stddeb,"GetMetaFileBits: hMem out: %04x\n", hmf);
824
825     return hmf;
826 }
827
828 /******************************************************************
829  *         SetMetaFileBits   (GDI.160)
830  *
831  * Trade in a meta file memory handle for a handle to a meta file object
832  */
833 HMETAFILE16 SetMetaFileBits( HGLOBAL16 hMem )
834 {
835     dprintf_metafile(stddeb,"SetMetaFileBits: hmf out: %04x\n", hMem);
836
837     return hMem;
838 }
839
840 /******************************************************************
841  *         SetMetaFileBitsBetter   (GDI.196)
842  */
843 HMETAFILE16 SetMetaFileBitsBetter( HMETAFILE16 hMeta )
844 {
845    if( IsValidMetaFile( hMeta ) )
846        return (HMETAFILE16)GlobalReAlloc16( hMeta, 0, 
847                            GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
848    return (HMETAFILE16)0;
849 }
850
851 /******************************************************************
852  *         MF_WriteRecord
853  *
854  * Warning: this function can change the metafile handle.
855  */
856
857 static BOOL32 MF_WriteRecord( DC *dc, METARECORD *mr, WORD rlen)
858 {
859     DWORD len;
860     METAHEADER *mh;
861     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
862
863     switch(physDev->mh->mtType)
864     {
865     case METAFILE_MEMORY:
866         len = physDev->mh->mtSize * 2 + rlen;
867         mh = HeapReAlloc( SystemHeap, 0, physDev->mh, len );
868         if (!mh) return FALSE;
869         physDev->mh = mh;
870         memcpy((WORD *)physDev->mh + physDev->mh->mtSize, mr, rlen);
871         break;
872     case METAFILE_DISK:
873         dprintf_metafile(stddeb,"Writing record to disk\n");
874         if (_lwrite32(physDev->mh->mtNoParameters, (char *)mr, rlen) == -1)
875             return FALSE;
876         break;
877     default:
878         fprintf( stderr, "Unknown metafile type %d\n", physDev->mh->mtType );
879         return FALSE;
880     }
881
882     physDev->mh->mtSize += rlen / 2;
883     physDev->mh->mtMaxRecord = MAX(physDev->mh->mtMaxRecord, rlen / 2);
884     return TRUE;
885 }
886
887
888 /******************************************************************
889  *         MF_MetaParam0
890  */
891
892 BOOL32 MF_MetaParam0(DC *dc, short func)
893 {
894     char buffer[8];
895     METARECORD *mr = (METARECORD *)&buffer;
896     
897     mr->rdSize = 3;
898     mr->rdFunction = func;
899     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
900 }
901
902
903 /******************************************************************
904  *         MF_MetaParam1
905  */
906 BOOL32 MF_MetaParam1(DC *dc, short func, short param1)
907 {
908     char buffer[8];
909     METARECORD *mr = (METARECORD *)&buffer;
910     
911     mr->rdSize = 4;
912     mr->rdFunction = func;
913     *(mr->rdParam) = param1;
914     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
915 }
916
917
918 /******************************************************************
919  *         MF_MetaParam2
920  */
921 BOOL32 MF_MetaParam2(DC *dc, short func, short param1, short param2)
922 {
923     char buffer[10];
924     METARECORD *mr = (METARECORD *)&buffer;
925     
926     mr->rdSize = 5;
927     mr->rdFunction = func;
928     *(mr->rdParam) = param2;
929     *(mr->rdParam + 1) = param1;
930     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
931 }
932
933
934 /******************************************************************
935  *         MF_MetaParam4
936  */
937
938 BOOL32 MF_MetaParam4(DC *dc, short func, short param1, short param2, 
939                    short param3, short param4)
940 {
941     char buffer[14];
942     METARECORD *mr = (METARECORD *)&buffer;
943     
944     mr->rdSize = 7;
945     mr->rdFunction = func;
946     *(mr->rdParam) = param4;
947     *(mr->rdParam + 1) = param3;
948     *(mr->rdParam + 2) = param2;
949     *(mr->rdParam + 3) = param1;
950     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
951 }
952
953
954 /******************************************************************
955  *         MF_MetaParam6
956  */
957
958 BOOL32 MF_MetaParam6(DC *dc, short func, short param1, short param2, 
959                    short param3, short param4, short param5, short param6)
960 {
961     char buffer[18];
962     METARECORD *mr = (METARECORD *)&buffer;
963     
964     mr->rdSize = 9;
965     mr->rdFunction = func;
966     *(mr->rdParam) = param6;
967     *(mr->rdParam + 1) = param5;
968     *(mr->rdParam + 2) = param4;
969     *(mr->rdParam + 3) = param3;
970     *(mr->rdParam + 4) = param2;
971     *(mr->rdParam + 5) = param1;
972     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
973 }
974
975
976 /******************************************************************
977  *         MF_MetaParam8
978  */
979 BOOL32 MF_MetaParam8(DC *dc, short func, short param1, short param2, 
980                    short param3, short param4, short param5,
981                    short param6, short param7, short param8)
982 {
983     char buffer[22];
984     METARECORD *mr = (METARECORD *)&buffer;
985     
986     mr->rdSize = 11;
987     mr->rdFunction = func;
988     *(mr->rdParam) = param8;
989     *(mr->rdParam + 1) = param7;
990     *(mr->rdParam + 2) = param6;
991     *(mr->rdParam + 3) = param5;
992     *(mr->rdParam + 4) = param4;
993     *(mr->rdParam + 5) = param3;
994     *(mr->rdParam + 6) = param2;
995     *(mr->rdParam + 7) = param1;
996     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
997 }
998
999
1000 /******************************************************************
1001  *         MF_CreateBrushIndirect
1002  */
1003
1004 BOOL32 MF_CreateBrushIndirect(DC *dc, HBRUSH16 hBrush, LOGBRUSH16 *logbrush)
1005 {
1006     int index;
1007     char buffer[sizeof(METARECORD) - 2 + sizeof(*logbrush)];
1008     METARECORD *mr = (METARECORD *)&buffer;
1009
1010     mr->rdSize = (sizeof(METARECORD) + sizeof(*logbrush) - 2) / 2;
1011     mr->rdFunction = META_CREATEBRUSHINDIRECT;
1012     memcpy(&(mr->rdParam), logbrush, sizeof(*logbrush));
1013     if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1014
1015     mr->rdSize = sizeof(METARECORD) / 2;
1016     mr->rdFunction = META_SELECTOBJECT;
1017
1018     if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1019     *(mr->rdParam) = index;
1020     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1021 }
1022
1023
1024 /******************************************************************
1025  *         MF_CreatePatternBrush
1026  */
1027
1028 BOOL32 MF_CreatePatternBrush(DC *dc, HBRUSH16 hBrush, LOGBRUSH16 *logbrush)
1029 {
1030     DWORD len, bmSize, biSize;
1031     HGLOBAL16 hmr;
1032     METARECORD *mr;
1033     BITMAPOBJ *bmp;
1034     BITMAPINFO *info;
1035     BITMAPINFOHEADER *infohdr;
1036     int index;
1037     char buffer[sizeof(METARECORD)];
1038
1039     switch (logbrush->lbStyle)
1040     {
1041     case BS_PATTERN:
1042         bmp = (BITMAPOBJ *)GDI_GetObjPtr((HGDIOBJ16)logbrush->lbHatch, BITMAP_MAGIC);
1043         if (!bmp) return FALSE;
1044         len = sizeof(METARECORD) + sizeof(BITMAPINFOHEADER) + 
1045               (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 6;
1046         if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1047             return FALSE;
1048         mr = (METARECORD *)GlobalLock16(hmr);
1049         memset(mr, 0, len);
1050         mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1051         mr->rdSize = len / 2;
1052         *(mr->rdParam) = logbrush->lbStyle;
1053         *(mr->rdParam + 1) = DIB_RGB_COLORS;
1054         infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
1055         infohdr->biSize = sizeof(BITMAPINFOHEADER);
1056         infohdr->biWidth = bmp->bitmap.bmWidth;
1057         infohdr->biHeight = bmp->bitmap.bmHeight;
1058         infohdr->biPlanes = bmp->bitmap.bmPlanes;
1059         infohdr->biBitCount = bmp->bitmap.bmBitsPixel;
1060         memcpy(mr->rdParam + (sizeof(BITMAPINFOHEADER) / 2) + 4,
1061                PTR_SEG_TO_LIN(bmp->bitmap.bmBits),
1062                bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes);
1063         break;
1064
1065     case BS_DIBPATTERN:
1066         info = (BITMAPINFO *)GlobalLock16((HGLOBAL16)logbrush->lbHatch);
1067         if (info->bmiHeader.biCompression)
1068             bmSize = info->bmiHeader.biSizeImage;
1069         else
1070             bmSize = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount 
1071                     + 31) / 32 * 8 * info->bmiHeader.biHeight;
1072         biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush->lbColor)); 
1073         len = sizeof(METARECORD) + biSize + bmSize + 2;
1074         if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1075             return FALSE;
1076         mr = (METARECORD *)GlobalLock16(hmr);
1077         memset(mr, 0, len);
1078         mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1079         mr->rdSize = len / 2;
1080         *(mr->rdParam) = logbrush->lbStyle;
1081         *(mr->rdParam + 1) = LOWORD(logbrush->lbColor);
1082         memcpy(mr->rdParam + 2, info, biSize + bmSize);
1083         break;
1084     default:
1085         return FALSE;
1086     }
1087     if (!(MF_WriteRecord(dc, mr, len)))
1088     {
1089         GlobalFree16(hmr);
1090         return FALSE;
1091     }
1092
1093     GlobalFree16(hmr);
1094     
1095     mr = (METARECORD *)&buffer;
1096     mr->rdSize = sizeof(METARECORD) / 2;
1097     mr->rdFunction = META_SELECTOBJECT;
1098
1099     if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1100     *(mr->rdParam) = index;
1101     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1102 }
1103
1104
1105 /******************************************************************
1106  *         MF_CreatePenIndirect
1107  */
1108
1109 BOOL32 MF_CreatePenIndirect(DC *dc, HPEN16 hPen, LOGPEN16 *logpen)
1110 {
1111     int index;
1112     char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
1113     METARECORD *mr = (METARECORD *)&buffer;
1114
1115     mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
1116     mr->rdFunction = META_CREATEPENINDIRECT;
1117     memcpy(&(mr->rdParam), logpen, sizeof(*logpen));
1118     if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1119
1120     mr->rdSize = sizeof(METARECORD) / 2;
1121     mr->rdFunction = META_SELECTOBJECT;
1122
1123     if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1124     *(mr->rdParam) = index;
1125     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1126 }
1127
1128
1129 /******************************************************************
1130  *         MF_CreateFontIndirect
1131  */
1132
1133 BOOL32 MF_CreateFontIndirect(DC *dc, HFONT16 hFont, LOGFONT16 *logfont)
1134 {
1135     int index;
1136     char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
1137     METARECORD *mr = (METARECORD *)&buffer;
1138
1139     mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
1140     mr->rdFunction = META_CREATEFONTINDIRECT;
1141     memcpy(&(mr->rdParam), logfont, sizeof(LOGFONT16));
1142     if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1143
1144     mr->rdSize = sizeof(METARECORD) / 2;
1145     mr->rdFunction = META_SELECTOBJECT;
1146
1147     if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1148     *(mr->rdParam) = index;
1149     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1150 }
1151
1152
1153 /******************************************************************
1154  *         MF_TextOut
1155  */
1156 BOOL32 MF_TextOut(DC *dc, short x, short y, LPCSTR str, short count)
1157 {
1158     BOOL32 ret;
1159     DWORD len;
1160     HGLOBAL16 hmr;
1161     METARECORD *mr;
1162
1163     len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4;
1164     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1165         return FALSE;
1166     mr = (METARECORD *)GlobalLock16(hmr);
1167     memset(mr, 0, len);
1168
1169     mr->rdSize = len / 2;
1170     mr->rdFunction = META_TEXTOUT;
1171     *(mr->rdParam) = count;
1172     memcpy(mr->rdParam + 1, str, count);
1173     *(mr->rdParam + ((count + 1) >> 1) + 1) = y;
1174     *(mr->rdParam + ((count + 1) >> 1) + 2) = x;
1175     ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1176     GlobalFree16(hmr);
1177     return ret;
1178 }
1179
1180 /******************************************************************
1181  *         MF_ExtTextOut
1182  */
1183 BOOL32 MF_ExtTextOut(DC*dc, short x, short y, UINT16 flags, const RECT16 *rect,
1184                      LPCSTR str, short count, const INT16 *lpDx)
1185 {
1186     BOOL32 ret;
1187     DWORD len;
1188     HGLOBAL16 hmr;
1189     METARECORD *mr;
1190     
1191     if((!flags && rect) || (flags && !rect))
1192         fprintf(stderr, "MF_ExtTextOut: Inconsistent flags and rect\n");
1193     len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 2 * sizeof(short)
1194             + sizeof(UINT16);
1195     if(rect)
1196         len += sizeof(RECT16);
1197     if (lpDx)
1198      len+=count*sizeof(INT16);
1199     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1200         return FALSE;
1201     mr = (METARECORD *)GlobalLock16(hmr);
1202     memset(mr, 0, len);
1203
1204     mr->rdSize = len / 2;
1205     mr->rdFunction = META_EXTTEXTOUT;
1206     *(mr->rdParam) = y;
1207     *(mr->rdParam + 1) = x;
1208     *(mr->rdParam + 2) = count;
1209     *(mr->rdParam + 3) = flags;
1210     if (rect) memcpy(mr->rdParam + 4, rect, sizeof(RECT16));
1211     memcpy(mr->rdParam + (rect ? 8 : 4), str, count);
1212     if (lpDx)
1213      memcpy(mr->rdParam + (rect ? 8 : 4) + ((count + 1) >> 1),lpDx,
1214       count*sizeof(INT16));
1215     ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1216     GlobalFree16(hmr);
1217     return ret;
1218 }
1219
1220 /******************************************************************
1221  *         MF_MetaPoly - implements Polygon and Polyline
1222  */
1223 BOOL32 MF_MetaPoly(DC *dc, short func, LPPOINT16 pt, short count)
1224 {
1225     BOOL32 ret;
1226     DWORD len;
1227     HGLOBAL16 hmr;
1228     METARECORD *mr;
1229
1230     len = sizeof(METARECORD) + (count * 4); 
1231     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1232         return FALSE;
1233     mr = (METARECORD *)GlobalLock16(hmr);
1234     memset(mr, 0, len);
1235
1236     mr->rdSize = len / 2;
1237     mr->rdFunction = func;
1238     *(mr->rdParam) = count;
1239     memcpy(mr->rdParam + 1, pt, count * 4);
1240     ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1241     GlobalFree16(hmr);
1242     return ret;
1243 }
1244
1245
1246 /******************************************************************
1247  *         MF_BitBlt
1248  */
1249 BOOL32 MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
1250                  short height, DC *dcSrc, short xSrc, short ySrc, DWORD rop)
1251 {
1252     BOOL32 ret;
1253     DWORD len;
1254     HGLOBAL16 hmr;
1255     METARECORD *mr;
1256     BITMAP16  BM;
1257
1258     GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1259     len = sizeof(METARECORD) + 12 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1260     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1261         return FALSE;
1262     mr = (METARECORD *)GlobalLock16(hmr);
1263     mr->rdFunction = META_BITBLT;
1264     *(mr->rdParam + 7) = BM.bmWidth;
1265     *(mr->rdParam + 8) = BM.bmHeight;
1266     *(mr->rdParam + 9) = BM.bmWidthBytes;
1267     *(mr->rdParam +10) = BM.bmPlanes;
1268     *(mr->rdParam +11) = BM.bmBitsPixel;
1269     dprintf_metafile(stddeb,"MF_StretchBlt->len = %ld  rop=%lx  \n",len,rop);
1270     if (GetBitmapBits32(dcSrc->w.hBitmap,BM.bmWidthBytes * BM.bmHeight,
1271                         mr->rdParam +12))
1272     {
1273       mr->rdSize = len / sizeof(INT16);
1274       *(mr->rdParam) = HIWORD(rop);
1275       *(mr->rdParam + 1) = ySrc;
1276       *(mr->rdParam + 2) = xSrc;
1277       *(mr->rdParam + 3) = height;
1278       *(mr->rdParam + 4) = width;
1279       *(mr->rdParam + 5) = yDest;
1280       *(mr->rdParam + 6) = xDest;
1281       ret = MF_WriteRecord( dcDest, mr, mr->rdSize * 2);
1282     }  
1283     else
1284         ret = FALSE;
1285     GlobalFree16(hmr);
1286     return ret;
1287 }
1288
1289
1290 /**********************************************************************
1291  *         MF_StretchBlt         
1292  * this function contains TWO ways for procesing StretchBlt in metafiles,
1293  * decide between rdFunction values  META_STRETCHBLT or META_DIBSTRETCHBLT
1294  * via #define STRETCH_VIA_DIB
1295  */
1296 #define STRETCH_VIA_DIB
1297 #undef  STRETCH_VIA_DIB
1298 BOOL32 MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
1299                      short heightDest, DC *dcSrc, short xSrc, short ySrc, 
1300                      short widthSrc, short heightSrc, DWORD rop)
1301 {
1302     BOOL32 ret;
1303     DWORD len;
1304     HGLOBAL16 hmr;
1305     METARECORD *mr;
1306     BITMAP16  BM;
1307 #ifdef STRETCH_VIA_DIB    
1308     LPBITMAPINFOHEADER lpBMI;
1309     WORD nBPP;
1310 #endif  
1311     GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1312 #ifdef STRETCH_VIA_DIB
1313     nBPP = BM.bmPlanes * BM.bmBitsPixel;
1314     len = sizeof(METARECORD) + 10 * sizeof(INT16) 
1315             + sizeof(BITMAPINFOHEADER) + (nBPP != 24 ? 1 << nBPP: 0) * sizeof(RGBQUAD) 
1316               + ((BM.bmWidth * nBPP + 31) / 32) * 4 * BM.bmHeight;
1317     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1318         return FALSE;
1319     mr = (METARECORD *)GlobalLock16(hmr);
1320     mr->rdFunction = META_DIBSTRETCHBLT;
1321     lpBMI=(LPBITMAPINFOHEADER)(mr->rdParam+10);
1322     lpBMI->biSize      = sizeof(BITMAPINFOHEADER);
1323     lpBMI->biWidth     = BM.bmWidth;
1324     lpBMI->biHeight    = BM.bmHeight;
1325     lpBMI->biPlanes    = 1;
1326     lpBMI->biBitCount  = nBPP;                              /* 1,4,8 or 24 */
1327     lpBMI->biClrUsed   = nBPP != 24 ? 1 << nBPP : 0;
1328     lpBMI->biSizeImage = ((lpBMI->biWidth * nBPP + 31) / 32) * 4 * lpBMI->biHeight;
1329     lpBMI->biCompression = BI_RGB;
1330     lpBMI->biXPelsPerMeter = MulDiv32(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSX),3937,100);
1331     lpBMI->biYPelsPerMeter = MulDiv32(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSY),3937,100);
1332     lpBMI->biClrImportant  = 0;                          /* 1 meter  = 39.37 inch */
1333
1334     dprintf_metafile(stddeb,"MF_StretchBltViaDIB->len = %ld  rop=%lx  PixYPM=%ld Caps=%d\n",
1335                len,rop,lpBMI->biYPelsPerMeter,GetDeviceCaps(hdcSrc,LOGPIXELSY));
1336     if (GetDIBits(hdcSrc,dcSrc->w.hBitmap,0,(UINT32)lpBMI->biHeight,
1337                   (LPSTR)lpBMI + DIB_BitmapInfoSize( (BITMAPINFO *)lpBMI,
1338                                                      DIB_RGB_COLORS ),
1339                   (LPBITMAPINFO)lpBMI, DIB_RGB_COLORS))
1340 #else
1341     len = sizeof(METARECORD) + 15 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1342     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1343         return FALSE;
1344     mr = (METARECORD *)GlobalLock16(hmr);
1345     mr->rdFunction = META_STRETCHBLT;
1346     *(mr->rdParam +10) = BM.bmWidth;
1347     *(mr->rdParam +11) = BM.bmHeight;
1348     *(mr->rdParam +12) = BM.bmWidthBytes;
1349     *(mr->rdParam +13) = BM.bmPlanes;
1350     *(mr->rdParam +14) = BM.bmBitsPixel;
1351     dprintf_metafile(stddeb,"MF_StretchBlt->len = %ld  rop=%lx  \n",len,rop);
1352     if (GetBitmapBits32( dcSrc->w.hBitmap, BM.bmWidthBytes * BM.bmHeight,
1353                          mr->rdParam +15))
1354 #endif    
1355     {
1356       mr->rdSize = len / sizeof(INT16);
1357       *(mr->rdParam) = LOWORD(rop);
1358       *(mr->rdParam + 1) = HIWORD(rop);
1359       *(mr->rdParam + 2) = heightSrc;
1360       *(mr->rdParam + 3) = widthSrc;
1361       *(mr->rdParam + 4) = ySrc;
1362       *(mr->rdParam + 5) = xSrc;
1363       *(mr->rdParam + 6) = heightDest;
1364       *(mr->rdParam + 7) = widthDest;
1365       *(mr->rdParam + 8) = yDest;
1366       *(mr->rdParam + 9) = xDest;
1367       ret = MF_WriteRecord( dcDest, mr, mr->rdSize * 2);
1368     }  
1369     else
1370         ret = FALSE;
1371     GlobalFree16(hmr);
1372     return ret;
1373 }
1374
1375