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

Last change on this file since 285 was 265, checked in by Eugene Romanenko, 12 years ago

small changes to make new openwatcom 1.8 happy

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