Added YUV routines needed for v4l driver, and in the future possibly
[wine/gsoc-2012-control.git] / dlls / wineps / escape.c
blobbf680c9184bea2ab084eefe24beaecc78770e483
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 SETCOPYCOUNT:
58 case GETTECHNOLOGY:
59 case SETLINECAP:
60 case SETLINEJOIN:
61 case SETMITERLIMIT:
62 case SETCHARSET:
63 case EXT_DEVICE_CAPS:
64 case SET_BOUNDS:
65 case EPSPRINTING:
66 case POSTSCRIPT_DATA:
67 case PASSTHROUGH:
68 case POSTSCRIPT_PASSTHROUGH:
69 case POSTSCRIPT_IGNORE:
70 case BEGIN_PATH:
71 case CLIP_TO_PATH:
72 case END_PATH:
73 return TRUE;
75 default:
76 return FALSE;
80 case NEXTBAND:
82 RECT *r = out_data;
83 if(!physDev->job.banding) {
84 physDev->job.banding = TRUE;
85 r->left = 0;
86 r->top = 0;
87 r->right = physDev->horzRes;
88 r->bottom = physDev->vertRes;
89 TRACE("NEXTBAND returning %ld,%ld - %ld,%ld\n", r->left, r->top, r->right, r->bottom );
90 return 1;
92 r->left = 0;
93 r->top = 0;
94 r->right = 0;
95 r->bottom = 0;
96 TRACE("NEXTBAND rect to 0,0 - 0,0\n" );
97 physDev->job.banding = FALSE;
98 return EndPage( physDev->hdc );
101 case SETCOPYCOUNT:
103 const INT *NumCopies = in_data;
104 INT *ActualCopies = out_data;
105 if(cbInput != sizeof(INT)) {
106 WARN("cbInput != sizeof(INT) (=%d) for SETCOPYCOUNT\n", cbInput);
107 return 0;
109 TRACE("SETCOPYCOUNT %d\n", *NumCopies);
110 *ActualCopies = 1;
111 return 1;
114 case GETTECHNOLOGY:
116 LPSTR p = out_data;
117 strcpy(p, "PostScript");
118 *(p + strlen(p) + 1) = '\0'; /* 2 '\0's at end of string */
119 return 1;
122 case SETLINECAP:
124 INT newCap = *(const INT *)in_data;
125 if(cbInput != sizeof(INT)) {
126 WARN("cbInput != sizeof(INT) (=%d) for SETLINECAP\n", cbInput);
127 return 0;
129 TRACE("SETLINECAP %d\n", newCap);
130 return 0;
133 case SETLINEJOIN:
135 INT newJoin = *(const INT *)in_data;
136 if(cbInput != sizeof(INT)) {
137 WARN("cbInput != sizeof(INT) (=%d) for SETLINEJOIN\n", cbInput);
138 return 0;
140 TRACE("SETLINEJOIN %d\n", newJoin);
141 return 0;
144 case SETMITERLIMIT:
146 INT newLimit = *(const INT *)in_data;
147 if(cbInput != sizeof(INT)) {
148 WARN("cbInput != sizeof(INT) (=%d) for SETMITERLIMIT\n", cbInput);
149 return 0;
151 TRACE("SETMITERLIMIT %d\n", newLimit);
152 return 0;
155 case SETCHARSET:
156 /* Undocumented escape used by winword6.
157 Switches between ANSI and a special charset.
158 If *lpInData == 1 we require that
159 0x91 is quoteleft
160 0x92 is quoteright
161 0x93 is quotedblleft
162 0x94 is quotedblright
163 0x95 is bullet
164 0x96 is endash
165 0x97 is emdash
166 0xa0 is non break space - yeah right.
168 If *lpInData == 0 we get ANSI.
169 Since there's nothing else there, let's just make these the default
170 anyway and see what happens...
172 return 1;
174 case EXT_DEVICE_CAPS:
176 UINT cap = *(const UINT *)in_data;
177 if(cbInput != sizeof(UINT)) {
178 WARN("cbInput != sizeof(UINT) (=%d) for EXT_DEVICE_CAPS\n", cbInput);
179 return 0;
181 TRACE("EXT_DEVICE_CAPS %d\n", cap);
182 return 0;
185 case SET_BOUNDS:
187 const RECT *r = in_data;
188 if(cbInput != sizeof(RECT)) {
189 WARN("cbInput != sizeof(RECT) (=%d) for SET_BOUNDS\n", cbInput);
190 return 0;
192 TRACE("SET_BOUNDS (%ld,%ld) - (%ld,%ld)\n", r->left, r->top,
193 r->right, r->bottom);
194 return 0;
197 case EPSPRINTING:
199 UINT epsprint = *(const UINT*)in_data;
200 /* FIXME: In this mode we do not need to send page intros and page
201 * ends according to the doc. But I just ignore that detail
202 * for now.
204 TRACE("EPS Printing support %sable.\n",epsprint?"en":"dis");
205 return 1;
208 case POSTSCRIPT_DATA:
209 case PASSTHROUGH:
210 case POSTSCRIPT_PASSTHROUGH:
212 /* Write directly to spool file, bypassing normal PS driver
213 * processing that is done along with writing PostScript code
214 * to the spool.
215 * We have a WORD before the data counting the size, but
216 * cbInput is just this +2.
217 * However Photoshop 7 has a bug that sets cbInput to 2 less than the
218 * length of the string, rather than 2 more. So we'll use the WORD at
219 * in_data[0] instead.
221 if(!physDev->job.in_passthrough) {
222 WriteSpool16(physDev->job.hJob, (LPSTR)psbegindocument, sizeof(psbegindocument)-1);
223 physDev->job.in_passthrough = TRUE;
225 return WriteSpool16(physDev->job.hJob,((char*)in_data)+2,*(const WORD*)in_data);
228 case POSTSCRIPT_IGNORE:
230 BOOL ret = physDev->job.quiet;
231 TRACE("POSTSCRIPT_IGNORE %d\n", *(const short*)in_data);
232 physDev->job.quiet = *(const short*)in_data;
233 return ret;
236 case GETSETPRINTORIENT:
238 /* If lpInData is present, it is a 20 byte structure, first 32
239 * bit LONG value is the orientation. if lpInData is NULL, it
240 * returns the current orientation.
242 FIXME("GETSETPRINTORIENT not implemented (data %p)!\n",in_data);
243 return 1;
245 case BEGIN_PATH:
246 TRACE("BEGIN_PATH\n");
247 if(physDev->pathdepth)
248 FIXME("Nested paths not yet handled\n");
249 return ++physDev->pathdepth;
251 case END_PATH:
253 const struct PATH_INFO *info = (const struct PATH_INFO*)in_data;
255 TRACE("END_PATH\n");
256 if(!physDev->pathdepth) {
257 ERR("END_PATH called without a BEIGN_PATH\n");
258 return -1;
260 TRACE("RenderMode = %d, FillMode = %d, BkMode = %d\n",
261 info->RenderMode, info->FillMode, info->BkMode);
262 switch(info->RenderMode) {
263 case RENDERMODE_NO_DISPLAY:
264 PSDRV_WriteClosePath(physDev); /* not sure if this is necessary, but it can't hurt */
265 break;
266 case RENDERMODE_OPEN:
267 case RENDERMODE_CLOSED:
268 default:
269 FIXME("END_PATH: RenderMode %d, not yet supported\n", info->RenderMode);
270 break;
272 return --physDev->pathdepth;
275 case CLIP_TO_PATH:
277 WORD mode = *(const WORD*)in_data;
279 switch(mode) {
280 case CLIP_SAVE:
281 TRACE("CLIP_TO_PATH: CLIP_SAVE\n");
282 PSDRV_WriteGSave(physDev);
283 return 1;
284 case CLIP_RESTORE:
285 TRACE("CLIP_TO_PATH: CLIP_RESTORE\n");
286 PSDRV_WriteGRestore(physDev);
287 return 1;
288 case CLIP_INCLUSIVE:
289 TRACE("CLIP_TO_PATH: CLIP_INCLUSIVE\n");
290 /* FIXME to clip or eoclip ? (see PATH_INFO.FillMode) */
291 PSDRV_WriteClip(physDev);
292 PSDRV_WriteNewPath(physDev);
293 return 1;
294 case CLIP_EXCLUSIVE:
295 FIXME("CLIP_EXCLUSIVE: not implemented\n");
296 return 0;
297 default:
298 FIXME("Unknown CLIP_TO_PATH mode %d\n", mode);
299 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_StartDocA
350 INT PSDRV_StartDocA( 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;
396 /************************************************************************
397 * PSDRV_StartDoc
399 INT PSDRV_StartDoc( PSDRV_PDEVICE *physDev, const DOCINFOW *doc )
401 DOCINFOA docA;
402 INT ret;
404 docA.cbSize = doc->cbSize;
405 docA.lpszDocName = doc->lpszDocName ?
406 HEAP_strdupWtoA( GetProcessHeap(), 0, doc->lpszDocName ) : NULL;
407 docA.lpszOutput = doc->lpszOutput ?
408 HEAP_strdupWtoA( GetProcessHeap(), 0, doc->lpszOutput ) : NULL;
409 docA.lpszDatatype = doc->lpszDatatype ?
410 HEAP_strdupWtoA( GetProcessHeap(), 0, doc->lpszDatatype ) : NULL;
411 docA.fwType = doc->fwType;
413 ret = PSDRV_StartDocA(physDev, &docA);
415 HeapFree( GetProcessHeap(), 0, (LPSTR)docA.lpszDocName );
416 HeapFree( GetProcessHeap(), 0, (LPSTR)docA.lpszOutput );
417 HeapFree( GetProcessHeap(), 0, (LPSTR)docA.lpszDatatype );
419 return ret;
422 /************************************************************************
423 * PSDRV_EndDoc
425 INT PSDRV_EndDoc( PSDRV_PDEVICE *physDev )
427 INT ret = 1;
428 if(!physDev->job.hJob) {
429 FIXME("hJob == 0. Now what?\n");
430 return 0;
433 if(!physDev->job.OutOfPage) {
434 WARN("Somebody forgot an EndPage\n");
435 PSDRV_EndPage( physDev );
437 PSDRV_WriteFooter( physDev );
439 if( CloseJob16( physDev->job.hJob ) == SP_ERROR ) {
440 WARN("CloseJob error\n");
441 ret = 0;
443 physDev->job.hJob = 0;
444 HeapFree(GetProcessHeap(), 0, physDev->job.DocName);
445 physDev->job.DocName = NULL;
447 return ret;