driver.c 23.7 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1
/*
Alexandre Julliard's avatar
Alexandre Julliard committed
2
 * Exported functions from the PostScript driver.
Alexandre Julliard's avatar
Alexandre Julliard committed
3
 *
4
 * [Ext]DeviceMode, DeviceCapabilities, AdvancedSetupDialog.
Alexandre Julliard's avatar
Alexandre Julliard committed
5 6 7 8 9
 *
 * Will need ExtTextOut for winword6 (urgh!)
 *
 * Copyright 1998  Huw D M Davies
 *
10 11 12 13 14 15 16 17 18 19 20 21
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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
Alexandre Julliard's avatar
Alexandre Julliard committed
23 24
 */

25 26
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
27 28 29 30 31 32

#include "config.h"

#include <string.h>

#include "wine/debug.h"
33
#include "psdlg.h"
34 35 36 37 38 39
#include "psdrv.h"

#include "winuser.h"
#include "wownt32.h"
#include "winspool.h"
#include "prsht.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
40

41
WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
42

Alexandre Julliard's avatar
Alexandre Julliard committed
43

Alexandre Julliard's avatar
Alexandre Julliard committed
44 45 46 47 48 49 50
/************************************************************************
 *
 *		PSDRV_MergeDevmodes
 *
 * Updates dm1 with some fields from dm2
 *
 */
51
void PSDRV_MergeDevmodes(PSDRV_DEVMODEA *dm1, PSDRV_DEVMODEA *dm2,
Alexandre Julliard's avatar
Alexandre Julliard committed
52
			 PRINTERINFO *pi)
Alexandre Julliard's avatar
Alexandre Julliard committed
53
{
Alexandre Julliard's avatar
Alexandre Julliard committed
54
    /* some sanity checks here on dm2 */
55

56
    if(dm2->dmPublic.dmFields & DM_ORIENTATION) {
57
        dm1->dmPublic.u1.s1.dmOrientation = dm2->dmPublic.u1.s1.dmOrientation;
58 59 60 61 62 63 64
	TRACE("Changing orientation to %d (%s)\n",
	      dm1->dmPublic.u1.s1.dmOrientation,
	      dm1->dmPublic.u1.s1.dmOrientation == DMORIENT_PORTRAIT ?
	      "Portrait" :
	      (dm1->dmPublic.u1.s1.dmOrientation == DMORIENT_LANDSCAPE ?
	       "Landscape" : "unknown"));
    }
65 66

    /* NB PaperWidth is always < PaperLength */
Alexandre Julliard's avatar
Alexandre Julliard committed
67 68 69 70
    if(dm2->dmPublic.dmFields & DM_PAPERSIZE) {
        PAGESIZE *page;

	for(page = pi->ppd->PageSizes; page; page = page->next) {
71
	    if(page->WinPage == dm2->dmPublic.u1.s1.dmPaperSize)
Alexandre Julliard's avatar
Alexandre Julliard committed
72 73 74
	        break;
	}
	if(page) {
75
	    dm1->dmPublic.u1.s1.dmPaperSize = dm2->dmPublic.u1.s1.dmPaperSize;
76
	    dm1->dmPublic.u1.s1.dmPaperWidth = page->PaperDimension->x *
Alexandre Julliard's avatar
Alexandre Julliard committed
77
								254.0 / 72.0;
78
	    dm1->dmPublic.u1.s1.dmPaperLength = page->PaperDimension->y *
Alexandre Julliard's avatar
Alexandre Julliard committed
79
								254.0 / 72.0;
80 81
	    dm1->dmPublic.dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH);
	    dm1->dmPublic.dmFields |= DM_PAPERSIZE;
82 83 84
	    TRACE("Changing page to %s %d x %d\n", page->FullName,
		  dm1->dmPublic.u1.s1.dmPaperWidth,
		  dm1->dmPublic.u1.s1.dmPaperLength );
Alexandre Julliard's avatar
Alexandre Julliard committed
85
	} else {
86 87
	    TRACE("Trying to change to unsupported pagesize %d\n",
		      dm2->dmPublic.u1.s1.dmPaperSize);
Alexandre Julliard's avatar
Alexandre Julliard committed
88
	}
89 90
    } else if((dm2->dmPublic.dmFields & DM_PAPERLENGTH) &&
       (dm2->dmPublic.dmFields & DM_PAPERWIDTH)) {
91 92
        dm1->dmPublic.u1.s1.dmPaperLength = dm2->dmPublic.u1.s1.dmPaperLength;
        dm1->dmPublic.u1.s1.dmPaperWidth = dm2->dmPublic.u1.s1.dmPaperWidth;
93 94
	TRACE("Changing PaperLength|Width to %dx%d\n",
	      dm2->dmPublic.u1.s1.dmPaperLength,
95
	      dm2->dmPublic.u1.s1.dmPaperWidth);
96 97 98 99 100 101 102 103 104
	dm1->dmPublic.dmFields &= ~DM_PAPERSIZE;
	dm1->dmPublic.dmFields |= (DM_PAPERLENGTH | DM_PAPERWIDTH);
    } else if(dm2->dmPublic.dmFields & (DM_PAPERLENGTH | DM_PAPERWIDTH)) {
      /* You might think that this would be allowed if dm1 is in custom size
	 mode, but apparently Windows reverts to standard paper mode even in
	 this case */
        FIXME("Trying to change only paperlength or paperwidth\n");
	dm1->dmPublic.dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH);
	dm1->dmPublic.dmFields |= DM_PAPERSIZE;
