source: trunk/Lucide/SOURCE/gui/print.cpp @ 162

Last change on this file since 162 was 162, checked in by Eugene Romanenko, 14 years ago

'pring to file' option for postscript output

File size: 16.2 KB
Line 
1/* ***** BEGIN LICENSE BLOCK *****
2 * Version: CDDL 1.0/LGPL 2.1
3 *
4 * The contents of this file are subject to the COMMON DEVELOPMENT AND
5 * DISTRIBUTION LICENSE (CDDL) Version 1.0 (the "License"); you may not use
6 * this file except in compliance with the License. You may obtain a copy of
7 * the License at http://www.sun.com/cddl/
8 *
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
13 *
14 * The Initial Developer of the Original Code is
15 * Eugene Romanenko, netlabs.org.
16 * Portions created by the Initial Developer are Copyright (C) 2006
17 * the Initial Developer. All Rights Reserved.
18 *
19 * Contributor(s):
20 *
21 * Alternatively, the contents of this file may be used under the terms of
22 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
23 * in which case the provisions of the LGPL are applicable instead of those
24 * above. If you wish to allow use of your version of this file only under the
25 * terms of the LGPL, and not to allow others to use your version of this file
26 * under the terms of the CDDL, indicate your decision by deleting the
27 * provisions above and replace them with the notice and other provisions
28 * required by the LGPL. If you do not delete the provisions above, a recipient
29 * may use your version of this file under the terms of any one of the CDDL
30 * or the LGPL.
31 *
32 * ***** END LICENSE BLOCK ***** */
33
34
35#define INCL_WIN
36#define INCL_GPI
37#define INCL_DOS
38#define INCL_DEV
39#define INCL_ERRORS
40#define INCL_SPL
41#define INCL_SPLDOSPRINT
42#include <os2.h>
43
44#include <ludoc.xh>
45
46#include <string.h>
47#include <process.h>
48#include <stdio.h>
49#include <io.h>
50
51#include "globals.h"
52#include "progressDlg.h"
53#include "print.h"
54#include "luutils.h"
55#include "messages.h"
56
57// OpenWatcom headers doesn't have GpiDrawBits() declaration
58extern "C" {
59    LONG APIENTRY GpiDrawBits(HPS hps, PVOID pBits, PBITMAPINFO2 pbmiInfoTable,
60                              LONG lCount, PPOINTL aptlPoints, LONG lRop, ULONG flOptions);
61}
62
63#ifndef DEVESC_ERROR
64#define DEVESC_ERROR        (-1L)
65#endif
66
67#define UNITS_MULTIPLIER    100
68#define STD_IMAGE_ZOOM      2.0
69#define HIGH_IMAGE_ZOOM     3.0
70#define PS_PRINT_BUF_SIZE   32768
71
72
73class LucidePrinting
74{
75    public:
76        LucidePrinting( HWND hWndFrame, LuDocument *_doc,
77                        const char *_title, PrintSetup *_psetup );
78        ~LucidePrinting();
79        void doPrint();
80
81    private:
82        bool queryCurrentForm( HAB lhab, PHCINFO pcurForm );
83        void printPagePm( long page, HPS hpsPrinter, PHCINFO pcurForm );
84        bool doPmPrint( HAB lhab );
85        bool doPsPrint( HAB lhab );
86
87        HWND hFrame;
88        LuDocument *doc;
89        char *title;
90        PrintSetup *psetup;
91        boolean abortPrinting;
92        ProgressDlg *progressDlg;
93
94        static void printabort( void *data );
95        static void printthread( void *data );
96};
97
98
99void printDocument( HWND hWndFrame, LuDocument *doc, const char *title, PrintSetup *psetup )
100{
101    LucidePrinting *p = new LucidePrinting( hWndFrame, doc, title, psetup );
102    p->doPrint();
103}
104
105
106LucidePrinting::LucidePrinting( HWND hWndFrame, LuDocument *_doc,
107                                const char *_title, PrintSetup *_psetup )
108{
109    hFrame = hWndFrame;
110    doc    = _doc;
111    title  = newstrdup( _title );
112    psetup = new PrintSetup;
113    memcpy( psetup, _psetup, sizeof( PrintSetup ) );
114    abortPrinting = false;
115    progressDlg = new ProgressDlg( hWndFrame );
116}
117
118LucidePrinting::~LucidePrinting()
119{
120    delete title;
121    delete psetup;
122    delete progressDlg;
123}
124
125void LucidePrinting::doPrint()
126{
127    progressDlg->setBreakFunc( printabort, this );
128    progressDlg->setText( "" );
129    progressDlg->show( printthread, this );
130}
131
132bool LucidePrinting::doPmPrint( HAB lhab )
133{
134    CHAR         achDriverName[ DRIVERNAME_LENGTH ] = "";
135    CHAR         achQueueProcParams[ 8 ] = "";
136    DEVOPENSTRUC dos   = { 0 };
137    SIZEL        sizel = { 0 };
138
139    HCINFO curForm = { 0 };
140    if ( !queryCurrentForm( lhab, &curForm ) ) {
141        return false;
142    }
143
144    // build a devopenstruct for the call to DevOpenDC
145    dos.pszLogAddress      = psetup->QueueInfo.pszName;              // 1
146    strcpy( achDriverName, psetup->QueueInfo.pszDriverName );
147    achDriverName[ strcspn( achDriverName, "." ) ] = '\0';
148    dos.pszDriverName      = achDriverName;                          // 2
149    dos.pdriv              = psetup->QueueInfo.pDriverData;          // 3
150    dos.pszDataType        = "PM_Q_STD";                             // 4
151    dos.pszComment         = (PSZ)appName;                           // 5
152    dos.pszQueueProcName   = NULL;                                   // 6
153    snprintf( achQueueProcParams, sizeof( achQueueProcParams ), "COP=%d", psetup->copies );
154    dos.pszQueueProcParams = achQueueProcParams;                     // 7
155
156    HDC hdcPrinter = DevOpenDC( lhab, OD_QUEUED, "*", 7L, (PDEVOPENDATA)&dos, NULLHANDLE );
157    if ( hdcPrinter == DEV_ERROR ) {
158        return false;
159    }
160
161    // PS in HiMetric, 0.01 mm
162    HPS hpsPrinter = GpiCreatePS( lhab, hdcPrinter, &sizel, PU_HIMETRIC | GPIA_ASSOC );
163    if ( hpsPrinter == DEV_ERROR ) {
164        DevCloseDC( hdcPrinter );
165        return false;
166    }
167
168    // Issue STARTDOC to begin printing
169    DevEscape( hdcPrinter, DEVESC_STARTDOC, strlen(title), (PBYTE)title, NULL, NULL );
170
171
172    long totalpages = abs( psetup->pgto - psetup->pgfrom ) + 1;
173    long pg = psetup->pgfrom;
174    for ( long i = 0; i < totalpages; i++ )
175    {
176        char *fmt = newstrdupL( PRINT_PRINTING_PAGE_OF );
177        char *buf = new char[ 255 ];
178        snprintf( buf, 255, fmt, pg, i + 1, totalpages );
179        progressDlg->setText( buf );
180        delete fmt;
181        delete buf;
182
183        printPagePm( pg - 1, hpsPrinter, &curForm );
184
185        if ( pg != psetup->pgto ) {
186            DevEscape( hdcPrinter, DEVESC_NEWFRAME, 0L, NULL, NULL, NULL );
187        }
188
189        if ( abortPrinting ) {
190            break;
191        }
192
193        pg += ( psetup->pgfrom <= psetup->pgto ) ? 1 : -1;
194    }
195
196    // Issue DEVESC_ENDDOC, or DEVESC_ABORTDOC if printing was aborted
197    DevEscape( hdcPrinter, abortPrinting ? DEVESC_ABORTDOC : DEVESC_ENDDOC,
198               0L, NULL, NULL, NULL );
199
200    // Release PS and DC
201    GpiAssociate( hpsPrinter, NULLHANDLE );
202    GpiDestroyPS( hpsPrinter );
203    DevCloseDC( hdcPrinter );
204    return true;
205}
206
207
208void LucidePrinting::printPagePm( long page, HPS hpsPrinter, PHCINFO pcurForm )
209{
210    long bpp = doc->getBpp( ev );
211    double w = 0, h = 0;
212    doc->getPageSize( ev, page, &w, &h );
213
214    // Magrins
215    LONG mLeft   = __max( psetup->margin_left, pcurForm->xLeftClip );
216    LONG mBottom = __max( psetup->margin_bottom, pcurForm->yBottomClip );
217    LONG mRight  = __max( psetup->margin_right, pcurForm->cx - pcurForm->xRightClip );
218    LONG mTop    = __max( psetup->margin_top, pcurForm->cy - pcurForm->yTopClip );
219
220    // Count paper page size in hi-metric
221    LONG pwidth = ( pcurForm->cx - mLeft - mRight ) * UNITS_MULTIPLIER;
222    LONG pheight = ( pcurForm->cy - mTop - mBottom ) * UNITS_MULTIPLIER;
223
224    double zoom = 1.0;
225    if ( doc->isScalable( ev ) && !doc->isFixedImage( ev ) )
226    {
227        double maxcoeff = psetup->higherQuality ? HIGH_IMAGE_ZOOM : STD_IMAGE_ZOOM;
228        zoom = __min( (double)pwidth / w, (double)pheight / h );
229        if ( zoom > maxcoeff ) {
230            zoom = maxcoeff;
231        }
232    }
233
234    //somPrintf( "Doc pgsz: %g/%g  zoom: %g\n", w, h, zoom );
235    //somPrintf( "Paper %s, pgsz: %d/%d\n", pcurForm->szFormname, pcurForm->cx, pcurForm->cy );
236    //somPrintf( "pw/ph %d/%d\n", pwidth, pheight );
237
238    w *= zoom;
239    h *= zoom;
240    double pgzoom = __min( (double)pwidth / w, (double)pheight / h );
241
242    // Printed size
243    LONG prwidth = w * pgzoom;
244    LONG prheight = h * pgzoom;
245    LONG yPos = 0;
246    if ( prheight < pheight ) {
247        yPos = pheight - prheight;
248    }
249    RECTL rclDraw = { mLeft*UNITS_MULTIPLIER, (mBottom*UNITS_MULTIPLIER)+yPos,
250                      prwidth, prheight+yPos };
251
252    LONG rclx = w;
253    LONG rcly = h;
254
255    if ( doc->isRenderIntoPS( ev ) )
256    {
257        doc->renderPageToPS( ev, page, 0, 0, rclx, rcly, zoom, 0, hpsPrinter, &rclDraw,
258                             NULL, NULL );
259    }
260    else
261    {
262        LuPixbuf *pixbuf = new LuPixbuf( ev, rclx, rcly, bpp );
263        POINTL aptlPoints[4]={ rclDraw.xLeft, rclDraw.yBottom,
264                               rclDraw.xRight-1, rclDraw.yTop-1,
265                               0, 0, rclx, rcly };
266
267        doc->renderPageToPixbuf( ev, page, 0, 0, rclx, rcly, zoom, 0, pixbuf,
268                                 NULL, NULL );
269
270        LONG lRop = ROP_SRCCOPY;
271        BITMAPINFO2 pbmi;
272        pbmi.cbFix = 16L;
273        pbmi.cx = rclx;
274        pbmi.cy = rcly;
275        pbmi.cPlanes = 1;
276        pbmi.cBitCount = bpp * 8;
277        GpiDrawBits( hpsPrinter, pixbuf->getDataPtr( ev ), &pbmi, 4L,
278                     aptlPoints, lRop, BBO_IGNORE );
279        delete pixbuf;
280    }
281}
282
283
284bool LucidePrinting::doPsPrint( HAB lhab )
285{
286    CHAR         achDriverName[ DRIVERNAME_LENGTH ] = "";
287    CHAR         achQueueProcParams[ 8 ] = "";
288    DEVOPENSTRUC dos   = { 0 };
289    SIZEL        sizel = { 0 };
290
291    HCINFO curForm = { 0 };
292    if ( !queryCurrentForm( lhab, &curForm ) ) {
293        return false;
294    }
295
296    char *generating_ps = newstrdupL( PRINT_GENERATING_POSTSCRIPT );
297    progressDlg->setText( generating_ps );
298    delete generating_ps;
299
300    // Magrins
301    LONG mLeft   = __max( psetup->margin_left, curForm.xLeftClip );
302    LONG mBottom = __max( psetup->margin_bottom, curForm.yBottomClip );
303    LONG mRight  = __max( psetup->margin_right, curForm.cx - curForm.xRightClip );
304    LONG mTop    = __max( psetup->margin_top, curForm.cy - curForm.yTopClip );
305
306    // Count paper page size in 1/72 inches
307    double pwidth = ( (double)( curForm.cx - mLeft - mRight ) / 25.4 ) * 72.0;
308    double pheight = ( (double)( curForm.cy - mTop - mBottom ) / 25.4 ) * 72.0;
309
310    char tmpps[ CCHMAXPATH ] = "";
311    if ( psetup->psToFile )
312    {
313        strcpy( tmpps, title );
314        char *pointpos = strrchr( tmpps, '.' );
315        if ( pointpos != NULL ) {
316            *pointpos = 0;
317        }
318        strcat( tmpps, ".ps" );
319
320        PFILEDLG fd = new FILEDLG;
321        memset( fd, 0, sizeof( FILEDLG ) );
322        fd->cbSize = sizeof( FILEDLG );
323        fd->fl = FDS_CENTER | FDS_SAVEAS_DIALOG;
324        strcpy( fd->szFullFile, tmpps );
325        WinFileDlg( HWND_DESKTOP, hFrame, fd );
326        if ( fd->lReturn == DID_OK ) {
327            strcpy( tmpps, fd->szFullFile );
328            delete fd;
329        }
330        else {
331            delete fd;
332            return true;
333        }
334    }
335    else {
336        getTmpDir( tmpps );
337        strcat( tmpps, "TMPLUCID.PS" );
338    }
339
340    boolean rcexp = doc->exportToPostScript( ev, tmpps, psetup->pgfrom-1, psetup->pgto-1,
341                                             pwidth, pheight, &abortPrinting );
342
343    if ( abortPrinting ) {
344        unlink( tmpps );
345        return true;
346    }
347    if ( !rcexp ) {
348        unlink( tmpps );
349        return false;
350    }
351
352    if ( !psetup->psToFile )
353    {
354        char *spooling_ps = newstrdupL( PRINT_SPOOLING_POSTSCRIPT );
355        progressDlg->setText( spooling_ps );
356        delete spooling_ps;
357
358        // build a devopenstruct for the call to DevOpenDC
359        dos.pszLogAddress      = psetup->QueueInfo.pszName;              // 1
360        strcpy( achDriverName, psetup->QueueInfo.pszDriverName );
361        achDriverName[ strcspn( achDriverName, "." ) ] = '\0';
362        dos.pszDriverName      = achDriverName;                          // 2
363        dos.pdriv              = psetup->QueueInfo.pDriverData;          // 3
364        dos.pszDataType        = "PM_Q_RAW";                             // 4
365        dos.pszComment         = (PSZ)appName;                           // 5
366        dos.pszQueueProcName   = NULL;                                   // 6
367        snprintf( achQueueProcParams, sizeof( achQueueProcParams ), "COP=%d", psetup->copies );
368        dos.pszQueueProcParams = achQueueProcParams;                     // 7
369
370        HDC hdcPrinter = DevOpenDC( lhab, OD_QUEUED, "*", 7L, (PDEVOPENDATA)&dos, NULLHANDLE );
371        if ( hdcPrinter == DEV_ERROR ) {
372            unlink( tmpps );
373            return false;
374        }
375
376        // Issue STARTDOC to begin printing
377        LONG rc = DevEscape( hdcPrinter, DEVESC_STARTDOC, strlen(title), (PBYTE)title, NULL, NULL );
378        if ( rc == DEVESC_ERROR ) {
379            DevCloseDC( hdcPrinter );
380            unlink( tmpps );
381            return false;
382        }
383
384        FILE *f = fopen( tmpps, "rb" );
385        if ( f == NULL ) {
386            DevEscape( hdcPrinter, DEVESC_ABORTDOC, 0L, NULL, NULL, NULL );
387            DevCloseDC( hdcPrinter );
388            unlink( tmpps );
389            return false;
390        }
391
392        bool splerr = false;
393        void *buf = malloc( PS_PRINT_BUF_SIZE );
394        int rd = 0;
395        while ( ( rc != DEVESC_ERROR ) && ( rd = fread( buf, 1, PS_PRINT_BUF_SIZE, f ) ) != 0 )
396        {
397            rc = DevEscape( hdcPrinter, DEVESC_RAWDATA, rd, (char *)buf, NULL, NULL );
398            if ( ( rc == DEVESC_ERROR ) || abortPrinting ) {
399                splerr = true;
400                break;
401            }
402        }
403        free( buf );
404        fclose( f );
405        unlink( tmpps );
406
407        DevEscape( hdcPrinter, splerr ? DEVESC_ABORTDOC : DEVESC_ENDDOC,
408                   0L, NULL, NULL, NULL );
409        DevCloseDC( hdcPrinter );
410
411        if ( splerr && !abortPrinting ) {
412            return false;
413        }
414    }
415
416    return true;
417}
418
419
420bool LucidePrinting::queryCurrentForm( HAB lhab, PHCINFO pcurForm )
421{
422    CHAR         achDriverName[ DRIVERNAME_LENGTH ] = "";
423    DEVOPENSTRUC dos   = { 0 };
424    // build a devopenstruct for the call to DevOpenDC
425    dos.pszLogAddress = psetup->QueueInfo.pszName;              // 1
426    strcpy( achDriverName, psetup->QueueInfo.pszDriverName );
427    achDriverName[ strcspn( achDriverName, "." ) ] = '\0';
428    dos.pszDriverName = achDriverName;                          // 2
429    dos.pdriv = psetup->QueueInfo.pDriverData;                  // 3
430
431    HDC hdcPrinterInfo = DevOpenDC( lhab, OD_INFO, "*", 3L, (PDEVOPENDATA)&dos, NULLHANDLE );
432    if ( hdcPrinterInfo == DEV_ERROR ) {
433        return false;
434    }
435
436    LONG lForms = DevQueryHardcopyCaps( hdcPrinterInfo, 0, 0, NULL );
437    if ( lForms == DQHC_ERROR ) {
438        DevCloseDC( hdcPrinterInfo );
439        return false;
440    }
441
442    HCINFO *forms = new HCINFO[ lForms ];
443    memset( forms, 0, sizeof( HCINFO ) * lForms );
444    lForms = DevQueryHardcopyCaps( hdcPrinterInfo, 0, lForms, forms );
445    if ( lForms == DQHC_ERROR ) {
446        delete forms;
447        DevCloseDC( hdcPrinterInfo );
448        return false;
449    }
450
451    for ( LONG i = 0; i < lForms; i++ ) {
452        if ( forms[i].flAttributes & HCAPS_CURRENT ) {
453            memcpy( pcurForm, &( forms[i] ), sizeof( HCINFO ) );
454            break;
455        }
456    }
457
458    delete forms;
459    DevCloseDC( hdcPrinterInfo );
460    return true;
461}
462
463// static method
464void LucidePrinting::printabort( void *data )
465{
466    ((LucidePrinting *)data)->abortPrinting = true;
467}
468
469// static method, thread for asynchronous printing
470void LucidePrinting::printthread( void *p )
471{
472    DosSetPriority( PRTYS_THREAD, PRTYC_IDLETIME, PRTYD_MAXIMUM, 0 );
473    LucidePrinting *_this = (LucidePrinting *)p;
474
475    HAB thab = WinInitialize( 0 );
476    HMQ thmq = WinCreateMsgQueue( thab, 0 );
477
478    bool printOk = false;
479    if ( _this->psetup->ptype == TypePostScript ) {
480        printOk = _this->doPsPrint( thab );
481    }
482    else {
483        printOk = _this->doPmPrint( thab );
484    }
485    _this->progressDlg->hide();
486
487    if ( !printOk )
488    {
489        char *printfailed = newstrdupL( PRINT_FAILED );
490        WinMessageBox( HWND_DESKTOP, _this->hFrame, printfailed, NULL,
491                       1, MB_OK | MB_ERROR | MB_MOVEABLE );
492        delete printfailed;
493    }
494
495    WinDestroyMsgQueue( thmq );
496    WinTerminate( thab );
497    _endthread();
498
499    delete _this;
500}
501
Note: See TracBrowser for help on using the repository browser.