For better concurrency, separate the connections from the bindings.
[wine.git] / dlls / wineps / escape.c
blob1598cdaec16469027ea995507944af976e7be010
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 "windef.h"
21 #include "wingdi.h"
22 #include "wine/wingdi16.h"
23 #include "wine/winuser16.h"
24 #include "wownt32.h"
25 #include "psdrv.h"
26 #include "wine/debug.h"
27 #include "winspool.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
31 /**********************************************************************
32 * ExtEscape (WINEPS.@)
34 INT PSDRV_ExtEscape( PSDRV_PDEVICE *physDev, INT nEscape, INT cbInput, LPCVOID in_data,
35 INT cbOutput, LPVOID out_data )
37 switch(nEscape)
39 case QUERYESCSUPPORT:
40 if(cbInput < sizeof(INT))
42 WARN("cbInput < sizeof(INT) (=%d) for QUERYESCSUPPORT\n", cbInput);
43 return 0;
44 } else {
45 UINT num = *(UINT *)in_data;
46 TRACE("QUERYESCSUPPORT for %d\n", num);
48 switch(num) {
49 case NEXTBAND:
50 case SETCOPYCOUNT:
51 case GETTECHNOLOGY:
52 case SETLINECAP:
53 case SETLINEJOIN:
54 case SETMITERLIMIT:
55 case SETCHARSET:
56 case EXT_DEVICE_CAPS:
57 case SET_BOUNDS:
58 case EPSPRINTING:
59 case POSTSCRIPT_DATA:
60 case PASSTHROUGH:
61 case POSTSCRIPT_PASSTHROUGH:
62 case POSTSCRIPT_IGNORE:
63 case BEGIN_PATH:
64 case CLIP_TO_PATH:
65 case END_PATH:
66 return TRUE;
68 default:
69 return FALSE;
73 case NEXTBAND:
75 RECT *r = out_data;
76 if(!physDev->job.banding) {
77 physDev->job.banding = TRUE;
78 r->left = 0;
79 r->top = 0;
80 r->right = physDev->horzRes;
81 r->bottom = physDev->vertRes;
82 TRACE("NEXTBAND returning %ld,%ld - %ld,%ld\n", r->left, r->top, r->right, r->bottom );
83 return 1;
85 r->left = 0;
86 r->top = 0;
87 r->right = 0;
88 r->bottom = 0;
89 TRACE("NEXTBAND rect to 0,0 - 0,0\n" );
90 physDev->job.banding = FALSE;
91 return EndPage( physDev->hdc );
94 case SETCOPYCOUNT:
96 const INT *NumCopies = in_data;
97 INT *ActualCopies = out_data;
98 if(cbInput != sizeof(INT)) {
99 WARN("cbInput != sizeof(INT) (=%d) for SETCOPYCOUNT\n", cbInput);
100 return 0;
102 TRACE("SETCOPYCOUNT %d\n", *NumCopies);
103 *ActualCopies = 1;
104 return 1;
107 case GETTECHNOLOGY:
109 LPSTR p = out_data;
110 strcpy(p, "PostScript");
111 *(p + strlen(p) + 1) = '\0'; /* 2 '\0's at end of string */
112 return 1;
115 case SETLINECAP:
117 INT newCap = *(INT *)in_data;
118 if(cbInput != sizeof(INT)) {
119 WARN("cbInput != sizeof(INT) (=%d) for SETLINECAP\n", cbInput);
120 return 0;
122 TRACE("SETLINECAP %d\n", newCap);
123 return 0;
126 case SETLINEJOIN:
128 INT newJoin = *(INT *)in_data;
129 if(cbInput != sizeof(INT)) {
130 WARN("cbInput != sizeof(INT) (=%d) for SETLINEJOIN\n", cbInput);
131 return 0;
133 TRACE("SETLINEJOIN %d\n", newJoin);
134 return 0;
137 case SETMITERLIMIT:
139 INT newLimit = *(INT *)in_data;
140 if(cbInput != sizeof(INT)) {
141 WARN("cbInput != sizeof(INT) (=%d) for SETMITERLIMIT\n", cbInput);
142 return 0;
144 TRACE("SETMITERLIMIT %d\n", newLimit);
145 return 0;
148 case SETCHARSET:
149 /* Undocumented escape used by winword6.
150 Switches between ANSI and a special charset.
151 If *lpInData == 1 we require that
152 0x91 is quoteleft
153 0x92 is quoteright
154 0x93 is quotedblleft
155 0x94 is quotedblright
156 0x95 is bullet
157 0x96 is endash
158 0x97 is emdash
159 0xa0 is non break space - yeah right.
161 If *lpInData == 0 we get ANSI.
162 Since there's nothing else there, let's just make these the default
163 anyway and see what happens...
165 return 1;
167 case EXT_DEVICE_CAPS:
169 UINT cap = *(UINT *)in_data;
170 if(cbInput != sizeof(UINT)) {
171 WARN("cbInput != sizeof(UINT) (=%d) for EXT_DEVICE_CAPS\n", cbInput);
172 return 0;
174 TRACE("EXT_DEVICE_CAPS %d\n", cap);
175 return 0;
178 case SET_BOUNDS:
180 const RECT *r = in_data;
181 if(cbInput != sizeof(RECT)) {
182 WARN("cbInput != sizeof(RECT) (=%d) for SET_BOUNDS\n", cbInput);
183 return 0;
185 TRACE("SET_BOUNDS (%ld,%ld) - (%ld,%ld)\n", r->left, r->top,
186 r->right, r->bottom);
187 return 0;
190 case EPSPRINTING:
192 UINT epsprint = *(UINT*)in_data;
193 /* FIXME: In this mode we do not need to send page intros and page
194 * ends according to the doc. But I just ignore that detail
195 * for now.
197 TRACE("EPS Printing support %sable.\n",epsprint?"en":"dis");
198 return 1;
201 case POSTSCRIPT_DATA:
202 case PASSTHROUGH:
203 case POSTSCRIPT_PASSTHROUGH:
205 /* Write directly to spool file, bypassing normal PS driver
206 * processing that is done along with writing PostScript code
207 * to the spool.
208 * (Usually we have a WORD before the data counting the size, but
209 * cbInput is just this +2.)
211 return WriteSpool16(physDev->job.hJob,((char*)in_data)+2,cbInput-2);
214 case POSTSCRIPT_IGNORE:
216 BOOL ret = physDev->job.quiet;
217 TRACE("POSTSCRIPT_IGNORE %d\n", *(short*)in_data);
218 physDev->job.quiet = *(short*)in_data;
219 return ret;
222 case GETSETPRINTORIENT:
224 /* If lpInData is present, it is a 20 byte structure, first 32
225 * bit LONG value is the orientation. if lpInData is NULL, it
226 * returns the current orientation.
228 FIXME("GETSETPRINTORIENT not implemented (data %p)!\n",in_data);
229 return 1;
231 case BEGIN_PATH:
232 TRACE("BEGIN_PATH\n");
233 if(physDev->pathdepth)
234 FIXME("Nested paths not yet handled\n");
235 return ++physDev->pathdepth;
237 case END_PATH:
239 struct PATH_INFO *info = (struct PATH_INFO*)in_data;
241 TRACE("END_PATH\n");
242 if(!physDev->pathdepth) {
243 ERR("END_PATH called without a BEIGN_PATH\n");
244 return -1;
246 TRACE("RenderMode = %d, FillMode = %d, BkMode = %d\n",
247 info->RenderMode, info->FillMode, info->BkMode);
248 switch(info->RenderMode) {
249 case RENDERMODE_NO_DISPLAY:
250 PSDRV_WriteClosePath(physDev); /* not sure if this is necessary, but it can't hurt */
251 break;
252 case RENDERMODE_OPEN:
253 case RENDERMODE_CLOSED:
254 default:
255 FIXME("END_PATH: RenderMode %d, not yet supported\n", info->RenderMode);
256 break;
258 return --physDev->pathdepth;
261 case CLIP_TO_PATH:
263 WORD mode = *(WORD*)in_data;
265 switch(mode) {
266 case CLIP_SAVE:
267 TRACE("CLIP_TO_PATH: CLIP_SAVE\n");
268 PSDRV_WriteGSave(physDev);
269 return 1;
270 case CLIP_RESTORE:
271 TRACE("CLIP_TO_PATH: CLIP_RESTORE\n");
272 PSDRV_WriteGRestore(physDev);
273 return 1;
274 case CLIP_INCLUSIVE:
275 TRACE("CLIP_TO_PATH: CLIP_INCLUSIVE\n");
276 /* FIXME to clip or eoclip ? (see PATH_INFO.FillMode) */
277 PSDRV_WriteClip(physDev);
278 return 1;
279 case CLIP_EXCLUSIVE:
280 FIXME("CLIP_EXCLUSIVE: not implemented\n");
281 return 0;
282 default:
283 FIXME("Unknown CLIP_TO_PATH mode %d\n", mode);
284 return 0;
286 return 0;
288 default:
289 FIXME("Unimplemented code 0x%x\n", nEscape);
290 return 0;
294 /************************************************************************
295 * PSDRV_StartPage
297 INT PSDRV_StartPage( PSDRV_PDEVICE *physDev )
299 if(!physDev->job.OutOfPage) {
300 FIXME("Already started a page?\n");
301 return 1;
303 physDev->job.PageNo++;
304 if(!PSDRV_WriteNewPage( physDev ))
305 return 0;
306 physDev->job.OutOfPage = FALSE;
307 return 1;
311 /************************************************************************
312 * PSDRV_EndPage
314 INT PSDRV_EndPage( PSDRV_PDEVICE *physDev )
316 if(physDev->job.OutOfPage) {
317 FIXME("Already ended a page?\n");
318 return 1;
320 if(!PSDRV_WriteEndPage( physDev ))
321 return 0;
322 PSDRV_EmptyDownloadList(physDev);
323 physDev->job.OutOfPage = TRUE;
324 return 1;
328 /************************************************************************
329 * PSDRV_StartDoc
331 INT PSDRV_StartDoc( PSDRV_PDEVICE *physDev, const DOCINFOA *doc )
333 if(physDev->job.hJob) {
334 FIXME("hJob != 0. Now what?\n");
335 return 0;
338 if(doc->lpszOutput) {
339 HeapFree( PSDRV_Heap, 0, physDev->job.output );
340 physDev->job.output = HeapAlloc( PSDRV_Heap, 0, strlen(doc->lpszOutput)+1 );
341 strcpy( physDev->job.output, doc->lpszOutput );
343 physDev->job.hJob = OpenJob16(physDev->job.output, doc->lpszDocName, HDC_16(physDev->hdc) );
344 if(!physDev->job.hJob) {
345 WARN("OpenJob failed\n");
346 return 0;
348 physDev->job.banding = FALSE;
349 physDev->job.OutOfPage = TRUE;
350 physDev->job.PageNo = 0;
351 if(!PSDRV_WriteHeader( physDev, doc->lpszDocName ))
352 return 0;
354 return physDev->job.hJob;
358 /************************************************************************
359 * PSDRV_EndDoc
361 INT PSDRV_EndDoc( PSDRV_PDEVICE *physDev )
363 INT ret = 1;
364 if(!physDev->job.hJob) {
365 FIXME("hJob == 0. Now what?\n");
366 return 0;
369 if(!physDev->job.OutOfPage) {
370 WARN("Somebody forgot a EndPage\n");
371 PSDRV_EndPage( physDev );
373 PSDRV_WriteFooter( physDev );
375 if( CloseJob16( physDev->job.hJob ) == SP_ERROR ) {
376 WARN("CloseJob error\n");
377 ret = 0;
379 physDev->job.hJob = 0;
380 return ret;