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