ANSI C fixes.
[wine/testsucceed.git] / misc / spooler.c
blobdbddc2940eb0470edb82dfcd984324ff7b388f68
1 /*
2 * Print spooler and PQ functions
4 * Copyright 1996 John Harvey
5 * 1998 Huw Davies
7 */
9 #include <ctype.h>
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include "winbase.h"
16 #include "wine/winuser16.h"
17 #include "callback.h"
18 #include "dc.h"
19 #include "debug.h"
20 #include "gdi.h"
21 #include "options.h"
22 #include "winerror.h"
23 #include "xmalloc.h"
25 DEFAULT_DEBUG_CHANNEL(print)
27 /**********************************************************************
28 * QueryAbort (GDI.155)
30 * Calls the app's AbortProc function if avail.
32 * RETURNS
33 * TRUE if no AbortProc avail or AbortProc wants to continue printing.
34 * FALSE if AbortProc wants to abort printing.
36 BOOL16 WINAPI QueryAbort16(HDC16 hdc, INT16 reserved)
38 DC *dc = DC_GetDCPtr( hdc );
40 if ((!dc) || (!dc->w.lpfnPrint))
41 return TRUE;
42 return Callbacks->CallDrvAbortProc(dc->w.lpfnPrint, hdc, 0);
45 /**********************************************************************
46 * SetAbortProc16 (GDI.381)
49 INT16 WINAPI SetAbortProc16(HDC16 hdc, SEGPTR abrtprc)
51 return Escape16(hdc, SETABORTPROC, 0, abrtprc, (SEGPTR)0);
54 /**********************************************************************
55 * SetAbortProc32 (GDI32.301)
58 INT WINAPI SetAbortProc(HDC hdc, ABORTPROC abrtprc)
60 FIXME(print, "stub\n");
61 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
62 return SP_ERROR;
66 /****************** misc. printer related functions */
69 * The following function should implement a queing system
71 #ifndef HPQ
72 #define HPQ WORD
73 #endif
74 struct hpq
76 struct hpq *next;
77 int tag;
78 int key;
81 static struct hpq *hpqueue;
83 /**********************************************************************
84 * CreatePQ (GDI.230)
87 HPQ WINAPI CreatePQ16(int size)
89 #if 0
90 HGLOBAL16 hpq = 0;
91 WORD tmp_size;
92 LPWORD pPQ;
94 tmp_size = size << 2;
95 if (!(hpq = GlobalAlloc16(GMEM_SHARE|GMEM_MOVEABLE, tmp_size + 8)))
96 return 0xffff;
97 pPQ = GlobalLock16(hpq);
98 *pPQ++ = 0;
99 *pPQ++ = tmp_size;
100 *pPQ++ = 0;
101 *pPQ++ = 0;
102 GlobalUnlock16(hpq);
104 return (HPQ)hpq;
105 #else
106 FIXME(print, "(%d): stub\n",size);
107 return 1;
108 #endif
111 /**********************************************************************
112 * DeletePQ (GDI.235)
115 int WINAPI DeletePQ16(HPQ hPQ)
117 return GlobalFree16((HGLOBAL16)hPQ);
120 /**********************************************************************
121 * ExtractPQ (GDI.232)
124 int WINAPI ExtractPQ16(HPQ hPQ)
126 struct hpq *queue, *prev, *current, *currentPrev;
127 int key = 0, tag = -1;
128 currentPrev = prev = NULL;
129 queue = current = hpqueue;
130 if (current)
131 key = current->key;
133 while (current)
135 currentPrev = current;
136 current = current->next;
137 if (current)
139 if (current->key < key)
141 queue = current;
142 prev = currentPrev;
146 if (queue)
148 tag = queue->tag;
150 if (prev)
151 prev->next = queue->next;
152 else
153 hpqueue = queue->next;
154 free(queue);
157 TRACE(print, "%x got tag %d key %d\n", hPQ, tag, key);
159 return tag;
162 /**********************************************************************
163 * InsertPQ (GDI.233)
166 int WINAPI InsertPQ16(HPQ hPQ, int tag, int key)
168 struct hpq *queueItem = xmalloc(sizeof(struct hpq));
169 queueItem->next = hpqueue;
170 hpqueue = queueItem;
171 queueItem->key = key;
172 queueItem->tag = tag;
174 FIXME(print, "(%x %d %d): stub???\n", hPQ, tag, key);
175 return TRUE;
178 /**********************************************************************
179 * MinPQ (GDI.231)
182 int WINAPI MinPQ16(HPQ hPQ)
184 FIXME(print, "(%x): stub\n", hPQ);
185 return 0;
188 /**********************************************************************
189 * SizePQ (GDI.234)
192 int WINAPI SizePQ16(HPQ hPQ, int sizechange)
194 FIXME(print, "(%x %d): stub\n", hPQ, sizechange);
195 return -1;
201 * The following functions implement part of the spooling process to
202 * print manager. I would like to see wine have a version of print managers
203 * that used LPR/LPD. For simplicity print jobs will be sent to a file for
204 * now.
206 typedef struct PRINTJOB
208 char *pszOutput;
209 char *pszTitle;
210 HDC16 hDC;
211 HANDLE16 hHandle;
212 int nIndex;
213 int fd;
214 } PRINTJOB, *PPRINTJOB;
216 #define MAX_PRINT_JOBS 1
217 #define SP_OK 1
219 PPRINTJOB gPrintJobsTable[MAX_PRINT_JOBS];
222 static PPRINTJOB FindPrintJobFromHandle(HANDLE16 hHandle)
224 return gPrintJobsTable[0];
227 /* TTD Need to do some DOS->UNIX file conversion here */
228 static int CreateSpoolFile(LPSTR pszOutput)
230 int fd=-1;
231 char psCmd[1024];
232 char *psCmdP = psCmd;
234 /* TTD convert the 'output device' into a spool file name */
236 if (pszOutput == NULL || *pszOutput == '\0')
237 return -1;
239 PROFILE_GetWineIniString( "spooler", pszOutput, "", psCmd, sizeof(psCmd) );
240 TRACE(print, "Got printerSpoolCommand '%s' for output device '%s'\n",
241 psCmd, pszOutput);
242 if (!*psCmd)
243 psCmdP = pszOutput;
244 else
246 while (*psCmdP && isspace(*psCmdP))
248 psCmdP++;
250 if (!*psCmdP)
251 return -1;
253 if (*psCmdP == '|')
255 int fds[2];
256 if (pipe(fds))
257 return -1;
258 if (fork() == 0)
260 psCmdP++;
262 TRACE(print, "In child need to exec %s\n",psCmdP);
263 close(0);
264 dup2(fds[0],0);
265 close (fds[1]);
266 system(psCmdP);
267 exit(0);
270 close (fds[0]);
271 fd = fds[1];
272 TRACE(print,"Need to execute a cmnd and pipe the output to it\n");
274 else
276 TRACE(print, "Just assume its a file\n");
278 if ((fd = open(psCmdP, O_CREAT | O_TRUNC | O_WRONLY , 0600)) < 0)
280 ERR(print, "Failed to create spool file %s, errno = %d\n",
281 psCmdP, errno);
284 return fd;
287 static int FreePrintJob(HANDLE16 hJob)
289 int nRet = SP_ERROR;
290 PPRINTJOB pPrintJob;
292 pPrintJob = FindPrintJobFromHandle(hJob);
293 if (pPrintJob != NULL)
295 gPrintJobsTable[pPrintJob->nIndex] = NULL;
296 free(pPrintJob->pszOutput);
297 free(pPrintJob->pszTitle);
298 if (pPrintJob->fd >= 0) close(pPrintJob->fd);
299 free(pPrintJob);
300 nRet = SP_OK;
302 return nRet;
305 /**********************************************************************
306 * OpenJob (GDI.240)
309 HANDLE16 WINAPI OpenJob16(LPSTR lpOutput, LPSTR lpTitle, HDC16 hDC)
311 HANDLE16 hHandle = (HANDLE16)SP_ERROR;
312 PPRINTJOB pPrintJob;
314 TRACE(print, "'%s' '%s' %04x\n", lpOutput, lpTitle, hDC);
316 pPrintJob = gPrintJobsTable[0];
317 if (pPrintJob == NULL)
319 int fd;
321 /* Try an create a spool file */
322 fd = CreateSpoolFile(lpOutput);
323 if (fd >= 0)
325 hHandle = 1;
327 pPrintJob = xmalloc(sizeof(PRINTJOB));
328 memset(pPrintJob, 0, sizeof(PRINTJOB));
330 pPrintJob->pszOutput = strdup(lpOutput);
331 if(lpTitle)
332 pPrintJob->pszTitle = strdup(lpTitle);
333 pPrintJob->hDC = hDC;
334 pPrintJob->fd = fd;
335 pPrintJob->nIndex = 0;
336 pPrintJob->hHandle = hHandle;
337 gPrintJobsTable[pPrintJob->nIndex] = pPrintJob;
340 TRACE(print, "return %04x\n", hHandle);
341 return hHandle;
344 /**********************************************************************
345 * CloseJob (GDI.243)
348 int WINAPI CloseJob16(HANDLE16 hJob)
350 int nRet = SP_ERROR;
351 PPRINTJOB pPrintJob = NULL;
353 TRACE(print, "%04x\n", hJob);
355 pPrintJob = FindPrintJobFromHandle(hJob);
356 if (pPrintJob != NULL)
358 /* Close the spool file */
359 close(pPrintJob->fd);
360 FreePrintJob(hJob);
361 nRet = 1;
363 return nRet;
366 /**********************************************************************
367 * WriteSpool (GDI.241)
370 int WINAPI WriteSpool16(HANDLE16 hJob, LPSTR lpData, WORD cch)
372 int nRet = SP_ERROR;
373 PPRINTJOB pPrintJob = NULL;
375 TRACE(print, "%04x %08lx %04x\n", hJob, (DWORD)lpData, cch);
377 pPrintJob = FindPrintJobFromHandle(hJob);
378 if (pPrintJob != NULL && pPrintJob->fd >= 0 && cch)
380 if (write(pPrintJob->fd, lpData, cch) != cch)
381 nRet = SP_OUTOFDISK;
382 else
383 nRet = cch;
384 if (pPrintJob->hDC == 0) {
385 TRACE(print, "hDC == 0 so no QueryAbort\n");
387 else if (!(QueryAbort16(pPrintJob->hDC, (nRet == SP_OUTOFDISK) ? nRet : 0 )))
389 CloseJob16(hJob); /* printing aborted */
390 nRet = SP_APPABORT;
393 return nRet;
396 /**********************************************************************
397 * WriteDialog (GDI.242)
400 int WINAPI WriteDialog16(HANDLE16 hJob, LPSTR lpMsg, WORD cchMsg)
402 int nRet = 0;
404 TRACE(print, "%04x %04x '%s'\n", hJob, cchMsg, lpMsg);
406 nRet = MessageBox16(0, lpMsg, "Printing Error", MB_OKCANCEL);
407 return nRet;
411 /**********************************************************************
412 * DeleteJob (GDI.244)
415 int WINAPI DeleteJob16(HANDLE16 hJob, WORD wNotUsed)
417 int nRet;
419 TRACE(print, "%04x\n", hJob);
421 nRet = FreePrintJob(hJob);
422 return nRet;
426 * The following two function would allow a page to be sent to the printer
427 * when it has been processed. For simplicity they havn't been implemented.
428 * This means a whole job has to be processed before it is sent to the printer.
431 /**********************************************************************
432 * StartSpoolPage (GDI.246)
435 int WINAPI StartSpoolPage16(HANDLE16 hJob)
437 FIXME(print, "StartSpoolPage GDI.246 unimplemented\n");
438 return 1;
443 /**********************************************************************
444 * EndSpoolPage (GDI.247)
447 int WINAPI EndSpoolPage16(HANDLE16 hJob)
449 FIXME(print, "EndSpoolPage GDI.247 unimplemented\n");
450 return 1;
454 /**********************************************************************
455 * GetSpoolJob (GDI.245)
458 DWORD WINAPI GetSpoolJob16(int nOption, LONG param)
460 DWORD retval = 0;
461 TRACE(print, "In GetSpoolJob param 0x%lx noption %d\n",param, nOption);
462 return retval;