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