Rewrote the collapsing of . and .. in RtlGetFullPathName_U for better
[wine.git] / dlls / wineps / escape.c
blobdbc343a43468decea6fee057903e0bfed2c2dc73
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 return 1;
292 case CLIP_EXCLUSIVE:
293 FIXME("CLIP_EXCLUSIVE: not implemented\n");
294 return 0;
295 default:
296 FIXME("Unknown CLIP_TO_PATH mode %d\n", mode);
297 return 0;
299 return 0;
301 default:
302 FIXME("Unimplemented code 0x%x\n", nEscape);
303 return 0;
307 /************************************************************************
308 * PSDRV_StartPage
310 INT PSDRV_StartPage( PSDRV_PDEVICE *physDev )
312 if(!physDev->job.OutOfPage) {
313 FIXME("Already started a page?\n");
314 return 1;
317 if(physDev->job.PageNo++ == 0) {
318 if(!PSDRV_WriteHeader( physDev, physDev->job.DocName ))
319 return 0;
322 if(!PSDRV_WriteNewPage( physDev ))
323 return 0;
324 physDev->job.OutOfPage = FALSE;
325 return 1;
329 /************************************************************************
330 * PSDRV_EndPage
332 INT PSDRV_EndPage( PSDRV_PDEVICE *physDev )
334 if(physDev->job.OutOfPage) {
335 FIXME("Already ended a page?\n");
336 return 1;
338 if(!PSDRV_WriteEndPage( physDev ))
339 return 0;
340 PSDRV_EmptyDownloadList(physDev, FALSE);
341 physDev->job.OutOfPage = TRUE;
342 return 1;
346 /************************************************************************
347 * PSDRV_StartDoc
349 INT PSDRV_StartDoc( PSDRV_PDEVICE *physDev, const DOCINFOA *doc )
351 LPCSTR output = "LPT1:";
352 BYTE buf[300];
353 HANDLE hprn = INVALID_HANDLE_VALUE;
354 PRINTER_INFO_5A *pi5 = (PRINTER_INFO_5A*)buf;
355 DWORD needed;
357 if(physDev->job.hJob) {
358 FIXME("hJob != 0. Now what?\n");
359 return 0;
362 if(doc->lpszOutput)
363 output = doc->lpszOutput;
364 else if(physDev->job.output)
365 output = physDev->job.output;
366 else {
367 if(OpenPrinterA(physDev->pi->FriendlyName, &hprn, NULL) &&
368 GetPrinterA(hprn, 5, buf, sizeof(buf), &needed)) {
369 output = pi5->pPortName;
371 if(hprn != INVALID_HANDLE_VALUE)
372 ClosePrinter(hprn);
375 physDev->job.hJob = OpenJob16(output, doc->lpszDocName, HDC_16(physDev->hdc) );
376 if(!physDev->job.hJob) {
377 WARN("OpenJob failed\n");
378 return 0;
380 physDev->job.banding = FALSE;
381 physDev->job.OutOfPage = TRUE;
382 physDev->job.PageNo = 0;
383 physDev->job.quiet = FALSE;
384 physDev->job.in_passthrough = FALSE;
385 physDev->job.had_passthrough_rect = FALSE;
386 if(doc->lpszDocName) {
387 physDev->job.DocName = HeapAlloc(GetProcessHeap(), 0, strlen(doc->lpszDocName)+1);
388 strcpy(physDev->job.DocName, doc->lpszDocName);
389 } else
390 physDev->job.DocName = NULL;
392 return physDev->job.hJob;
396 /************************************************************************
397 * PSDRV_EndDoc
399 INT PSDRV_EndDoc( PSDRV_PDEVICE *physDev )
401 INT ret = 1;
402 if(!physDev->job.hJob) {
403 FIXME("hJob == 0. Now what?\n");
404 return 0;
407 if(!physDev->job.OutOfPage) {
408 WARN("Somebody forgot a EndPage\n");
409 PSDRV_EndPage( physDev );
411 PSDRV_WriteFooter( physDev );
413 if( CloseJob16( physDev->job.hJob ) == SP_ERROR ) {
414 WARN("CloseJob error\n");
415 ret = 0;
417 physDev->job.hJob = 0;
418 if(physDev->job.DocName) {
419 HeapFree(GetProcessHeap(), 0, physDev->job.DocName);
420 physDev->job.DocName = NULL;
422 return ret;