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

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

better place for ask about ps file location, not in thread

File size: 15.6 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        strcpy( tmpps, psetup->psFile );
313    }
314    else {
315        getTmpDir( tmpps );
316        strcat( tmpps, "TMPLUCID.PS" );
317    }
318
319    boolean rcexp = doc->exportToPostScript( ev, tmpps, psetup->pgfrom-1, psetup->pgto-1,
320                                             pwidth, pheight, &abortPrinting );
321
322    if ( abortPrinting ) {
323        unlink( tmpps );
324        return true;
325    }
326    if ( !rcexp ) {
327        unlink( tmpps );
328        return false;
329    }
330
331    if ( !psetup->psToFile )
332    {
333        char *spooling_ps = newstrdupL( PRINT_SPOOLING_POSTSCRIPT );
334        progressDlg->setText( spooling_ps );
335        delete spooling_ps;
336
337        // build a devopenstruct for the call to DevOpenDC
338        dos.pszLogAddress      = psetup->QueueInfo.pszName;              // 1
339        strcpy( achDriverName, psetup->QueueInfo.pszDriverName );
340        achDriverName[ strcspn( achDriverName, "." ) ] = '\0';
341        dos.pszDriverName      = achDriverName;                          // 2
342        dos.pdriv              = psetup->QueueInfo.pDriverData;          // 3
343        dos.pszDataType        = "PM_Q_RAW";                             // 4
344        dos.pszComment         = (PSZ)appName;                           // 5
345        dos.pszQueueProcName   = NULL;                                   // 6
346        snprintf( achQueueProcParams, sizeof( achQueueProcParams ), "COP=%d", psetup->copies );
347        dos.pszQueueProcParams = achQueueProcParams;                     // 7
348
349        HDC hdcPrinter = DevOpenDC( lhab, OD_QUEUED, "*", 7L, (PDEVOPENDATA)&dos, NULLHANDLE );
350        if ( hdcPrinter == DEV_ERROR ) {
351            unlink( tmpps );
352            return false;
353        }
354
355        // Issue STARTDOC to begin printing
356        LONG rc = DevEscape( hdcPrinter, DEVESC_STARTDOC, strlen(title), (PBYTE)title, NULL, NULL );
357        if ( rc == DEVESC_ERROR ) {
358            DevCloseDC( hdcPrinter );
359            unlink( tmpps );
360            return false;
361        }
362
363        FILE *f = fopen( tmpps, "rb" );
364        if ( f == NULL ) {
365            DevEscape( hdcPrinter, DEVESC_ABORTDOC, 0L, NULL, NULL, NULL );
366            DevCloseDC( hdcPrinter );
367            unlink( tmpps );
368            return false;
369        }
370
371        bool splerr = false;
372        void *buf = malloc( PS_PRINT_BUF_SIZE );
373        int rd = 0;
374        while ( ( rc != DEVESC_ERROR ) && ( rd = fread( buf, 1, PS_PRINT_BUF_SIZE, f ) ) != 0 )
375        {
376            rc = DevEscape( hdcPrinter, DEVESC_RAWDATA, rd, (char *)buf, NULL, NULL );
377            if ( ( rc == DEVESC_ERROR ) || abortPrinting ) {
378                splerr = true;
379                break;
380            }
381        }
382        free( buf );
383        fclose( f );
384        unlink( tmpps );
385
386        DevEscape( hdcPrinter, splerr ? DEVESC_ABORTDOC : DEVESC_ENDDOC,
387                   0L, NULL, NULL, NULL );
388        DevCloseDC( hdcPrinter );
389
390        if ( splerr && !abortPrinting ) {
391            return false;
392        }
393    }
394
395    return true;
396}
397
398
399bool LucidePrinting::queryCurrentForm( HAB lhab, PHCINFO pcurForm )
400{
401    CHAR         achDriverName[ DRIVERNAME_LENGTH ] = "";
402    DEVOPENSTRUC dos   = { 0 };
403    // build a devopenstruct for the call to DevOpenDC
404    dos.pszLogAddress = psetup->QueueInfo.pszName;              // 1
405    strcpy( achDriverName, psetup->QueueInfo.pszDriverName );
406    achDriverName[ strcspn( achDriverName, "." ) ] = '\0';
407    dos.pszDriverName = achDriverName;                          // 2
408    dos.pdriv = psetup->QueueInfo.pDriverData;                  // 3
409
410    HDC hdcPrinterInfo = DevOpenDC( lhab, OD_INFO, "*", 3L, (PDEVOPENDATA)&dos, NULLHANDLE );
411    if ( hdcPrinterInfo == DEV_ERROR ) {
412        return false;
413    }
414
415    LONG lForms = DevQueryHardcopyCaps( hdcPrinterInfo, 0, 0, NULL );
416    if ( lForms == DQHC_ERROR ) {
417        DevCloseDC( hdcPrinterInfo );
418        return false;
419    }
420
421    HCINFO *forms = new HCINFO[ lForms ];
422    memset( forms, 0, sizeof( HCINFO ) * lForms );
423    lForms = DevQueryHardcopyCaps( hdcPrinterInfo, 0, lForms, forms );
424    if ( lForms == DQHC_ERROR ) {
425        delete forms;
426        DevCloseDC( hdcPrinterInfo );
427        return false;
428    }
429
430    for ( LONG i = 0; i < lForms; i++ ) {
431        if ( forms[i].flAttributes & HCAPS_CURRENT ) {
432            memcpy( pcurForm, &( forms[i] ), sizeof( HCINFO ) );
433            break;
434        }
435    }
436
437    delete forms;
438    DevCloseDC( hdcPrinterInfo );
439    return true;
440}
441
442// static method
443void LucidePrinting::printabort( void *data )
444{
445    ((LucidePrinting *)data)->abortPrinting = true;
446}
447
448// static method, thread for asynchronous printing
449void LucidePrinting::printthread( void *p )
450{
451    DosSetPriority( PRTYS_THREAD, PRTYC_IDLETIME, PRTYD_MAXIMUM, 0 );
452    LucidePrinting *_this = (LucidePrinting *)p;
453
454    HAB thab = WinInitialize( 0 );
455    HMQ thmq = WinCreateMsgQueue( thab, 0 );
456
457    bool printOk = false;
458    if ( _this->psetup->ptype == TypePostScript ) {
459        printOk = _this->doPsPrint( thab );
460    }
461    else {
462        printOk = _this->doPmPrint( thab );
463    }
464    _this->progressDlg->hide();
465
466    if ( !printOk )
467    {
468        char *printfailed = newstrdupL( PRINT_FAILED );
469        WinMessageBox( HWND_DESKTOP, _this->hFrame, printfailed, NULL,
470                       1, MB_OK | MB_ERROR | MB_MOVEABLE );
471        delete printfailed;
472    }
473
474    WinDestroyMsgQueue( thmq );
475    WinTerminate( thab );
476    _endthread();
477
478    delete _this;
479}
480
Note: See TracBrowser for help on using the repository browser.