Rounds to the lowest integer, not the nearest.
[wine.git] / graphics / psdrv / escape.c
blobca38b45d500ba9732e46f36951de8638baa6d620
1 /*
2 * PostScript driver Escape function
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"
12 DEFAULT_DEBUG_CHANNEL(psdrv)
15 INT PSDRV_Escape( DC *dc, INT nEscape, INT cbInput,
16 SEGPTR lpInData, SEGPTR lpOutData )
18 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
20 switch(nEscape) {
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;
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 */
37 case NEWFRAME:
38 TRACE("NEWFRAME\n");
40 if(!physDev->job.hJob) {
41 FIXME("hJob == 0. Now what?\n");
42 return SP_ERROR;
45 if(!PSDRV_EndPage( dc ))
46 return SP_ERROR;
47 return 1;
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);
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;
77 default:
78 return FALSE;
82 case SETABORTPROC:
83 TRACE("SETABORTPROC\n");
84 return 1;
86 case STARTDOC:
88 DOCINFOA doc;
89 char *name = NULL;
90 INT16 ret;
92 TRACE("STARTDOC\n");
94 /* lpInData may not be 0 terminated so we must copy it */
95 if(lpInData) {
96 name = HeapAlloc( GetProcessHeap(), 0, cbInput+1 );
97 memcpy(name, PTR_SEG_TO_LIN(lpInData), cbInput);
98 name[cbInput] = '\0';
100 doc.cbSize = sizeof(doc);
101 doc.lpszDocName = name;
102 doc.lpszOutput = doc.lpszDatatype = NULL;
103 doc.fwType = 0;
105 ret = PSDRV_StartDoc(dc, &doc);
106 if(name) HeapFree( GetProcessHeap(), 0, name );
107 if(ret <= 0) return -1;
108 ret = PSDRV_StartPage(dc);
109 if(ret <= 0) return -1;
110 return ret;
113 case ENDDOC:
114 TRACE("ENDDOC\n");
115 return PSDRV_EndDoc( dc );
117 case GETPHYSPAGESIZE:
119 POINT16 *p = (POINT16 *)PTR_SEG_TO_LIN(lpOutData);
121 p->x = dc->w.devCaps->horzRes;
122 p->y = dc->w.devCaps->vertRes;
123 TRACE("GETPHYSPAGESIZE: returning %dx%d\n", p->x, p->y);
124 return 1;
127 case GETPRINTINGOFFSET:
129 POINT16 *p = (POINT16 *)PTR_SEG_TO_LIN(lpOutData);
131 p->x = p->y = 0;
132 TRACE("GETPRINTINGOFFSET: returning %dx%d\n", p->x, p->y);
133 return 1;
136 case GETSCALINGFACTOR:
138 POINT16 *p = (POINT16 *)PTR_SEG_TO_LIN(lpOutData);
140 p->x = p->y = 0;
141 TRACE("GETSCALINGFACTOR: returning %dx%d\n", p->x, p->y);
142 return 1;
145 case SETCOPYCOUNT:
147 INT16 *NumCopies = (INT16 *)PTR_SEG_TO_LIN(lpInData);
148 INT16 *ActualCopies = (INT16 *)PTR_SEG_TO_LIN(lpOutData);
149 if(cbInput != 2) {
150 WARN("cbInput != 2 (=%d) for SETCOPYCOUNT\n", cbInput);
151 return 0;
153 TRACE("SETCOPYCOUNT %d\n", *NumCopies);
154 *ActualCopies = 1;
155 return 1;
158 case GETTECHNOLOGY:
160 LPSTR p = (LPSTR)PTR_SEG_TO_LIN(lpOutData);
161 strcpy(p, "PostScript");
162 *(p + strlen(p) + 1) = '\0'; /* 2 '\0's at end of string */
163 return 1;
166 case SETLINECAP:
168 INT16 newCap = *(INT16 *)PTR_SEG_TO_LIN(lpInData);
169 if(cbInput != 2) {
170 WARN("cbInput != 2 (=%d) for SETLINECAP\n", cbInput);
171 return 0;
173 TRACE("SETLINECAP %d\n", newCap);
174 return 0;
177 case SETLINEJOIN:
179 INT16 newJoin = *(INT16 *)PTR_SEG_TO_LIN(lpInData);
180 if(cbInput != 2) {
181 WARN("cbInput != 2 (=%d) for SETLINEJOIN\n", cbInput);
182 return 0;
184 TRACE("SETLINEJOIN %d\n", newJoin);
185 return 0;
188 case SETMITERLIMIT:
190 INT16 newLimit = *(INT16 *)PTR_SEG_TO_LIN(lpInData);
191 if(cbInput != 2) {
192 WARN("cbInput != 2 (=%d) for SETMITERLIMIT\n", cbInput);
193 return 0;
195 TRACE("SETMITERLIMIT %d\n", newLimit);
196 return 0;
199 case SETCHARSET:
200 /* Undocumented escape used by winword6.
201 Switches between ANSI and a special charset.
202 If *lpInData == 1 we require that
203 0x91 is quoteleft
204 0x92 is quoteright
205 0x93 is quotedblleft
206 0x94 is quotedblright
207 0x95 is bullet
208 0x96 is endash
209 0x97 is emdash
210 0xa0 is non break space - yeah right.
212 If *lpInData == 0 we get ANSI.
213 Since there's nothing else there, let's just make these the default
214 anyway and see what happens...
216 return 1;
218 case EXT_DEVICE_CAPS:
220 UINT16 cap = *(UINT16 *)PTR_SEG_TO_LIN(lpInData);
221 if(cbInput != 2) {
222 WARN("cbInput != 2 (=%d) for EXT_DEVICE_CAPS\n",
223 cbInput);
224 return 0;
226 TRACE("EXT_DEVICE_CAPS %d\n", cap);
227 return 0;
230 case SET_BOUNDS:
232 RECT16 *r = (RECT16 *)PTR_SEG_TO_LIN(lpInData);
233 if(cbInput != 8) {
234 WARN("cbInput != 8 (=%d) for SET_BOUNDS\n", cbInput);
235 return 0;
237 TRACE("SET_BOUNDS (%d,%d) - (%d,%d)\n", r->left, r->top,
238 r->right, r->bottom);
239 return 0;
242 default:
243 FIXME("Unimplemented code 0x%x\n", nEscape);
244 return 0;
248 /************************************************************************
249 * PSDRV_StartPage
251 INT PSDRV_StartPage( DC *dc )
253 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
255 if(!physDev->job.OutOfPage) {
256 FIXME("Already started a page?\n");
257 return 1;
259 physDev->job.PageNo++;
260 if(!PSDRV_WriteNewPage( dc ))
261 return 0;
262 physDev->job.OutOfPage = FALSE;
263 return 1;
267 /************************************************************************
268 * PSDRV_EndPage
270 INT PSDRV_EndPage( DC *dc )
272 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
274 if(physDev->job.OutOfPage) {
275 FIXME("Already ended a page?\n");
276 return 1;
278 if(!PSDRV_WriteEndPage( dc ))
279 return 0;
280 physDev->job.OutOfPage = TRUE;
281 return 1;
285 /************************************************************************
286 * PSDRV_StartDoc
288 INT PSDRV_StartDoc( DC *dc, const DOCINFOA *doc )
290 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
292 if(physDev->job.hJob) {
293 FIXME("hJob != 0. Now what?\n");
294 return 0;
297 if(doc->lpszOutput) {
298 HeapFree( PSDRV_Heap, 0, physDev->job.output );
299 physDev->job.output = HEAP_strdupA( PSDRV_Heap, 0, doc->lpszOutput );
301 physDev->job.hJob = OpenJob16(physDev->job.output, doc->lpszDocName,
302 dc->hSelf);
303 if(!physDev->job.hJob) {
304 WARN("OpenJob failed\n");
305 return 0;
307 physDev->job.banding = FALSE;
308 physDev->job.OutOfPage = TRUE;
309 physDev->job.PageNo = 0;
310 if(!PSDRV_WriteHeader( dc, doc->lpszDocName ))
311 return 0;
313 return physDev->job.hJob;
317 /************************************************************************
318 * PSDRV_EndDoc
320 INT PSDRV_EndDoc( DC *dc )
322 PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
324 if(!physDev->job.hJob) {
325 FIXME("hJob == 0. Now what?\n");
326 return 0;
329 if(!physDev->job.OutOfPage) {
330 WARN("Somebody forgot a EndPage\n");
331 PSDRV_EndPage( dc );
333 if(!PSDRV_WriteFooter( dc ))
334 return 0;
336 if( CloseJob16( physDev->job.hJob ) == SP_ERROR ) {
337 WARN("CloseJob error\n");
338 return 0;
340 physDev->job.hJob = 0;
341 return 1;