Winspool DocumentProperties and DeviceCapabilities should now work on
[wine] / graphics / psdrv / init.c
1 /*
2  *      PostScript driver initialization functions
3  *
4  *      Copyright 1998 Huw D M Davies
5  *
6  */
7 #include <string.h>
8
9 #include "gdi.h"
10 #include "psdrv.h"
11 #include "debugtools.h"
12 #include "heap.h"
13 #include "winreg.h"
14 #include "winspool.h"
15 #include "winerror.h"
16 #include "options.h"
17
18 DEFAULT_DEBUG_CHANNEL(psdrv)
19
20 static BOOL PSDRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device,
21                                LPCSTR output, const DEVMODEA* initData );
22 static BOOL PSDRV_DeleteDC( DC *dc );
23
24 static const DC_FUNCTIONS PSDRV_Funcs =
25 {
26     NULL,                            /* pAbortDoc */
27     PSDRV_Arc,                       /* pArc */
28     NULL,                            /* pBitBlt */
29     NULL,                            /* pBitmapBits */
30     PSDRV_Chord,                     /* pChord */
31     NULL,                            /* pCreateBitmap */
32     PSDRV_CreateDC,                  /* pCreateDC */
33     NULL,                            /* pCreateDIBSection */
34     NULL,                            /* pCreateDIBSection16 */
35     PSDRV_DeleteDC,                  /* pDeleteDC */
36     NULL,                            /* pDeleteObject */
37     PSDRV_DeviceCapabilities,        /* pDeviceCapabilities */
38     PSDRV_Ellipse,                   /* pEllipse */
39     PSDRV_EndDoc,                    /* pEndDoc */
40     PSDRV_EndPage,                   /* pEndPage */
41     PSDRV_EnumDeviceFonts,           /* pEnumDeviceFonts */
42     PSDRV_Escape,                    /* pEscape */
43     NULL,                            /* pExcludeClipRect */
44     PSDRV_ExtDeviceMode,             /* pExtDeviceMode */
45     NULL,                            /* pExtFloodFill */
46     PSDRV_ExtTextOut,                /* pExtTextOut */
47     NULL,                            /* pFillRgn */
48     NULL,                            /* pFrameRgn */
49     PSDRV_GetCharWidth,              /* pGetCharWidth */
50     NULL,                            /* pGetPixel */
51     PSDRV_GetTextExtentPoint,        /* pGetTextExtentPoint */
52     PSDRV_GetTextMetrics,            /* pGetTextMetrics */
53     NULL,                            /* pIntersectClipRect */
54     NULL,                            /* pInvertRgn */
55     PSDRV_LineTo,                    /* pLineTo */
56     NULL,                            /* pLoadOEMResource */
57     PSDRV_MoveToEx,                  /* pMoveToEx */
58     NULL,                            /* pOffsetClipRgn */
59     NULL,                            /* pOffsetViewportOrg (optional) */
60     NULL,                            /* pOffsetWindowOrg (optional) */
61     NULL,                            /* pPaintRgn */
62     PSDRV_PatBlt,                    /* pPatBlt */
63     PSDRV_Pie,                       /* pPie */
64     PSDRV_PolyPolygon,               /* pPolyPolygon */
65     PSDRV_PolyPolyline,              /* pPolyPolyline */
66     PSDRV_Polygon,                   /* pPolygon */
67     PSDRV_Polyline,                  /* pPolyline */
68     NULL,                            /* pPolyBezier */               
69     NULL,                            /* pRealizePalette */
70     PSDRV_Rectangle,                 /* pRectangle */
71     NULL,                            /* pRestoreDC */
72     PSDRV_RoundRect,                 /* pRoundRect */
73     NULL,                            /* pSaveDC */
74     NULL,                            /* pScaleViewportExt (optional) */
75     NULL,                            /* pScaleWindowExt (optional) */
76     NULL,                            /* pSelectClipRgn */
77     PSDRV_SelectObject,              /* pSelectObject */
78     NULL,                            /* pSelectPalette */
79     PSDRV_SetBkColor,                /* pSetBkColor */
80     NULL,                            /* pSetBkMode */
81     NULL,                            /* pSetDeviceClipping */
82     NULL,                            /* pSetDIBitsToDevice */
83     NULL,                            /* pSetMapMode (optional) */
84     NULL,                            /* pSetMapperFlags */
85     PSDRV_SetPixel,                  /* pSetPixel */
86     NULL,                            /* pSetPolyFillMode */
87     NULL,                            /* pSetROP2 */
88     NULL,                            /* pSetRelAbs */
89     NULL,                            /* pSetStretchBltMode */
90     NULL,                            /* pSetTextAlign */
91     NULL,                            /* pSetTextCharacterExtra */
92     PSDRV_SetTextColor,              /* pSetTextColor */
93     NULL,                            /* pSetTextJustification */
94     NULL,                            /* pSetViewportExt (optional) */
95     NULL,                            /* pSetViewportOrg (optional) */
96     NULL,                            /* pSetWindowExt (optional) */
97     NULL,                            /* pSetWindowOrg (optional) */
98     PSDRV_StartDoc,                  /* pStartDoc */
99     PSDRV_StartPage,                 /* pStartPage */
100     NULL,                            /* pStretchBlt */
101     PSDRV_StretchDIBits              /* pStretchDIBits */
102 };
103
104
105 /* Default entries for devcaps */
106
107 static DeviceCaps PSDRV_DevCaps = {
108 /* version */           0, 
109 /* technology */        DT_RASPRINTER,
110 /* horzSize */          210,
111 /* vertSize */          297,
112 /* horzRes */           4961,
113 /* vertRes */           7016, 
114 /* bitsPixel */         1,
115 /* planes */            1,
116 /* numBrushes */        -1,
117 /* numPens */           10,
118 /* numMarkers */        0,
119 /* numFonts */          39,
120 /* numColors */         2,
121 /* pdeviceSize */       0,      
122 /* curveCaps */         CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES |
123                         CC_WIDE | CC_STYLED | CC_WIDESTYLED | CC_INTERIORS |
124                         CC_ROUNDRECT,
125 /* lineCaps */          LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
126                         LC_STYLED | LC_WIDESTYLED | LC_INTERIORS,
127 /* polygoalnCaps */     PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON |
128                         PC_SCANLINE | PC_WIDE | PC_STYLED | PC_WIDESTYLED |
129                         PC_INTERIORS,
130 /* textCaps */          TC_CR_ANY, /* psdrv 0x59f7 */
131 /* clipCaps */          CP_RECTANGLE,
132 /* rasterCaps */        RC_BITBLT | RC_BITMAP64 | RC_GDI20_OUTPUT |
133                         RC_DIBTODEV | RC_STRETCHBLT |
134                         RC_STRETCHDIB, /* psdrv 0x6e99 */
135 /* aspectX */           600,
136 /* aspectY */           600,
137 /* aspectXY */          848,
138 /* pad1 */              { 0 },
139 /* logPixelsX */        600,
140 /* logPixelsY */        600, 
141 /* pad2 */              { 0 },
142 /* palette size */      0,
143 /* ..etc */             0, 0 };
144
145 static PSDRV_DEVMODEA DefaultDevmode = 
146 {
147   { /* dmPublic */
148 /* dmDeviceName */      "Wine PostScript Driver",
149 /* dmSpecVersion */     0x30a,
150 /* dmDriverVersion */   0x001,
151 /* dmSize */            sizeof(DEVMODEA),
152 /* dmDriverExtra */     0,
153 /* dmFields */          DM_ORIENTATION | DM_PAPERSIZE | DM_SCALE | 
154                         DM_COPIES | DM_DEFAULTSOURCE | DM_COLOR | 
155                         DM_DUPLEX | DM_YRESOLUTION | DM_TTOPTION,
156    { /* u1 */
157      { /* s1 */
158 /* dmOrientation */     DMORIENT_PORTRAIT,
159 /* dmPaperSize */       DMPAPER_A4,
160 /* dmPaperLength */     2969,
161 /* dmPaperWidth */      2101
162      }
163    },
164 /* dmScale */           100, /* ?? */
165 /* dmCopies */          1,
166 /* dmDefaultSource */   DMBIN_AUTO,
167 /* dmPrintQuality */    0,
168 /* dmColor */           DMCOLOR_MONOCHROME,
169 /* dmDuplex */          0,
170 /* dmYResolution */     0,
171 /* dmTTOption */        DMTT_SUBDEV,
172 /* dmCollate */         0,
173 /* dmFormName */        "",
174 /* dmUnusedPadding */   0,
175 /* dmBitsPerPel */      0,
176 /* dmPelsWidth */       0,
177 /* dmPelsHeight */      0,
178 /* dmDisplayFlags */    0,
179 /* dmDisplayFrequency */ 0
180   },
181   { /* dmDocPrivate */
182     0 /* dummy */
183   },
184   { /* dmDrvPrivate */
185 /* ppdfilename */       "default.ppd"
186   }
187 };
188
189 HANDLE PSDRV_Heap = 0;
190
191 static HANDLE PSDRV_DefaultFont = 0;
192 static LOGFONTA DefaultLogFont = {
193     100, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, 0, 0,
194     DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, ""
195 };
196
197 /*********************************************************************
198  *           PSDRV_Init
199  *
200  * Initializes font metrics and registers driver. Called from GDI_Init()
201  *
202  */
203 BOOL PSDRV_Init(void)
204 {
205     TRACE("\n");
206     PSDRV_Heap = HeapCreate(0, 0x10000, 0);
207     PSDRV_GetFontMetrics();
208     PSDRV_DefaultFont = CreateFontIndirectA(&DefaultLogFont);
209     return DRIVER_RegisterDriver( "WINEPS", &PSDRV_Funcs );
210 }
211
212 /**********************************************************************
213  *           PSDRV_CreateDC
214  */
215 static BOOL PSDRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device,
216                                LPCSTR output, const DEVMODEA* initData )
217 {
218     PSDRV_PDEVICE *physDev;
219     PRINTERINFO *pi;
220     DeviceCaps *devCaps;
221
222     /* If no device name was specified, retrieve the device name
223      * from the DEVMODE structure from the DC's physDev.
224      * (See CreateCompatibleDC) */
225     if ( !device && dc->physDev )
226     {
227         physDev = (PSDRV_PDEVICE *)dc->physDev;
228         device = physDev->Devmode->dmPublic.dmDeviceName;
229     }
230     pi = PSDRV_FindPrinterInfo(device);
231         
232     TRACE("(%s %s %s %p)\n", driver, device, output, initData);
233
234     if(!pi) return FALSE;
235
236     if(!pi->Fonts) {
237         MESSAGE("To use WINEPS you need to install some AFM files.\n");
238         return FALSE;
239     }
240
241     physDev = (PSDRV_PDEVICE *)HeapAlloc( PSDRV_Heap, HEAP_ZERO_MEMORY,
242                                                      sizeof(*physDev) );
243     if (!physDev) return FALSE;
244     dc->physDev = physDev;
245
246     physDev->pi = pi;
247
248     physDev->Devmode = (PSDRV_DEVMODEA *)HeapAlloc( PSDRV_Heap, 0,
249                                                      sizeof(PSDRV_DEVMODEA) );
250     if(!physDev->Devmode) {
251         HeapFree( PSDRV_Heap, 0, physDev );
252         return FALSE;
253     }
254     
255     memcpy( physDev->Devmode, pi->Devmode, sizeof(PSDRV_DEVMODEA) );
256
257     if(initData) {
258         PSDRV_MergeDevmodes(physDev->Devmode, (PSDRV_DEVMODEA *)initData, pi);
259     }
260
261     
262     devCaps = HeapAlloc( PSDRV_Heap, 0, sizeof(PSDRV_DevCaps) );
263     memcpy(devCaps, &PSDRV_DevCaps, sizeof(PSDRV_DevCaps));
264
265     if(physDev->Devmode->dmPublic.u1.s1.dmOrientation == DMORIENT_PORTRAIT) {
266         devCaps->horzSize = physDev->Devmode->dmPublic.u1.s1.dmPaperWidth / 10;
267         devCaps->vertSize = physDev->Devmode->dmPublic.u1.s1.dmPaperLength / 10;
268     } else {
269         devCaps->horzSize = physDev->Devmode->dmPublic.u1.s1.dmPaperLength / 10;
270         devCaps->vertSize = physDev->Devmode->dmPublic.u1.s1.dmPaperWidth / 10;
271     }
272
273     devCaps->horzRes = physDev->pi->ppd->DefaultResolution * 
274       devCaps->horzSize / 25.4;
275     devCaps->vertRes = physDev->pi->ppd->DefaultResolution * 
276       devCaps->vertSize / 25.4;
277
278     /* Are aspect[XY] and logPixels[XY] correct? */
279     /* Need to handle different res in x and y => fix ppd */
280     devCaps->aspectX = devCaps->logPixelsX = 
281                                 physDev->pi->ppd->DefaultResolution;
282     devCaps->aspectY = devCaps->logPixelsY = 
283                                 physDev->pi->ppd->DefaultResolution;
284     devCaps->aspectXY = (int)hypot( (double)devCaps->aspectX, 
285                                     (double)devCaps->aspectY );
286
287     if(physDev->pi->ppd->ColorDevice) {
288         devCaps->bitsPixel = 8;
289         devCaps->numColors = 256;
290         /* FIXME are these values OK? */
291     }
292
293     /* etc */
294
295     dc->w.devCaps = devCaps;
296
297     dc->w.hVisRgn = CreateRectRgn(0, 0, dc->w.devCaps->horzRes,
298                             dc->w.devCaps->vertRes);
299     
300     dc->w.hFont = PSDRV_DefaultFont;
301     physDev->job.output = output ?
302       HEAP_strdupA( PSDRV_Heap, 0, output ) :
303       HEAP_strdupA( PSDRV_Heap, 0, "LPT1:" );  /* HACK */
304     physDev->job.hJob = 0;
305     return TRUE;
306 }
307
308
309 /**********************************************************************
310  *           PSDRV_DeleteDC
311  */
312 static BOOL PSDRV_DeleteDC( DC *dc )
313 {
314     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
315     
316     TRACE("\n");
317
318     HeapFree( PSDRV_Heap, 0, physDev->Devmode );
319     HeapFree( PSDRV_Heap, 0, physDev->job.output );
320     HeapFree( PSDRV_Heap, 0, (void *)dc->w.devCaps );
321     HeapFree( PSDRV_Heap, 0, physDev );
322     dc->physDev = NULL;
323
324     return TRUE;
325 }
326
327
328         
329
330 /**********************************************************************
331  *              PSDRV_FindPrinterInfo
332  */
333 PRINTERINFO *PSDRV_FindPrinterInfo(LPCSTR name) 
334 {
335     static PRINTERINFO *PSDRV_PrinterList;
336     DWORD type = REG_BINARY, needed, res;
337     PRINTERINFO *pi = PSDRV_PrinterList, **last = &PSDRV_PrinterList;
338     FONTNAME *font;
339     AFM *afm;
340
341     TRACE("'%s'\n", name);
342     
343     for( ; pi; last = &pi->next, pi = pi->next) {
344         if(!strcmp(pi->FriendlyName, name))
345             return pi;
346     }
347
348     pi = *last = HeapAlloc( PSDRV_Heap, 0, sizeof(*pi) );
349     pi->FriendlyName = HEAP_strdupA( PSDRV_Heap, 0, name );
350     res = DrvGetPrinterData16((LPSTR)name, (LPSTR)INT_PD_DEFAULT_DEVMODE, &type,
351                             NULL, 0, &needed );
352
353     if(res == ERROR_INVALID_PRINTER_NAME || needed != sizeof(DefaultDevmode)) {
354         pi->Devmode = HeapAlloc( PSDRV_Heap, 0, sizeof(DefaultDevmode) );
355         memcpy(pi->Devmode, &DefaultDevmode, sizeof(DefaultDevmode) );
356         DrvSetPrinterData16((LPSTR)name, (LPSTR)INT_PD_DEFAULT_DEVMODE,
357                  REG_BINARY, (LPBYTE)&DefaultDevmode, sizeof(DefaultDevmode) );
358
359         /* need to do something here AddPrinter?? */
360     } else {
361         pi->Devmode = HeapAlloc( PSDRV_Heap, 0, needed );
362         DrvGetPrinterData16((LPSTR)name, (LPSTR)INT_PD_DEFAULT_DEVMODE, &type,
363                           (LPBYTE)pi->Devmode, needed, &needed);
364     }
365
366     PROFILE_GetWineIniString("psdrv", "ppdfile", "default.ppd",
367                              pi->Devmode->dmDrvPrivate.ppdFileName, 256);
368     pi->ppd = PSDRV_ParsePPD(pi->Devmode->dmDrvPrivate.ppdFileName);
369     if(!pi->ppd) {
370         HeapFree(PSDRV_Heap, 0, pi->FriendlyName);
371         HeapFree(PSDRV_Heap, 0, pi->Devmode);
372         HeapFree(PSDRV_Heap, 0, pi);
373         *last = NULL;
374         MESSAGE("Couldn't find PPD file '%s', expect a crash now!\n",
375             pi->Devmode->dmDrvPrivate.ppdFileName);
376         return NULL;
377     }
378
379     pi->next = NULL;
380     pi->Fonts = NULL;
381
382     for(font = pi->ppd->InstalledFonts; font; font = font->next) {
383         afm = PSDRV_FindAFMinList(PSDRV_AFMFontList, font->Name);
384         if(!afm) {
385             MESSAGE(
386          "Couldn't find AFM file for installed printer font '%s' - ignoring\n",
387          font->Name);
388         } else {
389             PSDRV_AddAFMtoList(&pi->Fonts, afm);
390         }
391     }
392
393     return pi;
394 }