msvcrt/tests: Remove a space before a '\n'.
[wine/gsoc-2012-control.git] / dlls / wineps.drv / escape.c
blobb3974615e1f1c0f828472064ae01e88914782cd2
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 "wownt32.h"
27 #include "psdrv.h"
28 #include "wine/debug.h"
29 #include "winspool.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
33 static const char psbegindocument[] =
34 "%%BeginDocument: Wine passthrough\n";
36 /**********************************************************************
37 * ExtEscape (WINEPS.@)
39 INT PSDRV_ExtEscape( PSDRV_PDEVICE *physDev, INT nEscape, INT cbInput, LPCVOID in_data,
40 INT cbOutput, LPVOID out_data )
42 switch(nEscape)
44 case QUERYESCSUPPORT:
45 if(cbInput < sizeof(INT))
47 WARN("cbInput < sizeof(INT) (=%d) for QUERYESCSUPPORT\n", cbInput);
48 return 0;
49 } else {
50 UINT num = *(const UINT *)in_data;
51 TRACE("QUERYESCSUPPORT for %d\n", num);
53 switch(num) {
54 case NEXTBAND:
55 /*case BANDINFO:*/
56 case SETCOPYCOUNT:
57 case GETTECHNOLOGY:
58 case SETLINECAP:
59 case SETLINEJOIN:
60 case SETMITERLIMIT:
61 case SETCHARSET:
62 case EXT_DEVICE_CAPS:
63 case SET_BOUNDS:
64 case EPSPRINTING:
65 case POSTSCRIPT_DATA:
66 case PASSTHROUGH:
67 case POSTSCRIPT_PASSTHROUGH:
68 case POSTSCRIPT_IGNORE:
69 case BEGIN_PATH:
70 case CLIP_TO_PATH:
71 case END_PATH:
72 /*case DRAWPATTERNRECT:*/
73 return TRUE;
75 default:
76 FIXME("QUERYESCSUPPORT(%d) - not supported.\n", num);
77 return FALSE;
81 case MFCOMMENT:
83 FIXME("MFCOMMENT(%p, %d)\n", in_data, cbInput);
84 return 1;
86 case DRAWPATTERNRECT:
88 DRAWPATRECT *dpr = (DRAWPATRECT*)in_data;
90 FIXME("DRAWPATTERNRECT(pos (%d,%d), size %dx%d, style %d, pattern %x), stub!\n",
91 dpr->ptPosition.x, dpr->ptPosition.y,
92 dpr->ptSize.x, dpr->ptSize.y,
93 dpr->wStyle, dpr->wPattern
95 return 1;
97 case BANDINFO:
99 BANDINFOSTRUCT *ibi = (BANDINFOSTRUCT*)in_data;
100 BANDINFOSTRUCT *obi = (BANDINFOSTRUCT*)out_data;
102 FIXME("BANDINFO(graphics %d, text %d, rect [%dx%d-%dx%d]), stub!\n",
103 ibi->GraphicsFlag,
104 ibi->TextFlag,
105 ibi->GraphicsRect.top,
106 ibi->GraphicsRect.bottom,
107 ibi->GraphicsRect.left,
108 ibi->GraphicsRect.right
110 *obi = *ibi;
111 return 1;
113 case NEXTBAND:
115 RECT *r = out_data;
116 if(!physDev->job.banding) {
117 physDev->job.banding = TRUE;
118 r->left = 0;
119 r->top = 0;
120 r->right = physDev->horzRes;
121 r->bottom = physDev->vertRes;
122 TRACE("NEXTBAND returning %d,%d - %d,%d\n", r->left, r->top, r->right, r->bottom );
123 return 1;
125 r->left = 0;
126 r->top = 0;
127 r->right = 0;
128 r->bottom = 0;
129 TRACE("NEXTBAND rect to 0,0 - 0,0\n" );
130 physDev->job.banding = FALSE;
131 return EndPage( physDev->hdc );
134 case SETCOPYCOUNT:
136 const INT *NumCopies = in_data;
137 INT *ActualCopies = out_data;
138 if(cbInput != sizeof(INT)) {
139 WARN("cbInput != sizeof(INT) (=%d) for SETCOPYCOUNT\n", cbInput);
140 return 0;
142 TRACE("SETCOPYCOUNT %d\n", *NumCopies);
143 *ActualCopies = 1;
144 return 1;
147 case GETTECHNOLOGY:
149 LPSTR p = out_data;
150 strcpy(p, "PostScript");
151 *(p + strlen(p) + 1) = '\0'; /* 2 '\0's at end of string */
152 return 1;
155 case SETLINECAP:
157 INT newCap = *(const INT *)in_data;
158 if(cbInput != sizeof(INT)) {
159 WARN("cbInput != sizeof(INT) (=%d) for SETLINECAP\n", cbInput);
160 return 0;
162 TRACE("SETLINECAP %d\n", newCap);
163 return 0;
166 case SETLINEJOIN:
168 INT newJoin = *(const INT *)in_data;
169 if(cbInput != sizeof(INT)) {
170 WARN("cbInput != sizeof(INT) (=%d) for SETLINEJOIN\n", cbInput);
171 return 0;
173 TRACE("SETLINEJOIN %d\n", newJoin);
174 return 0;
177 case SETMITERLIMIT:
179 INT newLimit = *(const INT *)in_data;
180 if(cbInput != sizeof(INT)) {
181 WARN("cbInput != sizeof(INT) (=%d) for SETMITERLIMIT\n", cbInput);
182 return 0;
184 TRACE("SETMITERLIMIT %d\n", newLimit);
185 return 0;
188 case SETCHARSET:
189 /* Undocumented escape used by winword6.
190 Switches between ANSI and a special charset.
191 If *lpInData == 1 we require that
192 0x91 is quoteleft
193 0x92 is quoteright
194 0x93 is quotedblleft
195 0x94 is quotedblright
196 0x95 is bullet
197 0x96 is endash
198 0x97 is emdash
199 0xa0 is non break space - yeah right.
201 If *lpInData == 0 we get ANSI.
202 Since there's nothing else there, let's just make these the default
203 anyway and see what happens...
205 return 1;
207 case EXT_DEVICE_CAPS:
209 UINT cap = *(const UINT *)in_data;
210 if(cbInput != sizeof(UINT)) {
211 WARN("cbInput != sizeof(UINT) (=%d) for EXT_DEVICE_CAPS\n", cbInput);
212 return 0;
214 TRACE("EXT_DEVICE_CAPS %d\n", cap);
215 return 0;
218 case SET_BOUNDS:
220 const RECT *r = in_data;
221 if(cbInput != sizeof(RECT)) {
222 WARN("cbInput != sizeof(RECT) (=%d) for SET_BOUNDS\n", cbInput);
223 return 0;
225 TRACE("SET_BOUNDS (%d,%d) - (%d,%d)\n", r->left, r->top,
226 r->right, r->bottom);
227 return 0;
230 case EPSPRINTING:
232 UINT epsprint = *(const UINT*)in_data;
233 /* FIXME: In this mode we do not need to send page intros and page
234 * ends according to the doc. But I just ignore that detail
235 * for now.
237 TRACE("EPS Printing support %sable.\n",epsprint?"en":"dis");
238 return 1;
241 case POSTSCRIPT_DATA:
242 case PASSTHROUGH:
243 case POSTSCRIPT_PASSTHROUGH:
245 /* Write directly to spool file, bypassing normal PS driver
246 * processing that is done along with writing PostScript code
247 * to the spool.
248 * We have a WORD before the data counting the size, but
249 * cbInput is just this +2.
250 * However Photoshop 7 has a bug that sets cbInput to 2 less than the
251 * length of the string, rather than 2 more. So we'll use the WORD at
252 * in_data[0] instead.
254 if(!physDev->job.in_passthrough) {
255 WriteSpool16(physDev->job.hJob, (LPSTR)psbegindocument, sizeof(psbegindocument)-1);
256 physDev->job.in_passthrough = TRUE;
258 return WriteSpool16(physDev->job.hJob,((char*)in_data)+2,*(const WORD*)in_data);
261 case POSTSCRIPT_IGNORE:
263 BOOL ret = physDev->job.quiet;
264 TRACE("POSTSCRIPT_IGNORE %d\n", *(const short*)in_data);
265 physDev->job.quiet = *(const short*)in_data;
266 return ret;
269 case GETSETPRINTORIENT:
271 /* If lpInData is present, it is a 20 byte structure, first 32
272 * bit LONG value is the orientation. if lpInData is NULL, it
273 * returns the current orientation.
275 FIXME("GETSETPRINTORIENT not implemented (data %p)!\n",in_data);
276 return 1;
278 case BEGIN_PATH:
279 TRACE("BEGIN_PATH\n");
280 if(physDev->pathdepth)
281 FIXME("Nested paths not yet handled\n");
282 return ++physDev->pathdepth;
284 case END_PATH:
286 const struct PATH_INFO *info = (const struct PATH_INFO*)in_data;
288 TRACE("END_PATH\n");
289 if(!physDev->pathdepth) {
290 ERR("END_PATH called without a BEIGN_PATH\n");
291 return -1;
293 TRACE("RenderMode = %d, FillMode = %d, BkMode = %d\n",
294 info->RenderMode, info->FillMode, info->BkMode);
295 switch(info->RenderMode) {
296 case RENDERMODE_NO_DISPLAY:
297 PSDRV_WriteClosePath(physDev); /* not sure if this is necessary, but it can't hurt */
298 break;
299 case RENDERMODE_OPEN:
300 case RENDERMODE_CLOSED:
301 default:
302 FIXME("END_PATH: RenderMode %d, not yet supported\n", info->RenderMode);
303 break;
305 return --physDev->pathdepth;
308 case CLIP_TO_PATH:
310 WORD mode = *(const WORD*)in_data;
312 switch(mode) {
313 case CLIP_SAVE:
314 TRACE("CLIP_TO_PATH: CLIP_SAVE\n");
315 PSDRV_WriteGSave(physDev);
316 return 1;
317 case CLIP_RESTORE:
318 TRACE("CLIP_TO_PATH: CLIP_RESTORE\n");
319 PSDRV_WriteGRestore(physDev);
320 return 1;
321 case CLIP_INCLUSIVE:
322 TRACE("CLIP_TO_PATH: CLIP_INCLUSIVE\n");
323 /* FIXME to clip or eoclip ? (see PATH_INFO.FillMode) */
324 PSDRV_WriteClip(physDev);
325 PSDRV_WriteNewPath(physDev);
326 return 1;
327 case CLIP_EXCLUSIVE:
328 FIXME("CLIP_EXCLUSIVE: not implemented\n");
329 return 0;
330 default:
331 FIXME("Unknown CLIP_TO_PATH mode %d\n", mode);
332 return 0;
335 default:
336 FIXME("Unimplemented code 0x%x\n", nEscape);
337 return 0;
341 /************************************************************************
342 * PSDRV_StartPage
344 INT PSDRV_StartPage( PSDRV_PDEVICE *physDev )
346 if(!physDev->job.OutOfPage) {
347 FIXME("Already started a page?\n");
348 return 1;
351 if(physDev->job.PageNo++ == 0) {
352 if(!PSDRV_WriteHeader( physDev, physDev->job.DocName ))
353 return 0;
356 if(!PSDRV_WriteNewPage( physDev ))
357 return 0;
358 physDev->job.OutOfPage = FALSE;
359 return 1;
363 /************************************************************************
364 * PSDRV_EndPage
366 INT PSDRV_EndPage( PSDRV_PDEVICE *physDev )
368 if(physDev->job.OutOfPage) {
369 FIXME("Already ended a page?\n");
370 return 1;
372 if(!PSDRV_WriteEndPage( physDev ))
373 return 0;
374 PSDRV_EmptyDownloadList(physDev, FALSE);
375 physDev->job.OutOfPage = TRUE;
376 return 1;
380 /************************************************************************
381 * PSDRV_StartDocA
383 static INT PSDRV_StartDocA( PSDRV_PDEVICE *physDev, const DOCINFOA *doc )
385 LPCSTR output = "LPT1:";
386 BYTE buf[300];
387 HANDLE hprn = INVALID_HANDLE_VALUE;
388 PRINTER_INFO_5A *pi5 = (PRINTER_INFO_5A*)buf;
389 DWORD needed;
391 if(physDev->job.hJob) {
392 FIXME("hJob != 0. Now what?\n");
393 return 0;
396 if(doc->lpszOutput)
397 output = doc->lpszOutput;
398 else if(physDev->job.output)
399 output = physDev->job.output;
400 else {
401 if(OpenPrinterA(physDev->pi->FriendlyName, &hprn, NULL) &&
402 GetPrinterA(hprn, 5, buf, sizeof(buf), &needed)) {
403 output = pi5->pPortName;
405 if(hprn != INVALID_HANDLE_VALUE)
406 ClosePrinter(hprn);
409 physDev->job.hJob = OpenJob16(output, doc->lpszDocName, HDC_16(physDev->hdc) );
410 if(!physDev->job.hJob) {
411 WARN("OpenJob failed\n");
412 return 0;
414 physDev->job.banding = FALSE;
415 physDev->job.OutOfPage = TRUE;
416 physDev->job.PageNo = 0;
417 physDev->job.quiet = FALSE;
418 physDev->job.in_passthrough = FALSE;
419 physDev->job.had_passthrough_rect = FALSE;
420 if(doc->lpszDocName) {
421 physDev->job.DocName = HeapAlloc(GetProcessHeap(), 0, strlen(doc->lpszDocName)+1);
422 strcpy(physDev->job.DocName, doc->lpszDocName);
423 } else
424 physDev->job.DocName = NULL;
426 return physDev->job.hJob;
429 /************************************************************************
430 * PSDRV_StartDoc
432 INT PSDRV_StartDoc( PSDRV_PDEVICE *physDev, const DOCINFOW *doc )
434 DOCINFOA docA;
435 INT ret, len;
436 LPSTR docname = NULL, output = NULL, datatype = NULL;
438 docA.cbSize = doc->cbSize;
439 if (doc->lpszDocName)
441 len = WideCharToMultiByte( CP_ACP, 0, doc->lpszDocName, -1, NULL, 0, NULL, NULL );
442 if ((docname = HeapAlloc( GetProcessHeap(), 0, len )))
443 WideCharToMultiByte( CP_ACP, 0, doc->lpszDocName, -1, docname, len, NULL, NULL );
445 if (doc->lpszOutput)
447 len = WideCharToMultiByte( CP_ACP, 0, doc->lpszOutput, -1, NULL, 0, NULL, NULL );
448 if ((output = HeapAlloc( GetProcessHeap(), 0, len )))
449 WideCharToMultiByte( CP_ACP, 0, doc->lpszOutput, -1, output, len, NULL, NULL );
451 if (doc->lpszDatatype)
453 len = WideCharToMultiByte( CP_ACP, 0, doc->lpszDatatype, -1, NULL, 0, NULL, NULL );
454 if ((datatype = HeapAlloc( GetProcessHeap(), 0, len )))
455 WideCharToMultiByte( CP_ACP, 0, doc->lpszDatatype, -1, datatype, len, NULL, NULL );
457 docA.lpszDocName = docname;
458 docA.lpszOutput = output;
459 docA.lpszDatatype = datatype;
460 docA.fwType = doc->fwType;
462 ret = PSDRV_StartDocA(physDev, &docA);
464 HeapFree( GetProcessHeap(), 0, docname );
465 HeapFree( GetProcessHeap(), 0, output );
466 HeapFree( GetProcessHeap(), 0, datatype );
468 return ret;
471 /************************************************************************
472 * PSDRV_EndDoc
474 INT PSDRV_EndDoc( PSDRV_PDEVICE *physDev )
476 INT ret = 1;
477 if(!physDev->job.hJob) {
478 FIXME("hJob == 0. Now what?\n");
479 return 0;
482 if(!physDev->job.OutOfPage) {
483 WARN("Somebody forgot an EndPage\n");
484 PSDRV_EndPage( physDev );
486 PSDRV_WriteFooter( physDev );
488 if( CloseJob16( physDev->job.hJob ) == SP_ERROR ) {
489 WARN("CloseJob error\n");
490 ret = 0;
492 physDev->job.hJob = 0;
493 HeapFree(GetProcessHeap(), 0, physDev->job.DocName);
494 physDev->job.DocName = NULL;
496 return ret;