2 static char RCSid[]="$Id: print.c,v 1.4 2005/01/04 13:01:38 mikulik Exp $" ;
5 /****************************************************************************
9 Outboard PM driver for GNUPLOT 3.3
11 MODULE: print.c -- support for printing graphics under OS/2
13 ****************************************************************************/
15 /* PM driver for GNUPLOT */
18 * Copyright 1992, 1993, 1998, 2004 Roger Fearick
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.
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,
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
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.
43 * This software is provided "as is" without express or implied warranty
44 * to the extent permitted by applicable law.
50 * Gnuplot driver for OS/2: Roger Fearick
53 #define INCL_SPLDOSPRINT
54 #define INCL_DOSPROCESS
55 #define INCL_DOSSEMAPHORES
67 #define GNUPAGE 4096 /* size of gnuplot page in pixels (driver dependent) */
70 typedef struct { /* for print thread parameters */
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 */
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
89 //static PDRIVDATA pdriv = NULL ;
90 static DRIVDATA driv = {sizeof( DRIVDATA) } ;
91 static char szPrintFile[CCHMAXPATHCOMP] = {0} ;
92 static DEVOPENSTRUC devop ;
94 ULONG GetPrinters( PPRQINFO3 *, ULONG * ) ;
95 int FindPrinter( char *, PPRQINFO3 ) ;
96 HMF CopyToMetaFile( HPS ) ;
97 static void ThreadPrintPage( ) ;
99 MPARAM PrintCmdProc( HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
101 ** Handle messages for print commands for 1- and 2-d spectra
102 ** (i.e for the appropriate 1-and 2-d child windows )
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 ;
111 unsigned short lErr ;
115 if( semPrint == 0L ) {
116 DosCreateMutexSem( NULL, &semPrint, 0L, 0L ) ;
121 case WM_USER_PRINT_BEGIN:
123 if( DosRequestMutexSem( semPrint, SEM_IMMEDIATE_RETURN ) != 0 ) {
125 WinMessageBox( HWND_DESKTOP,
130 MB_OK | MB_ICONEXCLAMATION ) ;
135 tp.pqp = (PQPRINT) mp1 ;
137 strcpy( tp.szPrintFile, szPrintFile ) ;
138 tid = _beginthread( ThreadPrintPage, NULL, 32768, &tp ) ;
139 hwndCancel = WinLoadDlg( HWND_DESKTOP,
141 (PFNWP)CancelPrintDlgProc,
149 case WM_USER_PRINT_OK :
151 if( hwndCancel != NULLHANDLE ) {
152 WinDismissDlg( hwndCancel, 0 ) ;
153 hwndCancel = NULLHANDLE ;
155 DosReleaseMutexSem( semPrint ) ;
158 case WM_USER_DEV_ERROR :
160 if( hwndCancel != NULLHANDLE ) {
161 WinDismissDlg( hwndCancel, 0 ) ;
162 hwndCancel = NULLHANDLE ;
164 lErr = ERRORIDERROR( (ERRORID) mp1 ) ;
165 sprintf( szTemp, "Dev error: %d %x", lErr, lErr ) ;
166 WinMessageBox( HWND_DESKTOP,
171 MB_OK | MB_ICONEXCLAMATION ) ;
172 DosReleaseMutexSem( semPrint ) ;
175 case WM_USER_PRINT_ERROR :
177 if( hwndCancel != NULLHANDLE ) {
178 WinDismissDlg( hwndCancel, 0 ) ;
179 hwndCancel = NULLHANDLE ;
181 lErr = ERRORIDERROR( (ERRORID) mp1 ) ;
182 sprintf( szTemp, "Print error: %d %x", lErr, lErr ) ;
183 WinMessageBox( HWND_DESKTOP,
188 MB_OK | MB_ICONEXCLAMATION ) ;
189 DosReleaseMutexSem( semPrint ) ;
192 case WM_USER_PRINT_CANCEL :
194 DevEscape( tp.hdc, DEVESC_ABORTDOC, 0L, NULL, NULL, NULL ) ;
198 case WM_USER_PRINT_QBUSY :
200 return( (MPARAM)DosRequestMutexSem( semPrint, SEM_IMMEDIATE_RETURN ) ) ;
208 int SetupPrinter( HWND hwnd, PQPRINT pqp )
210 ** Set up the printer
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 ) ;
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 ;
228 pqp->caps = prCaps.lTech & (CAPS_TECH_VECTOR_PLOTTER|CAPS_TECH_POSTSCRIPT) ?
229 QP_CAPS_FILE : QP_CAPS_NORMAL ;
230 if( WinDlgBox( HWND_DESKTOP,
232 (PFNWP)QPrintDlgProc,
236 if( pqp->caps & QP_CAPS_FILE ) {
237 if( pqp->szFilename[0] != 0 ) strcpy( szPrintFile, pqp->szFilename ) ;
241 pqp->xfrac = flXFrac ;
242 pqp->yfrac = flYFrac ;
248 int SetPrinterMode( HWND hwnd, PQPRINT pqp )
250 ** call up printer driver's own setup dialog box
252 ** returns : -1 if error
253 ** 0 if no settable modes
259 PPRQINFO3 pinfo = pqp->piPrinter ;
261 hab = WinQueryAnchorBlock( hwnd ) ;
262 driv.szDeviceName[0]='\0' ;
263 lBytes = DevPostDeviceModes( hab,
266 pinfo->pDriverData->szDeviceName,
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 ) {
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 ) ;
284 strcpy( driv.szDeviceName, pqp->pdriv->szDeviceName ) ;
285 // pqp->pdriv->szDeviceName[0] = '\0' ; /* to check if 'cancel' selected */
286 lBytes = DevPostDeviceModes( hab,
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 ???? */
298 return ( (int) lBytes ) ;
301 static void ThreadPrintPage( PRINTPARAMS *ptp )
303 ** thread to set up printer DC and print page
305 ** Input: THREADPARAMS *ptp -- pointer to thread data passed by beginthread
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
321 hab = WinInitialize( 0 ) ;
323 szPrintFile = ptp->szPrintFile[0] == '\0' ? NULL : ptp->szPrintFile ;
325 if( (hdc = OpenPrinterDC( hab, ptp->pqp, 0L, szPrintFile )) != DEV_ERROR ) {
327 // create presentation space for printer
330 hmf = CopyToMetaFile( ptp->hps ) ;
333 sizPage.cx = GNUXPAGE;
334 sizPage.cy = GNUYPAGE;
335 hps = GpiCreatePS( hab,
338 PU_HIMETRIC | GPIF_DEFAULT | GPIT_NORMAL | GPIA_ASSOC ) ;
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] ;
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) ;
354 else if( ys < xs/ratio ) { /* reduce xs to fit */
355 rectPage.xRight = rectPage.xLeft + (int)(ys*ratio) ;
359 rectPage.xRight = rectPage.xRight*ptp->pqp->xfrac ;
360 rectPage.yTop = rectPage.yTop*ptp->pqp->yfrac ;//alPage[1]*(1.0-flYFrac) ;
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) ;
369 else if( ys < xs/ratio ) { /* reduce xs to fit */
370 rectPage.xRight = rectPage.xLeft + (int)(ys*ratio) ;
382 NULL ) != DEVESC_ERROR ) {
386 rc = GpiSetPageViewport( hps, &rectPage ) ;
389 alOpt[1] = LT_ORIGINALVIEW ;
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 ) ;
400 DevEscape( hdc, DEVESC_ENDDOC, 0L, NULL, NULL, NULL ) ;
401 msgRet = WM_USER_PRINT_OK ;
404 msgRet = WM_USER_PRINT_ERROR;
408 msgRet = WM_USER_PRINT_ERROR ;
410 GpiDestroyPS( hps ) ;
414 msgRet = WM_USER_DEV_ERROR ;
417 WinPostMsg( ptp->hwnd, msgRet, (MPARAM)WinGetLastError(hab), 0L ) ;
418 WinTerminate( hab ) ;
421 HDC OpenPrinterDC( HAB hab, PQPRINT pqp, LONG lMode, char *szPrintFile )
423 ** get printer info from os2.ini and set up DC
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)
432 ** Return: HDC -- handle of printer device context
433 ** = DEV_ERROR (=0) if error
437 static CHAR achPrinterData[256] ;
439 if( pqp->piPrinter == NULL ) return DEV_ERROR ;
441 strcpy( achPrinterData, pqp->piPrinter->pszDriverName ) ;
442 achPrinterData[ strcspn(achPrinterData,".") ] = '\0' ;
444 devop.pszDriverName = achPrinterData ;
445 devop.pszLogAddress = pqp->piPrinter->pszName ;
447 if( pqp->pdriv != NULL
448 && strcmp( pqp->pdriv->szDeviceName, pqp->piPrinter->pDriverData->szDeviceName ) == 0 ) {
449 devop.pdriv = pqp->pdriv ;
451 else devop.pdriv = pqp->piPrinter->pDriverData ;
453 if( szPrintFile != NULL ) devop.pszLogAddress = szPrintFile ;
455 // set data type to RAW
457 devop.pszDataType = "PM_Q_RAW" ;
459 // open device context
463 lType = (szPrintFile == NULL) ? OD_QUEUED: OD_DIRECT ;
465 return DevOpenDC( hab, // WinQueryAnchorBlock( hwnd ),
469 (PDEVOPENDATA) &devop,
473 int FindPrinter( char *szName, PPRQINFO3 piPrinter )
475 ** Find a valid printer
478 PPRQINFO3 pprq = NULL ;
479 PDRIVDATA pdriv = NULL ;
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 ) ;
495 memcpy( piPrinter, &pprq[0], sizeof( PRQINFO3 ) ) ;
500 MRESULT EXPENTRY CancelPrintDlgProc ( HWND hwnd, ULONG usMsg, MPARAM mp1, MPARAM mp2 )
502 ** Cancel printing dialog box proc
508 switch ( SHORT1FROMMP(mp1) ) {
510 WinSendMsg( WinQueryWindow( hwnd, QW_OWNER ),
511 WM_USER_PRINT_CANCEL,
514 WinDismissDlg( hwnd, 0 ) ;
522 /* fall through to the default control processing */
523 return WinDefDlgProc ( hwnd , usMsg , mp1 , mp2 ) ;