Portability fixes.
[wine.git] / dlls / wineps / escape.c
blob1c9bd77f4737a7578fa21cedf12ee0d5649ef578
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 * We have a WORD before the data counting the size, but
209 * cbInput is just this +2.
210 * However Photoshop 7 has a bug that sets cbInput to 2 less than the
211 * length of the string, rather than 2 more. So we'll use the WORD at
212 * in_data[0] instead.
214 return WriteSpool16(physDev->job.hJob,((char*)in_data)+2,*(WORD*)in_data);
217 case POSTSCRIPT_IGNORE:
219 BOOL ret = physDev->job.quiet;
220 TRACE("POSTSCRIPT_IGNORE %d\n", *(short*)in_data);
221 physDev->job.quiet = *(short*)in_data;
222 return ret;
225 case GETSETPRINTORIENT:
227 /* If lpInData is present, it is a 20 byte structure, first 32
228 * bit LONG value is the orientation. if lpInData is NULL, it
229 * returns the current orientation.
231 FIXME("GETSETPRINTORIENT not implemented (data %p)!\n",in_data);
232 return 1;
234 case BEGIN_PATH:
235 TRACE("BEGIN_PATH\n");
236 if(physDev->pathdepth)
237 FIXME("Nested paths not yet handled\n");
238 return ++physDev->pathdepth;
240 case END_PATH:
242 struct PATH_INFO *info = (struct PATH_INFO*)in_data;
244 TRACE("END_PATH\n");
245 if(!physDev->pathdepth) {
246 ERR("END_PATH called without a BEIGN_PATH\n");
247 return -1;
249 TRACE("RenderMode = %d, FillMode = %d, BkMode = %d\n",
250 info->RenderMode, info->FillMode, info->BkMode);
251 switch(info->RenderMode) {
252 case RENDERMODE_NO_DISPLAY:
253 PSDRV_WriteClosePath(physDev); /* not sure if this is necessary, but it can't hurt */
254 break;
255 case RENDERMODE_OPEN:
256 case RENDERMODE_CLOSED:
257 default:
258 FIXME("END_PATH: RenderMode %d, not yet supported\n", info->RenderMode);
259 break;
261 return --physDev->pathdepth;
264 case CLIP_TO_PATH:
266 WORD mode = *(WORD*)in_data;
268 switch(mode) {
269 case CLIP_SAVE:
270 TRACE("CLIP_TO_PATH: CLIP_SAVE\n");
271 PSDRV_WriteGSave(physDev);
272 return 1;
273 case CLIP_RESTORE:
274 TRACE("CLIP_TO_PATH: CLIP_RESTORE\n");
275 PSDRV_WriteGRestore(physDev);
276 return 1;
277 case CLIP_INCLUSIVE:
278 TRACE("CLIP_TO_PATH: CLIP_INCLUSIVE\n");
279 /* FIXME to clip or eoclip ? (see PATH_INFO.FillMode) */
280 PSDRV_WriteClip(physDev);
281 return 1;
282 case CLIP_EXCLUSIVE:
283 FIXME("CLIP_EXCLUSIVE: not implemented\n");
284 return 0;
285 default:
286 FIXME("Unknown CLIP_TO_PATH mode %d\n", mode);
287 return 0;
289 return 0;
291 default:
292 FIXME("Unimplemented code 0x%x\n", nEscape);
293 return 0;
297 /************************************************************************
298 * PSDRV_StartPage
300 INT PSDRV_StartPage( PSDRV_PDEVICE *physDev )
302 if(!physDev->job.OutOfPage) {
303 FIXME("Already started a page?\n");
304 return 1;
306 physDev->job.PageNo++;
307 if(!PSDRV_WriteNewPage( physDev ))
308 return 0;
309 physDev->job.OutOfPage = FALSE;
310 return 1;
314 /************************************************************************
315 * PSDRV_EndPage
317 INT PSDRV_EndPage( PSDRV_PDEVICE *physDev )
319 if(physDev->job.OutOfPage) {
320 FIXME("Already ended a page?\n");
321 return 1;
323 if(!PSDRV_WriteEndPage( physDev ))
324 return 0;
325 PSDRV_EmptyDownloadList(physDev, FALSE);
326 physDev->job.OutOfPage = TRUE;
327 return 1;
331 /************************************************************************
332 * PSDRV_StartDoc
334 INT PSDRV_StartDoc( PSDRV_PDEVICE *physDev, const DOCINFOA *doc )
336 LPCSTR output = "LPT1:";
337 BYTE buf[300];
338 HANDLE hprn = INVALID_HANDLE_VALUE;
339 PRINTER_INFO_5A *pi5 = (PRINTER_INFO_5A*)buf;
340 DWORD needed;
342 if(physDev->job.hJob) {
343 FIXME("hJob != 0. Now what?\n");
344 return 0;
347 if(doc->lpszOutput)
348 output = doc->lpszOutput;
349 else if(physDev->job.output)
350 output = physDev->job.output;
351 else {
352 if(OpenPrinterA(physDev->pi->FriendlyName, &hprn, NULL) &&
353 GetPrinterA(hprn, 5, buf, sizeof(buf), &needed)) {
354 output = pi5->pPortName;
356 if(hprn != INVALID_HANDLE_VALUE)
357 ClosePrinter(hprn);
360 physDev->job.hJob = OpenJob16(output, doc->lpszDocName, HDC_16(physDev->hdc) );
361 if(!physDev->job.hJob) {
362 WARN("OpenJob failed\n");
363 return 0;
365 physDev->job.banding = FALSE;
366 physDev->job.OutOfPage = TRUE;
367 physDev->job.PageNo = 0;
368 if(!PSDRV_WriteHeader( physDev, doc->lpszDocName ))
369 return 0;
371 return physDev->job.hJob;
375 /************************************************************************
376 * PSDRV_EndDoc
378 INT PSDRV_EndDoc( PSDRV_PDEVICE *physDev )
380 INT ret = 1;
381 if(!physDev->job.hJob) {
382 FIXME("hJob == 0. Now what?\n");
383 return 0;
386 if(!physDev->job.OutOfPage) {
387 WARN("Somebody forgot a EndPage\n");
388 PSDRV_EndPage( physDev );
390 PSDRV_WriteFooter( physDev );
392 if( CloseJob16( physDev->job.hJob ) == SP_ERROR ) {
393 WARN("CloseJob error\n");
394 ret = 0;
396 physDev->job.hJob = 0;
397 return ret;