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