xmllite/writer: Implement WriteNodeShallow().
[wine.git] / dlls / wineps.drv / init.c
blob0d4467b69641d7b9766330faab8d50b7254c25a3
1 /*
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
22 #include <stdarg.h>
23 #include <string.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winerror.h"
28 #include "winreg.h"
29 #include "winnls.h"
30 #include "winuser.h"
31 #include "psdrv.h"
32 #include "winspool.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
37 static const PSDRV_DEVMODE DefaultDevmode =
39 { /* dmPublic */
40 /* dmDeviceName */ L"Wine PostScript Driver",
41 /* dmSpecVersion */ 0x30a,
42 /* dmDriverVersion */ 0x001,
43 /* dmSize */ sizeof(DEVMODEW),
44 /* dmDriverExtra */ sizeof(PSDRV_DEVMODE)-sizeof(DEVMODEW),
45 /* dmFields */ DM_ORIENTATION | DM_PAPERSIZE | DM_PAPERLENGTH | DM_PAPERWIDTH |
46 DM_SCALE | DM_COPIES | DM_DEFAULTSOURCE | DM_PRINTQUALITY |
47 DM_COLOR | DM_DUPLEX | DM_YRESOLUTION | DM_TTOPTION |
48 DM_COLLATE | DM_FORMNAME,
49 { /* u1 */
50 { /* s1 */
51 /* dmOrientation */ DMORIENT_PORTRAIT,
52 /* dmPaperSize */ DMPAPER_LETTER,
53 /* dmPaperLength */ 2794,
54 /* dmPaperWidth */ 2159,
55 /* dmScale */ 100,
56 /* dmCopies */ 1,
57 /* dmDefaultSource */ DMBIN_AUTO,
58 /* dmPrintQuality */ 300
61 /* dmColor */ DMCOLOR_COLOR,
62 /* dmDuplex */ DMDUP_SIMPLEX,
63 /* dmYResolution */ 300,
64 /* dmTTOption */ DMTT_SUBDEV,
65 /* dmCollate */ DMCOLLATE_FALSE,
66 /* dmFormName */ L"Letter",
67 /* dmLogPixels */ 0,
68 /* dmBitsPerPel */ 0,
69 /* dmPelsWidth */ 0,
70 /* dmPelsHeight */ 0,
71 { /* u2 */
72 /* dmDisplayFlags */ 0
74 /* dmDisplayFrequency */ 0,
75 /* dmICMMethod */ 0,
76 /* dmICMIntent */ 0,
77 /* dmMediaType */ 0,
78 /* dmDitherType */ 0,
79 /* dmReserved1 */ 0,
80 /* dmReserved2 */ 0,
81 /* dmPanningWidth */ 0,
82 /* dmPanningHeight */ 0
84 { /* dmDocPrivate */
85 /* dummy */ 0
87 { /* dmDrvPrivate */
88 /* numInstalledOptions */ 0
92 HINSTANCE PSDRV_hInstance = 0;
93 HANDLE PSDRV_Heap = 0;
95 static HFONT PSDRV_DefaultFont = 0;
96 static const LOGFONTA DefaultLogFont = {
97 100, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, 0, 0,
98 DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, ""
101 static const struct gdi_dc_funcs psdrv_funcs;
103 /*********************************************************************
104 * DllMain
106 * Initializes font metrics and registers driver. wineps dll entry point.
109 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
111 TRACE("(%p, %ld, %p)\n", hinst, reason, reserved);
113 switch(reason) {
115 case DLL_PROCESS_ATTACH:
116 PSDRV_hInstance = hinst;
117 DisableThreadLibraryCalls(hinst);
119 PSDRV_Heap = HeapCreate(0, 0x10000, 0);
120 if (PSDRV_Heap == NULL)
121 return FALSE;
123 if (PSDRV_GetFontMetrics() == FALSE) {
124 HeapDestroy(PSDRV_Heap);
125 return FALSE;
128 PSDRV_DefaultFont = CreateFontIndirectA(&DefaultLogFont);
129 if (PSDRV_DefaultFont == NULL) {
130 HeapDestroy(PSDRV_Heap);
131 return FALSE;
133 break;
135 case DLL_PROCESS_DETACH:
136 if (reserved) break;
137 DeleteObject( PSDRV_DefaultFont );
138 HeapDestroy( PSDRV_Heap );
139 break;
142 return TRUE;
145 static void dump_fields(DWORD fields)
147 int add_space = 0;
149 #define CHECK_FIELD(flag) \
150 do \
152 if (fields & flag) \
154 if (add_space++) TRACE(" "); \
155 TRACE(#flag); \
156 fields &= ~flag; \
159 while (0)
161 CHECK_FIELD(DM_ORIENTATION);
162 CHECK_FIELD(DM_PAPERSIZE);
163 CHECK_FIELD(DM_PAPERLENGTH);
164 CHECK_FIELD(DM_PAPERWIDTH);
165 CHECK_FIELD(DM_SCALE);
166 CHECK_FIELD(DM_POSITION);
167 CHECK_FIELD(DM_NUP);
168 CHECK_FIELD(DM_DISPLAYORIENTATION);
169 CHECK_FIELD(DM_COPIES);
170 CHECK_FIELD(DM_DEFAULTSOURCE);
171 CHECK_FIELD(DM_PRINTQUALITY);
172 CHECK_FIELD(DM_COLOR);
173 CHECK_FIELD(DM_DUPLEX);
174 CHECK_FIELD(DM_YRESOLUTION);
175 CHECK_FIELD(DM_TTOPTION);
176 CHECK_FIELD(DM_COLLATE);
177 CHECK_FIELD(DM_FORMNAME);
178 CHECK_FIELD(DM_LOGPIXELS);
179 CHECK_FIELD(DM_BITSPERPEL);
180 CHECK_FIELD(DM_PELSWIDTH);
181 CHECK_FIELD(DM_PELSHEIGHT);
182 CHECK_FIELD(DM_DISPLAYFLAGS);
183 CHECK_FIELD(DM_DISPLAYFREQUENCY);
184 CHECK_FIELD(DM_ICMMETHOD);
185 CHECK_FIELD(DM_ICMINTENT);
186 CHECK_FIELD(DM_MEDIATYPE);
187 CHECK_FIELD(DM_DITHERTYPE);
188 CHECK_FIELD(DM_PANNINGWIDTH);
189 CHECK_FIELD(DM_PANNINGHEIGHT);
190 if (fields) TRACE(" %#lx", fields);
191 TRACE("\n");
192 #undef CHECK_FIELD
195 /* Dump DEVMODE structure without a device specific part.
196 * Some applications and drivers fail to specify correct field
197 * flags (like DM_FORMNAME), so dump everything.
199 static void dump_devmode(const DEVMODEW *dm)
201 if (!TRACE_ON(psdrv)) return;
203 TRACE("dmDeviceName: %s\n", debugstr_w(dm->dmDeviceName));
204 TRACE("dmSpecVersion: 0x%04x\n", dm->dmSpecVersion);
205 TRACE("dmDriverVersion: 0x%04x\n", dm->dmDriverVersion);
206 TRACE("dmSize: 0x%04x\n", dm->dmSize);
207 TRACE("dmDriverExtra: 0x%04x\n", dm->dmDriverExtra);
208 TRACE("dmFields: 0x%04lx\n", dm->dmFields);
209 dump_fields(dm->dmFields);
210 TRACE("dmOrientation: %d\n", dm->dmOrientation);
211 TRACE("dmPaperSize: %d\n", dm->dmPaperSize);
212 TRACE("dmPaperLength: %d\n", dm->dmPaperLength);
213 TRACE("dmPaperWidth: %d\n", dm->dmPaperWidth);
214 TRACE("dmScale: %d\n", dm->dmScale);
215 TRACE("dmCopies: %d\n", dm->dmCopies);
216 TRACE("dmDefaultSource: %d\n", dm->dmDefaultSource);
217 TRACE("dmPrintQuality: %d\n", dm->dmPrintQuality);
218 TRACE("dmColor: %d\n", dm->dmColor);
219 TRACE("dmDuplex: %d\n", dm->dmDuplex);
220 TRACE("dmYResolution: %d\n", dm->dmYResolution);
221 TRACE("dmTTOption: %d\n", dm->dmTTOption);
222 TRACE("dmCollate: %d\n", dm->dmCollate);
223 TRACE("dmFormName: %s\n", debugstr_w(dm->dmFormName));
224 TRACE("dmLogPixels %u\n", dm->dmLogPixels);
225 TRACE("dmBitsPerPel %lu\n", dm->dmBitsPerPel);
226 TRACE("dmPelsWidth %lu\n", dm->dmPelsWidth);
227 TRACE("dmPelsHeight %lu\n", dm->dmPelsHeight);
230 static void PSDRV_UpdateDevCaps( PSDRV_PDEVICE *physDev )
232 PAGESIZE *page;
233 RESOLUTION *res;
234 INT width = 0, height = 0, resx = 0, resy = 0;
236 dump_devmode(&physDev->Devmode->dmPublic);
238 if (physDev->Devmode->dmPublic.dmFields & (DM_PRINTQUALITY | DM_YRESOLUTION | DM_LOGPIXELS))
240 if (physDev->Devmode->dmPublic.dmFields & DM_PRINTQUALITY)
241 resx = resy = physDev->Devmode->dmPublic.dmPrintQuality;
243 if (physDev->Devmode->dmPublic.dmFields & DM_YRESOLUTION)
244 resy = physDev->Devmode->dmPublic.dmYResolution;
246 if (physDev->Devmode->dmPublic.dmFields & DM_LOGPIXELS)
247 resx = resy = physDev->Devmode->dmPublic.dmLogPixels;
249 LIST_FOR_EACH_ENTRY(res, &physDev->pi->ppd->Resolutions, RESOLUTION, entry)
251 if (res->resx == resx && res->resy == resy)
253 physDev->logPixelsX = resx;
254 physDev->logPixelsY = resy;
255 break;
259 if (&res->entry == &physDev->pi->ppd->Resolutions)
261 WARN("Requested resolution %dx%d is not supported by device\n", resx, resy);
262 physDev->logPixelsX = physDev->pi->ppd->DefaultResolution;
263 physDev->logPixelsY = physDev->logPixelsX;
266 else
268 WARN("Using default device resolution %d\n", physDev->pi->ppd->DefaultResolution);
269 physDev->logPixelsX = physDev->pi->ppd->DefaultResolution;
270 physDev->logPixelsY = physDev->logPixelsX;
273 if(physDev->Devmode->dmPublic.dmFields & DM_PAPERSIZE) {
274 LIST_FOR_EACH_ENTRY(page, &physDev->pi->ppd->PageSizes, PAGESIZE, entry) {
275 if(page->WinPage == physDev->Devmode->dmPublic.dmPaperSize)
276 break;
279 if(&page->entry == &physDev->pi->ppd->PageSizes) {
280 FIXME("Can't find page\n");
281 SetRectEmpty(&physDev->ImageableArea);
282 physDev->PageSize.cx = 0;
283 physDev->PageSize.cy = 0;
284 } else if(page->ImageableArea) {
285 /* physDev sizes in device units; ppd sizes in 1/72" */
286 SetRect(&physDev->ImageableArea, page->ImageableArea->llx * physDev->logPixelsX / 72,
287 page->ImageableArea->ury * physDev->logPixelsY / 72,
288 page->ImageableArea->urx * physDev->logPixelsX / 72,
289 page->ImageableArea->lly * physDev->logPixelsY / 72);
290 physDev->PageSize.cx = page->PaperDimension->x *
291 physDev->logPixelsX / 72;
292 physDev->PageSize.cy = page->PaperDimension->y *
293 physDev->logPixelsY / 72;
294 } else {
295 physDev->ImageableArea.left = physDev->ImageableArea.bottom = 0;
296 physDev->ImageableArea.right = physDev->PageSize.cx =
297 page->PaperDimension->x * physDev->logPixelsX / 72;
298 physDev->ImageableArea.top = physDev->PageSize.cy =
299 page->PaperDimension->y * physDev->logPixelsY / 72;
301 } else if((physDev->Devmode->dmPublic.dmFields & DM_PAPERLENGTH) &&
302 (physDev->Devmode->dmPublic.dmFields & DM_PAPERWIDTH)) {
303 /* physDev sizes in device units; Devmode sizes in 1/10 mm */
304 physDev->ImageableArea.left = physDev->ImageableArea.bottom = 0;
305 physDev->ImageableArea.right = physDev->PageSize.cx =
306 physDev->Devmode->dmPublic.dmPaperWidth * physDev->logPixelsX / 254;
307 physDev->ImageableArea.top = physDev->PageSize.cy =
308 physDev->Devmode->dmPublic.dmPaperLength * physDev->logPixelsY / 254;
309 } else {
310 FIXME("Odd dmFields %lx\n", physDev->Devmode->dmPublic.dmFields);
311 SetRectEmpty(&physDev->ImageableArea);
312 physDev->PageSize.cx = 0;
313 physDev->PageSize.cy = 0;
316 TRACE("ImageableArea = %s: PageSize = %ldx%ld\n", wine_dbgstr_rect(&physDev->ImageableArea),
317 physDev->PageSize.cx, physDev->PageSize.cy);
319 /* these are in device units */
320 width = physDev->ImageableArea.right - physDev->ImageableArea.left;
321 height = physDev->ImageableArea.top - physDev->ImageableArea.bottom;
323 if(physDev->Devmode->dmPublic.dmOrientation == DMORIENT_PORTRAIT) {
324 physDev->horzRes = width;
325 physDev->vertRes = height;
326 } else {
327 physDev->horzRes = height;
328 physDev->vertRes = width;
331 /* these are in mm */
332 physDev->horzSize = (physDev->horzRes * 25.4) / physDev->logPixelsX;
333 physDev->vertSize = (physDev->vertRes * 25.4) / physDev->logPixelsY;
335 TRACE("devcaps: horzSize = %dmm, vertSize = %dmm, "
336 "horzRes = %d, vertRes = %d\n",
337 physDev->horzSize, physDev->vertSize,
338 physDev->horzRes, physDev->vertRes);
341 static PSDRV_PDEVICE *create_psdrv_physdev( PRINTERINFO *pi )
343 PSDRV_PDEVICE *physDev;
345 physDev = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physDev) );
346 if (!physDev) return NULL;
348 physDev->Devmode = HeapAlloc( GetProcessHeap(), 0, sizeof(PSDRV_DEVMODE) );
349 if (!physDev->Devmode)
351 HeapFree( GetProcessHeap(), 0, physDev );
352 return NULL;
355 *physDev->Devmode = *pi->Devmode;
356 physDev->pi = pi;
357 physDev->logPixelsX = pi->ppd->DefaultResolution;
358 physDev->logPixelsY = pi->ppd->DefaultResolution;
359 return physDev;
362 /**********************************************************************
363 * PSDRV_CreateDC
365 static BOOL CDECL PSDRV_CreateDC( PHYSDEV *pdev, LPCWSTR device, LPCWSTR output,
366 const DEVMODEW *initData )
368 PSDRV_PDEVICE *physDev;
369 PRINTERINFO *pi;
371 TRACE("(%s %s %p)\n", debugstr_w(device), debugstr_w(output), initData);
373 if (!device) return FALSE;
374 pi = PSDRV_FindPrinterInfo( device );
375 if(!pi) return FALSE;
377 if(!pi->Fonts) {
378 RASTERIZER_STATUS status;
379 if(!GetRasterizerCaps(&status, sizeof(status)) ||
380 !(status.wFlags & TT_AVAILABLE) ||
381 !(status.wFlags & TT_ENABLED)) {
382 MESSAGE("Disabling printer %s since it has no builtin fonts and there are no TrueType fonts available.\n",
383 debugstr_w(device));
384 return FALSE;
388 if (!(physDev = create_psdrv_physdev( pi ))) return FALSE;
390 if (output && *output) physDev->job.output = strdupW( output );
392 if(initData)
394 dump_devmode(initData);
395 PSDRV_MergeDevmodes(physDev->Devmode, (const PSDRV_DEVMODE *)initData, pi);
398 PSDRV_UpdateDevCaps(physDev);
399 SelectObject( (*pdev)->hdc, PSDRV_DefaultFont );
400 push_dc_driver( pdev, &physDev->dev, &psdrv_funcs );
401 return TRUE;
405 /**********************************************************************
406 * PSDRV_CreateCompatibleDC
408 static BOOL CDECL PSDRV_CreateCompatibleDC( PHYSDEV orig, PHYSDEV *pdev )
410 HDC hdc = (*pdev)->hdc;
411 PSDRV_PDEVICE *physDev, *orig_dev = get_psdrv_dev( orig );
412 PRINTERINFO *pi = PSDRV_FindPrinterInfo( orig_dev->pi->friendly_name );
414 if (!pi) return FALSE;
415 if (!(physDev = create_psdrv_physdev( pi ))) return FALSE;
416 PSDRV_MergeDevmodes( physDev->Devmode, orig_dev->Devmode, pi );
417 PSDRV_UpdateDevCaps(physDev);
418 SelectObject( hdc, PSDRV_DefaultFont );
419 push_dc_driver( pdev, &physDev->dev, &psdrv_funcs );
420 return TRUE;
425 /**********************************************************************
426 * PSDRV_DeleteDC
428 static BOOL CDECL PSDRV_DeleteDC( PHYSDEV dev )
430 PSDRV_PDEVICE *physDev = get_psdrv_dev( dev );
432 TRACE("\n");
434 HeapFree( GetProcessHeap(), 0, physDev->Devmode );
435 HeapFree( GetProcessHeap(), 0, physDev->job.output );
436 HeapFree( GetProcessHeap(), 0, physDev );
438 return TRUE;
442 /**********************************************************************
443 * ResetDC (WINEPS.@)
445 static BOOL CDECL PSDRV_ResetDC( PHYSDEV dev, const DEVMODEW *lpInitData )
447 PSDRV_PDEVICE *physDev = get_psdrv_dev( dev );
449 if (lpInitData)
451 PSDRV_MergeDevmodes(physDev->Devmode, (const PSDRV_DEVMODE *)lpInitData, physDev->pi);
452 PSDRV_UpdateDevCaps(physDev);
454 return TRUE;
457 /***********************************************************************
458 * GetDeviceCaps (WINEPS.@)
460 static INT CDECL PSDRV_GetDeviceCaps( PHYSDEV dev, INT cap )
462 PSDRV_PDEVICE *physDev = get_psdrv_dev( dev );
464 TRACE("%p,%d\n", dev->hdc, cap);
466 switch(cap)
468 case DRIVERVERSION:
469 return 0;
470 case TECHNOLOGY:
471 return DT_RASPRINTER;
472 case HORZSIZE:
473 return MulDiv(physDev->horzSize, 100, physDev->Devmode->dmPublic.dmScale);
474 case VERTSIZE:
475 return MulDiv(physDev->vertSize, 100, physDev->Devmode->dmPublic.dmScale);
476 case HORZRES:
477 return physDev->horzRes;
478 case VERTRES:
479 return physDev->vertRes;
480 case BITSPIXEL:
481 /* Although Windows returns 1 for monochrome printers, we want
482 CreateCompatibleBitmap to provide something other than 1 bpp */
483 return 32;
484 case NUMPENS:
485 return 10;
486 case NUMFONTS:
487 return 39;
488 case NUMCOLORS:
489 return -1;
490 case PDEVICESIZE:
491 return sizeof(PSDRV_PDEVICE);
492 case TEXTCAPS:
493 return TC_CR_ANY | TC_VA_ABLE; /* psdrv 0x59f7 */
494 case RASTERCAPS:
495 return (RC_BITBLT | RC_BITMAP64 | RC_GDI20_OUTPUT | RC_DIBTODEV |
496 RC_STRETCHBLT | RC_STRETCHDIB); /* psdrv 0x6e99 */
497 case ASPECTX:
498 return physDev->logPixelsX;
499 case ASPECTY:
500 return physDev->logPixelsY;
501 case LOGPIXELSX:
502 return MulDiv(physDev->logPixelsX, physDev->Devmode->dmPublic.dmScale, 100);
503 case LOGPIXELSY:
504 return MulDiv(physDev->logPixelsY, physDev->Devmode->dmPublic.dmScale, 100);
505 case NUMRESERVED:
506 return 0;
507 case COLORRES:
508 return 0;
509 case PHYSICALWIDTH:
510 return (physDev->Devmode->dmPublic.dmOrientation == DMORIENT_LANDSCAPE) ?
511 physDev->PageSize.cy : physDev->PageSize.cx;
512 case PHYSICALHEIGHT:
513 return (physDev->Devmode->dmPublic.dmOrientation == DMORIENT_LANDSCAPE) ?
514 physDev->PageSize.cx : physDev->PageSize.cy;
515 case PHYSICALOFFSETX:
516 if(physDev->Devmode->dmPublic.dmOrientation == DMORIENT_LANDSCAPE) {
517 if(physDev->pi->ppd->LandscapeOrientation == -90)
518 return physDev->PageSize.cy - physDev->ImageableArea.top;
519 else
520 return physDev->ImageableArea.bottom;
522 return physDev->ImageableArea.left;
524 case PHYSICALOFFSETY:
525 if(physDev->Devmode->dmPublic.dmOrientation == DMORIENT_LANDSCAPE) {
526 if(physDev->pi->ppd->LandscapeOrientation == -90)
527 return physDev->PageSize.cx - physDev->ImageableArea.right;
528 else
529 return physDev->ImageableArea.left;
531 return physDev->PageSize.cy - physDev->ImageableArea.top;
533 default:
534 dev = GET_NEXT_PHYSDEV( dev, pGetDeviceCaps );
535 return dev->funcs->pGetDeviceCaps( dev, cap );
539 static PRINTER_ENUM_VALUESA *load_font_sub_table( HANDLE printer, DWORD *num_entries )
541 DWORD res, needed, num;
542 PRINTER_ENUM_VALUESA *table = NULL;
543 static const char fontsubkey[] = "PrinterDriverData\\FontSubTable";
545 *num_entries = 0;
547 res = EnumPrinterDataExA( printer, fontsubkey, NULL, 0, &needed, &num );
548 if (res != ERROR_MORE_DATA) return NULL;
550 table = HeapAlloc( PSDRV_Heap, 0, needed );
551 if (!table) return NULL;
553 res = EnumPrinterDataExA( printer, fontsubkey, (LPBYTE)table, needed, &needed, &num );
554 if (res != ERROR_SUCCESS)
556 HeapFree( PSDRV_Heap, 0, table );
557 return NULL;
560 *num_entries = num;
561 return table;
564 static PSDRV_DEVMODE *get_printer_devmode( HANDLE printer )
566 DWORD needed, dm_size;
567 BOOL res;
568 PRINTER_INFO_9W *info;
569 PSDRV_DEVMODE *dm;
571 GetPrinterW( printer, 9, NULL, 0, &needed );
572 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return NULL;
574 info = HeapAlloc( PSDRV_Heap, 0, needed );
575 res = GetPrinterW( printer, 9, (BYTE *)info, needed, &needed );
576 if (!res || !info->pDevMode)
578 HeapFree( PSDRV_Heap, 0, info );
579 return NULL;
582 /* sanity check the sizes */
583 dm_size = info->pDevMode->dmSize + info->pDevMode->dmDriverExtra;
584 if ((char *)info->pDevMode - (char *)info + dm_size > needed)
586 HeapFree( PSDRV_Heap, 0, info );
587 return NULL;
590 dm = (PSDRV_DEVMODE*)info;
591 memmove( dm, info->pDevMode, dm_size );
592 return dm;
595 static PSDRV_DEVMODE *get_devmode( HANDLE printer, const WCHAR *name, BOOL *is_default )
597 PSDRV_DEVMODE *dm = get_printer_devmode( printer );
599 *is_default = FALSE;
601 if (dm && dm->dmPublic.dmSize + dm->dmPublic.dmDriverExtra >= sizeof(DefaultDevmode))
603 TRACE( "Retrieved devmode from winspool\n" );
604 return dm;
606 HeapFree( PSDRV_Heap, 0, dm );
608 TRACE( "Using default devmode\n" );
609 dm = HeapAlloc( PSDRV_Heap, 0, sizeof(DefaultDevmode) );
610 if (dm)
612 *dm = DefaultDevmode;
613 lstrcpynW( (WCHAR *)dm->dmPublic.dmDeviceName, name, CCHDEVICENAME );
614 *is_default = TRUE;
616 return dm;
619 static BOOL set_devmode( HANDLE printer, PSDRV_DEVMODE *dm )
621 PRINTER_INFO_9W info;
622 info.pDevMode = &dm->dmPublic;
624 return SetPrinterW( printer, 9, (BYTE *)&info, 0 );
627 static WCHAR *get_ppd_filename( HANDLE printer )
629 DWORD needed;
630 DRIVER_INFO_2W *info;
631 WCHAR *name;
633 GetPrinterDriverW( printer, NULL, 2, NULL, 0, &needed );
634 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return NULL;
635 info = HeapAlloc( GetProcessHeap(), 0, needed );
636 if (!info) return NULL;
637 GetPrinterDriverW( printer, NULL, 2, (BYTE*)info, needed, &needed );
638 name = (WCHAR *)info;
639 memmove( name, info->pDataFile, (lstrlenW( info->pDataFile ) + 1) * sizeof(WCHAR) );
640 return name;
643 static struct list printer_list = LIST_INIT( printer_list );
645 /**********************************************************************
646 * PSDRV_FindPrinterInfo
648 PRINTERINFO *PSDRV_FindPrinterInfo(LPCWSTR name)
650 PRINTERINFO *pi;
651 FONTNAME *font;
652 const AFM *afm;
653 HANDLE hPrinter = 0;
654 WCHAR *ppd_filename = NULL;
655 char *nameA = NULL;
656 BOOL using_default_devmode = FALSE;
657 int len;
659 TRACE("'%s'\n", debugstr_w(name));
661 LIST_FOR_EACH_ENTRY( pi, &printer_list, PRINTERINFO, entry )
663 if (!wcscmp( pi->friendly_name, name ))
664 return pi;
667 pi = HeapAlloc( PSDRV_Heap, HEAP_ZERO_MEMORY, sizeof(*pi) );
668 if (pi == NULL) return NULL;
670 if (!(pi->friendly_name = HeapAlloc( PSDRV_Heap, 0, (lstrlenW(name)+1)*sizeof(WCHAR) ))) goto fail;
671 lstrcpyW( pi->friendly_name, name );
673 if (OpenPrinterW( pi->friendly_name, &hPrinter, NULL ) == 0) {
674 ERR ("OpenPrinter failed with code %li\n", GetLastError ());
675 goto fail;
678 len = WideCharToMultiByte( CP_ACP, 0, name, -1, NULL, 0, NULL, NULL );
679 nameA = HeapAlloc( GetProcessHeap(), 0, len );
680 WideCharToMultiByte( CP_ACP, 0, name, -1, nameA, len, NULL, NULL );
682 pi->Devmode = get_devmode( hPrinter, name, &using_default_devmode );
683 if (!pi->Devmode) goto fail;
685 ppd_filename = get_ppd_filename( hPrinter );
686 if (!ppd_filename) goto fail;
688 pi->ppd = PSDRV_ParsePPD( ppd_filename, hPrinter );
689 if (!pi->ppd)
691 WARN( "Couldn't parse PPD file %s\n", debugstr_w(ppd_filename) );
692 goto fail;
695 if(using_default_devmode) {
696 DWORD papersize;
698 if(GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IPAPERSIZE | LOCALE_RETURN_NUMBER,
699 (LPWSTR)&papersize, sizeof(papersize)/sizeof(WCHAR))) {
700 PSDRV_DEVMODE dm;
701 memset(&dm, 0, sizeof(dm));
702 dm.dmPublic.dmFields = DM_PAPERSIZE;
703 dm.dmPublic.dmPaperSize = papersize;
704 PSDRV_MergeDevmodes(pi->Devmode, &dm, pi);
708 if(pi->ppd->DefaultPageSize) { /* We'll let the ppd override the devmode */
709 PSDRV_DEVMODE dm;
710 memset(&dm, 0, sizeof(dm));
711 dm.dmPublic.dmFields = DM_PAPERSIZE;
712 dm.dmPublic.dmPaperSize = pi->ppd->DefaultPageSize->WinPage;
713 PSDRV_MergeDevmodes(pi->Devmode, &dm, pi);
716 /* Duplex is indicated by the setting of the DM_DUPLEX bit in dmFields.
717 WinDuplex == 0 is a special case which means that the ppd has a
718 *DefaultDuplex: NotCapable entry. In this case we'll try not to confuse
719 apps and set dmDuplex to DMDUP_SIMPLEX but leave the DM_DUPLEX clear.
720 PSDRV_WriteHeader understands this and copes. */
721 pi->Devmode->dmPublic.dmFields &= ~DM_DUPLEX;
722 if(pi->ppd->DefaultDuplex) {
723 pi->Devmode->dmPublic.dmDuplex = pi->ppd->DefaultDuplex->WinDuplex;
724 if(pi->Devmode->dmPublic.dmDuplex != 0)
725 pi->Devmode->dmPublic.dmFields |= DM_DUPLEX;
726 else
727 pi->Devmode->dmPublic.dmDuplex = DMDUP_SIMPLEX;
730 set_devmode( hPrinter, pi->Devmode );
732 pi->FontSubTable = load_font_sub_table( hPrinter, &pi->FontSubTableSize );
734 LIST_FOR_EACH_ENTRY( font, &pi->ppd->InstalledFonts, FONTNAME, entry )
736 afm = PSDRV_FindAFMinList(PSDRV_AFMFontList, font->Name);
737 if(!afm) {
738 TRACE( "Couldn't find AFM file for installed printer font '%s' - "
739 "ignoring\n", font->Name);
741 else {
742 BOOL added;
743 if (PSDRV_AddAFMtoList(&pi->Fonts, afm, &added) == FALSE) {
744 PSDRV_FreeAFMList(pi->Fonts);
745 goto fail;
750 ClosePrinter( hPrinter );
751 HeapFree( GetProcessHeap(), 0, nameA );
752 HeapFree( GetProcessHeap(), 0, ppd_filename );
753 list_add_head( &printer_list, &pi->entry );
754 return pi;
756 fail:
757 if (hPrinter) ClosePrinter( hPrinter );
758 HeapFree(PSDRV_Heap, 0, pi->FontSubTable);
759 HeapFree(PSDRV_Heap, 0, pi->friendly_name);
760 HeapFree(PSDRV_Heap, 0, pi->Devmode);
761 HeapFree(PSDRV_Heap, 0, pi);
762 HeapFree( GetProcessHeap(), 0, nameA );
763 HeapFree( GetProcessHeap(), 0, ppd_filename );
764 return NULL;
768 static const struct gdi_dc_funcs psdrv_funcs =
770 NULL, /* pAbortDoc */
771 NULL, /* pAbortPath */
772 NULL, /* pAlphaBlend */
773 NULL, /* pAngleArc */
774 PSDRV_Arc, /* pArc */
775 NULL, /* pArcTo */
776 NULL, /* pBeginPath */
777 NULL, /* pBlendImage */
778 PSDRV_Chord, /* pChord */
779 NULL, /* pCloseFigure */
780 PSDRV_CreateCompatibleDC, /* pCreateCompatibleDC */
781 PSDRV_CreateDC, /* pCreateDC */
782 PSDRV_DeleteDC, /* pDeleteDC */
783 NULL, /* pDeleteObject */
784 PSDRV_Ellipse, /* pEllipse */
785 PSDRV_EndDoc, /* pEndDoc */
786 PSDRV_EndPage, /* pEndPage */
787 NULL, /* pEndPath */
788 PSDRV_EnumFonts, /* pEnumFonts */
789 PSDRV_ExtEscape, /* pExtEscape */
790 NULL, /* pExtFloodFill */
791 PSDRV_ExtTextOut, /* pExtTextOut */
792 PSDRV_FillPath, /* pFillPath */
793 NULL, /* pFillRgn */
794 NULL, /* pFontIsLinked */
795 NULL, /* pFrameRgn */
796 NULL, /* pGetBoundsRect */
797 NULL, /* pGetCharABCWidths */
798 NULL, /* pGetCharABCWidthsI */
799 PSDRV_GetCharWidth, /* pGetCharWidth */
800 NULL, /* pGetCharWidthInfo */
801 PSDRV_GetDeviceCaps, /* pGetDeviceCaps */
802 NULL, /* pGetDeviceGammaRamp */
803 NULL, /* pGetFontData */
804 NULL, /* pGetFontRealizationInfo */
805 NULL, /* pGetFontUnicodeRanges */
806 NULL, /* pGetGlyphIndices */
807 NULL, /* pGetGlyphOutline */
808 NULL, /* pGetICMProfile */
809 NULL, /* pGetImage */
810 NULL, /* pGetKerningPairs */
811 NULL, /* pGetNearestColor */
812 NULL, /* pGetOutlineTextMetrics */
813 NULL, /* pGetPixel */
814 NULL, /* pGetSystemPaletteEntries */
815 NULL, /* pGetTextCharsetInfo */
816 PSDRV_GetTextExtentExPoint, /* pGetTextExtentExPoint */
817 NULL, /* pGetTextExtentExPointI */
818 NULL, /* pGetTextFace */
819 PSDRV_GetTextMetrics, /* pGetTextMetrics */
820 NULL, /* pGradientFill */
821 NULL, /* pInvertRgn */
822 PSDRV_LineTo, /* pLineTo */
823 NULL, /* pMoveTo */
824 PSDRV_PaintRgn, /* pPaintRgn */
825 PSDRV_PatBlt, /* pPatBlt */
826 PSDRV_Pie, /* pPie */
827 PSDRV_PolyBezier, /* pPolyBezier */
828 PSDRV_PolyBezierTo, /* pPolyBezierTo */
829 NULL, /* pPolyDraw */
830 PSDRV_PolyPolygon, /* pPolyPolygon */
831 PSDRV_PolyPolyline, /* pPolyPolyline */
832 NULL, /* pPolylineTo */
833 PSDRV_PutImage, /* pPutImage */
834 NULL, /* pRealizeDefaultPalette */
835 NULL, /* pRealizePalette */
836 PSDRV_Rectangle, /* pRectangle */
837 PSDRV_ResetDC, /* pResetDC */
838 PSDRV_RoundRect, /* pRoundRect */
839 NULL, /* pSelectBitmap */
840 PSDRV_SelectBrush, /* pSelectBrush */
841 PSDRV_SelectFont, /* pSelectFont */
842 PSDRV_SelectPen, /* pSelectPen */
843 PSDRV_SetBkColor, /* pSetBkColor */
844 NULL, /* pSetBoundsRect */
845 PSDRV_SetDCBrushColor, /* pSetDCBrushColor */
846 PSDRV_SetDCPenColor, /* pSetDCPenColor */
847 NULL, /* pSetDIBitsToDevice */
848 NULL, /* pSetDeviceClipping */
849 NULL, /* pSetDeviceGammaRamp */
850 PSDRV_SetPixel, /* pSetPixel */
851 PSDRV_SetTextColor, /* pSetTextColor */
852 PSDRV_StartDoc, /* pStartDoc */
853 PSDRV_StartPage, /* pStartPage */
854 NULL, /* pStretchBlt */
855 NULL, /* pStretchDIBits */
856 PSDRV_StrokeAndFillPath, /* pStrokeAndFillPath */
857 PSDRV_StrokePath, /* pStrokePath */
858 NULL, /* pUnrealizePalette */
859 NULL, /* pD3DKMTCheckVidPnExclusiveOwnership */
860 NULL, /* pD3DKMTCloseAdapter */
861 NULL, /* pD3DKMTOpenAdapterFromLuid */
862 NULL, /* pD3DKMTQueryVideoMemoryInfo */
863 NULL, /* pD3DKMTSetVidPnSourceOwner */
864 GDI_PRIORITY_GRAPHICS_DRV /* priority */
868 /******************************************************************************
869 * PSDRV_get_gdi_driver
871 const struct gdi_dc_funcs * CDECL PSDRV_get_gdi_driver( unsigned int version )
873 if (version != WINE_GDI_DRIVER_VERSION)
875 ERR( "version mismatch, gdi32 wants %u but wineps has %u\n", version, WINE_GDI_DRIVER_VERSION );
876 return NULL;
878 return &psdrv_funcs;