Updated.
[wine] / dlls / wineps / escape.c
1 /*
2  *      PostScript driver Escape function
3  *
4  *      Copyright 1998  Huw D M Davies
5  */
6 #include "windef.h"
7 #include "wingdi.h"
8 #include "wine/winuser16.h"
9 #include "psdrv.h"
10 #include "debugtools.h"
11 #include "winspool.h"
12 #include "heap.h"
13
14 DEFAULT_DEBUG_CHANNEL(psdrv);
15
16
17 INT PSDRV_Escape( DC *dc, INT nEscape, INT cbInput, 
18                   SEGPTR lpInData, SEGPTR lpOutData )
19 {
20     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
21
22     switch(nEscape) {
23
24     case NEXTBAND: {
25         RECT16 *r = MapSL(lpOutData);
26         if(!physDev->job.banding) {
27             physDev->job.banding = TRUE;
28             r->left   = 0;
29             r->top    = 0;
30             r->right  = dc->devCaps->horzRes;
31             r->bottom = dc->devCaps->vertRes;
32             TRACE("NEXTBAND returning %d,%d - %d,%d\n", r->left,
33                   r->top, r->right, r->bottom );
34             return 1;
35         }
36         r->left   = 0;
37         r->top    = 0;
38         r->right  = 0;
39         r->bottom = 0;
40         TRACE("NEXTBAND rect to 0,0 - 0,0\n" );
41         physDev->job.banding = FALSE;
42     }   /* Fall through */
43
44     case NEWFRAME:
45         TRACE("NEWFRAME\n");
46
47         if(!physDev->job.hJob) {
48             FIXME("hJob == 0. Now what?\n");
49             return SP_ERROR;
50         }
51         
52         if(!PSDRV_EndPage( dc ))
53             return SP_ERROR;
54         return 1;
55           
56     case QUERYESCSUPPORT:
57         if(cbInput < 2) {
58             WARN("cbInput < 2 (=%d) for QUERYESCSUPPORT\n", cbInput);
59             return 0;
60         } else {
61             UINT16 num = *(UINT16 *)MapSL(lpInData);
62             TRACE("QUERYESCSUPPORT for %d\n", num);        
63
64             switch(num) {
65             case NEWFRAME:
66             case NEXTBAND:
67             case QUERYESCSUPPORT:
68             case SETABORTPROC:
69             case STARTDOC:
70             case ENDDOC:
71             case GETPHYSPAGESIZE:
72             case GETPRINTINGOFFSET:
73             case GETSCALINGFACTOR:
74             case SETCOPYCOUNT:
75             case GETTECHNOLOGY:
76             case SETLINECAP:
77             case SETLINEJOIN:
78             case SETMITERLIMIT:
79             case SETCHARSET:
80             case EXT_DEVICE_CAPS:
81             case SET_BOUNDS:
82             case PASSTHROUGH:
83             case POSTSCRIPT_PASSTHROUGH:
84                 return TRUE;
85
86             default:
87                 return FALSE;
88             }
89         }
90
91     case SETABORTPROC:
92         TRACE("SETABORTPROC\n");
93         return 1;
94
95     case STARTDOC:
96       {
97         DOCINFOA doc;
98         char *name = NULL;
99         INT16 ret;
100
101         TRACE("STARTDOC\n");
102
103         /* lpInData may not be 0 terminated so we must copy it */
104         if(lpInData) {
105             name = HeapAlloc( GetProcessHeap(), 0, cbInput+1 );
106             memcpy(name, MapSL(lpInData), cbInput);
107             name[cbInput] = '\0';
108         }
109         doc.cbSize = sizeof(doc);
110         doc.lpszDocName = name;
111         doc.lpszOutput = doc.lpszDatatype = NULL;
112         doc.fwType = 0;
113
114         ret = PSDRV_StartDoc(dc, &doc);
115         if(name) HeapFree( GetProcessHeap(), 0, name );
116         if(ret <= 0) return -1;
117         ret = PSDRV_StartPage(dc);
118         if(ret <= 0) return -1;
119         return ret;
120       }
121
122     case ENDDOC:
123         TRACE("ENDDOC\n");
124         return PSDRV_EndDoc( dc );
125
126     case GETPHYSPAGESIZE:
127         {
128             POINT16 *p  = MapSL(lpOutData);
129             
130             p->x = dc->devCaps->horzRes;
131             p->y = dc->devCaps->vertRes;
132             TRACE("GETPHYSPAGESIZE: returning %dx%d\n", p->x, p->y);
133             return 1;
134         }
135
136     case GETPRINTINGOFFSET:
137         {
138             POINT16 *p = MapSL(lpOutData);
139         
140             p->x = p->y = 0;
141             TRACE("GETPRINTINGOFFSET: returning %dx%d\n", p->x, p->y);
142             return 1;
143         }
144       
145     case GETSCALINGFACTOR:
146         {
147             POINT16 *p = MapSL(lpOutData);
148         
149             p->x = p->y = 0;
150             TRACE("GETSCALINGFACTOR: returning %dx%d\n", p->x, p->y);
151             return 1;
152         }
153
154     case SETCOPYCOUNT:
155         {
156             INT16 *NumCopies = MapSL(lpInData);
157             INT16 *ActualCopies = MapSL(lpOutData);
158             if(cbInput != 2) {
159                 WARN("cbInput != 2 (=%d) for SETCOPYCOUNT\n", cbInput);
160                 return 0;
161             }
162             TRACE("SETCOPYCOUNT %d\n", *NumCopies);
163             *ActualCopies = 1;
164             return 1;
165         }
166
167     case GETTECHNOLOGY:
168         {
169             LPSTR p = MapSL(lpOutData);
170             strcpy(p, "PostScript");
171             *(p + strlen(p) + 1) = '\0'; /* 2 '\0's at end of string */
172             return 1;
173         }
174
175     case SETLINECAP:
176         {
177             INT16 newCap = *(INT16 *)MapSL(lpInData);
178             if(cbInput != 2) {
179                 WARN("cbInput != 2 (=%d) for SETLINECAP\n", cbInput);
180                 return 0;
181             }                   
182             TRACE("SETLINECAP %d\n", newCap);
183             return 0;
184         }
185             
186     case SETLINEJOIN:
187         {
188             INT16 newJoin = *(INT16 *)MapSL(lpInData);
189             if(cbInput != 2) {
190                 WARN("cbInput != 2 (=%d) for SETLINEJOIN\n", cbInput);
191                 return 0;
192             }           
193             TRACE("SETLINEJOIN %d\n", newJoin);
194             return 0;
195         }
196
197     case SETMITERLIMIT:
198         {
199             INT16 newLimit = *(INT16 *)MapSL(lpInData);
200             if(cbInput != 2) {
201                 WARN("cbInput != 2 (=%d) for SETMITERLIMIT\n", cbInput);
202                 return 0;
203             }           
204             TRACE("SETMITERLIMIT %d\n", newLimit);
205             return 0;
206         }
207
208     case SETCHARSET: 
209       /* Undocumented escape used by winword6.
210          Switches between ANSI and a special charset.
211          If *lpInData == 1 we require that
212          0x91 is quoteleft
213          0x92 is quoteright
214          0x93 is quotedblleft
215          0x94 is quotedblright
216          0x95 is bullet
217          0x96 is endash
218          0x97 is emdash
219          0xa0 is non break space - yeah right.
220          
221          If *lpInData == 0 we get ANSI.
222          Since there's nothing else there, let's just make these the default
223          anyway and see what happens...
224       */
225         return 1;
226
227     case EXT_DEVICE_CAPS:
228         {
229             UINT16 cap = *(UINT16 *)MapSL(lpInData);
230             if(cbInput != 2) {
231                 WARN("cbInput != 2 (=%d) for EXT_DEVICE_CAPS\n",
232                      cbInput);
233                 return 0;
234             }           
235             TRACE("EXT_DEVICE_CAPS %d\n", cap);
236             return 0;
237         }
238
239     case SET_BOUNDS:
240         {
241             RECT16 *r = MapSL(lpInData);
242             if(cbInput != 8) {
243                 WARN("cbInput != 8 (=%d) for SET_BOUNDS\n", cbInput);
244                 return 0;
245             }           
246             TRACE("SET_BOUNDS (%d,%d) - (%d,%d)\n", r->left, r->top,
247                   r->right, r->bottom);
248             return 0;
249         }
250
251     case PASSTHROUGH:
252     case POSTSCRIPT_PASSTHROUGH:
253         {
254             /* Write directly to spool file, bypassing normal PS driver
255              * processing that is done along with writing PostScript code
256              * to the spool.
257              */
258             return WriteSpool16(physDev->job.hJob, ((char *)lpInData) + 2,
259                                 cbInput);
260         }
261
262     default:
263         FIXME("Unimplemented code 0x%x\n", nEscape);
264         return 0;
265     }
266 }
267
268 /************************************************************************
269  *           PSDRV_StartPage
270  */
271 INT PSDRV_StartPage( DC *dc )
272 {
273     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
274
275     if(!physDev->job.OutOfPage) {
276         FIXME("Already started a page?\n");
277         return 1;
278     }
279     physDev->job.PageNo++;
280     if(!PSDRV_WriteNewPage( dc ))
281         return 0;
282     physDev->job.OutOfPage = FALSE;
283     return 1;
284 }
285
286         
287 /************************************************************************
288  *           PSDRV_EndPage
289  */
290 INT PSDRV_EndPage( DC *dc )
291 {
292     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
293
294     if(physDev->job.OutOfPage) {
295         FIXME("Already ended a page?\n");
296         return 1;
297     }
298     if(!PSDRV_WriteEndPage( dc ))
299         return 0;
300     physDev->job.OutOfPage = TRUE;
301     return 1;
302 }
303
304
305 /************************************************************************
306  *           PSDRV_StartDoc
307  */
308 INT PSDRV_StartDoc( DC *dc, const DOCINFOA *doc )
309 {
310     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
311
312     if(physDev->job.hJob) {
313         FIXME("hJob != 0. Now what?\n");
314         return 0;
315     }
316
317     if(doc->lpszOutput) {
318         HeapFree( PSDRV_Heap, 0, physDev->job.output );
319         physDev->job.output = HEAP_strdupA( PSDRV_Heap, 0, doc->lpszOutput );
320     }
321     physDev->job.hJob = OpenJob16(physDev->job.output,  doc->lpszDocName,
322                                   dc->hSelf);
323     if(!physDev->job.hJob) {
324         WARN("OpenJob failed\n");
325         return 0;
326     }
327     physDev->job.banding = FALSE;
328     physDev->job.OutOfPage = TRUE;
329     physDev->job.PageNo = 0;
330     if(!PSDRV_WriteHeader( dc, doc->lpszDocName ))
331         return 0;
332
333     return physDev->job.hJob;
334 }
335
336
337 /************************************************************************
338  *           PSDRV_EndDoc
339  */
340 INT PSDRV_EndDoc( DC *dc )
341 {
342     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
343
344     if(!physDev->job.hJob) {
345         FIXME("hJob == 0. Now what?\n");
346         return 0;
347     }
348
349     if(!physDev->job.OutOfPage) {
350         WARN("Somebody forgot a EndPage\n");
351         PSDRV_EndPage( dc );
352     }
353     if(!PSDRV_WriteFooter( dc ))
354         return 0;
355
356     if( CloseJob16( physDev->job.hJob ) == SP_ERROR ) {
357         WARN("CloseJob error\n");
358         return 0;
359     }
360     physDev->job.hJob = 0;
361     return 1;
362 }