Protect use of pthread functions with #ifdef HAVE_PTHREAD_H.
[wine/multimedia.git] / dlls / wineps / escape.c
blob5cec36820cf9755d04da6062bb4500d81501e752
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"
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 = *(UINT *)in_data;
52 TRACE("QUERYESCSUPPORT for %d\n", num);
54 switch(num) {
55 case NEXTBAND:
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 return TRUE;
74 default:
75 return FALSE;
79 case NEXTBAND:
81 RECT *r = out_data;
82 if(!physDev->job.banding) {
83 physDev->job.banding = TRUE;
84 r->left = 0;
85 r->top = 0;
86 r->right = physDev->horzRes;
87 r->bottom = physDev->vertRes;
88 TRACE("NEXTBAND returning %ld,%ld - %ld,%ld\n", r->left, r->top, r->right, r->bottom );
89 return 1;
91 r->left = 0;
92 r->top = 0;
93 r->right = 0;
94 r->bottom = 0;
95 TRACE("NEXTBAND rect to 0,0 - 0,0\n" );
96 physDev->job.banding = FALSE;
97 return EndPage( physDev->hdc );
100 case SETCOPYCOUNT:
102 const INT *NumCopies = in_data;
103 INT *ActualCopies = out_data;
104 if(cbInput != sizeof(INT)) {
105 WARN("cbInput != sizeof(INT) (=%d) for SETCOPYCOUNT\n", cbInput);
106 return 0;
108 TRACE("SETCOPYCOUNT %d\n", *NumCopies);
109 *ActualCopies = 1;
110 return 1;
113 case GETTECHNOLOGY:
115 LPSTR p = out_data;
116 strcpy(p, "PostScript");
117 *(p + strlen(p) + 1) = '\0'; /* 2 '\0's at end of string */
118 return 1;
121 case SETLINECAP:
123 INT newCap = *(INT *)in_data;
124 if(cbInput != sizeof(INT)) {
125 WARN("cbInput != sizeof(INT) (=%d) for SETLINECAP\n", cbInput);
126 return 0;
128 TRACE("SETLINECAP %d\n", newCap);
129 return 0;
132 case SETLINEJOIN:
134 INT newJoin = *(INT *)in_data;
135 if(cbInput != sizeof(INT)) {
136 WARN("cbInput != sizeof(INT) (=%d) for SETLINEJOIN\n", cbInput);
137 return 0;
139 TRACE("SETLINEJOIN %d\n", newJoin);
140 return 0;
143 case SETMITERLIMIT:
145 INT newLimit = *(INT *)in_data;
146 if(cbInput != sizeof(INT)) {
147 WARN("cbInput != sizeof(INT) (=%d) for SETMITERLIMIT\n", cbInput);
148 return 0;
150 TRACE("SETMITERLIMIT %d\n", newLimit);
151 return 0;
154 case SETCHARSET:
155 /* Undocumented escape used by winword6.
156 Switches between ANSI and a special charset.
157 If *lpInData == 1 we require that
158 0x91 is quoteleft
159 0x92 is quoteright
160 0x93 is quotedblleft
161 0x94 is quotedblright
162 0x95 is bullet
163 0x96 is endash
164 0x97 is emdash
165 0xa0 is non break space - yeah right.
167 If *lpInData == 0 we get ANSI.
168 Since there's nothing else there, let's just make these the default
169 anyway and see what happens...
171 return 1;
173 case EXT_DEVICE_CAPS:
175 UINT cap = *(UINT *)in_data;
176 if(cbInput != sizeof(UINT)) {
177 WARN("cbInput != sizeof(UINT) (=%d) for EXT_DEVICE_CAPS\n", cbInput);
178 return 0;
180 TRACE("EXT_DEVICE_CAPS %d\n", cap);
181 return 0;
184 case SET_BOUNDS:
186 const RECT *r = in_data;
187 if(cbInput != sizeof(RECT)) {
188 WARN("cbInput != sizeof(RECT) (=%d) for SET_BOUNDS\n", cbInput);
189 return 0;
191 TRACE("SET_BOUNDS (%ld,%ld) - (%ld,%ld)\n", r->left, r->top,
192 r->right, r->bottom);
193 return 0;
196 case EPSPRINTING:
198 UINT epsprint = *(UINT*)in_data;
199 /* FIXME: In this mode we do not need to send page intros and page
200 * ends according to the doc. But I just ignore that detail
201 * for now.
203 TRACE("EPS Printing support %sable.\n",epsprint?"en":"dis");
204 return 1;
207 case POSTSCRIPT_DATA:
208 case PASSTHROUGH:
209 case POSTSCRIPT_PASSTHROUGH:
211 /* Write directly to spool file, bypassing normal PS driver
212 * processing that is done along with writing PostScript code
213 * to the spool.
214 * We have a WORD before the data counting the size, but
215 * cbInput is just this +2.
216 * However Photoshop 7 has a bug that sets cbInput to 2 less than the
217 * length of the string, rather than 2 more. So we'll use the WORD at
218 * in_data[0] instead.
220 if(!physDev->job.in_passthrough) {
221 WriteSpool16(physDev->job.hJob, (LPSTR)psbegindocument, sizeof(psbegindocument)-1);
222 physDev->job.in_passthrough = TRUE;
224 return WriteSpool16(physDev->job.hJob,((char*)in_data)+2,*(WORD*)in_data);
227 case POSTSCRIPT_IGNORE:
229 BOOL ret = physDev->job.quiet;
230 TRACE("POSTSCRIPT_IGNORE %d\n", *(short*)in_data);
231 physDev->job.quiet = *(short*)in_data;
232 return ret;
235 case GETSETPRINTORIENT:
237 /* If lpInData is present, it is a 20 byte structure, first 32
238 * bit LONG value is the orientation. if lpInData is NULL, it
239 * returns the current orientation.
241 FIXME("GETSETPRINTORIENT not implemented (data %p)!\n",in_data);
242 return 1;
244 case BEGIN_PATH:
245 TRACE("BEGIN_PATH\n");
246 if(physDev->pathdepth)
247 FIXME("Nested paths not yet handled\n");
248 return ++physDev->pathdepth;
250 case END_PATH:
252 struct PATH_INFO *info = (struct PATH_INFO*)in_data;
254 TRACE("END_PATH\n");
255 if(!physDev->pathdepth) {
256 ERR("END_PATH called without a BEIGN_PATH\n");
257 return -1;
259 TRACE("RenderMode = %d, FillMode = %d, BkMode = %d\n",
260 info->RenderMode, info->FillMode, info->BkMode);
261 switch(info->RenderMode) {
262 case RENDERMODE_NO_DISPLAY:
263 PSDRV_WriteClosePath(physDev); /* not sure if this is necessary, but it can't hurt */
264 break;
265 case RENDERMODE_OPEN:
266 case RENDERMODE_CLOSED:
267 default:
268 FIXME("END_PATH: RenderMode %d, not yet supported\n", info->RenderMode);
269 break;
271 return --physDev->pathdepth;
274 case CLIP_TO_PATH:
276 WORD mode = *(WORD*)in_data;
278 switch(mode) {
279 case CLIP_SAVE:
280 TRACE("CLIP_TO_PATH: CLIP_SAVE\n");
281 PSDRV_WriteGSave(physDev);
282 return 1;
283 case CLIP_RESTORE:
284 TRACE("CLIP_TO_PATH: CLIP_RESTORE\n");
285 PSDRV_WriteGRestore(physDev);
286 return 1;
287 case CLIP_INCLUSIVE:
288 TRACE("CLIP_TO_PATH: CLIP_INCLUSIVE\n");
289 /* FIXME to clip or eoclip ? (see PATH_INFO.FillMode) */
290 PSDRV_WriteClip(physDev);
291 PSDRV_WriteNewPath(physDev);
292 return 1;
293 case CLIP_EXCLUSIVE:
294 FIXME("CLIP_EXCLUSIVE: not implemented\n");
295 return 0;
296 default:
297 FIXME("Unknown CLIP_TO_PATH mode %d\n", mode);
298 return 0;
300 return 0;
302 default:
303 FIXME("Unimplemented code 0x%x\n", nEscape);
304 return 0;
308 /************************************************************************
309 * PSDRV_StartPage
311 INT PSDRV_StartPage( PSDRV_PDEVICE *physDev )
313 if(!physDev->job.OutOfPage) {
314 FIXME("Already started a page?\n");
315 return 1;
318 if(physDev->job.PageNo++ == 0) {
319 if(!PSDRV_WriteHeader( physDev, physDev->job.DocName ))
320 return 0;
323 if(!PSDRV_WriteNewPage( physDev ))
324 return 0;
325 physDev->job.OutOfPage = FALSE;
326 return 1;
330 /************************************************************************
331 * PSDRV_EndPage
333 INT PSDRV_EndPage( PSDRV_PDEVICE *physDev )
335 if(physDev->job.OutOfPage) {
336 FIXME("Already ended a page?\n");
337 return 1;
339 if(!PSDRV_WriteEndPage( physDev ))
340 return 0;
341 PSDRV_EmptyDownloadList(physDev, FALSE);
342 physDev->job.OutOfPage = TRUE;
343 return 1;
347 /************************************************************************
348 * PSDRV_StartDoc
350 INT PSDRV_StartDoc( PSDRV_PDEVICE *physDev, const DOCINFOA *doc )
352 LPCSTR output = "LPT1:";
353 BYTE buf[300];
354 HANDLE hprn = INVALID_HANDLE_VALUE;
355 PRINTER_INFO_5A *pi5 = (PRINTER_INFO_5A*)buf;
356 DWORD needed;
358 if(physDev->job.hJob) {
359 FIXME("hJob != 0. Now what?\n");
360 return 0;
363 if(doc->lpszOutput)
364 output = doc->lpszOutput;
365 else if(physDev->job.output)
366 output = physDev->job.output;
367 else {
368 if(OpenPrinterA(physDev->pi->FriendlyName, &hprn, NULL) &&
369 GetPrinterA(hprn, 5, buf, sizeof(buf), &needed)) {
370 output = pi5->pPortName;
372 if(hprn != INVALID_HANDLE_VALUE)
373 ClosePrinter(hprn);
376 physDev->job.hJob = OpenJob16(output, doc->lpszDocName, HDC_16(physDev->hdc) );
377 if(!physDev->job.hJob) {
378 WARN("OpenJob failed\n");
379 return 0;
381 physDev->job.banding = FALSE;
382 physDev->job.OutOfPage = TRUE;
383 physDev->job.PageNo = 0;
384 physDev->job.quiet = FALSE;
385 physDev->job.in_passthrough = FALSE;
386 physDev->job.had_passthrough_rect = FALSE;
387 if(doc->lpszDocName) {
388 physDev->job.DocName = HeapAlloc(GetProcessHeap(), 0, strlen(doc->lpszDocName)+1);
389 strcpy(physDev->job.DocName, doc->lpszDocName);
390 } else
391 physDev->job.DocName = NULL;
393 return physDev->job.hJob;
397 /************************************************************************
398 * PSDRV_EndDoc
400 INT PSDRV_EndDoc( PSDRV_PDEVICE *physDev )
402 INT ret = 1;
403 if(!physDev->job.hJob) {
404 FIXME("hJob == 0. Now what?\n");
405 return 0;
408 if(!physDev->job.OutOfPage) {
409 WARN("Somebody forgot a EndPage\n");
410 PSDRV_EndPage( physDev );
412 PSDRV_WriteFooter( physDev );
414 if( CloseJob16( physDev->job.hJob ) == SP_ERROR ) {
415 WARN("CloseJob error\n");
416 ret = 0;
418 physDev->job.hJob = 0;
419 if(physDev->job.DocName) {
420 HeapFree(GetProcessHeap(), 0, physDev->job.DocName);
421 physDev->job.DocName = NULL;
423 return ret;