ole32: Create moniker enumerator with an initial reference count.
[wine/multimedia.git] / dlls / wineps / escape.c
blobd7627c37fdc18ec995591c4b47400202ea17d5bb
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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"
31 #include "heap.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
35 static const char psbegindocument[] =
36 "%%BeginDocument: Wine passthrough\n";
38 /**********************************************************************
39 * ExtEscape (WINEPS.@)
41 INT PSDRV_ExtEscape( PSDRV_PDEVICE *physDev, INT nEscape, INT cbInput, LPCVOID in_data,
42 INT cbOutput, LPVOID out_data )
44 switch(nEscape)
46 case QUERYESCSUPPORT:
47 if(cbInput < sizeof(INT))
49 WARN("cbInput < sizeof(INT) (=%d) for QUERYESCSUPPORT\n", cbInput);
50 return 0;
51 } else {
52 UINT num = *(const UINT *)in_data;
53 TRACE("QUERYESCSUPPORT for %d\n", num);
55 switch(num) {
56 case NEXTBAND:
57 /*case BANDINFO:*/
58 case SETCOPYCOUNT:
59 case GETTECHNOLOGY:
60 case SETLINECAP:
61 case SETLINEJOIN:
62 case SETMITERLIMIT:
63 case SETCHARSET:
64 case EXT_DEVICE_CAPS:
65 case SET_BOUNDS:
66 case EPSPRINTING:
67 case POSTSCRIPT_DATA:
68 case PASSTHROUGH:
69 case POSTSCRIPT_PASSTHROUGH:
70 case POSTSCRIPT_IGNORE:
71 case BEGIN_PATH:
72 case CLIP_TO_PATH:
73 case END_PATH:
74 /*case DRAWPATTERNRECT:*/
75 return TRUE;
77 default:
78 FIXME("QUERYESCSUPPORT(%d) - not supported.\n", num);
79 return FALSE;
83 case MFCOMMENT:
85 FIXME("MFCOMMENT(%p, %d)\n", in_data, cbInput);
86 return 1;
88 case DRAWPATTERNRECT:
90 DRAWPATRECT *dpr = (DRAWPATRECT*)in_data;
92 FIXME("DRAWPATTERNRECT(pos (%ld,%ld), size %ldx%ld, style %d, pattern %x), stub!\n",
93 dpr->ptPosition.x, dpr->ptPosition.y,
94 dpr->ptSize.x, dpr->ptSize.y,
95 dpr->wStyle, dpr->wPattern
97 return 1;
99 case BANDINFO:
101 BANDINFOSTRUCT *ibi = (BANDINFOSTRUCT*)in_data;
102 BANDINFOSTRUCT *obi = (BANDINFOSTRUCT*)out_data;
104 FIXME("BANDINFO(graphics %d, text %d, rect [%ldx%ld-%ldx%ld]), stub!\n",
105 ibi->GraphicsFlag,
106 ibi->TextFlag,
107 ibi->GraphicsRect.top,
108 ibi->GraphicsRect.bottom,
109 ibi->GraphicsRect.left,
110 ibi->GraphicsRect.right
112 memcpy (obi, ibi, sizeof(*ibi));
113 return 1;
115 case NEXTBAND:
117 RECT *r = out_data;
118 if(!physDev->job.banding) {
119 physDev->job.banding = TRUE;
120 r->left = 0;
121 r->top = 0;
122 r->right = physDev->horzRes;
123 r->bottom = physDev->vertRes;
124 TRACE("NEXTBAND returning %ld,%ld - %ld,%ld\n", r->left, r->top, r->right, r->bottom );
125 return 1;
127 r->left = 0;
128 r->top = 0;
129 r->right = 0;
130 r->bottom = 0;
131 TRACE("NEXTBAND rect to 0,0 - 0,0\n" );
132 physDev->job.banding = FALSE;
133 return EndPage( physDev->hdc );
136 case SETCOPYCOUNT:
138 const INT *NumCopies = in_data;
139 INT *ActualCopies = out_data;
140 if(cbInput != sizeof(INT)) {
141 WARN("cbInput != sizeof(INT) (=%d) for SETCOPYCOUNT\n", cbInput);
142 return 0;
144 TRACE("SETCOPYCOUNT %d\n", *NumCopies);
145 *ActualCopies = 1;
146 return 1;
149 case GETTECHNOLOGY:
151 LPSTR p = out_data;
152 strcpy(p, "PostScript");
153 *(p + strlen(p) + 1) = '\0'; /* 2 '\0's at end of string */
154 return 1;
157 case SETLINECAP:
159 INT newCap = *(const INT *)in_data;
160 if(cbInput != sizeof(INT)) {
161 WARN("cbInput != sizeof(INT) (=%d) for SETLINECAP\n", cbInput);
162 return 0;
164 TRACE("SETLINECAP %d\n", newCap);
165 return 0;
168 case SETLINEJOIN:
170 INT newJoin = *(const INT *)in_data;
171 if(cbInput != sizeof(INT)) {
172 WARN("cbInput != sizeof(INT) (=%d) for SETLINEJOIN\n", cbInput);
173 return 0;
175 TRACE("SETLINEJOIN %d\n", newJoin);
176 return 0;
179 case SETMITERLIMIT:
181 INT newLimit = *(const INT *)in_data;
182 if(cbInput != sizeof(INT)) {
183 WARN("cbInput != sizeof(INT) (=%d) for SETMITERLIMIT\n", cbInput);
184 return 0;
186 TRACE("SETMITERLIMIT %d\n", newLimit);
187 return 0;
190 case SETCHARSET:
191 /* Undocumented escape used by winword6.
192 Switches between ANSI and a special charset.
193 If *lpInData == 1 we require that
194 0x91 is quoteleft
195 0x92 is quoteright
196 0x93 is quotedblleft
197 0x94 is quotedblright
198 0x95 is bullet
199 0x96 is endash
200 0x97 is emdash
201 0xa0 is non break space - yeah right.
203 If *lpInData == 0 we get ANSI.
204 Since there's nothing else there, let's just make these the default
205 anyway and see what happens...
207 return 1;
209 case EXT_DEVICE_CAPS:
211 UINT cap = *(const UINT *)in_data;
212 if(cbInput != sizeof(UINT)) {
213 WARN("cbInput != sizeof(UINT) (=%d) for EXT_DEVICE_CAPS\n", cbInput);
214 return 0;
216 TRACE("EXT_DEVICE_CAPS %d\n", cap);
217 return 0;
220 case SET_BOUNDS:
222 const RECT *r = in_data;
223 if(cbInput != sizeof(RECT)) {
224 WARN("cbInput != sizeof(RECT) (=%d) for SET_BOUNDS\n", cbInput);
225 return 0;
227 TRACE("SET_BOUNDS (%ld,%ld) - (%ld,%ld)\n", r->left, r->top,
228 r->right, r->bottom);
229 return 0;
232 case EPSPRINTING:
234 UINT epsprint = *(const UINT*)in_data;
235 /* FIXME: In this mode we do not need to send page intros and page
236 * ends according to the doc. But I just ignore that detail
237 * for now.
239 TRACE("EPS Printing support %sable.\n",epsprint?"en":"dis");
240 return 1;
243 case POSTSCRIPT_DATA:
244 case PASSTHROUGH:
245 case POSTSCRIPT_PASSTHROUGH:
247 /* Write directly to spool file, bypassing normal PS driver
248 * processing that is done along with writing PostScript code
249 * to the spool.
250 * We have a WORD before the data counting the size, but
251 * cbInput is just this +2.
252 * However Photoshop 7 has a bug that sets cbInput to 2 less than the
253 * length of the string, rather than 2 more. So we'll use the WORD at
254 * in_data[0] instead.
256 if(!physDev->job.in_passthrough) {
257 WriteSpool16(physDev->job.hJob, (LPSTR)psbegindocument, sizeof(psbegindocument)-1);
258 physDev->job.in_passthrough = TRUE;
260 return WriteSpool16(physDev->job.hJob,((char*)in_data)+2,*(const WORD*)in_data);
263 case POSTSCRIPT_IGNORE:
265 BOOL ret = physDev->job.quiet;
266 TRACE("POSTSCRIPT_IGNORE %d\n", *(const short*)in_data);
267 physDev->job.quiet = *(const short*)in_data;
268 return ret;
271 case GETSETPRINTORIENT:
273 /* If lpInData is present, it is a 20 byte structure, first 32
274 * bit LONG value is the orientation. if lpInData is NULL, it
275 * returns the current orientation.
277 FIXME("GETSETPRINTORIENT not implemented (data %p)!\n",in_data);
278 return 1;
280 case BEGIN_PATH:
281 TRACE("BEGIN_PATH\n");
282 if(physDev->pathdepth)
283 FIXME("Nested paths not yet handled\n");
284 return ++physDev->pathdepth;
286 case END_PATH:
288 const struct PATH_INFO *info = (const struct PATH_INFO*)in_data;
290 TRACE("END_PATH\n");
291 if(!physDev->pathdepth) {
292 ERR("END_PATH called without a BEIGN_PATH\n");
293 return -1;
295 TRACE("RenderMode = %d, FillMode = %d, BkMode = %d\n",
296 info->RenderMode, info->FillMode, info->BkMode);
297 switch(info->RenderMode) {
298 case RENDERMODE_NO_DISPLAY:
299 PSDRV_WriteClosePath(physDev); /* not sure if this is necessary, but it can't hurt */
300 break;
301 case RENDERMODE_OPEN:
302 case RENDERMODE_CLOSED:
303 default:
304 FIXME("END_PATH: RenderMode %d, not yet supported\n", info->RenderMode);
305 break;
307 return --physDev->pathdepth;
310 case CLIP_TO_PATH:
312 WORD mode = *(const WORD*)in_data;
314 switch(mode) {
315 case CLIP_SAVE:
316 TRACE("CLIP_TO_PATH: CLIP_SAVE\n");
317 PSDRV_WriteGSave(physDev);
318 return 1;
319 case CLIP_RESTORE:
320 TRACE("CLIP_TO_PATH: CLIP_RESTORE\n");
321 PSDRV_WriteGRestore(physDev);
322 return 1;
323 case CLIP_INCLUSIVE:
324 TRACE("CLIP_TO_PATH: CLIP_INCLUSIVE\n");
325 /* FIXME to clip or eoclip ? (see PATH_INFO.FillMode) */
326 PSDRV_WriteClip(physDev);
327 PSDRV_WriteNewPath(physDev);
328 return 1;
329 case CLIP_EXCLUSIVE:
330 FIXME("CLIP_EXCLUSIVE: not implemented\n");
331 return 0;
332 default:
333 FIXME("Unknown CLIP_TO_PATH mode %d\n", mode);
334 return 0;
337 default:
338 FIXME("Unimplemented code 0x%x\n", nEscape);
339 return 0;
343 /************************************************************************
344 * PSDRV_StartPage
346 INT PSDRV_StartPage( PSDRV_PDEVICE *physDev )
348 if(!physDev->job.OutOfPage) {
349 FIXME("Already started a page?\n");
350 return 1;
353 if(physDev->job.PageNo++ == 0) {
354 if(!PSDRV_WriteHeader( physDev, physDev->job.DocName ))
355 return 0;
358 if(!PSDRV_WriteNewPage( physDev ))
359 return 0;
360 physDev->job.OutOfPage = FALSE;
361 return 1;
365 /************************************************************************
366 * PSDRV_EndPage
368 INT PSDRV_EndPage( PSDRV_PDEVICE *physDev )
370 if(physDev->job.OutOfPage) {
371 FIXME("Already ended a page?\n");
372 return 1;
374 if(!PSDRV_WriteEndPage( physDev ))
375 return 0;
376 PSDRV_EmptyDownloadList(physDev, FALSE);
377 physDev->job.OutOfPage = TRUE;
378 return 1;
382 /************************************************************************
383 * PSDRV_StartDocA
385 INT PSDRV_StartDocA( PSDRV_PDEVICE *physDev, const DOCINFOA *doc )
387 LPCSTR output = "LPT1:";
388 BYTE buf[300];
389 HANDLE hprn = INVALID_HANDLE_VALUE;
390 PRINTER_INFO_5A *pi5 = (PRINTER_INFO_5A*)buf;
391 DWORD needed;
393 if(physDev->job.hJob) {
394 FIXME("hJob != 0. Now what?\n");
395 return 0;
398 if(doc->lpszOutput)
399 output = doc->lpszOutput;
400 else if(physDev->job.output)
401 output = physDev->job.output;
402 else {
403 if(OpenPrinterA(physDev->pi->FriendlyName, &hprn, NULL) &&
404 GetPrinterA(hprn, 5, buf, sizeof(buf), &needed)) {
405 output = pi5->pPortName;
407 if(hprn != INVALID_HANDLE_VALUE)
408 ClosePrinter(hprn);
411 physDev->job.hJob = OpenJob16(output, doc->lpszDocName, HDC_16(physDev->hdc) );
412 if(!physDev->job.hJob) {
413 WARN("OpenJob failed\n");
414 return 0;
416 physDev->job.banding = FALSE;
417 physDev->job.OutOfPage = TRUE;
418 physDev->job.PageNo = 0;
419 physDev->job.quiet = FALSE;
420 physDev->job.in_passthrough = FALSE;
421 physDev->job.had_passthrough_rect = FALSE;
422 if(doc->lpszDocName) {
423 physDev->job.DocName = HeapAlloc(GetProcessHeap(), 0, strlen(doc->lpszDocName)+1);
424 strcpy(physDev->job.DocName, doc->lpszDocName);
425 } else
426 physDev->job.DocName = NULL;
428 return physDev->job.hJob;
431 /************************************************************************
432 * PSDRV_StartDoc
434 INT PSDRV_StartDoc( PSDRV_PDEVICE *physDev, const DOCINFOW *doc )
436 DOCINFOA docA;
437 INT ret;
439 docA.cbSize = doc->cbSize;
440 docA.lpszDocName = doc->lpszDocName ?
441 HEAP_strdupWtoA( GetProcessHeap(), 0, doc->lpszDocName ) : NULL;
442 docA.lpszOutput = doc->lpszOutput ?
443 HEAP_strdupWtoA( GetProcessHeap(), 0, doc->lpszOutput ) : NULL;
444 docA.lpszDatatype = doc->lpszDatatype ?
445 HEAP_strdupWtoA( GetProcessHeap(), 0, doc->lpszDatatype ) : NULL;
446 docA.fwType = doc->fwType;
448 ret = PSDRV_StartDocA(physDev, &docA);
450 HeapFree( GetProcessHeap(), 0, (LPSTR)docA.lpszDocName );
451 HeapFree( GetProcessHeap(), 0, (LPSTR)docA.lpszOutput );
452 HeapFree( GetProcessHeap(), 0, (LPSTR)docA.lpszDatatype );
454 return ret;
457 /************************************************************************
458 * PSDRV_EndDoc
460 INT PSDRV_EndDoc( PSDRV_PDEVICE *physDev )
462 INT ret = 1;
463 if(!physDev->job.hJob) {
464 FIXME("hJob == 0. Now what?\n");
465 return 0;
468 if(!physDev->job.OutOfPage) {
469 WARN("Somebody forgot an EndPage\n");
470 PSDRV_EndPage( physDev );
472 PSDRV_WriteFooter( physDev );
474 if( CloseJob16( physDev->job.hJob ) == SP_ERROR ) {
475 WARN("CloseJob error\n");
476 ret = 0;
478 physDev->job.hJob = 0;
479 HeapFree(GetProcessHeap(), 0, physDev->job.DocName);
480 physDev->job.DocName = NULL;
482 return ret;