wineps: Move ExtEscape implementation to unixlib.
[wine.git] / dlls / wineps.drv / unixlib.c
blob2c80e2f75e20ac359de2f8a471bb84d78651647e
1 /*
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
23 #if 0
24 #pragma makedep unix
25 #endif
27 #include <stdarg.h>
29 #include "windef.h"
30 #include "winbase.h"
32 #include "psdrv.h"
33 #include "unixlib.h"
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)
43 LONGLONG ret;
45 if (!c) return -1;
47 /* We want to deal with a positive divisor to simplify the logic. */
48 if (c < 0)
50 a = -a;
51 c = -c;
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;
57 else
58 ret = (((LONGLONG)a * b) - (c / 2)) / c;
60 if (ret > 2147483647 || ret < -2147483647) return -1;
61 return ret;
64 static void dump_fields(int fields)
66 int add_space = 0;
68 #define CHECK_FIELD(flag) \
69 do \
70 { \
71 if (fields & flag) \
72 { \
73 if (add_space++) TRACE(" "); \
74 TRACE(#flag); \
75 fields &= ~flag; \
76 } \
77 } \
78 while (0)
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);
86 CHECK_FIELD(DM_NUP);
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);
110 TRACE("\n");
111 #undef CHECK_FIELD
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);
151 switch(cap)
153 case DRIVERVERSION:
154 return 0;
155 case TECHNOLOGY:
156 return DT_RASPRINTER;
157 case HORZSIZE:
158 return muldiv(pdev->horzSize, 100, pdev->Devmode->dmPublic.dmScale);
159 case VERTSIZE:
160 return muldiv(pdev->vertSize, 100, pdev->Devmode->dmPublic.dmScale);
161 case HORZRES:
162 return pdev->horzRes;
163 case VERTRES:
164 return pdev->vertRes;
165 case BITSPIXEL:
166 /* Although Windows returns 1 for monochrome printers, we want
167 CreateCompatibleBitmap to provide something other than 1 bpp */
168 return 32;
169 case NUMPENS:
170 return 10;
171 case NUMFONTS:
172 return 39;
173 case NUMCOLORS:
174 return -1;
175 case PDEVICESIZE:
176 return sizeof(PSDRV_PDEVICE);
177 case TEXTCAPS:
178 return TC_CR_ANY | TC_VA_ABLE; /* psdrv 0x59f7 */
179 case RASTERCAPS:
180 return (RC_BITBLT | RC_BITMAP64 | RC_GDI20_OUTPUT | RC_DIBTODEV |
181 RC_STRETCHBLT | RC_STRETCHDIB); /* psdrv 0x6e99 */
182 case ASPECTX:
183 return pdev->logPixelsX;
184 case ASPECTY:
185 return pdev->logPixelsY;
186 case LOGPIXELSX:
187 return muldiv(pdev->logPixelsX, pdev->Devmode->dmPublic.dmScale, 100);
188 case LOGPIXELSY:
189 return muldiv(pdev->logPixelsY, pdev->Devmode->dmPublic.dmScale, 100);
190 case NUMRESERVED:
191 return 0;
192 case COLORRES:
193 return 0;
194 case PHYSICALWIDTH:
195 return (pdev->Devmode->dmPublic.dmOrientation == DMORIENT_LANDSCAPE) ?
196 pdev->PageSize.cy : pdev->PageSize.cx;
197 case PHYSICALHEIGHT:
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;
205 else
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;
215 else
216 return pdev->ImageableArea.left;
218 return pdev->PageSize.cy - pdev->ImageableArea.top;
220 default:
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)
233 INPUTSLOT *slot;
235 LIST_FOR_EACH_ENTRY(slot, &ppd->InputSlots, INPUTSLOT, entry)
236 if (slot->WinBin == dm->dmPublic.dmDefaultSource)
237 return slot;
239 return NULL;
242 static PAGESIZE *unix_find_pagesize(PPD *ppd, const PSDRV_DEVMODE *dm)
244 PAGESIZE *page;
246 LIST_FOR_EACH_ENTRY(page, &ppd->PageSizes, PAGESIZE, entry)
247 if (page->WinPage == dm->dmPublic.dmPaperSize)
248 return page;
250 return NULL;
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 ?
263 "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);
273 if (page)
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;
289 else
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
308 this case */
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);
330 if (slot)
332 dm1->dmPublic.dmDefaultSource = dm2->dmPublic.dmDefaultSource;
333 TRACE("Changing bin to '%s'\n", slot->FullName);
335 else
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;
388 RESOLUTION *res;
389 PAGESIZE *page;
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;
410 break;
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;
421 else
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)
431 break;
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;
449 } else {
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;
464 } else {
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;
481 } else {
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);
500 if (devmode)
502 merge_devmodes(pdev->Devmode, (const PSDRV_DEVMODE *)devmode, pdev->pi);
503 update_dev_caps(pdev);
505 return TRUE;
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);
514 switch (escape)
516 case QUERYESCSUPPORT:
517 if (input_size < sizeof(SHORT))
519 WARN("input_size < sizeof(SHORT) (=%d) for QUERYESCSUPPORT\n", input_size);
520 return 0;
522 else
524 DWORD num = (input_size < sizeof(DWORD)) ? *(const USHORT *)input : *(const DWORD *)input;
525 TRACE("QUERYESCSUPPORT for %d\n", (int)num);
527 switch (num)
529 case NEXTBAND:
530 /*case BANDINFO:*/
531 case SETCOPYCOUNT:
532 case GETTECHNOLOGY:
533 case SETLINECAP:
534 case SETLINEJOIN:
535 case SETMITERLIMIT:
536 case SETCHARSET:
537 case EXT_DEVICE_CAPS:
538 case SET_BOUNDS:
539 case EPSPRINTING:
540 case POSTSCRIPT_DATA:
541 case PASSTHROUGH:
542 case POSTSCRIPT_PASSTHROUGH:
543 case POSTSCRIPT_IGNORE:
544 case BEGIN_PATH:
545 case CLIP_TO_PATH:
546 case END_PATH:
547 /*case DRAWPATTERNRECT:*/
549 /* PageMaker checks for it */
550 case DOWNLOADHEADER:
552 /* PageMaker doesn't check for DOWNLOADFACE and GETFACENAME but
553 * uses them, they are supposed to be supported by any PS printer.
555 case DOWNLOADFACE:
557 /* PageMaker checks for these as a part of process of detecting
558 * a "fully compatible" PS printer, but doesn't actually use them.
560 case OPENCHANNEL:
561 case CLOSECHANNEL:
562 return TRUE;
564 /* Windows PS driver reports 0, but still supports this escape */
565 case GETFACENAME:
566 return FALSE; /* suppress the FIXME below */
568 default:
569 FIXME("QUERYESCSUPPORT(%d) - not supported.\n", (int)num);
570 return FALSE;
574 case OPENCHANNEL:
575 FIXME("OPENCHANNEL: stub\n");
576 return 1;
578 case CLOSECHANNEL:
579 FIXME("CLOSECHANNEL: stub\n");
580 return 1;
582 case DOWNLOADHEADER:
583 FIXME("DOWNLOADHEADER: stub\n");
584 /* should return name of the downloaded procset */
585 *(char *)output = 0;
586 return 1;
588 case GETFACENAME:
589 FIXME("GETFACENAME: stub\n");
590 lstrcpynA(output, "Courier", output_size);
591 return 1;
593 case DOWNLOADFACE:
594 FIXME("DOWNLOADFACE: stub\n");
595 return 1;
597 case MFCOMMENT:
599 FIXME("MFCOMMENT(%p, %d)\n", input, input_size);
600 return 1;
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);
610 return 1;
612 case BANDINFO:
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));
619 *obi = *ibi;
620 return 1;
623 case SETCOPYCOUNT:
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);
630 return 0;
632 TRACE("SETCOPYCOUNT %d\n", *NumCopies);
633 *ActualCopies = 1;
634 return 1;
637 case GETTECHNOLOGY:
639 LPSTR p = output;
640 strcpy(p, "PostScript");
641 *(p + strlen(p) + 1) = '\0'; /* 2 '\0's at end of string */
642 return 1;
645 case SETLINECAP:
647 INT newCap = *(const INT *)input;
648 if (input_size != sizeof(INT))
650 WARN("input_size != sizeof(INT) (=%d) for SETLINECAP\n", input_size);
651 return 0;
653 TRACE("SETLINECAP %d\n", newCap);
654 return 0;
657 case SETLINEJOIN:
659 INT newJoin = *(const INT *)input;
660 if (input_size != sizeof(INT))
662 WARN("input_size != sizeof(INT) (=%d) for SETLINEJOIN\n", input_size);
663 return 0;
665 TRACE("SETLINEJOIN %d\n", newJoin);
666 return 0;
669 case SETMITERLIMIT:
671 INT newLimit = *(const INT *)input;
672 if (input_size != sizeof(INT))
674 WARN("input_size != sizeof(INT) (=%d) for SETMITERLIMIT\n", input_size);
675 return 0;
677 TRACE("SETMITERLIMIT %d\n", newLimit);
678 return 0;
681 case SETCHARSET:
682 /* Undocumented escape used by winword6.
683 Switches between ANSI and a special charset.
684 If *lpInData == 1 we require that
685 0x91 is quoteleft
686 0x92 is quoteright
687 0x93 is quotedblleft
688 0x94 is quotedblright
689 0x95 is bullet
690 0x96 is endash
691 0x97 is emdash
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...
698 return 1;
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);
706 return 0;
708 TRACE("EXT_DEVICE_CAPS %d\n", cap);
709 return 0;
712 case SET_BOUNDS:
714 const RECT *r = input;
715 if (input_size != sizeof(RECT))
717 WARN("input_size != sizeof(RECT) (=%d) for SET_BOUNDS\n", input_size);
718 return 0;
720 TRACE("SET_BOUNDS %s\n", wine_dbgstr_rect(r));
721 return 0;
724 case EPSPRINTING:
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
729 * for now.
731 TRACE("EPS Printing support %sable.\n",epsprint?"en":"dis");
732 return 1;
735 case POSTSCRIPT_DATA:
736 case PASSTHROUGH:
737 case POSTSCRIPT_PASSTHROUGH:
738 return 1;
740 case POSTSCRIPT_IGNORE:
741 return 1;
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);
750 return 1;
752 case BEGIN_PATH:
753 return 1;
755 case END_PATH:
756 return 1;
758 case CLIP_TO_PATH:
759 return 1;
760 default:
761 FIXME("Unimplemented code %d\n", escape);
762 return 0;
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;
773 return TRUE;
776 const unixlib_entry_t __wine_unix_call_funcs[] =
778 init_dc,
781 C_ASSERT(ARRAYSIZE(__wine_unix_call_funcs) == unix_funcs_count);