driver.c 23 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 33 34 35

#include "config.h"

#include <string.h>

#include "wine/debug.h"
#include "psdrv.h"

#include "winuser.h"
36
#include "wine/wingdi16.h"
37 38
#include "wownt32.h"
#include "prsht.h"
39
#include "psdlg.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
    if(dm2->dmPublic.dmFields & DM_PAPERSIZE) {
        PAGESIZE *page;

70
	LIST_FOR_EACH_ENTRY(page, &pi->ppd->PageSizes, PAGESIZE, entry) {
71
	    if(page->WinPage == dm2->dmPublic.u1.s1.dmPaperSize)
Alexandre Julliard's avatar
Alexandre Julliard committed
72 73
	        break;
	}
74
	if(&page->entry != &pi->ppd->PageSizes ) {
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
    }

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

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

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
	for(slot = pi->ppd->InputSlots; slot; slot = slot->next) {
121
	    if(slot->WinBin == dm2->dmPublic.u1.s1.dmDefaultSource)
Alexandre Julliard's avatar
Alexandre Julliard committed
122 123 124
	        break;
	}
	if(slot) {
125
	    dm1->dmPublic.u1.s1.dmDefaultSource = dm2->dmPublic.u1.s1.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",
129
		dm2->dmPublic.u1.s1.dmDefaultSource);
Alexandre Julliard's avatar
Alexandre Julliard committed
130 131 132
	}
    }

133
   if (dm2->dmPublic.dmFields & DM_DEFAULTSOURCE )
134
       dm1->dmPublic.u1.s1.dmDefaultSource = dm2->dmPublic.u1.s1.dmDefaultSource;
135
   if (dm2->dmPublic.dmFields & DM_PRINTQUALITY )
136
       dm1->dmPublic.u1.s1.dmPrintQuality = dm2->dmPublic.u1.s1.dmPrintQuality;
137 138
   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
   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 )
156
       dm1->dmPublic.u2.dmDisplayFlags = dm2->dmPublic.u2.dmDisplayFlags;
157 158 159
   if (dm2->dmPublic.dmFields & DM_DISPLAYFREQUENCY )
       dm1->dmPublic.dmDisplayFrequency = dm2->dmPublic.dmDisplayFrequency;
   if (dm2->dmPublic.dmFields & DM_POSITION )
160
       dm1->dmPublic.u1.s2.dmPosition = dm2->dmPublic.u1.s2.dmPosition;
161 162 163 164 165 166 167 168 169 170 171 172 173 174
   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 181 182 183 184
/****************************************************************
 *       PSDRV_PaperDlgProc
 *
 * Dialog proc for 'Paper' propsheet
 */
