2 * PostScript driver initialization functions
4 * Copyright 1998 Huw D M Davies
5 * Copyright 2001 Marcus Meissner
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/port.h"
30 #ifdef HAVE_CUPS_CUPS_H
31 # include <cups/cups.h>
34 #define NONAMELESSUNION
35 #define NONAMELESSSTRUCT
44 #include "wine/library.h"
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
50 static void *cupshandle = NULL;
53 static const PSDRV_DEVMODEA DefaultDevmode =
56 /* dmDeviceName */ "Wine PostScript Driver",
57 /* dmSpecVersion */ 0x30a,
58 /* dmDriverVersion */ 0x001,
59 /* dmSize */ sizeof(DEVMODEA),
60 /* dmDriverExtra */ sizeof(PSDRV_DEVMODEA)-sizeof(DEVMODEA),
61 /* dmFields */ DM_ORIENTATION | DM_PAPERSIZE | DM_SCALE |
62 DM_COPIES | DM_DEFAULTSOURCE | DM_COLOR |
63 DM_YRESOLUTION | DM_TTOPTION,
66 /* dmOrientation */ DMORIENT_PORTRAIT,
67 /* dmPaperSize */ DMPAPER_LETTER,
68 /* dmPaperLength */ 2794,
69 /* dmPaperWidth */ 2159,
70 /* dmScale */ 100, /* ?? */
72 /* dmDefaultSource */ DMBIN_AUTO,
73 /* dmPrintQuality */ 0
76 /* dmColor */ DMCOLOR_COLOR,
77 /* dmDuplex */ DMDUP_SIMPLEX,
78 /* dmYResolution */ 0,
79 /* dmTTOption */ DMTT_SUBDEV,
82 /* dmUnusedPadding */ 0,
87 /* dmDisplayFlags */ 0
89 /* dmDisplayFrequency */ 0,
96 /* dmPanningWidth */ 0,
97 /* dmPanningHeight */ 0
103 /* numInstalledOptions */ 0
107 HINSTANCE PSDRV_hInstance = 0;
108 HANDLE PSDRV_Heap = 0;
110 static HFONT PSDRV_DefaultFont = 0;
111 static const LOGFONTA DefaultLogFont = {
112 100, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, 0, 0,
113 DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, ""
116 static const CHAR default_devmodeA[] = "Default DevMode";
117 static const struct gdi_dc_funcs psdrv_funcs;
119 /*********************************************************************
122 * Initializes font metrics and registers driver. wineps dll entry point.
125 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
127 TRACE("(%p, %d, %p)\n", hinst, reason, reserved);
131 case DLL_PROCESS_ATTACH:
132 PSDRV_hInstance = hinst;
133 DisableThreadLibraryCalls(hinst);
135 PSDRV_Heap = HeapCreate(0, 0x10000, 0);
136 if (PSDRV_Heap == NULL)
139 if (PSDRV_GetFontMetrics() == FALSE) {
140 HeapDestroy(PSDRV_Heap);
144 PSDRV_DefaultFont = CreateFontIndirectA(&DefaultLogFont);
145 if (PSDRV_DefaultFont == NULL) {
146 HeapDestroy(PSDRV_Heap);
149 #ifdef SONAME_LIBCUPS
150 /* dynamically load CUPS if not yet loaded */
152 cupshandle = wine_dlopen(SONAME_LIBCUPS, RTLD_NOW, NULL, 0);
153 if (!cupshandle) cupshandle = (void*)-1;
158 case DLL_PROCESS_DETACH:
160 DeleteObject( PSDRV_DefaultFont );
161 HeapDestroy( PSDRV_Heap );
162 #ifdef SONAME_LIBCUPS
163 if (cupshandle && (cupshandle != (void*)-1)) {
164 wine_dlclose(cupshandle, NULL, 0);
174 static void PSDRV_UpdateDevCaps( PSDRV_PDEVICE *physDev )
177 INT width = 0, height = 0;
179 if(physDev->Devmode->dmPublic.dmFields & DM_PAPERSIZE) {
180 LIST_FOR_EACH_ENTRY(page, &physDev->pi->ppd->PageSizes, PAGESIZE, entry) {
181 if(page->WinPage == physDev->Devmode->dmPublic.u1.s1.dmPaperSize)
185 if(&page->entry == &physDev->pi->ppd->PageSizes) {
186 FIXME("Can't find page\n");
187 physDev->ImageableArea.left = 0;
188 physDev->ImageableArea.right = 0;
189 physDev->ImageableArea.bottom = 0;
190 physDev->ImageableArea.top = 0;
191 physDev->PageSize.cx = 0;
192 physDev->PageSize.cy = 0;
193 } else if(page->ImageableArea) {
194 /* physDev sizes in device units; ppd sizes in 1/72" */
195 physDev->ImageableArea.left = page->ImageableArea->llx *
196 physDev->logPixelsX / 72;
197 physDev->ImageableArea.right = page->ImageableArea->urx *
198 physDev->logPixelsX / 72;
199 physDev->ImageableArea.bottom = page->ImageableArea->lly *
200 physDev->logPixelsY / 72;
201 physDev->ImageableArea.top = page->ImageableArea->ury *
202 physDev->logPixelsY / 72;
203 physDev->PageSize.cx = page->PaperDimension->x *
204 physDev->logPixelsX / 72;
205 physDev->PageSize.cy = page->PaperDimension->y *
206 physDev->logPixelsY / 72;
208 physDev->ImageableArea.left = physDev->ImageableArea.bottom = 0;
209 physDev->ImageableArea.right = physDev->PageSize.cx =
210 page->PaperDimension->x * physDev->logPixelsX / 72;
211 physDev->ImageableArea.top = physDev->PageSize.cy =
212 page->PaperDimension->y * physDev->logPixelsY / 72;
214 } else if((physDev->Devmode->dmPublic.dmFields & DM_PAPERLENGTH) &&
215 (physDev->Devmode->dmPublic.dmFields & DM_PAPERWIDTH)) {
216 /* physDev sizes in device units; Devmode sizes in 1/10 mm */
217 physDev->ImageableArea.left = physDev->ImageableArea.bottom = 0;
218 physDev->ImageableArea.right = physDev->PageSize.cx =
219 physDev->Devmode->dmPublic.u1.s1.dmPaperWidth *
220 physDev->logPixelsX / 254;
221 physDev->ImageableArea.top = physDev->PageSize.cy =
222 physDev->Devmode->dmPublic.u1.s1.dmPaperLength *
223 physDev->logPixelsY / 254;
225 FIXME("Odd dmFields %x\n", physDev->Devmode->dmPublic.dmFields);
226 physDev->ImageableArea.left = 0;
227 physDev->ImageableArea.right = 0;
228 physDev->ImageableArea.bottom = 0;
229 physDev->ImageableArea.top = 0;
230 physDev->PageSize.cx = 0;
231 physDev->PageSize.cy = 0;
234 TRACE("ImageableArea = %d,%d - %d,%d: PageSize = %dx%d\n",
235 physDev->ImageableArea.left, physDev->ImageableArea.bottom,
236 physDev->ImageableArea.right, physDev->ImageableArea.top,
237 physDev->PageSize.cx, physDev->PageSize.cy);
239 /* these are in device units */
240 width = physDev->ImageableArea.right - physDev->ImageableArea.left;
241 height = physDev->ImageableArea.top - physDev->ImageableArea.bottom;
243 if(physDev->Devmode->dmPublic.u1.s1.dmOrientation == DMORIENT_PORTRAIT) {
244 physDev->horzRes = width;
245 physDev->vertRes = height;
247 physDev->horzRes = height;
248 physDev->vertRes = width;
251 /* these are in mm */
252 physDev->horzSize = (physDev->horzRes * 25.4) / physDev->logPixelsX;
253 physDev->vertSize = (physDev->vertRes * 25.4) / physDev->logPixelsY;
255 TRACE("devcaps: horzSize = %dmm, vertSize = %dmm, "
256 "horzRes = %d, vertRes = %d\n",
257 physDev->horzSize, physDev->vertSize,
258 physDev->horzRes, physDev->vertRes);
262 /***********************************************************
265 * Creates an ascii copy of supplied devmode on the process heap
267 * Copied from dlls/winspool/info.c until full unicodification
269 static LPDEVMODEA DEVMODEdupWtoA( const DEVMODEW *dmW )
274 /* there is no pointer dereference here, if your code checking tool complains it's broken */
275 ptrdiff_t off_formname = (const char *)dmW->dmFormName - (const char *)dmW;
277 if(!dmW) return NULL;
278 Formname = (dmW->dmSize > off_formname);
279 size = dmW->dmSize - CCHDEVICENAME - (Formname ? CCHFORMNAME : 0);
280 dmA = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size + dmW->dmDriverExtra );
281 WideCharToMultiByte(CP_ACP, 0, dmW->dmDeviceName, -1, (LPSTR)dmA->dmDeviceName,
282 CCHDEVICENAME, NULL, NULL);
284 memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
285 dmW->dmSize - CCHDEVICENAME * sizeof(WCHAR));
287 memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
288 off_formname - CCHDEVICENAME * sizeof(WCHAR));
289 WideCharToMultiByte(CP_ACP, 0, dmW->dmFormName, -1, (LPSTR)dmA->dmFormName,
290 CCHFORMNAME, NULL, NULL);
291 memcpy(&dmA->dmLogPixels, &dmW->dmLogPixels, dmW->dmSize -
292 (off_formname + CCHFORMNAME * sizeof(WCHAR)));
295 memcpy((char *)dmA + dmA->dmSize, (const char *)dmW + dmW->dmSize,
301 static PSDRV_PDEVICE *create_psdrv_physdev( PRINTERINFO *pi )
303 PSDRV_PDEVICE *physDev;
305 physDev = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physDev) );
306 if (!physDev) return NULL;
308 physDev->Devmode = HeapAlloc( GetProcessHeap(), 0, sizeof(PSDRV_DEVMODEA) );
309 if (!physDev->Devmode)
311 HeapFree( GetProcessHeap(), 0, physDev );
315 *physDev->Devmode = *pi->Devmode;
317 physDev->logPixelsX = pi->ppd->DefaultResolution;
318 physDev->logPixelsY = pi->ppd->DefaultResolution;
322 /**********************************************************************
325 static BOOL PSDRV_CreateDC( PHYSDEV *pdev, LPCWSTR driver, LPCWSTR device,
326 LPCWSTR output, const DEVMODEW* initData )
328 PSDRV_PDEVICE *physDev;
331 TRACE("(%s %s %s %p)\n", debugstr_w(driver), debugstr_w(device),
332 debugstr_w(output), initData);
334 if (!device) return FALSE;
335 pi = PSDRV_FindPrinterInfo( device );
336 if(!pi) return FALSE;
339 RASTERIZER_STATUS status;
340 if(!GetRasterizerCaps(&status, sizeof(status)) ||
341 !(status.wFlags & TT_AVAILABLE) ||
342 !(status.wFlags & TT_ENABLED)) {
343 MESSAGE("Disabling printer %s since it has no builtin fonts and there are no TrueType fonts available.\n",
349 if (!(physDev = create_psdrv_physdev( pi ))) return FALSE;
351 if (output && *output) physDev->job.output = strdupW( output );
354 DEVMODEA *devmodeA = DEVMODEdupWtoA( initData );
355 PSDRV_MergeDevmodes(physDev->Devmode, (PSDRV_DEVMODEA *)devmodeA, pi);
356 HeapFree( GetProcessHeap(), 0, devmodeA );
359 PSDRV_UpdateDevCaps(physDev);
360 SelectObject( (*pdev)->hdc, PSDRV_DefaultFont );
361 push_dc_driver( pdev, &physDev->dev, &psdrv_funcs );
366 /**********************************************************************
367 * PSDRV_CreateCompatibleDC
369 static BOOL PSDRV_CreateCompatibleDC( PHYSDEV orig, PHYSDEV *pdev )
371 HDC hdc = (*pdev)->hdc;
372 PSDRV_PDEVICE *physDev, *orig_dev = get_psdrv_dev( orig );
373 PRINTERINFO *pi = PSDRV_FindPrinterInfo( orig_dev->pi->friendly_name );
375 if (!pi) return FALSE;
376 if (!(physDev = create_psdrv_physdev( pi ))) return FALSE;
377 PSDRV_MergeDevmodes( physDev->Devmode, orig_dev->Devmode, pi );
378 PSDRV_UpdateDevCaps(physDev);
379 SelectObject( hdc, PSDRV_DefaultFont );
380 push_dc_driver( pdev, &physDev->dev, &psdrv_funcs );
386 /**********************************************************************
389 static BOOL PSDRV_DeleteDC( PHYSDEV dev )
391 PSDRV_PDEVICE *physDev = get_psdrv_dev( dev );
395 HeapFree( GetProcessHeap(), 0, physDev->Devmode );
396 HeapFree( GetProcessHeap(), 0, physDev->job.output );
397 HeapFree( GetProcessHeap(), 0, physDev );
403 /**********************************************************************
406 static HDC PSDRV_ResetDC( PHYSDEV dev, const DEVMODEW *lpInitData )
408 PSDRV_PDEVICE *physDev = get_psdrv_dev( dev );
411 DEVMODEA *devmodeA = DEVMODEdupWtoA( lpInitData );
412 PSDRV_MergeDevmodes(physDev->Devmode, (PSDRV_DEVMODEA *)devmodeA, physDev->pi);
413 HeapFree( GetProcessHeap(), 0, devmodeA );
414 PSDRV_UpdateDevCaps(physDev);
419 /***********************************************************************
420 * GetDeviceCaps (WINEPS.@)
422 static INT PSDRV_GetDeviceCaps( PHYSDEV dev, INT cap )
424 PSDRV_PDEVICE *physDev = get_psdrv_dev( dev );
431 return DT_RASPRINTER;
433 return MulDiv(physDev->horzSize, 100,
434 physDev->Devmode->dmPublic.u1.s1.dmScale);
436 return MulDiv(physDev->vertSize, 100,
437 physDev->Devmode->dmPublic.u1.s1.dmScale);
440 return physDev->horzRes;
443 return physDev->vertRes;
445 return (physDev->pi->ppd->ColorDevice != CD_False) ? 32 : 1;
459 return sizeof(PSDRV_PDEVICE);
461 return (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE |
462 CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT);
464 return (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
465 LC_STYLED | LC_WIDESTYLED | LC_INTERIORS);
467 return (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE |
468 PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS);
470 return TC_CR_ANY | TC_VA_ABLE; /* psdrv 0x59f7 */
474 return (RC_BITBLT | RC_BITMAP64 | RC_GDI20_OUTPUT | RC_DIBTODEV |
475 RC_STRETCHBLT | RC_STRETCHDIB); /* psdrv 0x6e99 */
476 /* Are aspect[XY] and logPixels[XY] correct? */
477 /* Need to handle different res in x and y => fix ppd */
480 return physDev->pi->ppd->DefaultResolution;
482 return (int)hypot( (double)physDev->pi->ppd->DefaultResolution,
483 (double)physDev->pi->ppd->DefaultResolution );
485 return MulDiv(physDev->logPixelsX,
486 physDev->Devmode->dmPublic.u1.s1.dmScale, 100);
488 return MulDiv(physDev->logPixelsY,
489 physDev->Devmode->dmPublic.u1.s1.dmScale, 100);
497 return (physDev->Devmode->dmPublic.u1.s1.dmOrientation == DMORIENT_LANDSCAPE) ?
498 physDev->PageSize.cy : physDev->PageSize.cx;
500 return (physDev->Devmode->dmPublic.u1.s1.dmOrientation == DMORIENT_LANDSCAPE) ?
501 physDev->PageSize.cx : physDev->PageSize.cy;
502 case PHYSICALOFFSETX:
503 if(physDev->Devmode->dmPublic.u1.s1.dmOrientation == DMORIENT_LANDSCAPE) {
504 if(physDev->pi->ppd->LandscapeOrientation == -90)
505 return physDev->PageSize.cy - physDev->ImageableArea.top;
507 return physDev->ImageableArea.bottom;
509 return physDev->ImageableArea.left;
511 case PHYSICALOFFSETY:
512 if(physDev->Devmode->dmPublic.u1.s1.dmOrientation == DMORIENT_LANDSCAPE) {
513 if(physDev->pi->ppd->LandscapeOrientation == -90)
514 return physDev->PageSize.cx - physDev->ImageableArea.right;
516 return physDev->ImageableArea.left;
518 return physDev->PageSize.cy - physDev->ImageableArea.top;
528 FIXME("(%p): unsupported capability %d, will return 0\n", dev->hdc, cap );
533 static PRINTER_ENUM_VALUESA *load_font_sub_table( HANDLE printer, DWORD *num_entries )
535 DWORD res, needed, num;
536 PRINTER_ENUM_VALUESA *table = NULL;
537 static const char fontsubkey[] = "PrinterDriverData\\FontSubTable";
541 res = EnumPrinterDataExA( printer, fontsubkey, NULL, 0, &needed, &num );
542 if (res != ERROR_MORE_DATA) return NULL;
544 table = HeapAlloc( PSDRV_Heap, 0, needed );
545 if (!table) return NULL;
547 res = EnumPrinterDataExA( printer, fontsubkey, (LPBYTE)table, needed, &needed, &num );
548 if (res != ERROR_SUCCESS)
550 HeapFree( PSDRV_Heap, 0, table );
558 static struct list printer_list = LIST_INIT( printer_list );
560 /**********************************************************************
561 * PSDRV_FindPrinterInfo
563 PRINTERINFO *PSDRV_FindPrinterInfo(LPCWSTR name)
565 DWORD type = REG_BINARY, needed, res, dwPaperSize;
570 const char *ppd = NULL;
572 char *ppdFileName = NULL, *nameA = NULL;
574 BOOL using_default_devmode = FALSE;
577 TRACE("'%s'\n", debugstr_w(name));
579 LIST_FOR_EACH_ENTRY( pi, &printer_list, PRINTERINFO, entry )
581 if (!strcmpW( pi->friendly_name, name ))
585 pi = HeapAlloc( PSDRV_Heap, HEAP_ZERO_MEMORY, sizeof(*pi) );
586 if (pi == NULL) return NULL;
588 if (!(pi->friendly_name = HeapAlloc( PSDRV_Heap, 0, (strlenW(name)+1)*sizeof(WCHAR) ))) goto fail;
589 strcpyW( pi->friendly_name, name );
591 if (OpenPrinterW( pi->friendly_name, &hPrinter, NULL ) == 0) {
592 ERR ("OpenPrinter failed with code %i\n", GetLastError ());
596 len = WideCharToMultiByte( CP_ACP, 0, name, -1, NULL, 0, NULL, NULL );
597 nameA = HeapAlloc( GetProcessHeap(), 0, len );
598 WideCharToMultiByte( CP_ACP, 0, name, -1, nameA, len, NULL, NULL );
601 res = GetPrinterDataExA(hPrinter, NULL, default_devmodeA, &type, NULL, 0, &needed);
603 if (needed < sizeof(DefaultDevmode)) {
604 pi->Devmode = HeapAlloc( PSDRV_Heap, 0, sizeof(DefaultDevmode) );
605 if (pi->Devmode == NULL)
608 *pi->Devmode = DefaultDevmode;
609 lstrcpynA((LPSTR)pi->Devmode->dmPublic.dmDeviceName, nameA, CCHDEVICENAME);
610 using_default_devmode = TRUE;
613 pi->Devmode = HeapAlloc( PSDRV_Heap, 0, needed );
614 if (pi->Devmode == NULL)
617 GetPrinterDataExA(hPrinter, NULL, default_devmodeA, &type, (LPBYTE)pi->Devmode, needed, &needed);
622 #ifdef SONAME_LIBCUPS
623 if (cupshandle != (void*)-1) {
624 typeof(cupsGetPPD) * pcupsGetPPD = NULL;
626 pcupsGetPPD = wine_dlsym(cupshandle, "cupsGetPPD", NULL, 0);
628 ppd = pcupsGetPPD( nameA );
631 needed=strlen(ppd)+1;
632 ppdFileName=HeapAlloc(PSDRV_Heap, 0, needed);
633 memcpy(ppdFileName, ppd, needed);
636 /* we should unlink() that file later */
638 res = ERROR_FILE_NOT_FOUND;
639 WARN("Did not find ppd for %s\n", debugstr_w(name));
645 res = GetPrinterDataExA(hPrinter, "PrinterDriverData", "PPD File", NULL, NULL, 0, &needed);
646 if ((res==ERROR_SUCCESS) || (res==ERROR_MORE_DATA)) {
647 ppdFileName=HeapAlloc(PSDRV_Heap, 0, needed);
648 res = GetPrinterDataExA(hPrinter, "PrinterDriverData", "PPD File", &ppdType,
649 (LPBYTE)ppdFileName, needed, &needed);
652 /* Look for a ppd file for this printer in the config file.
653 * First look under that printer's name, and then under 'generic'
655 /* @@ Wine registry key: HKCU\Software\Wine\Printing\PPD Files */
656 if((res != ERROR_SUCCESS) && !RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Printing\\PPD Files", &hkey))
658 const char* value_name;
660 if (RegQueryValueExA(hkey, nameA, 0, NULL, NULL, &needed) == ERROR_SUCCESS) {
662 } else if (RegQueryValueExA(hkey, "generic", 0, NULL, NULL, &needed) == ERROR_SUCCESS) {
663 value_name="generic";
668 HeapFree(PSDRV_Heap, 0, ppdFileName);
669 ppdFileName=HeapAlloc(PSDRV_Heap, 0, needed);
670 RegQueryValueExA(hkey, value_name, 0, &ppdType, (LPBYTE)ppdFileName, &needed);
677 const char *data_dir, *filename;
679 if ((data_dir = wine_get_data_dir())) filename = "/generic.ppd";
680 else if ((data_dir = wine_get_build_dir())) filename = "/dlls/wineps.drv/generic.ppd";
683 res = ERROR_FILE_NOT_FOUND;
684 ERR ("Error %i getting PPD file name for printer '%s'\n", res, debugstr_w(name));
687 ppdFileName = HeapAlloc( PSDRV_Heap, 0, strlen(data_dir) + strlen(filename) + 1 );
688 strcpy( ppdFileName, data_dir );
689 strcat( ppdFileName, filename );
692 if (ppdType==REG_EXPAND_SZ) {
695 /* Expand environment variable references */
696 needed=ExpandEnvironmentStringsA(ppdFileName,NULL,0);
697 tmp=HeapAlloc(PSDRV_Heap, 0, needed);
698 ExpandEnvironmentStringsA(ppdFileName,tmp,needed);
699 HeapFree(PSDRV_Heap, 0, ppdFileName);
704 pi->ppd = PSDRV_ParsePPD(ppdFileName);
706 MESSAGE("Couldn't find PPD file '%s', expect a crash now!\n",
711 /* Some gimp-print ppd files don't contain a DefaultResolution line
712 set it to 300 if it's not specified */
713 if(pi->ppd->DefaultResolution == 0)
714 pi->ppd->DefaultResolution = 300;
716 if(using_default_devmode) {
719 if(GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IPAPERSIZE | LOCALE_RETURN_NUMBER,
720 (LPWSTR)&papersize, sizeof(papersize)/sizeof(WCHAR))) {
722 memset(&dm, 0, sizeof(dm));
723 dm.dmPublic.dmFields = DM_PAPERSIZE;
724 dm.dmPublic.u1.s1.dmPaperSize = papersize;
725 PSDRV_MergeDevmodes(pi->Devmode, &dm, pi);
728 SetPrinterDataExA(hPrinter, NULL, default_devmodeA, REG_BINARY,
729 (LPBYTE)pi->Devmode, sizeof(DefaultDevmode));
732 if(pi->ppd->DefaultPageSize) { /* We'll let the ppd override the devmode */
734 memset(&dm, 0, sizeof(dm));
735 dm.dmPublic.dmFields = DM_PAPERSIZE;
736 dm.dmPublic.u1.s1.dmPaperSize = pi->ppd->DefaultPageSize->WinPage;
737 PSDRV_MergeDevmodes(pi->Devmode, &dm, pi);
741 * This is a hack. The default paper size should be read in as part of
742 * the Devmode structure, but Wine doesn't currently provide a convenient
743 * way to configure printers.
745 res = GetPrinterDataExA(hPrinter, "PrinterDriverData", "Paper Size", NULL,
746 (LPBYTE)&dwPaperSize, sizeof(DWORD), &needed);
747 if (res == ERROR_SUCCESS)
748 pi->Devmode->dmPublic.u1.s1.dmPaperSize = (SHORT) dwPaperSize;
749 else if (res == ERROR_FILE_NOT_FOUND)
750 TRACE ("No 'Paper Size' for printer '%s'\n", debugstr_w(name));
752 ERR ("GetPrinterDataA returned %i\n", res);
756 /* Duplex is indicated by the setting of the DM_DUPLEX bit in dmFields.
757 WinDuplex == 0 is a special case which means that the ppd has a
758 *DefaultDuplex: NotCapable entry. In this case we'll try not to confuse
759 apps and set dmDuplex to DMDUP_SIMPLEX but leave the DM_DUPLEX clear.
760 PSDRV_WriteHeader understands this and copes. */
761 pi->Devmode->dmPublic.dmFields &= ~DM_DUPLEX;
762 if(pi->ppd->DefaultDuplex) {
763 pi->Devmode->dmPublic.dmDuplex = pi->ppd->DefaultDuplex->WinDuplex;
764 if(pi->Devmode->dmPublic.dmDuplex != 0)
765 pi->Devmode->dmPublic.dmFields |= DM_DUPLEX;
767 pi->Devmode->dmPublic.dmDuplex = DMDUP_SIMPLEX;
770 pi->FontSubTable = load_font_sub_table( hPrinter, &pi->FontSubTableSize );
772 ClosePrinter( hPrinter );
776 for(font = pi->ppd->InstalledFonts; font; font = font->next) {
777 afm = PSDRV_FindAFMinList(PSDRV_AFMFontList, font->Name);
779 TRACE( "Couldn't find AFM file for installed printer font '%s' - "
780 "ignoring\n", font->Name);
784 if (PSDRV_AddAFMtoList(&pi->Fonts, afm, &added) == FALSE) {
785 PSDRV_FreeAFMList(pi->Fonts);
791 HeapFree( GetProcessHeap(), 0, nameA );
792 if (ppd) unlink(ppd);
793 list_add_head( &printer_list, &pi->entry );
797 ClosePrinter(hPrinter);
799 HeapFree(PSDRV_Heap, 0, ppdFileName);
800 HeapFree(PSDRV_Heap, 0, pi->FontSubTable);
801 HeapFree(PSDRV_Heap, 0, pi->friendly_name);
802 HeapFree(PSDRV_Heap, 0, pi->Devmode);
804 HeapFree(PSDRV_Heap, 0, pi);
805 HeapFree( GetProcessHeap(), 0, nameA );
806 if (ppd) unlink(ppd);
811 static const struct gdi_dc_funcs psdrv_funcs =
813 NULL, /* pAbortDoc */
814 NULL, /* pAbortPath */
815 NULL, /* pAlphaBlend */
816 NULL, /* pAngleArc */
817 PSDRV_Arc, /* pArc */
819 NULL, /* pBeginPath */
820 NULL, /* pBlendImage */
821 NULL, /* pChoosePixelFormat */
822 PSDRV_Chord, /* pChord */
823 NULL, /* pCloseFigure */
824 NULL, /* pCopyBitmap */
825 NULL, /* pCreateBitmap */
826 PSDRV_CreateCompatibleDC, /* pCreateCompatibleDC */
827 PSDRV_CreateDC, /* pCreateDC */
828 NULL, /* pDeleteBitmap */
829 PSDRV_DeleteDC, /* pDeleteDC */
830 NULL, /* pDeleteObject */
831 NULL, /* pDescribePixelFormat */
832 PSDRV_DeviceCapabilities, /* pDeviceCapabilities */
833 PSDRV_Ellipse, /* pEllipse */
834 PSDRV_EndDoc, /* pEndDoc */
835 PSDRV_EndPage, /* pEndPage */
837 PSDRV_EnumFonts, /* pEnumFonts */
838 NULL, /* pEnumICMProfiles */
839 NULL, /* pExcludeClipRect */
840 PSDRV_ExtDeviceMode, /* pExtDeviceMode */
841 PSDRV_ExtEscape, /* pExtEscape */
842 NULL, /* pExtFloodFill */
843 NULL, /* pExtSelectClipRgn */
844 PSDRV_ExtTextOut, /* pExtTextOut */
845 PSDRV_FillPath, /* pFillPath */
847 NULL, /* pFlattenPath */
848 NULL, /* pFontIsLinked */
849 NULL, /* pFrameRgn */
850 NULL, /* pGdiComment */
851 NULL, /* pGdiRealizationInfo */
852 NULL, /* pGetCharABCWidths */
853 NULL, /* pGetCharABCWidthsI */
854 PSDRV_GetCharWidth, /* pGetCharWidth */
855 PSDRV_GetDeviceCaps, /* pGetDeviceCaps */
856 NULL, /* pGetDeviceGammaRamp */
857 NULL, /* pGetFontData */
858 NULL, /* pGetFontUnicodeRanges */
859 NULL, /* pGetGlyphIndices */
860 NULL, /* pGetGlyphOutline */
861 NULL, /* pGetICMProfile */
862 NULL, /* pGetImage */
863 NULL, /* pGetKerningPairs */
864 NULL, /* pGetNearestColor */
865 NULL, /* pGetOutlineTextMetrics */
866 NULL, /* pGetPixel */
867 NULL, /* pGetPixelFormat */
868 NULL, /* pGetSystemPaletteEntries */
869 NULL, /* pGetTextCharsetInfo */
870 PSDRV_GetTextExtentExPoint, /* pGetTextExtentExPoint */
871 NULL, /* pGetTextExtentExPointI */
872 NULL, /* pGetTextFace */
873 PSDRV_GetTextMetrics, /* pGetTextMetrics */
874 NULL, /* pGradientFill */
875 NULL, /* pIntersectClipRect */
876 NULL, /* pInvertRgn */
877 PSDRV_LineTo, /* pLineTo */
878 NULL, /* pModifyWorldTransform */
880 NULL, /* pOffsetClipRgn */
881 NULL, /* pOffsetViewportOrg */
882 NULL, /* pOffsetWindowOrg */
883 PSDRV_PaintRgn, /* pPaintRgn */
884 PSDRV_PatBlt, /* pPatBlt */
885 PSDRV_Pie, /* pPie */
886 PSDRV_PolyBezier, /* pPolyBezier */
887 PSDRV_PolyBezierTo, /* pPolyBezierTo */
888 NULL, /* pPolyDraw */
889 PSDRV_PolyPolygon, /* pPolyPolygon */
890 PSDRV_PolyPolyline, /* pPolyPolyline */
892 NULL, /* pPolyline */
893 NULL, /* pPolylineTo */
894 PSDRV_PutImage, /* pPutImage */
895 NULL, /* pRealizeDefaultPalette */
896 NULL, /* pRealizePalette */
897 PSDRV_Rectangle, /* pRectangle */
898 PSDRV_ResetDC, /* pResetDC */
899 NULL, /* pRestoreDC */
900 PSDRV_RoundRect, /* pRoundRect */
902 NULL, /* pScaleViewportExt */
903 NULL, /* pScaleWindowExt */
904 NULL, /* pSelectBitmap */
905 PSDRV_SelectBrush, /* pSelectBrush */
906 NULL, /* pSelectClipPath */
907 PSDRV_SelectFont, /* pSelectFont */
908 NULL, /* pSelectPalette */
909 PSDRV_SelectPen, /* pSelectPen */
910 NULL, /* pSetArcDirection */
911 PSDRV_SetBkColor, /* pSetBkColor */
912 NULL, /* pSetBkMode */
913 PSDRV_SetDCBrushColor, /* pSetDCBrushColor */
914 PSDRV_SetDCPenColor, /* pSetDCPenColor */
915 NULL, /* pSetDIBitsToDevice */
916 NULL, /* pSetDeviceClipping */
917 NULL, /* pSetDeviceGammaRamp */
918 NULL, /* pSetLayout */
919 NULL, /* pSetMapMode */
920 NULL, /* pSetMapperFlags */
921 PSDRV_SetPixel, /* pSetPixel */
922 NULL, /* pSetPixelFormat */
923 NULL, /* pSetPolyFillMode */
925 NULL, /* pSetRelAbs */
926 NULL, /* pSetStretchBltMode */
927 NULL, /* pSetTextAlign */
928 NULL, /* pSetTextCharacterExtra */
929 PSDRV_SetTextColor, /* pSetTextColor */
930 NULL, /* pSetTextJustification */
931 NULL, /* pSetViewportExt */
932 NULL, /* pSetViewportOrg */
933 NULL, /* pSetWindowExt */
934 NULL, /* pSetWindowOrg */
935 NULL, /* pSetWorldTransform */
936 PSDRV_StartDoc, /* pStartDoc */
937 PSDRV_StartPage, /* pStartPage */
938 NULL, /* pStretchBlt */
939 NULL, /* pStretchDIBits */
940 PSDRV_StrokeAndFillPath, /* pStrokeAndFillPath */
941 PSDRV_StrokePath, /* pStrokePath */
942 NULL, /* pSwapBuffers */
943 NULL, /* pUnrealizePalette */
944 NULL, /* pWidenPath */
945 /* OpenGL not supported */
949 /******************************************************************************
950 * PSDRV_get_gdi_driver
952 const struct gdi_dc_funcs * CDECL PSDRV_get_gdi_driver( unsigned int version )
954 if (version != WINE_GDI_DRIVER_VERSION)
956 ERR( "version mismatch, gdi32 wants %u but wineps has %u\n", version, WINE_GDI_DRIVER_VERSION );