2 * Unix interface for wineps.drv
4 * Copyright 1998 Huw D M Davies
5 * Copyright 2001 Marcus Meissner
6 * Copyright 2023 Piotr Caban for CodeWeavers
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
34 #include "wine/gdi_driver.h"
35 #include "wine/debug.h"
36 #include "wine/wingdi16.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(psdrv
);
40 /* copied from kernelbase */
41 static int muldiv(int a
, int b
, int c
)
47 /* We want to deal with a positive divisor to simplify the logic. */
54 /* If the result is positive, we "add" to round. else, we subtract to round. */
55 if ((a
< 0 && b
< 0) || (a
>= 0 && b
>= 0))
56 ret
= (((LONGLONG
)a
* b
) + (c
/ 2)) / c
;
58 ret
= (((LONGLONG
)a
* b
) - (c
/ 2)) / c
;
60 if (ret
> 2147483647 || ret
< -2147483647) return -1;
64 static void dump_fields(int fields
)
68 #define CHECK_FIELD(flag) \
73 if (add_space++) TRACE(" "); \
80 CHECK_FIELD(DM_ORIENTATION
);
81 CHECK_FIELD(DM_PAPERSIZE
);
82 CHECK_FIELD(DM_PAPERLENGTH
);
83 CHECK_FIELD(DM_PAPERWIDTH
);
84 CHECK_FIELD(DM_SCALE
);
85 CHECK_FIELD(DM_POSITION
);
87 CHECK_FIELD(DM_DISPLAYORIENTATION
);
88 CHECK_FIELD(DM_COPIES
);
89 CHECK_FIELD(DM_DEFAULTSOURCE
);
90 CHECK_FIELD(DM_PRINTQUALITY
);
91 CHECK_FIELD(DM_COLOR
);
92 CHECK_FIELD(DM_DUPLEX
);
93 CHECK_FIELD(DM_YRESOLUTION
);
94 CHECK_FIELD(DM_TTOPTION
);
95 CHECK_FIELD(DM_COLLATE
);
96 CHECK_FIELD(DM_FORMNAME
);
97 CHECK_FIELD(DM_LOGPIXELS
);
98 CHECK_FIELD(DM_BITSPERPEL
);
99 CHECK_FIELD(DM_PELSWIDTH
);
100 CHECK_FIELD(DM_PELSHEIGHT
);
101 CHECK_FIELD(DM_DISPLAYFLAGS
);
102 CHECK_FIELD(DM_DISPLAYFREQUENCY
);
103 CHECK_FIELD(DM_ICMMETHOD
);
104 CHECK_FIELD(DM_ICMINTENT
);
105 CHECK_FIELD(DM_MEDIATYPE
);
106 CHECK_FIELD(DM_DITHERTYPE
);
107 CHECK_FIELD(DM_PANNINGWIDTH
);
108 CHECK_FIELD(DM_PANNINGHEIGHT
);
109 if (fields
) TRACE(" %#x", fields
);
114 static void dump_devmode(const DEVMODEW
*dm
)
116 if (!TRACE_ON(psdrv
)) return;
118 TRACE("dmDeviceName: %s\n", debugstr_w(dm
->dmDeviceName
));
119 TRACE("dmSpecVersion: 0x%04x\n", dm
->dmSpecVersion
);
120 TRACE("dmDriverVersion: 0x%04x\n", dm
->dmDriverVersion
);
121 TRACE("dmSize: 0x%04x\n", dm
->dmSize
);
122 TRACE("dmDriverExtra: 0x%04x\n", dm
->dmDriverExtra
);
123 TRACE("dmFields: 0x%04x\n", (int)dm
->dmFields
);
124 dump_fields(dm
->dmFields
);
125 TRACE("dmOrientation: %d\n", dm
->dmOrientation
);
126 TRACE("dmPaperSize: %d\n", dm
->dmPaperSize
);
127 TRACE("dmPaperLength: %d\n", dm
->dmPaperLength
);
128 TRACE("dmPaperWidth: %d\n", dm
->dmPaperWidth
);
129 TRACE("dmScale: %d\n", dm
->dmScale
);
130 TRACE("dmCopies: %d\n", dm
->dmCopies
);
131 TRACE("dmDefaultSource: %d\n", dm
->dmDefaultSource
);
132 TRACE("dmPrintQuality: %d\n", dm
->dmPrintQuality
);
133 TRACE("dmColor: %d\n", dm
->dmColor
);
134 TRACE("dmDuplex: %d\n", dm
->dmDuplex
);
135 TRACE("dmYResolution: %d\n", dm
->dmYResolution
);
136 TRACE("dmTTOption: %d\n", dm
->dmTTOption
);
137 TRACE("dmCollate: %d\n", dm
->dmCollate
);
138 TRACE("dmFormName: %s\n", debugstr_w(dm
->dmFormName
));
139 TRACE("dmLogPixels %u\n", dm
->dmLogPixels
);
140 TRACE("dmBitsPerPel %u\n", (unsigned int)dm
->dmBitsPerPel
);
141 TRACE("dmPelsWidth %u\n", (unsigned int)dm
->dmPelsWidth
);
142 TRACE("dmPelsHeight %u\n", (unsigned int)dm
->dmPelsHeight
);
145 static INT CDECL
get_device_caps(PHYSDEV dev
, INT cap
)
147 PSDRV_PDEVICE
*pdev
= get_psdrv_dev(dev
);
149 TRACE("%p,%d\n", dev
->hdc
, cap
);
156 return DT_RASPRINTER
;
158 return muldiv(pdev
->horzSize
, 100, pdev
->Devmode
->dmPublic
.dmScale
);
160 return muldiv(pdev
->vertSize
, 100, pdev
->Devmode
->dmPublic
.dmScale
);
162 return pdev
->horzRes
;
164 return pdev
->vertRes
;
166 /* Although Windows returns 1 for monochrome printers, we want
167 CreateCompatibleBitmap to provide something other than 1 bpp */
176 return sizeof(PSDRV_PDEVICE
);
178 return TC_CR_ANY
| TC_VA_ABLE
; /* psdrv 0x59f7 */
180 return (RC_BITBLT
| RC_BITMAP64
| RC_GDI20_OUTPUT
| RC_DIBTODEV
|
181 RC_STRETCHBLT
| RC_STRETCHDIB
); /* psdrv 0x6e99 */
183 return pdev
->logPixelsX
;
185 return pdev
->logPixelsY
;
187 return muldiv(pdev
->logPixelsX
, pdev
->Devmode
->dmPublic
.dmScale
, 100);
189 return muldiv(pdev
->logPixelsY
, pdev
->Devmode
->dmPublic
.dmScale
, 100);
195 return (pdev
->Devmode
->dmPublic
.dmOrientation
== DMORIENT_LANDSCAPE
) ?
196 pdev
->PageSize
.cy
: pdev
->PageSize
.cx
;
198 return (pdev
->Devmode
->dmPublic
.dmOrientation
== DMORIENT_LANDSCAPE
) ?
199 pdev
->PageSize
.cx
: pdev
->PageSize
.cy
;
200 case PHYSICALOFFSETX
:
201 if (pdev
->Devmode
->dmPublic
.dmOrientation
== DMORIENT_LANDSCAPE
)
203 if (pdev
->pi
->ppd
->LandscapeOrientation
== -90)
204 return pdev
->PageSize
.cy
- pdev
->ImageableArea
.top
;
206 return pdev
->ImageableArea
.bottom
;
208 return pdev
->ImageableArea
.left
;
210 case PHYSICALOFFSETY
:
211 if (pdev
->Devmode
->dmPublic
.dmOrientation
== DMORIENT_LANDSCAPE
)
213 if (pdev
->pi
->ppd
->LandscapeOrientation
== -90)
214 return pdev
->PageSize
.cx
- pdev
->ImageableArea
.right
;
216 return pdev
->ImageableArea
.left
;
218 return pdev
->PageSize
.cy
- pdev
->ImageableArea
.top
;
221 dev
= GET_NEXT_PHYSDEV(dev
, pGetDeviceCaps
);
222 return dev
->funcs
->pGetDeviceCaps(dev
, cap
);
226 static inline int paper_size_from_points(float size
)
228 return size
* 254 / 72;
231 static INPUTSLOT
*unix_find_slot(PPD
*ppd
, const PSDRV_DEVMODE
*dm
)
235 LIST_FOR_EACH_ENTRY(slot
, &ppd
->InputSlots
, INPUTSLOT
, entry
)
236 if (slot
->WinBin
== dm
->dmPublic
.dmDefaultSource
)
242 static PAGESIZE
*unix_find_pagesize(PPD
*ppd
, const PSDRV_DEVMODE
*dm
)
246 LIST_FOR_EACH_ENTRY(page
, &ppd
->PageSizes
, PAGESIZE
, entry
)
247 if (page
->WinPage
== dm
->dmPublic
.dmPaperSize
)
253 static void merge_devmodes(PSDRV_DEVMODE
*dm1
, const PSDRV_DEVMODE
*dm2
, PRINTERINFO
*pi
)
255 /* some sanity checks here on dm2 */
257 if (dm2
->dmPublic
.dmFields
& DM_ORIENTATION
)
259 dm1
->dmPublic
.dmOrientation
= dm2
->dmPublic
.dmOrientation
;
260 TRACE("Changing orientation to %d (%s)\n",
261 dm1
->dmPublic
.dmOrientation
,
262 dm1
->dmPublic
.dmOrientation
== DMORIENT_PORTRAIT
?
264 (dm1
->dmPublic
.dmOrientation
== DMORIENT_LANDSCAPE
?
265 "Landscape" : "unknown"));
268 /* NB PaperWidth is always < PaperLength */
269 if (dm2
->dmPublic
.dmFields
& DM_PAPERSIZE
)
271 PAGESIZE
*page
= unix_find_pagesize(pi
->ppd
, dm2
);
275 dm1
->dmPublic
.dmPaperSize
= dm2
->dmPublic
.dmPaperSize
;
276 dm1
->dmPublic
.dmPaperWidth
= paper_size_from_points(page
->PaperDimension
->x
);
277 dm1
->dmPublic
.dmPaperLength
= paper_size_from_points(page
->PaperDimension
->y
);
278 dm1
->dmPublic
.dmFields
|= DM_PAPERSIZE
| DM_PAPERWIDTH
| DM_PAPERLENGTH
;
279 TRACE("Changing page to %s %d x %d\n", debugstr_w(page
->FullName
),
280 dm1
->dmPublic
.dmPaperWidth
,
281 dm1
->dmPublic
.dmPaperLength
);
283 if (dm1
->dmPublic
.dmSize
>= FIELD_OFFSET(DEVMODEW
, dmFormName
) + CCHFORMNAME
* sizeof(WCHAR
))
285 lstrcpynW(dm1
->dmPublic
.dmFormName
, page
->FullName
, CCHFORMNAME
);
286 dm1
->dmPublic
.dmFields
|= DM_FORMNAME
;
290 TRACE("Trying to change to unsupported pagesize %d\n", dm2
->dmPublic
.dmPaperSize
);
293 else if ((dm2
->dmPublic
.dmFields
& DM_PAPERLENGTH
) &&
294 (dm2
->dmPublic
.dmFields
& DM_PAPERWIDTH
))
296 dm1
->dmPublic
.dmPaperLength
= dm2
->dmPublic
.dmPaperLength
;
297 dm1
->dmPublic
.dmPaperWidth
= dm2
->dmPublic
.dmPaperWidth
;
298 TRACE("Changing PaperLength|Width to %dx%d\n",
299 dm2
->dmPublic
.dmPaperLength
,
300 dm2
->dmPublic
.dmPaperWidth
);
301 dm1
->dmPublic
.dmFields
&= ~DM_PAPERSIZE
;
302 dm1
->dmPublic
.dmFields
|= (DM_PAPERLENGTH
| DM_PAPERWIDTH
);
304 else if (dm2
->dmPublic
.dmFields
& (DM_PAPERLENGTH
| DM_PAPERWIDTH
))
306 /* You might think that this would be allowed if dm1 is in custom size
307 mode, but apparently Windows reverts to standard paper mode even in
309 FIXME("Trying to change only paperlength or paperwidth\n");
310 dm1
->dmPublic
.dmFields
&= ~(DM_PAPERLENGTH
| DM_PAPERWIDTH
);
311 dm1
->dmPublic
.dmFields
|= DM_PAPERSIZE
;
314 if (dm2
->dmPublic
.dmFields
& DM_SCALE
)
316 dm1
->dmPublic
.dmScale
= dm2
->dmPublic
.dmScale
;
317 TRACE("Changing Scale to %d\n", dm2
->dmPublic
.dmScale
);
320 if (dm2
->dmPublic
.dmFields
& DM_COPIES
)
322 dm1
->dmPublic
.dmCopies
= dm2
->dmPublic
.dmCopies
;
323 TRACE("Changing Copies to %d\n", dm2
->dmPublic
.dmCopies
);
326 if (dm2
->dmPublic
.dmFields
& DM_DEFAULTSOURCE
)
328 INPUTSLOT
*slot
= unix_find_slot(pi
->ppd
, dm2
);
332 dm1
->dmPublic
.dmDefaultSource
= dm2
->dmPublic
.dmDefaultSource
;
333 TRACE("Changing bin to '%s'\n", slot
->FullName
);
337 TRACE("Trying to change to unsupported bin %d\n", dm2
->dmPublic
.dmDefaultSource
);
341 if (dm2
->dmPublic
.dmFields
& DM_DEFAULTSOURCE
)
342 dm1
->dmPublic
.dmDefaultSource
= dm2
->dmPublic
.dmDefaultSource
;
343 if (dm2
->dmPublic
.dmFields
& DM_PRINTQUALITY
)
344 dm1
->dmPublic
.dmPrintQuality
= dm2
->dmPublic
.dmPrintQuality
;
345 if (dm2
->dmPublic
.dmFields
& DM_COLOR
)
346 dm1
->dmPublic
.dmColor
= dm2
->dmPublic
.dmColor
;
347 if (dm2
->dmPublic
.dmFields
& DM_DUPLEX
&& pi
->ppd
->DefaultDuplex
&& pi
->ppd
->DefaultDuplex
->WinDuplex
!= 0)
348 dm1
->dmPublic
.dmDuplex
= dm2
->dmPublic
.dmDuplex
;
349 if (dm2
->dmPublic
.dmFields
& DM_YRESOLUTION
)
350 dm1
->dmPublic
.dmYResolution
= dm2
->dmPublic
.dmYResolution
;
351 if (dm2
->dmPublic
.dmFields
& DM_TTOPTION
)
352 dm1
->dmPublic
.dmTTOption
= dm2
->dmPublic
.dmTTOption
;
353 if (dm2
->dmPublic
.dmFields
& DM_COLLATE
)
354 dm1
->dmPublic
.dmCollate
= dm2
->dmPublic
.dmCollate
;
355 if (dm2
->dmPublic
.dmFields
& DM_FORMNAME
)
356 lstrcpynW(dm1
->dmPublic
.dmFormName
, dm2
->dmPublic
.dmFormName
, CCHFORMNAME
);
357 if (dm2
->dmPublic
.dmFields
& DM_BITSPERPEL
)
358 dm1
->dmPublic
.dmBitsPerPel
= dm2
->dmPublic
.dmBitsPerPel
;
359 if (dm2
->dmPublic
.dmFields
& DM_PELSWIDTH
)
360 dm1
->dmPublic
.dmPelsWidth
= dm2
->dmPublic
.dmPelsWidth
;
361 if (dm2
->dmPublic
.dmFields
& DM_PELSHEIGHT
)
362 dm1
->dmPublic
.dmPelsHeight
= dm2
->dmPublic
.dmPelsHeight
;
363 if (dm2
->dmPublic
.dmFields
& DM_DISPLAYFLAGS
)
364 dm1
->dmPublic
.dmDisplayFlags
= dm2
->dmPublic
.dmDisplayFlags
;
365 if (dm2
->dmPublic
.dmFields
& DM_DISPLAYFREQUENCY
)
366 dm1
->dmPublic
.dmDisplayFrequency
= dm2
->dmPublic
.dmDisplayFrequency
;
367 if (dm2
->dmPublic
.dmFields
& DM_POSITION
)
368 dm1
->dmPublic
.dmPosition
= dm2
->dmPublic
.dmPosition
;
369 if (dm2
->dmPublic
.dmFields
& DM_LOGPIXELS
)
370 dm1
->dmPublic
.dmLogPixels
= dm2
->dmPublic
.dmLogPixels
;
371 if (dm2
->dmPublic
.dmFields
& DM_ICMMETHOD
)
372 dm1
->dmPublic
.dmICMMethod
= dm2
->dmPublic
.dmICMMethod
;
373 if (dm2
->dmPublic
.dmFields
& DM_ICMINTENT
)
374 dm1
->dmPublic
.dmICMIntent
= dm2
->dmPublic
.dmICMIntent
;
375 if (dm2
->dmPublic
.dmFields
& DM_MEDIATYPE
)
376 dm1
->dmPublic
.dmMediaType
= dm2
->dmPublic
.dmMediaType
;
377 if (dm2
->dmPublic
.dmFields
& DM_DITHERTYPE
)
378 dm1
->dmPublic
.dmDitherType
= dm2
->dmPublic
.dmDitherType
;
379 if (dm2
->dmPublic
.dmFields
& DM_PANNINGWIDTH
)
380 dm1
->dmPublic
.dmPanningWidth
= dm2
->dmPublic
.dmPanningWidth
;
381 if (dm2
->dmPublic
.dmFields
& DM_PANNINGHEIGHT
)
382 dm1
->dmPublic
.dmPanningHeight
= dm2
->dmPublic
.dmPanningHeight
;
385 static void update_dev_caps(PSDRV_PDEVICE
*pdev
)
387 INT width
= 0, height
= 0, resx
= 0, resy
= 0;
391 dump_devmode(&pdev
->Devmode
->dmPublic
);
393 if (pdev
->Devmode
->dmPublic
.dmFields
& (DM_PRINTQUALITY
| DM_YRESOLUTION
| DM_LOGPIXELS
))
395 if (pdev
->Devmode
->dmPublic
.dmFields
& DM_PRINTQUALITY
)
396 resx
= resy
= pdev
->Devmode
->dmPublic
.dmPrintQuality
;
398 if (pdev
->Devmode
->dmPublic
.dmFields
& DM_YRESOLUTION
)
399 resy
= pdev
->Devmode
->dmPublic
.dmYResolution
;
401 if (pdev
->Devmode
->dmPublic
.dmFields
& DM_LOGPIXELS
)
402 resx
= resy
= pdev
->Devmode
->dmPublic
.dmLogPixels
;
404 LIST_FOR_EACH_ENTRY(res
, &pdev
->pi
->ppd
->Resolutions
, RESOLUTION
, entry
)
406 if (res
->resx
== resx
&& res
->resy
== resy
)
408 pdev
->logPixelsX
= resx
;
409 pdev
->logPixelsY
= resy
;
414 if (&res
->entry
== &pdev
->pi
->ppd
->Resolutions
)
416 WARN("Requested resolution %dx%d is not supported by device\n", resx
, resy
);
417 pdev
->logPixelsX
= pdev
->pi
->ppd
->DefaultResolution
;
418 pdev
->logPixelsY
= pdev
->logPixelsX
;
423 WARN("Using default device resolution %d\n", pdev
->pi
->ppd
->DefaultResolution
);
424 pdev
->logPixelsX
= pdev
->pi
->ppd
->DefaultResolution
;
425 pdev
->logPixelsY
= pdev
->logPixelsX
;
428 if (pdev
->Devmode
->dmPublic
.dmFields
& DM_PAPERSIZE
) {
429 LIST_FOR_EACH_ENTRY(page
, &pdev
->pi
->ppd
->PageSizes
, PAGESIZE
, entry
) {
430 if (page
->WinPage
== pdev
->Devmode
->dmPublic
.dmPaperSize
)
434 if (&page
->entry
== &pdev
->pi
->ppd
->PageSizes
) {
435 FIXME("Can't find page\n");
436 SetRectEmpty(&pdev
->ImageableArea
);
437 pdev
->PageSize
.cx
= 0;
438 pdev
->PageSize
.cy
= 0;
439 } else if (page
->ImageableArea
) {
440 /* pdev sizes in device units; ppd sizes in 1/72" */
441 SetRect(&pdev
->ImageableArea
, page
->ImageableArea
->llx
* pdev
->logPixelsX
/ 72,
442 page
->ImageableArea
->ury
* pdev
->logPixelsY
/ 72,
443 page
->ImageableArea
->urx
* pdev
->logPixelsX
/ 72,
444 page
->ImageableArea
->lly
* pdev
->logPixelsY
/ 72);
445 pdev
->PageSize
.cx
= page
->PaperDimension
->x
*
446 pdev
->logPixelsX
/ 72;
447 pdev
->PageSize
.cy
= page
->PaperDimension
->y
*
448 pdev
->logPixelsY
/ 72;
450 pdev
->ImageableArea
.left
= pdev
->ImageableArea
.bottom
= 0;
451 pdev
->ImageableArea
.right
= pdev
->PageSize
.cx
=
452 page
->PaperDimension
->x
* pdev
->logPixelsX
/ 72;
453 pdev
->ImageableArea
.top
= pdev
->PageSize
.cy
=
454 page
->PaperDimension
->y
* pdev
->logPixelsY
/ 72;
456 } else if ((pdev
->Devmode
->dmPublic
.dmFields
& DM_PAPERLENGTH
) &&
457 (pdev
->Devmode
->dmPublic
.dmFields
& DM_PAPERWIDTH
)) {
458 /* pdev sizes in device units; Devmode sizes in 1/10 mm */
459 pdev
->ImageableArea
.left
= pdev
->ImageableArea
.bottom
= 0;
460 pdev
->ImageableArea
.right
= pdev
->PageSize
.cx
=
461 pdev
->Devmode
->dmPublic
.dmPaperWidth
* pdev
->logPixelsX
/ 254;
462 pdev
->ImageableArea
.top
= pdev
->PageSize
.cy
=
463 pdev
->Devmode
->dmPublic
.dmPaperLength
* pdev
->logPixelsY
/ 254;
465 FIXME("Odd dmFields %x\n", (int)pdev
->Devmode
->dmPublic
.dmFields
);
466 SetRectEmpty(&pdev
->ImageableArea
);
467 pdev
->PageSize
.cx
= 0;
468 pdev
->PageSize
.cy
= 0;
471 TRACE("ImageableArea = %s: PageSize = %dx%d\n", wine_dbgstr_rect(&pdev
->ImageableArea
),
472 (int)pdev
->PageSize
.cx
, (int)pdev
->PageSize
.cy
);
474 /* these are in device units */
475 width
= pdev
->ImageableArea
.right
- pdev
->ImageableArea
.left
;
476 height
= pdev
->ImageableArea
.top
- pdev
->ImageableArea
.bottom
;
478 if (pdev
->Devmode
->dmPublic
.dmOrientation
== DMORIENT_PORTRAIT
) {
479 pdev
->horzRes
= width
;
480 pdev
->vertRes
= height
;
482 pdev
->horzRes
= height
;
483 pdev
->vertRes
= width
;
486 /* these are in mm */
487 pdev
->horzSize
= (pdev
->horzRes
* 25.4) / pdev
->logPixelsX
;
488 pdev
->vertSize
= (pdev
->vertRes
* 25.4) / pdev
->logPixelsY
;
490 TRACE("devcaps: horzSize = %dmm, vertSize = %dmm, "
491 "horzRes = %d, vertRes = %d\n",
492 pdev
->horzSize
, pdev
->vertSize
,
493 pdev
->horzRes
, pdev
->vertRes
);
496 static BOOL CDECL
reset_dc(PHYSDEV dev
, const DEVMODEW
*devmode
)
498 PSDRV_PDEVICE
*pdev
= get_psdrv_dev(dev
);
502 merge_devmodes(pdev
->Devmode
, (const PSDRV_DEVMODE
*)devmode
, pdev
->pi
);
503 update_dev_caps(pdev
);
508 static int CDECL
ext_escape(PHYSDEV dev
, int escape
, int input_size
, const void *input
,
509 int output_size
, void *output
)
511 TRACE("%p,%d,%d,%p,%d,%p\n",
512 dev
->hdc
, escape
, input_size
, input
, output_size
, output
);
516 case QUERYESCSUPPORT
:
517 if (input_size
< sizeof(SHORT
))
519 WARN("input_size < sizeof(SHORT) (=%d) for QUERYESCSUPPORT\n", input_size
);
524 DWORD num
= (input_size
< sizeof(DWORD
)) ? *(const USHORT
*)input
: *(const DWORD
*)input
;
525 TRACE("QUERYESCSUPPORT for %d\n", (int)num
);
537 case EXT_DEVICE_CAPS
:
540 case POSTSCRIPT_DATA
:
542 case POSTSCRIPT_PASSTHROUGH
:
543 case POSTSCRIPT_IGNORE
:
547 /*case DRAWPATTERNRECT:*/
549 /* PageMaker checks for it */
552 /* PageMaker doesn't check for DOWNLOADFACE and GETFACENAME but
553 * uses them, they are supposed to be supported by any PS printer.
557 /* PageMaker checks for these as a part of process of detecting
558 * a "fully compatible" PS printer, but doesn't actually use them.
564 /* Windows PS driver reports 0, but still supports this escape */
566 return FALSE
; /* suppress the FIXME below */
569 FIXME("QUERYESCSUPPORT(%d) - not supported.\n", (int)num
);
575 FIXME("OPENCHANNEL: stub\n");
579 FIXME("CLOSECHANNEL: stub\n");
583 FIXME("DOWNLOADHEADER: stub\n");
584 /* should return name of the downloaded procset */
589 FIXME("GETFACENAME: stub\n");
590 lstrcpynA(output
, "Courier", output_size
);
594 FIXME("DOWNLOADFACE: stub\n");
599 FIXME("MFCOMMENT(%p, %d)\n", input
, input_size
);
602 case DRAWPATTERNRECT
:
604 DRAWPATRECT
*dpr
= (DRAWPATRECT
*)input
;
606 FIXME("DRAWPATTERNRECT(pos (%d,%d), size %dx%d, style %d, pattern %x), stub!\n",
607 (int)dpr
->ptPosition
.x
, (int)dpr
->ptPosition
.y
,
608 (int)dpr
->ptSize
.x
, (int)dpr
->ptSize
.y
,
609 dpr
->wStyle
, dpr
->wPattern
);
614 BANDINFOSTRUCT
*ibi
= (BANDINFOSTRUCT
*)input
;
615 BANDINFOSTRUCT
*obi
= (BANDINFOSTRUCT
*)output
;
617 FIXME("BANDINFO(graphics %d, text %d, rect %s), stub!\n", ibi
->GraphicsFlag
,
618 ibi
->TextFlag
, wine_dbgstr_rect(&ibi
->GraphicsRect
));
625 const INT
*NumCopies
= input
;
626 INT
*ActualCopies
= output
;
627 if (input_size
!= sizeof(INT
))
629 WARN("input_size != sizeof(INT) (=%d) for SETCOPYCOUNT\n", input_size
);
632 TRACE("SETCOPYCOUNT %d\n", *NumCopies
);
640 strcpy(p
, "PostScript");
641 *(p
+ strlen(p
) + 1) = '\0'; /* 2 '\0's at end of string */
647 INT newCap
= *(const INT
*)input
;
648 if (input_size
!= sizeof(INT
))
650 WARN("input_size != sizeof(INT) (=%d) for SETLINECAP\n", input_size
);
653 TRACE("SETLINECAP %d\n", newCap
);
659 INT newJoin
= *(const INT
*)input
;
660 if (input_size
!= sizeof(INT
))
662 WARN("input_size != sizeof(INT) (=%d) for SETLINEJOIN\n", input_size
);
665 TRACE("SETLINEJOIN %d\n", newJoin
);
671 INT newLimit
= *(const INT
*)input
;
672 if (input_size
!= sizeof(INT
))
674 WARN("input_size != sizeof(INT) (=%d) for SETMITERLIMIT\n", input_size
);
677 TRACE("SETMITERLIMIT %d\n", newLimit
);
682 /* Undocumented escape used by winword6.
683 Switches between ANSI and a special charset.
684 If *lpInData == 1 we require that
688 0x94 is quotedblright
692 0xa0 is non break space - yeah right.
694 If *lpInData == 0 we get ANSI.
695 Since there's nothing else there, let's just make these the default
696 anyway and see what happens...
700 case EXT_DEVICE_CAPS
:
702 UINT cap
= *(const UINT
*)input
;
703 if (input_size
!= sizeof(UINT
))
705 WARN("input_size != sizeof(UINT) (=%d) for EXT_DEVICE_CAPS\n", input_size
);
708 TRACE("EXT_DEVICE_CAPS %d\n", cap
);
714 const RECT
*r
= input
;
715 if (input_size
!= sizeof(RECT
))
717 WARN("input_size != sizeof(RECT) (=%d) for SET_BOUNDS\n", input_size
);
720 TRACE("SET_BOUNDS %s\n", wine_dbgstr_rect(r
));
726 UINT epsprint
= *(const UINT
*)input
;
727 /* FIXME: In this mode we do not need to send page intros and page
728 * ends according to the doc. But I just ignore that detail
731 TRACE("EPS Printing support %sable.\n",epsprint
?"en":"dis");
735 case POSTSCRIPT_DATA
:
737 case POSTSCRIPT_PASSTHROUGH
:
740 case POSTSCRIPT_IGNORE
:
743 case GETSETPRINTORIENT
:
745 /* If lpInData is present, it is a 20 byte structure, first 32
746 * bit LONG value is the orientation. if lpInData is NULL, it
747 * returns the current orientation.
749 FIXME("GETSETPRINTORIENT not implemented (data %p)!\n",input
);
761 FIXME("Unimplemented code %d\n", escape
);
766 static NTSTATUS
init_dc(void *arg
)
768 struct init_dc_params
*params
= arg
;
770 params
->funcs
->pGetDeviceCaps
= get_device_caps
;
771 params
->funcs
->pResetDC
= reset_dc
;
772 params
->funcs
->pExtEscape
= ext_escape
;
776 const unixlib_entry_t __wine_unix_call_funcs
[] =
781 C_ASSERT(ARRAYSIZE(__wine_unix_call_funcs
) == unix_funcs_count
);