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 /************************************************************************
63 * Updates dm1 with some fields from dm2
66 void PSDRV_MergeDevmodes( PSDRV_DEVMODE
*dm1
, PSDRV_DEVMODE
*dm2
, PRINTERINFO
*pi
)
68 /* some sanity checks here on dm2 */
70 if(dm2
->dmPublic
.dmFields
& DM_ORIENTATION
) {
71 dm1
->dmPublic
.u1
.s1
.dmOrientation
= dm2
->dmPublic
.u1
.s1
.dmOrientation
;
72 TRACE("Changing orientation to %d (%s)\n",
73 dm1
->dmPublic
.u1
.s1
.dmOrientation
,
74 dm1
->dmPublic
.u1
.s1
.dmOrientation
== DMORIENT_PORTRAIT
?
76 (dm1
->dmPublic
.u1
.s1
.dmOrientation
== DMORIENT_LANDSCAPE
?
77 "Landscape" : "unknown"));
80 /* NB PaperWidth is always < PaperLength */
81 if(dm2
->dmPublic
.dmFields
& DM_PAPERSIZE
) {
84 LIST_FOR_EACH_ENTRY(page
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
) {
85 if(page
->WinPage
== dm2
->dmPublic
.u1
.s1
.dmPaperSize
)
88 if(&page
->entry
!= &pi
->ppd
->PageSizes
) {
89 dm1
->dmPublic
.u1
.s1
.dmPaperSize
= dm2
->dmPublic
.u1
.s1
.dmPaperSize
;
90 dm1
->dmPublic
.u1
.s1
.dmPaperWidth
= paper_size_from_points( page
->PaperDimension
->x
);
91 dm1
->dmPublic
.u1
.s1
.dmPaperLength
= paper_size_from_points( page
->PaperDimension
->y
);
92 dm1
->dmPublic
.dmFields
&= ~(DM_PAPERLENGTH
| DM_PAPERWIDTH
);
93 dm1
->dmPublic
.dmFields
|= DM_PAPERSIZE
;
94 TRACE("Changing page to %s %d x %d\n", page
->FullName
,
95 dm1
->dmPublic
.u1
.s1
.dmPaperWidth
,
96 dm1
->dmPublic
.u1
.s1
.dmPaperLength
);
98 TRACE("Trying to change to unsupported pagesize %d\n",
99 dm2
->dmPublic
.u1
.s1
.dmPaperSize
);
101 } else if((dm2
->dmPublic
.dmFields
& DM_PAPERLENGTH
) &&
102 (dm2
->dmPublic
.dmFields
& DM_PAPERWIDTH
)) {
103 dm1
->dmPublic
.u1
.s1
.dmPaperLength
= dm2
->dmPublic
.u1
.s1
.dmPaperLength
;
104 dm1
->dmPublic
.u1
.s1
.dmPaperWidth
= dm2
->dmPublic
.u1
.s1
.dmPaperWidth
;
105 TRACE("Changing PaperLength|Width to %dx%d\n",
106 dm2
->dmPublic
.u1
.s1
.dmPaperLength
,
107 dm2
->dmPublic
.u1
.s1
.dmPaperWidth
);
108 dm1
->dmPublic
.dmFields
&= ~DM_PAPERSIZE
;
109 dm1
->dmPublic
.dmFields
|= (DM_PAPERLENGTH
| DM_PAPERWIDTH
);
110 } else if(dm2
->dmPublic
.dmFields
& (DM_PAPERLENGTH
| DM_PAPERWIDTH
)) {
111 /* You might think that this would be allowed if dm1 is in custom size
112 mode, but apparently Windows reverts to standard paper mode even in
114 FIXME("Trying to change only paperlength or paperwidth\n");
115 dm1
->dmPublic
.dmFields
&= ~(DM_PAPERLENGTH
| DM_PAPERWIDTH
);
116 dm1
->dmPublic
.dmFields
|= DM_PAPERSIZE
;
119 if(dm2
->dmPublic
.dmFields
& DM_SCALE
) {
120 dm1
->dmPublic
.u1
.s1
.dmScale
= dm2
->dmPublic
.u1
.s1
.dmScale
;
121 TRACE("Changing Scale to %d\n", dm2
->dmPublic
.u1
.s1
.dmScale
);
124 if(dm2
->dmPublic
.dmFields
& DM_COPIES
) {
125 dm1
->dmPublic
.u1
.s1
.dmCopies
= dm2
->dmPublic
.u1
.s1
.dmCopies
;
126 TRACE("Changing Copies to %d\n", dm2
->dmPublic
.u1
.s1
.dmCopies
);
129 if (dm2
->dmPublic
.dmFields
& DM_DEFAULTSOURCE
)
131 INPUTSLOT
*slot
= find_slot( pi
->ppd
, dm2
);
135 dm1
->dmPublic
.u1
.s1
.dmDefaultSource
= dm2
->dmPublic
.u1
.s1
.dmDefaultSource
;
136 TRACE("Changing bin to '%s'\n", slot
->FullName
);
139 TRACE("Trying to change to unsupported bin %d\n", dm2
->dmPublic
.u1
.s1
.dmDefaultSource
);
142 if (dm2
->dmPublic
.dmFields
& DM_DEFAULTSOURCE
)
143 dm1
->dmPublic
.u1
.s1
.dmDefaultSource
= dm2
->dmPublic
.u1
.s1
.dmDefaultSource
;
144 if (dm2
->dmPublic
.dmFields
& DM_PRINTQUALITY
)
145 dm1
->dmPublic
.u1
.s1
.dmPrintQuality
= dm2
->dmPublic
.u1
.s1
.dmPrintQuality
;
146 if (dm2
->dmPublic
.dmFields
& DM_COLOR
)
147 dm1
->dmPublic
.dmColor
= dm2
->dmPublic
.dmColor
;
148 if (dm2
->dmPublic
.dmFields
& DM_DUPLEX
&& pi
->ppd
->DefaultDuplex
&& pi
->ppd
->DefaultDuplex
->WinDuplex
!= 0)
149 dm1
->dmPublic
.dmDuplex
= dm2
->dmPublic
.dmDuplex
;
150 if (dm2
->dmPublic
.dmFields
& DM_YRESOLUTION
)
151 dm1
->dmPublic
.dmYResolution
= dm2
->dmPublic
.dmYResolution
;
152 if (dm2
->dmPublic
.dmFields
& DM_TTOPTION
)
153 dm1
->dmPublic
.dmTTOption
= dm2
->dmPublic
.dmTTOption
;
154 if (dm2
->dmPublic
.dmFields
& DM_COLLATE
)
155 dm1
->dmPublic
.dmCollate
= dm2
->dmPublic
.dmCollate
;
156 if (dm2
->dmPublic
.dmFields
& DM_FORMNAME
)
157 lstrcpynA((LPSTR
)dm1
->dmPublic
.dmFormName
, (LPCSTR
)dm2
->dmPublic
.dmFormName
, CCHFORMNAME
);
158 if (dm2
->dmPublic
.dmFields
& DM_BITSPERPEL
)
159 dm1
->dmPublic
.dmBitsPerPel
= dm2
->dmPublic
.dmBitsPerPel
;
160 if (dm2
->dmPublic
.dmFields
& DM_PELSWIDTH
)
161 dm1
->dmPublic
.dmPelsWidth
= dm2
->dmPublic
.dmPelsWidth
;
162 if (dm2
->dmPublic
.dmFields
& DM_PELSHEIGHT
)
163 dm1
->dmPublic
.dmPelsHeight
= dm2
->dmPublic
.dmPelsHeight
;
164 if (dm2
->dmPublic
.dmFields
& DM_DISPLAYFLAGS
)
165 dm1
->dmPublic
.u2
.dmDisplayFlags
= dm2
->dmPublic
.u2
.dmDisplayFlags
;
166 if (dm2
->dmPublic
.dmFields
& DM_DISPLAYFREQUENCY
)
167 dm1
->dmPublic
.dmDisplayFrequency
= dm2
->dmPublic
.dmDisplayFrequency
;
168 if (dm2
->dmPublic
.dmFields
& DM_POSITION
)
169 dm1
->dmPublic
.u1
.s2
.dmPosition
= dm2
->dmPublic
.u1
.s2
.dmPosition
;
170 if (dm2
->dmPublic
.dmFields
& DM_LOGPIXELS
)
171 dm1
->dmPublic
.dmLogPixels
= dm2
->dmPublic
.dmLogPixels
;
172 if (dm2
->dmPublic
.dmFields
& DM_ICMMETHOD
)
173 dm1
->dmPublic
.dmICMMethod
= dm2
->dmPublic
.dmICMMethod
;
174 if (dm2
->dmPublic
.dmFields
& DM_ICMINTENT
)
175 dm1
->dmPublic
.dmICMIntent
= dm2
->dmPublic
.dmICMIntent
;
176 if (dm2
->dmPublic
.dmFields
& DM_MEDIATYPE
)
177 dm1
->dmPublic
.dmMediaType
= dm2
->dmPublic
.dmMediaType
;
178 if (dm2
->dmPublic
.dmFields
& DM_DITHERTYPE
)
179 dm1
->dmPublic
.dmDitherType
= dm2
->dmPublic
.dmDitherType
;
180 if (dm2
->dmPublic
.dmFields
& DM_PANNINGWIDTH
)
181 dm1
->dmPublic
.dmPanningWidth
= dm2
->dmPublic
.dmPanningWidth
;
182 if (dm2
->dmPublic
.dmFields
& DM_PANNINGHEIGHT
)
183 dm1
->dmPublic
.dmPanningHeight
= dm2
->dmPublic
.dmPanningHeight
;
192 PSDRV_DEVMODE
*dlgdm
;
195 /****************************************************************
198 * Dialog proc for 'Paper' propsheet
200 static INT_PTR CALLBACK
PSDRV_PaperDlgProc(HWND hwnd
, UINT msg
,
201 WPARAM wParam
, LPARAM lParam
)
210 di
= (PSDRV_DLGINFO
*)((PROPSHEETPAGEA
*)lParam
)->lParam
;
211 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LONG_PTR
)di
);
214 LIST_FOR_EACH_ENTRY(ps
, &di
->pi
->ppd
->PageSizes
, PAGESIZE
, entry
) {
215 SendDlgItemMessageA(hwnd
, IDD_PAPERS
, LB_INSERTSTRING
, i
,
216 (LPARAM
)ps
->FullName
);
217 if(di
->pi
->Devmode
->dmPublic
.u1
.s1
.dmPaperSize
== ps
->WinPage
)
221 SendDlgItemMessageA(hwnd
, IDD_PAPERS
, LB_SETCURSEL
, Cursel
, 0);
223 CheckRadioButton(hwnd
, IDD_ORIENT_PORTRAIT
, IDD_ORIENT_LANDSCAPE
,
224 di
->pi
->Devmode
->dmPublic
.u1
.s1
.dmOrientation
==
225 DMORIENT_PORTRAIT
? IDD_ORIENT_PORTRAIT
:
226 IDD_ORIENT_LANDSCAPE
);
228 if (list_empty( &di
->pi
->ppd
->Duplexes
))
230 ShowWindow(GetDlgItem(hwnd
, IDD_DUPLEX
), SW_HIDE
);
231 ShowWindow(GetDlgItem(hwnd
, IDD_DUPLEX_NAME
), SW_HIDE
);
236 LIST_FOR_EACH_ENTRY( duplex
, &di
->pi
->ppd
->Duplexes
, DUPLEX
, entry
)
238 SendDlgItemMessageA(hwnd
, IDD_DUPLEX
, CB_INSERTSTRING
, i
,
239 (LPARAM
)(duplex
->FullName
? duplex
->FullName
: duplex
->Name
));
240 if(di
->pi
->Devmode
->dmPublic
.dmDuplex
== duplex
->WinDuplex
)
244 SendDlgItemMessageA(hwnd
, IDD_DUPLEX
, CB_SETCURSEL
, Cursel
, 0);
249 di
= (PSDRV_DLGINFO
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
250 switch(LOWORD(wParam
)) {
252 if(HIWORD(wParam
) == LBN_SELCHANGE
) {
253 Cursel
= SendDlgItemMessageA(hwnd
, LOWORD(wParam
), LB_GETCURSEL
, 0, 0);
255 LIST_FOR_EACH_ENTRY(ps
, &di
->pi
->ppd
->PageSizes
, PAGESIZE
, entry
) {
256 if(i
>= Cursel
) break;
259 TRACE("Setting pagesize to item %d Winpage = %d\n", Cursel
, ps
->WinPage
);
260 di
->dlgdm
->dmPublic
.u1
.s1
.dmPaperSize
= ps
->WinPage
;
261 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, 0, 0);
264 case IDD_ORIENT_PORTRAIT
:
265 case IDD_ORIENT_LANDSCAPE
:
266 TRACE("Setting orientation to %s\n", wParam
== IDD_ORIENT_PORTRAIT
?
267 "portrait" : "landscape");
268 di
->dlgdm
->dmPublic
.u1
.s1
.dmOrientation
= wParam
== IDD_ORIENT_PORTRAIT
?
269 DMORIENT_PORTRAIT
: DMORIENT_LANDSCAPE
;
270 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, 0, 0);
273 if(HIWORD(wParam
) == CBN_SELCHANGE
) {
274 Cursel
= SendDlgItemMessageA(hwnd
, LOWORD(wParam
), CB_GETCURSEL
, 0, 0);
276 LIST_FOR_EACH_ENTRY( duplex
, &di
->pi
->ppd
->Duplexes
, DUPLEX
, entry
)
278 if (i
>= Cursel
) break;
281 TRACE("Setting duplex to item %d Winduplex = %d\n", Cursel
, duplex
->WinDuplex
);
282 di
->dlgdm
->dmPublic
.dmDuplex
= duplex
->WinDuplex
;
283 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, 0, 0);
291 NMHDR
*nmhdr
= (NMHDR
*)lParam
;
292 di
= (PSDRV_DLGINFO
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
293 switch(nmhdr
->code
) {
295 *di
->pi
->Devmode
= *di
->dlgdm
;
296 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, PSNRET_NOERROR
);
312 static void (WINAPI
*pInitCommonControls
) (void);
313 static HPROPSHEETPAGE (WINAPI
*pCreatePropertySheetPage
) (LPCPROPSHEETPAGEW
);
314 static int (WINAPI
*pPropertySheet
) (LPCPROPSHEETHEADERW
);
316 static PRINTERINFO
*PSDRV_FindPrinterInfoA(LPCSTR name
)
318 int len
= MultiByteToWideChar( CP_ACP
, 0, name
, -1, NULL
, 0 );
319 WCHAR
*nameW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
322 MultiByteToWideChar( CP_ACP
, 0, name
, -1, nameW
, len
);
323 pi
= PSDRV_FindPrinterInfo( nameW
);
324 HeapFree( GetProcessHeap(), 0, nameW
);
329 /***********************************************************
332 * Creates an ascii copy of supplied devmode on the process heap
334 * Copied from dlls/winspool/info.c until full unicodification
336 static DEVMODEA
*DEVMODEdupWtoA( const DEVMODEW
*dmW
)
341 /* there is no pointer dereference here, if your code checking tool complains it's broken */
342 ptrdiff_t off_formname
= (const char *)dmW
->dmFormName
- (const char *)dmW
;
344 if (!dmW
) return NULL
;
345 formname
= (dmW
->dmSize
> off_formname
);
346 size
= dmW
->dmSize
- CCHDEVICENAME
- (formname
? CCHFORMNAME
: 0);
347 dmA
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, size
+ dmW
->dmDriverExtra
);
348 WideCharToMultiByte( CP_ACP
, 0, dmW
->dmDeviceName
, -1, (LPSTR
)dmA
->dmDeviceName
,
349 CCHDEVICENAME
, NULL
, NULL
);
352 memcpy( &dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
353 dmW
->dmSize
- CCHDEVICENAME
* sizeof(WCHAR
) );
357 memcpy( &dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
358 off_formname
- CCHDEVICENAME
* sizeof(WCHAR
) );
359 WideCharToMultiByte( CP_ACP
, 0, dmW
->dmFormName
, -1, (LPSTR
)dmA
->dmFormName
,
360 CCHFORMNAME
, NULL
, NULL
);
361 memcpy( &dmA
->dmLogPixels
, &dmW
->dmLogPixels
, dmW
->dmSize
-
362 (off_formname
+ CCHFORMNAME
* sizeof(WCHAR
)) );
365 memcpy( (char *)dmA
+ dmA
->dmSize
, (const char *)dmW
+ dmW
->dmSize
,
366 dmW
->dmDriverExtra
);
370 /******************************************************************
371 * PSDRV_ExtDeviceMode
373 * Retrieves or modifies device-initialization information for the PostScript
374 * driver, or displays a driver-supplied dialog box for configuring the driver.
377 * lpszDriver -- Driver name
378 * hwnd -- Parent window for the dialog box
379 * lpdmOutput -- Address of a DEVMODE structure for writing initialization information
380 * lpszDevice -- Device name
381 * lpszPort -- Port name
382 * lpdmInput -- Address of a DEVMODE structure for reading initialization information
383 * lpProfile -- Name of initialization file, defaults to WIN.INI if NULL
384 * wMode -- Operation to perform. Can be a combination if > 0.
385 * (0) -- Returns number of bytes required by DEVMODE structure
386 * DM_UPDATE (1) -- Write current settings to environment and initialization file
387 * DM_COPY (2) -- Write current settings to lpdmOutput
388 * DM_PROMPT (4) -- Presents the driver's modal dialog box (USER.240)
389 * DM_MODIFY (8) -- Changes current settings according to lpdmInput before any other operation
392 * Returns size of DEVMODE structure if wMode is 0. Otherwise, IDOK is returned for success
393 * for both dialog and non-dialog operations. IDCANCEL is returned if the dialog box was cancelled.
394 * A return value less than zero is returned if a non-dialog operation fails.
398 * Just returns default devmode at the moment. No use of initialization file.
400 INT
PSDRV_ExtDeviceMode(LPSTR lpszDriver
, HWND hwnd
, LPDEVMODEA lpdmOutput
,
401 LPSTR lpszDevice
, LPSTR lpszPort
, LPDEVMODEA lpdmInput
,
402 LPSTR lpszProfile
, DWORD dwMode
)
404 PRINTERINFO
*pi
= PSDRV_FindPrinterInfoA(lpszDevice
);
407 TRACE("(Driver=%s, hwnd=%p, devOut=%p, Device='%s', Port='%s', devIn=%p, Profile='%s', Mode=%04x)\n",
408 lpszDriver
, hwnd
, lpdmOutput
, lpszDevice
, lpszPort
, lpdmInput
, debugstr_a(lpszProfile
), dwMode
);
410 /* If dwMode == 0, return size of DEVMODE structure */
412 return pi
->Devmode
->dmPublic
.dmSize
+ pi
->Devmode
->dmPublic
.dmDriverExtra
- CCHDEVICENAME
- CCHFORMNAME
;
414 /* If DM_MODIFY is set, change settings in accordance with lpdmInput */
415 if((dwMode
& DM_MODIFY
) && lpdmInput
)
417 DEVMODEW
*dmW
= GdiConvertToDevmodeW( lpdmInput
);
418 TRACE("DM_MODIFY set. devIn->dmFields = %08x\n", lpdmInput
->dmFields
);
419 if (dmW
) PSDRV_MergeDevmodes(pi
->Devmode
, (PSDRV_DEVMODE
*)dmW
, pi
);
420 HeapFree( GetProcessHeap(), 0, dmW
);
423 /* If DM_PROMPT is set, present modal dialog box */
424 if(dwMode
& DM_PROMPT
) {
425 HINSTANCE hinstComctl32
;
426 HPROPSHEETPAGE hpsp
[1];
428 PROPSHEETHEADERW psh
;
431 static const WCHAR PAPERW
[] = {'P','A','P','E','R','\0'};
432 static const WCHAR SetupW
[] = {'S','e','t','u','p','\0'};
434 hinstComctl32
= LoadLibraryA("comctl32.dll");
435 pInitCommonControls
= (void*)GetProcAddress(hinstComctl32
,
436 "InitCommonControls");
437 pCreatePropertySheetPage
= (void*)GetProcAddress(hinstComctl32
,
438 "CreatePropertySheetPageW");
439 pPropertySheet
= (void*)GetProcAddress(hinstComctl32
, "PropertySheetW");
440 memset(&psp
,0,sizeof(psp
));
441 dlgdm
= *pi
->Devmode
;
444 psp
.dwSize
= sizeof(psp
);
445 psp
.hInstance
= PSDRV_hInstance
;
446 psp
.u
.pszTemplate
= PAPERW
;
447 psp
.u2
.pszIcon
= NULL
;
448 psp
.pfnDlgProc
= PSDRV_PaperDlgProc
;
449 psp
.lParam
= (LPARAM
)&di
;
450 hpsp
[0] = pCreatePropertySheetPage(&psp
);
452 memset(&psh
, 0, sizeof(psh
));
453 psh
.dwSize
= sizeof(psh
);
454 psh
.pszCaption
= SetupW
;
456 psh
.hwndParent
= hwnd
;
457 psh
.u3
.phpage
= hpsp
;
459 pPropertySheet(&psh
);
463 /* If DM_UPDATE is set, should write settings to environment and initialization file */
464 if(dwMode
& DM_UPDATE
)
465 FIXME("Mode DM_UPDATE. Just do the same as DM_COPY\n");
467 /* If DM_COPY is set, should write settings to lpdmOutput */
468 if((dwMode
& DM_COPY
) || (dwMode
& DM_UPDATE
)) {
471 DEVMODEA
*dmA
= DEVMODEdupWtoA( &pi
->Devmode
->dmPublic
);
472 if (dmA
) memcpy( lpdmOutput
, dmA
, dmA
->dmSize
+ dmA
->dmDriverExtra
);
473 HeapFree( GetProcessHeap(), 0, dmA
);
476 FIXME("lpdmOutput is NULL what should we do??\n");
480 /***********************************************************************
481 * PSDRV_DeviceCapabilities
483 * Retrieves the capabilities of a printer device driver.
486 * lpszDriver -- printer driver name
487 * lpszDevice -- printer name
488 * lpszPort -- port name
489 * fwCapability -- device capability
490 * lpszOutput -- output buffer
491 * lpDevMode -- device data buffer
494 * Result depends on the setting of fwCapability. -1 indicates failure.
496 DWORD
PSDRV_DeviceCapabilities(LPSTR lpszDriver
, LPCSTR lpszDevice
, LPCSTR lpszPort
,
497 WORD fwCapability
, LPSTR lpszOutput
, LPDEVMODEA lpDevMode
)
502 pi
= PSDRV_FindPrinterInfoA(lpszDevice
);
504 TRACE("%s %s %s, %u, %p, %p\n", debugstr_a(lpszDriver
), debugstr_a(lpszDevice
),
505 debugstr_a(lpszPort
), fwCapability
, lpszOutput
, lpDevMode
);
508 ERR("no printer info for %s %s, return 0!\n",
509 debugstr_a(lpszDriver
), debugstr_a(lpszDevice
));
513 lpdm
= &pi
->Devmode
->dmPublic
;
514 if (lpDevMode
) lpdm
= GdiConvertToDevmodeW( lpDevMode
);
516 switch(fwCapability
) {
521 WORD
*wp
= (WORD
*)lpszOutput
;
524 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
526 TRACE("DC_PAPERS: %u\n", ps
->WinPage
);
528 if(lpszOutput
!= NULL
)
538 POINT16
*pt
= (POINT16
*)lpszOutput
;
541 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
543 TRACE("DC_PAPERSIZE: %f x %f\n", ps
->PaperDimension
->x
, ps
->PaperDimension
->y
);
545 if(lpszOutput
!= NULL
) {
546 pt
->x
= paper_size_from_points( ps
->PaperDimension
->x
);
547 pt
->y
= paper_size_from_points( ps
->PaperDimension
->y
);
558 char *cp
= lpszOutput
;
561 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
563 TRACE("DC_PAPERNAMES: %s\n", debugstr_a(ps
->FullName
));
565 if(lpszOutput
!= NULL
) {
566 lstrcpynA(cp
, ps
->FullName
, 64);
575 ret
= pi
->ppd
->LandscapeOrientation
? pi
->ppd
->LandscapeOrientation
: 90;
581 WORD
*wp
= (WORD
*)lpszOutput
;
584 LIST_FOR_EACH_ENTRY( slot
, &pi
->ppd
->InputSlots
, INPUTSLOT
, entry
)
587 if (lpszOutput
!= NULL
)
588 *wp
++ = slot
->WinBin
;
597 char *cp
= lpszOutput
;
600 LIST_FOR_EACH_ENTRY( slot
, &pi
->ppd
->InputSlots
, INPUTSLOT
, entry
)
603 if (lpszOutput
!= NULL
)
605 lstrcpynA( cp
, slot
->FullName
, 24 );
614 FIXME("DC_BINADJUST: stub.\n");
615 ret
= DCBA_FACEUPNONE
;
618 case DC_ENUMRESOLUTIONS
:
620 LONG
*lp
= (LONG
*)lpszOutput
;
622 if(lpszOutput
!= NULL
) {
623 lp
[0] = pi
->ppd
->DefaultResolution
;
624 lp
[1] = pi
->ppd
->DefaultResolution
;
630 /* Windows returns 9999 too */
632 TRACE("DC_COPIES: returning 9999\n");
637 ret
= lpdm
->dmDriverVersion
;
640 case DC_DATATYPE_PRODUCED
:
641 FIXME("DATA_TYPE_PRODUCED: stub.\n");
642 ret
= -1; /* simulate that the driver supports 'RAW' */
647 if(pi
->ppd
->DefaultDuplex
&& pi
->ppd
->DefaultDuplex
->WinDuplex
!= 0)
649 TRACE("DC_DUPLEX: returning %d\n", ret
);
652 case DC_EMF_COMPLIANT
:
653 FIXME("DC_EMF_COMPLIANT: stub.\n");
654 ret
= -1; /* simulate that the driver do not support EMF */
658 ret
= lpdm
->dmDriverExtra
;
662 ret
= lpdm
->dmFields
;
665 case DC_FILEDEPENDENCIES
:
666 FIXME("DC_FILEDEPENDENCIES: stub.\n");
675 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
677 if (ps
->PaperDimension
->x
> x
) x
= ps
->PaperDimension
->x
;
678 if (ps
->PaperDimension
->y
> y
) y
= ps
->PaperDimension
->y
;
680 ret
= MAKELONG( paper_size_from_points(x
), paper_size_from_points(y
) );
687 float x
= 1e6
, y
= 1e6
;
689 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
691 if (ps
->PaperDimension
->x
< x
) x
= ps
->PaperDimension
->x
;
692 if (ps
->PaperDimension
->y
< y
) y
= ps
->PaperDimension
->y
;
694 ret
= MAKELONG( paper_size_from_points(x
), paper_size_from_points(y
) );
703 FIXME("DC_TRUETYPE: stub\n");
708 ret
= lpdm
->dmSpecVersion
;
711 /* We'll just return false here, very few printers can collate anyway */
713 TRACE("DC_COLLATE: returning FALSE\n");
717 /* Printer supports colour printing - 1 if yes, 0 if no (Win2k/XP only) */
719 ret
= (pi
->ppd
->ColorDevice
!= CD_False
) ? TRUE
: FALSE
;
722 /* Identification number of the printer manufacturer for use with ICM (Win9x only) */
723 case DC_MANUFACTURER
:
724 FIXME("DC_MANUFACTURER: stub\n");
728 /* Identification number of the printer model for use with ICM (Win9x only) */
730 FIXME("DC_MODEL: stub\n");
734 /* Nonzero if the printer supports stapling, zero otherwise (Win2k/XP only) */
735 case DC_STAPLE
: /* WINVER >= 0x0500 */
736 FIXME("DC_STAPLE: stub\n");
740 /* Returns an array of 64-character string buffers containing the names of the paper forms
741 * available for use, unless pOutput is NULL. The return value is the number of paper forms.
744 case DC_MEDIAREADY
: /* WINVER >= 0x0500 */
745 FIXME("DC_MEDIAREADY: stub\n");
749 /* Returns an array of 64-character string buffers containing the names of the supported
750 * media types, unless pOutput is NULL. The return value is the number of supported.
751 * media types (XP only)
753 case DC_MEDIATYPENAMES
: /* WINVER >= 0x0501 */
754 FIXME("DC_MEDIATYPENAMES: stub\n");
758 /* Returns an array of DWORD values which represent the supported media types, unless
759 * pOutput is NULL. The return value is the number of supported media types. (XP only)
761 case DC_MEDIATYPES
: /* WINVER >= 0x0501 */
762 FIXME("DC_MEDIATYPES: stub\n");
766 /* Returns an array of DWORD values, each representing a supported number of document
767 * pages per printed page, unless pOutput is NULL. The return value is the number of
768 * array entries. (Win2k/XP only)
771 FIXME("DC_NUP: stub\n");
775 /* Returns an array of 32-character string buffers containing a list of printer description
776 * languages supported by the printer, unless pOutput is NULL. The return value is
777 * number of array entries. (Win2k/XP only)
780 case DC_PERSONALITY
: /* WINVER >= 0x0500 */
781 FIXME("DC_PERSONALITY: stub\n");
785 /* Returns the amount of printer memory in kilobytes. (Win2k/XP only) */
786 case DC_PRINTERMEM
: /* WINVER >= 0x0500 */
787 FIXME("DC_PRINTERMEM: stub\n");
791 /* Returns the printer's print rate in PRINTRATEUNIT units. (Win2k/XP only) */
792 case DC_PRINTRATE
: /* WINVER >= 0x0500 */
793 FIXME("DC_PRINTRATE: stub\n");
797 /* Returns the printer's print rate in pages per minute. (Win2k/XP only) */
798 case DC_PRINTRATEPPM
: /* WINVER >= 0x0500 */
799 FIXME("DC_PRINTRATEPPM: stub\n");
803 /* Returns the printer rate unit used for DC_PRINTRATE, which is one of
804 * PRINTRATEUNIT_{CPS,IPM,LPM,PPM} (Win2k/XP only)
806 case DC_PRINTRATEUNIT
: /* WINVER >= 0x0500 */
807 FIXME("DC_PRINTRATEUNIT: stub\n");
812 FIXME("Unsupported capability %d\n", fwCapability
);
816 if (lpDevMode
) HeapFree( GetProcessHeap(), 0, lpdm
);
824 HPROPSHEETPAGE hPages
[10];
827 INT
PSDRV_ExtDeviceModePropSheet(HWND hwnd
, LPSTR lpszDevice
, LPSTR lpszPort
,
830 EDMPS
*ps
= pPropSheet
;
833 psp
->dwSize
= sizeof(psp
);
834 psp
->hInstance
= 0x1234;