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 void (WINAPI
*pInitCommonControls
) (void);
337 static HPROPSHEETPAGE (WINAPI
*pCreatePropertySheetPage
) (LPCPROPSHEETPAGEW
);
338 static int (WINAPI
*pPropertySheet
) (LPCPROPSHEETHEADERW
);
340 static PRINTERINFO
*PSDRV_FindPrinterInfoA(LPCSTR name
)
342 int len
= MultiByteToWideChar( CP_ACP
, 0, name
, -1, NULL
, 0 );
343 WCHAR
*nameW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
346 MultiByteToWideChar( CP_ACP
, 0, name
, -1, nameW
, len
);
347 pi
= PSDRV_FindPrinterInfo( nameW
);
348 HeapFree( GetProcessHeap(), 0, nameW
);
353 /***********************************************************
356 * Creates an ascii copy of supplied devmode on the process heap
358 * Copied from dlls/winspool/info.c until full unicodification
360 static DEVMODEA
*DEVMODEdupWtoA( const DEVMODEW
*dmW
)
365 /* there is no pointer dereference here, if your code checking tool complains it's broken */
366 ptrdiff_t off_formname
= (const char *)dmW
->dmFormName
- (const char *)dmW
;
368 if (!dmW
) return NULL
;
369 formname
= (dmW
->dmSize
> off_formname
);
370 size
= dmW
->dmSize
- CCHDEVICENAME
- (formname
? CCHFORMNAME
: 0);
371 dmA
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, size
+ dmW
->dmDriverExtra
);
372 WideCharToMultiByte( CP_ACP
, 0, dmW
->dmDeviceName
, -1, (LPSTR
)dmA
->dmDeviceName
,
373 CCHDEVICENAME
, NULL
, NULL
);
376 memcpy( &dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
377 dmW
->dmSize
- CCHDEVICENAME
* sizeof(WCHAR
) );
381 memcpy( &dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
382 off_formname
- CCHDEVICENAME
* sizeof(WCHAR
) );
383 WideCharToMultiByte( CP_ACP
, 0, dmW
->dmFormName
, -1, (LPSTR
)dmA
->dmFormName
,
384 CCHFORMNAME
, NULL
, NULL
);
385 memcpy( &dmA
->dmLogPixels
, &dmW
->dmLogPixels
, dmW
->dmSize
-
386 (off_formname
+ CCHFORMNAME
* sizeof(WCHAR
)) );
389 memcpy( (char *)dmA
+ dmA
->dmSize
, (const char *)dmW
+ dmW
->dmSize
,
390 dmW
->dmDriverExtra
);
394 /******************************************************************
395 * PSDRV_ExtDeviceMode
397 * Retrieves or modifies device-initialization information for the PostScript
398 * driver, or displays a driver-supplied dialog box for configuring the driver.
401 * lpszDriver -- Driver name
402 * hwnd -- Parent window for the dialog box
403 * lpdmOutput -- Address of a DEVMODE structure for writing initialization information
404 * lpszDevice -- Device name
405 * lpszPort -- Port name
406 * lpdmInput -- Address of a DEVMODE structure for reading initialization information
407 * lpProfile -- Name of initialization file, defaults to WIN.INI if NULL
408 * wMode -- Operation to perform. Can be a combination if > 0.
409 * (0) -- Returns number of bytes required by DEVMODE structure
410 * DM_UPDATE (1) -- Write current settings to environment and initialization file
411 * DM_COPY (2) -- Write current settings to lpdmOutput
412 * DM_PROMPT (4) -- Presents the driver's modal dialog box (USER.240)
413 * DM_MODIFY (8) -- Changes current settings according to lpdmInput before any other operation
416 * Returns size of DEVMODE structure if wMode is 0. Otherwise, IDOK is returned for success
417 * for both dialog and non-dialog operations. IDCANCEL is returned if the dialog box was cancelled.
418 * A return value less than zero is returned if a non-dialog operation fails.
422 * Just returns default devmode at the moment. No use of initialization file.
424 INT
PSDRV_ExtDeviceMode(LPSTR lpszDriver
, HWND hwnd
, LPDEVMODEA lpdmOutput
,
425 LPSTR lpszDevice
, LPSTR lpszPort
, LPDEVMODEA lpdmInput
,
426 LPSTR lpszProfile
, DWORD dwMode
)
428 PRINTERINFO
*pi
= PSDRV_FindPrinterInfoA(lpszDevice
);
431 TRACE("(Driver=%s, hwnd=%p, devOut=%p, Device='%s', Port='%s', devIn=%p, Profile='%s', Mode=%04x)\n",
432 lpszDriver
, hwnd
, lpdmOutput
, lpszDevice
, lpszPort
, lpdmInput
, debugstr_a(lpszProfile
), dwMode
);
434 /* If dwMode == 0, return size of DEVMODE structure */
436 return pi
->Devmode
->dmPublic
.dmSize
+ pi
->Devmode
->dmPublic
.dmDriverExtra
- CCHDEVICENAME
- CCHFORMNAME
;
438 /* If DM_MODIFY is set, change settings in accordance with lpdmInput */
439 if((dwMode
& DM_MODIFY
) && lpdmInput
)
441 DEVMODEW
*dmW
= GdiConvertToDevmodeW( lpdmInput
);
442 TRACE("DM_MODIFY set. devIn->dmFields = %08x\n", lpdmInput
->dmFields
);
443 if (dmW
) PSDRV_MergeDevmodes(pi
->Devmode
, (PSDRV_DEVMODE
*)dmW
, pi
);
444 HeapFree( GetProcessHeap(), 0, dmW
);
447 /* If DM_PROMPT is set, present modal dialog box */
448 if(dwMode
& DM_PROMPT
) {
449 HINSTANCE hinstComctl32
;
450 HPROPSHEETPAGE hpsp
[1];
452 PROPSHEETHEADERW psh
;
455 static const WCHAR PAPERW
[] = {'P','A','P','E','R','\0'};
456 static const WCHAR SetupW
[] = {'S','e','t','u','p','\0'};
458 hinstComctl32
= LoadLibraryA("comctl32.dll");
459 pInitCommonControls
= (void*)GetProcAddress(hinstComctl32
,
460 "InitCommonControls");
461 pCreatePropertySheetPage
= (void*)GetProcAddress(hinstComctl32
,
462 "CreatePropertySheetPageW");
463 pPropertySheet
= (void*)GetProcAddress(hinstComctl32
, "PropertySheetW");
464 memset(&psp
,0,sizeof(psp
));
465 dlgdm
= *pi
->Devmode
;
468 psp
.dwSize
= sizeof(psp
);
469 psp
.hInstance
= PSDRV_hInstance
;
470 psp
.u
.pszTemplate
= PAPERW
;
471 psp
.u2
.pszIcon
= NULL
;
472 psp
.pfnDlgProc
= PSDRV_PaperDlgProc
;
473 psp
.lParam
= (LPARAM
)&di
;
474 hpsp
[0] = pCreatePropertySheetPage(&psp
);
476 memset(&psh
, 0, sizeof(psh
));
477 psh
.dwSize
= sizeof(psh
);
478 psh
.pszCaption
= SetupW
;
480 psh
.hwndParent
= hwnd
;
481 psh
.u3
.phpage
= hpsp
;
483 pPropertySheet(&psh
);
487 /* If DM_UPDATE is set, should write settings to environment and initialization file */
488 if(dwMode
& DM_UPDATE
)
489 FIXME("Mode DM_UPDATE. Just do the same as DM_COPY\n");
491 /* If DM_COPY is set, should write settings to lpdmOutput */
492 if((dwMode
& DM_COPY
) || (dwMode
& DM_UPDATE
)) {
495 DEVMODEA
*dmA
= DEVMODEdupWtoA( &pi
->Devmode
->dmPublic
);
496 if (dmA
) memcpy( lpdmOutput
, dmA
, dmA
->dmSize
+ dmA
->dmDriverExtra
);
497 HeapFree( GetProcessHeap(), 0, dmA
);
500 FIXME("lpdmOutput is NULL what should we do??\n");
504 /***********************************************************************
505 * PSDRV_DeviceCapabilities
507 * Retrieves the capabilities of a printer device driver.
510 * lpszDriver -- printer driver name
511 * lpszDevice -- printer name
512 * lpszPort -- port name
513 * fwCapability -- device capability
514 * lpszOutput -- output buffer
515 * lpDevMode -- device data buffer
518 * Result depends on the setting of fwCapability. -1 indicates failure.
520 DWORD
PSDRV_DeviceCapabilities(LPSTR lpszDriver
, LPCSTR lpszDevice
, LPCSTR lpszPort
,
521 WORD fwCapability
, LPSTR lpszOutput
, LPDEVMODEA lpDevMode
)
526 pi
= PSDRV_FindPrinterInfoA(lpszDevice
);
528 TRACE("%s %s %s, %u, %p, %p\n", debugstr_a(lpszDriver
), debugstr_a(lpszDevice
),
529 debugstr_a(lpszPort
), fwCapability
, lpszOutput
, lpDevMode
);
532 ERR("no printer info for %s %s, return 0!\n",
533 debugstr_a(lpszDriver
), debugstr_a(lpszDevice
));
537 lpdm
= &pi
->Devmode
->dmPublic
;
538 if (lpDevMode
) lpdm
= GdiConvertToDevmodeW( lpDevMode
);
540 switch(fwCapability
) {
545 WORD
*wp
= (WORD
*)lpszOutput
;
548 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
550 TRACE("DC_PAPERS: %u\n", ps
->WinPage
);
552 if(lpszOutput
!= NULL
)
562 POINT16
*pt
= (POINT16
*)lpszOutput
;
565 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
567 TRACE("DC_PAPERSIZE: %f x %f\n", ps
->PaperDimension
->x
, ps
->PaperDimension
->y
);
569 if(lpszOutput
!= NULL
) {
570 pt
->x
= paper_size_from_points( ps
->PaperDimension
->x
);
571 pt
->y
= paper_size_from_points( ps
->PaperDimension
->y
);
582 char *cp
= lpszOutput
;
585 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
587 TRACE("DC_PAPERNAMES: %s\n", debugstr_a(ps
->FullName
));
589 if(lpszOutput
!= NULL
) {
590 lstrcpynA(cp
, ps
->FullName
, 64);
599 ret
= pi
->ppd
->LandscapeOrientation
? pi
->ppd
->LandscapeOrientation
: 90;
605 WORD
*wp
= (WORD
*)lpszOutput
;
608 LIST_FOR_EACH_ENTRY( slot
, &pi
->ppd
->InputSlots
, INPUTSLOT
, entry
)
611 if (lpszOutput
!= NULL
)
612 *wp
++ = slot
->WinBin
;
621 char *cp
= lpszOutput
;
624 LIST_FOR_EACH_ENTRY( slot
, &pi
->ppd
->InputSlots
, INPUTSLOT
, entry
)
627 if (lpszOutput
!= NULL
)
629 lstrcpynA( cp
, slot
->FullName
, 24 );
638 FIXME("DC_BINADJUST: stub.\n");
639 ret
= DCBA_FACEUPNONE
;
642 case DC_ENUMRESOLUTIONS
:
644 LONG
*lp
= (LONG
*)lpszOutput
;
646 if(lpszOutput
!= NULL
) {
647 lp
[0] = pi
->ppd
->DefaultResolution
;
648 lp
[1] = pi
->ppd
->DefaultResolution
;
654 /* Windows returns 9999 too */
656 TRACE("DC_COPIES: returning 9999\n");
661 ret
= lpdm
->dmDriverVersion
;
664 case DC_DATATYPE_PRODUCED
:
665 FIXME("DATA_TYPE_PRODUCED: stub.\n");
666 ret
= -1; /* simulate that the driver supports 'RAW' */
671 if(pi
->ppd
->DefaultDuplex
&& pi
->ppd
->DefaultDuplex
->WinDuplex
!= 0)
673 TRACE("DC_DUPLEX: returning %d\n", ret
);
676 case DC_EMF_COMPLIANT
:
677 FIXME("DC_EMF_COMPLIANT: stub.\n");
678 ret
= -1; /* simulate that the driver do not support EMF */
682 ret
= lpdm
->dmDriverExtra
;
686 ret
= lpdm
->dmFields
;
689 case DC_FILEDEPENDENCIES
:
690 FIXME("DC_FILEDEPENDENCIES: stub.\n");
699 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
701 if (ps
->PaperDimension
->x
> x
) x
= ps
->PaperDimension
->x
;
702 if (ps
->PaperDimension
->y
> y
) y
= ps
->PaperDimension
->y
;
704 ret
= MAKELONG( paper_size_from_points(x
), paper_size_from_points(y
) );
711 float x
= 1e6
, y
= 1e6
;
713 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
715 if (ps
->PaperDimension
->x
< x
) x
= ps
->PaperDimension
->x
;
716 if (ps
->PaperDimension
->y
< y
) y
= ps
->PaperDimension
->y
;
718 ret
= MAKELONG( paper_size_from_points(x
), paper_size_from_points(y
) );
727 FIXME("DC_TRUETYPE: stub\n");
732 ret
= lpdm
->dmSpecVersion
;
735 /* We'll just return false here, very few printers can collate anyway */
737 TRACE("DC_COLLATE: returning FALSE\n");
741 /* Printer supports colour printing - 1 if yes, 0 if no (Win2k/XP only) */
743 ret
= (pi
->ppd
->ColorDevice
!= CD_False
) ? TRUE
: FALSE
;
746 /* Identification number of the printer manufacturer for use with ICM (Win9x only) */
747 case DC_MANUFACTURER
:
748 FIXME("DC_MANUFACTURER: stub\n");
752 /* Identification number of the printer model for use with ICM (Win9x only) */
754 FIXME("DC_MODEL: stub\n");
758 /* Nonzero if the printer supports stapling, zero otherwise (Win2k/XP only) */
759 case DC_STAPLE
: /* WINVER >= 0x0500 */
760 FIXME("DC_STAPLE: stub\n");
764 /* Returns an array of 64-character string buffers containing the names of the paper forms
765 * available for use, unless pOutput is NULL. The return value is the number of paper forms.
768 case DC_MEDIAREADY
: /* WINVER >= 0x0500 */
769 FIXME("DC_MEDIAREADY: stub\n");
773 /* Returns an array of 64-character string buffers containing the names of the supported
774 * media types, unless pOutput is NULL. The return value is the number of supported.
775 * media types (XP only)
777 case DC_MEDIATYPENAMES
: /* WINVER >= 0x0501 */
778 FIXME("DC_MEDIATYPENAMES: stub\n");
782 /* Returns an array of DWORD values which represent the supported media types, unless
783 * pOutput is NULL. The return value is the number of supported media types. (XP only)
785 case DC_MEDIATYPES
: /* WINVER >= 0x0501 */
786 FIXME("DC_MEDIATYPES: stub\n");
790 /* Returns an array of DWORD values, each representing a supported number of document
791 * pages per printed page, unless pOutput is NULL. The return value is the number of
792 * array entries. (Win2k/XP only)
795 FIXME("DC_NUP: stub\n");
799 /* Returns an array of 32-character string buffers containing a list of printer description
800 * languages supported by the printer, unless pOutput is NULL. The return value is
801 * number of array entries. (Win2k/XP only)
804 case DC_PERSONALITY
: /* WINVER >= 0x0500 */
805 FIXME("DC_PERSONALITY: stub\n");
809 /* Returns the amount of printer memory in kilobytes. (Win2k/XP only) */
810 case DC_PRINTERMEM
: /* WINVER >= 0x0500 */
811 FIXME("DC_PRINTERMEM: stub\n");
815 /* Returns the printer's print rate in PRINTRATEUNIT units. (Win2k/XP only) */
816 case DC_PRINTRATE
: /* WINVER >= 0x0500 */
817 FIXME("DC_PRINTRATE: stub\n");
821 /* Returns the printer's print rate in pages per minute. (Win2k/XP only) */
822 case DC_PRINTRATEPPM
: /* WINVER >= 0x0500 */
823 FIXME("DC_PRINTRATEPPM: stub\n");
827 /* Returns the printer rate unit used for DC_PRINTRATE, which is one of
828 * PRINTRATEUNIT_{CPS,IPM,LPM,PPM} (Win2k/XP only)
830 case DC_PRINTRATEUNIT
: /* WINVER >= 0x0500 */
831 FIXME("DC_PRINTRATEUNIT: stub\n");
836 FIXME("Unsupported capability %d\n", fwCapability
);
840 if (lpDevMode
) HeapFree( GetProcessHeap(), 0, lpdm
);
848 HPROPSHEETPAGE hPages
[10];
851 INT
PSDRV_ExtDeviceModePropSheet(HWND hwnd
, LPSTR lpszDevice
, LPSTR lpszPort
,
854 EDMPS
*ps
= pPropSheet
;
857 psp
->dwSize
= sizeof(psp
);
858 psp
->hInstance
= 0x1234;