Added regedit unit test, a couple minor changes to regedit.
[wine] / dlls / gdi / win16drv / init.c
1 /*
2  * Windows Device Context initialisation functions
3  *
4  * Copyright 1996 John Harvey
5  *           1998 Huw Davies
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <ctype.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "winreg.h"
27 #include "win16drv/win16drv.h"
28 #include "gdi.h"
29 #include "bitmap.h"
30 #include "font.h"
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(win16drv);
34
35 #define SUPPORT_REALIZED_FONTS 1
36 #include "pshpack1.h"
37 typedef struct
38 {
39   SHORT nSize;
40   SEGPTR lpindata;
41   SEGPTR lpFont;
42   SEGPTR lpXForm;
43   SEGPTR lpDrawMode;
44 } EXTTEXTDATA, *LPEXTTEXTDATA;
45 #include "poppack.h"
46
47 SEGPTR          win16drv_SegPtr_TextXForm;
48 LPTEXTXFORM16   win16drv_TextXFormP;
49 SEGPTR          win16drv_SegPtr_DrawMode;
50 LPDRAWMODE      win16drv_DrawModeP;
51
52
53 static BOOL WIN16DRV_CreateDC( DC *dc, PHYSDEV *pdev, LPCSTR driver, LPCSTR device,
54                                  LPCSTR output, const DEVMODEA* initData );
55 static INT WIN16DRV_GetDeviceCaps( PHYSDEV dev, INT cap );
56 static INT WIN16DRV_ExtEscape( PHYSDEV dev, INT escape, INT in_count, LPCVOID in_data,
57                                INT out_count, LPVOID out_data );
58
59 static const DC_FUNCTIONS WIN16DRV_Funcs =
60 {
61     NULL,                            /* pAbortDoc */
62     NULL,                            /* pAbortPath */
63     NULL,                            /* pAngleArc */
64     NULL,                            /* pArc */
65     NULL,                            /* pArcTo */
66     NULL,                            /* pBeginPath */
67     NULL,                            /* pBitBlt */
68     NULL,                            /* pChoosePixelFormat */
69     NULL,                            /* pChord */
70     NULL,                            /* pCloseFigure */
71     NULL,                            /* pCreateBitmap */
72     WIN16DRV_CreateDC,               /* pCreateDC */
73     NULL,                            /* pCreateDIBSection */
74     NULL,                            /* pDeleteBitmap */
75     NULL,                            /* pDeleteDC */
76     NULL,                            /* pDescribePixelFormat */
77     WIN16DRV_DeviceCapabilities,     /* pDeviceCapabilities */
78     WIN16DRV_Ellipse,                /* pEllipse */
79     NULL,                            /* pEndDoc */
80     NULL,                            /* pEndPage */
81     NULL,                            /* pEndPath */
82     WIN16DRV_EnumDeviceFonts,        /* pEnumDeviceFonts */
83     NULL,                            /* pExcludeClipRect */
84     WIN16DRV_ExtDeviceMode,          /* pExtDeviceMode */
85     WIN16DRV_ExtEscape,              /* pExtEscape */
86     NULL,                            /* pExtFloodFill */
87     NULL,                            /* pExtSelectClipRgn */
88     WIN16DRV_ExtTextOut,             /* pExtTextOut */
89     NULL,                            /* pFillPath */
90     NULL,                            /* pFillRgn */
91     NULL,                            /* pFlattenPath */
92     NULL,                            /* pFrameRgn */
93     NULL,                            /* pGetBitmapBits */
94     WIN16DRV_GetCharWidth,           /* pGetCharWidth */
95     NULL,                            /* pGetDCOrgEx */
96     NULL,                            /* pGetDIBColorTable */
97     NULL,                            /* pGetDIBits */
98     WIN16DRV_GetDeviceCaps,          /* pGetDeviceCaps */
99     NULL,                            /* pGetDeviceGammaRamp */
100     NULL,                            /* pGetNearestColor */
101     NULL,                            /* pGetPixel */
102     NULL,                            /* pGetPixelFormat */
103     NULL,                            /* pGetSystemPaletteEntries */
104     WIN16DRV_GetTextExtentPoint,     /* pGetTextExtentPoint */
105     WIN16DRV_GetTextMetrics,         /* pGetTextMetrics */
106     NULL,                            /* pIntersectClipRect */
107     NULL,                            /* pInvertRgn */
108     WIN16DRV_LineTo,                 /* pLineTo */
109     NULL,                            /* pMoveTo */
110     NULL,                            /* pOffsetClipRgn */
111     NULL,                            /* pOffsetViewportOrgEx */
112     NULL,                            /* pOffsetWindowOrgEx */
113     NULL,                            /* pPaintRgn */
114     WIN16DRV_PatBlt,                 /* pPatBlt */
115     NULL,                            /* pPie */
116     NULL,                            /* pPolyBezier */
117     NULL,                            /* pPolyBezierTo */
118     NULL,                            /* pPolyDraw */
119     NULL,                            /* pPolyPolygon */
120     NULL,                            /* pPolyPolyline */
121     WIN16DRV_Polygon,                /* pPolygon */
122     WIN16DRV_Polyline,               /* pPolyline */
123     NULL,                            /* pPolylineTo */
124     NULL,                            /* pRealizeDefaultPalette */
125     NULL,                            /* pRealizePalette */
126     WIN16DRV_Rectangle,              /* pRectangle */
127     NULL,                            /* pResetDC */
128     NULL,                            /* pRestoreDC */
129     NULL,                            /* pRoundRect */
130     NULL,                            /* pSaveDC */
131     NULL,                            /* pScaleViewportExtEx */
132     NULL,                            /* pScaleWindowExtEx */
133     WIN16DRV_SelectBitmap,           /* pSelectBitmap */
134     WIN16DRV_SelectBrush,            /* pSelectBrush */
135     NULL,                            /* pSelectClipPath */
136     WIN16DRV_SelectFont,             /* pSelectFont */
137     NULL,                            /* pSelectPalette */
138     WIN16DRV_SelectPen,              /* pSelectPen */
139     NULL,                            /* pSetBitmapBits */
140     NULL,                            /* pSetBkColor */
141     NULL,                            /* pSetBkMode */
142     NULL,                            /* pSetDCOrg */
143     NULL,                            /* pSetDIBColorTable */
144     NULL,                            /* pSetDIBits */
145     NULL,                            /* pSetDIBitsToDevice */
146     NULL,                            /* pSetDeviceClipping */
147     NULL,                            /* pSetDeviceGammaRamp */
148     NULL,                            /* pSetMapMode */
149     NULL,                            /* pSetMapperFlags */
150     NULL,                            /* pSetPixel */
151     NULL,                            /* pSetPixelFormat */
152     NULL,                            /* pSetPolyFillMode */
153     NULL,                            /* pSetROP2 */
154     NULL,                            /* pSetRelAbs */
155     NULL,                            /* pSetStretchBltMode */
156     NULL,                            /* pSetTextAlign */
157     NULL,                            /* pSetTextCharacterExtra */
158     NULL,                            /* pSetTextColor */
159     NULL,                            /* pSetTextJustification */
160     NULL,                            /* pSetViewportExtEx */
161     NULL,                            /* pSetViewportOrgEx */
162     NULL,                            /* pSetWindowExtEx */
163     NULL,                            /* pSetWindowOrgEx */
164     NULL,                            /* pStartDoc */
165     NULL,                            /* pStartPage */
166     NULL,                            /* pStretchBlt */
167     NULL,                            /* pStretchDIBits */
168     NULL,                            /* pStrokeAndFillPath */
169     NULL,                            /* pStrokePath */
170     NULL,                            /* pSwapBuffers */
171     NULL                             /* pWidenPath */
172 };
173
174
175 /**********************************************************************
176  *           WIN16DRV_Init
177  */
178 const DC_FUNCTIONS *WIN16DRV_Init(void)
179 {
180     static int enabled = -1;
181
182     if (enabled == -1)
183     {
184         char printerEnabled[20];
185         HKEY hkey;
186
187         /* default value */
188         strcpy( printerEnabled, "off" );
189         if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\wine", &hkey))
190         {
191             DWORD type, count = sizeof(printerEnabled);
192             RegQueryValueExA(hkey, "printer", 0, &type, printerEnabled, &count);
193             RegCloseKey(hkey);
194         }
195         enabled = !strcasecmp( printerEnabled, "on" );
196         if (!enabled)
197         {
198             MESSAGE("Printing disabled in wine.conf or .winerc file\n");
199             MESSAGE("Use \"printer=on\" in the \"[wine]\" section to enable it.\n");
200         }
201     }
202
203     return enabled ? &WIN16DRV_Funcs : NULL;
204 }
205
206 /* Tempory functions, for initialising structures */
207 /* These values should be calculated, not hardcoded */
208 void InitTextXForm(LPTEXTXFORM16 lpTextXForm)
209 {
210     lpTextXForm->txfHeight      = 0x0001;
211     lpTextXForm->txfWidth       = 0x000c;
212     lpTextXForm->txfEscapement  = 0x0000;
213     lpTextXForm->txfOrientation = 0x0000;
214     lpTextXForm->txfWeight      = 0x0190;
215     lpTextXForm->txfItalic      = 0x00;
216     lpTextXForm->txfUnderline   = 0x00;
217     lpTextXForm->txfStrikeOut   = 0x00;
218     lpTextXForm->txfOutPrecision = 0x02;
219     lpTextXForm->txfClipPrecision = 0x01;
220     lpTextXForm->txfAccelerator = 0x0001;
221     lpTextXForm->txfOverhang    = 0x0000;
222 }
223
224
225 void InitDrawMode(LPDRAWMODE lpDrawMode)
226 {
227     lpDrawMode->Rop2            = 0x000d;
228     lpDrawMode->bkMode          = 0x0001;
229     lpDrawMode->bkColor         = 0x3fffffff;
230     lpDrawMode->TextColor       = 0x20000000;
231     lpDrawMode->TBreakExtra     = 0x0000;
232     lpDrawMode->BreakExtra      = 0x0000;
233     lpDrawMode->BreakErr        = 0x0000;
234     lpDrawMode->BreakRem        = 0x0000;
235     lpDrawMode->BreakCount      = 0x0000;
236     lpDrawMode->CharExtra       = 0x0000;
237     lpDrawMode->LbkColor        = 0x00ffffff;
238     lpDrawMode->LTextColor      = 0x00000000;
239     lpDrawMode->ICMCXform       = 0; /* ? */
240     lpDrawMode->StretchBltMode  = STRETCH_ANDSCANS;
241     lpDrawMode->eMiterLimit     = 1;
242 }
243
244 BOOL WIN16DRV_CreateDC( DC *dc, PHYSDEV *pdev, LPCSTR driver, LPCSTR device, LPCSTR output,
245                         const DEVMODEA* initData )
246 {
247     LOADED_PRINTER_DRIVER *pLPD;
248     WORD wRet;
249     int nPDEVICEsize;
250     PDEVICE_HEADER *pPDH;
251     WIN16DRV_PDEVICE *physDev;
252
253     TRACE("In creatdc for (%s,%s,%s) initData %p\n",
254           driver, device, output, initData);
255
256     physDev = (WIN16DRV_PDEVICE *)HeapAlloc( GetProcessHeap(), 0, sizeof(*physDev) );
257     if (!physDev) return FALSE;
258     *pdev = (PHYSDEV)physDev;
259     physDev->hdc = dc->hSelf;
260     physDev->dc = dc;
261     physDev->org.x = physDev->org.y = 0;
262
263     pLPD = LoadPrinterDriver(driver);
264     if (pLPD == NULL)
265     {
266         WARN("Failed to find printer driver\n");
267         HeapFree( GetProcessHeap(), 0, physDev );
268         return FALSE;
269     }
270     TRACE("windevCreateDC pLPD %p\n", pLPD);
271
272     /* Now Get the device capabilities from the printer driver */
273     memset( &physDev->DevCaps, 0, sizeof(physDev->DevCaps) );
274     if(!output) output = "LPT1:";
275
276     /* Get GDIINFO which is the same as a DeviceCaps structure */
277     wRet = PRTDRV_Enable(&physDev->DevCaps, GETGDIINFO, device, driver, output,NULL);
278
279     /* Add this to the DC */
280     dc->bitsPerPixel = physDev->DevCaps.bitsPixel;
281
282     TRACE("Got devcaps width %d height %d bits %d planes %d\n",
283           physDev->DevCaps.horzRes, physDev->DevCaps.vertRes,
284           physDev->DevCaps.bitsPixel, physDev->DevCaps.planes);
285
286     /* Now we allocate enough memory for the PDEVICE structure */
287     /* The size of this varies between printer drivers */
288     /* This PDEVICE is used by the printer DRIVER not by the GDI so must */
289     /* be accessable from 16 bit code */
290     nPDEVICEsize = physDev->DevCaps.pdeviceSize + sizeof(PDEVICE_HEADER);
291
292     /* TTD Shouldn't really do pointer arithmetic on segment points */
293     physDev->segptrPDEVICE = K32WOWGlobalLock16(GlobalAlloc16(GHND, nPDEVICEsize))+sizeof(PDEVICE_HEADER);
294     *((BYTE *)MapSL(physDev->segptrPDEVICE)+0) = 'N';
295     *((BYTE *)MapSL(physDev->segptrPDEVICE)+1) = 'B';
296
297     /* Set up the header */
298     pPDH = (PDEVICE_HEADER *)((BYTE*)MapSL(physDev->segptrPDEVICE) - sizeof(PDEVICE_HEADER));
299     pPDH->pLPD = pLPD;
300
301     TRACE("PDEVICE allocated %08lx\n",(DWORD)(physDev->segptrPDEVICE));
302
303     /* Now get the printer driver to initialise this data */
304     wRet = PRTDRV_Enable((LPVOID)physDev->segptrPDEVICE, INITPDEVICE, device, driver, output, NULL);
305
306     physDev->FontInfo = NULL;
307     physDev->BrushInfo = NULL;
308     physDev->PenInfo = NULL;
309     win16drv_SegPtr_TextXForm = K32WOWGlobalLock16(GlobalAlloc16(GHND, sizeof(TEXTXFORM16)));
310     win16drv_TextXFormP = MapSL(win16drv_SegPtr_TextXForm);
311
312     InitTextXForm(win16drv_TextXFormP);
313
314     /* TTD Lots more to do here */
315     win16drv_SegPtr_DrawMode = K32WOWGlobalLock16(GlobalAlloc16(GHND, sizeof(DRAWMODE)));
316     win16drv_DrawModeP = MapSL(win16drv_SegPtr_DrawMode);
317
318     InitDrawMode(win16drv_DrawModeP);
319
320     return TRUE;
321 }
322
323 BOOL WIN16DRV_PatBlt( PHYSDEV dev, INT left, INT top, INT width, INT height, DWORD rop )
324 {
325
326     WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dev;
327     BOOL bRet = 0;
328
329     bRet = PRTDRV_StretchBlt( physDev->segptrPDEVICE, left, top, width, height, (SEGPTR)NULL, 0, 0, width, height,
330                        PATCOPY, physDev->BrushInfo, win16drv_SegPtr_DrawMode, NULL);
331
332     return bRet;
333 }
334
335
336 /***********************************************************************
337  *           WIN16DRV_GetDeviceCaps
338  */
339 static INT WIN16DRV_GetDeviceCaps( PHYSDEV dev, INT cap )
340 {
341     WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dev;
342     if (cap >= PHYSICALWIDTH || (cap % 2))
343     {
344         FIXME("(%04x): unsupported capability %d, will return 0\n", physDev->hdc, cap );
345         return 0;
346     }
347     return *((WORD *)&physDev->DevCaps + (cap / 2));
348 }
349
350
351 /***********************************************************************
352  *           WIN16DRV_ExtEscape
353  */
354 static INT WIN16DRV_ExtEscape( PHYSDEV dev, INT escape, INT in_count, LPCVOID in_data,
355                                INT out_count, LPVOID out_data )
356 {
357 #if 0
358     WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dc->physDev;
359     int nRet = 0;
360
361     /* We should really process the nEscape parameter, but for now just
362        pass it all to the driver */
363     if (dc != NULL && physDev->segptrPDEVICE != 0)
364     {
365         switch(nEscape)
366           {
367           case ENABLEPAIRKERNING:
368             FIXME("Escape: ENABLEPAIRKERNING ignored.\n");
369             nRet = 1;
370             break;
371           case GETPAIRKERNTABLE:
372             FIXME("Escape: GETPAIRKERNTABLE ignored.\n");
373             nRet = 0;
374             break;
375           case SETABORTPROC: {
376                 /* FIXME: The AbortProc should be called:
377                 - After every write to printer port or spool file
378                 - Several times when no more disk space
379                 - Before every metafile record when GDI does banding
380                 */
381
382        /* Call Control with hdc as lpInData */
383             HDC16 *seghdc = SEGPTR_NEW(HDC16);
384             *seghdc = dc->hSelf;
385             nRet = PRTDRV_Control(physDev->segptrPDEVICE, nEscape,
386                                   SEGPTR_GET(seghdc), lpOutData);
387             SEGPTR_FREE(seghdc);
388             break;
389           }
390
391           case NEXTBAND:
392             {
393               LPPOINT16 newInData =  SEGPTR_NEW(POINT16);
394
395               nRet = PRTDRV_Control(physDev->segptrPDEVICE, nEscape,
396                                     SEGPTR_GET(newInData), lpOutData);
397               SEGPTR_FREE(newInData);
398               break;
399             }
400
401           case GETEXTENDEDTEXTMETRICS:
402             {
403               EXTTEXTDATA *textData = SEGPTR_NEW(EXTTEXTDATA);
404
405               textData->nSize = cbInput;
406               textData->lpindata = lpInData;
407               textData->lpFont = SEGPTR_GET( physDev->FontInfo );
408               textData->lpXForm = win16drv_SegPtr_TextXForm;
409               textData->lpDrawMode = win16drv_SegPtr_DrawMode;
410               nRet = PRTDRV_Control(physDev->segptrPDEVICE, nEscape,
411                                     SEGPTR_GET(textData), lpOutData);
412               SEGPTR_FREE(textData);
413             }
414           break;
415           case STARTDOC:
416             {
417               /* lpInData is not necessarily \0 terminated so make it so */
418               char *cp = SEGPTR_ALLOC(cbInput + 1);
419               memcpy(cp, MapSL(lpInData), cbInput);
420               cp[cbInput] = '\0';
421
422               nRet = PRTDRV_Control(physDev->segptrPDEVICE, nEscape,
423                                     SEGPTR_GET(cp), lpOutData);
424               SEGPTR_FREE(cp);
425               if (nRet != -1)
426                 {
427                   HDC *tmpHdc = SEGPTR_NEW(HDC);
428
429 #define SETPRINTERDC SETABORTPROC
430
431                   *tmpHdc = dc->hSelf;
432                   PRTDRV_Control(physDev->segptrPDEVICE, SETPRINTERDC,
433                                  SEGPTR_GET(tmpHdc), (SEGPTR)NULL);
434                   SEGPTR_FREE(tmpHdc);
435                 }
436             }
437             break;
438           default:
439             nRet = PRTDRV_Control(physDev->segptrPDEVICE, nEscape,
440                                   lpInData, lpOutData);
441             break;
442         }
443     }
444     else
445         WARN("Escape(nEscape = %04x) - ???\n", nEscape);
446     return nRet;
447 #endif
448     /* FIXME: should convert args to SEGPTR and redo all the above */
449     FIXME("temporarily broken, please fix\n");
450     return 0;
451 }