105 106 107 108 109 110 111 112 113 114 115 116
    }

    if(dm2->dmPublic.dmFields & DM_SCALE) {
        dm1->dmPublic.dmScale = dm2->dmPublic.dmScale;
	TRACE("Changing Scale to %d\n", dm2->dmPublic.dmScale);
    }

    if(dm2->dmPublic.dmFields & DM_COPIES) {
        dm1->dmPublic.dmCopies = dm2->dmPublic.dmCopies;
	TRACE("Changing Copies to %d\n", dm2->dmPublic.dmCopies);
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
117 118
    if(dm2->dmPublic.dmFields & DM_DEFAULTSOURCE) {
        INPUTSLOT *slot;
119

Alexandre Julliard's avatar
Alexandre Julliard committed
120 121 122 123 124 125
	for(slot = pi->ppd->InputSlots; slot; slot = slot->next) {
	    if(slot->WinBin == dm2->dmPublic.dmDefaultSource)
	        break;
	}
	if(slot) {
	    dm1->dmPublic.dmDefaultSource = dm2->dmPublic.dmDefaultSource;
126
	    TRACE("Changing bin to '%s'\n", slot->FullName);
Alexandre Julliard's avatar
Alexandre Julliard committed
127
	} else {
128
	  TRACE("Trying to change to unsupported bin %d\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
129 130 131 132
		dm2->dmPublic.dmDefaultSource);
	}
    }

133 134 135 136 137 138
   if (dm2->dmPublic.dmFields & DM_DEFAULTSOURCE )
       dm1->dmPublic.dmDefaultSource = dm2->dmPublic.dmDefaultSource;
   if (dm2->dmPublic.dmFields & DM_PRINTQUALITY )
       dm1->dmPublic.dmPrintQuality = dm2->dmPublic.dmPrintQuality;
   if (dm2->dmPublic.dmFields & DM_COLOR )
       dm1->dmPublic.dmColor = dm2->dmPublic.dmColor;
139
   if (dm2->dmPublic.dmFields & DM_DUPLEX && pi->ppd->DefaultDuplex && pi->ppd->DefaultDuplex->WinDuplex != 0)
140 141 142 143 144 145 146 147
       dm1->dmPublic.dmDuplex = dm2->dmPublic.dmDuplex;
   if (dm2->dmPublic.dmFields & DM_YRESOLUTION )
       dm1->dmPublic.dmYResolution = dm2->dmPublic.dmYResolution;
   if (dm2->dmPublic.dmFields & DM_TTOPTION )
       dm1->dmPublic.dmTTOption = dm2->dmPublic.dmTTOption;
   if (dm2->dmPublic.dmFields & DM_COLLATE )
       dm1->dmPublic.dmCollate = dm2->dmPublic.dmCollate;
   if (dm2->dmPublic.dmFields & DM_FORMNAME )
Mike McCormack's avatar
Mike McCormack committed
148
       lstrcpynA((LPSTR)dm1->dmPublic.dmFormName, (LPCSTR)dm2->dmPublic.dmFormName, CCHFORMNAME);
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
   if (dm2->dmPublic.dmFields & DM_BITSPERPEL )
       dm1->dmPublic.dmBitsPerPel = dm2->dmPublic.dmBitsPerPel;
   if (dm2->dmPublic.dmFields & DM_PELSWIDTH )
       dm1->dmPublic.dmPelsWidth = dm2->dmPublic.dmPelsWidth;
   if (dm2->dmPublic.dmFields & DM_PELSHEIGHT )
       dm1->dmPublic.dmPelsHeight = dm2->dmPublic.dmPelsHeight;
   if (dm2->dmPublic.dmFields & DM_DISPLAYFLAGS )
       dm1->dmPublic.dmDisplayFlags = dm2->dmPublic.dmDisplayFlags;
   if (dm2->dmPublic.dmFields & DM_DISPLAYFREQUENCY )
       dm1->dmPublic.dmDisplayFrequency = dm2->dmPublic.dmDisplayFrequency;
   if (dm2->dmPublic.dmFields & DM_POSITION )
       dm1->dmPublic.u1.dmPosition = dm2->dmPublic.u1.dmPosition;
   if (dm2->dmPublic.dmFields & DM_LOGPIXELS )
       dm1->dmPublic.dmLogPixels = dm2->dmPublic.dmLogPixels;
   if (dm2->dmPublic.dmFields & DM_ICMMETHOD )
       dm1->dmPublic.dmICMMethod = dm2->dmPublic.dmICMMethod;
   if (dm2->dmPublic.dmFields & DM_ICMINTENT )
       dm1->dmPublic.dmICMIntent = dm2->dmPublic.dmICMIntent;
   if (dm2->dmPublic.dmFields & DM_MEDIATYPE )
       dm1->dmPublic.dmMediaType = dm2->dmPublic.dmMediaType;
   if (dm2->dmPublic.dmFields & DM_DITHERTYPE )
       dm1->dmPublic.dmDitherType = dm2->dmPublic.dmDitherType;
   if (dm2->dmPublic.dmFields & DM_PANNINGWIDTH )
       dm1->dmPublic.dmPanningWidth = dm2->dmPublic.dmPanningWidth;
   if (dm2->dmPublic.dmFields & DM_PANNINGHEIGHT )
       dm1->dmPublic.dmPanningHeight = dm2->dmPublic.dmPanningHeight;
Alexandre Julliard's avatar
Alexandre Julliard committed
175 176 177 178 179

    return;
}


