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 /************************************************************************
52 * Updates dm1 with some fields from dm2
55 void PSDRV_MergeDevmodes( PSDRV_DEVMODE
*dm1
, PSDRV_DEVMODE
*dm2
, PRINTERINFO
*pi
)
57 /* some sanity checks here on dm2 */
59 if(dm2
->dmPublic
.dmFields
& DM_ORIENTATION
) {
60 dm1
->dmPublic
.u1
.s1
.dmOrientation
= dm2
->dmPublic
.u1
.s1
.dmOrientation
;
61 TRACE("Changing orientation to %d (%s)\n",
62 dm1
->dmPublic
.u1
.s1
.dmOrientation
,
63 dm1
->dmPublic
.u1
.s1
.dmOrientation
== DMORIENT_PORTRAIT
?
65 (dm1
->dmPublic
.u1
.s1
.dmOrientation
== DMORIENT_LANDSCAPE
?
66 "Landscape" : "unknown"));
69 /* NB PaperWidth is always < PaperLength */
70 if(dm2
->dmPublic
.dmFields
& DM_PAPERSIZE
) {
73 LIST_FOR_EACH_ENTRY(page
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
) {
74 if(page
->WinPage
== dm2
->dmPublic
.u1
.s1
.dmPaperSize
)
77 if(&page
->entry
!= &pi
->ppd
->PageSizes
) {
78 dm1
->dmPublic
.u1
.s1
.dmPaperSize
= dm2
->dmPublic
.u1
.s1
.dmPaperSize
;
79 dm1
->dmPublic
.u1
.s1
.dmPaperWidth
= paper_size_from_points( page
->PaperDimension
->x
);
80 dm1
->dmPublic
.u1
.s1
.dmPaperLength
= paper_size_from_points( page
->PaperDimension
->y
);
81 dm1
->dmPublic
.dmFields
&= ~(DM_PAPERLENGTH
| DM_PAPERWIDTH
);
82 dm1
->dmPublic
.dmFields
|= DM_PAPERSIZE
;
83 TRACE("Changing page to %s %d x %d\n", page
->FullName
,
84 dm1
->dmPublic
.u1
.s1
.dmPaperWidth
,
85 dm1
->dmPublic
.u1
.s1
.dmPaperLength
);
87 TRACE("Trying to change to unsupported pagesize %d\n",
88 dm2
->dmPublic
.u1
.s1
.dmPaperSize
);
90 } else if((dm2
->dmPublic
.dmFields
& DM_PAPERLENGTH
) &&
91 (dm2
->dmPublic
.dmFields
& DM_PAPERWIDTH
)) {
92 dm1
->dmPublic
.u1
.s1
.dmPaperLength
= dm2
->dmPublic
.u1
.s1
.dmPaperLength
;
93 dm1
->dmPublic
.u1
.s1
.dmPaperWidth
= dm2
->dmPublic
.u1
.s1
.dmPaperWidth
;
94 TRACE("Changing PaperLength|Width to %dx%d\n",
95 dm2
->dmPublic
.u1
.s1
.dmPaperLength
,
96 dm2
->dmPublic
.u1
.s1
.dmPaperWidth
);
97 dm1
->dmPublic
.dmFields
&= ~DM_PAPERSIZE
;
98 dm1
->dmPublic
.dmFields
|= (DM_PAPERLENGTH
| DM_PAPERWIDTH
);
99 } else if(dm2
->dmPublic
.dmFields
& (DM_PAPERLENGTH
| DM_PAPERWIDTH
)) {
100 /* You might think that this would be allowed if dm1 is in custom size
101 mode, but apparently Windows reverts to standard paper mode even in
103 FIXME("Trying to change only paperlength or paperwidth\n");
104 dm1
->dmPublic
.dmFields
&= ~(DM_PAPERLENGTH
| DM_PAPERWIDTH
);
105 dm1
->dmPublic
.dmFields
|= DM_PAPERSIZE
;
108 if(dm2
->dmPublic
.dmFields
& DM_SCALE
) {
109 dm1
->dmPublic
.u1
.s1
.dmScale
= dm2
->dmPublic
.u1
.s1
.dmScale
;
110 TRACE("Changing Scale to %d\n", dm2
->dmPublic
.u1
.s1
.dmScale
);
113 if(dm2
->dmPublic
.dmFields
& DM_COPIES
) {
114 dm1
->dmPublic
.u1
.s1
.dmCopies
= dm2
->dmPublic
.u1
.s1
.dmCopies
;
115 TRACE("Changing Copies to %d\n", dm2
->dmPublic
.u1
.s1
.dmCopies
);
118 if (dm2
->dmPublic
.dmFields
& DM_DEFAULTSOURCE
)
122 LIST_FOR_EACH_ENTRY( slot
, &pi
->ppd
->InputSlots
, INPUTSLOT
, entry
)
123 if(slot
->WinBin
== dm2
->dmPublic
.u1
.s1
.dmDefaultSource
)
126 if (&slot
->entry
!= &pi
->ppd
->InputSlots
)
128 dm1
->dmPublic
.u1
.s1
.dmDefaultSource
= dm2
->dmPublic
.u1
.s1
.dmDefaultSource
;
129 TRACE("Changing bin to '%s'\n", slot
->FullName
);
132 TRACE("Trying to change to unsupported bin %d\n", dm2
->dmPublic
.u1
.s1
.dmDefaultSource
);
135 if (dm2
->dmPublic
.dmFields
& DM_DEFAULTSOURCE
)
136 dm1
->dmPublic
.u1
.s1
.dmDefaultSource
= dm2
->dmPublic
.u1
.s1
.dmDefaultSource
;
137 if (dm2
->dmPublic
.dmFields
& DM_PRINTQUALITY
)
138 dm1
->dmPublic
.u1
.s1
.dmPrintQuality
= dm2
->dmPublic
.u1
.s1
.dmPrintQuality
;
139 if (dm2
->dmPublic
.dmFields
& DM_COLOR
)
140 dm1
->dmPublic
.dmColor
= dm2
->dmPublic
.dmColor
;
141 if (dm2
->dmPublic
.dmFields
& DM_DUPLEX
&& pi
->ppd
->DefaultDuplex
&& pi
->ppd
->DefaultDuplex
->WinDuplex
!= 0)
142 dm1
->dmPublic
.dmDuplex
= dm2
->dmPublic
.dmDuplex
;
143 if (dm2
->dmPublic
.dmFields
& DM_YRESOLUTION
)
144 dm1
->dmPublic
.dmYResolution
= dm2
->dmPublic
.dmYResolution
;
145 if (dm2
->dmPublic
.dmFields
& DM_TTOPTION
)
146 dm1
->dmPublic
.dmTTOption
= dm2
->dmPublic
.dmTTOption
;
147 if (dm2
->dmPublic
.dmFields
& DM_COLLATE
)
148 dm1
->dmPublic
.dmCollate
= dm2
->dmPublic
.dmCollate
;
149 if (dm2
->dmPublic
.dmFields
& DM_FORMNAME
)
150 lstrcpynA((LPSTR
)dm1
->dmPublic
.dmFormName
, (LPCSTR
)dm2
->dmPublic
.dmFormName
, CCHFORMNAME
);
151 if (dm2
->dmPublic
.dmFields
& DM_BITSPERPEL
)
152 dm1
->dmPublic
.dmBitsPerPel
= dm2
->dmPublic
.dmBitsPerPel
;
153 if (dm2
->dmPublic
.dmFields
& DM_PELSWIDTH
)
154 dm1
->dmPublic
.dmPelsWidth
= dm2
->dmPublic
.dmPelsWidth
;
155 if (dm2
->dmPublic
.dmFields
& DM_PELSHEIGHT
)
156 dm1
->dmPublic
.dmPelsHeight
= dm2
->dmPublic
.dmPelsHeight
;
157 if (dm2
->dmPublic
.dmFields
& DM_DISPLAYFLAGS
)
158 dm1
->dmPublic
.u2
.dmDisplayFlags
= dm2
->dmPublic
.u2
.dmDisplayFlags
;
159 if (dm2
->dmPublic
.dmFields
& DM_DISPLAYFREQUENCY
)
160 dm1
->dmPublic
.dmDisplayFrequency
= dm2
->dmPublic
.dmDisplayFrequency
;
161 if (dm2
->dmPublic
.dmFields
& DM_POSITION
)
162 dm1
->dmPublic
.u1
.s2
.dmPosition
= dm2
->dmPublic
.u1
.s2
.dmPosition
;
163 if (dm2
->dmPublic
.dmFields
& DM_LOGPIXELS
)
164 dm1
->dmPublic
.dmLogPixels
= dm2
->dmPublic
.dmLogPixels
;
165 if (dm2
->dmPublic
.dmFields
& DM_ICMMETHOD
)
166 dm1
->dmPublic
.dmICMMethod
= dm2
->dmPublic
.dmICMMethod
;
167 if (dm2
->dmPublic
.dmFields
& DM_ICMINTENT
)
168 dm1
->dmPublic
.dmICMIntent
= dm2
->dmPublic
.dmICMIntent
;
169 if (dm2
->dmPublic
.dmFields
& DM_MEDIATYPE
)
170 dm1
->dmPublic
.dmMediaType
= dm2
->dmPublic
.dmMediaType
;
171 if (dm2
->dmPublic
.dmFields
& DM_DITHERTYPE
)
172 dm1
->dmPublic
.dmDitherType
= dm2
->dmPublic
.dmDitherType
;
173 if (dm2
->dmPublic
.dmFields
& DM_PANNINGWIDTH
)
174 dm1
->dmPublic
.dmPanningWidth
= dm2
->dmPublic
.dmPanningWidth
;
175 if (dm2
->dmPublic
.dmFields
& DM_PANNINGHEIGHT
)
176 dm1
->dmPublic
.dmPanningHeight
= dm2
->dmPublic
.dmPanningHeight
;
185 PSDRV_DEVMODE
*dlgdm
;
188 /****************************************************************
191 * Dialog proc for 'Paper' propsheet
193 static INT_PTR CALLBACK
PSDRV_PaperDlgProc(HWND hwnd
, UINT msg
,
194 WPARAM wParam
, LPARAM lParam
)
203 di
= (PSDRV_DLGINFO
*)((PROPSHEETPAGEA
*)lParam
)->lParam
;
204 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LONG_PTR
)di
);
207 LIST_FOR_EACH_ENTRY(ps
, &di
->pi
->ppd
->PageSizes
, PAGESIZE
, entry
) {
208 SendDlgItemMessageA(hwnd
, IDD_PAPERS
, LB_INSERTSTRING
, i
,
209 (LPARAM
)ps
->FullName
);
210 if(di
->pi
->Devmode
->dmPublic
.u1
.s1
.dmPaperSize
== ps
->WinPage
)
214 SendDlgItemMessageA(hwnd
, IDD_PAPERS
, LB_SETCURSEL
, Cursel
, 0);
216 CheckRadioButton(hwnd
, IDD_ORIENT_PORTRAIT
, IDD_ORIENT_LANDSCAPE
,
217 di
->pi
->Devmode
->dmPublic
.u1
.s1
.dmOrientation
==
218 DMORIENT_PORTRAIT
? IDD_ORIENT_PORTRAIT
:
219 IDD_ORIENT_LANDSCAPE
);
221 if (list_empty( &di
->pi
->ppd
->Duplexes
))
223 ShowWindow(GetDlgItem(hwnd
, IDD_DUPLEX
), SW_HIDE
);
224 ShowWindow(GetDlgItem(hwnd
, IDD_DUPLEX_NAME
), SW_HIDE
);
229 LIST_FOR_EACH_ENTRY( duplex
, &di
->pi
->ppd
->Duplexes
, DUPLEX
, entry
)
231 SendDlgItemMessageA(hwnd
, IDD_DUPLEX
, CB_INSERTSTRING
, i
,
232 (LPARAM
)(duplex
->FullName
? duplex
->FullName
: duplex
->Name
));
233 if(di
->pi
->Devmode
->dmPublic
.dmDuplex
== duplex
->WinDuplex
)
237 SendDlgItemMessageA(hwnd
, IDD_DUPLEX
, CB_SETCURSEL
, Cursel
, 0);
242 di
= (PSDRV_DLGINFO
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
243 switch(LOWORD(wParam
)) {
245 if(HIWORD(wParam
) == LBN_SELCHANGE
) {
246 Cursel
= SendDlgItemMessageA(hwnd
, LOWORD(wParam
), LB_GETCURSEL
, 0, 0);
248 LIST_FOR_EACH_ENTRY(ps
, &di
->pi
->ppd
->PageSizes
, PAGESIZE
, entry
) {
249 if(i
>= Cursel
) break;
252 TRACE("Setting pagesize to item %d Winpage = %d\n", Cursel
, ps
->WinPage
);
253 di
->dlgdm
->dmPublic
.u1
.s1
.dmPaperSize
= ps
->WinPage
;
254 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, 0, 0);
257 case IDD_ORIENT_PORTRAIT
:
258 case IDD_ORIENT_LANDSCAPE
:
259 TRACE("Setting orientation to %s\n", wParam
== IDD_ORIENT_PORTRAIT
?
260 "portrait" : "landscape");
261 di
->dlgdm
->dmPublic
.u1
.s1
.dmOrientation
= wParam
== IDD_ORIENT_PORTRAIT
?
262 DMORIENT_PORTRAIT
: DMORIENT_LANDSCAPE
;
263 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, 0, 0);
266 if(HIWORD(wParam
) == CBN_SELCHANGE
) {
267 Cursel
= SendDlgItemMessageA(hwnd
, LOWORD(wParam
), CB_GETCURSEL
, 0, 0);
269 LIST_FOR_EACH_ENTRY( duplex
, &di
->pi
->ppd
->Duplexes
, DUPLEX
, entry
)
271 if (i
>= Cursel
) break;
274 TRACE("Setting duplex to item %d Winduplex = %d\n", Cursel
, duplex
->WinDuplex
);
275 di
->dlgdm
->dmPublic
.dmDuplex
= duplex
->WinDuplex
;
276 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, 0, 0);
284 NMHDR
*nmhdr
= (NMHDR
*)lParam
;
285 di
= (PSDRV_DLGINFO
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
286 switch(nmhdr
->code
) {
288 *di
->pi
->Devmode
= *di
->dlgdm
;
289 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, PSNRET_NOERROR
);
305 static void (WINAPI
*pInitCommonControls
) (void);
306 static HPROPSHEETPAGE (WINAPI
*pCreatePropertySheetPage
) (LPCPROPSHEETPAGEW
);
307 static int (WINAPI
*pPropertySheet
) (LPCPROPSHEETHEADERW
);
309 static PRINTERINFO
*PSDRV_FindPrinterInfoA(LPCSTR name
)
311 int len
= MultiByteToWideChar( CP_ACP
, 0, name
, -1, NULL
, 0 );
312 WCHAR
*nameW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
315 MultiByteToWideChar( CP_ACP
, 0, name
, -1, nameW
, len
);
316 pi
= PSDRV_FindPrinterInfo( nameW
);
317 HeapFree( GetProcessHeap(), 0, nameW
);
322 /***********************************************************
325 * Creates an ascii copy of supplied devmode on the process heap
327 * Copied from dlls/winspool/info.c until full unicodification
329 static DEVMODEA
*DEVMODEdupWtoA( const DEVMODEW
*dmW
)
334 /* there is no pointer dereference here, if your code checking tool complains it's broken */
335 ptrdiff_t off_formname
= (const char *)dmW
->dmFormName
- (const char *)dmW
;
337 if (!dmW
) return NULL
;
338 formname
= (dmW
->dmSize
> off_formname
);
339 size
= dmW
->dmSize
- CCHDEVICENAME
- (formname
? CCHFORMNAME
: 0);
340 dmA
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, size
+ dmW
->dmDriverExtra
);
341 WideCharToMultiByte( CP_ACP
, 0, dmW
->dmDeviceName
, -1, (LPSTR
)dmA
->dmDeviceName
,
342 CCHDEVICENAME
, NULL
, NULL
);
345 memcpy( &dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
346 dmW
->dmSize
- CCHDEVICENAME
* sizeof(WCHAR
) );
350 memcpy( &dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
351 off_formname
- CCHDEVICENAME
* sizeof(WCHAR
) );
352 WideCharToMultiByte( CP_ACP
, 0, dmW
->dmFormName
, -1, (LPSTR
)dmA
->dmFormName
,
353 CCHFORMNAME
, NULL
, NULL
);
354 memcpy( &dmA
->dmLogPixels
, &dmW
->dmLogPixels
, dmW
->dmSize
-
355 (off_formname
+ CCHFORMNAME
* sizeof(WCHAR
)) );
358 memcpy( (char *)dmA
+ dmA
->dmSize
, (const char *)dmW
+ dmW
->dmSize
,
359 dmW
->dmDriverExtra
);
363 /******************************************************************
364 * PSDRV_ExtDeviceMode
366 * Retrieves or modifies device-initialization information for the PostScript
367 * driver, or displays a driver-supplied dialog box for configuring the driver.
370 * lpszDriver -- Driver name
371 * hwnd -- Parent window for the dialog box
372 * lpdmOutput -- Address of a DEVMODE structure for writing initialization information
373 * lpszDevice -- Device name
374 * lpszPort -- Port name
375 * lpdmInput -- Address of a DEVMODE structure for reading initialization information
376 * lpProfile -- Name of initialization file, defaults to WIN.INI if NULL
377 * wMode -- Operation to perform. Can be a combination if > 0.
378 * (0) -- Returns number of bytes required by DEVMODE structure
379 * DM_UPDATE (1) -- Write current settings to environment and initialization file
380 * DM_COPY (2) -- Write current settings to lpdmOutput
381 * DM_PROMPT (4) -- Presents the driver's modal dialog box (USER.240)
382 * DM_MODIFY (8) -- Changes current settings according to lpdmInput before any other operation
385 * Returns size of DEVMODE structure if wMode is 0. Otherwise, IDOK is returned for success
386 * for both dialog and non-dialog operations. IDCANCEL is returned if the dialog box was cancelled.
387 * A return value less than zero is returned if a non-dialog operation fails.
391 * Just returns default devmode at the moment. No use of initialization file.
393 INT
PSDRV_ExtDeviceMode(LPSTR lpszDriver
, HWND hwnd
, LPDEVMODEA lpdmOutput
,
394 LPSTR lpszDevice
, LPSTR lpszPort
, LPDEVMODEA lpdmInput
,
395 LPSTR lpszProfile
, DWORD dwMode
)
397 PRINTERINFO
*pi
= PSDRV_FindPrinterInfoA(lpszDevice
);
400 TRACE("(Driver=%s, hwnd=%p, devOut=%p, Device='%s', Port='%s', devIn=%p, Profile='%s', Mode=%04x)\n",
401 lpszDriver
, hwnd
, lpdmOutput
, lpszDevice
, lpszPort
, lpdmInput
, debugstr_a(lpszProfile
), dwMode
);
403 /* If dwMode == 0, return size of DEVMODE structure */
405 return pi
->Devmode
->dmPublic
.dmSize
+ pi
->Devmode
->dmPublic
.dmDriverExtra
- CCHDEVICENAME
- CCHFORMNAME
;
407 /* If DM_MODIFY is set, change settings in accordance with lpdmInput */
408 if((dwMode
& DM_MODIFY
) && lpdmInput
)
410 DEVMODEW
*dmW
= GdiConvertToDevmodeW( lpdmInput
);
411 TRACE("DM_MODIFY set. devIn->dmFields = %08x\n", lpdmInput
->dmFields
);
412 if (dmW
) PSDRV_MergeDevmodes(pi
->Devmode
, (PSDRV_DEVMODE
*)dmW
, pi
);
413 HeapFree( GetProcessHeap(), 0, dmW
);
416 /* If DM_PROMPT is set, present modal dialog box */
417 if(dwMode
& DM_PROMPT
) {
418 HINSTANCE hinstComctl32
;
419 HPROPSHEETPAGE hpsp
[1];
421 PROPSHEETHEADERW psh
;
424 static const WCHAR PAPERW
[] = {'P','A','P','E','R','\0'};
425 static const WCHAR SetupW
[] = {'S','e','t','u','p','\0'};
427 hinstComctl32
= LoadLibraryA("comctl32.dll");
428 pInitCommonControls
= (void*)GetProcAddress(hinstComctl32
,
429 "InitCommonControls");
430 pCreatePropertySheetPage
= (void*)GetProcAddress(hinstComctl32
,
431 "CreatePropertySheetPageW");
432 pPropertySheet
= (void*)GetProcAddress(hinstComctl32
, "PropertySheetW");
433 memset(&psp
,0,sizeof(psp
));
434 dlgdm
= *pi
->Devmode
;
437 psp
.dwSize
= sizeof(psp
);
438 psp
.hInstance
= PSDRV_hInstance
;
439 psp
.u
.pszTemplate
= PAPERW
;
440 psp
.u2
.pszIcon
= NULL
;
441 psp
.pfnDlgProc
= PSDRV_PaperDlgProc
;
442 psp
.lParam
= (LPARAM
)&di
;
443 hpsp
[0] = pCreatePropertySheetPage(&psp
);
445 memset(&psh
, 0, sizeof(psh
));
446 psh
.dwSize
= sizeof(psh
);
447 psh
.pszCaption
= SetupW
;
449 psh
.hwndParent
= hwnd
;
450 psh
.u3
.phpage
= hpsp
;
452 pPropertySheet(&psh
);
456 /* If DM_UPDATE is set, should write settings to environment and initialization file */
457 if(dwMode
& DM_UPDATE
)
458 FIXME("Mode DM_UPDATE. Just do the same as DM_COPY\n");
460 /* If DM_COPY is set, should write settings to lpdmOutput */
461 if((dwMode
& DM_COPY
) || (dwMode
& DM_UPDATE
)) {
464 DEVMODEA
*dmA
= DEVMODEdupWtoA( &pi
->Devmode
->dmPublic
);
465 if (dmA
) memcpy( lpdmOutput
, dmA
, dmA
->dmSize
+ dmA
->dmDriverExtra
);
466 HeapFree( GetProcessHeap(), 0, dmA
);
469 FIXME("lpdmOutput is NULL what should we do??\n");
473 /***********************************************************************
474 * PSDRV_DeviceCapabilities
476 * Retrieves the capabilities of a printer device driver.
479 * lpszDriver -- printer driver name
480 * lpszDevice -- printer name
481 * lpszPort -- port name
482 * fwCapability -- device capability
483 * lpszOutput -- output buffer
484 * lpDevMode -- device data buffer
487 * Result depends on the setting of fwCapability. -1 indicates failure.
489 DWORD
PSDRV_DeviceCapabilities(LPSTR lpszDriver
, LPCSTR lpszDevice
, LPCSTR lpszPort
,
490 WORD fwCapability
, LPSTR lpszOutput
, LPDEVMODEA lpDevMode
)
495 pi
= PSDRV_FindPrinterInfoA(lpszDevice
);
497 TRACE("%s %s %s, %u, %p, %p\n", debugstr_a(lpszDriver
), debugstr_a(lpszDevice
),
498 debugstr_a(lpszPort
), fwCapability
, lpszOutput
, lpDevMode
);
501 ERR("no printer info for %s %s, return 0!\n",
502 debugstr_a(lpszDriver
), debugstr_a(lpszDevice
));
506 lpdm
= &pi
->Devmode
->dmPublic
;
507 if (lpDevMode
) lpdm
= GdiConvertToDevmodeW( lpDevMode
);
509 switch(fwCapability
) {
514 WORD
*wp
= (WORD
*)lpszOutput
;
517 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
519 TRACE("DC_PAPERS: %u\n", ps
->WinPage
);
521 if(lpszOutput
!= NULL
)
531 POINT16
*pt
= (POINT16
*)lpszOutput
;
534 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
536 TRACE("DC_PAPERSIZE: %f x %f\n", ps
->PaperDimension
->x
, ps
->PaperDimension
->y
);
538 if(lpszOutput
!= NULL
) {
539 pt
->x
= paper_size_from_points( ps
->PaperDimension
->x
);
540 pt
->y
= paper_size_from_points( ps
->PaperDimension
->y
);
551 char *cp
= lpszOutput
;
554 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
556 TRACE("DC_PAPERNAMES: %s\n", debugstr_a(ps
->FullName
));
558 if(lpszOutput
!= NULL
) {
559 lstrcpynA(cp
, ps
->FullName
, 64);
568 ret
= pi
->ppd
->LandscapeOrientation
? pi
->ppd
->LandscapeOrientation
: 90;
574 WORD
*wp
= (WORD
*)lpszOutput
;
577 LIST_FOR_EACH_ENTRY( slot
, &pi
->ppd
->InputSlots
, INPUTSLOT
, entry
)
580 if (lpszOutput
!= NULL
)
581 *wp
++ = slot
->WinBin
;
590 char *cp
= lpszOutput
;
593 LIST_FOR_EACH_ENTRY( slot
, &pi
->ppd
->InputSlots
, INPUTSLOT
, entry
)
596 if (lpszOutput
!= NULL
)
598 lstrcpynA( cp
, slot
->FullName
, 24 );
607 FIXME("DC_BINADJUST: stub.\n");
608 ret
= DCBA_FACEUPNONE
;
611 case DC_ENUMRESOLUTIONS
:
613 LONG
*lp
= (LONG
*)lpszOutput
;
615 if(lpszOutput
!= NULL
) {
616 lp
[0] = pi
->ppd
->DefaultResolution
;
617 lp
[1] = pi
->ppd
->DefaultResolution
;
623 /* Windows returns 9999 too */
625 TRACE("DC_COPIES: returning 9999\n");
630 ret
= lpdm
->dmDriverVersion
;
633 case DC_DATATYPE_PRODUCED
:
634 FIXME("DATA_TYPE_PRODUCED: stub.\n");
635 ret
= -1; /* simulate that the driver supports 'RAW' */
640 if(pi
->ppd
->DefaultDuplex
&& pi
->ppd
->DefaultDuplex
->WinDuplex
!= 0)
642 TRACE("DC_DUPLEX: returning %d\n", ret
);
645 case DC_EMF_COMPLIANT
:
646 FIXME("DC_EMF_COMPLIANT: stub.\n");
647 ret
= -1; /* simulate that the driver do not support EMF */
651 ret
= lpdm
->dmDriverExtra
;
655 ret
= lpdm
->dmFields
;
658 case DC_FILEDEPENDENCIES
:
659 FIXME("DC_FILEDEPENDENCIES: stub.\n");
668 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
670 if (ps
->PaperDimension
->x
> x
) x
= ps
->PaperDimension
->x
;
671 if (ps
->PaperDimension
->y
> y
) y
= ps
->PaperDimension
->y
;
673 ret
= MAKELONG( paper_size_from_points(x
), paper_size_from_points(y
) );
680 float x
= 1e6
, y
= 1e6
;
682 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
684 if (ps
->PaperDimension
->x
< x
) x
= ps
->PaperDimension
->x
;
685 if (ps
->PaperDimension
->y
< y
) y
= ps
->PaperDimension
->y
;
687 ret
= MAKELONG( paper_size_from_points(x
), paper_size_from_points(y
) );
696 FIXME("DC_TRUETYPE: stub\n");
701 ret
= lpdm
->dmSpecVersion
;
704 /* We'll just return false here, very few printers can collate anyway */
706 TRACE("DC_COLLATE: returning FALSE\n");
710 /* Printer supports colour printing - 1 if yes, 0 if no (Win2k/XP only) */
712 ret
= (pi
->ppd
->ColorDevice
!= CD_False
) ? TRUE
: FALSE
;
715 /* Identification number of the printer manufacturer for use with ICM (Win9x only) */
716 case DC_MANUFACTURER
:
717 FIXME("DC_MANUFACTURER: stub\n");
721 /* Identification number of the printer model for use with ICM (Win9x only) */
723 FIXME("DC_MODEL: stub\n");
727 /* Nonzero if the printer supports stapling, zero otherwise (Win2k/XP only) */
728 case DC_STAPLE
: /* WINVER >= 0x0500 */
729 FIXME("DC_STAPLE: stub\n");
733 /* Returns an array of 64-character string buffers containing the names of the paper forms
734 * available for use, unless pOutput is NULL. The return value is the number of paper forms.
737 case DC_MEDIAREADY
: /* WINVER >= 0x0500 */
738 FIXME("DC_MEDIAREADY: stub\n");
742 /* Returns an array of 64-character string buffers containing the names of the supported
743 * media types, unless pOutput is NULL. The return value is the number of supported.
744 * media types (XP only)
746 case DC_MEDIATYPENAMES
: /* WINVER >= 0x0501 */
747 FIXME("DC_MEDIATYPENAMES: stub\n");
751 /* Returns an array of DWORD values which represent the supported media types, unless
752 * pOutput is NULL. The return value is the number of supported media types. (XP only)
754 case DC_MEDIATYPES
: /* WINVER >= 0x0501 */
755 FIXME("DC_MEDIATYPES: stub\n");
759 /* Returns an array of DWORD values, each representing a supported number of document
760 * pages per printed page, unless pOutput is NULL. The return value is the number of
761 * array entries. (Win2k/XP only)
764 FIXME("DC_NUP: stub\n");
768 /* Returns an array of 32-character string buffers containing a list of printer description
769 * languages supported by the printer, unless pOutput is NULL. The return value is
770 * number of array entries. (Win2k/XP only)
773 case DC_PERSONALITY
: /* WINVER >= 0x0500 */
774 FIXME("DC_PERSONALITY: stub\n");
778 /* Returns the amount of printer memory in kilobytes. (Win2k/XP only) */
779 case DC_PRINTERMEM
: /* WINVER >= 0x0500 */
780 FIXME("DC_PRINTERMEM: stub\n");
784 /* Returns the printer's print rate in PRINTRATEUNIT units. (Win2k/XP only) */
785 case DC_PRINTRATE
: /* WINVER >= 0x0500 */
786 FIXME("DC_PRINTRATE: stub\n");
790 /* Returns the printer's print rate in pages per minute. (Win2k/XP only) */
791 case DC_PRINTRATEPPM
: /* WINVER >= 0x0500 */
792 FIXME("DC_PRINTRATEPPM: stub\n");
796 /* Returns the printer rate unit used for DC_PRINTRATE, which is one of
797 * PRINTRATEUNIT_{CPS,IPM,LPM,PPM} (Win2k/XP only)
799 case DC_PRINTRATEUNIT
: /* WINVER >= 0x0500 */
800 FIXME("DC_PRINTRATEUNIT: stub\n");
805 FIXME("Unsupported capability %d\n", fwCapability
);
809 if (lpDevMode
) HeapFree( GetProcessHeap(), 0, lpdm
);
817 HPROPSHEETPAGE hPages
[10];
820 INT
PSDRV_ExtDeviceModePropSheet(HWND hwnd
, LPSTR lpszDevice
, LPSTR lpszPort
,
823 EDMPS
*ps
= pPropSheet
;
826 psp
->dwSize
= sizeof(psp
);
827 psp
->hInstance
= 0x1234;