Fixed activation/Focus message order problem when creating a new HWND.
[wine/multimedia.git] / misc / spooler.c
blob0823eb5871547f5dd25b5cc3efa1802693f90e03
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 "windows.h"
21 #include "xmalloc.h"
23 /**********************************************************************
24 * QueryAbort (GDI.155)
26 * Calls the app's AbortProc function if avail.
28 * RETURNS
29 * TRUE if no AbortProc avail or AbortProc wants to continue printing.
30 * FALSE if AbortProc wants to abort printing.
32 BOOL16 WINAPI QueryAbort(HDC16 hdc, INT16 reserved)
34 DC *dc = DC_GetDCPtr( hdc );
36 if ((!dc) || (!dc->w.lpfnPrint))
37 return TRUE;
38 return Callbacks->CallDrvAbortProc(dc->w.lpfnPrint, hdc, 0);
41 /**********************************************************************
42 * SetAbortProc (GDI.381)
45 INT16 WINAPI SetAbortProc(HDC16 hdc, FARPROC16 abrtprc)
47 DC *dc = DC_GetDCPtr( hdc );
49 if (dc) {
50 dc->w.lpfnPrint = abrtprc;
51 return 1;
53 return -1;
56 /****************** misc. printer related functions */
59 * The following function should implement a queing system
61 #ifndef HPQ
62 #define HPQ WORD
63 #endif
64 struct hpq
66 struct hpq *next;
67 int tag;
68 int key;
71 static struct hpq *hpqueue;
73 /**********************************************************************
74 * CreatePQ (GDI.230)
77 HPQ WINAPI CreatePQ(int size)
79 #if 0
80 HGLOBAL16 hpq = 0;
81 WORD tmp_size;
82 LPWORD pPQ;
84 tmp_size = size << 2;
85 if (!(hpq = GlobalAlloc16(GMEM_SHARE|GMEM_MOVEABLE, tmp_size + 8)))
86 return 0xffff;
87 pPQ = GlobalLock16(hpq);
88 *pPQ++ = 0;
89 *pPQ++ = tmp_size;
90 *pPQ++ = 0;
91 *pPQ++ = 0;
92 GlobalUnlock16(hpq);
94 return (HPQ)hpq;
95 #else
96 FIXME(print, "(%d): stub\n",size);
97 return 1;
98 #endif
101 /**********************************************************************
102 * DeletePQ (GDI.235)
105 int WINAPI DeletePQ(HPQ hPQ)
107 return GlobalFree16((HGLOBAL16)hPQ);
110 /**********************************************************************
111 * ExtractPQ (GDI.232)
114 int WINAPI ExtractPQ(HPQ hPQ)
116 struct hpq *queue, *prev, *current, *currentPrev;
117 int key = 0, tag = -1;
118 currentPrev = prev = NULL;
119 queue = current = hpqueue;
120 if (current)
121 key = current->key;
123 while (current)
125 currentPrev = current;
126 current = current->next;
127 if (current)
129 if (current->key < key)
131 queue = current;
132 prev = currentPrev;
136 if (queue)
138 tag = queue->tag;
140 if (prev)
141 prev->next = queue->next;
142 else
143 hpqueue = queue->next;
144 free(queue);
147 TRACE(print, "%x got tag %d key %d\n", hPQ, tag, key);
149 return tag;
152 /**********************************************************************
153 * InsertPQ (GDI.233)
156 int WINAPI InsertPQ(HPQ hPQ, int tag, int key)
158 struct hpq *queueItem = xmalloc(sizeof(struct hpq));
159 queueItem->next = hpqueue;
160 hpqueue = queueItem;
161 queueItem->key = key;
162 queueItem->tag = tag;
164 FIXME(print, "(%x %d %d): stub???\n", hPQ, tag, key);
165 return TRUE;
168 /**********************************************************************
169 * MinPQ (GDI.231)
172 int WINAPI MinPQ(HPQ hPQ)
174 FIXME(print, "(%x): stub\n", hPQ);
175 return 0;
178 /**********************************************************************
179 * SizePQ (GDI.234)
182 int WINAPI SizePQ(HPQ hPQ, int sizechange)
184 FIXME(print, "(%x %d): stub\n", hPQ, sizechange);
185 return -1;
191 * The following functions implement part of the spooling process to
192 * print manager. I would like to see wine have a version of print managers
193 * that used LPR/LPD. For simplicity print jobs will be sent to a file for
194 * now.
196 typedef struct PRINTJOB
198 char *pszOutput;
199 char *pszTitle;
200 HDC16 hDC;
201 HANDLE16 hHandle;
202 int nIndex;
203 int fd;
204 } PRINTJOB, *PPRINTJOB;
206 #define MAX_PRINT_JOBS 1
207 #define SP_OK 1
209 PPRINTJOB gPrintJobsTable[MAX_PRINT_JOBS];
212 static PPRINTJOB FindPrintJobFromHandle(HANDLE16 hHandle)
214 return gPrintJobsTable[0];
217 /* TTD Need to do some DOS->UNIX file conversion here */
218 static int CreateSpoolFile(LPSTR pszOutput)
220 int fd=-1;
221 char psCmd[1024];
222 char *psCmdP = psCmd;
224 /* TTD convert the 'output device' into a spool file name */
226 if (pszOutput == NULL || *pszOutput == '\0')
227 return -1;
229 PROFILE_GetWineIniString( "spooler", pszOutput, "", psCmd, sizeof(psCmd) );
230 TRACE(print, "Got printerSpoolCommand '%s' for output device '%s'\n",
231 psCmd, pszOutput);
232 if (!*psCmd)
233 psCmdP = pszOutput;
234 else
236 while (*psCmdP && isspace(*psCmdP))
238 psCmdP++;
240 if (!*psCmdP)
241 return -1;
243 if (*psCmdP == '|')
245 int fds[2];
246 if (pipe(fds))
247 return -1;
248 if (fork() == 0)
250 psCmdP++;
252 TRACE(print, "In child need to exec %s\n",psCmdP);
253 close(0);
254 dup2(fds[0],0);
255 close (fds[1]);
256 system(psCmdP);
257 exit(0);
260 close (fds[0]);
261 fd = fds[1];
262 TRACE(print,"Need to execute a cmnd and pipe the output to it\n");
264 else
266 TRACE(print, "Just assume its a file\n");
268 if ((fd = open(psCmdP, O_CREAT | O_TRUNC | O_WRONLY , 0600)) < 0)
270 ERR(print, "Failed to create spool file %s, errno = %d\n",
271 psCmdP, errno);
274 return fd;
277 static int FreePrintJob(HANDLE16 hJob)
279 int nRet = SP_ERROR;
280 PPRINTJOB pPrintJob;
282 pPrintJob = FindPrintJobFromHandle(hJob);
283 if (pPrintJob != NULL)
285 gPrintJobsTable[pPrintJob->nIndex] = NULL;
286 free(pPrintJob->pszOutput);
287 free(pPrintJob->pszTitle);
288 if (pPrintJob->fd >= 0) close(pPrintJob->fd);
289 free(pPrintJob);
290 nRet = SP_OK;
292 return nRet;
295 /**********************************************************************
296 * OpenJob (GDI.240)
299 HANDLE16 WINAPI OpenJob(LPSTR lpOutput, LPSTR lpTitle, HDC16 hDC)
301 HANDLE16 hHandle = (HANDLE16)SP_ERROR;
302 PPRINTJOB pPrintJob;
304 TRACE(print, "'%s' '%s' %04x\n", lpOutput, lpTitle, hDC);
306 pPrintJob = gPrintJobsTable[0];
307 if (pPrintJob == NULL)
309 int fd;
311 /* Try an create a spool file */
312 fd = CreateSpoolFile(lpOutput);
313 if (fd >= 0)
315 hHandle = 1;
317 pPrintJob = xmalloc(sizeof(PRINTJOB));
318 memset(pPrintJob, 0, sizeof(PRINTJOB));
320 pPrintJob->pszOutput = strdup(lpOutput);
321 if(lpTitle)
322 pPrintJob->pszTitle = strdup(lpTitle);
323 pPrintJob->hDC = hDC;
324 pPrintJob->fd = fd;
325 pPrintJob->nIndex = 0;
326 pPrintJob->hHandle = hHandle;
327 gPrintJobsTable[pPrintJob->nIndex] = pPrintJob;
330 TRACE(print, "return %04x\n", hHandle);
331 return hHandle;
334 /**********************************************************************
335 * CloseJob (GDI.243)
338 int WINAPI CloseJob(HANDLE16 hJob)
340 int nRet = SP_ERROR;
341 PPRINTJOB pPrintJob = NULL;
343 TRACE(print, "%04x\n", hJob);
345 pPrintJob = FindPrintJobFromHandle(hJob);
346 if (pPrintJob != NULL)
348 /* Close the spool file */
349 close(pPrintJob->fd);
350 FreePrintJob(hJob);
351 nRet = 1;
353 return nRet;
356 /**********************************************************************
357 * WriteSpool (GDI.241)
360 int WINAPI WriteSpool(HANDLE16 hJob, LPSTR lpData, WORD cch)
362 int nRet = SP_ERROR;
363 PPRINTJOB pPrintJob = NULL;
365 TRACE(print, "%04x %08lx %04x\n", hJob, (DWORD)lpData, cch);
367 pPrintJob = FindPrintJobFromHandle(hJob);
368 if (pPrintJob != NULL && pPrintJob->fd >= 0 && cch)
370 if (write(pPrintJob->fd, lpData, cch) != cch)
371 nRet = SP_OUTOFDISK;
372 else
373 nRet = cch;
374 if (pPrintJob->hDC == 0) {
375 TRACE(print, "hDC == 0 so no QueryAbort\n");
377 else if (!(QueryAbort(pPrintJob->hDC, (nRet == SP_OUTOFDISK) ? nRet : 0 )))
379 CloseJob(hJob); /* printing aborted */
380 nRet = SP_APPABORT;
383 return nRet;
386 /**********************************************************************
387 * WriteDialog (GDI.242)
390 int WINAPI WriteDialog(HANDLE16 hJob, LPSTR lpMsg, WORD cchMsg)
392 int nRet = 0;
394 TRACE(print, "%04x %04x '%s'\n", hJob, cchMsg, lpMsg);
396 nRet = MessageBox16(0, lpMsg, "Printing Error", MB_OKCANCEL);
397 return nRet;
401 /**********************************************************************
402 * DeleteJob (GDI.244)
405 int WINAPI DeleteJob(HANDLE16 hJob, WORD wNotUsed)
407 int nRet;
409 TRACE(print, "%04x\n", hJob);
411 nRet = FreePrintJob(hJob);
412 return nRet;
416 * The following two function would allow a page to be sent to the printer
417 * when it has been processed. For simplicity they havn't been implemented.
418 * This means a whole job has to be processed before it is sent to the printer.
421 /**********************************************************************
422 * StartSpoolPage (GDI.246)
425 int WINAPI StartSpoolPage(HANDLE16 hJob)
427 FIXME(print, "StartSpoolPage GDI.246 unimplemented\n");
428 return 1;
433 /**********************************************************************
434 * EndSpoolPage (GDI.247)
437 int WINAPI EndSpoolPage(HANDLE16 hJob)
439 FIXME(print, "EndSpoolPage GDI.247 unimplemented\n");
440 return 1;
444 /**********************************************************************
445 * GetSpoolJob (GDI.245)
448 DWORD WINAPI GetSpoolJob(int nOption, LONG param)
450 DWORD retval = 0;
451 TRACE(print, "In GetSpoolJob param 0x%lx noption %d\n",param, nOption);
452 return retval;