180
/**************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
181
 *	AdvancedSetupDialog	[WINEPS16.93]
Alexandre Julliard's avatar
Alexandre Julliard committed
182 183
 *
 */
184 185
WORD WINAPI PSDRV_AdvancedSetupDialog16(HWND16 hwnd, HANDLE16 hDriver,
					 LPDEVMODEA devin, LPDEVMODEA devout)
Alexandre Julliard's avatar
Alexandre Julliard committed
186
{
187 188 189 190

  TRACE("hwnd = %04x, hDriver = %04x devin=%p devout=%p\n", hwnd,
	hDriver, devin, devout);
  return IDCANCEL;
Alexandre Julliard's avatar
Alexandre Julliard committed
191 192
}

193 194 195 196 197
/****************************************************************
 *       PSDRV_PaperDlgProc
 *
 * Dialog proc for 'Paper' propsheet
 */
198
INT_PTR CALLBACK PSDRV_PaperDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
199
			       lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
200
{
201
  PSDRV_DLGINFO *di;
202
  int i, Cursel = 0;
203
  PAGESIZE *ps;
204
  DUPLEX *duplex;
Alexandre Julliard's avatar
Alexandre Julliard committed
205

206 207 208
  switch(msg) {
  case WM_INITDIALOG:
    di = (PSDRV_DLGINFO*)((PROPSHEETPAGEA*)lParam)->lParam;
209
    SetWindowLongPtrW(hwnd, DWLP_USER, (LONG_PTR)di);
210 211

    for(ps = di->pi->ppd->PageSizes, i = 0; ps; ps = ps->next, i++) {
212
      SendDlgItemMessageA(hwnd, IDD_PAPERS, LB_INSERTSTRING, i,
213 214 215 216 217
			  (LPARAM)ps->FullName);
      if(di->pi->Devmode->dmPublic.u1.s1.dmPaperSize == ps->WinPage)
	Cursel = i;
    }
    SendDlgItemMessageA(hwnd, IDD_PAPERS, LB_SETCURSEL, Cursel, 0);
218
    
219 220 221 222
    CheckRadioButton(hwnd, IDD_ORIENT_PORTRAIT, IDD_ORIENT_LANDSCAPE,
		     di->pi->Devmode->dmPublic.u1.s1.dmOrientation ==
		     DMORIENT_PORTRAIT ? IDD_ORIENT_PORTRAIT :
		     IDD_ORIENT_LANDSCAPE);
223 224 225 226 227 228 229 230 231 232 233 234 235 236

    if(!di->pi->ppd->Duplexes) {
        ShowWindow(GetDlgItem(hwnd, IDD_DUPLEX), SW_HIDE);
        ShowWindow(GetDlgItem(hwnd, IDD_DUPLEX_NAME), SW_HIDE);        
    } else {
        Cursel = 0;
        for(duplex = di->pi->ppd->Duplexes, i = 0; duplex; duplex = duplex->next, i++) {
            SendDlgItemMessageA(hwnd, IDD_DUPLEX, CB_INSERTSTRING, i,
                                (LPARAM)(duplex->FullName ? duplex->FullName : duplex->Name));
            if(di->pi->Devmode->dmPublic.dmDuplex == duplex->WinDuplex)
                Cursel = i;
        }
        SendDlgItemMessageA(hwnd, IDD_DUPLEX, CB_SETCURSEL, Cursel, 0);
    }
237
    break;
Alexandre Julliard's avatar
Alexandre Julliard committed
238

239
  case WM_COMMAND:
240
    di = (PSDRV_DLGINFO *)GetWindowLongPtrW(hwnd, DWLP_USER);
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
    switch(LOWORD(wParam)) {
    case IDD_PAPERS:
      if(HIWORD(wParam) == LBN_SELCHANGE) {
	Cursel = SendDlgItemMessageA(hwnd, LOWORD(wParam), LB_GETCURSEL, 0, 0);
	for(i = 0, ps = di->pi->ppd->PageSizes; i < Cursel; i++, ps = ps->next)
	  ;
	TRACE("Setting pagesize to item %d Winpage = %d\n", Cursel,
	      ps->WinPage);
	di->dlgdm->dmPublic.u1.s1.dmPaperSize = ps->WinPage;
      }
      break;
    case IDD_ORIENT_PORTRAIT:
    case IDD_ORIENT_LANDSCAPE:
      TRACE("Setting orientation to %s\n", wParam == IDD_ORIENT_PORTRAIT ?
	    "portrait" : "landscape");
      di->dlgdm->dmPublic.u1.s1.dmOrientation = wParam == IDD_ORIENT_PORTRAIT ?
	DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE;
      break;
259 260 261 262 263 264 265 266 267 268
    case IDD_DUPLEX:
      if(HIWORD(wParam) == CBN_SELCHANGE) {
	Cursel = SendDlgItemMessageA(hwnd, LOWORD(wParam), CB_GETCURSEL, 0, 0);
	for(i = 0, duplex = di->pi->ppd->Duplexes; i < Cursel; i++, duplex = duplex->next)
	  ;
	TRACE("Setting duplex to item %d Winduplex = %d\n", Cursel,
	      duplex->WinDuplex);
	di->dlgdm->dmPublic.dmDuplex = duplex->WinDuplex;
      }
      break;
269 270 271 272 273 274
    }
    break;

  case WM_NOTIFY:
   {
    NMHDR *nmhdr = (NMHDR *)lParam;
275
    di = (PSDRV_DLGINFO *)GetWindowLongPtrW(hwnd, DWLP_USER);
276 277 278
    switch(nmhdr->code) {
    case PSN_APPLY:
      memcpy(di->pi->Devmode, di->dlgdm, sizeof(PSDRV_DEVMODEA));
279
      SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, PSNRET_NOERROR);
Alexandre Julliard's avatar
Alexandre Julliard committed
280 281 282 283 284
      return TRUE;

    default:
      return FALSE;
    }
285 286
    break;
   }
287

288
  default:
Alexandre Julliard's avatar
Alexandre Julliard committed
289 290
    return FALSE;
  }
