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