2 * Exported functions from the PostScript driver.
4 * [Ext]DeviceMode, DeviceCapabilities, AdvancedSetupDialog.
6 * Will need ExtTextOut for winword6 (urgh!)
8 * Copyright 1998 Huw D M Davies
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
32 #include "wine/debug.h"
36 #include "wine/wingdi16.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
42 /* convert points to paper size units (10th of a millimeter) */
43 static inline int paper_size_from_points( float size )
45 return size * 254 / 72;
48 INPUTSLOT *find_slot( PPD *ppd, PSDRV_DEVMODE *dm )
52 LIST_FOR_EACH_ENTRY( slot, &ppd->InputSlots, INPUTSLOT, entry )
53 if (slot->WinBin == dm->dmPublic.u1.s1.dmDefaultSource)
59 PAGESIZE *find_pagesize( PPD *ppd, PSDRV_DEVMODE *dm )
63 LIST_FOR_EACH_ENTRY( page, &ppd->PageSizes, PAGESIZE, entry )
64 if (page->WinPage == dm->dmPublic.u1.s1.dmPaperSize)
70 DUPLEX *find_duplex( PPD *ppd, PSDRV_DEVMODE *dm )
73 WORD win_duplex = dm->dmPublic.dmFields & DM_DUPLEX ? dm->dmPublic.dmDuplex : 0;
75 if (win_duplex == 0) return NULL; /* Not capable */
77 LIST_FOR_EACH_ENTRY( duplex, &ppd->Duplexes, DUPLEX, entry )
78 if (duplex->WinDuplex == win_duplex)
84 /************************************************************************
88 * Updates dm1 with some fields from dm2
91 void PSDRV_MergeDevmodes( PSDRV_DEVMODE *dm1, PSDRV_DEVMODE *dm2, PRINTERINFO *pi )
93 /* some sanity checks here on dm2 */
95 if(dm2->dmPublic.dmFields & DM_ORIENTATION) {
96 dm1->dmPublic.u1.s1.dmOrientation = dm2->dmPublic.u1.s1.dmOrientation;
97 TRACE("Changing orientation to %d (%s)\n",
98 dm1->dmPublic.u1.s1.dmOrientation,
99 dm1->dmPublic.u1.s1.dmOrientation == DMORIENT_PORTRAIT ?
101 (dm1->dmPublic.u1.s1.dmOrientation == DMORIENT_LANDSCAPE ?
102 "Landscape" : "unknown"));
105 /* NB PaperWidth is always < PaperLength */
106 if (dm2->dmPublic.dmFields & DM_PAPERSIZE)
108 PAGESIZE *page = find_pagesize( pi->ppd, dm2 );
112 dm1->dmPublic.u1.s1.dmPaperSize = dm2->dmPublic.u1.s1.dmPaperSize;
113 dm1->dmPublic.u1.s1.dmPaperWidth = paper_size_from_points( page->PaperDimension->x );
114 dm1->dmPublic.u1.s1.dmPaperLength = paper_size_from_points( page->PaperDimension->y );
115 dm1->dmPublic.dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH);
116 dm1->dmPublic.dmFields |= DM_PAPERSIZE;
117 TRACE("Changing page to %s %d x %d\n", page->FullName,
118 dm1->dmPublic.u1.s1.dmPaperWidth,
119 dm1->dmPublic.u1.s1.dmPaperLength );
121 if (dm1->dmPublic.dmSize >= FIELD_OFFSET(DEVMODEW, dmFormName) + CCHFORMNAME * sizeof(WCHAR))
123 MultiByteToWideChar(CP_ACP, 0, page->FullName, -1, dm1->dmPublic.dmFormName, CCHFORMNAME);
124 dm1->dmPublic.dmFields |= DM_FORMNAME;
128 TRACE("Trying to change to unsupported pagesize %d\n", dm2->dmPublic.u1.s1.dmPaperSize);
131 else if((dm2->dmPublic.dmFields & DM_PAPERLENGTH) &&
132 (dm2->dmPublic.dmFields & DM_PAPERWIDTH)) {
133 dm1->dmPublic.u1.s1.dmPaperLength = dm2->dmPublic.u1.s1.dmPaperLength;
134 dm1->dmPublic.u1.s1.dmPaperWidth = dm2->dmPublic.u1.s1.dmPaperWidth;
135 TRACE("Changing PaperLength|Width to %dx%d\n",
136 dm2->dmPublic.u1.s1.dmPaperLength,
137 dm2->dmPublic.u1.s1.dmPaperWidth);
138 dm1->dmPublic.dmFields &= ~DM_PAPERSIZE;
139 dm1->dmPublic.dmFields |= (DM_PAPERLENGTH | DM_PAPERWIDTH);
140 } else if(dm2->dmPublic.dmFields & (DM_PAPERLENGTH | DM_PAPERWIDTH)) {
141 /* You might think that this would be allowed if dm1 is in custom size
142 mode, but apparently Windows reverts to standard paper mode even in
144 FIXME("Trying to change only paperlength or paperwidth\n");
145 dm1->dmPublic.dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH);
146 dm1->dmPublic.dmFields |= DM_PAPERSIZE;
149 if(dm2->dmPublic.dmFields & DM_SCALE) {
150 dm1->dmPublic.u1.s1.dmScale = dm2->dmPublic.u1.s1.dmScale;
151 TRACE("Changing Scale to %d\n", dm2->dmPublic.u1.s1.dmScale);
154 if(dm2->dmPublic.dmFields & DM_COPIES) {
155 dm1->dmPublic.u1.s1.dmCopies = dm2->dmPublic.u1.s1.dmCopies;
156 TRACE("Changing Copies to %d\n", dm2->dmPublic.u1.s1.dmCopies);
159 if (dm2->dmPublic.dmFields & DM_DEFAULTSOURCE)
161 INPUTSLOT *slot = find_slot( pi->ppd, dm2 );
165 dm1->dmPublic.u1.s1.dmDefaultSource = dm2->dmPublic.u1.s1.dmDefaultSource;
166 TRACE("Changing bin to '%s'\n", slot->FullName);
169 TRACE("Trying to change to unsupported bin %d\n", dm2->dmPublic.u1.s1.dmDefaultSource);
172 if (dm2->dmPublic.dmFields & DM_DEFAULTSOURCE )
173 dm1->dmPublic.u1.s1.dmDefaultSource = dm2->dmPublic.u1.s1.dmDefaultSource;
174 if (dm2->dmPublic.dmFields & DM_PRINTQUALITY )
175 dm1->dmPublic.u1.s1.dmPrintQuality = dm2->dmPublic.u1.s1.dmPrintQuality;
176 if (dm2->dmPublic.dmFields & DM_COLOR )
177 dm1->dmPublic.dmColor = dm2->dmPublic.dmColor;
178 if (dm2->dmPublic.dmFields & DM_DUPLEX && pi->ppd->DefaultDuplex && pi->ppd->DefaultDuplex->WinDuplex != 0)
179 dm1->dmPublic.dmDuplex = dm2->dmPublic.dmDuplex;
180 if (dm2->dmPublic.dmFields & DM_YRESOLUTION )
181 dm1->dmPublic.dmYResolution = dm2->dmPublic.dmYResolution;
182 if (dm2->dmPublic.dmFields & DM_TTOPTION )
183 dm1->dmPublic.dmTTOption = dm2->dmPublic.dmTTOption;
184 if (dm2->dmPublic.dmFields & DM_COLLATE )
185 dm1->dmPublic.dmCollate = dm2->dmPublic.dmCollate;
186 if (dm2->dmPublic.dmFields & DM_FORMNAME )
187 lstrcpynW(dm1->dmPublic.dmFormName, dm2->dmPublic.dmFormName, CCHFORMNAME);
188 if (dm2->dmPublic.dmFields & DM_BITSPERPEL )
189 dm1->dmPublic.dmBitsPerPel = dm2->dmPublic.dmBitsPerPel;
190 if (dm2->dmPublic.dmFields & DM_PELSWIDTH )
191 dm1->dmPublic.dmPelsWidth = dm2->dmPublic.dmPelsWidth;
192 if (dm2->dmPublic.dmFields & DM_PELSHEIGHT )
193 dm1->dmPublic.dmPelsHeight = dm2->dmPublic.dmPelsHeight;
194 if (dm2->dmPublic.dmFields & DM_DISPLAYFLAGS )
195 dm1->dmPublic.u2.dmDisplayFlags = dm2->dmPublic.u2.dmDisplayFlags;
196 if (dm2->dmPublic.dmFields & DM_DISPLAYFREQUENCY )
197 dm1->dmPublic.dmDisplayFrequency = dm2->dmPublic.dmDisplayFrequency;
198 if (dm2->dmPublic.dmFields & DM_POSITION )
199 dm1->dmPublic.u1.s2.dmPosition = dm2->dmPublic.u1.s2.dmPosition;
200 if (dm2->dmPublic.dmFields & DM_LOGPIXELS )
201 dm1->dmPublic.dmLogPixels = dm2->dmPublic.dmLogPixels;
202 if (dm2->dmPublic.dmFields & DM_ICMMETHOD )
203 dm1->dmPublic.dmICMMethod = dm2->dmPublic.dmICMMethod;
204 if (dm2->dmPublic.dmFields & DM_ICMINTENT )
205 dm1->dmPublic.dmICMIntent = dm2->dmPublic.dmICMIntent;
206 if (dm2->dmPublic.dmFields & DM_MEDIATYPE )
207 dm1->dmPublic.dmMediaType = dm2->dmPublic.dmMediaType;
208 if (dm2->dmPublic.dmFields & DM_DITHERTYPE )
209 dm1->dmPublic.dmDitherType = dm2->dmPublic.dmDitherType;
210 if (dm2->dmPublic.dmFields & DM_PANNINGWIDTH )
211 dm1->dmPublic.dmPanningWidth = dm2->dmPublic.dmPanningWidth;
212 if (dm2->dmPublic.dmFields & DM_PANNINGHEIGHT )
213 dm1->dmPublic.dmPanningHeight = dm2->dmPublic.dmPanningHeight;
222 PSDRV_DEVMODE *dlgdm;
225 /****************************************************************
228 * Dialog proc for 'Paper' propsheet
230 static INT_PTR CALLBACK PSDRV_PaperDlgProc(HWND hwnd, UINT msg,
231 WPARAM wParam, LPARAM lParam)
233 static const WCHAR resW[] = {'%','d',0};
234 static const WCHAR resxyW[] = {'%','d','x','%','d',0};
243 di = (PSDRV_DLGINFO*)((PROPSHEETPAGEA*)lParam)->lParam;
244 SetWindowLongPtrW(hwnd, DWLP_USER, (LONG_PTR)di);
247 LIST_FOR_EACH_ENTRY(ps, &di->pi->ppd->PageSizes, PAGESIZE, entry) {
248 SendDlgItemMessageA(hwnd, IDD_PAPERS, LB_INSERTSTRING, i,
249 (LPARAM)ps->FullName);
250 if(di->pi->Devmode->dmPublic.u1.s1.dmPaperSize == ps->WinPage)
254 SendDlgItemMessageA(hwnd, IDD_PAPERS, LB_SETCURSEL, Cursel, 0);
256 CheckRadioButton(hwnd, IDD_ORIENT_PORTRAIT, IDD_ORIENT_LANDSCAPE,
257 di->pi->Devmode->dmPublic.u1.s1.dmOrientation ==
258 DMORIENT_PORTRAIT ? IDD_ORIENT_PORTRAIT :
259 IDD_ORIENT_LANDSCAPE);
261 if (list_empty( &di->pi->ppd->Duplexes ))
263 ShowWindow(GetDlgItem(hwnd, IDD_DUPLEX), SW_HIDE);
264 ShowWindow(GetDlgItem(hwnd, IDD_DUPLEX_NAME), SW_HIDE);
269 LIST_FOR_EACH_ENTRY( duplex, &di->pi->ppd->Duplexes, DUPLEX, entry )
271 SendDlgItemMessageA(hwnd, IDD_DUPLEX, CB_INSERTSTRING, i,
272 (LPARAM)(duplex->FullName ? duplex->FullName : duplex->Name));
273 if(di->pi->Devmode->dmPublic.dmDuplex == duplex->WinDuplex)
277 SendDlgItemMessageA(hwnd, IDD_DUPLEX, CB_SETCURSEL, Cursel, 0);
280 if (list_empty( &di->pi->ppd->Resolutions ))
285 res = di->pi->ppd->DefaultResolution;
286 len = sprintfW(buf, resW, res);
288 LoadStringW(PSDRV_hInstance, IDS_DPI, buf + len, sizeof(buf)/sizeof(buf[0]) - len);
289 SendDlgItemMessageW(hwnd, IDD_QUALITY, CB_ADDSTRING, 0, (LPARAM)buf);
290 SendDlgItemMessageW(hwnd, IDD_QUALITY, CB_SETITEMDATA, 0, MAKELONG(res, res));
298 resx = resy = di->pi->ppd->DefaultResolution;
300 if (di->pi->Devmode->dmPublic.dmFields & DM_PRINTQUALITY)
301 resx = resy = di->pi->Devmode->dmPublic.u1.s1.dmPrintQuality;
303 if (di->pi->Devmode->dmPublic.dmFields & DM_YRESOLUTION)
304 resy = di->pi->Devmode->dmPublic.dmYResolution;
306 if (di->pi->Devmode->dmPublic.dmFields & DM_LOGPIXELS)
307 resx = resy = di->pi->Devmode->dmPublic.dmLogPixels;
309 LIST_FOR_EACH_ENTRY(res, &di->pi->ppd->Resolutions, RESOLUTION, entry)
315 if (res->resx == res->resy)
316 len = sprintfW(buf, resW, res->resx);
318 len = sprintfW(buf, resxyW, res->resx, res->resy);
320 LoadStringW(PSDRV_hInstance, IDS_DPI, buf + len, sizeof(buf)/sizeof(buf[0]) - len);
321 idx = SendDlgItemMessageW(hwnd, IDD_QUALITY, CB_ADDSTRING, 0, (LPARAM)buf);
322 SendDlgItemMessageW(hwnd, IDD_QUALITY, CB_SETITEMDATA, idx, MAKELONG(res->resx, res->resy));
324 if (res->resx == resx && res->resy == resy)
328 SendDlgItemMessageW(hwnd, IDD_QUALITY, CB_SETCURSEL, Cursel, 0);
333 di = (PSDRV_DLGINFO *)GetWindowLongPtrW(hwnd, DWLP_USER);
334 switch(LOWORD(wParam)) {
336 if(HIWORD(wParam) == LBN_SELCHANGE) {
337 Cursel = SendDlgItemMessageA(hwnd, LOWORD(wParam), LB_GETCURSEL, 0, 0);
339 LIST_FOR_EACH_ENTRY(ps, &di->pi->ppd->PageSizes, PAGESIZE, entry) {
340 if(i >= Cursel) break;
343 TRACE("Setting pagesize to item %d Winpage = %d\n", Cursel, ps->WinPage);
344 di->dlgdm->dmPublic.u1.s1.dmPaperSize = ps->WinPage;
345 di->dlgdm->dmPublic.dmFields |= DM_PAPERSIZE;
347 if (di->dlgdm->dmPublic.dmSize >= FIELD_OFFSET(DEVMODEW, dmFormName) + CCHFORMNAME * sizeof(WCHAR))
349 MultiByteToWideChar(CP_ACP, 0, ps->FullName, -1, di->dlgdm->dmPublic.dmFormName, CCHFORMNAME);
350 di->dlgdm->dmPublic.dmFields |= DM_FORMNAME;
352 SendMessageW(GetParent(hwnd), PSM_CHANGED, 0, 0);
355 case IDD_ORIENT_PORTRAIT:
356 case IDD_ORIENT_LANDSCAPE:
357 TRACE("Setting orientation to %s\n", wParam == IDD_ORIENT_PORTRAIT ?
358 "portrait" : "landscape");
359 di->dlgdm->dmPublic.u1.s1.dmOrientation = wParam == IDD_ORIENT_PORTRAIT ?
360 DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE;
361 di->dlgdm->dmPublic.dmFields |= DM_ORIENTATION;
362 SendMessageW(GetParent(hwnd), PSM_CHANGED, 0, 0);
365 if(HIWORD(wParam) == CBN_SELCHANGE) {
366 Cursel = SendDlgItemMessageA(hwnd, LOWORD(wParam), CB_GETCURSEL, 0, 0);
368 LIST_FOR_EACH_ENTRY( duplex, &di->pi->ppd->Duplexes, DUPLEX, entry )
370 if (i >= Cursel) break;
373 TRACE("Setting duplex to item %d Winduplex = %d\n", Cursel, duplex->WinDuplex);
374 di->dlgdm->dmPublic.dmDuplex = duplex->WinDuplex;
375 di->dlgdm->dmPublic.dmFields |= DM_DUPLEX;
376 SendMessageW(GetParent(hwnd), PSM_CHANGED, 0, 0);
381 if (HIWORD(wParam) == CBN_SELCHANGE)
386 Cursel = SendDlgItemMessageW(hwnd, LOWORD(wParam), CB_GETCURSEL, 0, 0);
387 data = SendDlgItemMessageW(hwnd, IDD_QUALITY, CB_GETITEMDATA, Cursel, 0);
391 TRACE("Setting resolution to %dx%d\n", resx, resy);
393 di->dlgdm->dmPublic.u1.s1.dmPrintQuality = resx;
394 di->dlgdm->dmPublic.dmFields |= DM_PRINTQUALITY;
396 di->dlgdm->dmPublic.dmYResolution = resy;
397 di->dlgdm->dmPublic.dmFields |= DM_YRESOLUTION;
399 if (di->pi->Devmode->dmPublic.dmFields & DM_LOGPIXELS)
401 di->dlgdm->dmPublic.dmLogPixels = resx;
402 di->dlgdm->dmPublic.dmFields |= DM_LOGPIXELS;
405 SendMessageW(GetParent(hwnd), PSM_CHANGED, 0, 0);
413 NMHDR *nmhdr = (NMHDR *)lParam;
414 di = (PSDRV_DLGINFO *)GetWindowLongPtrW(hwnd, DWLP_USER);
415 switch(nmhdr->code) {
417 *di->pi->Devmode = *di->dlgdm;
418 SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, PSNRET_NOERROR);
434 static HPROPSHEETPAGE (WINAPI *pCreatePropertySheetPage) (LPCPROPSHEETPAGEW);
435 static int (WINAPI *pPropertySheet) (LPCPROPSHEETHEADERW);
437 static PRINTERINFO *PSDRV_FindPrinterInfoA(LPCSTR name)
439 int len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
440 WCHAR *nameW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
443 MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, len );
444 pi = PSDRV_FindPrinterInfo( nameW );
445 HeapFree( GetProcessHeap(), 0, nameW );
450 /***********************************************************
453 * Creates an ascii copy of supplied devmode on the process heap
455 * Copied from dlls/winspool/info.c until full unicodification
457 static DEVMODEA *DEVMODEdupWtoA( const DEVMODEW *dmW )
462 /* there is no pointer dereference here, if your code checking tool complains it's broken */
463 ptrdiff_t off_formname = (const char *)dmW->dmFormName - (const char *)dmW;
465 if (!dmW) return NULL;
466 formname = (dmW->dmSize > off_formname);
467 size = dmW->dmSize - CCHDEVICENAME - (formname ? CCHFORMNAME : 0);
468 dmA = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size + dmW->dmDriverExtra );
469 WideCharToMultiByte( CP_ACP, 0, dmW->dmDeviceName, -1, (LPSTR)dmA->dmDeviceName,
470 CCHDEVICENAME, NULL, NULL );
473 memcpy( &dmA->dmSpecVersion, &dmW->dmSpecVersion,
474 dmW->dmSize - CCHDEVICENAME * sizeof(WCHAR) );
478 memcpy( &dmA->dmSpecVersion, &dmW->dmSpecVersion,
479 off_formname - CCHDEVICENAME * sizeof(WCHAR) );
480 WideCharToMultiByte( CP_ACP, 0, dmW->dmFormName, -1, (LPSTR)dmA->dmFormName,
481 CCHFORMNAME, NULL, NULL );
482 memcpy( &dmA->dmLogPixels, &dmW->dmLogPixels, dmW->dmSize -
483 (off_formname + CCHFORMNAME * sizeof(WCHAR)) );
486 memcpy( (char *)dmA + dmA->dmSize, (const char *)dmW + dmW->dmSize,
487 dmW->dmDriverExtra );
491 /******************************************************************
492 * PSDRV_ExtDeviceMode
494 * Retrieves or modifies device-initialization information for the PostScript
495 * driver, or displays a driver-supplied dialog box for configuring the driver.
498 * lpszDriver -- Driver name
499 * hwnd -- Parent window for the dialog box
500 * lpdmOutput -- Address of a DEVMODE structure for writing initialization information
501 * lpszDevice -- Device name
502 * lpszPort -- Port name
503 * lpdmInput -- Address of a DEVMODE structure for reading initialization information
504 * lpProfile -- Name of initialization file, defaults to WIN.INI if NULL
505 * wMode -- Operation to perform. Can be a combination if > 0.
506 * (0) -- Returns number of bytes required by DEVMODE structure
507 * DM_UPDATE (1) -- Write current settings to environment and initialization file
508 * DM_COPY (2) -- Write current settings to lpdmOutput
509 * DM_PROMPT (4) -- Presents the driver's modal dialog box (USER.240)
510 * DM_MODIFY (8) -- Changes current settings according to lpdmInput before any other operation
513 * Returns size of DEVMODE structure if wMode is 0. Otherwise, IDOK is returned for success
514 * for both dialog and non-dialog operations. IDCANCEL is returned if the dialog box was cancelled.
515 * A return value less than zero is returned if a non-dialog operation fails.
519 * Just returns default devmode at the moment. No use of initialization file.
521 INT PSDRV_ExtDeviceMode(LPSTR lpszDriver, HWND hwnd, LPDEVMODEA lpdmOutput,
522 LPSTR lpszDevice, LPSTR lpszPort, LPDEVMODEA lpdmInput,
523 LPSTR lpszProfile, DWORD dwMode)
525 PRINTERINFO *pi = PSDRV_FindPrinterInfoA(lpszDevice);
528 TRACE("(Driver=%s, hwnd=%p, devOut=%p, Device='%s', Port='%s', devIn=%p, Profile='%s', Mode=%04x)\n",
529 lpszDriver, hwnd, lpdmOutput, lpszDevice, lpszPort, lpdmInput, debugstr_a(lpszProfile), dwMode);
531 /* If dwMode == 0, return size of DEVMODE structure */
533 return pi->Devmode->dmPublic.dmSize + pi->Devmode->dmPublic.dmDriverExtra - CCHDEVICENAME - CCHFORMNAME;
535 /* If DM_MODIFY is set, change settings in accordance with lpdmInput */
536 if((dwMode & DM_MODIFY) && lpdmInput)
538 DEVMODEW *dmW = GdiConvertToDevmodeW( lpdmInput );
539 TRACE("DM_MODIFY set. devIn->dmFields = %08x\n", lpdmInput->dmFields);
540 if (dmW) PSDRV_MergeDevmodes(pi->Devmode, (PSDRV_DEVMODE *)dmW, pi);
541 HeapFree( GetProcessHeap(), 0, dmW );
544 /* If DM_PROMPT is set, present modal dialog box */
545 if(dwMode & DM_PROMPT) {
546 HINSTANCE hinstComctl32;
547 HPROPSHEETPAGE hpsp[1];
549 PROPSHEETHEADERW psh;
552 static const WCHAR PAPERW[] = {'P','A','P','E','R','\0'};
553 static const WCHAR SetupW[] = {'S','e','t','u','p','\0'};
555 hinstComctl32 = LoadLibraryA("comctl32.dll");
556 pCreatePropertySheetPage = (void*)GetProcAddress(hinstComctl32,
557 "CreatePropertySheetPageW");
558 pPropertySheet = (void*)GetProcAddress(hinstComctl32, "PropertySheetW");
559 memset(&psp,0,sizeof(psp));
560 dlgdm = *pi->Devmode;
563 psp.dwSize = sizeof(psp);
564 psp.hInstance = PSDRV_hInstance;
565 psp.u.pszTemplate = PAPERW;
566 psp.u2.pszIcon = NULL;
567 psp.pfnDlgProc = PSDRV_PaperDlgProc;
568 psp.lParam = (LPARAM)&di;
569 hpsp[0] = pCreatePropertySheetPage(&psp);
571 memset(&psh, 0, sizeof(psh));
572 psh.dwSize = sizeof(psh);
573 psh.pszCaption = SetupW;
575 psh.hwndParent = hwnd;
576 psh.u3.phpage = hpsp;
578 pPropertySheet(&psh);
582 /* If DM_UPDATE is set, should write settings to environment and initialization file */
583 if(dwMode & DM_UPDATE)
584 FIXME("Mode DM_UPDATE. Just do the same as DM_COPY\n");
586 /* If DM_COPY is set, should write settings to lpdmOutput */
587 if((dwMode & DM_COPY) || (dwMode & DM_UPDATE)) {
590 DEVMODEA *dmA = DEVMODEdupWtoA( &pi->Devmode->dmPublic );
591 if (dmA) memcpy( lpdmOutput, dmA, dmA->dmSize + dmA->dmDriverExtra );
592 HeapFree( GetProcessHeap(), 0, dmA );
595 FIXME("lpdmOutput is NULL what should we do??\n");
599 /***********************************************************************
600 * PSDRV_DeviceCapabilities
602 * Retrieves the capabilities of a printer device driver.
605 * lpszDriver -- printer driver name
606 * lpszDevice -- printer name
607 * lpszPort -- port name
608 * fwCapability -- device capability
609 * lpszOutput -- output buffer
610 * lpDevMode -- device data buffer
613 * Result depends on the setting of fwCapability. -1 indicates failure.
615 DWORD PSDRV_DeviceCapabilities(LPSTR lpszDriver, LPCSTR lpszDevice, LPCSTR lpszPort,
616 WORD fwCapability, LPSTR lpszOutput, LPDEVMODEA lpDevMode)
621 pi = PSDRV_FindPrinterInfoA(lpszDevice);
623 TRACE("%s %s %s, %u, %p, %p\n", debugstr_a(lpszDriver), debugstr_a(lpszDevice),
624 debugstr_a(lpszPort), fwCapability, lpszOutput, lpDevMode);
627 ERR("no printer info for %s %s, return 0!\n",
628 debugstr_a(lpszDriver), debugstr_a(lpszDevice));
632 lpdm = &pi->Devmode->dmPublic;
633 if (lpDevMode) lpdm = GdiConvertToDevmodeW( lpDevMode );
635 switch(fwCapability) {
640 WORD *wp = (WORD *)lpszOutput;
643 LIST_FOR_EACH_ENTRY(ps, &pi->ppd->PageSizes, PAGESIZE, entry)
645 TRACE("DC_PAPERS: %u\n", ps->WinPage);
647 if(lpszOutput != NULL)
657 POINT16 *pt = (POINT16 *)lpszOutput;
660 LIST_FOR_EACH_ENTRY(ps, &pi->ppd->PageSizes, PAGESIZE, entry)
662 TRACE("DC_PAPERSIZE: %f x %f\n", ps->PaperDimension->x, ps->PaperDimension->y);
664 if(lpszOutput != NULL) {
665 pt->x = paper_size_from_points( ps->PaperDimension->x );
666 pt->y = paper_size_from_points( ps->PaperDimension->y );
677 char *cp = lpszOutput;
680 LIST_FOR_EACH_ENTRY(ps, &pi->ppd->PageSizes, PAGESIZE, entry)
682 TRACE("DC_PAPERNAMES: %s\n", debugstr_a(ps->FullName));
684 if(lpszOutput != NULL) {
685 lstrcpynA(cp, ps->FullName, 64);
694 ret = pi->ppd->LandscapeOrientation ? pi->ppd->LandscapeOrientation : 90;
700 WORD *wp = (WORD *)lpszOutput;
703 LIST_FOR_EACH_ENTRY( slot, &pi->ppd->InputSlots, INPUTSLOT, entry )
706 if (lpszOutput != NULL)
707 *wp++ = slot->WinBin;
716 char *cp = lpszOutput;
719 LIST_FOR_EACH_ENTRY( slot, &pi->ppd->InputSlots, INPUTSLOT, entry )
722 if (lpszOutput != NULL)
724 lstrcpynA( cp, slot->FullName, 24 );
733 FIXME("DC_BINADJUST: stub.\n");
734 ret = DCBA_FACEUPNONE;
737 case DC_ENUMRESOLUTIONS:
740 LONG *lp = (LONG *)lpszOutput;
743 LIST_FOR_EACH_ENTRY(res, &pi->ppd->Resolutions, RESOLUTION, entry)
746 if (lpszOutput != NULL)
757 /* Windows returns 9999 too */
759 TRACE("DC_COPIES: returning 9999\n");
764 ret = lpdm->dmDriverVersion;
767 case DC_DATATYPE_PRODUCED:
768 FIXME("DATA_TYPE_PRODUCED: stub.\n");
769 ret = -1; /* simulate that the driver supports 'RAW' */
774 if(pi->ppd->DefaultDuplex && pi->ppd->DefaultDuplex->WinDuplex != 0)
776 TRACE("DC_DUPLEX: returning %d\n", ret);
779 case DC_EMF_COMPLIANT:
780 FIXME("DC_EMF_COMPLIANT: stub.\n");
781 ret = -1; /* simulate that the driver do not support EMF */
785 ret = lpdm->dmDriverExtra;
789 ret = lpdm->dmFields;
792 case DC_FILEDEPENDENCIES:
793 FIXME("DC_FILEDEPENDENCIES: stub.\n");
802 LIST_FOR_EACH_ENTRY(ps, &pi->ppd->PageSizes, PAGESIZE, entry)
804 if (ps->PaperDimension->x > x) x = ps->PaperDimension->x;
805 if (ps->PaperDimension->y > y) y = ps->PaperDimension->y;
807 ret = MAKELONG( paper_size_from_points(x), paper_size_from_points(y) );
814 float x = 1e6, y = 1e6;
816 LIST_FOR_EACH_ENTRY(ps, &pi->ppd->PageSizes, PAGESIZE, entry)
818 if (ps->PaperDimension->x < x) x = ps->PaperDimension->x;
819 if (ps->PaperDimension->y < y) y = ps->PaperDimension->y;
821 ret = MAKELONG( paper_size_from_points(x), paper_size_from_points(y) );
830 FIXME("DC_TRUETYPE: stub\n");
835 ret = lpdm->dmSpecVersion;
838 /* We'll just return false here, very few printers can collate anyway */
840 TRACE("DC_COLLATE: returning FALSE\n");
844 /* Printer supports colour printing - 1 if yes, 0 if no (Win2k/XP only) */
846 ret = pi->ppd->ColorDevice != CD_False;
849 /* Identification number of the printer manufacturer for use with ICM (Win9x only) */
850 case DC_MANUFACTURER:
851 FIXME("DC_MANUFACTURER: stub\n");
855 /* Identification number of the printer model for use with ICM (Win9x only) */
857 FIXME("DC_MODEL: stub\n");
861 /* Nonzero if the printer supports stapling, zero otherwise (Win2k/XP only) */
862 case DC_STAPLE: /* WINVER >= 0x0500 */
863 FIXME("DC_STAPLE: stub\n");
867 /* Returns an array of 64-character string buffers containing the names of the paper forms
868 * available for use, unless pOutput is NULL. The return value is the number of paper forms.
871 case DC_MEDIAREADY: /* WINVER >= 0x0500 */
872 FIXME("DC_MEDIAREADY: stub\n");
876 /* Returns an array of 64-character string buffers containing the names of the supported
877 * media types, unless pOutput is NULL. The return value is the number of supported.
878 * media types (XP only)
880 case DC_MEDIATYPENAMES: /* WINVER >= 0x0501 */
881 FIXME("DC_MEDIATYPENAMES: stub\n");
885 /* Returns an array of DWORD values which represent the supported media types, unless
886 * pOutput is NULL. The return value is the number of supported media types. (XP only)
888 case DC_MEDIATYPES: /* WINVER >= 0x0501 */
889 FIXME("DC_MEDIATYPES: stub\n");
893 /* Returns an array of DWORD values, each representing a supported number of document
894 * pages per printed page, unless pOutput is NULL. The return value is the number of
895 * array entries. (Win2k/XP only)
898 FIXME("DC_NUP: stub\n");
902 /* Returns an array of 32-character string buffers containing a list of printer description
903 * languages supported by the printer, unless pOutput is NULL. The return value is
904 * number of array entries. (Win2k/XP only)
907 case DC_PERSONALITY: /* WINVER >= 0x0500 */
908 FIXME("DC_PERSONALITY: stub\n");
912 /* Returns the amount of printer memory in kilobytes. (Win2k/XP only) */
913 case DC_PRINTERMEM: /* WINVER >= 0x0500 */
914 FIXME("DC_PRINTERMEM: stub\n");
918 /* Returns the printer's print rate in PRINTRATEUNIT units. (Win2k/XP only) */
919 case DC_PRINTRATE: /* WINVER >= 0x0500 */
920 FIXME("DC_PRINTRATE: stub\n");
924 /* Returns the printer's print rate in pages per minute. (Win2k/XP only) */
925 case DC_PRINTRATEPPM: /* WINVER >= 0x0500 */
926 FIXME("DC_PRINTRATEPPM: stub\n");
930 /* Returns the printer rate unit used for DC_PRINTRATE, which is one of
931 * PRINTRATEUNIT_{CPS,IPM,LPM,PPM} (Win2k/XP only)
933 case DC_PRINTRATEUNIT: /* WINVER >= 0x0500 */
934 FIXME("DC_PRINTRATEUNIT: stub\n");
939 FIXME("Unsupported capability %d\n", fwCapability);
943 if (lpDevMode) HeapFree( GetProcessHeap(), 0, lpdm );
951 HPROPSHEETPAGE hPages[10];
954 INT PSDRV_ExtDeviceModePropSheet(HWND hwnd, LPSTR lpszDevice, LPSTR lpszPort,
957 EDMPS *ps = pPropSheet;
960 psp->dwSize = sizeof(psp);
961 psp->hInstance = 0x1234;