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
, const 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
, const 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
, const 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
, const 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
);
121 if (dm1
->dmPublic
.dmSize
>= FIELD_OFFSET(DEVMODEW
, dmFormName
) + CCHFORMNAME
* sizeof(WCHAR
))
123 MultiByteToWideChar(CP_ACP
, 0, page
->FullName
, -1, dm1
->dmPublic
.dmFormName
, CCHFORMNAME
);
124 dm1
->dmPublic
.dmFields
|= DM_FORMNAME
;
128 TRACE("Trying to change to unsupported pagesize %d\n", dm2
->dmPublic
.u1
.s1
.dmPaperSize
);
131 else if((dm2
->dmPublic
.dmFields
& DM_PAPERLENGTH
) &&
132 (dm2
->dmPublic
.dmFields
& DM_PAPERWIDTH
)) {
133 dm1
->dmPublic
.u1
.s1
.dmPaperLength
= dm2
->dmPublic
.u1
.s1
.dmPaperLength
;
134 dm1
->dmPublic
.u1
.s1
.dmPaperWidth
= dm2
->dmPublic
.u1
.s1
.dmPaperWidth
;
135 TRACE("Changing PaperLength|Width to %dx%d\n",
136 dm2
->dmPublic
.u1
.s1
.dmPaperLength
,
137 dm2
->dmPublic
.u1
.s1
.dmPaperWidth
);
138 dm1
->dmPublic
.dmFields
&= ~DM_PAPERSIZE
;
139 dm1
->dmPublic
.dmFields
|= (DM_PAPERLENGTH
| DM_PAPERWIDTH
);
140 } else if(dm2
->dmPublic
.dmFields
& (DM_PAPERLENGTH
| DM_PAPERWIDTH
)) {
141 /* You might think that this would be allowed if dm1 is in custom size
142 mode, but apparently Windows reverts to standard paper mode even in
144 FIXME("Trying to change only paperlength or paperwidth\n");
145 dm1
->dmPublic
.dmFields
&= ~(DM_PAPERLENGTH
| DM_PAPERWIDTH
);
146 dm1
->dmPublic
.dmFields
|= DM_PAPERSIZE
;
149 if(dm2
->dmPublic
.dmFields
& DM_SCALE
) {
150 dm1
->dmPublic
.u1
.s1
.dmScale
= dm2
->dmPublic
.u1
.s1
.dmScale
;
151 TRACE("Changing Scale to %d\n", dm2
->dmPublic
.u1
.s1
.dmScale
);
154 if(dm2
->dmPublic
.dmFields
& DM_COPIES
) {
155 dm1
->dmPublic
.u1
.s1
.dmCopies
= dm2
->dmPublic
.u1
.s1
.dmCopies
;
156 TRACE("Changing Copies to %d\n", dm2
->dmPublic
.u1
.s1
.dmCopies
);
159 if (dm2
->dmPublic
.dmFields
& DM_DEFAULTSOURCE
)
161 INPUTSLOT
*slot
= find_slot( pi
->ppd
, dm2
);
165 dm1
->dmPublic
.u1
.s1
.dmDefaultSource
= dm2
->dmPublic
.u1
.s1
.dmDefaultSource
;
166 TRACE("Changing bin to '%s'\n", slot
->FullName
);
169 TRACE("Trying to change to unsupported bin %d\n", dm2
->dmPublic
.u1
.s1
.dmDefaultSource
);
172 if (dm2
->dmPublic
.dmFields
& DM_DEFAULTSOURCE
)
173 dm1
->dmPublic
.u1
.s1
.dmDefaultSource
= dm2
->dmPublic
.u1
.s1
.dmDefaultSource
;
174 if (dm2
->dmPublic
.dmFields
& DM_PRINTQUALITY
)
175 dm1
->dmPublic
.u1
.s1
.dmPrintQuality
= dm2
->dmPublic
.u1
.s1
.dmPrintQuality
;
176 if (dm2
->dmPublic
.dmFields
& DM_COLOR
)
177 dm1
->dmPublic
.dmColor
= dm2
->dmPublic
.dmColor
;
178 if (dm2
->dmPublic
.dmFields
& DM_DUPLEX
&& pi
->ppd
->DefaultDuplex
&& pi
->ppd
->DefaultDuplex
->WinDuplex
!= 0)
179 dm1
->dmPublic
.dmDuplex
= dm2
->dmPublic
.dmDuplex
;
180 if (dm2
->dmPublic
.dmFields
& DM_YRESOLUTION
)
181 dm1
->dmPublic
.dmYResolution
= dm2
->dmPublic
.dmYResolution
;
182 if (dm2
->dmPublic
.dmFields
& DM_TTOPTION
)
183 dm1
->dmPublic
.dmTTOption
= dm2
->dmPublic
.dmTTOption
;
184 if (dm2
->dmPublic
.dmFields
& DM_COLLATE
)
185 dm1
->dmPublic
.dmCollate
= dm2
->dmPublic
.dmCollate
;
186 if (dm2
->dmPublic
.dmFields
& DM_FORMNAME
)
187 lstrcpynW(dm1
->dmPublic
.dmFormName
, dm2
->dmPublic
.dmFormName
, CCHFORMNAME
);
188 if (dm2
->dmPublic
.dmFields
& DM_BITSPERPEL
)
189 dm1
->dmPublic
.dmBitsPerPel
= dm2
->dmPublic
.dmBitsPerPel
;
190 if (dm2
->dmPublic
.dmFields
& DM_PELSWIDTH
)
191 dm1
->dmPublic
.dmPelsWidth
= dm2
->dmPublic
.dmPelsWidth
;
192 if (dm2
->dmPublic
.dmFields
& DM_PELSHEIGHT
)
193 dm1
->dmPublic
.dmPelsHeight
= dm2
->dmPublic
.dmPelsHeight
;
194 if (dm2
->dmPublic
.dmFields
& DM_DISPLAYFLAGS
)
195 dm1
->dmPublic
.u2
.dmDisplayFlags
= dm2
->dmPublic
.u2
.dmDisplayFlags
;
196 if (dm2
->dmPublic
.dmFields
& DM_DISPLAYFREQUENCY
)
197 dm1
->dmPublic
.dmDisplayFrequency
= dm2
->dmPublic
.dmDisplayFrequency
;
198 if (dm2
->dmPublic
.dmFields
& DM_POSITION
)
199 dm1
->dmPublic
.u1
.s2
.dmPosition
= dm2
->dmPublic
.u1
.s2
.dmPosition
;
200 if (dm2
->dmPublic
.dmFields
& DM_LOGPIXELS
)
201 dm1
->dmPublic
.dmLogPixels
= dm2
->dmPublic
.dmLogPixels
;
202 if (dm2
->dmPublic
.dmFields
& DM_ICMMETHOD
)
203 dm1
->dmPublic
.dmICMMethod
= dm2
->dmPublic
.dmICMMethod
;
204 if (dm2
->dmPublic
.dmFields
& DM_ICMINTENT
)
205 dm1
->dmPublic
.dmICMIntent
= dm2
->dmPublic
.dmICMIntent
;
206 if (dm2
->dmPublic
.dmFields
& DM_MEDIATYPE
)
207 dm1
->dmPublic
.dmMediaType
= dm2
->dmPublic
.dmMediaType
;
208 if (dm2
->dmPublic
.dmFields
& DM_DITHERTYPE
)
209 dm1
->dmPublic
.dmDitherType
= dm2
->dmPublic
.dmDitherType
;
210 if (dm2
->dmPublic
.dmFields
& DM_PANNINGWIDTH
)
211 dm1
->dmPublic
.dmPanningWidth
= dm2
->dmPublic
.dmPanningWidth
;
212 if (dm2
->dmPublic
.dmFields
& DM_PANNINGHEIGHT
)
213 dm1
->dmPublic
.dmPanningHeight
= dm2
->dmPublic
.dmPanningHeight
;
222 PSDRV_DEVMODE
*dlgdm
;
225 /****************************************************************
228 * Dialog proc for 'Paper' propsheet
230 static INT_PTR CALLBACK
PSDRV_PaperDlgProc(HWND hwnd
, UINT msg
,
231 WPARAM wParam
, LPARAM lParam
)
233 static const WCHAR resW
[] = {'%','d',0};
234 static const WCHAR resxyW
[] = {'%','d','x','%','d',0};
243 di
= (PSDRV_DLGINFO
*)((PROPSHEETPAGEA
*)lParam
)->lParam
;
244 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LONG_PTR
)di
);
247 LIST_FOR_EACH_ENTRY(ps
, &di
->pi
->ppd
->PageSizes
, PAGESIZE
, entry
) {
248 SendDlgItemMessageA(hwnd
, IDD_PAPERS
, LB_INSERTSTRING
, i
,
249 (LPARAM
)ps
->FullName
);
250 if(di
->pi
->Devmode
->dmPublic
.u1
.s1
.dmPaperSize
== ps
->WinPage
)
254 SendDlgItemMessageA(hwnd
, IDD_PAPERS
, LB_SETCURSEL
, Cursel
, 0);
256 CheckRadioButton(hwnd
, IDD_ORIENT_PORTRAIT
, IDD_ORIENT_LANDSCAPE
,
257 di
->pi
->Devmode
->dmPublic
.u1
.s1
.dmOrientation
==
258 DMORIENT_PORTRAIT
? IDD_ORIENT_PORTRAIT
:
259 IDD_ORIENT_LANDSCAPE
);
261 if (list_empty( &di
->pi
->ppd
->Duplexes
))
263 ShowWindow(GetDlgItem(hwnd
, IDD_DUPLEX
), SW_HIDE
);
264 ShowWindow(GetDlgItem(hwnd
, IDD_DUPLEX_NAME
), SW_HIDE
);
269 LIST_FOR_EACH_ENTRY( duplex
, &di
->pi
->ppd
->Duplexes
, DUPLEX
, entry
)
271 SendDlgItemMessageA(hwnd
, IDD_DUPLEX
, CB_INSERTSTRING
, i
,
272 (LPARAM
)(duplex
->FullName
? duplex
->FullName
: duplex
->Name
));
273 if(di
->pi
->Devmode
->dmPublic
.dmDuplex
== duplex
->WinDuplex
)
277 SendDlgItemMessageA(hwnd
, IDD_DUPLEX
, CB_SETCURSEL
, Cursel
, 0);
280 if (list_empty( &di
->pi
->ppd
->Resolutions
))
285 res
= di
->pi
->ppd
->DefaultResolution
;
286 len
= sprintfW(buf
, resW
, res
);
288 LoadStringW(PSDRV_hInstance
, IDS_DPI
, buf
+ len
, sizeof(buf
)/sizeof(buf
[0]) - len
);
289 SendDlgItemMessageW(hwnd
, IDD_QUALITY
, CB_ADDSTRING
, 0, (LPARAM
)buf
);
290 SendDlgItemMessageW(hwnd
, IDD_QUALITY
, CB_SETITEMDATA
, 0, MAKELONG(res
, res
));
298 resx
= resy
= di
->pi
->ppd
->DefaultResolution
;
300 if (di
->pi
->Devmode
->dmPublic
.dmFields
& DM_PRINTQUALITY
)
301 resx
= resy
= di
->pi
->Devmode
->dmPublic
.u1
.s1
.dmPrintQuality
;
303 if (di
->pi
->Devmode
->dmPublic
.dmFields
& DM_YRESOLUTION
)
304 resy
= di
->pi
->Devmode
->dmPublic
.dmYResolution
;
306 if (di
->pi
->Devmode
->dmPublic
.dmFields
& DM_LOGPIXELS
)
307 resx
= resy
= di
->pi
->Devmode
->dmPublic
.dmLogPixels
;
309 LIST_FOR_EACH_ENTRY(res
, &di
->pi
->ppd
->Resolutions
, RESOLUTION
, entry
)
315 if (res
->resx
== res
->resy
)
316 len
= sprintfW(buf
, resW
, res
->resx
);
318 len
= sprintfW(buf
, resxyW
, res
->resx
, res
->resy
);
320 LoadStringW(PSDRV_hInstance
, IDS_DPI
, buf
+ len
, sizeof(buf
)/sizeof(buf
[0]) - len
);
321 idx
= SendDlgItemMessageW(hwnd
, IDD_QUALITY
, CB_ADDSTRING
, 0, (LPARAM
)buf
);
322 SendDlgItemMessageW(hwnd
, IDD_QUALITY
, CB_SETITEMDATA
, idx
, MAKELONG(res
->resx
, res
->resy
));
324 if (res
->resx
== resx
&& res
->resy
== resy
)
328 SendDlgItemMessageW(hwnd
, IDD_QUALITY
, CB_SETCURSEL
, Cursel
, 0);
333 di
= (PSDRV_DLGINFO
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
334 switch(LOWORD(wParam
)) {
336 if(HIWORD(wParam
) == LBN_SELCHANGE
) {
337 Cursel
= SendDlgItemMessageA(hwnd
, LOWORD(wParam
), LB_GETCURSEL
, 0, 0);
339 LIST_FOR_EACH_ENTRY(ps
, &di
->pi
->ppd
->PageSizes
, PAGESIZE
, entry
) {
340 if(i
>= Cursel
) break;
343 TRACE("Setting pagesize to item %d, WinPage %d (%s), PaperSize %.2fx%.2f\n", Cursel
,
344 ps
->WinPage
, ps
->FullName
, ps
->PaperDimension
->x
, ps
->PaperDimension
->y
);
345 di
->dlgdm
->dmPublic
.u1
.s1
.dmPaperSize
= ps
->WinPage
;
346 di
->dlgdm
->dmPublic
.dmFields
|= DM_PAPERSIZE
;
348 di
->dlgdm
->dmPublic
.u1
.s1
.dmPaperWidth
= paper_size_from_points(ps
->PaperDimension
->x
);
349 di
->dlgdm
->dmPublic
.u1
.s1
.dmPaperLength
= paper_size_from_points(ps
->PaperDimension
->y
);
350 di
->dlgdm
->dmPublic
.dmFields
|= DM_PAPERLENGTH
| DM_PAPERWIDTH
;
352 if (di
->dlgdm
->dmPublic
.dmSize
>= FIELD_OFFSET(DEVMODEW
, dmFormName
) + CCHFORMNAME
* sizeof(WCHAR
))
354 MultiByteToWideChar(CP_ACP
, 0, ps
->FullName
, -1, di
->dlgdm
->dmPublic
.dmFormName
, CCHFORMNAME
);
355 di
->dlgdm
->dmPublic
.dmFields
|= DM_FORMNAME
;
357 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, 0, 0);
360 case IDD_ORIENT_PORTRAIT
:
361 case IDD_ORIENT_LANDSCAPE
:
362 TRACE("Setting orientation to %s\n", wParam
== IDD_ORIENT_PORTRAIT
?
363 "portrait" : "landscape");
364 di
->dlgdm
->dmPublic
.u1
.s1
.dmOrientation
= wParam
== IDD_ORIENT_PORTRAIT
?
365 DMORIENT_PORTRAIT
: DMORIENT_LANDSCAPE
;
366 di
->dlgdm
->dmPublic
.dmFields
|= DM_ORIENTATION
;
367 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, 0, 0);
370 if(HIWORD(wParam
) == CBN_SELCHANGE
) {
371 Cursel
= SendDlgItemMessageA(hwnd
, LOWORD(wParam
), CB_GETCURSEL
, 0, 0);
373 LIST_FOR_EACH_ENTRY( duplex
, &di
->pi
->ppd
->Duplexes
, DUPLEX
, entry
)
375 if (i
>= Cursel
) break;
378 TRACE("Setting duplex to item %d Winduplex = %d\n", Cursel
, duplex
->WinDuplex
);
379 di
->dlgdm
->dmPublic
.dmDuplex
= duplex
->WinDuplex
;
380 di
->dlgdm
->dmPublic
.dmFields
|= DM_DUPLEX
;
381 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, 0, 0);
386 if (HIWORD(wParam
) == CBN_SELCHANGE
)
391 Cursel
= SendDlgItemMessageW(hwnd
, LOWORD(wParam
), CB_GETCURSEL
, 0, 0);
392 data
= SendDlgItemMessageW(hwnd
, IDD_QUALITY
, CB_GETITEMDATA
, Cursel
, 0);
396 TRACE("Setting resolution to %dx%d\n", resx
, resy
);
398 di
->dlgdm
->dmPublic
.u1
.s1
.dmPrintQuality
= resx
;
399 di
->dlgdm
->dmPublic
.dmFields
|= DM_PRINTQUALITY
;
401 di
->dlgdm
->dmPublic
.dmYResolution
= resy
;
402 di
->dlgdm
->dmPublic
.dmFields
|= DM_YRESOLUTION
;
404 if (di
->pi
->Devmode
->dmPublic
.dmFields
& DM_LOGPIXELS
)
406 di
->dlgdm
->dmPublic
.dmLogPixels
= resx
;
407 di
->dlgdm
->dmPublic
.dmFields
|= DM_LOGPIXELS
;
410 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, 0, 0);
418 NMHDR
*nmhdr
= (NMHDR
*)lParam
;
419 di
= (PSDRV_DLGINFO
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
420 switch(nmhdr
->code
) {
422 *di
->pi
->Devmode
= *di
->dlgdm
;
423 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, PSNRET_NOERROR
);
439 static HPROPSHEETPAGE (WINAPI
*pCreatePropertySheetPage
) (LPCPROPSHEETPAGEW
);
440 static int (WINAPI
*pPropertySheet
) (LPCPROPSHEETHEADERW
);
442 static PRINTERINFO
*PSDRV_FindPrinterInfoA(LPCSTR name
)
444 int len
= MultiByteToWideChar( CP_ACP
, 0, name
, -1, NULL
, 0 );
445 WCHAR
*nameW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
448 MultiByteToWideChar( CP_ACP
, 0, name
, -1, nameW
, len
);
449 pi
= PSDRV_FindPrinterInfo( nameW
);
450 HeapFree( GetProcessHeap(), 0, nameW
);
455 /***********************************************************
458 * Creates an ascii copy of supplied devmode on the process heap
460 * Copied from dlls/winspool/info.c until full unicodification
462 static DEVMODEA
*DEVMODEdupWtoA( const DEVMODEW
*dmW
)
467 /* there is no pointer dereference here, if your code checking tool complains it's broken */
468 ptrdiff_t off_formname
= (const char *)dmW
->dmFormName
- (const char *)dmW
;
470 if (!dmW
) return NULL
;
471 formname
= (dmW
->dmSize
> off_formname
);
472 size
= dmW
->dmSize
- CCHDEVICENAME
- (formname
? CCHFORMNAME
: 0);
473 dmA
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, size
+ dmW
->dmDriverExtra
);
474 WideCharToMultiByte( CP_ACP
, 0, dmW
->dmDeviceName
, -1, (LPSTR
)dmA
->dmDeviceName
,
475 CCHDEVICENAME
, NULL
, NULL
);
478 memcpy( &dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
479 dmW
->dmSize
- CCHDEVICENAME
* sizeof(WCHAR
) );
483 memcpy( &dmA
->dmSpecVersion
, &dmW
->dmSpecVersion
,
484 off_formname
- CCHDEVICENAME
* sizeof(WCHAR
) );
485 WideCharToMultiByte( CP_ACP
, 0, dmW
->dmFormName
, -1, (LPSTR
)dmA
->dmFormName
,
486 CCHFORMNAME
, NULL
, NULL
);
487 memcpy( &dmA
->dmLogPixels
, &dmW
->dmLogPixels
, dmW
->dmSize
-
488 (off_formname
+ CCHFORMNAME
* sizeof(WCHAR
)) );
491 memcpy( (char *)dmA
+ dmA
->dmSize
, (const char *)dmW
+ dmW
->dmSize
,
492 dmW
->dmDriverExtra
);
496 /******************************************************************
497 * PSDRV_ExtDeviceMode
499 * Retrieves or modifies device-initialization information for the PostScript
500 * driver, or displays a driver-supplied dialog box for configuring the driver.
503 * lpszDriver -- Driver name
504 * hwnd -- Parent window for the dialog box
505 * lpdmOutput -- Address of a DEVMODE structure for writing initialization information
506 * lpszDevice -- Device name
507 * lpszPort -- Port name
508 * lpdmInput -- Address of a DEVMODE structure for reading initialization information
509 * lpProfile -- Name of initialization file, defaults to WIN.INI if NULL
510 * wMode -- Operation to perform. Can be a combination if > 0.
511 * (0) -- Returns number of bytes required by DEVMODE structure
512 * DM_UPDATE (1) -- Write current settings to environment and initialization file
513 * DM_COPY (2) -- Write current settings to lpdmOutput
514 * DM_PROMPT (4) -- Presents the driver's modal dialog box (USER.240)
515 * DM_MODIFY (8) -- Changes current settings according to lpdmInput before any other operation
518 * Returns size of DEVMODE structure if wMode is 0. Otherwise, IDOK is returned for success
519 * for both dialog and non-dialog operations. IDCANCEL is returned if the dialog box was cancelled.
520 * A return value less than zero is returned if a non-dialog operation fails.
524 * Just returns default devmode at the moment. No use of initialization file.
526 INT
PSDRV_ExtDeviceMode(LPSTR lpszDriver
, HWND hwnd
, LPDEVMODEA lpdmOutput
,
527 LPSTR lpszDevice
, LPSTR lpszPort
, LPDEVMODEA lpdmInput
,
528 LPSTR lpszProfile
, DWORD dwMode
)
530 PRINTERINFO
*pi
= PSDRV_FindPrinterInfoA(lpszDevice
);
533 TRACE("(Driver=%s, hwnd=%p, devOut=%p, Device='%s', Port='%s', devIn=%p, Profile='%s', Mode=%04x)\n",
534 lpszDriver
, hwnd
, lpdmOutput
, lpszDevice
, lpszPort
, lpdmInput
, debugstr_a(lpszProfile
), dwMode
);
536 /* If dwMode == 0, return size of DEVMODE structure */
538 return pi
->Devmode
->dmPublic
.dmSize
+ pi
->Devmode
->dmPublic
.dmDriverExtra
- CCHDEVICENAME
- CCHFORMNAME
;
540 /* If DM_MODIFY is set, change settings in accordance with lpdmInput */
541 if((dwMode
& DM_MODIFY
) && lpdmInput
)
543 DEVMODEW
*dmW
= GdiConvertToDevmodeW( lpdmInput
);
544 TRACE("DM_MODIFY set. devIn->dmFields = %08x\n", lpdmInput
->dmFields
);
545 if (dmW
) PSDRV_MergeDevmodes(pi
->Devmode
, (PSDRV_DEVMODE
*)dmW
, pi
);
546 HeapFree( GetProcessHeap(), 0, dmW
);
549 /* If DM_PROMPT is set, present modal dialog box */
550 if(dwMode
& DM_PROMPT
) {
551 HINSTANCE hinstComctl32
;
552 HPROPSHEETPAGE hpsp
[1];
554 PROPSHEETHEADERW psh
;
558 static const WCHAR PAPERW
[] = {'P','A','P','E','R','\0'};
560 LoadStringW(PSDRV_hInstance
, IDS_SETUP
, SetupW
, sizeof(SetupW
)/sizeof(SetupW
[0]));
561 hinstComctl32
= LoadLibraryA("comctl32.dll");
562 pCreatePropertySheetPage
= (void*)GetProcAddress(hinstComctl32
,
563 "CreatePropertySheetPageW");
564 pPropertySheet
= (void*)GetProcAddress(hinstComctl32
, "PropertySheetW");
565 memset(&psp
,0,sizeof(psp
));
566 dlgdm
= *pi
->Devmode
;
569 psp
.dwSize
= sizeof(psp
);
570 psp
.hInstance
= PSDRV_hInstance
;
571 psp
.u
.pszTemplate
= PAPERW
;
572 psp
.u2
.pszIcon
= NULL
;
573 psp
.pfnDlgProc
= PSDRV_PaperDlgProc
;
574 psp
.lParam
= (LPARAM
)&di
;
575 hpsp
[0] = pCreatePropertySheetPage(&psp
);
577 memset(&psh
, 0, sizeof(psh
));
578 psh
.dwSize
= sizeof(psh
);
579 psh
.pszCaption
= SetupW
;
581 psh
.hwndParent
= hwnd
;
582 psh
.u3
.phpage
= hpsp
;
584 pPropertySheet(&psh
);
588 /* If DM_UPDATE is set, should write settings to environment and initialization file */
589 if(dwMode
& DM_UPDATE
)
590 FIXME("Mode DM_UPDATE. Just do the same as DM_COPY\n");
592 /* If DM_COPY is set, should write settings to lpdmOutput */
593 if((dwMode
& DM_COPY
) || (dwMode
& DM_UPDATE
)) {
596 DEVMODEA
*dmA
= DEVMODEdupWtoA( &pi
->Devmode
->dmPublic
);
597 if (dmA
) memcpy( lpdmOutput
, dmA
, dmA
->dmSize
+ dmA
->dmDriverExtra
);
598 HeapFree( GetProcessHeap(), 0, dmA
);
601 FIXME("lpdmOutput is NULL what should we do??\n");
605 /***********************************************************************
606 * PSDRV_DeviceCapabilities
608 * Retrieves the capabilities of a printer device driver.
611 * lpszDriver -- printer driver name
612 * lpszDevice -- printer name
613 * lpszPort -- port name
614 * fwCapability -- device capability
615 * lpszOutput -- output buffer
616 * lpDevMode -- device data buffer
619 * Result depends on the setting of fwCapability. -1 indicates failure.
621 DWORD
PSDRV_DeviceCapabilities(LPSTR lpszDriver
, LPCSTR lpszDevice
, LPCSTR lpszPort
,
622 WORD fwCapability
, LPSTR lpszOutput
, LPDEVMODEA lpDevMode
)
627 pi
= PSDRV_FindPrinterInfoA(lpszDevice
);
629 TRACE("%s %s %s, %u, %p, %p\n", debugstr_a(lpszDriver
), debugstr_a(lpszDevice
),
630 debugstr_a(lpszPort
), fwCapability
, lpszOutput
, lpDevMode
);
633 ERR("no printer info for %s %s, return 0!\n",
634 debugstr_a(lpszDriver
), debugstr_a(lpszDevice
));
638 lpdm
= &pi
->Devmode
->dmPublic
;
639 if (lpDevMode
) lpdm
= GdiConvertToDevmodeW( lpDevMode
);
641 switch(fwCapability
) {
646 WORD
*wp
= (WORD
*)lpszOutput
;
649 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
651 TRACE("DC_PAPERS: %u\n", ps
->WinPage
);
653 if(lpszOutput
!= NULL
)
663 POINT16
*pt
= (POINT16
*)lpszOutput
;
666 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
668 TRACE("DC_PAPERSIZE: %f x %f\n", ps
->PaperDimension
->x
, ps
->PaperDimension
->y
);
670 if(lpszOutput
!= NULL
) {
671 pt
->x
= paper_size_from_points( ps
->PaperDimension
->x
);
672 pt
->y
= paper_size_from_points( ps
->PaperDimension
->y
);
683 char *cp
= lpszOutput
;
686 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
688 TRACE("DC_PAPERNAMES: %s\n", debugstr_a(ps
->FullName
));
690 if(lpszOutput
!= NULL
) {
691 lstrcpynA(cp
, ps
->FullName
, 64);
700 ret
= pi
->ppd
->LandscapeOrientation
? pi
->ppd
->LandscapeOrientation
: 90;
706 WORD
*wp
= (WORD
*)lpszOutput
;
709 LIST_FOR_EACH_ENTRY( slot
, &pi
->ppd
->InputSlots
, INPUTSLOT
, entry
)
712 if (lpszOutput
!= NULL
)
713 *wp
++ = slot
->WinBin
;
722 char *cp
= lpszOutput
;
725 LIST_FOR_EACH_ENTRY( slot
, &pi
->ppd
->InputSlots
, INPUTSLOT
, entry
)
728 if (lpszOutput
!= NULL
)
730 lstrcpynA( cp
, slot
->FullName
, 24 );
739 FIXME("DC_BINADJUST: stub.\n");
740 ret
= DCBA_FACEUPNONE
;
743 case DC_ENUMRESOLUTIONS
:
746 LONG
*lp
= (LONG
*)lpszOutput
;
749 LIST_FOR_EACH_ENTRY(res
, &pi
->ppd
->Resolutions
, RESOLUTION
, entry
)
752 if (lpszOutput
!= NULL
)
763 /* Windows returns 9999 too */
765 TRACE("DC_COPIES: returning 9999\n");
770 ret
= lpdm
->dmDriverVersion
;
773 case DC_DATATYPE_PRODUCED
:
774 FIXME("DATA_TYPE_PRODUCED: stub.\n");
775 ret
= -1; /* simulate that the driver supports 'RAW' */
780 if(pi
->ppd
->DefaultDuplex
&& pi
->ppd
->DefaultDuplex
->WinDuplex
!= 0)
782 TRACE("DC_DUPLEX: returning %d\n", ret
);
785 case DC_EMF_COMPLIANT
:
786 FIXME("DC_EMF_COMPLIANT: stub.\n");
787 ret
= -1; /* simulate that the driver do not support EMF */
791 ret
= lpdm
->dmDriverExtra
;
795 ret
= lpdm
->dmFields
;
798 case DC_FILEDEPENDENCIES
:
799 FIXME("DC_FILEDEPENDENCIES: stub.\n");
808 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
810 if (ps
->PaperDimension
->x
> x
) x
= ps
->PaperDimension
->x
;
811 if (ps
->PaperDimension
->y
> y
) y
= ps
->PaperDimension
->y
;
813 ret
= MAKELONG( paper_size_from_points(x
), paper_size_from_points(y
) );
820 float x
= 1e6
, y
= 1e6
;
822 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
824 if (ps
->PaperDimension
->x
< x
) x
= ps
->PaperDimension
->x
;
825 if (ps
->PaperDimension
->y
< y
) y
= ps
->PaperDimension
->y
;
827 ret
= MAKELONG( paper_size_from_points(x
), paper_size_from_points(y
) );
836 FIXME("DC_TRUETYPE: stub\n");
841 ret
= lpdm
->dmSpecVersion
;
844 /* We'll just return false here, very few printers can collate anyway */
846 TRACE("DC_COLLATE: returning FALSE\n");
850 /* Printer supports colour printing - 1 if yes, 0 if no (Win2k/XP only) */
852 ret
= pi
->ppd
->ColorDevice
!= CD_False
;
855 /* Identification number of the printer manufacturer for use with ICM (Win9x only) */
856 case DC_MANUFACTURER
:
857 FIXME("DC_MANUFACTURER: stub\n");
861 /* Identification number of the printer model for use with ICM (Win9x only) */
863 FIXME("DC_MODEL: stub\n");
867 /* Nonzero if the printer supports stapling, zero otherwise (Win2k/XP only) */
868 case DC_STAPLE
: /* WINVER >= 0x0500 */
869 FIXME("DC_STAPLE: stub\n");
873 /* Returns an array of 64-character string buffers containing the names of the paper forms
874 * available for use, unless pOutput is NULL. The return value is the number of paper forms.
877 case DC_MEDIAREADY
: /* WINVER >= 0x0500 */
878 FIXME("DC_MEDIAREADY: stub\n");
882 /* Returns an array of 64-character string buffers containing the names of the supported
883 * media types, unless pOutput is NULL. The return value is the number of supported.
884 * media types (XP only)
886 case DC_MEDIATYPENAMES
: /* WINVER >= 0x0501 */
887 FIXME("DC_MEDIATYPENAMES: stub\n");
891 /* Returns an array of DWORD values which represent the supported media types, unless
892 * pOutput is NULL. The return value is the number of supported media types. (XP only)
894 case DC_MEDIATYPES
: /* WINVER >= 0x0501 */
895 FIXME("DC_MEDIATYPES: stub\n");
899 /* Returns an array of DWORD values, each representing a supported number of document
900 * pages per printed page, unless pOutput is NULL. The return value is the number of
901 * array entries. (Win2k/XP only)
904 FIXME("DC_NUP: stub\n");
908 /* Returns an array of 32-character string buffers containing a list of printer description
909 * languages supported by the printer, unless pOutput is NULL. The return value is
910 * number of array entries. (Win2k/XP only)
913 case DC_PERSONALITY
: /* WINVER >= 0x0500 */
914 FIXME("DC_PERSONALITY: stub\n");
918 /* Returns the amount of printer memory in kilobytes. (Win2k/XP only) */
919 case DC_PRINTERMEM
: /* WINVER >= 0x0500 */
920 FIXME("DC_PRINTERMEM: stub\n");
924 /* Returns the printer's print rate in PRINTRATEUNIT units. (Win2k/XP only) */
925 case DC_PRINTRATE
: /* WINVER >= 0x0500 */
926 FIXME("DC_PRINTRATE: stub\n");
930 /* Returns the printer's print rate in pages per minute. (Win2k/XP only) */
931 case DC_PRINTRATEPPM
: /* WINVER >= 0x0500 */
932 FIXME("DC_PRINTRATEPPM: stub\n");
936 /* Returns the printer rate unit used for DC_PRINTRATE, which is one of
937 * PRINTRATEUNIT_{CPS,IPM,LPM,PPM} (Win2k/XP only)
939 case DC_PRINTRATEUNIT
: /* WINVER >= 0x0500 */
940 FIXME("DC_PRINTRATEUNIT: stub\n");
945 FIXME("Unsupported capability %d\n", fwCapability
);
949 if (lpDevMode
) HeapFree( GetProcessHeap(), 0, lpdm
);
957 HPROPSHEETPAGE hPages
[10];
960 INT
PSDRV_ExtDeviceModePropSheet(HWND hwnd
, LPSTR lpszDevice
, LPSTR lpszPort
,
963 EDMPS
*ps
= pPropSheet
;
966 psp
->dwSize
= sizeof(psp
);
967 psp
->hInstance
= 0x1234;