Initial release of Maemo 5 port of gnuplot
[gnuplot] / src / os2 / print.c
1 #ifdef INCRCSDATA
2 static char RCSid[]="$Id: print.c,v 1.4 2005/01/04 13:01:38 mikulik Exp $" ;
3 #endif
4
5 /****************************************************************************
6
7     PROGRAM: gnupmdrv
8
9     Outboard PM driver for GNUPLOT 3.3
10
11     MODULE:  print.c -- support for printing graphics under OS/2
12
13 ****************************************************************************/
14
15 /* PM driver for GNUPLOT */
16
17 /*[
18  * Copyright 1992, 1993, 1998, 2004 Roger Fearick
19  *
20  * Permission to use, copy, and distribute this software and its
21  * documentation for any purpose with or without fee is hereby granted,
22  * provided that the above copyright notice appear in all copies and
23  * that both that copyright notice and this permission notice appear
24  * in supporting documentation.
25  *
26  * Permission to modify the software is granted, but not the right to
27  * distribute the complete modified source code.  Modifications are to
28  * be distributed as patches to the released version.  Permission to
29  * distribute binaries produced by compiling modified sources is granted,
30  * provided you
31  *   1. distribute the corresponding source modifications from the
32  *    released version in the form of a patch file along with the binaries,
33  *   2. add special version identification to distinguish your version
34  *    in addition to the base release version number,
35  *   3. provide your name and address as the primary contact for the
36  *    support of your modified version, and
37  *   4. retain our contact information in regard to use of the base
38  *    software.
39  * Permission to distribute the released version of the source code along
40  * with corresponding source modifications in the form of a patch file is
41  * granted with same provisions 2 through 4 for binary distributions.
42  *
43  * This software is provided "as is" without express or implied warranty
44  * to the extent permitted by applicable law.
45 ]*/
46
47 /*
48  * AUTHOR
49  *
50  *   Gnuplot driver for OS/2:  Roger Fearick
51  */
52
53 #define INCL_SPLDOSPRINT
54 #define INCL_DOSPROCESS
55 #define INCL_DOSSEMAPHORES
56 #define INCL_DEV
57 #define INCL_SPL
58 #define INCL_PM
59 #define INCL_WIN
60 #include <os2.h>
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #include <process.h>
65 #include "gnupmdrv.h"
66
67 #define   GNUPAGE   4096        /* size of gnuplot page in pixels (driver dependent) */
68
69
70 typedef struct {            /* for print thread parameters */
71     HWND  hwnd ;
72     HDC   hdc ;                 /* printer device context */
73     HPS   hps ;                 /* screen PS to be printed */
74     char  szPrintFile[256] ;    /* file for printer output if not to printer */
75     PQPRINT pqp ;       /* print queue info */
76     } PRINTPARAMS ;
77
78 static struct {
79     long    lTech ;     // printer technology
80     long    lVer ;      // driver version
81     long    lWidth ;    // page width in pels
82     long    lHeight ;   // page height in pels
83     long    lWChars ;   // page width in chars
84     long    lHChars ;   // page height in chars
85     long    lHorRes ;   // horizontal resolution pels / metre
86     long    lVertRes ;  // vertical resolution pels / metre
87     } prCaps ;
88
89 //static PDRIVDATA    pdriv = NULL ;
90 static DRIVDATA     driv = {sizeof( DRIVDATA) } ;
91 static char         szPrintFile[CCHMAXPATHCOMP] = {0} ;
92 static DEVOPENSTRUC devop ;
93
94 ULONG GetPrinters( PPRQINFO3 *, ULONG *  ) ;
95 int FindPrinter( char *, PPRQINFO3  ) ;
96 HMF     CopyToMetaFile( HPS ) ;
97 static void    ThreadPrintPage( ) ;
98
99 MPARAM PrintCmdProc( HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
100 /*
101 **  Handle messages for print commands for 1- and 2-d spectra
102 ** (i.e for the appropriate 1-and 2-d child windows )
103 */
104     {
105     static PRINTPARAMS tp ;
106     static char szBusy[] = "Busy - try again later" ;
107     static char szStart[] = "Printing started" ;
108     static HEV semPrint = 0L ;
109     static HWND hwndCancel = NULLHANDLE ;
110     char szTemp[32] ;
111     unsigned short lErr ;
112     TID tid ;
113     char *pszMess;
114
115     if( semPrint == 0L ) {
116         DosCreateMutexSem( NULL, &semPrint, 0L, 0L ) ;
117         }
118
119     switch( msg ) {
120
121         case WM_USER_PRINT_BEGIN:
122
123             if( DosRequestMutexSem( semPrint, SEM_IMMEDIATE_RETURN ) != 0 ) {
124                 pszMess = szBusy ;
125                 WinMessageBox( HWND_DESKTOP,
126                                hWnd,
127                                pszMess,
128                                APP_NAME,
129                                0,
130                                MB_OK | MB_ICONEXCLAMATION ) ;
131                 }
132             else {
133                 pszMess = szStart ;
134                 tp.hwnd = hWnd ;
135                 tp.pqp = (PQPRINT) mp1 ;
136                 tp.hps = (HPS) mp2 ;
137                 strcpy( tp.szPrintFile, szPrintFile ) ;
138                 tid = _beginthread( ThreadPrintPage, NULL, 32768, &tp ) ;
139                 hwndCancel = WinLoadDlg( HWND_DESKTOP,
140                                          hWnd,
141                                          (PFNWP)CancelPrintDlgProc,
142                                          0L,
143                                          ID_PRINTSTOP,
144                                          NULL ) ;
145                 }
146             break ;
147
148
149         case WM_USER_PRINT_OK :
150
151             if( hwndCancel != NULLHANDLE ) {
152                 WinDismissDlg( hwndCancel, 0 ) ;
153                 hwndCancel = NULLHANDLE ;
154                 }
155              DosReleaseMutexSem( semPrint ) ;
156              break ;
157
158         case WM_USER_DEV_ERROR :
159
160             if( hwndCancel != NULLHANDLE ) {
161                 WinDismissDlg( hwndCancel, 0 ) ;
162                 hwndCancel = NULLHANDLE ;
163                 }
164             lErr = ERRORIDERROR( (ERRORID) mp1 ) ;
165             sprintf( szTemp, "Dev error: %d %x", lErr, lErr ) ;
166             WinMessageBox( HWND_DESKTOP,
167                            hWnd,
168                            szTemp,
169                            APP_NAME,
170                            0,
171                            MB_OK | MB_ICONEXCLAMATION ) ;
172              DosReleaseMutexSem( semPrint ) ;
173              break ;
174
175         case WM_USER_PRINT_ERROR :
176
177             if( hwndCancel != NULLHANDLE ) {
178                 WinDismissDlg( hwndCancel, 0 ) ;
179                 hwndCancel = NULLHANDLE ;
180                 }
181             lErr = ERRORIDERROR( (ERRORID) mp1 ) ;
182             sprintf( szTemp, "Print error: %d %x", lErr, lErr ) ;
183             WinMessageBox( HWND_DESKTOP,
184                            hWnd,
185                            szTemp,
186                            APP_NAME,
187                            0,
188                            MB_OK | MB_ICONEXCLAMATION ) ;
189              DosReleaseMutexSem( semPrint ) ;
190              break ;
191
192         case WM_USER_PRINT_CANCEL :
193
194              DevEscape( tp.hdc, DEVESC_ABORTDOC, 0L, NULL, NULL, NULL ) ;
195              break ;
196
197
198         case WM_USER_PRINT_QBUSY :
199
200             return( (MPARAM)DosRequestMutexSem( semPrint, SEM_IMMEDIATE_RETURN ) ) ;
201
202         default : break ;
203         }
204
205     return 0L ;
206     }
207
208 int SetupPrinter( HWND hwnd, PQPRINT pqp )
209 /*
210 **  Set up the printer
211 **
212 */
213     {
214     HDC hdc ;
215     float flXFrac, flYFrac;
216           /* check that printer is still around .. */
217     if( FindPrinter( pqp->szPrinterName, pqp->piPrinter ) != 0 ) return 0 ;
218           /* get printer capabilities */
219     if( (hdc = OpenPrinterDC( WinQueryAnchorBlock( hwnd ), pqp, OD_INFO, NULL )) != DEV_ERROR ) {
220         DevQueryCaps( hdc, CAPS_TECHNOLOGY, (long)sizeof(prCaps)/sizeof(long), (PLONG)&prCaps ) ;
221         DevCloseDC( hdc ) ;
222         pqp->xsize = (float)100.0* (float) prCaps.lWidth / (float) prCaps.lHorRes ; // in cm
223         pqp->ysize = (float)100.0* (float) prCaps.lHeight / (float) prCaps.lVertRes ; // in cm
224         flXFrac = pqp->xfrac ;
225         flYFrac = pqp->yfrac ;
226         pqp->szFilename[0] = 0 ;
227         szPrintFile[0] = 0 ;
228         pqp->caps  = prCaps.lTech & (CAPS_TECH_VECTOR_PLOTTER|CAPS_TECH_POSTSCRIPT) ?
229                    QP_CAPS_FILE : QP_CAPS_NORMAL ;
230         if( WinDlgBox( HWND_DESKTOP,
231                       hwnd,
232                     (PFNWP)QPrintDlgProc,
233                     0L,
234                     ID_QPRINT,
235                     pqp ) == DID_OK ) {
236           if( pqp->caps & QP_CAPS_FILE ) {
237               if( pqp->szFilename[0] != 0 ) strcpy( szPrintFile, pqp->szFilename ) ;
238               }
239           return 1 ;
240           }
241         pqp->xfrac = flXFrac ;
242         pqp->yfrac = flYFrac ;
243         }
244
245     return 0 ;
246     }
247
248 int SetPrinterMode( HWND hwnd, PQPRINT pqp )
249 /*
250 **  call up printer driver's own setup dialog box
251 **
252 **  returns :  -1 if error
253 **              0 if no settable modes
254 **              1 if OK
255 */
256     {
257     HAB hab ;
258     LONG lBytes ;
259     PPRQINFO3 pinfo = pqp->piPrinter ;
260
261     hab = WinQueryAnchorBlock( hwnd ) ;
262     driv.szDeviceName[0]='\0' ;
263     lBytes = DevPostDeviceModes( hab,
264                                  NULL,
265                                  devop.pszDriverName,
266                                  pinfo->pDriverData->szDeviceName,
267                                  //driv.szDeviceName,
268                                  NULL,
269                                  DPDM_POSTJOBPROP ) ;
270     if( lBytes > 0L ) {
271             /* if we have old pdriv data, and if it's for the same printer,
272                keep it to retain user's current settings, else get new */
273         if( pqp->pdriv != NULL
274         && strcmp( pqp->pdriv->szDeviceName, pinfo->pDriverData->szDeviceName ) != 0 ) {
275             free( pqp->pdriv ) ;
276             pqp->pdriv = NULL ;
277             }
278         if( pqp->pdriv == NULL ) {
279             if( lBytes < pinfo->pDriverData->cb ) lBytes = pinfo->pDriverData->cb ;
280             pqp->pdriv = malloc( lBytes ) ;
281             pqp->cbpdriv = lBytes ;
282             memcpy( pqp->pdriv, pinfo->pDriverData, lBytes ) ;
283             }
284         strcpy( driv.szDeviceName, pqp->pdriv->szDeviceName ) ;
285 //        pqp->pdriv->szDeviceName[0] = '\0' ;  /* to check if 'cancel' selected */
286         lBytes = DevPostDeviceModes( hab,
287                                      pqp->pdriv,
288                                      devop.pszDriverName,
289                                      driv.szDeviceName,
290                                      NULL,
291                                      DPDM_POSTJOBPROP ) ;
292         if( lBytes != 1 /*pqp->pdriv->szDeviceName[0] == '\0'*/ ) {  /* could be: 'cancel' selected */
293             pqp->cbpdriv = lBytes = 0 ;
294             free(pqp->pdriv ) ;   /* is this right ???? */
295             pqp->pdriv = NULL ;
296             }
297         }
298     return ( (int) lBytes ) ;
299     }
300
301 static void ThreadPrintPage( PRINTPARAMS *ptp )
302 /*
303 **  thread to set up printer DC and print page
304 **
305 **  Input: THREADPARAMS *ptp -- pointer to thread data passed by beginthread
306 **
307 */
308     {
309     HAB         hab ;       // thread anchor block nandle
310     HDC         hdc ;       // printer device context handle
311     HPS         hps ;       // presentation space handle
312     SHORT       msgRet ;    // message posted prior to return (end of thread)
313     SIZEL       sizPage ;   // size of page for creation of presentation space
314     LONG        alPage[2] ; // actual size of printer page in pixels
315     RECTL       rectPage ;  // viewport on page into which we draw
316     LONG        lColors ;
317     char        *szPrintFile ;
318     HMF         hmf ;
319     LONG        alOpt[9] ;
320     HPS         hpsSc ;
321     hab = WinInitialize( 0 ) ;
322
323     szPrintFile = ptp->szPrintFile[0] == '\0' ? NULL : ptp->szPrintFile ;
324
325     if( (hdc = OpenPrinterDC( hab, ptp->pqp, 0L, szPrintFile )) != DEV_ERROR ) {
326
327             // create presentation space for printer
328
329         ptp->hdc = hdc ;
330         hmf = CopyToMetaFile( ptp->hps ) ;
331         hpsSc = ptp->hps ;
332
333         sizPage.cx = GNUXPAGE;
334         sizPage.cy = GNUYPAGE;
335         hps = GpiCreatePS( hab,
336                            hdc,
337                            &sizPage,
338                            PU_HIMETRIC | GPIF_DEFAULT | GPIT_NORMAL | GPIA_ASSOC ) ;
339
340         DevQueryCaps( hdc, CAPS_WIDTH, 2L, alPage ) ;
341         DevQueryCaps( hdc, CAPS_PHYS_COLORS, 1L, &lColors ) ;
342         rectPage.xLeft = 0L ;
343         rectPage.xRight = alPage[0] ;
344         rectPage.yTop = alPage[1] ;//alPage[1]*(1.0-flYFrac) ;
345         rectPage.yBottom = 0L ; //  = alPage[1] ;
346
347         {
348         double ratio = 1.560 ;
349         double xs = rectPage.xRight - rectPage.xLeft ;
350         double ys = rectPage.yTop - rectPage.yBottom ;
351         if( ys > xs/ratio ) { /* reduce ys to fit */
352             rectPage.yTop = rectPage.yBottom + (int)(xs/ratio) ;
353             }
354         else if( ys < xs/ratio ) { /* reduce xs to fit */
355             rectPage.xRight = rectPage.xLeft + (int)(ys*ratio) ;
356             }
357         }
358
359         rectPage.xRight = rectPage.xRight*ptp->pqp->xfrac ;
360         rectPage.yTop = rectPage.yTop*ptp->pqp->yfrac ;//alPage[1]*(1.0-flYFrac) ;
361
362         {
363         double ratio = 1.560 ;
364         double xs = rectPage.xRight - rectPage.xLeft ;
365         double ys = rectPage.yTop - rectPage.yBottom ;
366         if( ys > xs/ratio ) { /* reduce ys to fit */
367             rectPage.yTop = rectPage.yBottom + (int)(xs/ratio) ;
368             }
369         else if( ys < xs/ratio ) { /* reduce xs to fit */
370             rectPage.xRight = rectPage.xLeft + (int)(ys*ratio) ;
371             }
372         }
373
374
375             // start printing
376
377         if( DevEscape( hdc,
378                        DEVESC_STARTDOC,
379                        7L,
380                        APP_NAME,
381                        NULL,
382                        NULL ) != DEVESC_ERROR ) {
383             char buff[256] ;
384             int rc;
385
386             rc = GpiSetPageViewport( hps, &rectPage ) ;
387
388             alOpt[0] = 0L ;
389             alOpt[1] = LT_ORIGINALVIEW ;
390             alOpt[2] = 0L ;
391             alOpt[3] = LC_LOADDISC ;
392             alOpt[4] = RES_DEFAULT ;
393             alOpt[5] = SUP_DEFAULT ;
394             alOpt[6] = CTAB_DEFAULT ;
395             alOpt[7] = CREA_DEFAULT ;
396             alOpt[8] = DDEF_DEFAULT ;
397             if (rc) rc=GpiPlayMetaFile( hps, hmf, 9L, alOpt, NULL, 255, buff ) ;
398
399             if (rc) {
400               DevEscape( hdc, DEVESC_ENDDOC, 0L, NULL, NULL, NULL ) ;
401               msgRet = WM_USER_PRINT_OK ;
402               }
403             else
404               msgRet = WM_USER_PRINT_ERROR;
405
406             }
407         else
408             msgRet = WM_USER_PRINT_ERROR ;
409
410         GpiDestroyPS( hps ) ;
411         DevCloseDC( hdc ) ;
412         }
413     else
414         msgRet = WM_USER_DEV_ERROR ;
415
416     DosEnterCritSec() ;
417     WinPostMsg( ptp->hwnd, msgRet, (MPARAM)WinGetLastError(hab), 0L ) ;
418     WinTerminate( hab ) ;
419     }
420
421 HDC OpenPrinterDC( HAB hab, PQPRINT pqp, LONG lMode, char *szPrintFile )
422 /*
423 ** get printer info from os2.ini and set up DC
424 **
425 ** Input:  HAB hab  -- handle of anchor block of printing thread
426 **         PQPRINT-- pointer to data of current selected printer
427 **         LONG lMode -- mode in which device context is opened = OD_QUEUED, OD_DIRECT, OD_INFO
428 **         char *szPrintFile -- name of file for printer output, NULL
429 **                  if to printer (only used for devices that support file
430 **                  output eg plotter, postscript)
431 **
432 ** Return: HDC      -- handle of printer device context
433 **                   = DEV_ERROR (=0) if error
434 */
435     {
436     LONG   lType ;
437     static CHAR   achPrinterData[256] ;
438
439     if( pqp->piPrinter == NULL ) return DEV_ERROR ;
440
441     strcpy( achPrinterData, pqp->piPrinter->pszDriverName ) ;
442     achPrinterData[ strcspn(achPrinterData,".") ] = '\0' ;
443
444     devop.pszDriverName = achPrinterData ;
445     devop.pszLogAddress = pqp->piPrinter->pszName ;
446
447     if( pqp->pdriv != NULL
448         && strcmp( pqp->pdriv->szDeviceName, pqp->piPrinter->pDriverData->szDeviceName ) == 0 ) {
449         devop.pdriv = pqp->pdriv ;
450         }
451     else devop.pdriv = pqp->piPrinter->pDriverData ;
452
453     if( szPrintFile != NULL )  devop.pszLogAddress = szPrintFile ;
454
455             // set data type to RAW
456
457     devop.pszDataType = "PM_Q_RAW" ;
458
459             // open device context
460     if( lMode != 0L )
461         lType = lMode ;
462     else
463         lType = (szPrintFile == NULL) ? OD_QUEUED: OD_DIRECT ;
464
465     return DevOpenDC( hab, //  WinQueryAnchorBlock( hwnd ),
466                       lType,
467                       "*",
468                       4L,
469                       (PDEVOPENDATA) &devop,
470                       NULLHANDLE ) ;
471     }
472
473 int FindPrinter( char *szName, PPRQINFO3 piPrinter )
474 /*
475 **  Find a valid printer
476 */
477     {
478     PPRQINFO3 pprq = NULL ;
479     PDRIVDATA pdriv = NULL ;
480     LONG np ;
481
482     if( *szName && (strcmp( szName, piPrinter->pszName ) == 0) ) return 0 ;
483     if( GetPrinters( &pprq , &np ) == 0 ) return 1 ;
484     for( --np; np>=0; np-- ) {
485         if( strcmp( szName, pprq[np].pszName ) == 0 ) {
486             if( piPrinter->pDriverData != NULL ) free( piPrinter->pDriverData ) ;
487             pdriv = malloc( pprq[np].pDriverData->cb ) ;
488             memcpy( piPrinter, &pprq[np], sizeof( PRQINFO3 ) ) ;
489             piPrinter->pDriverData = pdriv ;
490             memcpy( pdriv, pprq[np].pDriverData, pprq[np].pDriverData->cb ) ;
491             free( pprq ) ;
492             return 0 ;
493             }
494         }
495     memcpy( piPrinter, &pprq[0], sizeof( PRQINFO3 ) ) ;
496     free( pprq ) ;
497     return 0 ;
498     }
499
500 MRESULT EXPENTRY CancelPrintDlgProc ( HWND hwnd, ULONG usMsg, MPARAM mp1, MPARAM mp2 )
501 /*
502 **  Cancel printing dialog box proc
503 */
504     {
505     switch ( usMsg ) {
506
507         case WM_COMMAND :
508             switch ( SHORT1FROMMP(mp1) ) {
509                 case DID_CANCEL:
510                     WinSendMsg( WinQueryWindow( hwnd, QW_OWNER ),
511                                     WM_USER_PRINT_CANCEL,
512                                     0L,
513                                     0L ) ;
514                     WinDismissDlg( hwnd, 0 ) ;
515                     break ;
516                 default:
517                     break ;
518                 }
519         default:
520             break ;
521         }
522         /* fall through to the default control processing */
523     return WinDefDlgProc ( hwnd , usMsg , mp1 , mp2 ) ;
524     }
525
526