If using the default values, also set dwType to REG_SZ as our default
[wine] / dlls / gdi / mfdrv / init.c
1 /*
2  * Metafile driver initialisation functions
3  *
4  * Copyright 1996 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdarg.h>
22 #include <string.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wine/winbase16.h"
27 #include "gdi.h"
28 #include "wownt32.h"
29 #include "mfdrv/metafiledrv.h"
30 #include "wine/debug.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
33
34 static const DC_FUNCTIONS MFDRV_Funcs =
35 {
36     NULL,                            /* pAbortDoc */
37     MFDRV_AbortPath,                 /* pAbortPath */
38     NULL,                            /* pAngleArc */
39     MFDRV_Arc,                       /* pArc */
40     NULL,                            /* pArcTo */
41     MFDRV_BeginPath,                 /* pBeginPath */
42     MFDRV_BitBlt,                    /* pBitBlt */
43     NULL,                            /* pChoosePixelFormat */
44     MFDRV_Chord,                     /* pChord */
45     MFDRV_CloseFigure,               /* pCloseFigure */
46     NULL,                            /* pCreateBitmap */
47     NULL,                            /* pCreateDC */
48     NULL,                            /* pCreateDIBSection */
49     NULL,                            /* pDeleteBitmap */
50     NULL,                            /* pDeleteDC */
51     NULL,                            /* pDescribePixelFormat */
52     NULL,                            /* pDeviceCapabilities */
53     MFDRV_Ellipse,                   /* pEllipse */
54     NULL,                            /* pEndDoc */
55     NULL,                            /* pEndPage */
56     MFDRV_EndPath,                   /* pEndPath */
57     NULL,                            /* pEnumDeviceFonts */
58     MFDRV_ExcludeClipRect,           /* pExcludeClipRect */
59     NULL,                            /* pExtDeviceMode */
60     MFDRV_ExtEscape,                 /* pExtEscape */
61     MFDRV_ExtFloodFill,              /* pExtFloodFill */
62     MFDRV_ExtSelectClipRgn,          /* pExtSelectClipRgn */
63     MFDRV_ExtTextOut,                /* pExtTextOut */
64     MFDRV_FillPath,                  /* pFillPath */
65     MFDRV_FillRgn,                   /* pFillRgn */
66     MFDRV_FlattenPath,               /* pFlattenPath */
67     MFDRV_FrameRgn,                  /* pFrameRgn */
68     NULL,                            /* pGdiComment */
69     NULL,                            /* pGetBitmapBits */
70     NULL,                            /* pGetCharWidth */
71     NULL,                            /* pGetDCOrgEx */
72     NULL,                            /* pGetDIBColorTable */
73     NULL,                            /* pGetDIBits */
74     MFDRV_GetDeviceCaps,             /* pGetDeviceCaps */
75     NULL,                            /* pGetDeviceGammaRamp */
76     NULL,                            /* pGetNearestColor */
77     NULL,                            /* pGetPixel */
78     NULL,                            /* pGetPixelFormat */
79     NULL,                            /* pGetSystemPaletteEntries */
80     NULL,                            /* pGetTextExtentPoint */
81     NULL,                            /* pGetTextMetrics */
82     MFDRV_IntersectClipRect,         /* pIntersectClipRect */
83     MFDRV_InvertRgn,                 /* pInvertRgn */
84     MFDRV_LineTo,                    /* pLineTo */
85     NULL,                            /* pModifyWorldTransform */
86     MFDRV_MoveTo,                    /* pMoveTo */
87     MFDRV_OffsetClipRgn,             /* pOffsetClipRgn */
88     MFDRV_OffsetViewportOrg,         /* pOffsetViewportOrg */
89     MFDRV_OffsetWindowOrg,           /* pOffsetWindowOrg */
90     MFDRV_PaintRgn,                  /* pPaintRgn */
91     MFDRV_PatBlt,                    /* pPatBlt */
92     MFDRV_Pie,                       /* pPie */
93     MFDRV_PolyBezier,                /* pPolyBezier */
94     MFDRV_PolyBezierTo,              /* pPolyBezierTo */
95     NULL,                            /* pPolyDraw */
96     MFDRV_PolyPolygon,               /* pPolyPolygon */
97     NULL,                            /* pPolyPolyline */
98     MFDRV_Polygon,                   /* pPolygon */
99     MFDRV_Polyline,                  /* pPolyline */
100     NULL,                            /* pPolylineTo */
101     NULL,                            /* pRealizeDefaultPalette */
102     MFDRV_RealizePalette,            /* pRealizePalette */
103     MFDRV_Rectangle,                 /* pRectangle */
104     NULL,                            /* pResetDC */
105     MFDRV_RestoreDC,                 /* pRestoreDC */
106     MFDRV_RoundRect,                 /* pRoundRect */
107     MFDRV_SaveDC,                    /* pSaveDC */
108     MFDRV_ScaleViewportExt,          /* pScaleViewportExt */
109     MFDRV_ScaleWindowExt,            /* pScaleWindowExt */
110     MFDRV_SelectBitmap,              /* pSelectBitmap */
111     MFDRV_SelectBrush,               /* pSelectBrush */
112     MFDRV_SelectClipPath,            /* pSelectClipPath */
113     MFDRV_SelectFont,                /* pSelectFont */
114     MFDRV_SelectPalette,             /* pSelectPalette */
115     MFDRV_SelectPen,                 /* pSelectPen */
116     NULL,                            /* pSetArcDirection */
117     NULL,                            /* pSetBitmapBits */
118     MFDRV_SetBkColor,                /* pSetBkColor */
119     MFDRV_SetBkMode,                 /* pSetBkMode */
120     NULL,                            /* pSetDCBrushColor*/
121     NULL,                            /* pSetDCOrg */
122     NULL,                            /* pSetDCPenColor*/
123     NULL,                            /* pSetDIBColorTable */
124     NULL,                            /* pSetDIBits */
125     MFDRV_SetDIBitsToDevice,         /* pSetDIBitsToDevice */
126     NULL,                            /* pSetDeviceClipping */
127     NULL,                            /* pSetDeviceGammaRamp */
128     MFDRV_SetMapMode,                /* pSetMapMode */
129     MFDRV_SetMapperFlags,            /* pSetMapperFlags */
130     MFDRV_SetPixel,                  /* pSetPixel */
131     NULL,                            /* pSetPixelFormat */
132     MFDRV_SetPolyFillMode,           /* pSetPolyFillMode */
133     MFDRV_SetROP2,                   /* pSetROP2 */
134     MFDRV_SetRelAbs,                 /* pSetRelAbs */
135     MFDRV_SetStretchBltMode,         /* pSetStretchBltMode */
136     MFDRV_SetTextAlign,              /* pSetTextAlign */
137     MFDRV_SetTextCharacterExtra,     /* pSetTextCharacterExtra */
138     MFDRV_SetTextColor,              /* pSetTextColor */
139     MFDRV_SetTextJustification,      /* pSetTextJustification */
140     MFDRV_SetViewportExt,            /* pSetViewportExt */
141     MFDRV_SetViewportOrg,            /* pSetViewportOrg */
142     MFDRV_SetWindowExt,              /* pSetWindowExt */
143     MFDRV_SetWindowOrg,              /* pSetWindowOrg */
144     NULL,                            /* pSetWorldTransform */
145     NULL,                            /* pStartDoc */
146     NULL,                            /* pStartPage */
147     MFDRV_StretchBlt,                /* pStretchBlt */
148     MFDRV_StretchDIBits,             /* pStretchDIBits */
149     MFDRV_StrokeAndFillPath,         /* pStrokeAndFillPath */
150     MFDRV_StrokePath,                /* pStrokePath */
151     NULL,                            /* pSwapBuffers */
152     MFDRV_WidenPath                  /* pWidenPath */
153 };
154
155
156
157 /**********************************************************************
158  *           MFDRV_AllocMetaFile
159  */
160 static DC *MFDRV_AllocMetaFile(void)
161 {
162     DC *dc;
163     METAFILEDRV_PDEVICE *physDev;
164
165     if (!(dc = DC_AllocDC( &MFDRV_Funcs, METAFILE_DC_MAGIC ))) return NULL;
166
167     physDev = (METAFILEDRV_PDEVICE *)HeapAlloc(GetProcessHeap(),0,sizeof(*physDev));
168     if (!physDev)
169     {
170         GDI_FreeObject( dc->hSelf, dc );
171         return NULL;
172     }
173     dc->physDev = (PHYSDEV)physDev;
174     physDev->hdc = dc->hSelf;
175     physDev->dc = dc;
176
177     if (!(physDev->mh = HeapAlloc( GetProcessHeap(), 0, sizeof(*physDev->mh) )))
178     {
179         HeapFree( GetProcessHeap(), 0, physDev );
180         GDI_FreeObject( dc->hSelf, dc );
181         return NULL;
182     }
183
184     physDev->nextHandle = 0;
185     physDev->hFile = 0;
186
187     physDev->mh->mtHeaderSize   = sizeof(METAHEADER) / sizeof(WORD);
188     physDev->mh->mtVersion      = 0x0300;
189     physDev->mh->mtSize         = physDev->mh->mtHeaderSize;
190     physDev->mh->mtNoObjects    = 0;
191     physDev->mh->mtMaxRecord    = 0;
192     physDev->mh->mtNoParameters = 0;
193
194     return dc;
195 }
196
197
198 /**********************************************************************
199  *           MFDRV_DeleteDC
200  */
201 static BOOL MFDRV_DeleteDC( PHYSDEV dev )
202 {
203     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
204     DC *dc = physDev->dc;
205
206     if (physDev->mh) HeapFree( GetProcessHeap(), 0, physDev->mh );
207     HeapFree( GetProcessHeap(), 0, physDev );
208     dc->physDev = NULL;
209     GDI_FreeObject( dc->hSelf, dc );
210     return TRUE;
211 }
212
213
214 /**********************************************************************
215  *           CreateMetaFileA   (GDI32.@)
216  *
217  *  Create a new DC and associate it with a metafile. Pass a filename
218  *  to create a disk-based metafile, NULL to create a memory metafile.
219  *
220  * RETURNS
221  *  A handle to the metafile DC if successful, NULL on failure.
222  */
223 HDC WINAPI CreateMetaFileA( LPCSTR filename ) /* [in] Filename of disk metafile */
224 {
225     HDC ret;
226     DC *dc;
227     METAFILEDRV_PDEVICE *physDev;
228     HANDLE hFile;
229
230     TRACE("'%s'\n", filename );
231
232     if (!(dc = MFDRV_AllocMetaFile())) return 0;
233     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
234
235     if (filename)  /* disk based metafile */
236     {
237         physDev->mh->mtType = METAFILE_DISK;
238         if ((hFile = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
239                                 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
240             MFDRV_DeleteDC( dc->physDev );
241             return 0;
242         }
243         if (!WriteFile( hFile, (LPSTR)physDev->mh, sizeof(*physDev->mh), NULL,
244                         NULL )) {
245             MFDRV_DeleteDC( dc->physDev );
246             return 0;
247         }
248         physDev->hFile = hFile;
249
250         /* Grow METAHEADER to include filename */
251         physDev->mh = MF_CreateMetaHeaderDisk(physDev->mh, filename);
252     }
253     else  /* memory based metafile */
254         physDev->mh->mtType = METAFILE_MEMORY;
255
256     TRACE("returning %p\n", dc->hSelf);
257     ret = dc->hSelf;
258     GDI_ReleaseObj( dc->hSelf );
259     return ret;
260 }
261
262 /**********************************************************************
263  *          CreateMetaFileW   (GDI32.@)
264  */
265 HDC WINAPI CreateMetaFileW(LPCWSTR filename)
266 {
267     LPSTR filenameA;
268     DWORD len;
269     HDC hReturnDC;
270
271     if (!filename) return CreateMetaFileA(NULL);
272
273     len = WideCharToMultiByte( CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL );
274     filenameA = HeapAlloc( GetProcessHeap(), 0, len );
275     WideCharToMultiByte( CP_ACP, 0, filename, -1, filenameA, len, NULL, NULL );
276
277     hReturnDC = CreateMetaFileA(filenameA);
278
279     HeapFree( GetProcessHeap(), 0, filenameA );
280
281     return hReturnDC;
282 }
283
284
285 /**********************************************************************
286  *          MFDRV_CloseMetaFile
287  */
288 static DC *MFDRV_CloseMetaFile( HDC hdc )
289 {
290     DC *dc;
291     METAFILEDRV_PDEVICE *physDev;
292
293     TRACE("(%p)\n", hdc );
294
295     if (!(dc = (DC *) GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC ))) return 0;
296     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
297
298     /* Construct the end of metafile record - this is documented
299      * in SDK Knowledgebase Q99334.
300      */
301
302     if (!MFDRV_MetaParam0(dc->physDev, META_EOF))
303     {
304         MFDRV_DeleteDC( dc->physDev );
305         return 0;
306     }
307
308     if (physDev->mh->mtType == METAFILE_DISK)  /* disk based metafile */
309     {
310         if (SetFilePointer(physDev->hFile, 0, NULL, FILE_BEGIN) != 0) {
311             MFDRV_DeleteDC( dc->physDev );
312             return 0;
313         }
314
315         physDev->mh->mtType = METAFILE_MEMORY; /* This is what windows does */
316         if (!WriteFile(physDev->hFile, (LPSTR)physDev->mh,
317                        sizeof(*physDev->mh), NULL, NULL)) {
318             MFDRV_DeleteDC( dc->physDev );
319             return 0;
320         }
321         CloseHandle(physDev->hFile);
322         physDev->mh->mtType = METAFILE_DISK;
323     }
324
325     return dc;
326 }
327
328 /******************************************************************
329  *           CloseMetaFile     (GDI.126)
330  */
331 HMETAFILE16 WINAPI CloseMetaFile16(
332                                    HDC16 hdc /* [in] Metafile DC to close */
333 )
334 {
335     HMETAFILE16 hmf;
336     METAFILEDRV_PDEVICE *physDev;
337     DC *dc = MFDRV_CloseMetaFile(HDC_32(hdc));
338     if (!dc) return 0;
339     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
340
341     /* Now allocate a global handle for the metafile */
342
343     hmf = MF_Create_HMETAFILE16( physDev->mh );
344
345     physDev->mh = NULL;  /* So it won't be deleted */
346     MFDRV_DeleteDC( dc->physDev );
347     return hmf;
348 }
349
350 /******************************************************************
351  *           CloseMetaFile   (GDI32.@)
352  *
353  *  Stop recording graphics operations in metafile associated with
354  *  hdc and retrieve metafile.
355  *
356  * RETURNS
357  *  Handle of newly created metafile on success, NULL on failure.
358  */
359 HMETAFILE WINAPI CloseMetaFile(
360                                    HDC hdc /* [in] Metafile DC to close */
361 )
362 {
363     HMETAFILE hmf;
364     METAFILEDRV_PDEVICE *physDev;
365     DC *dc = MFDRV_CloseMetaFile(hdc);
366     if (!dc) return 0;
367     physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
368
369     /* Now allocate a global handle for the metafile */
370
371     hmf = MF_Create_HMETAFILE( physDev->mh );
372
373     physDev->mh = NULL;  /* So it won't be deleted */
374     MFDRV_DeleteDC( dc->physDev );
375     return hmf;
376 }
377
378
379 /******************************************************************
380  *         MFDRV_WriteRecord
381  *
382  * Warning: this function can change the pointer to the metafile header.
383  */
384 BOOL MFDRV_WriteRecord( PHYSDEV dev, METARECORD *mr, DWORD rlen)
385 {
386     DWORD len, size;
387     METAHEADER *mh;
388     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
389
390     switch(physDev->mh->mtType)
391     {
392     case METAFILE_MEMORY:
393         len = physDev->mh->mtSize * 2 + rlen;
394         /* reallocate memory if needed */
395         size = HeapSize( GetProcessHeap(), 0, physDev->mh );
396         if (len > size)
397         {
398             /*expand size*/
399             size += size / 2 + rlen;
400             mh = HeapReAlloc( GetProcessHeap(), 0, physDev->mh, size);
401             if (!mh) return FALSE;
402             physDev->mh = mh;
403             TRACE("Reallocated metafile: new size is %ld\n",size);
404         }
405         memcpy((WORD *)physDev->mh + physDev->mh->mtSize, mr, rlen);
406         break;
407     case METAFILE_DISK:
408         TRACE("Writing record to disk\n");
409         if (!WriteFile(physDev->hFile, (char *)mr, rlen, NULL, NULL))
410             return FALSE;
411         break;
412     default:
413         ERR("Unknown metafile type %d\n", physDev->mh->mtType );
414         return FALSE;
415     }
416
417     physDev->mh->mtSize += rlen / 2;
418     physDev->mh->mtMaxRecord = max(physDev->mh->mtMaxRecord, rlen / 2);
419     return TRUE;
420 }
421
422
423 /******************************************************************
424  *         MFDRV_MetaParam0
425  */
426
427 BOOL MFDRV_MetaParam0(PHYSDEV dev, short func)
428 {
429     char buffer[8];
430     METARECORD *mr = (METARECORD *)&buffer;
431
432     mr->rdSize = 3;
433     mr->rdFunction = func;
434     return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
435 }
436
437
438 /******************************************************************
439  *         MFDRV_MetaParam1
440  */
441 BOOL MFDRV_MetaParam1(PHYSDEV dev, short func, short param1)
442 {
443     char buffer[8];
444     METARECORD *mr = (METARECORD *)&buffer;
445
446     mr->rdSize = 4;
447     mr->rdFunction = func;
448     *(mr->rdParm) = param1;
449     return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
450 }
451
452
453 /******************************************************************
454  *         MFDRV_MetaParam2
455  */
456 BOOL MFDRV_MetaParam2(PHYSDEV dev, short func, short param1, short param2)
457 {
458     char buffer[10];
459     METARECORD *mr = (METARECORD *)&buffer;
460
461     mr->rdSize = 5;
462     mr->rdFunction = func;
463     *(mr->rdParm) = param2;
464     *(mr->rdParm + 1) = param1;
465     return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
466 }
467
468
469 /******************************************************************
470  *         MFDRV_MetaParam4
471  */
472
473 BOOL MFDRV_MetaParam4(PHYSDEV dev, short func, short param1, short param2,
474                       short param3, short param4)
475 {
476     char buffer[14];
477     METARECORD *mr = (METARECORD *)&buffer;
478
479     mr->rdSize = 7;
480     mr->rdFunction = func;
481     *(mr->rdParm) = param4;
482     *(mr->rdParm + 1) = param3;
483     *(mr->rdParm + 2) = param2;
484     *(mr->rdParm + 3) = param1;
485     return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
486 }
487
488
489 /******************************************************************
490  *         MFDRV_MetaParam6
491  */
492
493 BOOL MFDRV_MetaParam6(PHYSDEV dev, short func, short param1, short param2,
494                       short param3, short param4, short param5, short param6)
495 {
496     char buffer[18];
497     METARECORD *mr = (METARECORD *)&buffer;
498
499     mr->rdSize = 9;
500     mr->rdFunction = func;
501     *(mr->rdParm) = param6;
502     *(mr->rdParm + 1) = param5;
503     *(mr->rdParm + 2) = param4;
504     *(mr->rdParm + 3) = param3;
505     *(mr->rdParm + 4) = param2;
506     *(mr->rdParm + 5) = param1;
507     return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
508 }
509
510
511 /******************************************************************
512  *         MFDRV_MetaParam8
513  */
514 BOOL MFDRV_MetaParam8(PHYSDEV dev, short func, short param1, short param2,
515                       short param3, short param4, short param5,
516                       short param6, short param7, short param8)
517 {
518     char buffer[22];
519     METARECORD *mr = (METARECORD *)&buffer;
520
521     mr->rdSize = 11;
522     mr->rdFunction = func;
523     *(mr->rdParm) = param8;
524     *(mr->rdParm + 1) = param7;
525     *(mr->rdParm + 2) = param6;
526     *(mr->rdParm + 3) = param5;
527     *(mr->rdParm + 4) = param4;
528     *(mr->rdParm + 5) = param3;
529     *(mr->rdParm + 6) = param2;
530     *(mr->rdParm + 7) = param1;
531     return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
532 }
533
534
535 /******************************************************************
536  *         MFDRV_AddHandleDC
537  *
538  * Note: this function assumes that we never delete objects.
539  * If we do someday, we'll need to maintain a table to re-use deleted
540  * handles.
541  */
542 int MFDRV_AddHandleDC( PHYSDEV dev )
543 {
544     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
545     physDev->mh->mtNoObjects++;
546     return physDev->nextHandle++;
547 }
548
549 /**********************************************************************
550  *           MFDRV_ExtEscape
551  */
552 INT MFDRV_ExtEscape( PHYSDEV dev, INT nEscape, INT cbInput, LPCVOID in_data,
553                      INT cbOutput, LPVOID out_data )
554 {
555     METARECORD *mr;
556     DWORD len;
557     INT ret;
558
559     len = sizeof(*mr) + sizeof(WORD) + ((cbInput + 1) & ~1);
560     mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
561     mr->rdSize = len / 2;
562     mr->rdFunction = META_ESCAPE;
563     mr->rdParm[0] = nEscape;
564     mr->rdParm[1] = cbInput;
565     memcpy(&(mr->rdParm[2]), in_data, cbInput);
566     ret = MFDRV_WriteRecord( dev, mr, len);
567     HeapFree(GetProcessHeap(), 0, mr);
568     return ret;
569 }
570
571
572 /******************************************************************
573  *         MFDRV_GetDeviceCaps
574  *
575  *A very simple implementation that returns DT_METAFILE
576  */
577 INT MFDRV_GetDeviceCaps(PHYSDEV dev, INT cap)
578 {
579     switch(cap)
580     {
581     case TECHNOLOGY:
582         return DT_METAFILE;
583     case TEXTCAPS:
584         return 0;
585     default:
586         TRACE(" unsupported capability %d, will return 0\n", cap );
587     }
588     return 0;
589 }