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