Fixed cut&paste problem in SETRTS.
[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
13 DEFAULT_DEBUG_CHANNEL(psdrv);
14
15
16 /**********************************************************************
17  *           ExtEscape  (WINEPS.@)
18  */
19 INT PSDRV_ExtEscape( DC *dc, INT nEscape, INT cbInput, LPCVOID in_data,
20                      INT cbOutput, LPVOID out_data )
21 {
22     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
23
24     switch(nEscape)
25     {
26     case QUERYESCSUPPORT:
27         if(cbInput < sizeof(INT))
28         {
29             WARN("cbInput < sizeof(INT) (=%d) for QUERYESCSUPPORT\n", cbInput);
30             return 0;
31         } else {
32             UINT num = *(UINT *)in_data;
33             TRACE("QUERYESCSUPPORT for %d\n", num);
34
35             switch(num) {
36             case NEXTBAND:
37             case SETCOPYCOUNT:
38             case GETTECHNOLOGY:
39             case SETLINECAP:
40             case SETLINEJOIN:
41             case SETMITERLIMIT:
42             case SETCHARSET:
43             case EXT_DEVICE_CAPS:
44             case SET_BOUNDS:
45             case EPSPRINTING:
46             case PASSTHROUGH:
47             case POSTSCRIPT_PASSTHROUGH:
48                 return TRUE;
49
50             default:
51                 return FALSE;
52             }
53         }
54
55     case NEXTBAND:
56     {
57         RECT *r = out_data;
58         if(!physDev->job.banding) {
59             physDev->job.banding = TRUE;
60             r->left   = 0;
61             r->top    = 0;
62             r->right  = physDev->horzRes;
63             r->bottom = physDev->vertRes;
64             TRACE("NEXTBAND returning %d,%d - %d,%d\n", r->left, r->top, r->right, r->bottom );
65             return 1;
66         }
67         r->left   = 0;
68         r->top    = 0;
69         r->right  = 0;
70         r->bottom = 0;
71         TRACE("NEXTBAND rect to 0,0 - 0,0\n" );
72         physDev->job.banding = FALSE;
73         return EndPage( dc->hSelf );
74     }
75
76     case SETCOPYCOUNT:
77         {
78             const INT *NumCopies = in_data;
79             INT *ActualCopies = out_data;
80             if(cbInput != sizeof(INT)) {
81                 WARN("cbInput != sizeof(INT) (=%d) for SETCOPYCOUNT\n", cbInput);
82                 return 0;
83             }
84             TRACE("SETCOPYCOUNT %d\n", *NumCopies);
85             *ActualCopies = 1;
86             return 1;
87         }
88
89     case GETTECHNOLOGY:
90         {
91             LPSTR p = out_data;
92             strcpy(p, "PostScript");
93             *(p + strlen(p) + 1) = '\0'; /* 2 '\0's at end of string */
94             return 1;
95         }
96
97     case SETLINECAP:
98         {
99             INT newCap = *(INT *)in_data;
100             if(cbInput != sizeof(INT)) {
101                 WARN("cbInput != sizeof(INT) (=%d) for SETLINECAP\n", cbInput);
102                 return 0;
103             }
104             TRACE("SETLINECAP %d\n", newCap);
105             return 0;
106         }
107
108     case SETLINEJOIN:
109         {
110             INT newJoin = *(INT *)in_data;
111             if(cbInput != sizeof(INT)) {
112                 WARN("cbInput != sizeof(INT) (=%d) for SETLINEJOIN\n", cbInput);
113                 return 0;
114             }
115             TRACE("SETLINEJOIN %d\n", newJoin);
116             return 0;
117         }
118
119     case SETMITERLIMIT:
120         {
121             INT newLimit = *(INT *)in_data;
122             if(cbInput != sizeof(INT)) {
123                 WARN("cbInput != sizeof(INT) (=%d) for SETMITERLIMIT\n", cbInput);
124                 return 0;
125             }
126             TRACE("SETMITERLIMIT %d\n", newLimit);
127             return 0;
128         }
129
130     case SETCHARSET: 
131       /* Undocumented escape used by winword6.
132          Switches between ANSI and a special charset.
133          If *lpInData == 1 we require that
134          0x91 is quoteleft
135          0x92 is quoteright
136          0x93 is quotedblleft
137          0x94 is quotedblright
138          0x95 is bullet
139          0x96 is endash
140          0x97 is emdash
141          0xa0 is non break space - yeah right.
142          
143          If *lpInData == 0 we get ANSI.
144          Since there's nothing else there, let's just make these the default
145          anyway and see what happens...
146       */
147         return 1;
148
149     case EXT_DEVICE_CAPS:
150         {
151             UINT cap = *(UINT *)in_data;
152             if(cbInput != sizeof(UINT)) {
153                 WARN("cbInput != sizeof(UINT) (=%d) for EXT_DEVICE_CAPS\n", cbInput);
154                 return 0;
155             }
156             TRACE("EXT_DEVICE_CAPS %d\n", cap);
157             return 0;
158         }
159
160     case SET_BOUNDS:
161         {
162             const RECT *r = in_data;
163             if(cbInput != sizeof(RECT)) {
164                 WARN("cbInput != sizeof(RECT) (=%d) for SET_BOUNDS\n", cbInput);
165                 return 0;
166             }
167             TRACE("SET_BOUNDS (%d,%d) - (%d,%d)\n", r->left, r->top,
168                   r->right, r->bottom);
169             return 0;
170         }
171
172     case EPSPRINTING:
173         {
174             UINT epsprint = *(UINT*)in_data;
175             /* FIXME: In this mode we do not need to send page intros and page
176              * ends according to the doc. But I just ignore that detail
177              * for now.
178              */
179             TRACE("EPS Printing support %sable.\n",epsprint?"en":"dis");
180             return 1;
181         }
182     case PASSTHROUGH:
183     case POSTSCRIPT_PASSTHROUGH:
184         {
185             /* Write directly to spool file, bypassing normal PS driver
186              * processing that is done along with writing PostScript code
187              * to the spool.
188              * (Usually we have a WORD before the data counting the size, but
189              * cbInput is just this +2.)
190              */
191             return WriteSpool16(physDev->job.hJob,((char*)in_data)+2,cbInput-2);
192         }
193
194     case GETSETPRINTORIENT:
195         {
196             /* If lpInData is present, it is a 20 byte structure, first 32
197              * bit LONG value is the orientation. if lpInData is NULL, it
198              * returns the current orientation.
199              */
200             FIXME("GETSETPRINTORIENT not implemented (data %p)!\n",in_data);
201             return 1;
202         }
203     default:
204         FIXME("Unimplemented code 0x%x\n", nEscape);
205         return 0;
206     }
207 }
208
209 /************************************************************************
210  *           PSDRV_StartPage
211  */
212 INT PSDRV_StartPage( DC *dc )
213 {
214     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
215
216     if(!physDev->job.OutOfPage) {
217         FIXME("Already started a page?\n");
218         return 1;
219     }
220     physDev->job.PageNo++;
221     if(!PSDRV_WriteNewPage( dc ))
222         return 0;
223     physDev->job.OutOfPage = FALSE;
224     return 1;
225 }
226
227         
228 /************************************************************************
229  *           PSDRV_EndPage
230  */
231 INT PSDRV_EndPage( DC *dc )
232 {
233     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
234
235     if(physDev->job.OutOfPage) {
236         FIXME("Already ended a page?\n");
237         return 1;
238     }
239     if(!PSDRV_WriteEndPage( dc ))
240         return 0;
241     physDev->job.OutOfPage = TRUE;
242     return 1;
243 }
244
245
246 /************************************************************************
247  *           PSDRV_StartDoc
248  */
249 INT PSDRV_StartDoc( DC *dc, const DOCINFOA *doc )
250 {
251     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
252
253     if(physDev->job.hJob) {
254         FIXME("hJob != 0. Now what?\n");
255         return 0;
256     }
257
258     if(doc->lpszOutput) {
259         HeapFree( PSDRV_Heap, 0, physDev->job.output );
260         physDev->job.output = HeapAlloc( PSDRV_Heap, 0, strlen(doc->lpszOutput)+1 );
261         strcpy( physDev->job.output, doc->lpszOutput );
262     }
263     physDev->job.hJob = OpenJob16(physDev->job.output,  doc->lpszDocName,
264                                   dc->hSelf);
265     if(!physDev->job.hJob) {
266         WARN("OpenJob failed\n");
267         return 0;
268     }
269     physDev->job.banding = FALSE;
270     physDev->job.OutOfPage = TRUE;
271     physDev->job.PageNo = 0;
272     if(!PSDRV_WriteHeader( dc, doc->lpszDocName ))
273         return 0;
274
275     return physDev->job.hJob;
276 }
277
278
279 /************************************************************************
280  *           PSDRV_EndDoc
281  */
282 INT PSDRV_EndDoc( DC *dc )
283 {
284     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
285
286     if(!physDev->job.hJob) {
287         FIXME("hJob == 0. Now what?\n");
288         return 0;
289     }
290
291     if(!physDev->job.OutOfPage) {
292         WARN("Somebody forgot a EndPage\n");
293         PSDRV_EndPage( dc );
294     }
295     if(!PSDRV_WriteFooter( dc ))
296         return 0;
297
298     if( CloseJob16( physDev->job.hJob ) == SP_ERROR ) {
299         WARN("CloseJob error\n");
300         return 0;
301     }
302     physDev->job.hJob = 0;
303     return 1;
304 }