Added a first-cut version of MapVirtualKeyExW() that has the same
[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 "gdi.h"
10 #include "heap.h"
11 #include "global.h"
12 #include "metafile.h"
13 #include "metafiledrv.h"
14 #include "debugtools.h"
15
16 DEFAULT_DEBUG_CHANNEL(metafile);
17
18 #include <string.h>
19
20 static const DC_FUNCTIONS MFDRV_Funcs =
21 {
22     NULL,                            /* pAbortDoc */
23     MFDRV_AbortPath,                 /* pAbortPath */
24     NULL,                            /* pAngleArc */
25     MFDRV_Arc,                       /* pArc */
26     NULL,                            /* pArcTo */
27     MFDRV_BeginPath,                 /* pBeginPath */
28     MFDRV_BitBlt,                    /* pBitBlt */
29     NULL,                            /* pBitmapBits */  
30     NULL,                            /* pChoosePixelFormat */
31     MFDRV_Chord,                     /* pChord */
32     MFDRV_CloseFigure,               /* pCloseFigure */
33     NULL,                            /* pCreateBitmap */
34     NULL, /* no implementation */    /* pCreateDC */
35     NULL,                            /* pCreateDIBSection */
36     NULL,                            /* pCreateDIBSection16 */
37     NULL, /* no implementation */    /* pDeleteDC */
38     NULL,                            /* pDeleteObject */
39     NULL,                            /* pDescribePixelFormat */
40     NULL,                            /* pDeviceCapabilities */
41     MFDRV_Ellipse,                   /* pEllipse */
42     NULL,                            /* pEndDoc */
43     NULL,                            /* pEndPage */
44     MFDRV_EndPath,                   /* pEndPath */
45     NULL,                            /* pEnumDeviceFonts */
46     NULL,                            /* pEscape */
47     MFDRV_ExcludeClipRect,           /* pExcludeClipRect */
48     NULL,                            /* pExtDeviceMode */
49     MFDRV_ExtFloodFill,              /* pExtFloodFill */
50     MFDRV_ExtTextOut,                /* pExtTextOut */
51     MFDRV_FillPath,                  /* pFillPath */
52     MFDRV_FillRgn,                   /* pFillRgn */
53     MFDRV_FlattenPath,               /* pFlattenPath */
54     MFDRV_FrameRgn,                  /* pFrameRgn */
55     NULL,                            /* pGetCharWidth */
56     NULL,                            /* pGetDCOrgEx */
57     NULL, /* no implementation */    /* pGetPixel */
58     NULL,                            /* pGetPixelFormat */
59     NULL,                            /* pGetTextExtentPoint */
60     NULL,                            /* pGetTextMetrics */
61     MFDRV_IntersectClipRect,         /* pIntersectClipRect */
62     MFDRV_InvertRgn,                 /* pInvertRgn */
63     MFDRV_LineTo,                    /* pLineTo */
64     MFDRV_MoveTo,                    /* pMoveTo */
65     MFDRV_OffsetClipRgn,             /* pOffsetClipRgn */
66     MFDRV_OffsetViewportOrg,         /* pOffsetViewportOrg */
67     MFDRV_OffsetWindowOrg,           /* pOffsetWindowOrg */
68     MFDRV_PaintRgn,                  /* pPaintRgn */
69     MFDRV_PatBlt,                    /* pPatBlt */
70     MFDRV_Pie,                       /* pPie */
71     MFDRV_PolyBezier,                /* pPolyBezier */
72     MFDRV_PolyBezierTo,              /* pPolyBezierTo */
73     NULL,                            /* pPolyDraw */
74     MFDRV_PolyPolygon,               /* pPolyPolygon */
75     NULL,                            /* pPolyPolyline */
76     MFDRV_Polygon,                   /* pPolygon */
77     MFDRV_Polyline,                  /* pPolyline */
78     NULL,                            /* pPolylineTo */
79     NULL,                            /* pRealizePalette */
80     MFDRV_Rectangle,                 /* pRectangle */
81     MFDRV_RestoreDC,                 /* pRestoreDC */
82     MFDRV_RoundRect,                 /* pRoundRect */
83     MFDRV_SaveDC,                    /* pSaveDC */
84     MFDRV_ScaleViewportExt,          /* pScaleViewportExt */
85     MFDRV_ScaleWindowExt,            /* pScaleWindowExt */
86     MFDRV_SelectClipPath,            /* pSelectClipPath */
87     NULL,                            /* pSelectClipRgn */
88     MFDRV_SelectObject,              /* pSelectObject */
89     NULL,                            /* pSelectPalette */
90     MFDRV_SetBkColor,                /* pSetBkColor */
91     MFDRV_SetBkMode,                 /* pSetBkMode */
92     NULL,                            /* pSetDeviceClipping */
93     MFDRV_SetDIBitsToDevice,         /* pSetDIBitsToDevice */
94     MFDRV_SetMapMode,                /* pSetMapMode */
95     MFDRV_SetMapperFlags,            /* pSetMapperFlags */
96     MFDRV_SetPixel,                  /* pSetPixel */
97     NULL,                            /* pSetPixelFormat */
98     MFDRV_SetPolyFillMode,           /* pSetPolyFillMode */
99     MFDRV_SetROP2,                   /* pSetROP2 */
100     MFDRV_SetRelAbs,                 /* pSetRelAbs */
101     MFDRV_SetStretchBltMode,         /* pSetStretchBltMode */
102     MFDRV_SetTextAlign,              /* pSetTextAlign */
103     MFDRV_SetTextCharacterExtra,     /* pSetTextCharacterExtra */
104     MFDRV_SetTextColor,              /* pSetTextColor */
105     MFDRV_SetTextJustification,      /* pSetTextJustification */
106     MFDRV_SetViewportExt,            /* pSetViewportExt */
107     MFDRV_SetViewportOrg,            /* pSetViewportOrg */
108     MFDRV_SetWindowExt,              /* pSetWindowExt */
109     MFDRV_SetWindowOrg,              /* pSetWindowOrg */
110     NULL,                            /* pStartDoc */
111     NULL,                            /* pStartPage */
112     MFDRV_StretchBlt,                /* pStretchBlt */
113     MFDRV_StretchDIBits,             /* pStretchDIBits */
114     MFDRV_StrokeAndFillPath,         /* pStrokeAndFillPath */
115     MFDRV_StrokePath,                /* pStrokePath */
116     NULL,                            /* pSwapBuffers */
117     MFDRV_WidenPath                  /* pWidenPath */
118 };
119
120
121
122 /**********************************************************************
123  *           MFDRV_AllocMetaFile
124  */
125 static DC *MFDRV_AllocMetaFile(void)
126 {
127     DC *dc;
128     METAFILEDRV_PDEVICE *physDev;
129     
130     if (!(dc = DC_AllocDC( &MFDRV_Funcs ))) return NULL;
131     dc->header.wMagic = METAFILE_DC_MAGIC;
132
133     physDev = (METAFILEDRV_PDEVICE *)HeapAlloc(GetProcessHeap(),0,sizeof(*physDev));
134     if (!physDev)
135     {
136         GDI_FreeObject( dc->hSelf, dc );
137         return NULL;
138     }
139     dc->physDev = physDev;
140
141     if (!(physDev->mh = HeapAlloc( GetProcessHeap(), 0, sizeof(*physDev->mh) )))
142     {
143         HeapFree( GetProcessHeap(), 0, physDev );
144         GDI_FreeObject( dc->hSelf, dc );
145         return NULL;
146     }
147
148     physDev->nextHandle = 0;
149     physDev->hFile = 0;
150
151     physDev->mh->mtHeaderSize   = sizeof(METAHEADER) / sizeof(WORD);
152     physDev->mh->mtVersion      = 0x0300;
153     physDev->mh->mtSize         = physDev->mh->mtHeaderSize;
154     physDev->mh->mtNoObjects    = 0;
155     physDev->mh->mtMaxRecord    = 0;
156     physDev->mh->mtNoParameters = 0;
157
158     return dc;
159 }
160
161
162 /**********************************************************************
163  *           MFDRV_DeleteDC
164  */
165 static BOOL MFDRV_DeleteDC( DC *dc )
166 {
167     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
168     
169     if (physDev->mh) HeapFree( GetProcessHeap(), 0, physDev->mh );
170     HeapFree( GetProcessHeap(), 0, physDev );
171     dc->physDev = NULL;
172     GDI_FreeObject( dc->hSelf, dc );
173     return TRUE;
174 }
175
176 /**********************************************************************
177  *           CreateMetaFile16   (GDI.125)
178  *
179  *  Create a new DC and associate it with a metafile. Pass a filename
180  *  to create a disk-based metafile, NULL to create a memory metafile.
181  *
182  * RETURNS
183  *  A handle to the metafile DC if successful, NULL on failure.
184  */
185 HDC16 WINAPI CreateMetaFile16( 
186                               LPCSTR filename /* [in] Filename of disk metafile */
187 )
188 {
189     HDC ret;
190     DC *dc;
191     METAFILEDRV_PDEVICE *physDev;
192     HFILE hFile;
193
194     TRACE("'%s'\n", filename );
195
196     if (!(dc = MFDRV_AllocMetaFile())) return 0;
197     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
198     
199     if (filename)  /* disk based metafile */
200     {
201         physDev->mh->mtType = METAFILE_DISK;
202         if ((hFile = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
203                                 CREATE_ALWAYS, 0, -1)) == HFILE_ERROR) {
204             MFDRV_DeleteDC( dc );
205             return 0;
206         }
207         if (!WriteFile( hFile, (LPSTR)physDev->mh, sizeof(*physDev->mh), NULL,
208                         NULL )) {
209             MFDRV_DeleteDC( dc );
210             return 0;
211         }
212         physDev->hFile = hFile;
213
214         /* Grow METAHEADER to include filename */
215         physDev->mh = MF_CreateMetaHeaderDisk(physDev->mh, filename);
216     }
217     else  /* memory based metafile */
218         physDev->mh->mtType = METAFILE_MEMORY;
219         
220     TRACE("returning %04x\n", dc->hSelf);
221     ret = dc->hSelf;
222     GDI_ReleaseObj( dc->hSelf );
223     return ret;
224 }
225
226 /**********************************************************************
227  *           CreateMetaFileA   (GDI32.51)
228  */
229 HDC WINAPI CreateMetaFileA( 
230                               LPCSTR filename /* [in] Filename of disk metafile */
231 )
232 {
233   return CreateMetaFile16( filename );
234 }
235
236 /**********************************************************************
237  *          CreateMetaFileW   (GDI32.52)
238  */
239 HDC WINAPI CreateMetaFileW(LPCWSTR filename)
240 {
241     LPSTR filenameA;
242     HDC hReturnDC;
243
244     filenameA = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
245
246     hReturnDC = CreateMetaFileA(filenameA);
247
248     HeapFree( GetProcessHeap(), 0, filenameA );
249
250     return hReturnDC;
251 }
252
253
254 /**********************************************************************
255  *          MFDRV_CloseMetaFile
256  */
257 static DC *MFDRV_CloseMetaFile( HDC hdc ) 
258 {
259     DC *dc;
260     METAFILEDRV_PDEVICE *physDev;
261     
262     TRACE("(%04x)\n", hdc );
263
264     if (!(dc = (DC *) GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC ))) return 0;
265     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
266
267     /* Construct the end of metafile record - this is documented
268      * in SDK Knowledgebase Q99334.
269      */
270
271     if (!MFDRV_MetaParam0(dc, META_EOF))
272     {
273         MFDRV_DeleteDC( dc );
274         return 0;
275     }   
276
277     if (physDev->mh->mtType == METAFILE_DISK)  /* disk based metafile */
278     {
279         if (SetFilePointer(physDev->hFile, 0, NULL, FILE_BEGIN) != 0) {
280             MFDRV_DeleteDC( dc );
281             return 0;
282         }
283
284         physDev->mh->mtType = METAFILE_MEMORY; /* This is what windows does */
285         if (!WriteFile(physDev->hFile, (LPSTR)physDev->mh,
286                        sizeof(*physDev->mh), NULL, NULL)) {
287             MFDRV_DeleteDC( dc );
288             return 0;
289         }
290         CloseHandle(physDev->hFile);
291         physDev->mh->mtType = METAFILE_DISK;
292     }
293
294     return dc;
295 }
296
297 /******************************************************************
298  *           CloseMetaFile16   (GDI.126)
299  */
300 HMETAFILE16 WINAPI CloseMetaFile16( 
301                                    HDC16 hdc /* [in] Metafile DC to close */
302 )
303 {
304     HMETAFILE16 hmf;
305     METAFILEDRV_PDEVICE *physDev;
306     DC *dc = MFDRV_CloseMetaFile(hdc);
307     if (!dc) return 0;
308     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
309
310     /* Now allocate a global handle for the metafile */
311
312     hmf = MF_Create_HMETAFILE16( physDev->mh );
313
314     physDev->mh = NULL;  /* So it won't be deleted */
315     MFDRV_DeleteDC( dc );
316     return hmf;
317 }
318
319 /******************************************************************
320  *           CloseMetaFile   (GDI32.17)
321  *
322  *  Stop recording graphics operations in metafile associated with
323  *  hdc and retrieve metafile.
324  *
325  * RETURNS
326  *  Handle of newly created metafile on success, NULL on failure.
327  */
328 HMETAFILE WINAPI CloseMetaFile( 
329                                    HDC hdc /* [in] Metafile DC to close */
330 )
331 {
332     HMETAFILE hmf;
333     METAFILEDRV_PDEVICE *physDev;
334     DC *dc = MFDRV_CloseMetaFile(hdc);
335     if (!dc) return 0;
336     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
337
338     /* Now allocate a global handle for the metafile */
339
340     hmf = MF_Create_HMETAFILE( physDev->mh );
341
342     physDev->mh = NULL;  /* So it won't be deleted */
343     MFDRV_DeleteDC( dc );
344     return hmf;
345 }
346
347
348 /******************************************************************
349  *         MFDRV_WriteRecord
350  *
351  * Warning: this function can change the pointer to the metafile header.
352  */
353 BOOL MFDRV_WriteRecord( DC *dc, METARECORD *mr, DWORD rlen)
354 {
355     DWORD len;
356     METAHEADER *mh;
357     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
358
359     switch(physDev->mh->mtType)
360     {
361     case METAFILE_MEMORY:
362         len = physDev->mh->mtSize * 2 + rlen;
363         mh = HeapReAlloc( GetProcessHeap(), 0, physDev->mh, len );
364         if (!mh) return FALSE;
365         physDev->mh = mh;
366         memcpy((WORD *)physDev->mh + physDev->mh->mtSize, mr, rlen);
367         break;
368     case METAFILE_DISK:
369         TRACE("Writing record to disk\n");
370         if (!WriteFile(physDev->hFile, (char *)mr, rlen, NULL, NULL))
371             return FALSE;
372         break;
373     default:
374         ERR("Unknown metafile type %d\n", physDev->mh->mtType );
375         return FALSE;
376     }
377
378     physDev->mh->mtSize += rlen / 2;
379     physDev->mh->mtMaxRecord = max(physDev->mh->mtMaxRecord, rlen / 2);
380     return TRUE;
381 }
382
383
384 /******************************************************************
385  *         MFDRV_MetaParam0
386  */
387
388 BOOL MFDRV_MetaParam0(DC *dc, short func)
389 {
390     char buffer[8];
391     METARECORD *mr = (METARECORD *)&buffer;
392     
393     mr->rdSize = 3;
394     mr->rdFunction = func;
395     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
396 }
397
398
399 /******************************************************************
400  *         MFDRV_MetaParam1
401  */
402 BOOL MFDRV_MetaParam1(DC *dc, short func, short param1)
403 {
404     char buffer[8];
405     METARECORD *mr = (METARECORD *)&buffer;
406     
407     mr->rdSize = 4;
408     mr->rdFunction = func;
409     *(mr->rdParm) = param1;
410     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
411 }
412
413
414 /******************************************************************
415  *         MFDRV_MetaParam2
416  */
417 BOOL MFDRV_MetaParam2(DC *dc, short func, short param1, short param2)
418 {
419     char buffer[10];
420     METARECORD *mr = (METARECORD *)&buffer;
421     
422     mr->rdSize = 5;
423     mr->rdFunction = func;
424     *(mr->rdParm) = param2;
425     *(mr->rdParm + 1) = param1;
426     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
427 }
428
429
430 /******************************************************************
431  *         MFDRV_MetaParam4
432  */
433
434 BOOL MFDRV_MetaParam4(DC *dc, short func, short param1, short param2, 
435                       short param3, short param4)
436 {
437     char buffer[14];
438     METARECORD *mr = (METARECORD *)&buffer;
439     
440     mr->rdSize = 7;
441     mr->rdFunction = func;
442     *(mr->rdParm) = param4;
443     *(mr->rdParm + 1) = param3;
444     *(mr->rdParm + 2) = param2;
445     *(mr->rdParm + 3) = param1;
446     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
447 }
448
449
450 /******************************************************************
451  *         MFDRV_MetaParam6
452  */
453
454 BOOL MFDRV_MetaParam6(DC *dc, short func, short param1, short param2, 
455                       short param3, short param4, short param5, short param6)
456 {
457     char buffer[18];
458     METARECORD *mr = (METARECORD *)&buffer;
459     
460     mr->rdSize = 9;
461     mr->rdFunction = func;
462     *(mr->rdParm) = param6;
463     *(mr->rdParm + 1) = param5;
464     *(mr->rdParm + 2) = param4;
465     *(mr->rdParm + 3) = param3;
466     *(mr->rdParm + 4) = param2;
467     *(mr->rdParm + 5) = param1;
468     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
469 }
470
471
472 /******************************************************************
473  *         MFDRV_MetaParam8
474  */
475 BOOL MFDRV_MetaParam8(DC *dc, short func, short param1, short param2, 
476                       short param3, short param4, short param5,
477                       short param6, short param7, short param8)
478 {
479     char buffer[22];
480     METARECORD *mr = (METARECORD *)&buffer;
481     
482     mr->rdSize = 11;
483     mr->rdFunction = func;
484     *(mr->rdParm) = param8;
485     *(mr->rdParm + 1) = param7;
486     *(mr->rdParm + 2) = param6;
487     *(mr->rdParm + 3) = param5;
488     *(mr->rdParm + 4) = param4;
489     *(mr->rdParm + 5) = param3;
490     *(mr->rdParm + 6) = param2;
491     *(mr->rdParm + 7) = param1;
492     return MFDRV_WriteRecord( dc, mr, mr->rdSize * 2);
493 }
494
495
496 /******************************************************************
497  *         MFDRV_AddHandleDC
498  *
499  * Note: this function assumes that we never delete objects.
500  * If we do someday, we'll need to maintain a table to re-use deleted
501  * handles.
502  */
503 int MFDRV_AddHandleDC( DC *dc )
504 {
505     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
506     physDev->mh->mtNoObjects++;
507     return physDev->nextHandle++;
508 }
509
510