291
  return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
292 293 294
}


295
static void (WINAPI *pInitCommonControls) (void);
296 297
static HPROPSHEETPAGE (WINAPI *pCreatePropertySheetPage) (LPCPROPSHEETPAGEW);
static int (WINAPI *pPropertySheet) (LPCPROPSHEETHEADERW);
Alexandre Julliard's avatar
Alexandre Julliard committed
298

299 300 301 302 303 304

 /******************************************************************
 *         PSDRV_ExtDeviceMode
 *
 *  Retrieves or modifies device-initialization information for the PostScript
 *  driver, or displays a driver-supplied dialog box for configuring the driver.
Alexandre Julliard's avatar
Alexandre Julliard committed
305
 *
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
 * PARAMETERS
 *  lpszDriver  -- Driver name
 *  hwnd        -- Parent window for the dialog box
 *  lpdmOutput  -- Address of a DEVMODE structure for writing initialization information
 *  lpszDevice  -- Device name
 *  lpszPort    -- Port name
 *  lpdmInput   -- Address of a DEVMODE structure for reading initialization information
 *  lpProfile   -- Name of initialization file, defaults to WIN.INI if NULL
 *  wMode      -- Operation to perform.  Can be a combination if > 0.
 *      (0)             -- Returns number of bytes required by DEVMODE structure
 *      DM_UPDATE (1)   -- Write current settings to environment and initialization file
 *      DM_COPY (2)     -- Write current settings to lpdmOutput
 *      DM_PROMPT (4)   -- Presents the driver's modal dialog box (USER.240)
 *      DM_MODIFY (8)   -- Changes current settings according to lpdmInput before any other operation
 *
 * RETURNS
 *  Returns size of DEVMODE structure if wMode is 0.  Otherwise, IDOK is returned for success
 *  for both dialog and non-dialog operations.  IDCANCEL is returned if the dialog box was cancelled.
 *  A return value less than zero is returned if a non-dialog operation fails.
 *  
 * BUGS
 *
 * Just returns default devmode at the moment.  No use of initialization file.
Alexandre Julliard's avatar
Alexandre Julliard committed
329
 */
