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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
30 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
40 /************************************************************************
44 * Updates dm1 with some fields from dm2
47 void PSDRV_MergeDevmodes(PSDRV_DEVMODEA *dm1, PSDRV_DEVMODEA *dm2,
50 /* some sanity checks here on dm2 */
52 if(dm2->dmPublic.dmFields & DM_ORIENTATION) {
53 dm1->dmPublic.u1.s1.dmOrientation = dm2->dmPublic.u1.s1.dmOrientation;
54 TRACE("Changing orientation to %d (%s)\n",
55 dm1->dmPublic.u1.s1.dmOrientation,
56 dm1->dmPublic.u1.s1.dmOrientation == DMORIENT_PORTRAIT ?
58 (dm1->dmPublic.u1.s1.dmOrientation == DMORIENT_LANDSCAPE ?
59 "Landscape" : "unknown"));
62 /* NB PaperWidth is always < PaperLength */
63 if(dm2->dmPublic.dmFields & DM_PAPERSIZE) {
66 for(page = pi->ppd->PageSizes; page; page = page->next) {
67 if(page->WinPage == dm2->dmPublic.u1.s1.dmPaperSize)
71 dm1->dmPublic.u1.s1.dmPaperSize = dm2->dmPublic.u1.s1.dmPaperSize;
72 dm1->dmPublic.u1.s1.dmPaperWidth = page->PaperDimension->x *
74 dm1->dmPublic.u1.s1.dmPaperLength = page->PaperDimension->y *
76 dm1->dmPublic.dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH);
77 dm1->dmPublic.dmFields |= DM_PAPERSIZE;
78 TRACE("Changing page to %s %d x %d\n", page->FullName,
79 dm1->dmPublic.u1.s1.dmPaperWidth,
80 dm1->dmPublic.u1.s1.dmPaperLength );
82 TRACE("Trying to change to unsupported pagesize %d\n",
83 dm2->dmPublic.u1.s1.dmPaperSize);
85 } else if((dm2->dmPublic.dmFields & DM_PAPERLENGTH) &&
86 (dm2->dmPublic.dmFields & DM_PAPERWIDTH)) {
87 dm1->dmPublic.u1.s1.dmPaperLength = dm2->dmPublic.u1.s1.dmPaperLength;
88 dm1->dmPublic.u1.s1.dmPaperWidth = dm2->dmPublic.u1.s1.dmPaperWidth;
89 TRACE("Changing PaperLength|Width to %dx%d\n",
90 dm2->dmPublic.u1.s1.dmPaperLength,
91 dm2->dmPublic.u1.s1.dmPaperWidth);
92 dm1->dmPublic.dmFields &= ~DM_PAPERSIZE;
93 dm1->dmPublic.dmFields |= (DM_PAPERLENGTH | DM_PAPERWIDTH);
94 } else if(dm2->dmPublic.dmFields & (DM_PAPERLENGTH | DM_PAPERWIDTH)) {
95 /* You might think that this would be allowed if dm1 is in custom size
96 mode, but apparently Windows reverts to standard paper mode even in
98 FIXME("Trying to change only paperlength or paperwidth\n");
99 dm1->dmPublic.dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH);
100 dm1->dmPublic.dmFields |= DM_PAPERSIZE;
103 if(dm2->dmPublic.dmFields & DM_SCALE) {
104 dm1->dmPublic.dmScale = dm2->dmPublic.dmScale;
105 TRACE("Changing Scale to %d\n", dm2->dmPublic.dmScale);
108 if(dm2->dmPublic.dmFields & DM_COPIES) {
109 dm1->dmPublic.dmCopies = dm2->dmPublic.dmCopies;
110 TRACE("Changing Copies to %d\n", dm2->dmPublic.dmCopies);
113 if(dm2->dmPublic.dmFields & DM_DEFAULTSOURCE) {
116 for(slot = pi->ppd->InputSlots; slot; slot = slot->next) {
117 if(slot->WinBin == dm2->dmPublic.dmDefaultSource)
121 dm1->dmPublic.dmDefaultSource = dm2->dmPublic.dmDefaultSource;
122 TRACE("Changing bin to '%s'\n", slot->FullName);
124 TRACE("Trying to change to unsupported bin %d\n",
125 dm2->dmPublic.dmDefaultSource);
129 if (dm2->dmPublic.dmFields & DM_DEFAULTSOURCE )
130 dm1->dmPublic.dmDefaultSource = dm2->dmPublic.dmDefaultSource;
131 if (dm2->dmPublic.dmFields & DM_PRINTQUALITY )
132 dm1->dmPublic.dmPrintQuality = dm2->dmPublic.dmPrintQuality;
133 if (dm2->dmPublic.dmFields & DM_COLOR )
134 dm1->dmPublic.dmColor = dm2->dmPublic.dmColor;
135 if (dm2->dmPublic.dmFields & DM_DUPLEX )
136 dm1->dmPublic.dmDuplex = dm2->dmPublic.dmDuplex;
137 if (dm2->dmPublic.dmFields & DM_YRESOLUTION )
138 dm1->dmPublic.dmYResolution = dm2->dmPublic.dmYResolution;
139 if (dm2->dmPublic.dmFields & DM_TTOPTION )
140 dm1->dmPublic.dmTTOption = dm2->dmPublic.dmTTOption;
141 if (dm2->dmPublic.dmFields & DM_COLLATE )
142 dm1->dmPublic.dmCollate = dm2->dmPublic.dmCollate;
143 if (dm2->dmPublic.dmFields & DM_FORMNAME )
144 lstrcpynA(dm1->dmPublic.dmFormName, dm2->dmPublic.dmFormName, CCHFORMNAME);
145 if (dm2->dmPublic.dmFields & DM_BITSPERPEL )
146 dm1->dmPublic.dmBitsPerPel = dm2->dmPublic.dmBitsPerPel;
147 if (dm2->dmPublic.dmFields & DM_PELSWIDTH )
148 dm1->dmPublic.dmPelsWidth = dm2->dmPublic.dmPelsWidth;
149 if (dm2->dmPublic.dmFields & DM_PELSHEIGHT )
150 dm1->dmPublic.dmPelsHeight = dm2->dmPublic.dmPelsHeight;
151 if (dm2->dmPublic.dmFields & DM_DISPLAYFLAGS )
152 dm1->dmPublic.dmDisplayFlags = dm2->dmPublic.dmDisplayFlags;
153 if (dm2->dmPublic.dmFields & DM_DISPLAYFREQUENCY )
154 dm1->dmPublic.dmDisplayFrequency = dm2->dmPublic.dmDisplayFrequency;
155 if (dm2->dmPublic.dmFields & DM_POSITION )
156 dm1->dmPublic.u1.dmPosition = dm2->dmPublic.u1.dmPosition;
157 if (dm2->dmPublic.dmFields & DM_LOGPIXELS )
158 dm1->dmPublic.dmLogPixels = dm2->dmPublic.dmLogPixels;
159 if (dm2->dmPublic.dmFields & DM_ICMMETHOD )
160 dm1->dmPublic.dmICMMethod = dm2->dmPublic.dmICMMethod;
161 if (dm2->dmPublic.dmFields & DM_ICMINTENT )
162 dm1->dmPublic.dmICMIntent = dm2->dmPublic.dmICMIntent;
163 if (dm2->dmPublic.dmFields & DM_MEDIATYPE )
164 dm1->dmPublic.dmMediaType = dm2->dmPublic.dmMediaType;
165 if (dm2->dmPublic.dmFields & DM_DITHERTYPE )
166 dm1->dmPublic.dmDitherType = dm2->dmPublic.dmDitherType;
167 if (dm2->dmPublic.dmFields & DM_PANNINGWIDTH )
168 dm1->dmPublic.dmPanningWidth = dm2->dmPublic.dmPanningWidth;
169 if (dm2->dmPublic.dmFields & DM_PANNINGHEIGHT )
170 dm1->dmPublic.dmPanningHeight = dm2->dmPublic.dmPanningHeight;
176 /**************************************************************
177 * AdvancedSetupDialog [WINEPS16.93]
180 WORD WINAPI PSDRV_AdvancedSetupDialog16(HWND16 hwnd, HANDLE16 hDriver,
181 LPDEVMODEA devin, LPDEVMODEA devout)
184 TRACE("hwnd = %04x, hDriver = %04x devin=%p devout=%p\n", hwnd,
185 hDriver, devin, devout);
189 /****************************************************************
192 * Dialog proc for 'Paper' propsheet
194 INT_PTR CALLBACK PSDRV_PaperDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
204 di = (PSDRV_DLGINFO*)((PROPSHEETPAGEA*)lParam)->lParam;
205 SetWindowLongA(hwnd, DWL_USER, (LONG)di);
207 for(ps = di->pi->ppd->PageSizes, i = 0; ps; ps = ps->next, i++) {
208 SendDlgItemMessageA(hwnd, IDD_PAPERS, LB_INSERTSTRING, i,
209 (LPARAM)ps->FullName);
210 if(di->pi->Devmode->dmPublic.u1.s1.dmPaperSize == ps->WinPage)
213 SendDlgItemMessageA(hwnd, IDD_PAPERS, LB_SETCURSEL, Cursel, 0);
215 CheckRadioButton(hwnd, IDD_ORIENT_PORTRAIT, IDD_ORIENT_LANDSCAPE,
216 di->pi->Devmode->dmPublic.u1.s1.dmOrientation ==
217 DMORIENT_PORTRAIT ? IDD_ORIENT_PORTRAIT :
218 IDD_ORIENT_LANDSCAPE);
222 di = (PSDRV_DLGINFO *)GetWindowLongA(hwnd, DWL_USER);
223 switch(LOWORD(wParam)) {
225 if(HIWORD(wParam) == LBN_SELCHANGE) {
226 Cursel = SendDlgItemMessageA(hwnd, LOWORD(wParam), LB_GETCURSEL, 0, 0);
227 for(i = 0, ps = di->pi->ppd->PageSizes; i < Cursel; i++, ps = ps->next)
229 TRACE("Setting pagesize to item %d Winpage = %d\n", Cursel,
231 di->dlgdm->dmPublic.u1.s1.dmPaperSize = ps->WinPage;
234 case IDD_ORIENT_PORTRAIT:
235 case IDD_ORIENT_LANDSCAPE:
236 TRACE("Setting orientation to %s\n", wParam == IDD_ORIENT_PORTRAIT ?
237 "portrait" : "landscape");
238 di->dlgdm->dmPublic.u1.s1.dmOrientation = wParam == IDD_ORIENT_PORTRAIT ?
239 DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE;
246 NMHDR *nmhdr = (NMHDR *)lParam;
247 di = (PSDRV_DLGINFO *)GetWindowLongA(hwnd, DWL_USER);
248 switch(nmhdr->code) {
250 memcpy(di->pi->Devmode, di->dlgdm, sizeof(PSDRV_DEVMODEA));
251 SetWindowLongA(hwnd, DWL_MSGRESULT, PSNRET_NOERROR);
269 static void (WINAPI *pInitCommonControls) (void);
270 static HPROPSHEETPAGE (WINAPI *pCreatePropertySheetPage) (LPCPROPSHEETPAGEW);
271 static int (WINAPI *pPropertySheet) (LPCPROPSHEETHEADERW);
273 /***************************************************************
274 * ExtDeviceMode [WINEPS16.90]
276 * Just returns default devmode at the moment
278 INT16 WINAPI PSDRV_ExtDeviceMode16(HWND16 hwnd, HANDLE16 hDriver,
279 LPDEVMODEA lpdmOutput, LPSTR lpszDevice,
280 LPSTR lpszPort, LPDEVMODEA lpdmInput,
281 LPSTR lpszProfile, WORD fwMode)
283 PRINTERINFO *pi = PSDRV_FindPrinterInfo(lpszDevice);
286 TRACE("(hwnd=%04x, hDriver=%04x, devOut=%p, Device='%s', Port='%s', devIn=%p, Profile='%s', Mode=%04x)\n",
287 hwnd, hDriver, lpdmOutput, lpszDevice, lpszPort, lpdmInput, lpszProfile,
291 return pi->Devmode->dmPublic.dmSize + pi->Devmode->dmPublic.dmDriverExtra;
293 if((fwMode & DM_MODIFY) && lpdmInput) {
294 TRACE("DM_MODIFY set. devIn->dmFields = %08lx\n", lpdmInput->dmFields);
295 PSDRV_MergeDevmodes(pi->Devmode, (PSDRV_DEVMODEA *)lpdmInput, pi);
298 if(fwMode & DM_PROMPT) {
299 HINSTANCE hinstComctl32, hinstWineps32 = LoadLibraryA("WINEPS");
300 HPROPSHEETPAGE hpsp[1];
302 PROPSHEETHEADERW psh;
304 PSDRV_DEVMODEA *dlgdm;
305 static const WCHAR PAPERW[] = {'P','A','P','E','R','\0'};
306 static const WCHAR SetupW[] = {'S','e','t','u','p','\0'};
308 hinstComctl32 = LoadLibraryA("comctl32.dll");
309 pInitCommonControls = (void*)GetProcAddress(hinstComctl32,
310 "InitCommonControls");
311 pCreatePropertySheetPage = (void*)GetProcAddress(hinstComctl32,
312 "CreatePropertySheetPageW");
313 pPropertySheet = (void*)GetProcAddress(hinstComctl32, "PropertySheetW");
314 memset(&psp,0,sizeof(psp));
315 dlgdm = HeapAlloc( PSDRV_Heap, 0, sizeof(*dlgdm) );
316 memcpy(dlgdm, pi->Devmode, sizeof(*dlgdm));
317 di = HeapAlloc( PSDRV_Heap, 0, sizeof(*di) );
320 psp.dwSize = sizeof(psp);
321 psp.hInstance = hinstWineps32;
322 psp.u.pszTemplate = PAPERW;
323 psp.u2.pszIcon = NULL;
324 psp.pfnDlgProc = PSDRV_PaperDlgProc;
325 psp.lParam = (LPARAM)di;
326 hpsp[0] = pCreatePropertySheetPage(&psp);
328 memset(&psh, 0, sizeof(psh));
329 psh.dwSize = sizeof(psh);
330 psh.pszCaption = SetupW;
332 psh.hwndParent = HWND_32(hwnd);
333 psh.u3.phpage = hpsp;
335 pPropertySheet(&psh);
338 if(fwMode & DM_UPDATE)
339 FIXME("Mode DM_UPDATE. Just do the same as DM_COPY\n");
341 if((fwMode & DM_COPY) || (fwMode & DM_UPDATE)) {
343 memcpy(lpdmOutput, pi->Devmode, pi->Devmode->dmPublic.dmSize + pi->Devmode->dmPublic.dmDriverExtra );
345 FIXME("lpdmOutput is NULL what should we do??\n");
350 /**************************************************************
352 * PSDRV_ExtDeviceMode
354 INT PSDRV_ExtDeviceMode(LPSTR lpszDriver, HWND hwnd, LPDEVMODEA lpdmOutput,
355 LPSTR lpszDevice, LPSTR lpszPort, LPDEVMODEA lpdmInput,
356 LPSTR lpszProfile, DWORD dwMode)
358 return PSDRV_ExtDeviceMode16(HWND_16(hwnd), 0, lpdmOutput, lpszDevice,
359 lpszPort, lpdmInput, lpszProfile, dwMode);
362 /***********************************************************************
363 * DeviceCapabilities [WINEPS16.91]
366 DWORD WINAPI PSDRV_DeviceCapabilities16(LPCSTR lpszDevice, LPCSTR lpszPort,
367 WORD fwCapability, LPSTR lpszOutput,
368 LPDEVMODEA lpDevMode)
372 pi = PSDRV_FindPrinterInfo(lpszDevice);
374 TRACE("Cap=%d. Got PrinterInfo = %p\n", fwCapability, pi);
378 ERR("no printerinfo for %s, return 0!\n",lpszDevice);
383 lpdm = lpDevMode ? lpDevMode : (DEVMODEA *)pi->Devmode;
385 switch(fwCapability) {
390 WORD *wp = (WORD *)lpszOutput;
393 for(ps = pi->ppd->PageSizes; ps; ps = ps->next, i++)
394 if(lpszOutput != NULL)
402 POINT16 *pt = (POINT16 *)lpszOutput;
405 for(ps = pi->ppd->PageSizes; ps; ps = ps->next, i++)
406 if(lpszOutput != NULL) {
407 pt->x = ps->PaperDimension->x * 254.0 / 72.0;
408 pt->y = ps->PaperDimension->y * 254.0 / 72.0;
417 char *cp = lpszOutput;
420 for(ps = pi->ppd->PageSizes; ps; ps = ps->next, i++)
421 if(lpszOutput != NULL) {
422 lstrcpynA(cp, ps->FullName, 64);
429 return pi->ppd->LandscapeOrientation ? pi->ppd->LandscapeOrientation : 90;
434 WORD *wp = (WORD *)lpszOutput;
437 /* We explicitly list DMBIN_AUTO first; actually while win9x does this
438 win2000 lists DMBIN_FORMSOURCE instead. */
440 if(lpszOutput != NULL)
443 for(slot = pi->ppd->InputSlots; slot; slot = slot->next, i++)
444 if(lpszOutput != NULL)
445 *wp++ = slot->WinBin;
452 char *cp = lpszOutput;
455 /* Add an entry corresponding to DMBIN_AUTO, see DC_BINS */
457 if(lpszOutput != NULL) {
458 strcpy(cp, "Automatically Select");
462 for(slot = pi->ppd->InputSlots; slot; slot = slot->next, i++)
463 if(lpszOutput != NULL) {
464 lstrcpynA(cp, slot->FullName, 24);
471 FIXME("DC_BINADJUST: stub.\n");
472 return DCBA_FACEUPNONE;
474 case DC_ENUMRESOLUTIONS:
476 LONG *lp = (LONG*)lpszOutput;
478 if(lpszOutput != NULL) {
479 lp[0] = (LONG)pi->ppd->DefaultResolution;
480 lp[1] = (LONG)pi->ppd->DefaultResolution;
486 FIXME("DC_COPIES: returning %d. Is this correct?\n", lpdm->dmCopies);
487 return lpdm->dmCopies;
490 return lpdm->dmDriverVersion;
492 case DC_DATATYPE_PRODUCED:
493 FIXME("DATA_TYPE_PRODUCED: stub.\n");
494 return -1; /* simulate that the driver supports 'RAW' */
497 FIXME("DC_DUPLEX: returning %d. Is this correct?\n", lpdm->dmDuplex);
498 return lpdm->dmDuplex;
500 case DC_EMF_COMPLIANT:
501 FIXME("DC_EMF_COMPLIANT: stub.\n");
502 return -1; /* simulate that the driver do not support EMF */
505 return lpdm->dmDriverExtra;
508 return lpdm->dmFields;
510 case DC_FILEDEPENDENCIES:
511 FIXME("DC_FILEDEPENDENCIES: stub.\n");
519 ptMax.x = ptMax.y = 0;
521 if(lpszOutput == NULL)
525 for(ps = pi->ppd->PageSizes; ps; ps = ps->next, i++) {
526 if(ps->PaperDimension->x > ptMax.x)
527 ptMax.x = ps->PaperDimension->x;
528 if(ps->PaperDimension->y > ptMax.y)
529 ptMax.y = ps->PaperDimension->y;
531 *((POINT*)lpszOutput) = ptMax;
540 ptMax.x = ptMax.y = 0;
542 if(lpszOutput == NULL)
546 for(ps = pi->ppd->PageSizes; ps; ps = ps->next, i++) {
547 if(ps->PaperDimension->x > ptMax.x)
548 ptMax.x = ps->PaperDimension->x;
549 if(ps->PaperDimension->y > ptMax.y)
550 ptMax.y = ps->PaperDimension->y;
552 *((POINT*)lpszOutput) = ptMax;
560 FIXME("DC_TRUETYPE: stub\n");
564 return lpdm->dmSpecVersion;
567 FIXME("Unsupported capability %d\n", fwCapability);
572 /**************************************************************
574 * PSDRV_DeviceCapabilities
576 DWORD PSDRV_DeviceCapabilities(LPSTR lpszDriver, LPCSTR lpszDevice,
577 LPCSTR lpszPort, WORD fwCapability,
578 LPSTR lpszOutput, LPDEVMODEA lpdm)
580 return PSDRV_DeviceCapabilities16(lpszDevice, lpszPort, fwCapability,
584 /***************************************************************
585 * DeviceMode [WINEPS16.13]
588 void WINAPI PSDRV_DeviceMode16(HWND16 hwnd, HANDLE16 hDriver,
589 LPSTR lpszDevice, LPSTR lpszPort)
591 PSDRV_ExtDeviceMode16( hwnd, hDriver, NULL, lpszDevice, lpszPort, NULL,
600 HPROPSHEETPAGE hPages[10];
603 INT PSDRV_ExtDeviceModePropSheet(HWND hwnd, LPSTR lpszDevice, LPSTR lpszPort,
606 EDMPS *ps = pPropSheet;
609 psp->dwSize = sizeof(psp);
610 psp->hInstance = 0x1234;