Removed W->A from DEFWND_ImmIsUIMessageW.
[wine] / dlls / wineps / escape.c
1 /*
2  *      PostScript driver Escape function
3  *
4  *      Copyright 1998  Huw D M Davies
5  *
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.
10  *
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.
15  *
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
19  */
20 #include <stdarg.h>
21
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
32 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
33
34 static const char psbegindocument[] =
35 "%%BeginDocument: Wine passthrough\n";
36
37 /**********************************************************************
38  *           ExtEscape  (WINEPS.@)
39  */
40 INT PSDRV_ExtEscape( PSDRV_PDEVICE *physDev, INT nEscape, INT cbInput, LPCVOID in_data,
41                      INT cbOutput, LPVOID out_data )
42 {
43     switch(nEscape)
44     {
45     case QUERYESCSUPPORT:
46         if(cbInput < sizeof(INT))
47         {
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);
53
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;
73
74             default:
75                 return FALSE;
76             }
77         }
78
79     case NEXTBAND:
80     {
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;
90         }
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 );
98     }
99
100     case SETCOPYCOUNT:
101         {
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;
107             }
108             TRACE("SETCOPYCOUNT %d\n", *NumCopies);
109             *ActualCopies = 1;
110             return 1;
111         }
112
113     case GETTECHNOLOGY:
114         {
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;
119         }
120
121     case SETLINECAP:
122         {
123             INT newCap = *(INT *)in_data;
124             if(cbInput != sizeof(INT)) {
125                 WARN("cbInput != sizeof(INT) (=%d) for SETLINECAP\n", cbInput);
126                 return 0;
127             }
128             TRACE("SETLINECAP %d\n", newCap);
129             return 0;
130         }
131
132     case SETLINEJOIN:
133         {
134             INT newJoin = *(INT *)in_data;
135             if(cbInput != sizeof(INT)) {
136                 WARN("cbInput != sizeof(INT) (=%d) for SETLINEJOIN\n", cbInput);
137                 return 0;
138             }
139             TRACE("SETLINEJOIN %d\n", newJoin);
140             return 0;
141         }
142
143     case SETMITERLIMIT:
144         {
145             INT newLimit = *(INT *)in_data;
146             if(cbInput != sizeof(INT)) {
147                 WARN("cbInput != sizeof(INT) (=%d) for SETMITERLIMIT\n", cbInput);
148                 return 0;
149             }
150             TRACE("SETMITERLIMIT %d\n", newLimit);
151             return 0;
152         }
153
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.
166
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...
170       */
171         return 1;
172
173     case EXT_DEVICE_CAPS:
174         {
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;
179             }
180             TRACE("EXT_DEVICE_CAPS %d\n", cap);
181             return 0;
182         }
183
184     case SET_BOUNDS:
185         {
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;
190             }
191             TRACE("SET_BOUNDS (%ld,%ld) - (%ld,%ld)\n", r->left, r->top,
192                   r->right, r->bottom);
193             return 0;
194         }
195
196     case EPSPRINTING:
197         {
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.
202              */
203             TRACE("EPS Printing support %sable.\n",epsprint?"en":"dis");
204             return 1;
205         }
206
207     case POSTSCRIPT_DATA:
208     case PASSTHROUGH:
209     case POSTSCRIPT_PASSTHROUGH:
210         {
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.
219              */
220             if(!physDev->job.in_passthrough) {
221                 WriteSpool16(physDev->job.hJob, (LPSTR)psbegindocument, sizeof(psbegindocument)-1);
222                 physDev->job.in_passthrough = TRUE;
223             }
224             return WriteSpool16(physDev->job.hJob,((char*)in_data)+2,*(WORD*)in_data);
225         }
226
227     case POSTSCRIPT_IGNORE:
228       {
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;
233       }
234
235     case GETSETPRINTORIENT:
236         {
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.
240              */
241             FIXME("GETSETPRINTORIENT not implemented (data %p)!\n",in_data);
242             return 1;
243         }
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;
249
250     case END_PATH:
251       {
252         struct PATH_INFO *info = (struct PATH_INFO*)in_data;
253
254         TRACE("END_PATH\n");
255         if(!physDev->pathdepth) {
256             ERR("END_PATH called without a BEIGN_PATH\n");
257             return -1;
258         }
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;
270         }
271         return --physDev->pathdepth;
272       }
273
274     case CLIP_TO_PATH:
275       {
276         WORD mode = *(WORD*)in_data;
277
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;
299         }
300         return 0;
301       }
302     default:
303         FIXME("Unimplemented code 0x%x\n", nEscape);
304         return 0;
305     }
306 }
307
308 /************************************************************************
309  *           PSDRV_StartPage
310  */
311 INT PSDRV_StartPage( PSDRV_PDEVICE *physDev )
312 {
313     if(!physDev->job.OutOfPage) {
314         FIXME("Already started a page?\n");
315         return 1;
316     }
317
318     if(physDev->job.PageNo++ == 0) {
319         if(!PSDRV_WriteHeader( physDev, physDev->job.DocName ))
320             return 0;
321     }
322
323     if(!PSDRV_WriteNewPage( physDev ))
324         return 0;
325     physDev->job.OutOfPage = FALSE;
326     return 1;
327 }
328
329
330 /************************************************************************
331  *           PSDRV_EndPage
332  */
333 INT PSDRV_EndPage( PSDRV_PDEVICE *physDev )
334 {
335     if(physDev->job.OutOfPage) {
336         FIXME("Already ended a page?\n");
337         return 1;
338     }
339     if(!PSDRV_WriteEndPage( physDev ))
340         return 0;
341     PSDRV_EmptyDownloadList(physDev, FALSE);
342     physDev->job.OutOfPage = TRUE;
343     return 1;
344 }
345
346
347 /************************************************************************
348  *           PSDRV_StartDoc
349  */
350 INT PSDRV_StartDoc( PSDRV_PDEVICE *physDev, const DOCINFOA *doc )
351 {
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;
357
358     if(physDev->job.hJob) {
359         FIXME("hJob != 0. Now what?\n");
360         return 0;
361     }
362
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;
371         }
372         if(hprn != INVALID_HANDLE_VALUE)
373             ClosePrinter(hprn);
374     }
375
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;
380     }
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;
392
393     return physDev->job.hJob;
394 }
395
396
397 /************************************************************************
398  *           PSDRV_EndDoc
399  */
400 INT PSDRV_EndDoc( PSDRV_PDEVICE *physDev )
401 {
402     INT ret = 1;
403     if(!physDev->job.hJob) {
404         FIXME("hJob == 0. Now what?\n");
405         return 0;
406     }
407
408     if(!physDev->job.OutOfPage) {
409         WARN("Somebody forgot a EndPage\n");
410         PSDRV_EndPage( physDev );
411     }
412     PSDRV_WriteFooter( physDev );
413
414     if( CloseJob16( physDev->job.hJob ) == SP_ERROR ) {
415         WARN("CloseJob error\n");
416         ret = 0;
417     }
418     physDev->job.hJob = 0;
419     if(physDev->job.DocName) {
420         HeapFree(GetProcessHeap(), 0, physDev->job.DocName);
421         physDev->job.DocName = NULL;
422     }
423     return ret;
424 }