330 331 332
INT PSDRV_ExtDeviceMode(LPSTR lpszDriver, HWND hwnd, LPDEVMODEA lpdmOutput,
			LPSTR lpszDevice, LPSTR lpszPort, LPDEVMODEA lpdmInput,
			LPSTR lpszProfile, DWORD dwMode)
Alexandre Julliard's avatar
Alexandre Julliard committed
333
{
Alexandre Julliard's avatar
Alexandre Julliard committed
334
  PRINTERINFO *pi = PSDRV_FindPrinterInfo(lpszDevice);
335
  if(!pi) return -1;
Alexandre Julliard's avatar
Alexandre Julliard committed
336

337
  TRACE("(Driver=%s, hwnd=%p, devOut=%p, Device='%s', Port='%s', devIn=%p, Profile='%s', Mode=%04x)\n",
338
  lpszDriver, hwnd, lpdmOutput, lpszDevice, lpszPort, lpdmInput, lpszProfile, dwMode);
Alexandre Julliard's avatar
Alexandre Julliard committed
339

340 341
  /* If dwMode == 0, return size of DEVMODE structure */
  if(!dwMode)
342
    return pi->Devmode->dmPublic.dmSize + pi->Devmode->dmPublic.dmDriverExtra;
343

344 345
  /* If DM_MODIFY is set, change settings in accordance with lpdmInput */
  if((dwMode & DM_MODIFY) && lpdmInput) {
346
    TRACE("DM_MODIFY set. devIn->dmFields = %08x\n", lpdmInput->dmFields);
347
    PSDRV_MergeDevmodes(pi->Devmode, (PSDRV_DEVMODEA *)lpdmInput, pi);
Alexandre Julliard's avatar
Alexandre Julliard committed
348 349
  }

350 351
  /* If DM_PROMPT is set, present modal dialog box */
  if(dwMode & DM_PROMPT) {
352
    HINSTANCE hinstComctl32;
353
    HPROPSHEETPAGE hpsp[1];
354 355
    PROPSHEETPAGEW psp;
    PROPSHEETHEADERW psh;
356 357
    PSDRV_DLGINFO *di;
    PSDRV_DEVMODEA *dlgdm;
358 359
    static const WCHAR PAPERW[] = {'P','A','P','E','R','\0'};
    static const WCHAR SetupW[] = {'S','e','t','u','p','\0'};
360 361 362 363 364

    hinstComctl32 = LoadLibraryA("comctl32.dll");
    pInitCommonControls = (void*)GetProcAddress(hinstComctl32,
						"InitCommonControls");
    pCreatePropertySheetPage = (void*)GetProcAddress(hinstComctl32,
365
						    "CreatePropertySheetPageW");
366
    pPropertySheet = (void*)GetProcAddress(hinstComctl32, "PropertySheetW");
367 368 369 370 371 372 373
    memset(&psp,0,sizeof(psp));
    dlgdm = HeapAlloc( PSDRV_Heap, 0, sizeof(*dlgdm) );
    memcpy(dlgdm, pi->Devmode, sizeof(*dlgdm));
    di = HeapAlloc( PSDRV_Heap, 0, sizeof(*di) );
    di->pi = pi;
    di->dlgdm = dlgdm;
    psp.dwSize = sizeof(psp);
374
    psp.hInstance = PSDRV_hInstance;
375
    psp.u.pszTemplate = PAPERW;
376 377 378 379 380 381 382
    psp.u2.pszIcon = NULL;
    psp.pfnDlgProc = PSDRV_PaperDlgProc;
    psp.lParam = (LPARAM)di;
    hpsp[0] = pCreatePropertySheetPage(&psp);

    memset(&psh, 0, sizeof(psh));
    psh.dwSize = sizeof(psh);
383
    psh.pszCaption = SetupW;
384
    psh.nPages = 1;
385
    psh.hwndParent = HWND_32(hwnd);
386
    psh.u3.phpage = hpsp;
387

388
    pPropertySheet(&psh);
389

390
  }
391 392 393
  
  /* If DM_UPDATE is set, should write settings to environment and initialization file */
  if(dwMode & DM_UPDATE)
394 395
    FIXME("Mode DM_UPDATE.  Just do the same as DM_COPY\n");

396 397
  /* If DM_COPY is set, should write settings to lpdmOutput */
  if((dwMode & DM_COPY) || (dwMode & DM_UPDATE)) {
398
    if (lpdmOutput)
399
        memcpy(lpdmOutput, pi->Devmode, pi->Devmode->dmPublic.dmSize + pi->Devmode->dmPublic.dmDriverExtra );
400 401
    else
        FIXME("lpdmOutput is NULL what should we do??\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
402
  }
Alexandre Julliard's avatar
Alexandre Julliard committed
403 404
  return IDOK;
}
405 406
/***************************************************************
 *	ExtDeviceMode	[WINEPS16.90]
407 408
 *
 */
409 410 411 412 413 414

INT16 WINAPI PSDRV_ExtDeviceMode16(HWND16 hwnd, HANDLE16 hDriver,
				   LPDEVMODEA lpdmOutput, LPSTR lpszDevice,
				   LPSTR lpszPort, LPDEVMODEA lpdmInput,
				   LPSTR lpszProfile, WORD fwMode)

415
{
416 417
    return PSDRV_ExtDeviceMode(NULL, HWND_32(hwnd), lpdmOutput, lpszDevice,
				 lpszPort, lpdmInput, lpszProfile, (DWORD) fwMode);
418
}
Alexandre Julliard's avatar
Alexandre Julliard committed
419

420
/***********************************************************************
421 422 423 424 425 426 427 428 429 430 431
 *	PSDRV_DeviceCapabilities	
 *
 *      Retrieves the capabilities of a printer device driver.
 *
 * Parameters
 *      lpszDriver -- printer driver name
 *      lpszDevice -- printer name
 *      lpszPort -- port name
 *      fwCapability -- device capability
 *      lpszOutput -- output buffer
 *      lpDevMode -- device data buffer
Alexandre Julliard's avatar
Alexandre Julliard committed
432
 *
433 434
 * Returns
 *      Result depends on the setting of fwCapability.  -1 indicates failure.
Alexandre Julliard's avatar
Alexandre Julliard committed
435
 */
436
DWORD PSDRV_DeviceCapabilities(LPSTR lpszDriver, LPCSTR lpszDevice, LPCSTR lpszPort,
437 438
					WORD fwCapability, LPSTR lpszOutput,
					LPDEVMODEA lpDevMode)
Alexandre Julliard's avatar
Alexandre Julliard committed
439
{
Alexandre Julliard's avatar
Alexandre Julliard committed
440
  PRINTERINFO *pi;
441
  DEVMODEA *lpdm;
442
  DWORD ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
443
  pi = PSDRV_FindPrinterInfo(lpszDevice);
444

445 446
  TRACE("Cap=%d. Got PrinterInfo = %p\n", fwCapability, pi);

447 448 449 450 451 452 453

  if (!pi) {
	  ERR("no printerinfo for %s, return 0!\n",lpszDevice);
	  return 0;
  }


454
  lpdm = lpDevMode ? lpDevMode : (DEVMODEA *)pi->Devmode;
Alexandre Julliard's avatar
Alexandre Julliard committed
455 456 457 458

  switch(fwCapability) {

  case DC_PAPERS:
Alexandre Julliard's avatar
Alexandre Julliard committed
459 460 461 462 463 464 465 466 467 468
    {
      PAGESIZE *ps;
      WORD *wp = (WORD *)lpszOutput;
      int i = 0;

      for(ps = pi->ppd->PageSizes; ps; ps = ps->next, i++)
	if(lpszOutput != NULL)
	  *wp++ = ps->WinPage;
      return i;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
469 470

  case DC_PAPERSIZE:
Alexandre Julliard's avatar
Alexandre Julliard committed
471 472 473 474
    {
      PAGESIZE *ps;
      POINT16 *pt = (POINT16 *)lpszOutput;
      int i = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
475

Alexandre Julliard's avatar
Alexandre Julliard committed
476 477 478 479 480 481 482 483
      for(ps = pi->ppd->PageSizes; ps; ps = ps->next, i++)
	if(lpszOutput != NULL) {
	  pt->x = ps->PaperDimension->x * 254.0 / 72.0;
	  pt->y = ps->PaperDimension->y * 254.0 / 72.0;
	  pt++;
	}
      return i;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
484 485

  case DC_PAPERNAMES:
Alexandre Julliard's avatar
Alexandre Julliard committed
486 487 488 489 490 491 492
    {
      PAGESIZE *ps;
      char *cp = lpszOutput;
      int i = 0;

      for(ps = pi->ppd->PageSizes; ps; ps = ps->next, i++)
	if(lpszOutput != NULL) {
493
	  lstrcpynA(cp, ps->FullName, 64);
Alexandre Julliard's avatar
Alexandre Julliard committed
494 495 496 497
	  cp += 64;
	}
      return i;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
498 499

  case DC_ORIENTATION:
Alexandre Julliard's avatar
Alexandre Julliard committed
500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518
    return pi->ppd->LandscapeOrientation ? pi->ppd->LandscapeOrientation : 90;

  case DC_BINS:
    {
      INPUTSLOT *slot;
      WORD *wp = (WORD *)lpszOutput;
      int i = 0;

      for(slot = pi->ppd->InputSlots; slot; slot = slot->next, i++)
	if(lpszOutput != NULL)
	  *wp++ = slot->WinBin;
      return i;
    }

  case DC_BINNAMES:
    {
      INPUTSLOT *slot;
      char *cp = lpszOutput;
      int i = 0;
519

Alexandre Julliard's avatar
Alexandre Julliard committed
520 521
      for(slot = pi->ppd->InputSlots; slot; slot = slot->next, i++)
	if(lpszOutput != NULL) {
522
	  lstrcpynA(cp, slot->FullName, 24);
Alexandre Julliard's avatar
Alexandre Julliard committed
523 524 525 526
	  cp += 24;
	}
      return i;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
527

528 529 530 531
  case DC_BINADJUST:
    FIXME("DC_BINADJUST: stub.\n");
    return DCBA_FACEUPNONE;

Alexandre Julliard's avatar
Alexandre Julliard committed
532
  case DC_ENUMRESOLUTIONS:
533 534 535 536 537 538 539 540 541 542
    {
      LONG *lp = (LONG*)lpszOutput;

      if(lpszOutput != NULL) {
	lp[0] = (LONG)pi->ppd->DefaultResolution;
	lp[1] = (LONG)pi->ppd->DefaultResolution;
      }
      return 1;
    }

543
  /* Windows returns 9999 too */
544
  case DC_COPIES:
545 546
    TRACE("DC_COPIES: returning 9999\n");
    return 9999;
547 548 549

  case DC_DRIVER:
    return lpdm->dmDriverVersion;
Alexandre Julliard's avatar
Alexandre Julliard committed
550

551 552 553 554 555
  case DC_DATATYPE_PRODUCED:
    FIXME("DATA_TYPE_PRODUCED: stub.\n");
    return -1; /* simulate that the driver supports 'RAW' */

  case DC_DUPLEX:
556 557 558
    ret = 0;
    if(pi->ppd->DefaultDuplex && pi->ppd->DefaultDuplex->WinDuplex != 0)
      ret = 1;
559
    TRACE("DC_DUPLEX: returning %d\n", ret);
560
    return ret;
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584

  case DC_EMF_COMPLIANT:
    FIXME("DC_EMF_COMPLIANT: stub.\n");
    return -1; /* simulate that the driver do not support EMF */

  case DC_EXTRA:
    return lpdm->dmDriverExtra;

  case DC_FIELDS:
    return lpdm->dmFields;

  case DC_FILEDEPENDENCIES:
    FIXME("DC_FILEDEPENDENCIES: stub.\n");
    return 0;

  case DC_MAXEXTENT:
    {
      PAGESIZE *ps;
      int i;
      POINT ptMax;
      ptMax.x = ptMax.y = 0;

      if(lpszOutput == NULL)
	return -1;
585

586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605
      i = 0;
      for(ps = pi->ppd->PageSizes; ps; ps = ps->next, i++) {
	if(ps->PaperDimension->x > ptMax.x)
	  ptMax.x = ps->PaperDimension->x;
	if(ps->PaperDimension->y > ptMax.y)
	  ptMax.y = ps->PaperDimension->y;
      }
      *((POINT*)lpszOutput) = ptMax;
      return 1;
    }

  case DC_MINEXTENT:
    {
      PAGESIZE *ps;
      int i;
      POINT ptMax;
      ptMax.x = ptMax.y = 0;

      if(lpszOutput == NULL)
	return -1;
606

607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626
      i = 0;
      for(ps = pi->ppd->PageSizes; ps; ps = ps->next, i++) {
	if(ps->PaperDimension->x > ptMax.x)
	  ptMax.x = ps->PaperDimension->x;
	if(ps->PaperDimension->y > ptMax.y)
	  ptMax.y = ps->PaperDimension->y;
      }
      *((POINT*)lpszOutput) = ptMax;
      return 1;
    }

  case DC_SIZE:
    return lpdm->dmSize;

  case DC_TRUETYPE:
    FIXME("DC_TRUETYPE: stub\n");
    return DCTT_SUBDEV;

  case DC_VERSION:
    return lpdm->dmSpecVersion;
Alexandre Julliard's avatar
Alexandre Julliard committed
627

628
  /* We'll just return false here, very few printers can collate anyway */
629
  case DC_COLLATE:
630 631 632
    TRACE("DC_COLLATE: returning FALSE\n");
    return FALSE;

633 634
  /* Printer supports colour printing - 1 if yes, 0 if no (Win2k/XP only) */
  case DC_COLORDEVICE:
635 636
    return pi->ppd->ColorDevice;

637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713
  /* Identification number of the printer manufacturer for use with ICM (Win9x only) */
  case DC_MANUFACTURER:
    FIXME("DC_MANUFACTURER: stub\n");
    return -1;
    
  /* Identification number of the printer model for use with ICM (Win9x only) */
  case DC_MODEL:
    FIXME("DC_MODEL: stub\n");
    return -1;
    
  /* Nonzero if the printer supports stapling, zero otherwise (Win2k/XP only) */
  case DC_STAPLE: /* WINVER >= 0x0500 */
    FIXME("DC_STAPLE: stub\n");
    return -1;
    
  /* Returns an array of 64-character string buffers containing the names of the paper forms
   * available for use, unless pOutput is NULL.  The return value is the number of paper forms.
   * (Win2k/XP only)
   */
  case DC_MEDIAREADY: /* WINVER >= 0x0500 */
    FIXME("DC_MEDIAREADY: stub\n");
    return -1;

  /* Returns an array of 64-character string buffers containing the names of the supported
   * media types, unless pOutput is NULL.  The return value is the number of supported.
   * media types (XP only)
   */
  case DC_MEDIATYPENAMES: /* WINVER >= 0x0501 */
    FIXME("DC_MEDIATYPENAMES: stub\n");
    return -1;
    
  /* Returns an array of DWORD values which represent the supported media types, unless
   * pOutput is NULL.  The return value is the number of supported media types. (XP only)
   */
  case DC_MEDIATYPES: /* WINVER >= 0x0501 */
    FIXME("DC_MEDIATYPES: stub\n");
    return -1;

  /* Returns an array of DWORD values, each representing a supported number of document
   * pages per printed page, unless pOutput is NULL.  The return value is the number of
   * array entries. (Win2k/XP only)
   */
  case DC_NUP:
    FIXME("DC_NUP: stub\n");
    return -1;
    
  /* Returns an array of 32-character string buffers containing a list of printer description
   * languages supported by the printer, unless pOutput is NULL.  The return value is
   * number of array entries. (Win2k/XP only)
   */
   
  case DC_PERSONALITY: /* WINVER >= 0x0500 */
    FIXME("DC_PERSONALITY: stub\n");
    return -1;
    
  /* Returns the amount of printer memory in kilobytes. (Win2k/XP only) */
  case DC_PRINTERMEM: /* WINVER >= 0x0500 */
    FIXME("DC_PRINTERMEM: stub\n");
    return -1;
    
  /* Returns the printer's print rate in PRINTRATEUNIT units. (Win2k/XP only) */
  case DC_PRINTRATE: /* WINVER >= 0x0500 */
    FIXME("DC_PRINTRATE: stub\n");
    return -1;
    
  /* Returns the printer's print rate in pages per minute. (Win2k/XP only) */
  case DC_PRINTRATEPPM: /* WINVER >= 0x0500 */
    FIXME("DC_PRINTRATEPPM: stub\n");
    return -1;
   
  /* Returns the printer rate unit used for DC_PRINTRATE, which is one of
   * PRINTRATEUNIT_{CPS,IPM,LPM,PPM} (Win2k/XP only)
   */  
  case DC_PRINTRATEUNIT: /* WINVER >= 0x0500 */
    FIXME("DC_PRINTRATEUNIT: stub\n");
    return -1;
    
Alexandre Julliard's avatar
Alexandre Julliard committed
714
  default:
715
    FIXME("Unsupported capability %d\n", fwCapability);
Alexandre Julliard's avatar
Alexandre Julliard committed
716 717 718 719
  }
  return -1;
}

720
/**************************************************************
721
 *     DeviceCapabilities [WINEPS16.91]
722
 */
723
DWORD WINAPI PSDRV_DeviceCapabilities16(LPCSTR lpszDevice,
724 725
			       LPCSTR lpszPort, WORD fwCapability,
			       LPSTR lpszOutput, LPDEVMODEA lpdm)
726
{
727
    return PSDRV_DeviceCapabilities(NULL, lpszDevice, lpszPort, fwCapability,
728
				      lpszOutput, lpdm);
729 730
}

Alexandre Julliard's avatar
Alexandre Julliard committed
731
/***************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
732
 *	DeviceMode	[WINEPS16.13]
Alexandre Julliard's avatar
Alexandre Julliard committed
733 734 735 736 737
 *
 */
void WINAPI PSDRV_DeviceMode16(HWND16 hwnd, HANDLE16 hDriver,
LPSTR lpszDevice, LPSTR lpszPort)
{
738
    PSDRV_ExtDeviceMode16( hwnd, hDriver, NULL, lpszDevice, lpszPort, NULL,
Alexandre Julliard's avatar
Alexandre Julliard committed
739 740 741
			   NULL, DM_PROMPT );
    return;
}
742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757

#if 0
typedef struct {
  DWORD nPages;
  DWORD Unknown;
  HPROPSHEETPAGE hPages[10];
} EDMPS;

INT PSDRV_ExtDeviceModePropSheet(HWND hwnd, LPSTR lpszDevice, LPSTR lpszPort,
				 LPVOID pPropSheet)
{
    EDMPS *ps = pPropSheet;
    PROPSHEETPAGE psp;

    psp->dwSize = sizeof(psp);
    psp->hInstance = 0x1234;
758

759
    ps->nPages = 1;
760

761 762 763
}

#endif