source: trunk/Lucide/gui/print.cpp @ 393

Last change on this file since 393 was 367, checked in by dmik, 12 years ago

Merged bramches/kmk (r294:365) to trunk.

File size: 15.8 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_SPL
36#define INCL_SPLDOSPRINT
37#include "os2all.h"
38
39#include <ludoc.xh>
40
41#include <string.h>
42#include <process.h>
43#include <stdio.h>
44#include <io.h>
45#include <algorithm>
46
47#include "globals.h"
48#include "progressDlg.h"
49#include "print.h"
50#include "luutils.h"
51#include "messages.h"
52
53
54#ifndef DEVESC_ERROR
55#define DEVESC_ERROR        (-1L)
56#endif
57
58#define UNITS_MULTIPLIER    100
59#define STD_IMAGE_ZOOM      2.0
60#define HIGH_IMAGE_ZOOM     3.0
61#define PS_PRINT_BUF_SIZE   32768
62
63
64class LucidePrinting
65{
66    public:
67        LucidePrinting( HWND hWndFrame, LuDocument *_doc,
68                        const char *_title, PrintSetup *_psetup );
69        ~LucidePrinting();
70        void doPrint();
71
72    private:
73        bool queryCurrentForm( HAB lhab, PHCINFO pcurForm );
74        void printPagePm( long page, HPS hpsPrinter, PHCINFO pcurForm );
75        bool doPmPrint( HAB lhab );
76        bool doPsPrint( HAB lhab );
77
78        HWND hFrame;
79        LuDocument *doc;
80        char *title;
81        PrintSetup *psetup;
82        boolean abortPrinting;
83        ProgressDlg *progressDlg;
84
85        static void printabort( void *data );
86        static void printthread( void *data );
87};
88
89
90void printDocument( HWND hWndFrame, LuDocument *doc, const char *title, PrintSetup *psetup )
91{
92    LucidePrinting *p = new LucidePrinting( hWndFrame, doc, title, psetup );
93    p->doPrint();
94}
95
96
97LucidePrinting::LucidePrinting( HWND hWndFrame, LuDocument *_doc,
98                                const char *_title, PrintSetup *_psetup )
99{
100    hFrame = hWndFrame;
101    doc    = _doc;
102    title  = newstrdup( _title );
103    psetup = new PrintSetup;
104    memcpy( psetup, _psetup, sizeof( PrintSetup ) );
105    abortPrinting = false;
106    progressDlg = new ProgressDlg( hWndFrame );
107}
108
109LucidePrinting::~LucidePrinting()
110{
111    delete title;
112    delete psetup;
113    delete progressDlg;
114}
115
116void LucidePrinting::doPrint()
117{
118    progressDlg->setBreakFunc( printabort, this );
119    progressDlg->setText( "" );
120    progressDlg->show( printthread, this );
121}
122
123static bool isPrintPageNum( PrintOddEven oddeven, long page )
124{
125    if ( oddeven == OEOdd ) {
126        return ( ( page % 2 ) != 0 );
127    }
128    else if ( oddeven == OEEven ) {
129        return ( ( page % 2 ) == 0 );
130    }
131    return true;
132}
133
134static long countPagesToPrint( PrintOddEven oddeven, long pgfrom, long pgto )
135{
136    long r = 0;
137    for ( long i = pgfrom; i <= pgto; i++ ) {
138        if ( isPrintPageNum( oddeven, i ) ) {
139            r++;
140        }
141    }
142    return r;
143}
144
145bool LucidePrinting::doPmPrint( HAB lhab )
146{
147    CHAR         achDriverName[ DRIVERNAME_LENGTH ] = "";
148    CHAR         achQueueProcParams[ 8 ] = "";
149    DEVOPENSTRUC dos   = { 0 };
150    SIZEL        sizel = { 0 };
151
152    HCINFO curForm = { 0 };
153    if ( !queryCurrentForm( lhab, &curForm ) ) {
154        return false;
155    }
156
157    // build a devopenstruct for the call to DevOpenDC
158    dos.pszLogAddress      = psetup->QueueInfo.pszName;              // 1
159    strcpy( achDriverName, psetup->QueueInfo.pszDriverName );
160    achDriverName[ strcspn( achDriverName, "." ) ] = '\0';
161    dos.pszDriverName      = achDriverName;                          // 2
162    dos.pdriv              = psetup->QueueInfo.pDriverData;          // 3
163    dos.pszDataType        = "PM_Q_RAW";                             // 4
164    dos.pszComment         = (PSZ)appName;                           // 5
165    dos.pszQueueProcName   = NULL;                                   // 6
166    snprintf( achQueueProcParams, sizeof( achQueueProcParams ), "COP=%d", psetup->copies );
167    dos.pszQueueProcParams = achQueueProcParams;                     // 7
168
169    HDC hdcPrinter = DevOpenDC( lhab, OD_QUEUED, "*", 7L, (PDEVOPENDATA)&dos, NULLHANDLE );
170    if ( hdcPrinter == DEV_ERROR ) {
171        return false;
172    }
173
174    // PS in HiMetric, 0.01 mm
175    HPS hpsPrinter = GpiCreatePS( lhab, hdcPrinter, &sizel, PU_HIMETRIC | GPIA_ASSOC );
176    if ( hpsPrinter == DEV_ERROR ) {
177        DevCloseDC( hdcPrinter );
178        return false;
179    }
180
181    // Issue STARTDOC to begin printing
182    DevEscape( hdcPrinter, DEVESC_STARTDOC, strlen(title), (PBYTE)title, NULL, NULL );
183
184    long pgfrom = psetup->pgfrom;
185    long pgto = psetup->pgto;
186    if ( pgfrom > pgto ) {
187        long tmp = pgfrom;
188        pgfrom = pgto;
189        pgto = tmp;
190    }
191
192    long pagestoprint = countPagesToPrint( psetup->oddeven, pgfrom, pgto );
193    long pg = psetup->pgfrom;
194    for ( long i = pgfrom, j = 1; i <= pgto; i++ )
195    {
196        if ( isPrintPageNum( psetup->oddeven, pg ) )
197        {
198            char *fmt = newstrdupL( PRINT_PRINTING_PAGE_OF );
199            char *buf = new char[ 255 ];
200            snprintf( buf, 255, fmt, pg, j++, pagestoprint );
201            progressDlg->setText( buf );
202            delete fmt;
203            delete buf;
204
205            printPagePm( pg - 1, hpsPrinter, &curForm );
206
207            if ( pg != psetup->pgto ) {
208                DevEscape( hdcPrinter, DEVESC_NEWFRAME, 0L, NULL, NULL, NULL );
209            }
210        }
211
212        if ( abortPrinting ) {
213            break;
214        }
215
216        pg += ( psetup->pgfrom <= psetup->pgto ) ? 1 : -1;
217    }
218
219    // Issue DEVESC_ENDDOC, or DEVESC_ABORTDOC if printing was aborted
220    DevEscape( hdcPrinter, abortPrinting ? DEVESC_ABORTDOC : DEVESC_ENDDOC,
221               0L, NULL, NULL, NULL );
222
223    // Release PS and DC
224    GpiAssociate( hpsPrinter, NULLHANDLE );
225    GpiDestroyPS( hpsPrinter );
226    DevCloseDC( hdcPrinter );
227    return true;
228}
229
230
231void LucidePrinting::printPagePm( long page, HPS hpsPrinter, PHCINFO pcurForm )
232{
233    long bpp = doc->getBpp( ev );
234    double w = 0, h = 0;
235    doc->getPageSize( ev, page, &w, &h );
236
237    // Magrins
238    LONG mLeft   = psetup->margin_left;
239    LONG mBottom = psetup->margin_bottom;
240    LONG mRight  = psetup->margin_right;
241    LONG mTop    = psetup->margin_top;
242
243    // Count paper page size in hi-metric
244    LONG pwidth = ( pcurForm->cx - psetup->margin_left - mRight ) * UNITS_MULTIPLIER;
245    LONG pheight = ( pcurForm->cy - mTop - mBottom ) * UNITS_MULTIPLIER;
246
247    double zoom = 1.0;
248    if ( doc->isScalable( ev ) && !doc->isFixedImage( ev ) )
249    {
250        double maxcoeff = psetup->higherQuality ? HIGH_IMAGE_ZOOM : STD_IMAGE_ZOOM;
251        zoom = std::min( (double)pwidth / w, (double)pheight / h );
252        if ( zoom > maxcoeff ) {
253            zoom = maxcoeff;
254        }
255    }
256
257    //somPrintf( "Doc pgsz: %g/%g  zoom: %g\n", w, h, zoom );
258    //somPrintf( "Paper %s, pgsz: %d/%d\n", pcurForm->szFormname, pcurForm->cx, pcurForm->cy );
259    //somPrintf( "pw/ph %d/%d\n", pwidth, pheight );
260
261    w *= zoom;
262    h *= zoom;
263    double pgzoom = std::min( (double)pwidth / w, (double)pheight / h );
264
265    // Printed size
266    LONG prwidth = w * pgzoom;
267    LONG prheight = h * pgzoom;
268    LONG yPos = 0;
269    if ( prheight < pheight ) {
270        yPos = pheight - prheight;
271    }
272    RECTL rclDraw = { psetup->margin_left*UNITS_MULTIPLIER, (mBottom*UNITS_MULTIPLIER)+yPos,
273                      prwidth, prheight+yPos };
274
275    LONG rclx = w;
276    LONG rcly = h;
277
278    if ( doc->isRenderIntoPS( ev ) )
279    {
280        doc->renderPageToPS( ev, page, 0, 0, rclx, rcly, zoom, 0, hpsPrinter, &rclDraw,
281                             NULL, NULL );
282    }
283    else
284    {
285        LuPixbuf *pixbuf = new LuPixbuf( ev, rclx, rcly, bpp );
286        POINTL aptlPoints[4]={ rclDraw.xLeft, rclDraw.yBottom,
287                               rclDraw.xRight-1, rclDraw.yTop-1,
288                               0, 0, rclx, rcly };
289
290        doc->renderPageToPixbuf( ev, page, 0, 0, rclx, rcly, zoom, 0, pixbuf,
291                                 NULL, NULL );
292
293        LONG lRop = ROP_SRCCOPY;
294        BITMAPINFO2 pbmi;
295        pbmi.cbFix = 16L;
296        pbmi.cx = rclx;
297        pbmi.cy = rcly;
298        pbmi.cPlanes = 1;
299        pbmi.cBitCount = bpp * 8;
300        GpiDrawBits( hpsPrinter, pixbuf->getDataPtr( ev ), &pbmi, 4L,
301                     aptlPoints, lRop, BBO_IGNORE );
302        delete pixbuf;
303    }
304}
305
306
307bool LucidePrinting::doPsPrint( HAB lhab )
308{
309    CHAR         achDriverName[ DRIVERNAME_LENGTH ] = "";
310    CHAR         achQueueProcParams[ 8 ] = "";
311    DEVOPENSTRUC dos   = { 0 };
312    SIZEL        sizel = { 0 };
313
314    HCINFO curForm = { 0 };
315    if ( !queryCurrentForm( lhab, &curForm ) ) {
316        return false;
317    }
318
319    char *generating_ps = newstrdupL( PRINT_GENERATING_POSTSCRIPT );
320    progressDlg->setText( generating_ps );
321    delete generating_ps;
322
323    // Magrins
324    LONG mLeft   = psetup->margin_left;
325    LONG mBottom = psetup->margin_bottom;
326    LONG mRight  = psetup->margin_right;
327    LONG mTop    = psetup->margin_top;
328
329    // Count paper page size in 1/72 inches
330    double pwidth = ( (double)( curForm.cx - mLeft - mRight ) / 25.4 ) * 72.0;
331    double pheight = ( (double)( curForm.cy - mTop - mBottom ) / 25.4 ) * 72.0;
332
333    char tmpps[ CCHMAXPATH ] = "";
334    if ( psetup->psToFile ) {
335        strcpy( tmpps, psetup->psFile );
336    }
337    else {
338        getTmpDir( tmpps );
339        strcat( tmpps, "TMPLUCID.PS" );
340    }
341
342    boolean rcexp = doc->exportToPostScript( ev, tmpps, psetup->pgfrom-1, psetup->pgto-1,
343                                             pwidth, pheight, &abortPrinting );
344
345    if ( abortPrinting ) {
346        unlink( tmpps );
347        return true;
348    }
349    if ( !rcexp ) {
350        unlink( tmpps );
351        return false;
352    }
353
354    if ( !psetup->psToFile )
355    {
356        char *spooling_ps = newstrdupL( PRINT_SPOOLING_POSTSCRIPT );
357        progressDlg->setText( spooling_ps );
358        delete spooling_ps;
359
360        // build a devopenstruct for the call to DevOpenDC
361        dos.pszLogAddress      = psetup->QueueInfo.pszName;              // 1
362        strcpy( achDriverName, psetup->QueueInfo.pszDriverName );
363        achDriverName[ strcspn( achDriverName, "." ) ] = '\0';
364        dos.pszDriverName      = achDriverName;                          // 2
365        dos.pdriv              = psetup->QueueInfo.pDriverData;          // 3
366        dos.pszDataType        = "PM_Q_RAW";                             // 4
367        dos.pszComment         = (PSZ)appName;                           // 5
368        dos.pszQueueProcName   = NULL;                                   // 6
369        snprintf( achQueueProcParams, sizeof( achQueueProcParams ), "COP=%d", psetup->copies );
370        dos.pszQueueProcParams = achQueueProcParams;                     // 7
371
372        HDC hdcPrinter = DevOpenDC( lhab, OD_QUEUED, "*", 7L, (PDEVOPENDATA)&dos, NULLHANDLE );
373        if ( hdcPrinter == DEV_ERROR ) {
374            unlink( tmpps );
375            return false;
376        }
377
378        // Issue STARTDOC to begin printing
379        LONG rc = DevEscape( hdcPrinter, DEVESC_STARTDOC, strlen(title), (PBYTE)title, NULL, NULL );
380        if ( rc == DEVESC_ERROR ) {
381            DevCloseDC( hdcPrinter );
382            unlink( tmpps );
383            return false;
384        }
385
386        FILE *f = fopen( tmpps, "rb" );
387        if ( f == NULL ) {
388            DevEscape( hdcPrinter, DEVESC_ABORTDOC, 0L, NULL, NULL, NULL );
389            DevCloseDC( hdcPrinter );
390            unlink( tmpps );
391            return false;
392        }
393
394        bool splerr = false;
395        void *buf = malloc( PS_PRINT_BUF_SIZE );
396        int rd = 0;
397        while ( ( rc != DEVESC_ERROR ) && ( rd = fread( buf, 1, PS_PRINT_BUF_SIZE, f ) ) != 0 )
398        {
399            rc = DevEscape( hdcPrinter, DEVESC_RAWDATA, rd, (PBYTE)buf, NULL, NULL );
400            if ( ( rc == DEVESC_ERROR ) || abortPrinting ) {
401                splerr = true;
402                break;
403            }
404        }
405        free( buf );
406        fclose( f );
407        unlink( tmpps );
408
409        DevEscape( hdcPrinter, splerr ? DEVESC_ABORTDOC : DEVESC_ENDDOC,
410                   0L, NULL, NULL, NULL );
411        DevCloseDC( hdcPrinter );
412
413        if ( splerr && !abortPrinting ) {
414            return false;
415        }
416    }
417
418    return true;
419}
420
421
422bool LucidePrinting::queryCurrentForm( HAB lhab, PHCINFO pcurForm )
423{
424    CHAR         achDriverName[ DRIVERNAME_LENGTH ] = "";
425    DEVOPENSTRUC dos   = { 0 };
426    // build a devopenstruct for the call to DevOpenDC
427    dos.pszLogAddress = psetup->QueueInfo.pszName;              // 1
428    strcpy( achDriverName, psetup->QueueInfo.pszDriverName );
429    achDriverName[ strcspn( achDriverName, "." ) ] = '\0';
430    dos.pszDriverName = achDriverName;                          // 2
431    dos.pdriv = psetup->QueueInfo.pDriverData;                  // 3
432
433    HDC hdcPrinterInfo = DevOpenDC( lhab, OD_INFO, "*", 3L, (PDEVOPENDATA)&dos, NULLHANDLE );
434    if ( hdcPrinterInfo == DEV_ERROR ) {
435        return false;
436    }
437
438    LONG lForms = DevQueryHardcopyCaps( hdcPrinterInfo, 0, 0, NULL );
439    if ( lForms == DQHC_ERROR ) {
440        DevCloseDC( hdcPrinterInfo );
441        return false;
442    }
443
444    HCINFO *forms = new HCINFO[ lForms ];
445    memset( forms, 0, sizeof( HCINFO ) * lForms );
446    lForms = DevQueryHardcopyCaps( hdcPrinterInfo, 0, lForms, forms );
447    if ( lForms == DQHC_ERROR ) {
448        delete forms;
449        DevCloseDC( hdcPrinterInfo );
450        return false;
451    }
452
453    for ( LONG i = 0; i < lForms; i++ ) {
454        if ( forms[i].flAttributes & HCAPS_CURRENT ) {
455            memcpy( pcurForm, &( forms[i] ), sizeof( HCINFO ) );
456            break;
457        }
458    }
459
460    delete forms;
461    DevCloseDC( hdcPrinterInfo );
462    return true;
463}
464
465// static method
466void LucidePrinting::printabort( void *data )
467{
468    ((LucidePrinting *)data)->abortPrinting = true;
469}
470
471// static method, thread for asynchronous printing
472void LucidePrinting::printthread( void *p )
473{
474    DosSetPriority( PRTYS_THREAD, PRTYC_IDLETIME, PRTYD_MAXIMUM, 0 );
475    LucidePrinting *_this = (LucidePrinting *)p;
476
477    HAB thab = WinInitialize( 0 );
478    HMQ thmq = WinCreateMsgQueue( thab, 0 );
479
480    bool printOk = false;
481    if ( _this->psetup->ptype == TypePostScript ) {
482        printOk = _this->doPsPrint( thab );
483    }
484    else {
485        printOk = _this->doPmPrint( thab );
486    }
487    _this->progressDlg->hide();
488
489    if ( !printOk )
490    {
491        char *printfailed = newstrdupL( PRINT_FAILED );
492        WinMessageBox( HWND_DESKTOP, _this->hFrame, printfailed, NULL,
493                       1, MB_OK | MB_ERROR | MB_MOVEABLE );
494        delete printfailed;
495    }
496
497    WinDestroyMsgQueue( thmq );
498    WinTerminate( thab );
499    _endthread();
500
501    delete _this;
502}
503
Note: See TracBrowser for help on using the repository browser.