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

Last change on this file since 92 was 92, checked in by Eugene Romanenko, 15 years ago

postscript printing updates, ability to abort PS generation, gcc support changes

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