Ownerdraw buttons should erase themselves in WM_ERASEBKGND.
[wine.git] / dlls / wineps / escape.c
blobd2afb4c18cee53459d5cc83c96822d9bdeda3ae5
1 /*
2 * PostScript driver Escape function
4 * Copyright 1998 Huw D M Davies
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.
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.
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
20 #include <stdarg.h>
22 #include "windef.h"
23 #include "winbase.h"
24 #include "wingdi.h"
25 #include "wine/wingdi16.h"
26 #include "wine/winuser16.h"
27 #include "wownt32.h"
28 #include "psdrv.h"
29 #include "wine/debug.h"
30 #include "winspool.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
34 /**********************************************************************
35 * ExtEscape (WINEPS.@)
37 INT PSDRV_ExtEscape( PSDRV_PDEVICE *physDev, INT nEscape, INT cbInput, LPCVOID in_data,
38 INT cbOutput, LPVOID out_data )
40 switch(nEscape)
42 case QUERYESCSUPPORT:
43 if(cbInput < sizeof(INT))
45 WARN("cbInput < sizeof(INT) (=%d) for QUERYESCSUPPORT\n", cbInput);
46 return 0;
47 } else {
48 UINT num = *(UINT *)in_data;
49 TRACE("QUERYESCSUPPORT for %d\n", num);
51 switch(num) {
52 case NEXTBAND:
53 case SETCOPYCOUNT:
54 case GETTECHNOLOGY:
55 case SETLINECAP:
56 case SETLINEJOIN:
57 case SETMITERLIMIT:
58 case SETCHARSET:
59 case EXT_DEVICE_CAPS:
60 case SET_BOUNDS:
61 case EPSPRINTING:
62 case POSTSCRIPT_DATA:
63 case PASSTHROUGH:
64 case POSTSCRIPT_PASSTHROUGH:
65 case POSTSCRIPT_IGNORE:
66 case BEGIN_PATH:
67 case CLIP_TO_PATH:
68 case END_PATH:
69 return TRUE;
71 default:
72 return FALSE;
76 case NEXTBAND:
78 RECT *r = out_data;
79 if(!physDev->job.banding) {
80 physDev->job.banding = TRUE;
81 r->left = 0;
82 r->top = 0;
83 r->right = physDev->horzRes;
84 r->bottom = physDev->vertRes;
85 TRACE("NEXTBAND returning %ld,%ld - %ld,%ld\n", r->left, r->top, r->right, r->bottom );
86 return 1;
88 r->left = 0;
89 r->top = 0;
90 r->right = 0;
91 r->bottom = 0;
92 TRACE("NEXTBAND rect to 0,0 - 0,0\n" );
93 physDev->job.banding = FALSE;
94 return EndPage( physDev->hdc );
97 case SETCOPYCOUNT:
99 const INT *NumCopies = in_data;
100 INT *ActualCopies = out_data;
101 if(cbInput != sizeof(INT)) {
102 WARN("cbInput != sizeof(INT) (=%d) for SETCOPYCOUNT\n", cbInput);
103 return 0;
105 TRACE("SETCOPYCOUNT %d\n", *NumCopies);
106 *ActualCopies = 1;
107 return 1;
110 case GETTECHNOLOGY:
112 LPSTR p = out_data;
113 strcpy(p, "PostScript");
114 *(p + strlen(p) + 1) = '\0'; /* 2 '\0's at end of string */
115 return 1;
118 case SETLINECAP:
120 INT newCap = *(INT *)in_data;
121 if(cbInput != sizeof(INT)) {
122 WARN("cbInput != sizeof(INT) (=%d) for SETLINECAP\n", cbInput);
123 return 0;
125 TRACE("SETLINECAP %d\n", newCap);
126 return 0;
129 case SETLINEJOIN:
131 INT newJoin = *(INT *)in_data;
132 if(cbInput != sizeof(INT)) {
133 WARN("cbInput != sizeof(INT) (=%d) for SETLINEJOIN\n", cbInput);
134 return 0;
136 TRACE("SETLINEJOIN %d\n", newJoin);
137 return 0;
140 case SETMITERLIMIT:
142 INT newLimit = *(INT *)in_data;
143 if(cbInput != sizeof(INT)) {
144 WARN("cbInput != sizeof(INT) (=%d) for SETMITERLIMIT\n", cbInput);
145 return 0;
147 TRACE("SETMITERLIMIT %d\n", newLimit);
148 return 0;
151 case SETCHARSET:
152 /* Undocumented escape used by winword6.
153 Switches between ANSI and a special charset.
154 If *lpInData == 1 we require that
155 0x91 is quoteleft
156 0x92 is quoteright
157 0x93 is quotedblleft
158 0x94 is quotedblright
159 0x95 is bullet
160 0x96 is endash
161 0x97 is emdash
162 0xa0 is non break space - yeah right.
164 If *lpInData == 0 we get ANSI.
165 Since there's nothing else there, let's just make these the default
166 anyway and see what happens...
168 return 1;
170 case EXT_DEVICE_CAPS:
172 UINT cap = *(UINT *)in_data;
173 if(cbInput != sizeof(UINT)) {
174 WARN("cbInput != sizeof(UINT) (=%d) for EXT_DEVICE_CAPS\n", cbInput);
175 return 0;
177 TRACE("EXT_DEVICE_CAPS %d\n", cap);
178 return 0;
181 case SET_BOUNDS:
183 const RECT *r = in_data;
184 if(cbInput != sizeof(RECT)) {
185 WARN("cbInput != sizeof(RECT) (=%d) for SET_BOUNDS\n", cbInput);
186 return 0;
188 TRACE("SET_BOUNDS (%ld,%ld) - (%ld,%ld)\n", r->left, r->top,
189 r->right, r->bottom);
190 return 0;
193 case EPSPRINTING:
195 UINT epsprint = *(UINT*)in_data;
196 /* FIXME: In this mode we do not need to send page intros and page
197 * ends according to the doc. But I just ignore that detail
198 * for now.
200 TRACE("EPS Printing support %sable.\n",epsprint?"en":"dis");
201 return 1;
204 case POSTSCRIPT_DATA:
205 case PASSTHROUGH:
206 case POSTSCRIPT_PASSTHROUGH:
208 /* Write directly to spool file, bypassing normal PS driver
209 * processing that is done along with writing PostScript code
210 * to the spool.
211 * We have a WORD before the data counting the size, but
212 * cbInput is just this +2.
213 * However Photoshop 7 has a bug that sets cbInput to 2 less than the
214 * length of the string, rather than 2 more. So we'll use the WORD at
215 * in_data[0] instead.
217 return WriteSpool16(physDev->job.hJob,((char*)in_data)+2,*(WORD*)in_data);
220 case POSTSCRIPT_IGNORE:
222 BOOL ret = physDev->job.quiet;
223 TRACE("POSTSCRIPT_IGNORE %d\n", *(short*)in_data);
224 physDev->job.quiet = *(short*)in_data;
225 return ret;
228 case GETSETPRINTORIENT:
230 /* If lpInData is present, it is a 20 byte structure, first 32
231 * bit LONG value is the orientation. if lpInData is NULL, it
232 * returns the current orientation.
234 FIXME("GETSETPRINTORIENT not implemented (data %p)!\n",in_data);
235 return 1;
237 case BEGIN_PATH:
238 TRACE("BEGIN_PATH\n");
239 if(physDev->pathdepth)
240 FIXME("Nested paths not yet handled\n");
241 return ++physDev->pathdepth;
243 case END_PATH:
245 struct PATH_INFO *info = (struct PATH_INFO*)in_data;
247 TRACE("END_PATH\n");
248 if(!physDev->pathdepth) {
249 ERR("END_PATH called without a BEIGN_PATH\n");
250 return -1;
252 TRACE("RenderMode = %d, FillMode = %d, BkMode = %d\n",
253 info->RenderMode, info->FillMode, info->BkMode);
254 switch(info->RenderMode) {
255 case RENDERMODE_NO_DISPLAY:
256 PSDRV_WriteClosePath(physDev); /* not sure if this is necessary, but it can't hurt */
257 break;
258 case RENDERMODE_OPEN:
259 case RENDERMODE_CLOSED:
260 default:
261 FIXME("END_PATH: RenderMode %d, not yet supported\n", info->RenderMode);
262 break;
264 return --physDev->pathdepth;
267 case CLIP_TO_PATH:
269 WORD mode = *(WORD*)in_data;
271 switch(mode) {
272 case CLIP_SAVE:
273 TRACE("CLIP_TO_PATH: CLIP_SAVE\n");
274 PSDRV_WriteGSave(physDev);
275 return 1;
276 case CLIP_RESTORE:
277 TRACE("CLIP_TO_PATH: CLIP_RESTORE\n");
278 PSDRV_WriteGRestore(physDev);
279 return 1;
280 case CLIP_INCLUSIVE:
281 TRACE("CLIP_TO_PATH: CLIP_INCLUSIVE\n");
282 /* FIXME to clip or eoclip ? (see PATH_INFO.FillMode) */
283 PSDRV_WriteClip(physDev);
284 return 1;
285 case CLIP_EXCLUSIVE:
286 FIXME("CLIP_EXCLUSIVE: not implemented\n");
287 return 0;
288 default:
289 FIXME("Unknown CLIP_TO_PATH mode %d\n", mode);
290 return 0;
292 return 0;
294 default:
295 FIXME("Unimplemented code 0x%x\n", nEscape);
296 return 0;
300 /************************************************************************
301 * PSDRV_StartPage
303 INT PSDRV_StartPage( PSDRV_PDEVICE *physDev )
305 if(!physDev->job.OutOfPage) {
306 FIXME("Already started a page?\n");
307 return 1;
309 physDev->job.PageNo++;
310 if(!PSDRV_WriteNewPage( physDev ))
311 return 0;
312 physDev->job.OutOfPage = FALSE;
313 return 1;
317 /************************************************************************
318 * PSDRV_EndPage
320 INT PSDRV_EndPage( PSDRV_PDEVICE *physDev )
322 if(physDev->job.OutOfPage) {
323 FIXME("Already ended a page?\n");
324 return 1;
326 if(!PSDRV_WriteEndPage( physDev ))
327 return 0;
328 PSDRV_EmptyDownloadList(physDev, FALSE);
329 physDev->job.OutOfPage = TRUE;
330 return 1;
334 /************************************************************************
335 * PSDRV_StartDoc
337 INT PSDRV_StartDoc( PSDRV_PDEVICE *physDev, const DOCINFOA *doc )
339 LPCSTR output = "LPT1:";
340 BYTE buf[300];
341 HANDLE hprn = INVALID_HANDLE_VALUE;
342 PRINTER_INFO_5A *pi5 = (PRINTER_INFO_5A*)buf;
343 DWORD needed;
345 if(physDev->job.hJob) {
346 FIXME("hJob != 0. Now what?\n");
347 return 0;
350 if(doc->lpszOutput)
351 output = doc->lpszOutput;
352 else if(physDev->job.output)
353 output = physDev->job.output;
354 else {
355 if(OpenPrinterA(physDev->pi->FriendlyName, &hprn, NULL) &&
356 GetPrinterA(hprn, 5, buf, sizeof(buf), &needed)) {
357 output = pi5->pPortName;
359 if(hprn != INVALID_HANDLE_VALUE)
360 ClosePrinter(hprn);
363 physDev->job.hJob = OpenJob16(output, doc->lpszDocName, HDC_16(physDev->hdc) );
364 if(!physDev->job.hJob) {
365 WARN("OpenJob failed\n");
366 return 0;
368 physDev->job.banding = FALSE;
369 physDev->job.OutOfPage = TRUE;
370 physDev->job.PageNo = 0;
371 if(!PSDRV_WriteHeader( physDev, doc->lpszDocName ))
372 return 0;
374 return physDev->job.hJob;
378 /************************************************************************
379 * PSDRV_EndDoc
381 INT PSDRV_EndDoc( PSDRV_PDEVICE *physDev )
383 INT ret = 1;
384 if(!physDev->job.hJob) {
385 FIXME("hJob == 0. Now what?\n");
386 return 0;
389 if(!physDev->job.OutOfPage) {
390 WARN("Somebody forgot a EndPage\n");
391 PSDRV_EndPage( physDev );
393 PSDRV_WriteFooter( physDev );
395 if( CloseJob16( physDev->job.hJob ) == SP_ERROR ) {
396 WARN("CloseJob error\n");
397 ret = 0;
399 physDev->job.hJob = 0;
400 return ret;