Authors: Chris Morgan <cmorgan@wpi.edu>, James Abbatiello <abbejy@wpi.edu>
[wine/multimedia.git] / misc / spooler.c
blob56ab4d7d1604d62952dcc7ace79c9571ddba9db7
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 "callback.h"
16 #include "dc.h"
17 #include "debug.h"
18 #include "gdi.h"
19 #include "options.h"
20 #include "wine/winuser16.h"
21 #include "winerror.h"
22 #include "xmalloc.h"
24 DEFAULT_DEBUG_CHANNEL(print)
26 /**********************************************************************
27 * QueryAbort (GDI.155)
29 * Calls the app's AbortProc function if avail.
31 * RETURNS
32 * TRUE if no AbortProc avail or AbortProc wants to continue printing.
33 * FALSE if AbortProc wants to abort printing.
35 BOOL16 WINAPI QueryAbort16(HDC16 hdc, INT16 reserved)
37 DC *dc = DC_GetDCPtr( hdc );
39 if ((!dc) || (!dc->w.lpfnPrint))
40 return TRUE;
41 return Callbacks->CallDrvAbortProc(dc->w.lpfnPrint, hdc, 0);
44 /**********************************************************************
45 * SetAbortProc16 (GDI.381)
48 INT16 WINAPI SetAbortProc16(HDC16 hdc, SEGPTR abrtprc)
50 return Escape16(hdc, SETABORTPROC, 0, abrtprc, (SEGPTR)0);
53 /**********************************************************************
54 * SetAbortProc32 (GDI32.301)
57 INT WINAPI SetAbortProc(HDC hdc, ABORTPROC abrtprc)
59 FIXME(print, "stub\n");
60 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
61 return SP_ERROR;
65 /****************** misc. printer related functions */
68 * The following function should implement a queing system
70 #ifndef HPQ
71 #define HPQ WORD
72 #endif
73 struct hpq
75 struct hpq *next;
76 int tag;
77 int key;
80 static struct hpq *hpqueue;
82 /**********************************************************************
83 * CreatePQ (GDI.230)
86 HPQ WINAPI CreatePQ16(int size)
88 #if 0
89 HGLOBAL16 hpq = 0;
90 WORD tmp_size;
91 LPWORD pPQ;
93 tmp_size = size << 2;
94 if (!(hpq = GlobalAlloc16(GMEM_SHARE|GMEM_MOVEABLE, tmp_size + 8)))
95 return 0xffff;
96 pPQ = GlobalLock16(hpq);
97 *pPQ++ = 0;
98 *pPQ++ = tmp_size;
99 *pPQ++ = 0;
100 *pPQ++ = 0;
101 GlobalUnlock16(hpq);
103 return (HPQ)hpq;
104 #else
105 FIXME(print, "(%d): stub\n",size);
106 return 1;
107 #endif
110 /**********************************************************************
111 * DeletePQ (GDI.235)
114 int WINAPI DeletePQ16(HPQ hPQ)
116 return GlobalFree16((HGLOBAL16)hPQ);
119 /**********************************************************************
120 * ExtractPQ (GDI.232)
123 int WINAPI ExtractPQ16(HPQ hPQ)
125 struct hpq *queue, *prev, *current, *currentPrev;
126 int key = 0, tag = -1;
127 currentPrev = prev = NULL;
128 queue = current = hpqueue;
129 if (current)
130 key = current->key;
132 while (current)
134 currentPrev = current;
135 current = current->next;
136 if (current)
138 if (current->key < key)
140 queue = current;
141 prev = currentPrev;
145 if (queue)
147 tag = queue->tag;
149 if (prev)
150 prev->next = queue->next;
151 else
152 hpqueue = queue->next;
153 free(queue);
156 TRACE(print, "%x got tag %d key %d\n", hPQ, tag, key);
158 return tag;
161 /**********************************************************************
162 * InsertPQ (GDI.233)
165 int WINAPI InsertPQ16(HPQ hPQ, int tag, int key)
167 struct hpq *queueItem = xmalloc(sizeof(struct hpq));
168 queueItem->next = hpqueue;
169 hpqueue = queueItem;
170 queueItem->key = key;
171 queueItem->tag = tag;
173 FIXME(print, "(%x %d %d): stub???\n", hPQ, tag, key);
174 return TRUE;
177 /**********************************************************************
178 * MinPQ (GDI.231)
181 int WINAPI MinPQ16(HPQ hPQ)
183 FIXME(print, "(%x): stub\n", hPQ);
184 return 0;
187 /**********************************************************************
188 * SizePQ (GDI.234)
191 int WINAPI SizePQ16(HPQ hPQ, int sizechange)
193 FIXME(print, "(%x %d): stub\n", hPQ, sizechange);
194 return -1;
200 * The following functions implement part of the spooling process to
201 * print manager. I would like to see wine have a version of print managers
202 * that used LPR/LPD. For simplicity print jobs will be sent to a file for
203 * now.
205 typedef struct PRINTJOB
207 char *pszOutput;
208 char *pszTitle;
209 HDC16 hDC;
210 HANDLE16 hHandle;
211 int nIndex;
212 int fd;
213 } PRINTJOB, *PPRINTJOB;
215 #define MAX_PRINT_JOBS 1
216 #define SP_OK 1
218 PPRINTJOB gPrintJobsTable[MAX_PRINT_JOBS];
221 static PPRINTJOB FindPrintJobFromHandle(HANDLE16 hHandle)
223 return gPrintJobsTable[0];
226 /* TTD Need to do some DOS->UNIX file conversion here */
227 static int CreateSpoolFile(LPSTR pszOutput)
229 int fd=-1;
230 char psCmd[1024];
231 char *psCmdP = psCmd;
233 /* TTD convert the 'output device' into a spool file name */
235 if (pszOutput == NULL || *pszOutput == '\0')
236 return -1;
238 PROFILE_GetWineIniString( "spooler", pszOutput, "", psCmd, sizeof(psCmd) );
239 TRACE(print, "Got printerSpoolCommand '%s' for output device '%s'\n",
240 psCmd, pszOutput);
241 if (!*psCmd)
242 psCmdP = pszOutput;
243 else
245 while (*psCmdP && isspace(*psCmdP))
247 psCmdP++;
249 if (!*psCmdP)
250 return -1;
252 if (*psCmdP == '|')
254 int fds[2];
255 if (pipe(fds))
256 return -1;
257 if (fork() == 0)
259 psCmdP++;
261 TRACE(print, "In child need to exec %s\n",psCmdP);
262 close(0);
263 dup2(fds[0],0);
264 close (fds[1]);
265 system(psCmdP);
266 exit(0);
269 close (fds[0]);
270 fd = fds[1];
271 TRACE(print,"Need to execute a cmnd and pipe the output to it\n");
273 else
275 TRACE(print, "Just assume its a file\n");
277 if ((fd = open(psCmdP, O_CREAT | O_TRUNC | O_WRONLY , 0600)) < 0)
279 ERR(print, "Failed to create spool file %s, errno = %d\n",
280 psCmdP, errno);
283 return fd;
286 static int FreePrintJob(HANDLE16 hJob)
288 int nRet = SP_ERROR;
289 PPRINTJOB pPrintJob;
291 pPrintJob = FindPrintJobFromHandle(hJob);
292 if (pPrintJob != NULL)
294 gPrintJobsTable[pPrintJob->nIndex] = NULL;
295 free(pPrintJob->pszOutput);
296 free(pPrintJob->pszTitle);
297 if (pPrintJob->fd >= 0) close(pPrintJob->fd);
298 free(pPrintJob);
299 nRet = SP_OK;
301 return nRet;
304 /**********************************************************************
305 * OpenJob (GDI.240)
308 HANDLE16 WINAPI OpenJob16(LPSTR lpOutput, LPSTR lpTitle, HDC16 hDC)
310 HANDLE16 hHandle = (HANDLE16)SP_ERROR;
311 PPRINTJOB pPrintJob;
313 TRACE(print, "'%s' '%s' %04x\n", lpOutput, lpTitle, hDC);
315 pPrintJob = gPrintJobsTable[0];
316 if (pPrintJob == NULL)
318 int fd;
320 /* Try an create a spool file */
321 fd = CreateSpoolFile(lpOutput);
322 if (fd >= 0)
324 hHandle = 1;
326 pPrintJob = xmalloc(sizeof(PRINTJOB));
327 memset(pPrintJob, 0, sizeof(PRINTJOB));
329 pPrintJob->pszOutput = strdup(lpOutput);
330 if(lpTitle)
331 pPrintJob->pszTitle = strdup(lpTitle);
332 pPrintJob->hDC = hDC;
333 pPrintJob->fd = fd;
334 pPrintJob->nIndex = 0;
335 pPrintJob->hHandle = hHandle;
336 gPrintJobsTable[pPrintJob->nIndex] = pPrintJob;
339 TRACE(print, "return %04x\n", hHandle);
340 return hHandle;
343 /**********************************************************************
344 * CloseJob (GDI.243)
347 int WINAPI CloseJob16(HANDLE16 hJob)
349 int nRet = SP_ERROR;
350 PPRINTJOB pPrintJob = NULL;
352 TRACE(print, "%04x\n", hJob);
354 pPrintJob = FindPrintJobFromHandle(hJob);
355 if (pPrintJob != NULL)
357 /* Close the spool file */
358 close(pPrintJob->fd);
359 FreePrintJob(hJob);
360 nRet = 1;
362 return nRet;
365 /**********************************************************************
366 * WriteSpool (GDI.241)
369 int WINAPI WriteSpool16(HANDLE16 hJob, LPSTR lpData, WORD cch)
371 int nRet = SP_ERROR;
372 PPRINTJOB pPrintJob = NULL;
374 TRACE(print, "%04x %08lx %04x\n", hJob, (DWORD)lpData, cch);
376 pPrintJob = FindPrintJobFromHandle(hJob);
377 if (pPrintJob != NULL && pPrintJob->fd >= 0 && cch)
379 if (write(pPrintJob->fd, lpData, cch) != cch)
380 nRet = SP_OUTOFDISK;
381 else
382 nRet = cch;
383 if (pPrintJob->hDC == 0) {
384 TRACE(print, "hDC == 0 so no QueryAbort\n");
386 else if (!(QueryAbort16(pPrintJob->hDC, (nRet == SP_OUTOFDISK) ? nRet : 0 )))
388 CloseJob16(hJob); /* printing aborted */
389 nRet = SP_APPABORT;
392 return nRet;
395 /**********************************************************************
396 * WriteDialog (GDI.242)
399 int WINAPI WriteDialog16(HANDLE16 hJob, LPSTR lpMsg, WORD cchMsg)
401 int nRet = 0;
403 TRACE(print, "%04x %04x '%s'\n", hJob, cchMsg, lpMsg);
405 nRet = MessageBox16(0, lpMsg, "Printing Error", MB_OKCANCEL);
406 return nRet;
410 /**********************************************************************
411 * DeleteJob (GDI.244)
414 int WINAPI DeleteJob16(HANDLE16 hJob, WORD wNotUsed)
416 int nRet;
418 TRACE(print, "%04x\n", hJob);
420 nRet = FreePrintJob(hJob);
421 return nRet;
425 * The following two function would allow a page to be sent to the printer
426 * when it has been processed. For simplicity they havn't been implemented.
427 * This means a whole job has to be processed before it is sent to the printer.
430 /**********************************************************************
431 * StartSpoolPage (GDI.246)
434 int WINAPI StartSpoolPage16(HANDLE16 hJob)
436 FIXME(print, "StartSpoolPage GDI.246 unimplemented\n");
437 return 1;
442 /**********************************************************************
443 * EndSpoolPage (GDI.247)
446 int WINAPI EndSpoolPage16(HANDLE16 hJob)
448 FIXME(print, "EndSpoolPage GDI.247 unimplemented\n");
449 return 1;
453 /**********************************************************************
454 * GetSpoolJob (GDI.245)
457 DWORD WINAPI GetSpoolJob16(int nOption, LONG param)
459 DWORD retval = 0;
460 TRACE(print, "In GetSpoolJob param 0x%lx noption %d\n",param, nOption);
461 return retval;