Change (32 bit) HMETAFILEs to GDI objects (HMETAFILE16s remain as
[wine] / graphics / metafiledrv / init.c
1 /*
2  * Metafile driver initialisation functions
3  *
4  * Copyright 1996 Alexandre Julliard
5  */
6
7 #include "windef.h"
8 #include "wine/winbase16.h"
9 #include "dc.h"
10 #include "heap.h"
11 #include "global.h"
12 #include "metafile.h"
13 #include "metafiledrv.h"
14 #include "debug.h"
15
16 #include <string.h>
17
18 static const DC_FUNCTIONS MFDRV_Funcs =
19 {
20     MFDRV_Arc,                       /* pArc */
21     MFDRV_BitBlt,                    /* pBitBlt */
22     NULL,                            /* pBitmapBits */  
23     MFDRV_Chord,                     /* pChord */
24     NULL,                            /* pCreateBitmap */
25     NULL, /* no implementation */    /* pCreateDC */
26     NULL, /* no implementation */    /* pDeleteDC */
27     NULL,                            /* pCreateDIBSection */
28     NULL,                            /* pCreateDIBSection16 */
29     NULL,                            /* pDeleteObject */
30     MFDRV_Ellipse,                   /* pEllipse */
31     NULL,                            /* pEnumDeviceFonts */
32     NULL,                            /* pEscape */
33     NULL,                            /* pExcludeClipRect */
34     NULL,                            /* pExcludeVisRect */
35     MFDRV_ExtFloodFill,              /* pExtFloodFill */
36     MFDRV_ExtTextOut,                /* pExtTextOut */
37     NULL,                            /* pGetCharWidth */
38     NULL, /* no implementation */    /* pGetPixel */
39     NULL,                            /* pGetTextExtentPoint */
40     NULL,                            /* pGetTextMetrics */
41     NULL,                            /* pIntersectClipRect */
42     NULL,                            /* pIntersectVisRect */
43     MFDRV_LineTo,                    /* pLineTo */
44     NULL,                            /* pLoadOEMResource */
45     MFDRV_MoveToEx,                  /* pMoveToEx */
46     NULL,                            /* pOffsetClipRgn */
47     MFDRV_OffsetViewportOrg,         /* pOffsetViewportOrg */
48     MFDRV_OffsetWindowOrg,           /* pOffsetWindowOrg */
49     MFDRV_PaintRgn,                  /* pPaintRgn */
50     MFDRV_PatBlt,                    /* pPatBlt */
51     MFDRV_Pie,                       /* pPie */
52     MFDRV_PolyPolygon,               /* pPolyPolygon */
53     NULL,                            /* pPolyPolyline */
54     MFDRV_Polygon,                   /* pPolygon */
55     MFDRV_Polyline,                  /* pPolyline */
56     NULL,                            /* pPolyBezier */
57     NULL,                            /* pRealizePalette */
58     MFDRV_Rectangle,                 /* pRectangle */
59     NULL,                            /* pRestoreDC */
60     MFDRV_RoundRect,                 /* pRoundRect */
61     NULL,                            /* pSaveDC */
62     MFDRV_ScaleViewportExt,          /* pScaleViewportExt */
63     MFDRV_ScaleWindowExt,            /* pScaleWindowExt */
64     NULL,                            /* pSelectClipRgn */
65     MFDRV_SelectObject,              /* pSelectObject */
66     NULL,                            /* pSelectPalette */
67     MFDRV_SetBkColor,                /* pSetBkColor */
68     NULL,                            /* pSetBkMode */
69     NULL,                            /* pSetDeviceClipping */
70     NULL,                            /* pSetDIBitsToDevice */
71     MFDRV_SetMapMode,                /* pSetMapMode */
72     NULL,                            /* pSetMapperFlags */
73     MFDRV_SetPixel,                  /* pSetPixel */
74     NULL,                            /* pSetPolyFillMode */
75     NULL,                            /* pSetROP2 */
76     NULL,                            /* pSetRelAbs */
77     NULL,                            /* pSetStretchBltMode */
78     NULL,                            /* pSetTextAlign */
79     NULL,                            /* pSetTextCharacterExtra */
80     MFDRV_SetTextColor,              /* pSetTextColor */
81     NULL,                            /* pSetTextJustification */
82     MFDRV_SetViewportExt,            /* pSetViewportExt */
83     MFDRV_SetViewportOrg,            /* pSetViewportOrg */
84     MFDRV_SetWindowExt,              /* pSetWindowExt */
85     MFDRV_SetWindowOrg,              /* pSetWindowOrg */
86     MFDRV_StretchBlt,                /* pStretchBlt */
87     NULL                             /* pStretchDIBits */
88 };
89
90
91
92 /**********************************************************************
93  *           MFDRV_AllocMetaFile
94  */
95 static DC *MFDRV_AllocMetaFile(void)
96 {
97     DC *dc;
98     METAFILEDRV_PDEVICE *physDev;
99     
100     if (!(dc = DC_AllocDC( &MFDRV_Funcs ))) return NULL;
101     dc->header.wMagic = METAFILE_DC_MAGIC;
102
103     physDev = (METAFILEDRV_PDEVICE *)HeapAlloc(SystemHeap,0,sizeof(*physDev));
104     if (!physDev)
105     {
106         GDI_HEAP_FREE( dc->hSelf );
107         return NULL;
108     }
109     dc->physDev = physDev;
110
111     if (!(physDev->mh = HeapAlloc( SystemHeap, 0, sizeof(*physDev->mh) )))
112     {
113         HeapFree( SystemHeap, 0, physDev );
114         GDI_HEAP_FREE( dc->hSelf );
115         return NULL;
116     }
117
118     physDev->nextHandle = 0;
119     physDev->hFile = 0;
120
121     physDev->mh->mtHeaderSize   = sizeof(METAHEADER) / sizeof(WORD);
122     physDev->mh->mtVersion      = 0x0300;
123     physDev->mh->mtSize         = physDev->mh->mtHeaderSize;
124     physDev->mh->mtNoObjects    = 0;
125     physDev->mh->mtMaxRecord    = 0;
126     physDev->mh->mtNoParameters = 0;
127
128     return dc;
129 }
130
131
132 /**********************************************************************
133  *           MFDRV_DeleteDC
134  */
135 static BOOL MFDRV_DeleteDC( DC *dc )
136 {
137     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
138     
139     if (physDev->mh) HeapFree( SystemHeap, 0, physDev->mh );
140     HeapFree( SystemHeap, 0, physDev );
141     dc->physDev = NULL;
142     GDI_FreeObject(dc->hSelf);
143     return TRUE;
144 }
145
146 /**********************************************************************
147  *           CreateMetaFile16   (GDI.125)
148  *
149  *  Create a new DC and associate it with a metafile. Pass a filename
150  *  to create a disk-based metafile, NULL to create a memory metafile.
151  *
152  * RETURNS
153  *  A handle to the metafile DC if successful, NULL on failure.
154  */
155 HDC16 WINAPI CreateMetaFile16( 
156                               LPCSTR filename /* Filename of disk metafile */
157 )
158 {
159     DC *dc;
160     METAFILEDRV_PDEVICE *physDev;
161     HFILE hFile;
162
163     TRACE(metafile, "'%s'\n", filename );
164
165     if (!(dc = MFDRV_AllocMetaFile())) return 0;
166     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
167     
168     if (filename)  /* disk based metafile */
169     {
170         physDev->mh->mtType = METAFILE_DISK;
171         if ((hFile = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
172                                 CREATE_ALWAYS, 0, -1)) == HFILE_ERROR) {
173             MFDRV_DeleteDC( dc );
174             return 0;
175         }
176         if (!WriteFile( hFile, (LPSTR)physDev->mh, sizeof(*physDev->mh), NULL,
177                         NULL )) {
178             MFDRV_DeleteDC( dc );
179             return 0;
180         }
181         physDev->hFile = hFile;
182
183         /* Grow METAHEADER to include filename */
184         physDev->mh = MF_CreateMetaHeaderDisk(physDev->mh, filename);
185     }
186     else  /* memory based metafile */
187         physDev->mh->mtType = METAFILE_MEMORY;
188         
189     TRACE(metafile, "returning %04x\n", dc->hSelf);
190     return dc->hSelf;
191 }
192
193 /**********************************************************************
194  *           CreateMetaFileA   (GDI32.51)
195  */
196 HDC WINAPI CreateMetaFileA( 
197                               LPCSTR filename /* Filename of disk metafile */
198 )
199 {
200   return CreateMetaFile16( filename );
201 }
202
203 /**********************************************************************
204  *          CreateMetaFileW   (GDI32.52)
205  */
206 HDC WINAPI CreateMetaFileW(LPCWSTR filename)
207 {
208     LPSTR filenameA;
209     HDC hReturnDC;
210
211     filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
212
213     hReturnDC = CreateMetaFileA(filenameA);
214
215     HeapFree( GetProcessHeap(), 0, filenameA );
216
217     return hReturnDC;
218 }
219
220
221 /**********************************************************************
222  *          MFDRV_CloseMetaFile
223  */
224 static DC *MFDRV_CloseMetaFile( HDC hdc ) 
225 {
226     DC *dc;
227     METAFILEDRV_PDEVICE *physDev;
228     
229     TRACE(metafile, "(%04x)\n", hdc );
230
231     if (!(dc = (DC *) GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC ))) return 0;
232     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
233
234     /* Construct the end of metafile record - this is documented
235      * in SDK Knowledgebase Q99334.
236      */
237
238     if (!MFDRV_MetaParam0(dc, META_EOF))
239     {
240         MFDRV_DeleteDC( dc );
241         return 0;
242     }   
243
244     if (physDev->mh->mtType == METAFILE_DISK)  /* disk based metafile */
245     {
246         if (SetFilePointer(physDev->hFile, 0, NULL, FILE_BEGIN) != 0) {
247             MFDRV_DeleteDC( dc );
248             return 0;
249         }
250
251         physDev->mh->mtType = METAFILE_MEMORY; /* This is what windows does */
252         if (!WriteFile(physDev->hFile, (LPSTR)physDev->mh,
253                        sizeof(*physDev->mh), NULL, NULL)) {
254             MFDRV_DeleteDC( dc );
255             return 0;
256         }
257         CloseHandle(physDev->hFile);
258         physDev->mh->mtType = METAFILE_DISK;
259     }
260
261     return dc;
262 }
263
264 /******************************************************************
265  *           CloseMetaFile16   (GDI.126)
266  */
267 HMETAFILE16 WINAPI CloseMetaFile16( 
268                                    HDC16 hdc /* Metafile DC to close */
269 )
270 {
271     HMETAFILE16 hmf;
272     METAFILEDRV_PDEVICE *physDev;
273     DC *dc = MFDRV_CloseMetaFile(hdc);
274     if (!dc) return 0;
275     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
276
277     /* Now allocate a global handle for the metafile */
278
279     hmf = MF_Create_HMETAFILE16( physDev->mh );
280
281     physDev->mh = NULL;  /* So it won't be deleted */
282     MFDRV_DeleteDC( dc );
283     return hmf;
284 }
285
286 /******************************************************************
287  *           CloseMetaFile   (GDI32.17)
288  *
289  *  Stop recording graphics operations in metafile associated with
290  *  hdc and retrieve metafile.
291  *
292  * RETURNS
293  *  Handle of newly created metafile on success, NULL on failure.
294  */
295 HMETAFILE WINAPI CloseMetaFile( 
296                                    HDC hdc /* Metafile DC to close */
297 )
298 {
299     HMETAFILE hmf;
300     METAFILEDRV_PDEVICE *physDev;
301     DC *dc = MFDRV_CloseMetaFile(hdc);
302     if (!dc) return 0;
303     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
304
305     /* Now allocate a global handle for the metafile */
306
307     hmf = MF_Create_HMETAFILE( physDev->mh );
308
309     physDev->mh = NULL;  /* So it won't be deleted */
310     MFDRV_DeleteDC( dc );
311     return hmf;
312 }
313
314
315 /******************************************************************
316  *         MFDRV_WriteRecord
317  *
318  * Warning: this function can change the pointer to the metafile header.
319  */
320 BOOL MFDRV_WriteRecord( DC *dc, METARECORD *mr, DWORD rlen)
321 {
322     DWORD len;
323     METAHEADER *mh;
324     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
325
326     switch(physDev->mh->mtType)
327     {
328     case METAFILE_MEMORY:
329         len = physDev->mh->mtSize * 2 + rlen;
330         mh = HeapReAlloc( SystemHeap, 0, physDev->mh, len );
331         if (!mh) return FALSE;
332         physDev->mh = mh;
333         memcpy((WORD *)physDev->mh + physDev->mh->mtSize, mr, rlen);
334         break;
335     case METAFILE_DISK:
336         TRACE(metafile,"Writing record to disk\n");
337         if (!WriteFile(physDev->hFile, (char *)mr, rlen, NULL, NULL))
338             return FALSE;
339         break;
340     default:
341         ERR(metafile, "Unknown metafile type %d\n", physDev->mh->mtType );
342         return FALSE;
343     }
344
345     physDev->mh->mtSize += rlen / 2;
346     physDev->mh->mtMaxRecord = MAX(physDev->mh->mtMaxRecord, rlen / 2);
347     return TRUE;
348 }
349
350
351 /******************************************************************
352  *         MFDRV_MetaParam0
353  */
354
355 BOOL MFDRV_MetaParam0(DC *dc, short func)
356 {
357     char buffer[8];
358     METARECORD *mr = (METARECORD *)&buffer;
359     
360     mr->rdSize = 3;
361     mr->rdFunction = func;
362     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
363 }
364
365
366 /******************************************************************
367  *         MFDRV_MetaParam1
368  */
369 BOOL MFDRV_MetaParam1(DC *dc, short func, short param1)
370 {
371     char buffer[8];
372     METARECORD *mr = (METARECORD *)&buffer;
373     
374     mr->rdSize = 4;
375     mr->rdFunction = func;
376     *(mr->rdParm) = param1;
377     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
378 }
379
380
381 /******************************************************************
382  *         MFDRV_MetaParam2
383  */
384 BOOL MFDRV_MetaParam2(DC *dc, short func, short param1, short param2)
385 {
386     char buffer[10];
387     METARECORD *mr = (METARECORD *)&buffer;
388     
389     mr->rdSize = 5;
390     mr->rdFunction = func;
391     *(mr->rdParm) = param2;
392     *(mr->rdParm + 1) = param1;
393     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
394 }
395
396
397 /******************************************************************
398  *         MFDRV_MetaParam4
399  */
400
401 BOOL MFDRV_MetaParam4(DC *dc, short func, short param1, short param2, 
402                       short param3, short param4)
403 {
404     char buffer[14];
405     METARECORD *mr = (METARECORD *)&buffer;
406     
407     mr->rdSize = 7;
408     mr->rdFunction = func;
409     *(mr->rdParm) = param4;
410     *(mr->rdParm + 1) = param3;
411     *(mr->rdParm + 2) = param2;
412     *(mr->rdParm + 3) = param1;
413     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
414 }
415
416
417 /******************************************************************
418  *         MFDRV_MetaParam6
419  */
420
421 BOOL MFDRV_MetaParam6(DC *dc, short func, short param1, short param2, 
422                       short param3, short param4, short param5, short param6)
423 {
424     char buffer[18];
425     METARECORD *mr = (METARECORD *)&buffer;
426     
427     mr->rdSize = 9;
428     mr->rdFunction = func;
429     *(mr->rdParm) = param6;
430     *(mr->rdParm + 1) = param5;
431     *(mr->rdParm + 2) = param4;
432     *(mr->rdParm + 3) = param3;
433     *(mr->rdParm + 4) = param2;
434     *(mr->rdParm + 5) = param1;
435     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
436 }
437
438
439 /******************************************************************
440  *         MFDRV_MetaParam8
441  */
442 BOOL MFDRV_MetaParam8(DC *dc, short func, short param1, short param2, 
443                       short param3, short param4, short param5,
444                       short param6, short param7, short param8)
445 {
446     char buffer[22];
447     METARECORD *mr = (METARECORD *)&buffer;
448     
449     mr->rdSize = 11;
450     mr->rdFunction = func;
451     *(mr->rdParm) = param8;
452     *(mr->rdParm + 1) = param7;
453     *(mr->rdParm + 2) = param6;
454     *(mr->rdParm + 3) = param5;
455     *(mr->rdParm + 4) = param4;
456     *(mr->rdParm + 5) = param3;
457     *(mr->rdParm + 6) = param2;
458     *(mr->rdParm + 7) = param1;
459     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
460 }
461
462
463 /******************************************************************
464  *         MFDRV_AddHandleDC
465  *
466  * Note: this function assumes that we never delete objects.
467  * If we do someday, we'll need to maintain a table to re-use deleted
468  * handles.
469  */
470 int MFDRV_AddHandleDC( DC *dc )
471 {
472     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
473     physDev->mh->mtNoObjects++;
474     return physDev->nextHandle++;
475 }
476
477
478
479
480
481
482
483
484
485 /********************************************************************
486
487        Enhanced Metafile driver initializations
488
489        This possibly  should be moved to their own file/directory
490        at some point.
491
492 **********************************************************************/
493
494 /**********************************************************************
495  *          CreateEnhMetaFile32A   (GDI32.41)
496 */
497 HDC WINAPI CreateEnhMetaFileA( 
498     HDC hdc, /* optional reference DC */
499     LPCSTR filename, /* optional filename for disk metafiles */
500     const RECT *rect, /* optional bounding rectangle */
501     LPCSTR description /* optional description */ 
502     )
503 {
504 #if 0
505     DC *dc;
506     METAFILEDRV_PDEVICE *physDev;
507     HFILE hFile;
508
509     if (!(dc = MFDRV_AllocMetaFile())) return 0;
510     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
511     
512     if (filename)  /* disk based metafile */
513     {
514         physDev->mh->mtType = METAFILE_DISK;
515         if ((hFile = _lcreat( filename, 0 )) == HFILE_ERROR)
516         {
517             MFDRV_DeleteDC( dc );
518             return 0;
519         }
520         if (_lwrite( hFile, (LPSTR)physDev->mh,
521                        sizeof(*physDev->mh)) == HFILE_ERROR)
522         {
523             MFDRV_DeleteDC( dc );
524             return 0;
525         }
526         physDev->mh->mtNoParameters = hFile; /* store file descriptor here */
527                                     /* windows probably uses this too*/
528     }
529     else  /* memory based metafile */
530         physDev->mh->mtType = METAFILE_MEMORY;
531
532     TRACE(metafile, "returning %04x\n", dc->hSelf);
533     return dc->hSelf;
534 #endif
535
536     FIXME(metafile, "(0x%lx,%s,%p,%s): stub\n",
537          (DWORD)hdc, filename, rect, description);
538
539     return 0;
540 }
541
542 /**********************************************************************
543  *          CreateEnhMetaFile32W   (GDI32.42)
544  */
545 HDC WINAPI CreateEnhMetaFileW(
546     HDC         hdc,        /* optional reference DC */
547     LPCWSTR       filename,   /* optional filename for disk metafiles */
548     const RECT* rect,       /* optional bounding rectangle */
549     LPCWSTR       description /* optional description */ 
550     )
551 {
552     LPSTR filenameA;
553     LPSTR descriptionA;
554     HDC hReturnDC;
555
556     filenameA    = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
557     descriptionA = HEAP_strdupWtoA( GetProcessHeap(), 0, description );
558
559     hReturnDC = CreateEnhMetaFileA(hdc,
560                                     filenameA,
561                                     rect,
562                                     descriptionA);
563
564     HeapFree( GetProcessHeap(), 0, filenameA );
565     HeapFree( GetProcessHeap(), 0, descriptionA );
566
567     return hReturnDC;
568 }
569
570 HENHMETAFILE WINAPI CloseEnhMetaFile( HDC hdc /* metafile DC */ )
571 {
572   /* write EMR_EOF(0x0, 0x10, 0x14) */
573   return 0;
574 }
575
576