driver.c 24.4 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
#include "psdrv.h"

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

40
WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
41

Alexandre Julliard's avatar
Alexandre Julliard committed
42

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

55
    if(dm2->dmPublic.dmFields & DM_ORIENTATION) {
56
        dm1->dmPublic.u1.s1.dmOrientation = dm2->dmPublic.u1.s1.dmOrientation;
57 58 59 60 61 62 63
	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"));
    }
64 65

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

69
	LIST_FOR_EACH_ENTRY(page, &pi->ppd->PageSizes, PAGESIZE, entry) {
70
	    if(page->WinPage == dm2->dmPublic.u1.s1.dmPaperSize)
Alexandre Julliard's avatar
Alexandre Julliard committed
71 72
	        break;
	}
73
	if(&page->entry != &pi->ppd->PageSizes ) {
74
	    dm1->dmPublic.u1.s1.dmPaperSize = dm2->dmPublic.u1.s1.dmPaperSize;
75
	    dm1->dmPublic.u1.s1.dmPaperWidth = page->PaperDimension->x *
Alexandre Julliard's avatar
Alexandre Julliard committed
76
								254.0 / 72.0;
77
	    dm1->dmPublic.u1.s1.dmPaperLength = page->PaperDimension->y *
Alexandre Julliard's avatar
Alexandre Julliard committed
78
								254.0 / 72.0;
79 80
	    dm1->dmPublic.dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH);
	    dm1->dmPublic.dmFields |= DM_PAPERSIZE;
81 82 83
	    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
84
	} else {
85 86
	    TRACE("Trying to change to unsupported pagesize %d\n",
		      dm2->dmPublic.u1.s1.dmPaperSize);
Alexandre Julliard's avatar
Alexandre Julliard committed
87
	}
88 89
    } else if((dm2->dmPublic.dmFields & DM_PAPERLENGTH) &&
       (dm2->dmPublic.dmFields & DM_PAPERWIDTH)) {
90 91
        dm1->dmPublic.u1.s1.dmPaperLength = dm2->dmPublic.u1.s1.dmPaperLength;
        dm1->dmPublic.u1.s1.dmPaperWidth = dm2->dmPublic.u1.s1.dmPaperWidth;
92 93
	TRACE("Changing PaperLength|Width to %dx%d\n",
	      dm2->dmPublic.u1.s1.dmPaperLength,
94
	      dm2->dmPublic.u1.s1.dmPaperWidth);
95 96 97 98 99 100 101 102 103
	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;
104 105 106
    }

    if(dm2->dmPublic.dmFields & DM_SCALE) {
107 108
        dm1->dmPublic.u1.s1.dmScale = dm2->dmPublic.u1.s1.dmScale;
	TRACE("Changing Scale to %d\n", dm2->dmPublic.u1.s1.dmScale);
109 110 111
    }

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

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

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

132
   if (dm2->dmPublic.dmFields & DM_DEFAULTSOURCE )
133
       dm1->dmPublic.u1.s1.dmDefaultSource = dm2->dmPublic.u1.s1.dmDefaultSource;
134
   if (dm2->dmPublic.dmFields & DM_PRINTQUALITY )
135
       dm1->dmPublic.u1.s1.dmPrintQuality = dm2->dmPublic.u1.s1.dmPrintQuality;
136 137
   if (dm2->dmPublic.dmFields & DM_COLOR )
       dm1->dmPublic.dmColor = dm2->dmPublic.dmColor;
138
   if (dm2->dmPublic.dmFields & DM_DUPLEX && pi->ppd->DefaultDuplex && pi->ppd->DefaultDuplex->WinDuplex != 0)
139 140 141 142 143 144 145 146
       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
147
       lstrcpynA((LPSTR)dm1->dmPublic.dmFormName, (LPCSTR)dm2->dmPublic.dmFormName, CCHFORMNAME);
148 149 150 151 152 153 154
   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 )
155
       dm1->dmPublic.u2.dmDisplayFlags = dm2->dmPublic.u2.dmDisplayFlags;
