Changes in crossover-wine-src-6.1.0 except for configure
[wine/hacks.git] / dlls / wineps.drv / escape.c
blob3e5de7f5ab44a7a0362710da3fc47887af5d60a4
1 /*
2 * PostScript driver Escape function
4 * Copyright 1998 Huw D M Davies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <stdarg.h>
22 #include "windef.h"
23 #include "winbase.h"
24 #include "wingdi.h"
25 #include "wine/wingdi16.h"
26 #include "wine/winuser16.h"
27 #include "wownt32.h"
28 #include "psdrv.h"
29 #include "wine/debug.h"
30 #include "winspool.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
34 static const char psbegindocument[] =
35 "%%BeginDocument: Wine passthrough\n";
37 /**********************************************************************
38 * ExtEscape (WINEPS.@)
40 INT PSDRV_ExtEscape( PSDRV_PDEVICE *physDev, INT nEscape, INT cbInput, LPCVOID in_data,
41 INT cbOutput, LPVOID out_data )
43 switch(nEscape)
45 case QUERYESCSUPPORT:
46 if(cbInput < sizeof(INT))
48 WARN("cbInput < sizeof(INT) (=%d) for QUERYESCSUPPORT\n", cbInput);
49 return 0;
50 } else {
51 UINT num = *(const UINT *)in_data;
52 TRACE("QUERYESCSUPPORT for %d\n", num);
54 switch(num) {
55 case NEXTBAND:
56 /*case BANDINFO:*/
57 case SETCOPYCOUNT:
58 case GETTECHNOLOGY:
59 case SETLINECAP:
60 case SETLINEJOIN:
61 case SETMITERLIMIT:
62 case SETCHARSET:
63 case EXT_DEVICE_CAPS:
64 case SET_BOUNDS:
65 case EPSPRINTING:
66 case POSTSCRIPT_DATA:
67 case PASSTHROUGH:
68 case POSTSCRIPT_PASSTHROUGH:
69 case POSTSCRIPT_IGNORE:
70 case BEGIN_PATH:
71 case CLIP_TO_PATH:
72 case END_PATH:
73 /*case DRAWPATTERNRECT:*/
74 return TRUE;
76 default:
77 FIXME("QUERYESCSUPPORT(%d) - not supported.\n", num);
78 return FALSE;
82 case MFCOMMENT:
84 FIXME("MFCOMMENT(%p, %d)\n", in_data, cbInput);
85 return 1;
87 case DRAWPATTERNRECT:
89 DRAWPATRECT *dpr = (DRAWPATRECT*)in_data;
91 FIXME("DRAWPATTERNRECT(pos (%d,%d), size %dx%d, style %d, pattern %x), stub!\n",
92 dpr->ptPosition.x, dpr->ptPosition.y,
93 dpr->ptSize.x, dpr->ptSize.y,
94 dpr->wStyle, dpr->wPattern
96 return 1;
98 case BANDINFO:
100 BANDINFOSTRUCT *ibi = (BANDINFOSTRUCT*)in_data;
101 BANDINFOSTRUCT *obi = (BANDINFOSTRUCT*)out_data;
103 FIXME("BANDINFO(graphics %d, text %d, rect [%dx%d-%dx%d]), stub!\n",
104 ibi->GraphicsFlag,
105 ibi->TextFlag,
106 ibi->GraphicsRect.top,
107 ibi->GraphicsRect.bottom,
108 ibi->GraphicsRect.left,
109 ibi->GraphicsRect.right
111 memcpy (obi, ibi, sizeof(*ibi));
112 return 1;
114 case NEXTBAND:
116 RECT *r = out_data;
117 if(!physDev->job.banding) {
118 physDev->job.banding = TRUE;
119 r->left = 0;
120 r->top = 0;
121 r->right = physDev->horzRes;
122 r->bottom = physDev->vertRes;
123 TRACE("NEXTBAND returning %d,%d - %d,%d\n", r->left, r->top, r->right, r->bottom );
124 return 1;
126 r->left = 0;
127 r->top = 0;
128 r->right = 0;
129 r->bottom = 0;
130 TRACE("NEXTBAND rect to 0,0 - 0,0\n" );
131 physDev->job.banding = FALSE;
132 return EndPage( physDev->hdc );
135 case SETCOPYCOUNT:
137 const INT *NumCopies = in_data;
138 INT *ActualCopies = out_data;
139 if(cbInput != sizeof(INT)) {
140 WARN("cbInput != sizeof(INT) (=%d) for SETCOPYCOUNT\n", cbInput);
141 return 0;
143 TRACE("SETCOPYCOUNT %d\n", *NumCopies);
144 *ActualCopies = 1;
145 return 1;
148 case GETTECHNOLOGY:
150 LPSTR p = out_data;
151 strcpy(p, "PostScript");
152 *(p + strlen(p) + 1) = '\0'; /* 2 '\0's at end of string */
153 return 1;
156 case SETLINECAP:
158 INT newCap = *(const INT *)in_data;
159 if(cbInput != sizeof(INT)) {
160 WARN("cbInput != sizeof(INT) (=%d) for SETLINECAP\n", cbInput);
161 return 0;
163 TRACE("SETLINECAP %d\n", newCap);
164 return 0;
167 case SETLINEJOIN:
169 INT newJoin = *(const INT *)in_data;
170 if(cbInput != sizeof(INT)) {
171 WARN("cbInput != sizeof(INT) (=%d) for SETLINEJOIN\n", cbInput);
172 return 0;
174 TRACE("SETLINEJOIN %d\n", newJoin);
175 return 0;
178 case SETMITERLIMIT:
180 INT newLimit = *(const INT *)in_data;
181 if(cbInput != sizeof(INT)) {
182 WARN("cbInput != sizeof(INT) (=%d) for SETMITERLIMIT\n", cbInput);
183 return 0;
185 TRACE("SETMITERLIMIT %d\n", newLimit);
186 return 0;
189 case SETCHARSET:
190 /* Undocumented escape used by winword6.
191 Switches between ANSI and a special charset.
192 If *lpInData == 1 we require that
193 0x91 is quoteleft
194 0x92 is quoteright
195 0x93 is quotedblleft
196 0x94 is quotedblright
197 0x95 is bullet
198 0x96 is endash
199 0x97 is emdash
200 0xa0 is non break space - yeah right.
202 If *lpInData == 0 we get ANSI.
203 Since there's nothing else there, let's just make these the default
204 anyway and see what happens...
206 return 1;
208 case EXT_DEVICE_CAPS:
210 UINT cap = *(const UINT *)in_data;
211 if(cbInput != sizeof(UINT)) {
212 WARN("cbInput != sizeof(UINT) (=%d) for EXT_DEVICE_CAPS\n", cbInput);
213 return 0;
215 TRACE("EXT_DEVICE_CAPS %d\n", cap);
216 return 0;
219 case SET_BOUNDS:
221 const RECT *r = in_data;
222 if(cbInput != sizeof(RECT)) {
223 WARN("cbInput != sizeof(RECT) (=%d) for SET_BOUNDS\n", cbInput);
224 return 0;
226 TRACE("SET_BOUNDS (%d,%d) - (%d,%d)\n", r->left, r->top,
227 r->right, r->bottom);
228 return 0;
231 case EPSPRINTING:
233 UINT epsprint = *(const UINT*)in_data;
234 /* FIXME: In this mode we do not need to send page intros and page
235 * ends according to the doc. But I just ignore that detail
236 * for now.
238 TRACE("EPS Printing support %sable.\n",epsprint?"en":"dis");
239 return 1;
242 case POSTSCRIPT_DATA:
243 case PASSTHROUGH:
244 case POSTSCRIPT_PASSTHROUGH:
246 /* Write directly to spool file, bypassing normal PS driver
247 * processing that is done along with writing PostScript code
248 * to the spool.
249 * We have a WORD before the data counting the size, but
250 * cbInput is just this +2.
251 * However Photoshop 7 has a bug that sets cbInput to 2 less than the
252 * length of the string, rather than 2 more. So we'll use the WORD at
253 * in_data[0] instead.
255 if(!physDev->job.in_passthrough) {
256 WriteSpool16(physDev->job.hJob, (LPSTR)psbegindocument, sizeof(psbegindocument)-1);
257 physDev->job.in_passthrough = TRUE;
259 return WriteSpool16(physDev->job.hJob,((char*)in_data)+2,*(const WORD*)in_data);
262 case POSTSCRIPT_IGNORE:
264 BOOL ret = physDev->job.quiet;
265 TRACE("POSTSCRIPT_IGNORE %d\n", *(const short*)in_data);
266 physDev->job.quiet = *(const short*)in_data;
267 return ret;
270 case GETSETPRINTORIENT:
272 /* If lpInData is present, it is a 20 byte structure, first 32
273 * bit LONG value is the orientation. if lpInData is NULL, it
274 * returns the current orientation.
276 FIXME("GETSETPRINTORIENT not implemented (data %p)!\n",in_data);
277 return 1;
279 case BEGIN_PATH:
280 TRACE("BEGIN_PATH\n");
281 if(physDev->pathdepth)
282 FIXME("Nested paths not yet handled\n");
283 return ++physDev->pathdepth;
285 case END_PATH:
287 const struct PATH_INFO *info = (const struct PATH_INFO*)in_data;
289 TRACE("END_PATH\n");
290 if(!physDev->pathdepth) {
291 ERR("END_PATH called without a BEIGN_PATH\n");
292 return -1;
294 TRACE("RenderMode = %d, FillMode = %d, BkMode = %d\n",
295 info->RenderMode, info->FillMode, info->BkMode);
296 switch(info->RenderMode) {
297 case RENDERMODE_NO_DISPLAY:
298 PSDRV_WriteClosePath(physDev); /* not sure if this is necessary, but it can't hurt */
299 break;
300 case RENDERMODE_OPEN:
301 case RENDERMODE_CLOSED:
302 default:
303 FIXME("END_PATH: RenderMode %d, not yet supported\n", info->RenderMode);
304 break;
306 return --physDev->pathdepth;
309 case CLIP_TO_PATH:
311 WORD mode = *(const WORD*)in_data;
313 switch(mode) {
314 case CLIP_SAVE:
315 TRACE("CLIP_TO_PATH: CLIP_SAVE\n");
316 PSDRV_WriteGSave(physDev);
317 return 1;
318 case CLIP_RESTORE:
319 TRACE("CLIP_TO_PATH: CLIP_RESTORE\n");
320 PSDRV_WriteGRestore(physDev);
321 return 1;
322 case CLIP_INCLUSIVE:
323 TRACE("CLIP_TO_PATH: CLIP_INCLUSIVE\n");
324 /* FIXME to clip or eoclip ? (see PATH_INFO.FillMode) */
325 PSDRV_WriteClip(physDev);
326 PSDRV_WriteNewPath(physDev);
327 return 1;
328 case CLIP_EXCLUSIVE:
329 FIXME("CLIP_EXCLUSIVE: not implemented\n");
330 return 0;
331 default:
332 FIXME("Unknown CLIP_TO_PATH mode %d\n", mode);
333 return 0;
336 default:
337 FIXME("Unimplemented code 0x%x\n", nEscape);
338 return 0;
342 /************************************************************************
343 * PSDRV_StartPage
345 INT PSDRV_StartPage( PSDRV_PDEVICE *physDev )
347 if(!physDev->job.OutOfPage) {
348 FIXME("Already started a page?\n");
349 return 1;
352 if(physDev->job.PageNo++ == 0) {
353 if(!PSDRV_WriteHeader( physDev, physDev->job.DocName ))
354 return 0;
357 if(!PSDRV_WriteNewPage( physDev ))
358 return 0;
359 physDev->job.OutOfPage = FALSE;
360 return 1;
364 /************************************************************************
365 * PSDRV_EndPage
367 INT PSDRV_EndPage( PSDRV_PDEVICE *physDev )
369 if(physDev->job.OutOfPage) {
370 FIXME("Already ended a page?\n");
371 return 1;
373 if(!PSDRV_WriteEndPage( physDev ))
374 return 0;
375 PSDRV_EmptyDownloadList(physDev, FALSE);
376 physDev->job.OutOfPage = TRUE;
377 return 1;
381 /************************************************************************
382 * PSDRV_StartDocA
384 static INT PSDRV_StartDocA( PSDRV_PDEVICE *physDev, const DOCINFOA *doc )
386 LPCSTR output = "LPT1:";
387 BYTE buf[300];
388 HANDLE hprn = INVALID_HANDLE_VALUE;
389 PRINTER_INFO_5A *pi5 = (PRINTER_INFO_5A*)buf;
390 DWORD needed;
392 if(physDev->job.hJob) {
393 FIXME("hJob != 0. Now what?\n");
394 return 0;
397 if(doc->lpszOutput)
398 output = doc->lpszOutput;
399 else if(physDev->job.output)
400 output = physDev->job.output;
401 else {
402 if(OpenPrinterA(physDev->pi->FriendlyName, &hprn, NULL) &&
403 GetPrinterA(hprn, 5, buf, sizeof(buf), &needed)) {
404 output = pi5->pPortName;
406 if(hprn != INVALID_HANDLE_VALUE)
407 ClosePrinter(hprn);
410 physDev->job.hJob = OpenJob16(output, doc->lpszDocName, HDC_16(physDev->hdc) );
411 if(!physDev->job.hJob) {
412 WARN("OpenJob failed\n");
413 return 0;
415 physDev->job.banding = FALSE;
416 physDev->job.OutOfPage = TRUE;
417 physDev->job.PageNo = 0;
418 physDev->job.quiet = FALSE;
419 physDev->job.in_passthrough = FALSE;
420 physDev->job.had_passthrough_rect = FALSE;
421 if(doc->lpszDocName) {
422 physDev->job.DocName = HeapAlloc(GetProcessHeap(), 0, strlen(doc->lpszDocName)+1);
423 strcpy(physDev->job.DocName, doc->lpszDocName);
424 } else
425 physDev->job.DocName = NULL;
427 return physDev->job.hJob;
430 /************************************************************************
431 * PSDRV_StartDoc
433 INT PSDRV_StartDoc( PSDRV_PDEVICE *physDev, const DOCINFOW *doc )
435 DOCINFOA docA;
436 INT ret, len;
437 LPSTR docname = NULL, output = NULL, datatype = NULL;
439 docA.cbSize = doc->cbSize;
440 if (doc->lpszDocName)
442 len = WideCharToMultiByte( CP_ACP, 0, doc->lpszDocName, -1, NULL, 0, NULL, NULL );
443 if ((docname = HeapAlloc( GetProcessHeap(), 0, len )))
444 WideCharToMultiByte( CP_ACP, 0, doc->lpszDocName, -1, docname, len, NULL, NULL );
446 if (doc->lpszOutput)
448 len = WideCharToMultiByte( CP_ACP, 0, doc->lpszOutput, -1, NULL, 0, NULL, NULL );
449 if ((output = HeapAlloc( GetProcessHeap(), 0, len )))
450 WideCharToMultiByte( CP_ACP, 0, doc->lpszOutput, -1, output, len, NULL, NULL );
452 if (doc->lpszDatatype)
454 len = WideCharToMultiByte( CP_ACP, 0, doc->lpszDatatype, -1, NULL, 0, NULL, NULL );
455 if ((datatype = HeapAlloc( GetProcessHeap(), 0, len )))
456 WideCharToMultiByte( CP_ACP, 0, doc->lpszDatatype, -1, datatype, len, NULL, NULL );
458 docA.lpszDocName = docname;
459 docA.lpszOutput = output;
460 docA.lpszDatatype = datatype;
461 docA.fwType = doc->fwType;
463 ret = PSDRV_StartDocA(physDev, &docA);
465 HeapFree( GetProcessHeap(), 0, docname );
466 HeapFree( GetProcessHeap(), 0, output );
467 HeapFree( GetProcessHeap(), 0, datatype );
469 return ret;
472 /************************************************************************
473 * PSDRV_EndDoc
475 INT PSDRV_EndDoc( PSDRV_PDEVICE *physDev )
477 INT ret = 1;
478 if(!physDev->job.hJob) {
479 FIXME("hJob == 0. Now what?\n");
480 return 0;
483 if(!physDev->job.OutOfPage) {
484 WARN("Somebody forgot an EndPage\n");
485 PSDRV_EndPage( physDev );
487 PSDRV_WriteFooter( physDev );
489 if( CloseJob16( physDev->job.hJob ) == SP_ERROR ) {
490 WARN("CloseJob error\n");
491 ret = 0;
493 physDev->job.hJob = 0;
494 HeapFree(GetProcessHeap(), 0, physDev->job.DocName);
495 physDev->job.DocName = NULL;
497 return ret;