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
;
557 static const WCHAR PAPERW
[] = {'P','A','P','E','R','\0'};
558 static const WCHAR SetupW
[] = {'S','e','t','u','p','\0'};
560 hinstComctl32
= LoadLibraryA("comctl32.dll");
561 pCreatePropertySheetPage
= (void*)GetProcAddress(hinstComctl32
,
562 "CreatePropertySheetPageW");
563 pPropertySheet
= (void*)GetProcAddress(hinstComctl32
, "PropertySheetW");
564 memset(&psp
,0,sizeof(psp
));
565 dlgdm
= *pi
->Devmode
;
568 psp
.dwSize
= sizeof(psp
);
569 psp
.hInstance
= PSDRV_hInstance
;
570 psp
.u
.pszTemplate
= PAPERW
;
571 psp
.u2
.pszIcon
= NULL
;
572 psp
.pfnDlgProc
= PSDRV_PaperDlgProc
;
573 psp
.lParam
= (LPARAM
)&di
;
574 hpsp
[0] = pCreatePropertySheetPage(&psp
);
576 memset(&psh
, 0, sizeof(psh
));
577 psh
.dwSize
= sizeof(psh
);
578 psh
.pszCaption
= SetupW
;
580 psh
.hwndParent
= hwnd
;
581 psh
.u3
.phpage
= hpsp
;
583 pPropertySheet(&psh
);
587 /* If DM_UPDATE is set, should write settings to environment and initialization file */
588 if(dwMode
& DM_UPDATE
)
589 FIXME("Mode DM_UPDATE. Just do the same as DM_COPY\n");
591 /* If DM_COPY is set, should write settings to lpdmOutput */
592 if((dwMode
& DM_COPY
) || (dwMode
& DM_UPDATE
)) {
595 DEVMODEA
*dmA
= DEVMODEdupWtoA( &pi
->Devmode
->dmPublic
);
596 if (dmA
) memcpy( lpdmOutput
, dmA
, dmA
->dmSize
+ dmA
->dmDriverExtra
);
597 HeapFree( GetProcessHeap(), 0, dmA
);
600 FIXME("lpdmOutput is NULL what should we do??\n");
604 /***********************************************************************
605 * PSDRV_DeviceCapabilities
607 * Retrieves the capabilities of a printer device driver.
610 * lpszDriver -- printer driver name
611 * lpszDevice -- printer name
612 * lpszPort -- port name
613 * fwCapability -- device capability
614 * lpszOutput -- output buffer
615 * lpDevMode -- device data buffer
618 * Result depends on the setting of fwCapability. -1 indicates failure.
620 DWORD
PSDRV_DeviceCapabilities(LPSTR lpszDriver
, LPCSTR lpszDevice
, LPCSTR lpszPort
,
621 WORD fwCapability
, LPSTR lpszOutput
, LPDEVMODEA lpDevMode
)
626 pi
= PSDRV_FindPrinterInfoA(lpszDevice
);
628 TRACE("%s %s %s, %u, %p, %p\n", debugstr_a(lpszDriver
), debugstr_a(lpszDevice
),
629 debugstr_a(lpszPort
), fwCapability
, lpszOutput
, lpDevMode
);
632 ERR("no printer info for %s %s, return 0!\n",
633 debugstr_a(lpszDriver
), debugstr_a(lpszDevice
));
637 lpdm
= &pi
->Devmode
->dmPublic
;
638 if (lpDevMode
) lpdm
= GdiConvertToDevmodeW( lpDevMode
);
640 switch(fwCapability
) {
645 WORD
*wp
= (WORD
*)lpszOutput
;
648 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
650 TRACE("DC_PAPERS: %u\n", ps
->WinPage
);
652 if(lpszOutput
!= NULL
)
662 POINT16
*pt
= (POINT16
*)lpszOutput
;
665 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
667 TRACE("DC_PAPERSIZE: %f x %f\n", ps
->PaperDimension
->x
, ps
->PaperDimension
->y
);
669 if(lpszOutput
!= NULL
) {
670 pt
->x
= paper_size_from_points( ps
->PaperDimension
->x
);
671 pt
->y
= paper_size_from_points( ps
->PaperDimension
->y
);
682 char *cp
= lpszOutput
;
685 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
687 TRACE("DC_PAPERNAMES: %s\n", debugstr_a(ps
->FullName
));
689 if(lpszOutput
!= NULL
) {
690 lstrcpynA(cp
, ps
->FullName
, 64);
699 ret
= pi
->ppd
->LandscapeOrientation
? pi
->ppd
->LandscapeOrientation
: 90;
705 WORD
*wp
= (WORD
*)lpszOutput
;
708 LIST_FOR_EACH_ENTRY( slot
, &pi
->ppd
->InputSlots
, INPUTSLOT
, entry
)
711 if (lpszOutput
!= NULL
)
712 *wp
++ = slot
->WinBin
;
721 char *cp
= lpszOutput
;
724 LIST_FOR_EACH_ENTRY( slot
, &pi
->ppd
->InputSlots
, INPUTSLOT
, entry
)
727 if (lpszOutput
!= NULL
)
729 lstrcpynA( cp
, slot
->FullName
, 24 );
738 FIXME("DC_BINADJUST: stub.\n");
739 ret
= DCBA_FACEUPNONE
;
742 case DC_ENUMRESOLUTIONS
:
745 LONG
*lp
= (LONG
*)lpszOutput
;
748 LIST_FOR_EACH_ENTRY(res
, &pi
->ppd
->Resolutions
, RESOLUTION
, entry
)
751 if (lpszOutput
!= NULL
)
762 /* Windows returns 9999 too */
764 TRACE("DC_COPIES: returning 9999\n");
769 ret
= lpdm
->dmDriverVersion
;
772 case DC_DATATYPE_PRODUCED
:
773 FIXME("DATA_TYPE_PRODUCED: stub.\n");
774 ret
= -1; /* simulate that the driver supports 'RAW' */
779 if(pi
->ppd
->DefaultDuplex
&& pi
->ppd
->DefaultDuplex
->WinDuplex
!= 0)
781 TRACE("DC_DUPLEX: returning %d\n", ret
);
784 case DC_EMF_COMPLIANT
:
785 FIXME("DC_EMF_COMPLIANT: stub.\n");
786 ret
= -1; /* simulate that the driver do not support EMF */
790 ret
= lpdm
->dmDriverExtra
;
794 ret
= lpdm
->dmFields
;
797 case DC_FILEDEPENDENCIES
:
798 FIXME("DC_FILEDEPENDENCIES: stub.\n");
807 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
809 if (ps
->PaperDimension
->x
> x
) x
= ps
->PaperDimension
->x
;
810 if (ps
->PaperDimension
->y
> y
) y
= ps
->PaperDimension
->y
;
812 ret
= MAKELONG( paper_size_from_points(x
), paper_size_from_points(y
) );
819 float x
= 1e6
, y
= 1e6
;
821 LIST_FOR_EACH_ENTRY(ps
, &pi
->ppd
->PageSizes
, PAGESIZE
, entry
)
823 if (ps
->PaperDimension
->x
< x
) x
= ps
->PaperDimension
->x
;
824 if (ps
->PaperDimension
->y
< y
) y
= ps
->PaperDimension
->y
;
826 ret
= MAKELONG( paper_size_from_points(x
), paper_size_from_points(y
) );
835 FIXME("DC_TRUETYPE: stub\n");
840 ret
= lpdm
->dmSpecVersion
;
843 /* We'll just return false here, very few printers can collate anyway */
845 TRACE("DC_COLLATE: returning FALSE\n");
849 /* Printer supports colour printing - 1 if yes, 0 if no (Win2k/XP only) */
851 ret
= pi
->ppd
->ColorDevice
!= CD_False
;
854 /* Identification number of the printer manufacturer for use with ICM (Win9x only) */
855 case DC_MANUFACTURER
:
856 FIXME("DC_MANUFACTURER: stub\n");
860 /* Identification number of the printer model for use with ICM (Win9x only) */
862 FIXME("DC_MODEL: stub\n");
866 /* Nonzero if the printer supports stapling, zero otherwise (Win2k/XP only) */
867 case DC_STAPLE
: /* WINVER >= 0x0500 */
868 FIXME("DC_STAPLE: stub\n");
872 /* Returns an array of 64-character string buffers containing the names of the paper forms
873 * available for use, unless pOutput is NULL. The return value is the number of paper forms.
876 case DC_MEDIAREADY
: /* WINVER >= 0x0500 */
877 FIXME("DC_MEDIAREADY: stub\n");
881 /* Returns an array of 64-character string buffers containing the names of the supported
882 * media types, unless pOutput is NULL. The return value is the number of supported.
883 * media types (XP only)
885 case DC_MEDIATYPENAMES
: /* WINVER >= 0x0501 */
886 FIXME("DC_MEDIATYPENAMES: stub\n");
890 /* Returns an array of DWORD values which represent the supported media types, unless
891 * pOutput is NULL. The return value is the number of supported media types. (XP only)
893 case DC_MEDIATYPES
: /* WINVER >= 0x0501 */
894 FIXME("DC_MEDIATYPES: stub\n");
898 /* Returns an array of DWORD values, each representing a supported number of document
899 * pages per printed page, unless pOutput is NULL. The return value is the number of
900 * array entries. (Win2k/XP only)
903 FIXME("DC_NUP: stub\n");
907 /* Returns an array of 32-character string buffers containing a list of printer description
908 * languages supported by the printer, unless pOutput is NULL. The return value is
909 * number of array entries. (Win2k/XP only)
912 case DC_PERSONALITY
: /* WINVER >= 0x0500 */
913 FIXME("DC_PERSONALITY: stub\n");
917 /* Returns the amount of printer memory in kilobytes. (Win2k/XP only) */
918 case DC_PRINTERMEM
: /* WINVER >= 0x0500 */
919 FIXME("DC_PRINTERMEM: stub\n");
923 /* Returns the printer's print rate in PRINTRATEUNIT units. (Win2k/XP only) */
924 case DC_PRINTRATE
: /* WINVER >= 0x0500 */
925 FIXME("DC_PRINTRATE: stub\n");
929 /* Returns the printer's print rate in pages per minute. (Win2k/XP only) */
930 case DC_PRINTRATEPPM
: /* WINVER >= 0x0500 */
931 FIXME("DC_PRINTRATEPPM: stub\n");
935 /* Returns the printer rate unit used for DC_PRINTRATE, which is one of
936 * PRINTRATEUNIT_{CPS,IPM,LPM,PPM} (Win2k/XP only)
938 case DC_PRINTRATEUNIT
: /* WINVER >= 0x0500 */
939 FIXME("DC_PRINTRATEUNIT: stub\n");
944 FIXME("Unsupported capability %d\n", fwCapability
);
948 if (lpDevMode
) HeapFree( GetProcessHeap(), 0, lpdm
);
956 HPROPSHEETPAGE hPages
[10];
959 INT
PSDRV_ExtDeviceModePropSheet(HWND hwnd
, LPSTR lpszDevice
, LPSTR lpszPort
,
962 EDMPS
*ps
= pPropSheet
;
965 psp
->dwSize
= sizeof(psp
);
966 psp
->hInstance
= 0x1234;