156 157 158
   if (dm2->dmPublic.dmFields & DM_DISPLAYFREQUENCY )
       dm1->dmPublic.dmDisplayFrequency = dm2->dmPublic.dmDisplayFrequency;
   if (dm2->dmPublic.dmFields & DM_POSITION )
159
       dm1->dmPublic.u1.s2.dmPosition = dm2->dmPublic.u1.s2.dmPosition;
160 161 162 163 164 165 166 167 168 169 170 171 172 173
   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
174 175 176 177 178

    return;
}


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

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

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

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

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

    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);
    }
238
    break;
Alexandre Julliard's avatar
Alexandre Julliard committed
239

240
  case WM_COMMAND:
241
    di = (PSDRV_DLGINFO *)GetWindowLongPtrW(hwnd, DWLP_USER);
242 243 244 245
    switch(LOWORD(wParam)) {
    case IDD_PAPERS:
      if(HIWORD(wParam) == LBN_SELCHANGE) {
	Cursel = SendDlgItemMessageA(hwnd, LOWORD(wParam), LB_GETCURSEL, 0, 0);
246 247 248 249 250
        i = 0;
	LIST_FOR_EACH_ENTRY(ps, &di->pi->ppd->PageSizes, PAGESIZE, entry) {
            if(i >= Cursel) break;
            i++;
        }
251 252 253 254 255 256 257 258 259 260 261 262
	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;
263 264 265 266 267 268 269 270 271 272
    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;
273 274 275 276 277 278
    }
    break;

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

    default:
      return FALSE;
    }
289 290
    break;
   }
291

292
  default:
Alexandre Julliard's avatar
Alexandre Julliard committed
293 294
    return FALSE;
  }
295
  return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
296 297 298
}


299
static void (WINAPI *pInitCommonControls) (void);
300 301
static HPROPSHEETPAGE (WINAPI *pCreatePropertySheetPage) (LPCPROPSHEETPAGEW);
static int (WINAPI *pPropertySheet) (LPCPROPSHEETHEADERW);
Alexandre Julliard's avatar
Alexandre Julliard committed
302

303 304 305 306 307 308

 /******************************************************************
 *         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
309
 *
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
 * 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
333
 */
334 335 336
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
337
{
Alexandre Julliard's avatar
Alexandre Julliard committed
338
  PRINTERINFO *pi = PSDRV_FindPrinterInfo(lpszDevice);
339
  if(!pi) return -1;
Alexandre Julliard's avatar
Alexandre Julliard committed
340

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

344 345
  /* If dwMode == 0, return size of DEVMODE structure */
  if(!dwMode)
346
    return pi->Devmode->dmPublic.dmSize + pi->Devmode->dmPublic.dmDriverExtra;
347

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

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

    hinstComctl32 = LoadLibraryA("comctl32.dll");
    pInitCommonControls = (void*)GetProcAddress(hinstComctl32,
						"InitCommonControls");
    pCreatePropertySheetPage = (void*)GetProcAddress(hinstComctl32,
369
						    "CreatePropertySheetPageW");
370
    pPropertySheet = (void*)GetProcAddress(hinstComctl32, "PropertySheetW");
371 372 373 374 375 376 377
    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);
378
    psp.hInstance = PSDRV_hInstance;
379
    psp.u.pszTemplate = PAPERW;
380 381 382 383 384 385 386
    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);
387
    psh.pszCaption = SetupW;
388
    psh.nPages = 1;
389
    psh.hwndParent = HWND_32(hwnd);
390
    psh.u3.phpage = hpsp;
391

392
    pPropertySheet(&psh);
393

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

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

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

419
{
420 421
    return PSDRV_ExtDeviceMode(NULL, HWND_32(hwnd), lpdmOutput, lpszDevice,
				 lpszPort, lpdmInput, lpszProfile, (DWORD) fwMode);
422
}
Alexandre Julliard's avatar
Alexandre Julliard committed
423

424
/***********************************************************************
425 426 427 428 429 430 431 432 433 434 435
 *	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
436
 *
437 438
 * Returns
 *      Result depends on the setting of fwCapability.  -1 indicates failure.
Alexandre Julliard's avatar
Alexandre Julliard committed
439
 */