185 186
static INT_PTR CALLBACK PSDRV_PaperDlgProc(HWND hwnd, UINT msg,
                                           WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
187
{
188
  PSDRV_DLGINFO *di;
189
  int i, Cursel = 0;
190
  PAGESIZE *ps;
191
  DUPLEX *duplex;
Alexandre Julliard's avatar
Alexandre Julliard committed
192

193 194 195
  switch(msg) {
  case WM_INITDIALOG:
    di = (PSDRV_DLGINFO*)((PROPSHEETPAGEA*)lParam)->lParam;
196
    SetWindowLongPtrW(hwnd, DWLP_USER, (LONG_PTR)di);
197

198 199
    i = 0;
    LIST_FOR_EACH_ENTRY(ps, &di->pi->ppd->PageSizes, PAGESIZE, entry) {
200
      SendDlgItemMessageA(hwnd, IDD_PAPERS, LB_INSERTSTRING, i,
201 202 203
			  (LPARAM)ps->FullName);
      if(di->pi->Devmode->dmPublic.u1.s1.dmPaperSize == ps->WinPage)
	Cursel = i;
204
      i++;
205 206
    }
    SendDlgItemMessageA(hwnd, IDD_PAPERS, LB_SETCURSEL, Cursel, 0);
207
    
208 209 210 211
    CheckRadioButton(hwnd, IDD_ORIENT_PORTRAIT, IDD_ORIENT_LANDSCAPE,
		     di->pi->Devmode->dmPublic.u1.s1.dmOrientation ==
		     DMORIENT_PORTRAIT ? IDD_ORIENT_PORTRAIT :
		     IDD_ORIENT_LANDSCAPE);
212 213 214 215 216 217 218 219 220 221 222 223 224 225

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

228
  case WM_COMMAND:
229
    di = (PSDRV_DLGINFO *)GetWindowLongPtrW(hwnd, DWLP_USER);
230 231 232 233
    switch(LOWORD(wParam)) {
    case IDD_PAPERS:
      if(HIWORD(wParam) == LBN_SELCHANGE) {
	Cursel = SendDlgItemMessageA(hwnd, LOWORD(wParam), LB_GETCURSEL, 0, 0);
234 235 236 237 238
        i = 0;
	LIST_FOR_EACH_ENTRY(ps, &di->pi->ppd->PageSizes, PAGESIZE, entry) {
            if(i >= Cursel) break;
            i++;
        }
239 240 241 242 243 244 245 246 247 248 249 250
	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;
251 252 253 254 255 256 257 258 259 260
    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;
261 262 263 264 265 266
    }
    break;

  case WM_NOTIFY:
   {
    NMHDR *nmhdr = (NMHDR *)lParam;
267
    di = (PSDRV_DLGINFO *)GetWindowLongPtrW(hwnd, DWLP_USER);
268 269
    switch(nmhdr->code) {
    case PSN_APPLY:
270
      *di->pi->Devmode = *di->dlgdm;
271
      SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, PSNRET_NOERROR);
Alexandre Julliard's avatar
Alexandre Julliard committed
272 273 274 275 276
      return TRUE;

    default:
      return FALSE;
    }
277 278
    break;
   }
279

280
  default:
Alexandre Julliard's avatar
Alexandre Julliard committed
281 282
    return FALSE;
  }
283
  return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
284 285 286
}


287
static void (WINAPI *pInitCommonControls) (void);
288 289
static HPROPSHEETPAGE (WINAPI *pCreatePropertySheetPage) (LPCPROPSHEETPAGEW);
static int (WINAPI *pPropertySheet) (LPCPROPSHEETHEADERW);
Alexandre Julliard's avatar
Alexandre Julliard committed
290

291 292 293 294 295 296

 /******************************************************************
 *         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
297
 *
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
 * 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
321
 */
322 323 324
INT CDECL 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
325
{
Alexandre Julliard's avatar
Alexandre Julliard committed
326
  PRINTERINFO *pi = PSDRV_FindPrinterInfo(lpszDevice);
327
  if(!pi) return -1;
Alexandre Julliard's avatar
Alexandre Julliard committed
328

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

332 333
  /* If dwMode == 0, return size of DEVMODE structure */
  if(!dwMode)
334
    return pi->Devmode->dmPublic.dmSize + pi->Devmode->dmPublic.dmDriverExtra;
335

336 337
  /* If DM_MODIFY is set, change settings in accordance with lpdmInput */
  if((dwMode & DM_MODIFY) && lpdmInput) {
338
    TRACE("DM_MODIFY set. devIn->dmFields = %08x\n", lpdmInput->dmFields);
339
    PSDRV_MergeDevmodes(pi->Devmode, (PSDRV_DEVMODEA *)lpdmInput, pi);
Alexandre Julliard's avatar
Alexandre Julliard committed
340 341
  }

342 343
  /* If DM_PROMPT is set, present modal dialog box */
  if(dwMode & DM_PROMPT) {
344
    HINSTANCE hinstComctl32;
345
    HPROPSHEETPAGE hpsp[1];
346 347
    PROPSHEETPAGEW psp;
    PROPSHEETHEADERW psh;
348 349
    PSDRV_DLGINFO *di;
    PSDRV_DEVMODEA *dlgdm;
350 351
    static const WCHAR PAPERW[] = {'P','A','P','E','R','\0'};
    static const WCHAR SetupW[] = {'S','e','t','u','p','\0'};
352 353 354 355 356

    hinstComctl32 = LoadLibraryA("comctl32.dll");
    pInitCommonControls = (void*)GetProcAddress(hinstComctl32,
						"InitCommonControls");
    pCreatePropertySheetPage = (void*)GetProcAddress(hinstComctl32,
357
						    "CreatePropertySheetPageW");
358
    pPropertySheet = (void*)GetProcAddress(hinstComctl32, "PropertySheetW");
359 360
    memset(&psp,0,sizeof(psp));
    dlgdm = HeapAlloc( PSDRV_Heap, 0, sizeof(*dlgdm) );
361
    *dlgdm = *pi->Devmode;
362 363 364 365
    di = HeapAlloc( PSDRV_Heap, 0, sizeof(*di) );
    di->pi = pi;
    di->dlgdm = dlgdm;
    psp.dwSize = sizeof(psp);
366
    psp.hInstance = PSDRV_hInstance;
367
    psp.u.pszTemplate = PAPERW;
368 369 370 371 372 373 374
    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);
375
    psh.pszCaption = SetupW;
376
    psh.nPages = 1;
377
    psh.hwndParent = HWND_32(hwnd);
378
    psh.u3.phpage = hpsp;
379

380
    pPropertySheet(&psh);
381

382
  }
383 384 385
  
  /* If DM_UPDATE is set, should write settings to environment and initialization file */
  if(dwMode & DM_UPDATE)
386 387
    FIXME("Mode DM_UPDATE.  Just do the same as DM_COPY\n");

388 389
  /* If DM_COPY is set, should write settings to lpdmOutput */
  if((dwMode & DM_COPY) || (dwMode & DM_UPDATE)) {
390
    if (lpdmOutput)
391
        memcpy(lpdmOutput, pi->Devmode, pi->Devmode->dmPublic.dmSize + pi->Devmode->dmPublic.dmDriverExtra );
392 393
    else
        FIXME("lpdmOutput is NULL what should we do??\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
394
  }
Alexandre Julliard's avatar
Alexandre Julliard committed
395 396
  return IDOK;
}
397
/***********************************************************************
398 399 400 401 402 403 404 405 406 407 408
 *	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
409
 *
410 411
 * Returns
 *      Result depends on the setting of fwCapability.  -1 indicates failure.
Alexandre Julliard's avatar
Alexandre Julliard committed
412
 */
413 414
DWORD CDECL PSDRV_DeviceCapabilities(LPSTR lpszDriver, LPCSTR lpszDevice, LPCSTR lpszPort,
                                     WORD fwCapability, LPSTR lpszOutput, LPDEVMODEA lpDevMode)
Alexandre Julliard's avatar
Alexandre Julliard committed
415
{
Alexandre Julliard's avatar
Alexandre Julliard committed
416
  PRINTERINFO *pi;
417
  DEVMODEA *lpdm;
418
  DWORD ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
419
  pi = PSDRV_FindPrinterInfo(lpszDevice);
420

421 422
  TRACE("%s %s %s, %u, %p, %p\n", debugstr_a(lpszDriver), debugstr_a(lpszDevice),
        debugstr_a(lpszPort), fwCapability, lpszOutput, lpDevMode);
423 424

  if (!pi) {
425 426 427
      ERR("no printer info for %s %s, return 0!\n",
          debugstr_a(lpszDriver), debugstr_a(lpszDevice));
      return 0;
428 429
  }

430
  lpdm = lpDevMode ? lpDevMode : (DEVMODEA *)pi->Devmode;
Alexandre Julliard's avatar
Alexandre Julliard committed
431 432 433 434

  switch(fwCapability) {

  case DC_PAPERS:
Alexandre Julliard's avatar
Alexandre Julliard committed
435 436 437 438 439
    {
      PAGESIZE *ps;
      WORD *wp = (WORD *)lpszOutput;
      int i = 0;

440 441
      LIST_FOR_EACH_ENTRY(ps, &pi->ppd->PageSizes, PAGESIZE, entry)
      {
442
        TRACE("DC_PAPERS: %u\n", ps->WinPage);
443
        i++;
Alexandre Julliard's avatar
Alexandre Julliard committed
444 445
	if(lpszOutput != NULL)
	  *wp++ = ps->WinPage;
446
      }
Alexandre Julliard's avatar
Alexandre Julliard committed
447 448
      return i;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
449 450

  case DC_PAPERSIZE:
Alexandre Julliard's avatar
Alexandre Julliard committed
451 452 453 454
    {
      PAGESIZE *ps;
      POINT16 *pt = (POINT16 *)lpszOutput;
      int i = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
455

456 457
      LIST_FOR_EACH_ENTRY(ps, &pi->ppd->PageSizes, PAGESIZE, entry)
      {
458
        TRACE("DC_PAPERSIZE: %f x %f\n", ps->PaperDimension->x, ps->PaperDimension->y);
459
        i++;
Alexandre Julliard's avatar
Alexandre Julliard committed
460 461 462 463 464
	if(lpszOutput != NULL) {
	  pt->x = ps->PaperDimension->x * 254.0 / 72.0;
	  pt->y = ps->PaperDimension->y * 254.0 / 72.0;
	  pt++;
	}
465
      }
Alexandre Julliard's avatar
Alexandre Julliard committed
466 467
      return i;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
468 469

  case DC_PAPERNAMES:
Alexandre Julliard's avatar
Alexandre Julliard committed
470 471 472 473 474
    {
      PAGESIZE *ps;
      char *cp = lpszOutput;
      int i = 0;

475 476
      LIST_FOR_EACH_ENTRY(ps, &pi->ppd->PageSizes, PAGESIZE, entry)
      {
477
        TRACE("DC_PAPERNAMES: %s\n", debugstr_a(ps->FullName));
478
        i++;
Alexandre Julliard's avatar
Alexandre Julliard committed
479
	if(lpszOutput != NULL) {
480
	  lstrcpynA(cp, ps->FullName, 64);
Alexandre Julliard's avatar
Alexandre Julliard committed
481 482
	  cp += 64;
	}
483
      }
Alexandre Julliard's avatar
Alexandre Julliard committed
484 485
      return i;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
486 487

  case DC_ORIENTATION:
Alexandre Julliard's avatar
Alexandre Julliard committed
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
    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;
507

Alexandre Julliard's avatar
Alexandre Julliard committed
508 509
      for(slot = pi->ppd->InputSlots; slot; slot = slot->next, i++)
	if(lpszOutput != NULL) {
510
	  lstrcpynA(cp, slot->FullName, 24);
Alexandre Julliard's avatar
Alexandre Julliard committed
511 512 513 514
	  cp += 24;
	}
      return i;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
515

516 517 518 519
  case DC_BINADJUST:
    FIXME("DC_BINADJUST: stub.\n");
    return DCBA_FACEUPNONE;

Alexandre Julliard's avatar
Alexandre Julliard committed
520
  case DC_ENUMRESOLUTIONS:
521 522 523 524
    {
      LONG *lp = (LONG*)lpszOutput;

      if(lpszOutput != NULL) {
525 526
	lp[0] = pi->ppd->DefaultResolution;
	lp[1] = pi->ppd->DefaultResolution;
527 528 529 530
      }
      return 1;
    }

531
  /* Windows returns 9999 too */
532
  case DC_COPIES:
533 534
    TRACE("DC_COPIES: returning 9999\n");
    return 9999;
535 536 537

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

539 540 541 542 543
  case DC_DATATYPE_PRODUCED:
    FIXME("DATA_TYPE_PRODUCED: stub.\n");
    return -1; /* simulate that the driver supports 'RAW' */

  case DC_DUPLEX:
544 545 546
    ret = 0;
    if(pi->ppd->DefaultDuplex && pi->ppd->DefaultDuplex->WinDuplex != 0)
      ret = 1;
547
    TRACE("DC_DUPLEX: returning %d\n", ret);
548
    return ret;
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569

  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;

570 571
      LIST_FOR_EACH_ENTRY(ps, &pi->ppd->PageSizes, PAGESIZE, entry)
      {
572 573 574 575 576
	if(ps->PaperDimension->x > ptMax.x)
	  ptMax.x = ps->PaperDimension->x;
	if(ps->PaperDimension->y > ptMax.y)
	  ptMax.y = ps->PaperDimension->y;
      }
577
      return MAKELONG(ptMax.x * 254.0 / 72.0, ptMax.y * 254.0 / 72.0 );
578 579 580 581 582
    }

  case DC_MINEXTENT:
    {
      PAGESIZE *ps;
583 584
      POINT ptMin;
      ptMin.x = ptMin.y = -1;
585

586 587
      LIST_FOR_EACH_ENTRY(ps, &pi->ppd->PageSizes, PAGESIZE, entry)
      {
588 589 590 591
	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;
592
      }
593
      return MAKELONG(ptMin.x * 254.0 / 72.0, ptMin.y * 254.0 / 72.0);
594 595 596 597 598 599 600 601 602 603 604
    }

  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
605

606
  /* We'll just return false here, very few printers can collate anyway */
607
  case DC_COLLATE:
608 609 610
    TRACE("DC_COLLATE: returning FALSE\n");
    return FALSE;

611 612
  /* Printer supports colour printing - 1 if yes, 0 if no (Win2k/XP only) */
  case DC_COLORDEVICE:
613
    return (pi->ppd->ColorDevice != CD_False) ? TRUE : FALSE;
614

615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 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
  /* 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
692
  default:
693
    FIXME("Unsupported capability %d\n", fwCapability);
Alexandre Julliard's avatar
Alexandre Julliard committed
694 695 696 697
  }
  return -1;
}

698 699 700 701 702 703 704 705 706 707 708 709 710 711 712
#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;
713

714
    ps->nPages = 1;
715

716 717 718
}

#endif