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 );
122 TRACE("Trying to change to unsupported pagesize %d\n", dm2->dmPublic.u1.s1.dmPaperSize);
125 else if((dm2->dmPublic.dmFields & DM_PAPERLENGTH) &&
126 (dm2->dmPublic.dmFields & DM_PAPERWIDTH)) {
127 dm1->dmPublic.u1.s1.dmPaperLength = dm2->dmPublic.u1.s1.dmPaperLength;
128 dm1->dmPublic.u1.s1.dmPaperWidth = dm2->dmPublic.u1.s1.dmPaperWidth;
129 TRACE("Changing PaperLength|Width to %dx%d\n",
130 dm2->dmPublic.u1.s1.dmPaperLength,
131 dm2->dmPublic.u1.s1.dmPaperWidth);
132 dm1->dmPublic.dmFields &= ~DM_PAPERSIZE;
133 dm1->dmPublic.dmFields |= (DM_PAPERLENGTH | DM_PAPERWIDTH);
134 } else if(dm2->dmPublic.dmFields & (DM_PAPERLENGTH | DM_PAPERWIDTH)) {
135 /* You might think that this would be allowed if dm1 is in custom size
136 mode, but apparently Windows reverts to standard paper mode even in
138 FIXME("Trying to change only paperlength or paperwidth\n");
139 dm1->dmPublic.dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH);
140 dm1->dmPublic.dmFields |= DM_PAPERSIZE;
143 if(dm2->dmPublic.dmFields & DM_SCALE) {
144 dm1->dmPublic.u1.s1.dmScale = dm2->dmPublic.u1.s1.dmScale;
145 TRACE("Changing Scale to %d\n", dm2->dmPublic.u1.s1.dmScale);
148 if(dm2->dmPublic.dmFields & DM_COPIES) {
149 dm1->dmPublic.u1.s1.dmCopies = dm2->dmPublic.u1.s1.dmCopies;
150 TRACE("Changing Copies to %d\n", dm2->dmPublic.u1.s1.dmCopies);
153 if (dm2->dmPublic.dmFields & DM_DEFAULTSOURCE)
155 INPUTSLOT *slot = find_slot( pi->ppd, dm2 );
159 dm1->dmPublic.u1.s1.dmDefaultSource = dm2->dmPublic.u1.s1.dmDefaultSource;
160 TRACE("Changing bin to '%s'\n", slot->FullName);
163 TRACE("Trying to change to unsupported bin %d\n", dm2->dmPublic.u1.s1.dmDefaultSource);
166 if (dm2->dmPublic.dmFields & DM_DEFAULTSOURCE )
167 dm1->dmPublic.u1.s1.dmDefaultSource = dm2->dmPublic.u1.s1.dmDefaultSource;
168 if (dm2->dmPublic.dmFields & DM_PRINTQUALITY )
169 dm1->dmPublic.u1.s1.dmPrintQuality = dm2->dmPublic.u1.s1.dmPrintQuality;
170 if (dm2->dmPublic.dmFields & DM_COLOR )
171 dm1->dmPublic.dmColor = dm2->dmPublic.dmColor;
172 if (dm2->dmPublic.dmFields & DM_DUPLEX && pi->ppd->DefaultDuplex && pi->ppd->DefaultDuplex->WinDuplex != 0)
173 dm1->dmPublic.dmDuplex = dm2->dmPublic.dmDuplex;
174 if (dm2->dmPublic.dmFields & DM_YRESOLUTION )
175 dm1->dmPublic.dmYResolution = dm2->dmPublic.dmYResolution;
176 if (dm2->dmPublic.dmFields & DM_TTOPTION )
177 dm1->dmPublic.dmTTOption = dm2->dmPublic.dmTTOption;
178 if (dm2->dmPublic.dmFields & DM_COLLATE )
179 dm1->dmPublic.dmCollate = dm2->dmPublic.dmCollate;
180 if (dm2->dmPublic.dmFields & DM_FORMNAME )
181 lstrcpynA((LPSTR)dm1->dmPublic.dmFormName, (LPCSTR)dm2->dmPublic.dmFormName, CCHFORMNAME);
182 if (dm2->dmPublic.dmFields & DM_BITSPERPEL )
183 dm1->dmPublic.dmBitsPerPel = dm2->dmPublic.dmBitsPerPel;
184 if (dm2->dmPublic.dmFields & DM_PELSWIDTH )
185 dm1->dmPublic.dmPelsWidth = dm2->dmPublic.dmPelsWidth;
186 if (dm2->dmPublic.dmFields & DM_PELSHEIGHT )
187 dm1->dmPublic.dmPelsHeight = dm2->dmPublic.dmPelsHeight;
188 if (dm2->dmPublic.dmFields & DM_DISPLAYFLAGS )
189 dm1->dmPublic.u2.dmDisplayFlags = dm2->dmPublic.u2.dmDisplayFlags;
190 if (dm2->dmPublic.dmFields & DM_DISPLAYFREQUENCY )
191 dm1->dmPublic.dmDisplayFrequency = dm2->dmPublic.dmDisplayFrequency;
192 if (dm2->dmPublic.dmFields & DM_POSITION )
193 dm1->dmPublic.u1.s2.dmPosition = dm2->dmPublic.u1.s2.dmPosition;
194 if (dm2->dmPublic.dmFields & DM_LOGPIXELS )
195 dm1->dmPublic.dmLogPixels = dm2->dmPublic.dmLogPixels;
196 if (dm2->dmPublic.dmFields & DM_ICMMETHOD )
197 dm1->dmPublic.dmICMMethod = dm2->dmPublic.dmICMMethod;
198 if (dm2->dmPublic.dmFields & DM_ICMINTENT )
199 dm1->dmPublic.dmICMIntent = dm2->dmPublic.dmICMIntent;
200 if (dm2->dmPublic.dmFields & DM_MEDIATYPE )
201 dm1->dmPublic.dmMediaType = dm2->dmPublic.dmMediaType;
202 if (dm2->dmPublic.dmFields & DM_DITHERTYPE )
203 dm1->dmPublic.dmDitherType = dm2->dmPublic.dmDitherType;
204 if (dm2->dmPublic.dmFields & DM_PANNINGWIDTH )
205 dm1->dmPublic.dmPanningWidth = dm2->dmPublic.dmPanningWidth;
206 if (dm2->dmPublic.dmFields & DM_PANNINGHEIGHT )
207 dm1->dmPublic.dmPanningHeight = dm2->dmPublic.dmPanningHeight;
216 PSDRV_DEVMODE *dlgdm;
219 /****************************************************************
222 * Dialog proc for 'Paper' propsheet
224 static INT_PTR CALLBACK PSDRV_PaperDlgProc(HWND hwnd, UINT msg,
225 WPARAM wParam, LPARAM lParam)
234 di = (PSDRV_DLGINFO*)((PROPSHEETPAGEA*)lParam)->lParam;
235 SetWindowLongPtrW(hwnd, DWLP_USER, (LONG_PTR)di);
238 LIST_FOR_EACH_ENTRY(ps, &di->pi->ppd->PageSizes, PAGESIZE, entry) {
239 SendDlgItemMessageA(hwnd, IDD_PAPERS, LB_INSERTSTRING, i,
240 (LPARAM)ps->FullName);
241 if(di->pi->Devmode->dmPublic.u1.s1.dmPaperSize == ps->WinPage)
245 SendDlgItemMessageA(hwnd, IDD_PAPERS, LB_SETCURSEL, Cursel, 0);
247 CheckRadioButton(hwnd, IDD_ORIENT_PORTRAIT, IDD_ORIENT_LANDSCAPE,
248 di->pi->Devmode->dmPublic.u1.s1.dmOrientation ==
249 DMORIENT_PORTRAIT ? IDD_ORIENT_PORTRAIT :
250 IDD_ORIENT_LANDSCAPE);
252 if (list_empty( &di->pi->ppd->Duplexes ))
254 ShowWindow(GetDlgItem(hwnd, IDD_DUPLEX), SW_HIDE);
255 ShowWindow(GetDlgItem(hwnd, IDD_DUPLEX_NAME), SW_HIDE);
260 LIST_FOR_EACH_ENTRY( duplex, &di->pi->ppd->Duplexes, DUPLEX, entry )
262 SendDlgItemMessageA(hwnd, IDD_DUPLEX, CB_INSERTSTRING, i,
263 (LPARAM)(duplex->FullName ? duplex->FullName : duplex->Name));
264 if(di->pi->Devmode->dmPublic.dmDuplex == duplex->WinDuplex)
268 SendDlgItemMessageA(hwnd, IDD_DUPLEX, CB_SETCURSEL, Cursel, 0);
273 di = (PSDRV_DLGINFO *)GetWindowLongPtrW(hwnd, DWLP_USER);
274 switch(LOWORD(wParam)) {
276 if(HIWORD(wParam) == LBN_SELCHANGE) {
277 Cursel = SendDlgItemMessageA(hwnd, LOWORD(wParam), LB_GETCURSEL, 0, 0);
279 LIST_FOR_EACH_ENTRY(ps, &di->pi->ppd->PageSizes, PAGESIZE, entry) {
280 if(i >= Cursel) break;
283 TRACE("Setting pagesize to item %d Winpage = %d\n", Cursel, ps->WinPage);
284 di->dlgdm->dmPublic.u1.s1.dmPaperSize = ps->WinPage;
285 SendMessageW(GetParent(hwnd), PSM_CHANGED, 0, 0);
288 case IDD_ORIENT_PORTRAIT:
289 case IDD_ORIENT_LANDSCAPE:
290 TRACE("Setting orientation to %s\n", wParam == IDD_ORIENT_PORTRAIT ?
291 "portrait" : "landscape");
292 di->dlgdm->dmPublic.u1.s1.dmOrientation = wParam == IDD_ORIENT_PORTRAIT ?
293 DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE;
294 SendMessageW(GetParent(hwnd), PSM_CHANGED, 0, 0);
297 if(HIWORD(wParam) == CBN_SELCHANGE) {
298 Cursel = SendDlgItemMessageA(hwnd, LOWORD(wParam), CB_GETCURSEL, 0, 0);
300 LIST_FOR_EACH_ENTRY( duplex, &di->pi->ppd->Duplexes, DUPLEX, entry )
302 if (i >= Cursel) break;
305 TRACE("Setting duplex to item %d Winduplex = %d\n", Cursel, duplex->WinDuplex);
306 di->dlgdm->dmPublic.dmDuplex = duplex->WinDuplex;
307 SendMessageW(GetParent(hwnd), PSM_CHANGED, 0, 0);
315 NMHDR *nmhdr = (NMHDR *)lParam;
316 di = (PSDRV_DLGINFO *)GetWindowLongPtrW(hwnd, DWLP_USER);
317 switch(nmhdr->code) {
319 *di->pi->Devmode = *di->dlgdm;
320 SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, PSNRET_NOERROR);
336 static HPROPSHEETPAGE (WINAPI *pCreatePropertySheetPage) (LPCPROPSHEETPAGEW);
337 static int (WINAPI *pPropertySheet) (LPCPROPSHEETHEADERW);
339 static PRINTERINFO *PSDRV_FindPrinterInfoA(LPCSTR name)
341 int len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
342 WCHAR *nameW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
345 MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, len );
346 pi = PSDRV_FindPrinterInfo( nameW );
347 HeapFree( GetProcessHeap(), 0, nameW );
352 /***********************************************************
355 * Creates an ascii copy of supplied devmode on the process heap
357 * Copied from dlls/winspool/info.c until full unicodification
359 static DEVMODEA *DEVMODEdupWtoA( const DEVMODEW *dmW )
364 /* there is no pointer dereference here, if your code checking tool complains it's broken */
365 ptrdiff_t off_formname = (const char *)dmW->dmFormName - (const char *)dmW;
367 if (!dmW) return NULL;
368 formname = (dmW->dmSize > off_formname);
369 size = dmW->dmSize - CCHDEVICENAME - (formname ? CCHFORMNAME : 0);
370 dmA = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size + dmW->dmDriverExtra );
371 WideCharToMultiByte( CP_ACP, 0, dmW->dmDeviceName, -1, (LPSTR)dmA->dmDeviceName,
372 CCHDEVICENAME, NULL, NULL );
375 memcpy( &dmA->dmSpecVersion, &dmW->dmSpecVersion,
376 dmW->dmSize - CCHDEVICENAME * sizeof(WCHAR) );
380 memcpy( &dmA->dmSpecVersion, &dmW->dmSpecVersion,
381 off_formname - CCHDEVICENAME * sizeof(WCHAR) );
382 WideCharToMultiByte( CP_ACP, 0, dmW->dmFormName, -1, (LPSTR)dmA->dmFormName,
383 CCHFORMNAME, NULL, NULL );
384 memcpy( &dmA->dmLogPixels, &dmW->dmLogPixels, dmW->dmSize -
385 (off_formname + CCHFORMNAME * sizeof(WCHAR)) );
388 memcpy( (char *)dmA + dmA->dmSize, (const char *)dmW + dmW->dmSize,
389 dmW->dmDriverExtra );
393 /******************************************************************
394 * PSDRV_ExtDeviceMode
396 * Retrieves or modifies device-initialization information for the PostScript
397 * driver, or displays a driver-supplied dialog box for configuring the driver.
400 * lpszDriver -- Driver name
401 * hwnd -- Parent window for the dialog box
402 * lpdmOutput -- Address of a DEVMODE structure for writing initialization information
403 * lpszDevice -- Device name
404 * lpszPort -- Port name
405 * lpdmInput -- Address of a DEVMODE structure for reading initialization information
406 * lpProfile -- Name of initialization file, defaults to WIN.INI if NULL
407 * wMode -- Operation to perform. Can be a combination if > 0.
408 * (0) -- Returns number of bytes required by DEVMODE structure
409 * DM_UPDATE (1) -- Write current settings to environment and initialization file
410 * DM_COPY (2) -- Write current settings to lpdmOutput
411 * DM_PROMPT (4) -- Presents the driver's modal dialog box (USER.240)
412 * DM_MODIFY (8) -- Changes current settings according to lpdmInput before any other operation
415 * Returns size of DEVMODE structure if wMode is 0. Otherwise, IDOK is returned for success
416 * for both dialog and non-dialog operations. IDCANCEL is returned if the dialog box was cancelled.
417 * A return value less than zero is returned if a non-dialog operation fails.
421 * Just returns default devmode at the moment. No use of initialization file.
423 INT PSDRV_ExtDeviceMode(LPSTR lpszDriver, HWND hwnd, LPDEVMODEA lpdmOutput,
424 LPSTR lpszDevice, LPSTR lpszPort, LPDEVMODEA lpdmInput,
425 LPSTR lpszProfile, DWORD dwMode)
427 PRINTERINFO *pi = PSDRV_FindPrinterInfoA(lpszDevice);
430 TRACE("(Driver=%s, hwnd=%p, devOut=%p, Device='%s', Port='%s', devIn=%p, Profile='%s', Mode=%04x)\n",
431 lpszDriver, hwnd, lpdmOutput, lpszDevice, lpszPort, lpdmInput, debugstr_a(lpszProfile), dwMode);
433 /* If dwMode == 0, return size of DEVMODE structure */
435 return pi->Devmode->dmPublic.dmSize + pi->Devmode->dmPublic.dmDriverExtra - CCHDEVICENAME - CCHFORMNAME;
437 /* If DM_MODIFY is set, change settings in accordance with lpdmInput */
438 if((dwMode & DM_MODIFY) && lpdmInput)
440 DEVMODEW *dmW = GdiConvertToDevmodeW( lpdmInput );
441 TRACE("DM_MODIFY set. devIn->dmFields = %08x\n", lpdmInput->dmFields);
442 if (dmW) PSDRV_MergeDevmodes(pi->Devmode, (PSDRV_DEVMODE *)dmW, pi);
443 HeapFree( GetProcessHeap(), 0, dmW );
446 /* If DM_PROMPT is set, present modal dialog box */
447 if(dwMode & DM_PROMPT) {
448 HINSTANCE hinstComctl32;
449 HPROPSHEETPAGE hpsp[1];
451 PROPSHEETHEADERW psh;
454 static const WCHAR PAPERW[] = {'P','A','P','E','R','\0'};
455 static const WCHAR SetupW[] = {'S','e','t','u','p','\0'};
457 hinstComctl32 = LoadLibraryA("comctl32.dll");
458 pCreatePropertySheetPage = (void*)GetProcAddress(hinstComctl32,
459 "CreatePropertySheetPageW");
460 pPropertySheet = (void*)GetProcAddress(hinstComctl32, "PropertySheetW");
461 memset(&psp,0,sizeof(psp));
462 dlgdm = *pi->Devmode;
465 psp.dwSize = sizeof(psp);
466 psp.hInstance = PSDRV_hInstance;
467 psp.u.pszTemplate = PAPERW;
468 psp.u2.pszIcon = NULL;
469 psp.pfnDlgProc = PSDRV_PaperDlgProc;
470 psp.lParam = (LPARAM)&di;
471 hpsp[0] = pCreatePropertySheetPage(&psp);
473 memset(&psh, 0, sizeof(psh));
474 psh.dwSize = sizeof(psh);
475 psh.pszCaption = SetupW;
477 psh.hwndParent = hwnd;
478 psh.u3.phpage = hpsp;
480 pPropertySheet(&psh);
484 /* If DM_UPDATE is set, should write settings to environment and initialization file */
485 if(dwMode & DM_UPDATE)
486 FIXME("Mode DM_UPDATE. Just do the same as DM_COPY\n");
488 /* If DM_COPY is set, should write settings to lpdmOutput */
489 if((dwMode & DM_COPY) || (dwMode & DM_UPDATE)) {
492 DEVMODEA *dmA = DEVMODEdupWtoA( &pi->Devmode->dmPublic );
493 if (dmA) memcpy( lpdmOutput, dmA, dmA->dmSize + dmA->dmDriverExtra );
494 HeapFree( GetProcessHeap(), 0, dmA );
497 FIXME("lpdmOutput is NULL what should we do??\n");
501 /***********************************************************************
502 * PSDRV_DeviceCapabilities
504 * Retrieves the capabilities of a printer device driver.
507 * lpszDriver -- printer driver name
508 * lpszDevice -- printer name
509 * lpszPort -- port name
510 * fwCapability -- device capability
511 * lpszOutput -- output buffer
512 * lpDevMode -- device data buffer
515 * Result depends on the setting of fwCapability. -1 indicates failure.
517 DWORD PSDRV_DeviceCapabilities(LPSTR lpszDriver, LPCSTR lpszDevice, LPCSTR lpszPort,
518 WORD fwCapability, LPSTR lpszOutput, LPDEVMODEA lpDevMode)
523 pi = PSDRV_FindPrinterInfoA(lpszDevice);
525 TRACE("%s %s %s, %u, %p, %p\n", debugstr_a(lpszDriver), debugstr_a(lpszDevice),
526 debugstr_a(lpszPort), fwCapability, lpszOutput, lpDevMode);
529 ERR("no printer info for %s %s, return 0!\n",
530 debugstr_a(lpszDriver), debugstr_a(lpszDevice));
534 lpdm = &pi->Devmode->dmPublic;
535 if (lpDevMode) lpdm = GdiConvertToDevmodeW( lpDevMode );
537 switch(fwCapability) {
542 WORD *wp = (WORD *)lpszOutput;
545 LIST_FOR_EACH_ENTRY(ps, &pi->ppd->PageSizes, PAGESIZE, entry)
547 TRACE("DC_PAPERS: %u\n", ps->WinPage);
549 if(lpszOutput != NULL)
559 POINT16 *pt = (POINT16 *)lpszOutput;
562 LIST_FOR_EACH_ENTRY(ps, &pi->ppd->PageSizes, PAGESIZE, entry)
564 TRACE("DC_PAPERSIZE: %f x %f\n", ps->PaperDimension->x, ps->PaperDimension->y);
566 if(lpszOutput != NULL) {
567 pt->x = paper_size_from_points( ps->PaperDimension->x );
568 pt->y = paper_size_from_points( ps->PaperDimension->y );
579 char *cp = lpszOutput;
582 LIST_FOR_EACH_ENTRY(ps, &pi->ppd->PageSizes, PAGESIZE, entry)
584 TRACE("DC_PAPERNAMES: %s\n", debugstr_a(ps->FullName));
586 if(lpszOutput != NULL) {
587 lstrcpynA(cp, ps->FullName, 64);
596 ret = pi->ppd->LandscapeOrientation ? pi->ppd->LandscapeOrientation : 90;
602 WORD *wp = (WORD *)lpszOutput;
605 LIST_FOR_EACH_ENTRY( slot, &pi->ppd->InputSlots, INPUTSLOT, entry )
608 if (lpszOutput != NULL)
609 *wp++ = slot->WinBin;
618 char *cp = lpszOutput;
621 LIST_FOR_EACH_ENTRY( slot, &pi->ppd->InputSlots, INPUTSLOT, entry )
624 if (lpszOutput != NULL)
626 lstrcpynA( cp, slot->FullName, 24 );
635 FIXME("DC_BINADJUST: stub.\n");
636 ret = DCBA_FACEUPNONE;
639 case DC_ENUMRESOLUTIONS:
641 LONG *lp = (LONG*)lpszOutput;
643 if(lpszOutput != NULL) {
644 lp[0] = pi->ppd->DefaultResolution;
645 lp[1] = pi->ppd->DefaultResolution;
651 /* Windows returns 9999 too */
653 TRACE("DC_COPIES: returning 9999\n");
658 ret = lpdm->dmDriverVersion;
661 case DC_DATATYPE_PRODUCED:
662 FIXME("DATA_TYPE_PRODUCED: stub.\n");
663 ret = -1; /* simulate that the driver supports 'RAW' */
668 if(pi->ppd->DefaultDuplex && pi->ppd->DefaultDuplex->WinDuplex != 0)
670 TRACE("DC_DUPLEX: returning %d\n", ret);
673 case DC_EMF_COMPLIANT:
674 FIXME("DC_EMF_COMPLIANT: stub.\n");
675 ret = -1; /* simulate that the driver do not support EMF */
679 ret = lpdm->dmDriverExtra;
683 ret = lpdm->dmFields;
686 case DC_FILEDEPENDENCIES:
687 FIXME("DC_FILEDEPENDENCIES: stub.\n");
696 LIST_FOR_EACH_ENTRY(ps, &pi->ppd->PageSizes, PAGESIZE, entry)
698 if (ps->PaperDimension->x > x) x = ps->PaperDimension->x;
699 if (ps->PaperDimension->y > y) y = ps->PaperDimension->y;
701 ret = MAKELONG( paper_size_from_points(x), paper_size_from_points(y) );
708 float x = 1e6, y = 1e6;
710 LIST_FOR_EACH_ENTRY(ps, &pi->ppd->PageSizes, PAGESIZE, entry)
712 if (ps->PaperDimension->x < x) x = ps->PaperDimension->x;
713 if (ps->PaperDimension->y < y) y = ps->PaperDimension->y;
715 ret = MAKELONG( paper_size_from_points(x), paper_size_from_points(y) );
724 FIXME("DC_TRUETYPE: stub\n");
729 ret = lpdm->dmSpecVersion;
732 /* We'll just return false here, very few printers can collate anyway */
734 TRACE("DC_COLLATE: returning FALSE\n");
738 /* Printer supports colour printing - 1 if yes, 0 if no (Win2k/XP only) */
740 ret = pi->ppd->ColorDevice != CD_False;
743 /* Identification number of the printer manufacturer for use with ICM (Win9x only) */
744 case DC_MANUFACTURER:
745 FIXME("DC_MANUFACTURER: stub\n");
749 /* Identification number of the printer model for use with ICM (Win9x only) */
751 FIXME("DC_MODEL: stub\n");
755 /* Nonzero if the printer supports stapling, zero otherwise (Win2k/XP only) */
756 case DC_STAPLE: /* WINVER >= 0x0500 */
757 FIXME("DC_STAPLE: stub\n");
761 /* Returns an array of 64-character string buffers containing the names of the paper forms
762 * available for use, unless pOutput is NULL. The return value is the number of paper forms.
765 case DC_MEDIAREADY: /* WINVER >= 0x0500 */
766 FIXME("DC_MEDIAREADY: stub\n");
770 /* Returns an array of 64-character string buffers containing the names of the supported
771 * media types, unless pOutput is NULL. The return value is the number of supported.
772 * media types (XP only)
774 case DC_MEDIATYPENAMES: /* WINVER >= 0x0501 */
775 FIXME("DC_MEDIATYPENAMES: stub\n");
779 /* Returns an array of DWORD values which represent the supported media types, unless
780 * pOutput is NULL. The return value is the number of supported media types. (XP only)
782 case DC_MEDIATYPES: /* WINVER >= 0x0501 */
783 FIXME("DC_MEDIATYPES: stub\n");
787 /* Returns an array of DWORD values, each representing a supported number of document
788 * pages per printed page, unless pOutput is NULL. The return value is the number of
789 * array entries. (Win2k/XP only)
792 FIXME("DC_NUP: stub\n");
796 /* Returns an array of 32-character string buffers containing a list of printer description
797 * languages supported by the printer, unless pOutput is NULL. The return value is
798 * number of array entries. (Win2k/XP only)
801 case DC_PERSONALITY: /* WINVER >= 0x0500 */
802 FIXME("DC_PERSONALITY: stub\n");
806 /* Returns the amount of printer memory in kilobytes. (Win2k/XP only) */
807 case DC_PRINTERMEM: /* WINVER >= 0x0500 */
808 FIXME("DC_PRINTERMEM: stub\n");
812 /* Returns the printer's print rate in PRINTRATEUNIT units. (Win2k/XP only) */
813 case DC_PRINTRATE: /* WINVER >= 0x0500 */
814 FIXME("DC_PRINTRATE: stub\n");
818 /* Returns the printer's print rate in pages per minute. (Win2k/XP only) */
819 case DC_PRINTRATEPPM: /* WINVER >= 0x0500 */
820 FIXME("DC_PRINTRATEPPM: stub\n");
824 /* Returns the printer rate unit used for DC_PRINTRATE, which is one of
825 * PRINTRATEUNIT_{CPS,IPM,LPM,PPM} (Win2k/XP only)
827 case DC_PRINTRATEUNIT: /* WINVER >= 0x0500 */
828 FIXME("DC_PRINTRATEUNIT: stub\n");
833 FIXME("Unsupported capability %d\n", fwCapability);
837 if (lpDevMode) HeapFree( GetProcessHeap(), 0, lpdm );
845 HPROPSHEETPAGE hPages[10];
848 INT PSDRV_ExtDeviceModePropSheet(HWND hwnd, LPSTR lpszDevice, LPSTR lpszPort,
851 EDMPS *ps = pPropSheet;
854 psp->dwSize = sizeof(psp);
855 psp->hInstance = 0x1234;