440
DWORD PSDRV_DeviceCapabilities(LPSTR lpszDriver, LPCSTR lpszDevice, LPCSTR lpszPort,
441 442
					WORD fwCapability, LPSTR lpszOutput,
					LPDEVMODEA lpDevMode)
Alexandre Julliard's avatar
Alexandre Julliard committed
443
{
Alexandre Julliard's avatar
Alexandre Julliard committed
444
  PRINTERINFO *pi;
445
  DEVMODEA *lpdm;
446
  DWORD ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
447
  pi = PSDRV_FindPrinterInfo(lpszDevice);
448

449 450
  TRACE("%s %s %s, %u, %p, %p\n", debugstr_a(lpszDriver), debugstr_a(lpszDevice),
        debugstr_a(lpszPort), fwCapability, lpszOutput, lpDevMode);
451 452

  if (!pi) {
453 454 455
      ERR("no printer info for %s %s, return 0!\n",
          debugstr_a(lpszDriver), debugstr_a(lpszDevice));
      return 0;
456 457
  }

458
  lpdm = lpDevMode ? lpDevMode : (DEVMODEA *)pi->Devmode;
Alexandre Julliard's avatar
Alexandre Julliard committed
459 460 461 462

  switch(fwCapability) {

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

468 469
      LIST_FOR_EACH_ENTRY(ps, &pi->ppd->PageSizes, PAGESIZE, entry)
      {
470
        TRACE("DC_PAPERS: %u\n", ps->WinPage);
471
        i++;
Alexandre Julliard's avatar
Alexandre Julliard committed
472 473
	if(lpszOutput != NULL)
	  *wp++ = ps->WinPage;
474
      }
Alexandre Julliard's avatar
Alexandre Julliard committed
475 476
      return i;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
477 478

  case DC_PAPERSIZE:
Alexandre Julliard's avatar
Alexandre Julliard committed
479 480 481 482
    {
      PAGESIZE *ps;
      POINT16 *pt = (POINT16 *)lpszOutput;
      int i = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
483

484 485
      LIST_FOR_EACH_ENTRY(ps, &pi->ppd->PageSizes, PAGESIZE, entry)
      {
486
        TRACE("DC_PAPERSIZE: %f x %f\n", ps->PaperDimension->x, ps->PaperDimension->y);
487
        i++;
Alexandre Julliard's avatar
Alexandre Julliard committed
488 489 490 491 492
	if(lpszOutput != NULL) {
	  pt->x = ps->PaperDimension->x * 254.0 / 72.0;
	  pt->y = ps->PaperDimension->y * 254.0 / 72.0;
	  pt++;
	}
493
      }
Alexandre Julliard's avatar
Alexandre Julliard committed
494 495
      return i;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
496 497

  case DC_PAPERNAMES:
Alexandre Julliard's avatar
Alexandre Julliard committed
498 499 500 501 502
    {
      PAGESIZE *ps;
      char *cp = lpszOutput;
      int i = 0;

503 504
      LIST_FOR_EACH_ENTRY(ps, &pi->ppd->PageSizes, PAGESIZE, entry)
      {
505
        TRACE("DC_PAPERNAMES: %s\n", debugstr_a(ps->FullName));
506
        i++;
Alexandre Julliard's avatar
Alexandre Julliard committed
507
	if(lpszOutput != NULL) {
508
	  lstrcpynA(cp, ps->FullName, 64);
Alexandre Julliard's avatar
Alexandre Julliard committed
509 510
	  cp += 64;
	}
511
      }
Alexandre Julliard's avatar
Alexandre Julliard committed
512 513
      return i;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
514 515

  case DC_ORIENTATION:
Alexandre Julliard's avatar
Alexandre Julliard committed
516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
    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;
535

Alexandre Julliard's avatar
Alexandre Julliard committed
536 537
      for(slot = pi->ppd->InputSlots; slot; slot = slot->next, i++)
	if(lpszOutput != NULL) {
538
	  lstrcpynA(cp, slot->FullName, 24);
Alexandre Julliard's avatar
Alexandre Julliard committed
539 540 541 542
	  cp += 24;
	}
      return i;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
543

544 545 546 547
  case DC_BINADJUST:
    FIXME("DC_BINADJUST: stub.\n");
    return DCBA_FACEUPNONE;

Alexandre Julliard's avatar
Alexandre Julliard committed
548
  case DC_ENUMRESOLUTIONS:
549 550 551 552 553 554 555 556 557 558
    {
      LONG *lp = (LONG*)lpszOutput;

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

559
  /* Windows returns 9999 too */
560
  case DC_COPIES:
561 562
    TRACE("DC_COPIES: returning 9999\n");
    return 9999;
563 564 565

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

567 568 569 570 571
  case DC_DATATYPE_PRODUCED:
    FIXME("DATA_TYPE_PRODUCED: stub.\n");
    return -1; /* simulate that the driver supports 'RAW' */

  case DC_DUPLEX:
572 573 574
    ret = 0;
    if(pi->ppd->DefaultDuplex && pi->ppd->DefaultDuplex->WinDuplex != 0)
      ret = 1;
575
    TRACE("DC_DUPLEX: returning %d\n", ret);
576
    return ret;
577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597

  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;
      POINT ptMax;
      ptMax.x = ptMax.y = 0;

598 599
      LIST_FOR_EACH_ENTRY(ps, &pi->ppd->PageSizes, PAGESIZE, entry)
      {
600 601 602 603 604
	if(ps->PaperDimension->x > ptMax.x)
	  ptMax.x = ps->PaperDimension->x;
	if(ps->PaperDimension->y > ptMax.y)
	  ptMax.y = ps->PaperDimension->y;
      }
605
      return MAKELONG(ptMax.x * 254.0 / 72.0, ptMax.y * 254.0 / 72.0 );
606 607 608 609 610
    }

  case DC_MINEXTENT:
    {
      PAGESIZE *ps;
611 612
      POINT ptMin;
      ptMin.x = ptMin.y = -1;
613

614 615
      LIST_FOR_EACH_ENTRY(ps, &pi->ppd->PageSizes, PAGESIZE, entry)
      {
616 617 618 619
	if(ptMin.x == -1 || ps->PaperDimension->x < ptMin.x)
	  ptMin.x = ps->PaperDimension->x;
	if(ptMin.y == -1 || ps->PaperDimension->y < ptMin.y)
	  ptMin.y = ps->PaperDimension->y;
620
      }
621
      return MAKELONG(ptMin.x * 254.0 / 72.0, ptMin.y * 254.0 / 72.0);
622 623 624 625 626 627 628 629 630 631 632
    }

  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
633

634
  /* We'll just return false here, very few printers can collate anyway */
635
  case DC_COLLATE:
636 637 638
    TRACE("DC_COLLATE: returning FALSE\n");
    return FALSE;

639 640
  /* Printer supports colour printing - 1 if yes, 0 if no (Win2k/XP only) */
  case DC_COLORDEVICE:
641
    return (pi->ppd->ColorDevice != CD_False) ? TRUE : FALSE;
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 714 715 716 717 718 719
  /* 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
720
  default:
721
    FIXME("Unsupported capability %d\n", fwCapability);
Alexandre Julliard's avatar
Alexandre Julliard committed
722 723 724 725
  }
  return -1;
}

726
/**************************************************************
727
 *     DeviceCapabilities [WINEPS16.91]
728
 */
729
DWORD WINAPI PSDRV_DeviceCapabilities16(LPCSTR lpszDevice,
730 731
			       LPCSTR lpszPort, WORD fwCapability,
			       LPSTR lpszOutput, LPDEVMODEA lpdm)
732
{
733
    return PSDRV_DeviceCapabilities(NULL, lpszDevice, lpszPort, fwCapability,
734
				      lpszOutput, lpdm);
735 736
}

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

#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;
764

765
    ps->nPages = 1;
766

767 768 769
}

#endif