Initial release of Maemo 5 port of gnuplot
[gnuplot] / src / win / wprinter.c
1 #ifndef lint
2 static char *RCSid() { return RCSid("$Id: wprinter.c,v 1.5 2005/08/03 16:55:40 mikulik Exp $"); }
3 #endif
4
5 /* GNUPLOT - win/wprinter.c */
6 /*[
7  * Copyright 1992, 1993, 1998, 2004   Maurice Castro, Russell Lang
8  *
9  * Permission to use, copy, and distribute this software and its
10  * documentation for any purpose with or without fee is hereby granted,
11  * provided that the above copyright notice appear in all copies and
12  * that both that copyright notice and this permission notice appear
13  * in supporting documentation.
14  *
15  * Permission to modify the software is granted, but not the right to
16  * distribute the complete modified source code.  Modifications are to
17  * be distributed as patches to the released version.  Permission to
18  * distribute binaries produced by compiling modified sources is granted,
19  * provided you
20  *   1. distribute the corresponding source modifications from the
21  *    released version in the form of a patch file along with the binaries,
22  *   2. add special version identification to distinguish your version
23  *    in addition to the base release version number,
24  *   3. provide your name and address as the primary contact for the
25  *    support of your modified version, and
26  *   4. retain our contact information in regard to use of the base
27  *    software.
28  * Permission to distribute the released version of the source code along
29  * with corresponding source modifications in the form of a patch file is
30  * granted with same provisions 2 through 4 for binary distributions.
31  *
32  * This software is provided "as is" without express or implied warranty
33  * to the extent permitted by applicable law.
34 ]*/
35
36 /*
37  * AUTHORS
38  *
39  *   Maurice Castro
40  *   Russell Lang
41  */
42
43 /* Dump a file to the printer */
44
45 #define STRICT
46 #include <windows.h>
47 #include <windowsx.h>
48 #if WINVER >= 0x030a
49 #include <commdlg.h>
50 #endif
51 #ifdef WIN32
52 #include <stdio.h>
53 #include <stdlib.h>
54 #endif
55 #ifdef __MSC__
56 #include <memory.h>
57 #else
58 #include <mem.h>
59 #endif
60 #include "wgnuplib.h"
61 #include "wresourc.h"
62 #include "wcommon.h"
63
64 GP_LPPRINT prlist = NULL;
65
66 BOOL CALLBACK WINEXPORT PrintSizeDlgProc(HWND hdlg, UINT wmsg, WPARAM wparam, LPARAM lparam);
67
68 BOOL CALLBACK WINEXPORT
69 PrintSizeDlgProc(HWND hdlg, UINT wmsg, WPARAM wparam, LPARAM lparam)
70 {
71     char buf[8];
72     GP_LPPRINT lpr = (GP_LPPRINT)GetWindowLong(GetParent(hdlg), 4);
73
74     switch (wmsg) {
75     case WM_INITDIALOG:
76         wsprintf(buf,"%d",lpr->pdef.x);
77         SetDlgItemText(hdlg, PSIZE_DEFX, buf);
78         wsprintf(buf,"%d",lpr->pdef.y);
79         SetDlgItemText(hdlg, PSIZE_DEFY, buf);
80         wsprintf(buf,"%d",lpr->poff.x);
81         SetDlgItemText(hdlg, PSIZE_OFFX, buf);
82         wsprintf(buf,"%d",lpr->poff.y);
83         SetDlgItemText(hdlg, PSIZE_OFFY, buf);
84         wsprintf(buf,"%d",lpr->psize.x);
85         SetDlgItemText(hdlg, PSIZE_X, buf);
86         wsprintf(buf,"%d",lpr->psize.y);
87         SetDlgItemText(hdlg, PSIZE_Y, buf);
88         CheckDlgButton(hdlg, PSIZE_DEF, TRUE);
89         EnableWindow(GetDlgItem(hdlg, PSIZE_X), FALSE);
90         EnableWindow(GetDlgItem(hdlg, PSIZE_Y), FALSE);
91         return TRUE;
92     case WM_COMMAND:
93         switch (wparam) {
94         case PSIZE_DEF:
95             EnableWindow(GetDlgItem(hdlg, PSIZE_X), FALSE);
96             EnableWindow(GetDlgItem(hdlg, PSIZE_Y), FALSE);
97             return FALSE;
98         case PSIZE_OTHER:
99             EnableWindow(GetDlgItem(hdlg, PSIZE_X), TRUE);
100             EnableWindow(GetDlgItem(hdlg, PSIZE_Y), TRUE);
101             return FALSE;
102         case IDOK:
103             if (SendDlgItemMessage(hdlg, PSIZE_OTHER, BM_GETCHECK, 0, 0L)) {
104                 SendDlgItemMessage(hdlg, PSIZE_X, WM_GETTEXT, 7,
105                                    (LPARAM) (LPSTR) buf);
106                 GetInt(buf, (LPINT)&lpr->psize.x);
107                 SendDlgItemMessage(hdlg, PSIZE_Y, WM_GETTEXT, 7,
108                                    (LPARAM) (LPSTR) buf);
109                 GetInt(buf, (LPINT)&lpr->psize.y);
110             } else {
111                 lpr->psize.x = lpr->pdef.x;
112                 lpr->psize.y = lpr->pdef.y;
113             }
114             SendDlgItemMessage(hdlg, PSIZE_OFFX, WM_GETTEXT, 7,
115                                (LPARAM) (LPSTR) buf);
116             GetInt(buf, (LPINT)&lpr->poff.x);
117             SendDlgItemMessage(hdlg, PSIZE_OFFY, WM_GETTEXT, 7,
118                                (LPARAM) (LPSTR) buf);
119             GetInt(buf, (LPINT)&lpr->poff.y);
120
121             if (lpr->psize.x <= 0)
122                 lpr->psize.x = lpr->pdef.x;
123             if (lpr->psize.y <= 0)
124                 lpr->psize.y = lpr->pdef.y;
125
126             EndDialog(hdlg, IDOK);
127             return TRUE;
128         case IDCANCEL:
129             EndDialog(hdlg, IDCANCEL);
130             return TRUE;
131         } /* switch(wparam) */
132         break;
133     } /* switch(msg) */
134     return FALSE;
135 }
136
137
138
139 /* GetWindowLong(hwnd, 4) must be available for use */
140 BOOL
141 PrintSize(HDC printer, HWND hwnd, LPRECT lprect)
142 {
143     HDC hdc;
144 #ifndef WIN32
145     DLGPROC lpfnPrintSizeDlgProc;
146 #endif
147     BOOL status = FALSE;
148     GP_PRINT pr;
149
150     SetWindowLong(hwnd, 4, (LONG)((GP_LPPRINT)&pr));
151     pr.poff.x = 0;
152     pr.poff.y = 0;
153     pr.psize.x = GetDeviceCaps(printer, HORZSIZE);
154     pr.psize.y = GetDeviceCaps(printer, VERTSIZE);
155     hdc = GetDC(hwnd);
156     GetClientRect(hwnd,lprect);
157     pr.pdef.x = MulDiv(lprect->right-lprect->left, 254, 10*GetDeviceCaps(hdc, LOGPIXELSX));
158     pr.pdef.y = MulDiv(lprect->bottom-lprect->top, 254, 10*GetDeviceCaps(hdc, LOGPIXELSX));
159     ReleaseDC(hwnd,hdc);
160
161 #ifdef WIN32
162     if (DialogBox (hdllInstance, "PrintSizeDlgBox", hwnd, PrintSizeDlgProc)
163         == IDOK)
164 #else
165 # ifdef __DLL__
166     lpfnPrintSizeDlgProc = (DLGPROC) GetProcAddress(hdllInstance,
167                                                     "PrintSizeDlgProc");
168 # else
169     lpfnPrintSizeDlgProc = (DLGPROC) MakeProcInstance(
170         (FARPROC) PrintSizeDlgProc, hdllInstance);
171 # endif
172     if (DialogBox (hdllInstance, "PrintSizeDlgBox", hwnd, lpfnPrintSizeDlgProc)
173         == IDOK)
174 #endif
175         {
176             lprect->left = MulDiv(pr.poff.x*10, GetDeviceCaps(printer, LOGPIXELSX), 254);
177             lprect->top = MulDiv(pr.poff.y*10, GetDeviceCaps(printer, LOGPIXELSY), 254);
178             lprect->right = lprect->left + MulDiv(pr.psize.x*10, GetDeviceCaps(printer, LOGPIXELSX), 254);
179             lprect->bottom = lprect->top + MulDiv(pr.psize.y*10, GetDeviceCaps(printer, LOGPIXELSY), 254);
180             status = TRUE;
181         }
182 #ifndef WIN32
183 # ifndef __DLL__
184     FreeProcInstance((FARPROC)lpfnPrintSizeDlgProc);
185 # endif
186 #endif
187     SetWindowLong(hwnd, 4, (LONG)(0L));
188
189     return status;
190 }
191
192 #ifdef WIN32
193 /* Win32 doesn't support OpenJob() etc. so we must use some old code
194  * which attempts to sneak the output through a Windows printer driver */
195 void
196 PrintRegister(GP_LPPRINT lpr)
197 {
198     GP_LPPRINT next;
199     next = prlist;
200     prlist = lpr;
201     lpr->next = next;
202 }
203
204 GP_LPPRINT
205 PrintFind(HDC hdc)
206 {
207     GP_LPPRINT this;
208     this = prlist;
209     while (this && (this->hdcPrn!=hdc)) {
210         this = this->next;
211     }
212     return this;
213 }
214
215 void
216 PrintUnregister(GP_LPPRINT lpr)
217 {
218     GP_LPPRINT this, prev;
219     prev = (GP_LPPRINT)NULL;
220     this = prlist;
221     while (this && (this!=lpr)) {
222         prev = this;
223         this = this->next;
224     }
225     if (this && (this == lpr)) {
226         /* unhook it */
227         if (prev)
228             prev->next = this->next;
229         else
230             prlist = this->next;
231     }
232 }
233
234
235 /* GetWindowLong(GetParent(hDlg), 4) must be available for use */
236 BOOL CALLBACK WINEXPORT
237 PrintDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
238 {
239     GP_LPPRINT lpr;
240     lpr = (GP_LPPRINT)GetWindowLong(GetParent(hDlg), 4);
241
242     switch(message) {
243     case WM_INITDIALOG:
244         lpr->hDlgPrint = hDlg;
245         SetWindowText(hDlg,(LPSTR)lParam);
246         EnableMenuItem(GetSystemMenu(hDlg,FALSE),SC_CLOSE,MF_GRAYED);
247         return TRUE;
248     case WM_COMMAND:
249         lpr->bUserAbort = TRUE;
250         lpr->hDlgPrint = 0;
251         EnableWindow(GetParent(hDlg),TRUE);
252         EndDialog(hDlg, FALSE);
253         return TRUE;
254     }
255     return FALSE;
256 }
257
258
259 BOOL CALLBACK WINEXPORT
260 PrintAbortProc(HDC hdcPrn, int code)
261 {
262     MSG msg;
263     GP_LPPRINT lpr;
264     lpr = PrintFind(hdcPrn);
265
266     while (!lpr->bUserAbort && PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
267                 if (!lpr->hDlgPrint || !IsDialogMessage(lpr->hDlgPrint,&msg)) {
268                 TranslateMessage(&msg);
269                 DispatchMessage(&msg);
270                 }
271     }
272     return(!lpr->bUserAbort);
273 }
274
275
276 /* GetWindowLong(hwnd, 4) must be available for use */
277 void WDPROC
278 DumpPrinter(HWND hwnd, LPSTR szAppName, LPSTR szFileName)
279 {
280     HDC printer;
281     PRINTDLG pd;
282     GP_PRINT pr;
283     DOCINFO di;
284     char *buf;
285     WORD *bufcount;
286     int count;
287     FILE *f;
288     long lsize;
289     long ldone;
290     char pcdone[10];
291
292     memset(&pd, 0, sizeof(PRINTDLG));
293     pd.lStructSize = sizeof(PRINTDLG);
294     pd.hwndOwner = hwnd;
295     pd.Flags = PD_PRINTSETUP | PD_RETURNDC;
296
297     if ((f = fopen(szFileName, "rb")) == (FILE *)NULL)
298         return;
299     fseek(f, 0L, SEEK_END);
300     lsize = ftell(f);
301     if (lsize <= 0)
302         lsize = 1;
303     fseek(f, 0L, SEEK_SET);
304     ldone = 0;
305
306     if (PrintDlg(&pd)) {
307         printer = pd.hDC;
308         if (printer != (HDC)NULL) {
309             pr.hdcPrn = printer;
310             SetWindowLong(hwnd, 4, (LONG)((GP_LPPRINT)&pr));
311             PrintRegister((GP_LPPRINT)&pr);
312             if ( (buf = malloc(4096+2)) != (char *)NULL ) {
313                 bufcount = (WORD *)buf;
314                 EnableWindow(hwnd,FALSE);
315                 pr.bUserAbort = FALSE;
316 /* is parent set correctly */
317                 pr.hDlgPrint = CreateDialogParam(hdllInstance,
318                                                  "CancelDlgBox",
319                                                  hwnd, PrintDlgProc,
320                                                  (LPARAM) szAppName);
321                 SetAbortProc(printer, PrintAbortProc);
322                 di.cbSize = sizeof(DOCINFO);
323                 di.lpszDocName = szAppName;
324                 di.lpszOutput = NULL;
325                 if (StartDoc(printer, &di) > 0) {
326                     while ( pr.hDlgPrint && !pr.bUserAbort
327                             && (count = fread(buf+2, 1, 4096, f)) != 0 ) {
328                         *bufcount = count;
329                         Escape(printer, PASSTHROUGH, count+2, (LPSTR)buf, NULL);
330                         ldone += count;
331                         sprintf(pcdone, "%d%% done",
332                                 (int) (ldone * 100 / lsize));
333                         SetWindowText(GetDlgItem(pr.hDlgPrint, CANCEL_PCDONE),
334                                       pcdone);
335                         if (pr.bUserAbort)
336                             AbortDoc(printer);
337                         else
338                             EndDoc(printer);
339                     }
340                     if (!pr.bUserAbort) {
341                         EnableWindow(hwnd,TRUE);
342                         DestroyWindow(pr.hDlgPrint);
343                     }
344                     free(buf);
345                 }
346             }
347             DeleteDC(printer);
348             SetWindowLong(hwnd, 4, (LONG)(0L));
349             PrintUnregister((GP_LPPRINT)&pr);
350         }
351     }
352     fclose(f);
353 }
354
355 #else  /* !WIN32 */
356
357 /* documented in Device Driver Adaptation Guide */
358 /* Prototypes taken from print.h */
359  DECLARE_HANDLE(HPJOB);
360
361 HPJOB   WINAPI OpenJob(LPSTR, LPSTR, HPJOB);
362 int     WINAPI StartSpoolPage(HPJOB);
363 int     WINAPI EndSpoolPage(HPJOB);
364 int     WINAPI WriteSpool(HPJOB, LPSTR, int);
365 int     WINAPI CloseJob(HPJOB);
366 int     WINAPI DeleteJob(HPJOB, int);
367 int     WINAPI WriteDialog(HPJOB, LPSTR, int);
368 int     WINAPI DeleteSpoolPage(HPJOB);
369
370 /* Modeless dialog box - Cancel printing */
371 BOOL CALLBACK WINEXPORT
372 CancelDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
373 {
374     switch(message) {
375     case WM_INITDIALOG:
376         SetWindowText(hDlg,(LPSTR)lParam);
377         return TRUE;
378     case WM_COMMAND:
379         switch(LOWORD(wParam)) {
380         case IDCANCEL:
381             DestroyWindow(hDlg);
382             return TRUE;
383         }
384     }
385     return FALSE;
386 }
387
388
389
390 /* Dialog box to select printer port */
391 BOOL CALLBACK WINEXPORT
392 SpoolDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
393 {
394     LPSTR entry;
395
396     switch(message) {
397     case WM_INITDIALOG:
398         entry = (LPSTR)lParam;
399         while (*entry) {
400             SendDlgItemMessage(hDlg, SPOOL_PORT, LB_ADDSTRING, 0, (LPARAM)entry);
401             entry += lstrlen(entry)+1;
402         }
403         SendDlgItemMessage(hDlg, SPOOL_PORT, LB_SETCURSEL, 0, (LPARAM)0);
404         return TRUE;
405     case WM_COMMAND:
406         switch(LOWORD(wParam)) {
407         case SPOOL_PORT:
408             if (HIWORD(lParam) == LBN_DBLCLK)
409                 PostMessage(hDlg, WM_COMMAND, IDOK, 0L);
410             return FALSE;
411         case IDOK:
412             EndDialog(hDlg, 1+(int)SendDlgItemMessage(hDlg, SPOOL_PORT, LB_GETCURSEL, 0, 0L));
413             return TRUE;
414         case IDCANCEL:
415             EndDialog(hDlg, 0);
416             return TRUE;
417         }
418     }
419     return FALSE;
420 }
421
422 /* Print File to port */
423 void WDPROC
424 DumpPrinter(HWND hwnd, LPSTR szAppName, LPSTR szFileName)
425 {
426 #define PRINT_BUF_SIZE 4096
427     char *buffer;
428     char *portname;
429     int i, iport;
430     DLGPROC lpfnSpoolProc;
431     HPJOB hJob;
432     UINT count;
433     HFILE hf;
434     int error = FALSE;
435     DLGPROC lpfnCancelProc;
436     long lsize;
437     long ldone;
438     char pcdone[10];
439     MSG msg;
440     HWND hDlgModeless;
441
442     if ((buffer = LocalAllocPtr(LHND, PRINT_BUF_SIZE)) == (char *)NULL)
443         return;
444     /* get list of ports */
445     GetProfileString("ports", NULL, "", buffer, PRINT_BUF_SIZE);
446     /* select a port */
447     lpfnSpoolProc = (DLGPROC)MakeProcInstance((FARPROC)SpoolDlgProc, hdllInstance);
448     iport = DialogBoxParam(hdllInstance, "SpoolDlgBox", hwnd, lpfnSpoolProc, (LPARAM)buffer);
449     FreeProcInstance((FARPROC)lpfnSpoolProc);
450     if (!iport) {
451         LocalFreePtr((void NEAR *)buffer);
452         return;
453     }
454     portname = buffer;
455     for (i=1; i<iport && lstrlen(portname)!=0; i++)
456         portname += lstrlen(portname)+1;
457
458     /* open file and get length */
459     hf = _lopen(szFileName, OF_READ);
460     if (hf == HFILE_ERROR) {
461         LocalFreePtr((void NEAR *)buffer);
462         return;
463     }
464     lsize = _llseek(hf, 0L, 2);
465     (void) _llseek(hf, 0L, 0);
466     if (lsize <= 0)
467         lsize = 1;
468
469     hJob = OpenJob(portname, szFileName, (HDC)NULL);
470     switch ((int)hJob) {
471     case SP_APPABORT:
472     case SP_ERROR:
473     case SP_OUTOFDISK:
474     case SP_OUTOFMEMORY:
475     case SP_USERABORT:
476         _lclose(hf);
477         LocalFreePtr((void NEAR *)buffer);
478         return;
479     }
480     if (StartSpoolPage(hJob) < 0)
481         error = TRUE;
482
483     ldone = 0;
484     lpfnCancelProc = (DLGPROC)MakeProcInstance((FARPROC)CancelDlgProc, hdllInstance);
485     hDlgModeless = CreateDialogParam(hdllInstance, "CancelDlgBox", hwnd, lpfnCancelProc, (LPARAM)szAppName);
486
487     while (!error && hDlgModeless && IsWindow(hDlgModeless)
488            && ((count = _lread(hf, buffer, PRINT_BUF_SIZE))!= 0) ) {
489         wsprintf(pcdone, "%d%% done", (int)(ldone * 100 / lsize));
490         SetWindowText(GetDlgItem(hDlgModeless, CANCEL_PCDONE), pcdone);
491         if (WriteSpool(hJob, buffer, count) < 0)
492             error = TRUE;
493         ldone += count;
494         while (IsWindow(hDlgModeless) && PeekMessage(&msg, hDlgModeless, 0, 0, PM_REMOVE)) {
495             if (!IsDialogMessage(hDlgModeless, &msg)) {
496                 TranslateMessage(&msg);
497                 DispatchMessage(&msg);
498             }
499         }
500     }
501     LocalFreePtr((void NEAR *)buffer);
502     _lclose(hf);
503
504     if (!hDlgModeless || !IsWindow(hDlgModeless))
505         error=TRUE;
506     if (IsWindow(hDlgModeless))
507         DestroyWindow(hDlgModeless);
508     hDlgModeless = 0;
509     FreeProcInstance((FARPROC)lpfnCancelProc);
510     EndSpoolPage(hJob);
511     if (error)
512         DeleteJob(hJob, 0);
513     else
514         CloseJob(hJob);
515 }
516 #endif /* !WIN32 */
517