source: trunk/Lucide/SOURCE/gui/docViewer.cpp @ 70

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

PgDown? fix

File size: 56.1 KB
RevLine 
[35]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
[40]24 * above. If you wish to allow use of your version of this file only under the
[35]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
[40]29 * may use your version of this file under the terms of any one of the CDDL
[35]30 * or the LGPL.
31 *
32 * ***** END LICENSE BLOCK ***** */
33
34
[2]35#define INCL_DOS
36#define INCL_WIN
37#define INCL_GPI
38#include <os2.h>
39
[23]40#include <string>
[2]41#include <process.h>
42#include <stdio.h>
43
44#include <ludoc.xh>
45#include "lucide.h"
46#include "docViewer.h"
47#include "progressDlg.h"
[25]48#include "pluginman.h"
[2]49#include "luutils.h"
50#include "lucide_res.h"
51#include "messages.h"
52
53
[17]54// OpenWatcom headers doesn't have GpiDrawBits() declaration
[2]55extern "C" {
56    LONG APIENTRY GpiDrawBits(HPS hps, PVOID pBits, PBITMAPINFO2 pbmiInfoTable,
57                              LONG lCount, PPOINTL aptlPoints, LONG lRop, ULONG flOptions);
58}
59
[17]60typedef LuDocument_LuRectSequence    *PLuRectSequence;
61typedef LuDocument_LuLinkMapSequence *PLuLinkMapSequence;
[2]62
63#define LINE_HEIGHT     16
64
65// DocumentViewer constructor
66DocumentViewer::DocumentViewer( HAB _hab, HWND hWndFrame )
67{
68    hab         = _hab;
69    hMainFrame  = hWndFrame;
70    sHscrollMax = 0;
71    sVscrollMax = 0;
72    sHscrollPos = 0;
73    sVscrollPos = 0;
74    sVscrollInc = 0;
75    sHscrollInc = 0;
76    cxClient    = 0;
77    cyClient    = 0;
78    hWndDoc     = NULLHANDLE;
79    doc         = NULL;
80    totalpages  = 0;
81    currentpage = 0;
82    hpsBuffer   = NULLHANDLE;
83    hdcBuffer   = NULLHANDLE;
84    width       = 0;
85    height      = 0;
86    fullwidth   = 0;
87    fullheight  = 0;
[27]88    bpp         = 0;
[2]89    zoom        = 1.0;
90    realzoom    = 1.0;
[55]91    rotation    = 0;
[2]92    ev          = somGetGlobalEnvironment();
93    pixbuf      = NULL;
94    spos_x      = 0;
95    spos_y      = 0;
96    progressDlg = new ProgressDlg( hWndFrame );
[17]97    drawareas   = NULL;
98    drawareaIndex = 0;
[50]99    closed        = true;
[2]100    // continuous view
[17]101    continuous  = false;
[2]102    pagesizes   = NULL;
103    realVscrollMax = 0;
[17]104    VScrollStep = 1;
[18]105    WinSetRectEmpty( hab, &savedRcl );
[61]106    drawPS = false;
[2]107    // asynch draw
108    abortAsynch = false;
109    termdraw    = false;
110    enableAsynchDraw = false;
111    DosCreateMutexSem( NULL, &todrawAccess, 0, FALSE );
112    DosCreateEventSem( NULL, &haveDraw, 0, FALSE );
113    // selection
114    mousePressed = false;
115    selectionStart.x = 0;  selectionStart.y = 0;
116    selectionEnd.x = 0;  selectionEnd.y = 0;
[23]117    selection = NULL;
[2]118    selrects = NULL;
119    // links
120    links = NULL;
121    handptr = WinLoadPointer( HWND_DESKTOP, NULLHANDLE, IDP_HAND );
122    // search
123    foundrects = NULL;
124    searchString = NULL;
125    abortSearch = false;
126
127    // create windows
128    ULONG dfFlags = FCF_VERTSCROLL | FCF_HORZSCROLL | FCF_NOBYTEALIGN;
129    hWndDocFrame = WinCreateStdWindow( hWndFrame, WS_VISIBLE, &dfFlags, NULL, NULL,
130                                       WS_VISIBLE, NULLHANDLE, 0, NULL );
[67]131    WinSetWindowULong( hWndDocFrame, QWL_USER, (ULONG)this );
132    oldFrameProc = WinSubclassWindow( hWndDocFrame, docFrameProc );
[2]133
134    hWndDoc = WinCreateWindow( hWndDocFrame, "er.docview", NULL,
135                               WS_VISIBLE | WS_TABSTOP, 0, 0, 0, 0, hWndDocFrame,
136                               HWND_TOP, FID_CLIENT, this, NULL );
137
138    hWndHscroll = WinWindowFromID( hWndDocFrame, FID_HORZSCROLL );
139    hWndVscroll = WinWindowFromID( hWndDocFrame, FID_VERTSCROLL );
140
[61]141    drawThreadId = _beginthread( drawthread, NULL, 262144, this );
[2]142}
143
144// DocumentViewer destructor
145DocumentViewer::~DocumentViewer()
146{
147    termdraw    = true;
148    abortAsynch = true;
149    DosPostEventSem( haveDraw );
150    DosWaitThread( &drawThreadId, DCWW_WAIT );
151    DosCloseMutexSem( todrawAccess );
152    DosCloseEventSem( haveDraw );
153
154    if ( doc != NULL ) {
[22]155        freeRects( selrects );
156        freeRects( foundrects );
[17]157        freeLinks();
[2]158    }
159
160    WinDestroyPointer( handptr );
161
162    if ( ( hpsBuffer != NULLHANDLE ) && ( hdcBuffer != NULLHANDLE ) ) {
163        DestroyGraphicsBuffer( hpsBuffer, hdcBuffer );
164        hpsBuffer = hdcBuffer = NULLHANDLE;
165    }
166    delete pixbuf;
167    delete progressDlg;
168    delete searchString;
169    delete pagesizes;
[23]170    delete selection;
[2]171}
172
173
174// static, registration of a window class
175void DocumentViewer::registerClass( HAB hab )
176{
177    WinRegisterClass( hab, "er.docview", docViewProc, CS_SIZEREDRAW, sizeof( ULONG ) * 2 );
178}
179
180// sets the document for viewing
181void DocumentViewer::setDocument( LuDocument *_doc )
182{
[26]183    close();
184    doc = _doc;
[22]185
[2]186    if ( doc != NULL )
187    {
[50]188        closed = false;
189
[2]190        totalpages = doc->getPageCount( ev );
[27]191        bpp = doc->getBpp( ev );
[50]192        if ( !doc->isScalable( ev ) ) {
193            zoom = 1;
194        }
[2]195
196        pagesizes = new LuSize[ totalpages ];
[55]197        countPagesizes();
[2]198
[22]199        selrects = new PLuRectSequence[ totalpages ];
200        memset( selrects, 0, sizeof( PLuRectSequence ) * totalpages );
201
[2]202        foundrects = new PLuRectSequence[ totalpages ];
203        memset( foundrects, 0, sizeof( PLuRectSequence ) * totalpages );
[22]204
[17]205        links = new PLuLinkMapSequence[ totalpages ];
206        memset( links, 0, sizeof( PLuLinkMapSequence ) * totalpages );
[22]207
[23]208        selection = new LuRectangle[ totalpages ];
209        memset( selection, 0, sizeof( LuRectangle ) * totalpages );
210
[61]211        drawPS = doc->isRenderIntoPS( ev );
212        if ( drawPS ) {
213            enableAsynchDraw = false;
214        }
215        else {
216            enableAsynchDraw = doc->isAsynchRenderingSupported( ev );
217        }
[18]218        goToPage( 0 );
[50]219
220        if ( continuous ) {
221            drawPage();
222        }
[18]223    }
224}
225
[55]226void DocumentViewer::countPagesizes()
227{
228    for ( long i = 0; i < totalpages; i++ )
229    {
230        doc->getPageSize( ev, i, &pagesizes[i].x, &pagesizes[i].y );
231        if ( ( rotation == 90 ) || ( rotation == 270 ) ) {
232            double tmp = pagesizes[i].x;
233            pagesizes[i].x = pagesizes[i].y;
234            pagesizes[i].y = tmp;
235        }
236        fullwidth = __max( fullwidth, pagesizes[i].x );
237        fullheight += pagesizes[i].y;
238    }
239}
[18]240
[26]241// closes the document
242void DocumentViewer::close()
243{
[50]244    if ( closed ) {
245        return;
246    }
247
248    closed = true;
[26]249    abortAsynch = true;
250    DosRequestMutexSem( todrawAccess, SEM_INDEFINITE_WAIT );
251
252    delete drawareas;
253    drawareas = NULL;
254
255    delete pagesizes;
256    pagesizes   = NULL;
257
258    delete selection;
259    selection   = NULL;
260
261    freeRects( foundrects );
262    delete foundrects;
263    foundrects  = NULL;
264
265    freeRects( selrects );
266    delete selrects;
267    selrects    = NULL;
268
269    freeLinks();
270
271    doc         = NULL;
272    totalpages  = 0;
273    currentpage = 0;
274    fullwidth   = 0;
275    fullheight  = 0;
276
277    DosReleaseMutexSem( todrawAccess );
278}
279
[50]280// sets the page layout
281void DocumentViewer::setPageLayout( PgLayout layout )
[18]282{
[50]283    continuous = ( layout == Continuous );
[18]284    if ( doc != NULL ) {
285        long pg = currentpage;
[2]286        drawPage();
[18]287        if ( continuous ) {
288            goToPage( pg );
289        }
[2]290    }
291}
292
[22]293void DocumentViewer::freeRects( LuDocument_LuRectSequence **rects )
[2]294{
[22]295    if ( rects != NULL )
[17]296    {
[2]297        for ( long i = 0; i < totalpages; i++ ) {
[22]298            if ( rects[ i ] != NULL ) {
299                LuDocument::freeRectangles( ev, rects[ i ] );
300                rects[ i ] = NULL;
[17]301            }
[2]302        }
303    }
304}
305
[17]306void DocumentViewer::freeLinks()
307{
308    if ( links != NULL )
309    {
310        for ( long i = 0; i < totalpages; i++ ) {
311            if ( links[ i ] != NULL ) {
312                LuDocument::freeLinkMapping( ev, links[ i ] );
313                links[ i ] = NULL;
314            }
315        }
[2]316
[17]317        delete links;
318        links = NULL;
319    }
320}
321
322
[2]323// switch view to specified page
324void DocumentViewer::goToPage( long page )
325{
[17]326    if ( continuous && ( doc != NULL ) )
327    {
[65]328        bool needRedraw = ( page == currentpage );
[17]329        double pgpos = pagenumToPos( page ) / VScrollStep;
330        vertScroll( hWndDoc, MPFROM2SHORT( pgpos, SB_SLIDERPOSITION ), NULLHANDLE );
[65]331        if ( needRedraw ) {
332            drawPage();
333        }
[2]334    }
[17]335    else
336    {
337        currentpage = page;
[35]338        sVscrollPos = 0;
[17]339        if ( doc != NULL ) {
340            drawPage();
341            Lucide::checkNavigationMenus();
342        }
343    }
[2]344}
345
346// Sets the zoom level
347// _zoom - actual zoom level or:
348//         -1 - fit width
349//         -2 - fit page
350void DocumentViewer::setZoom( double _zoom )
351{
[32]352
[2]353    if ( doc != NULL ) {
[55]354        if ( doc->isScalable( ev ) ) {
355            zoom = _zoom;
356            drawPage();
357        }
[2]358    }
[55]359    else {
360        zoom = _zoom;
361    }
[2]362}
363
[55]364// Sets the rotation
365// rotation may be 0, 90, 180 or 270 degrees
366// -90 will be changed to 270, 360 to 0
367void DocumentViewer::setRotation( long _rotation )
368{
369    if ( _rotation == -90 ) {
370        _rotation = 270;
371    }
372    if ( _rotation == 360 ) {
373        _rotation = 0;
374    }
375
376    if ( doc != NULL )
377    {
378        if ( doc->isRotable( ev ) )
379        {
380            rotation = _rotation;
381            countPagesizes();
382            drawPage();
383        }
384    }
385    else {
386        rotation = _rotation;
387    }
388}
389
[2]390// copy selected text to clipboard
391void DocumentViewer::copyToClipbrd()
392{
[23]393    if ( continuous )
394    {
395        std::string txt = "";
396        for ( long i = 0; i < totalpages; i++ ) {
397            if ( selrects[ i ] != NULL ) {
398                txt += doc->getText( ev, i, &(selection[ i ]) );
399            }
400        }
401        textToClipbrd( hab, txt.c_str() );
402    }
403    else {
404        char *t = doc->getText( ev, currentpage, &(selection[ currentpage ]) );
405        textToClipbrd( hab, t );
406    }
[2]407}
408
[40]409// select all text (continuous view) or current page (single page view)
410void DocumentViewer::selectAll()
411{
412    if ( continuous )
413    {
414        for ( long i = 0; i < totalpages; i++ )
415        {
416            selection[ i ].x1 = 0;
417            selection[ i ].y1 = 0;
418            selection[ i ].x2 = pagesizes[ i ].x;
419            selection[ i ].y2 = pagesizes[ i ].y;
420            LuDocument::freeRectangles( ev, selrects[ i ] );
[59]421            selrects[ i ] = doc->getSelectionRectangles( ev, i, &(selection[i]) );
[40]422        }
423    }
424    else
425    {
426        selection[ currentpage ].x1 = 0;
427        selection[ currentpage ].y1 = 0;
428        selection[ currentpage ].x2 = pagesizes[ currentpage ].x;
429        selection[ currentpage ].y2 = pagesizes[ currentpage ].y;
430        LuDocument::freeRectangles( ev, selrects[ currentpage ] );
[59]431        selrects[ currentpage ] = doc->getSelectionRectangles( ev, currentpage, &(selection[currentpage]) );
[40]432    }
433
434    Lucide::enableCopy( true );
435    WinInvalidateRect( hWndDoc, NULL, FALSE );
436}
437
[2]438// perform search in document
439void DocumentViewer::searchDocument( const char *_searchString, bool _caseSensitive,
440                                     bool _continueSearch )
441{
442    abortSearch = false;
443    if ( !continueSearch ) {
[22]444        freeRects( foundrects );
[2]445    }
446
447    delete searchString;
448    searchString = newstrdup( _searchString );
449    caseSensitive = _caseSensitive;
450    continueSearch = _continueSearch;
451
452    progressDlg->setBreakFunc( searchabort, this );
453    progressDlg->setText( "" );
454    progressDlg->show( searchthread, this );
455}
456
457// static method, cancels asynch rendering if abortAsynch is true
458void DocumentViewer::searchabort( void *data )
459{
460    ((DocumentViewer *)data)->abortSearch = true;
461}
462
463// static method, thread for asynchronous searching
464void DocumentViewer::searchthread( void *p )
465{
466    DosSetPriority( PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MINIMUM, 0 );
467    DocumentViewer *_this = (DocumentViewer *)p;
468
469    HAB thab = WinInitialize( 0 );
470    HMQ thmq = WinCreateMsgQueue( thab, 0 );
471
472    long i = _this->currentpage;
473    if ( _this->continueSearch && ( _this->currentpage < ( _this->totalpages - 1 ) ) ) {
474        i = _this->currentpage + 1;
475    }
476
477    bool found = false;
478    for ( ; i < _this->totalpages; i++ )
479    {
480        char *fmt = newstrdupL( FIND_SEARCH_PAGE_OF );
481        char *buf = new char[ 255 ];
482        snprintf( buf, 255, fmt, i + 1, _this->totalpages );
483        _this->progressDlg->setText( buf );
484        delete fmt;
485        delete buf;
486
487        _this->foundrects[ i ] = _this->doc->searchText( _this->ev, i,
488                                        (char *)_this->searchString, _this->caseSensitive );
489        if ( _this->foundrects[ i ] != NULL )
490        {
491            found = true;
492            _this->progressDlg->hide();
493            _this->goToPage( i );
[17]494            if ( _this->foundrects[i]->_length > 0 ) {
[2]495                RECTL r;
[19]496                _this->docPosToWinPos( i, &(_this->foundrects[i]->_buffer[0]), &r );
[2]497                _this->scrollToPos( _this->hWndDoc, NULLHANDLE, r.xLeft, r.yBottom, false );
498            }
499            break;
500        }
501
502        if ( _this->abortSearch ) {
503            break;
504        }
505    }
506    _this->progressDlg->hide();
507
508    if ( !found && !_this->abortSearch )
509    {
510        char *notfound = newstrdupL( FIND_NOT_FOUND );
511        WinMessageBox( HWND_DESKTOP, _this->hMainFrame, notfound, NULL,
512                       1, MB_OK | MB_ICONEXCLAMATION | MB_MOVEABLE );
513        delete notfound;
514    }
515
516    WinDestroyMsgQueue( thmq );
517    WinTerminate( thab );
518    _endthread();
519}
520
521// count real zoom level based on specified
522void DocumentViewer::adjustSize()
523{
524    if ( doc != NULL )
525    {
[55]526        width  = pagesizes[ currentpage ].x;
527        height = pagesizes[ currentpage ].y;
[2]528
529        fullwidth = 0;
530        fullheight = 0;
531        for ( long i = 0; i < totalpages; i++ ) {
532            fullwidth = __max( fullwidth, pagesizes[i].x );
533            fullheight += pagesizes[i].y;
534        }
535
536        if ( zoom == -1 ) { // fit width
537            realzoom = (double)cxClient / ( continuous ? fullwidth : width );
538        }
539        else if ( zoom == -2 ) { // fit page
540            realzoom = __min( (double)cxClient / width, (double)cyClient / height );
541        }
542        else {
543            realzoom = zoom;
544        }
545        width *= realzoom;
546        height *= realzoom;
547        fullwidth *= realzoom;
548        fullheight *= realzoom;
549    }
550}
551
552// page redraw
553void DocumentViewer::drawPage()
554{
[40]555    if ( !continuous )
[2]556    {
[22]557        LuDocument::freeRectangles( ev, selrects[ currentpage ] );
558        selrects[ currentpage ] = NULL;
559
[17]560        if ( links != NULL ) {
561            if ( links[ currentpage ] == NULL ) {
562                links[ currentpage ] = doc->getLinkMapping( ev, currentpage );
563            }
564        }
[22]565
[2]566        Lucide::enableCopy( false );
567    }
[40]568    WinSendMsg( hWndDoc, WM_SIZE, MPFROM2SHORT( cxClient, cyClient ),
569                MPFROM2SHORT( cxClient, cyClient ) );
570    WinInvalidateRect( hWndDoc, NULL, FALSE );
[2]571}
572
573
574// handles vertical scrolling
575MRESULT DocumentViewer::vertScroll( HWND hwnd, MPARAM mp2, HRGN hrgn )
576{
577    sVscrollInc = 0;
578
579    switch ( SHORT2FROMMP( mp2 ) )
580    {
581        case SB_LINEUP:
[28]582            sVscrollInc = -(__max( LINE_HEIGHT, VScrollStep ));
[2]583            break ;
584        case SB_LINEDOWN:
[28]585            sVscrollInc = __max( LINE_HEIGHT, VScrollStep );
[2]586            break;
587        case SB_PAGEUP:
588            sVscrollInc = __min( -1, -( cyClient - LINE_HEIGHT ) );
589            break;
590        case SB_PAGEDOWN:
[70]591            sVscrollInc = __max( 1, cyClient - LINE_HEIGHT );
[2]592            break;
593        case SB_SLIDERTRACK:
594        case SB_SLIDERPOSITION:
[17]595            sVscrollInc = ( SHORT1FROMMP( mp2 ) - sVscrollPos ) * VScrollStep;
[2]596            break;
597    }
598
[17]599    sVscrollInc = __max( -sVscrollPos * VScrollStep, __min( sVscrollInc,
600                              ( sVscrollMax - sVscrollPos ) * VScrollStep ) );
[2]601
602    if ( sVscrollInc != 0 )
603    {
[17]604        sVscrollPos += (SHORT)( sVscrollInc / VScrollStep );
[2]605        WinScrollWindow( hwnd, 0, sVscrollInc, NULL, NULL, hrgn, NULL, SW_INVALIDATERGN );
606        WinSendMsg( hWndVscroll, SBM_SETPOS, MPFROMSHORT( sVscrollPos ), MPVOID );
607        WinUpdateWindow( hwnd );
608        sVscrollInc = 0;
609    }
610    return ( MRFROMLONG( 0 ) );
611}
612
613// handles horizontal scrolling
614MRESULT DocumentViewer::horizScroll( HWND hwnd, MPARAM mp2, HRGN hrgn )
615{
616    sHscrollInc = 0;
617
618    switch ( SHORT2FROMMP( mp2 ) )
619    {
620        case SB_LINELEFT:
621            sHscrollInc = -LINE_HEIGHT;
622            break;
623        case SB_LINERIGHT:
624            sHscrollInc = LINE_HEIGHT;
625            break;
626        case SB_PAGELEFT:
627            sHscrollInc = __min( -1, -( cxClient - LINE_HEIGHT ) );
628            break;
629        case SB_PAGERIGHT:
630            sHscrollInc = __max( 1, cxClient - LINE_HEIGHT );
631            break;
632        case SB_SLIDERTRACK:
633        case SB_SLIDERPOSITION:
634            sHscrollInc = SHORT1FROMMP( mp2 ) - sHscrollPos;
635            break;
636    }
637
638    sHscrollInc = __max( -sHscrollPos, __min( sHscrollInc, sHscrollMax - sHscrollPos ) );
639
640    if ( sHscrollInc != 0 )
641    {
642        sHscrollPos += (SHORT)sHscrollInc;
643        WinScrollWindow( hwnd, -sHscrollInc, 0, NULL, NULL, hrgn, NULL, SW_INVALIDATERGN );
644        WinSendMsg( hWndHscroll, SBM_SETPOS, MPFROMSHORT( sHscrollPos ), MPVOID );
645        WinUpdateWindow( hwnd );
646        sHscrollInc = 0;
647    }
648    return ( MRFROMLONG( 0 ) );
649}
650
651
652// handles WM_SIZE message
653// creates appropriate hps buffer, sets scrollbars limits
654void DocumentViewer::wmSize( HWND hwnd, MPARAM mp2 )
655{
[33]656    if ( !WinIsWindowShowing( hwnd ) ) {
657        return;
658    }
659
[2]660    cxClient = SHORT1FROMMP( mp2 );
661    cyClient = SHORT2FROMMP( mp2 );
662
[54]663    double relativeScrollPos = ( sVscrollMax == 0 ) ? 0 :
664                                    (double)sVscrollPos / (double)sVscrollMax;
[32]665
[2]666    adjustSize();
667
668    if ( ( hpsBuffer != NULLHANDLE ) && ( hdcBuffer != NULLHANDLE ) ) {
669        DestroyGraphicsBuffer( hpsBuffer, hdcBuffer );
670        hpsBuffer = hdcBuffer = NULLHANDLE;
671    }
672
673    HPS hps = WinGetPS( hwnd );
674    RECTL rectl = { 0, 0, cxClient, cyClient };
675    CreateGraphicsBuffer( hab, &rectl, hps, &hpsBuffer, &hdcBuffer );
676    WinReleasePS( hps );
677
678    sHscrollMax = (SHORT)__max( 0, ( continuous ? fullwidth : width ) - cxClient );
679    sHscrollPos = __min( sHscrollPos, sHscrollMax );
680
681    WinSendMsg( hWndHscroll, SBM_SETSCROLLBAR,
682                MPFROMSHORT(sHscrollPos), MPFROM2SHORT(0, sHscrollMax) );
683    WinSendMsg( hWndHscroll, SBM_SETTHUMBSIZE,
684                MPFROM2SHORT( cxClient, width ), MPVOID );
685    WinEnableWindow( hWndHscroll, (BOOL)( sHscrollMax != 0 ) );
686
687    if ( continuous )
688    {
689        realVscrollMax = __max( 0, fullheight - cyClient );
690        VScrollStep = LINE_HEIGHT;
691        ULONG ssize = realVscrollMax / VScrollStep;
692        while ( ssize > 32000 ) {
693            VScrollStep += LINE_HEIGHT;
694            ssize = realVscrollMax / VScrollStep;
695        }
696
697        sVscrollMax = (SHORT)ssize;
698    }
699    else {
700        realVscrollMax = sVscrollMax = (SHORT)__max( 0, height - cyClient );
[17]701        VScrollStep = 1;
[2]702    }
703    sVscrollPos = __min( sVscrollPos, sVscrollMax );
704
705    WinSendMsg( hWndVscroll, SBM_SETSCROLLBAR,
706                MPFROMSHORT(sVscrollPos), MPFROM2SHORT(0, sVscrollMax) );
707    if ( continuous ) {
708        WinSendMsg( hWndVscroll, SBM_SETTHUMBSIZE,
709                    MPFROM2SHORT( cyClient/VScrollStep, fullheight/VScrollStep ), MPVOID );
710    }
711    else {
712        WinSendMsg( hWndVscroll, SBM_SETTHUMBSIZE,
713                    MPFROM2SHORT( cyClient, height ), MPVOID );
714    }
715    WinEnableWindow( hWndVscroll, (BOOL)( sVscrollMax != 0 ) );
[32]716
717    SHORT realScrollPos = (SHORT)(sVscrollMax * relativeScrollPos);
718    vertScroll( hWndDoc, MPFROM2SHORT( realScrollPos, SB_SLIDERPOSITION ), NULLHANDLE );
[2]719}
720
721// returns true if subrect inside rect
722inline bool isSubrect( PRECTL rect, PRECTL subrect )
723{
724    return ( ( subrect->xLeft >= rect->xLeft ) &&
725             ( subrect->yBottom >= rect->yBottom ) &&
726             ( subrect->xRight <= rect->xRight ) &&
727             ( subrect->yTop <= rect->yTop ) );
728}
729
730// static method, cancels asynch rendering if abortAsynch is true
731long _System DocumentViewer::asynchCallbackFnAbort( void *data )
732{
733    return (long)(((DocumentViewer *)data)->abortAsynch);
734}
735
736// static method, draws area during asynch rendering
737long _System DocumentViewer::asynchCallbackFnDraw( void *data )
738{
[27]739    DocumentViewer *_this = (DocumentViewer *)data;
740    HPS hps = WinGetPS( _this->hWndDoc );
[2]741    if ( hps != NULLHANDLE )
742    {
[27]743        PRECTL drawRect = &((*_this->drawareas)[_this->drawareaIndex].drawrect);
[17]744        LONG rclx = drawRect->xRight - drawRect->xLeft;
745        LONG rcly = drawRect->yTop - drawRect->yBottom;
[2]746
[17]747        POINTL aptlPoints[4]={ drawRect->xLeft, drawRect->yBottom,
748                               drawRect->xRight-1, drawRect->yTop-1,
[2]749                               0, 0, rclx, rcly };
750
751        LONG lRop = ROP_SRCCOPY;
752        BITMAPINFO2 pbmi;
753        pbmi.cbFix = 16L;
754        pbmi.cx = rclx;
755        pbmi.cy = rcly;
756        pbmi.cPlanes = 1;
[27]757        pbmi.cBitCount = _this->bpp * 8;
758        GpiDrawBits( hps, _this->pixbuf->getDataPtr( _this->ev ), &pbmi, 4L,
[2]759                     aptlPoints, lRop, BBO_IGNORE );
760
761        WinReleasePS( hps );
762    }
763    return 0;
764}
765
766// static method, thread for asynchronous rendering
767void DocumentViewer::drawthread( void *p )
768{
769    DosSetPriority( PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MINIMUM, 0 );
[17]770    DocumentViewer *_this = (DocumentViewer *)p;
[2]771
772    HAB thab = WinInitialize( 0 );
773    HMQ thmq = WinCreateMsgQueue( thab, 0 );
774
775    ULONG postCnt;
[17]776    while ( !_this->termdraw )
[2]777    {
[17]778        DosWaitEventSem( _this->haveDraw, SEM_INDEFINITE_WAIT );
779        DosResetEventSem( _this->haveDraw, &postCnt );
780        _this->abortAsynch = false;
[2]781
[17]782        if ( ( _this->drawareas != NULL ) && ( _this->doc != NULL ) )
[2]783        {
[17]784            DosRequestMutexSem( _this->todrawAccess, SEM_INDEFINITE_WAIT );
785
[18]786            for ( _this->drawareaIndex = 0;
787                  _this->drawareaIndex < _this->drawareas->size();
788                  _this->drawareaIndex++ )
[2]789            {
[18]790                PageDrawArea *pda = &(*_this->drawareas)[ _this->drawareaIndex ];
[17]791
792                LONG rclx = pda->drawrect.xRight - pda->drawrect.xLeft;
793                LONG rcly = pda->drawrect.yTop - pda->drawrect.yBottom;
[27]794                _this->pixbuf = new LuPixbuf( _this->ev, rclx, rcly, _this->bpp );
[17]795                _this->doc->renderPageToPixbufAsynch( _this->ev, pda->pagenum,
[55]796                       pda->startpos.x, pda->startpos.y, rclx, rcly, _this->realzoom,
797                       _this->rotation, _this->pixbuf,
798                       asynchCallbackFnDraw, asynchCallbackFnAbort, p );
[17]799                delete _this->pixbuf;
800                _this->pixbuf = NULL;
801
802                if ( _this->abortAsynch ) {
803                    break;  // TODO: remove completed areas from drawareas
[2]804                }
805            }
[17]806
807            if ( !_this->abortAsynch )
808            {
809                HPS hps = WinGetPS( _this->hWndDoc );
810                if ( hps != NULLHANDLE ) {
[19]811                    for ( int i = 0; i < _this->drawareas->size(); i++ )
[18]812                    {
[19]813                        PageDrawArea *pda = &(*_this->drawareas)[ i ];
[18]814
[22]815                        _this->drawSelection( pda->pagenum, hps, &pda->drawrect );
[19]816                        _this->drawFound( pda->pagenum, hps, &pda->drawrect );
[18]817                    }
[17]818                    WinReleasePS( hps );
819                }
[18]820                WinSetRectEmpty( _this->hab, &_this->savedRcl );
[17]821                delete _this->drawareas;
822                _this->drawareas = NULL;
823            }
824
825            DosReleaseMutexSem( _this->todrawAccess );
[2]826        }
827    }
828    WinDestroyMsgQueue( thmq );
829    WinTerminate( thab );
830    _endthread();
831}
832
833// handles WM_PAINT if document supports asynch rendering.
834// posts events to drawthread
835void DocumentViewer::wmPaintAsynch( HWND hwnd )
836{
837    RECTL rcl;
838    HPS hps = WinBeginPaint( hwnd, 0L, &rcl );
[50]839    RECTL rclWin = { 0 };
840    WinQueryWindowRect( hwnd, &rclWin );
841    if ( WinEqualRect( hab, &rcl, &rclWin ) ) {
842        GpiErase( hps );
[2]843    }
[50]844    WinEndPaint( hps );
[2]845
[50]846    if ( doc != NULL )
[2]847    {
[50]848        RECTL rclPage = { 0, 0, width, height };
849        if ( height < cyClient )
850        {
851            rclPage.yBottom = cyClient - height;
852            rclPage.yTop = cyClient;
853        }
854        RECTL rclDraw = { 0 };
855        if ( WinIntersectRect( hab, &rclDraw, &rcl, &rclPage ) )
856        {
857            if ( ( drawareas != NULL ) && ( drawareas->size() > 0 ) ) {
858                if ( isSubrect( &((*drawareas)[0].drawrect), &rclDraw ) &&
859                     ( sVscrollInc == 0 ) && ( sHscrollInc == 0 ) ) {
860                    return;
861                }
[17]862            }
[2]863
[50]864            abortAsynch = true;
865            DosRequestMutexSem( todrawAccess, SEM_INDEFINITE_WAIT );
[17]866
[50]867            if ( drawareas == NULL ) {
868                drawareas = new DrawAreas;
869            }
870            if ( drawareas->size() == 0 ) {
871                PageDrawArea pda;
872                memset( &pda, 0, sizeof( pda ) );
873                pda.pagenum = currentpage;
874                drawareas->push_back( pda );
875            }
[17]876
[50]877            PageDrawArea *ppda = &((*drawareas)[0]);
[17]878
[50]879            if ( !WinIsRectEmpty( hab, &ppda->drawrect ) )
880            {
881                if ( sVscrollInc > 0 ) {
882                    ppda->drawrect.yTop    += sVscrollInc;
883                } else if ( sVscrollInc < 0 ) {
884                    ppda->drawrect.yBottom += sVscrollInc;
885                }
886                if ( sHscrollInc > 0 ) {
887                    ppda->drawrect.xLeft  -= sHscrollInc;
888                } else if ( sHscrollInc < 0 ) {
889                    ppda->drawrect.xRight -= sHscrollInc;
890                }
[2]891            }
[50]892            WinUnionRect( hab, &ppda->drawrect, &ppda->drawrect, &rclDraw );
893            ppda->startpos.x = sHscrollPos + ppda->drawrect.xLeft;
894            ppda->startpos.y = ( cyClient - ppda->drawrect.yTop ) + sVscrollPos;
[2]895
[50]896            // workaround ?
897            ppda->drawrect.xRight++;
898            ppda->drawrect.yTop++;
[2]899
[50]900            DosReleaseMutexSem( todrawAccess );
901            DosPostEventSem( haveDraw );
902        }
[2]903    }
904}
905
906
[18]907// handles WM_PAINT if continuous asynchronous rendering used
908void DocumentViewer::wmPaintContAsynch( HWND hwnd )
909{
910    RECTL rcl, rclWin, rclDraw = { 0 };
911    HPS hps = WinBeginPaint( hwnd, 0L, &rcl );
[50]912    GpiErase( hpsBuffer );
913    BlitGraphicsBuffer( hps, hpsBuffer, &rcl );
914    WinEndPaint( hps );
[18]915
[50]916    if ( doc != NULL )
917    {
918        if ( isSubrect( &savedRcl, &rcl ) && ( sVscrollInc == 0 ) && ( sHscrollInc == 0 ) ) {
919            return;
920        }
[18]921
[50]922        abortAsynch = true;
923        DosRequestMutexSem( todrawAccess, SEM_INDEFINITE_WAIT );
[18]924
[50]925        WinQueryWindowRect( hwnd, &rclWin );
926        WinUnionRect( hab, &rcl, &rcl, &savedRcl );
[18]927
[50]928        if ( sVscrollInc > 0 ) {
929            rcl.yTop    += sVscrollInc;
930        } else if ( sVscrollInc < 0 ) {
931            rcl.yBottom += sVscrollInc;
932        }
933        if ( sHscrollInc > 0 ) {
934            rcl.xLeft  -= sHscrollInc;
935        } else if ( sHscrollInc < 0 ) {
936            rcl.xRight -= sHscrollInc;
937        }
[18]938
[50]939        WinIntersectRect( hab, &rclDraw, &rcl, &rclWin );
940        WinCopyRect( hab, &rcl, &rclDraw );
941        WinCopyRect( hab, &savedRcl, &rcl );
[18]942
[50]943        delete drawareas;
944        drawareas = findDrawAreas( &rcl );
[18]945
[50]946        for ( int i = 0; i < drawareas->size(); i++ )
947        {
948            PageDrawArea *pda = &(*drawareas)[ i ];
[18]949
[50]950            // load links for page if not loaded before
951            if ( links[ pda->pagenum ] == NULL ) {
952                links[ pda->pagenum ] = doc->getLinkMapping( ev, pda->pagenum );
953            }
[18]954        }
[50]955        DosReleaseMutexSem( todrawAccess );
956        DosPostEventSem( haveDraw );
957
958        determineCurrentPage();
[18]959    }
960}
961
962
[2]963// handles WM_PAINT if single-page synchronous rendering used
964void DocumentViewer::wmPaint( HWND hwnd )
965{
966    RECTL rcl;
967    HPS hps = WinBeginPaint( hwnd, 0L, &rcl );
968    GpiErase( hpsBuffer );
969
[50]970    if ( doc != NULL )
[2]971    {
[50]972        RECTL rclPage = { 0, 0, width, height };
973        if ( height < cyClient )
974        {
975            rclPage.yBottom = cyClient - height;
976            rclPage.yTop = cyClient;
977        }
978        RECTL rclDraw = { 0 };
979        if ( WinIntersectRect( hab, &rclDraw, &rcl, &rclPage ) )
980        {
981            spos_x = sHscrollPos + rclDraw.xLeft;
982            spos_y = (cyClient - rclDraw.yTop) + sVscrollPos;
983            LONG rclx = rclDraw.xRight - rclDraw.xLeft;
984            LONG rcly = rclDraw.yTop - rclDraw.yBottom;
[2]985
[61]986            if ( drawPS )
987            {
988                doc->renderPageToPS( ev, currentpage, spos_x, spos_y, rclx, rcly,
989                                     realzoom, rotation, hpsBuffer, &rclDraw );
990            }
991            else
992            {
993                pixbuf = new LuPixbuf( ev, rclx, rcly, bpp );
994                POINTL aptlPoints[4]={ rclDraw.xLeft, rclDraw.yBottom,
995                                       rclDraw.xRight-1, rclDraw.yTop-1,
996                                       0, 0, rclx, rcly };
[2]997
[61]998                doc->renderPageToPixbuf( ev, currentpage, spos_x, spos_y,
999                                         rclx, rcly, realzoom, rotation, pixbuf );
1000                LONG lRop = ROP_SRCCOPY;
1001                BITMAPINFO2 pbmi;
1002                pbmi.cbFix = 16L;
1003                pbmi.cx = rclx;
1004                pbmi.cy = rcly;
1005                pbmi.cPlanes = 1;
1006                pbmi.cBitCount = bpp * 8;
1007                GpiDrawBits( hpsBuffer, pixbuf->getDataPtr( ev ), &pbmi, 4L,
1008                             aptlPoints, lRop, BBO_IGNORE );
1009                delete pixbuf;
1010                pixbuf = NULL;
1011            }
[2]1012
[50]1013            drawSelection( currentpage, hpsBuffer, &rclDraw );
1014            drawFound( currentpage, hpsBuffer, &rclDraw );
[2]1015
[50]1016            BlitGraphicsBuffer( hps, hpsBuffer, &rcl );
1017        }
1018    }
1019    else {
[2]1020        BlitGraphicsBuffer( hps, hpsBuffer, &rcl );
1021    }
1022    WinEndPaint( hps );
1023}
1024
1025
1026// founds number of page at specified vertical position
[17]1027// for continuous view only
1028long DocumentViewer::posToPagenum( LONG yPosWin, double *pageRest )
[2]1029{
[17]1030    double yPos = ( cyClient - yPosWin ) + ( sVscrollPos * VScrollStep );
[2]1031    double pgend = 0;
1032    for ( long i = 0; i < totalpages; i++ )
1033    {
1034        pgend += ( pagesizes[ i ].y * realzoom );
1035        if ( yPos < pgend ) {
1036            *pageRest = pgend - yPos;
1037            return i;
1038        }
1039    }
1040    return 0;
1041}
1042
[17]1043// founds vertical position of specified
1044// for continuous view only
1045double DocumentViewer::pagenumToPos( long pagenum )
1046{
1047    double ypos = 0;
1048    for ( long i = 0; i < pagenum; i++ ) {
1049        ypos += pagesizes[ i ].y;
1050    }
1051    return ypos * realzoom;
1052}
1053
[2]1054// founds pages and it's areas to draw
[18]1055// for continuous view only
[22]1056DrawAreas *DocumentViewer::findDrawAreas( PRECTL r )
[2]1057{
1058    DrawAreas *areas = new DrawAreas;
1059    if ( doc != NULL )
1060    {
1061        long foundpage = -1;
[17]1062        double pageRest;
[2]1063        for ( LONG i = r->yTop; i >= r->yBottom; i-- )
1064        {
1065            pageRest = 0;
[17]1066            long pg = posToPagenum( i, &pageRest );
[2]1067            if ( pg != foundpage )
1068            {
1069                PageDrawArea pda;
1070                pda.pagenum = pg;
[18]1071                pda.drawrect.xLeft   = __min( pagesizes[ pg ].x * realzoom, r->xLeft );
[2]1072                pda.drawrect.yBottom = __max( i - pageRest, r->yBottom );
[18]1073                pda.drawrect.xRight  = __min( pagesizes[ pg ].x * realzoom, r->xRight );
[2]1074                pda.drawrect.yTop    = i;
1075
[22]1076                pda.startpos.x = sHscrollPos + pda.drawrect.xLeft;
[2]1077                pda.startpos.y = ( pagesizes[ pg ].y * realzoom ) - pageRest;
1078
1079                areas->push_back( pda );
1080                foundpage = pg;
1081                i -= pageRest;
1082            }
1083        }
1084    }
1085
1086    return areas;
1087}
1088
1089
1090// found current page in continuous view mode.
1091// it's a page which occupes a most larger area in the window.
[17]1092void DocumentViewer::determineCurrentPage()
[2]1093{
1094    RECTL rcl = { 0 };
1095    WinQueryWindowRect( hWndDoc, &rcl );
[22]1096    DrawAreas *areas = findDrawAreas( &rcl );
[2]1097    long pg = 0;
1098    long sz = 0;
1099    for ( int i = 0; i < areas->size(); i++ )
1100    {
1101        PageDrawArea *pda = &(*areas)[ i ];
1102        long pgsz = pda->drawrect.yTop - pda->drawrect.yBottom;
1103        if ( pgsz > sz ) {
1104            pg = pda->pagenum;
1105            sz = pgsz;
1106        }
1107    }
1108    delete areas;
1109
1110    if ( pg != currentpage ) {
1111        currentpage = pg;
1112        Lucide::checkNavigationMenus();
1113    }
1114}
1115
1116
1117// handles WM_PAINT if continuous synchronous rendering used
1118void DocumentViewer::wmPaintCont( HWND hwnd )
1119{
1120    RECTL rcl;
1121    HPS hps = WinBeginPaint( hwnd, 0L, &rcl );
1122    GpiErase( hpsBuffer );
1123
[50]1124    if ( doc != NULL )
[2]1125    {
[50]1126        delete drawareas;
1127        drawareas = findDrawAreas( &rcl );
[2]1128
[50]1129        for ( int i = 0; i < drawareas->size(); i++ )
1130        {
1131            PageDrawArea *pda = &(*drawareas)[ i ];
[17]1132
[50]1133            // load links for page if not loaded before
1134            if ( links[ pda->pagenum ] == NULL ) {
1135                links[ pda->pagenum ] = doc->getLinkMapping( ev, pda->pagenum );
1136            }
[2]1137
[50]1138            spos_x = pda->startpos.x;
1139            //spos_y = ( cyClient - pda->drawrect.yTop ) + ( sVscrollPos * VScrollStep );
1140            spos_y = pda->startpos.y;
1141            LONG rclx = pda->drawrect.xRight - pda->drawrect.xLeft;
1142            LONG rcly = pda->drawrect.yTop - pda->drawrect.yBottom;
[2]1143
[61]1144            if ( drawPS )
1145            {
1146                doc->renderPageToPS( ev, pda->pagenum, spos_x, spos_y, rclx, rcly,
1147                                     realzoom, rotation, hpsBuffer, &(pda->drawrect) );
1148            }
1149            else
1150            {
1151                pixbuf = new LuPixbuf( ev, rclx, rcly, bpp );
1152                POINTL aptlPoints[4]={ pda->drawrect.xLeft, pda->drawrect.yBottom,
1153                                       pda->drawrect.xRight-1, pda->drawrect.yTop-1,
1154                                       0, 0, rclx, rcly };
1155                doc->renderPageToPixbuf( ev, pda->pagenum, spos_x, spos_y,
1156                                         rclx, rcly, realzoom, rotation, pixbuf );
1157                LONG lRop = ROP_SRCCOPY;
1158                BITMAPINFO2 pbmi;
1159                pbmi.cbFix = 16L;
1160                pbmi.cx = rclx;
1161                pbmi.cy = rcly;
1162                pbmi.cPlanes = 1;
1163                pbmi.cBitCount = bpp * 8;
1164                GpiDrawBits( hpsBuffer, pixbuf->getDataPtr( ev ), &pbmi, 4L,
1165                             aptlPoints, lRop, BBO_IGNORE );
1166                delete pixbuf;
1167                pixbuf = NULL;
1168            }
[2]1169
[50]1170            drawSelection( pda->pagenum, hpsBuffer, &pda->drawrect );
1171            drawFound( pda->pagenum, hpsBuffer, &pda->drawrect );
1172        }
1173        delete drawareas;
1174        drawareas = NULL;
[2]1175    }
1176    BlitGraphicsBuffer( hps, hpsBuffer, &rcl );
1177    WinEndPaint( hps );
1178
[50]1179    if ( doc != NULL ) {
1180        determineCurrentPage();
1181    }
[2]1182}
1183
1184
[59]1185// Rotates document rectangle
1186void DocumentViewer::rotateRectangle( long pagenum, LuRectangle *r )
[2]1187{
[59]1188    double tmp_x1 = r->x1;
[55]1189    double tmp_y1 = r->y1;
1190    double tmp_x2 = r->x2;
1191    double tmp_y2 = r->y2;
1192
[59]1193    double w = pagesizes[ pagenum ].x;
1194    double h = pagesizes[ pagenum ].y;
1195
[55]1196    if ( rotation == 90 ) {
[59]1197        r->x1 = tmp_y1;
1198        r->y1 = w - tmp_x1;
1199        r->x2 = tmp_y2;
1200        r->y2 = w - tmp_x2;
1201    }
1202    else if ( rotation == 180 )
1203    {
1204        r->x1 = w - tmp_x2;
1205        r->y1 = h - tmp_y2;
1206        r->x2 = w - tmp_x1;
1207        r->y2 = h - tmp_y1;
1208    }
1209    else if ( rotation == 270 )
1210    {
1211        r->x1 = h - tmp_y1;
[55]1212        r->y1 = tmp_x1;
[59]1213        r->x2 = h - tmp_y2;
[55]1214        r->y2 = tmp_x2;
1215    }
[59]1216
1217    if ( r->x1 > r->x2 ) {
1218        double tmp = r->x1;
1219        r->x1 = r->x2;
1220        r->x2 = tmp;
1221    }
1222
1223    if ( r->y1 > r->y2 ) {
1224        double tmp = r->y1;
1225        r->y1 = r->y2;
1226        r->y2 = tmp;
1227    }
[2]1228}
1229
[22]1230// converts window position to document position
[59]1231// single page mode only
1232void DocumentViewer::winPosToDocPos( PPOINTL startpoint, PPOINTL endpoint, LuRectangle *r )
1233{
1234    r->x1 = ( startpoint->x + sHscrollPos ) / realzoom;
1235    r->y1 = ( ( cyClient - startpoint->y ) + sVscrollPos ) / realzoom;
1236    r->x2 = ( endpoint->x + sHscrollPos ) / realzoom;
1237    r->y2 = ( ( cyClient - endpoint->y ) + sVscrollPos ) / realzoom;
1238
1239    rotateRectangle( currentpage, r );
1240}
1241
1242// converts window position to document position
[22]1243// continuous view mode only
1244void DocumentViewer::winPosToDocPos( PageDrawArea *pda, LuRectangle *r )
1245{
1246    r->x1 = ( sHscrollPos + pda->drawrect.xLeft ) / realzoom;;
1247    r->y1 = pda->startpos.y / realzoom;
1248    r->x2 = ( ( pda->drawrect.xRight - pda->drawrect.xLeft ) / realzoom ) + r->x1;
1249    r->y2 = ( ( pda->drawrect.yTop - pda->drawrect.yBottom ) / realzoom ) + r->y1;
[59]1250
1251    rotateRectangle( pda->pagenum, r );
[22]1252}
1253
[2]1254// converts document position to window position
[59]1255void DocumentViewer::docPosToWinPos( long pagenum, LuRectangle *r, PRECTL rcl )
[2]1256{
[19]1257    double yplus = continuous ? pagenumToPos( pagenum ) : 0;
[59]1258    double w = pagesizes[ pagenum ].x;
1259    double h = pagesizes[ pagenum ].y;
[17]1260
[55]1261    double tmp_x1 = r->x1;
1262    double tmp_y1 = r->y1;
1263    double tmp_x2 = r->x2;
1264    double tmp_y2 = r->y2;
1265
1266    if ( rotation == 90 )
1267    {
[59]1268        tmp_x1 = w - r->y2;
[55]1269        tmp_y1 = r->x1;
[59]1270        tmp_x2 = w - r->y1;
[55]1271        tmp_y2 = r->x2;
1272    }
1273    else if ( rotation == 180 )
1274    {
[59]1275        tmp_x1 = w - r->x2;
1276        tmp_y1 = h - r->y2;
1277        tmp_x2 = w - r->x1;
1278        tmp_y2 = h - r->y1;
[55]1279    }
1280    else if ( rotation == 270 )
1281    {
1282        tmp_x1 = r->y1;
[59]1283        tmp_y1 = h - r->x2;
[55]1284        tmp_x2 = r->y2;
[59]1285        tmp_y2 = h - r->x1;
[55]1286    }
1287
[59]1288    rcl->xLeft   = ( tmp_x1 * realzoom ) - sHscrollPos;
1289    rcl->yBottom = cyClient - ( yplus + ( tmp_y2 * realzoom ) ) + ( sVscrollPos * VScrollStep );
1290    rcl->xRight  = ( tmp_x2 * realzoom ) - sHscrollPos;
1291    rcl->yTop    = cyClient - ( yplus + ( tmp_y1 * realzoom ) ) + ( sVscrollPos * VScrollStep );
[2]1292}
1293
1294// creates region from sequence of rectangles
[59]1295HRGN DocumentViewer::rectsToRegion( long pagenum, HPS hps, LuDocument_LuRectSequence *rects )
[2]1296{
1297    HRGN hrgn = GpiCreateRegion( hps, 0, NULL );
1298    if ( rects != NULL )
1299    {
1300        RECTL r = {0};
1301        for ( int i = 0; i < rects->_length; i++ )
1302        {
[59]1303            docPosToWinPos( pagenum, &(rects->_buffer[i]), &r );
[2]1304            HRGN tmprgn = GpiCreateRegion( hps, 1, &r );
1305            GpiCombineRegion( hps, hrgn, hrgn, tmprgn, CRGN_OR );
1306            GpiDestroyRegion( hps, tmprgn );
1307        }
1308    }
1309    return hrgn;
1310}
1311
1312// draws selected area in window, using XOR mix
1313// drawing area may be restricted by r rectangle
[19]1314void DocumentViewer::drawSelection( long pagenum, HPS hps, PRECTL r )
[2]1315{
1316    GpiSetMix( hps, FM_XOR );
1317    GpiSetColor( hps, CLR_YELLOW );
[59]1318    HRGN selectRegion = rectsToRegion( pagenum, hps, selrects[ pagenum ] );
[2]1319    if ( r != NULL )
1320    {
1321        HRGN tmprgn = GpiCreateRegion( hps, 1, r );
1322        GpiCombineRegion( hps, selectRegion, selectRegion, tmprgn, CRGN_AND );
1323        GpiDestroyRegion( hps, tmprgn );
1324    }
1325    GpiPaintRegion( hps, selectRegion );
1326    GpiDestroyRegion( hps, selectRegion );
1327}
1328
[19]1329void DocumentViewer::drawFound( long pagenum, HPS hps, PRECTL r )
[2]1330{
1331    GpiSetMix( hps, FM_XOR );
1332    GpiSetColor( hps, CLR_CYAN );
[59]1333    HRGN selectRegion = rectsToRegion( pagenum, hps, foundrects[ pagenum ] );
[2]1334    if ( r != NULL )
1335    {
1336        HRGN tmprgn = GpiCreateRegion( hps, 1, r );
1337        GpiCombineRegion( hps, selectRegion, selectRegion, tmprgn, CRGN_AND );
1338        GpiDestroyRegion( hps, tmprgn );
1339    }
1340    GpiPaintRegion( hps, selectRegion );
1341    GpiDestroyRegion( hps, selectRegion );
1342}
1343
[17]1344// scrolls window to specified pos (optionally with text selection)
[19]1345void DocumentViewer::scrollToPos( HWND hwnd, HRGN hrgn, LONG xpos, LONG ypos,
[2]1346                                  bool withSelection )
1347{
1348    SHORT xinc = 0;
1349    SHORT yinc = 0;
1350
1351    if ( ( xpos < 0 ) && ( sHscrollPos > 0 ) ) {
1352        xinc = __max( sHscrollPos * -1, xpos );
1353    } else if ( ( xpos > cxClient ) && ( sHscrollPos < sHscrollMax ) ) {
1354        xinc = __min( sHscrollMax - sHscrollPos, xpos - cxClient );
1355    }
1356    if ( ( ypos < 0 ) && ( sVscrollPos < sVscrollMax ) ) {
[19]1357        yinc = __min( ( sVscrollMax - sVscrollPos ) * VScrollStep, ypos * -1 );
[2]1358    }
1359    else if ( ( ypos > cyClient ) && ( sVscrollPos > 0 ) ) {
[19]1360        yinc = __max( ( sVscrollPos * -1 ) * VScrollStep, cyClient - ypos );
[2]1361    }
1362
1363    if ( xinc != 0 ) {
1364        horizScroll( hwnd, MPFROM2SHORT( sHscrollPos + xinc, SB_SLIDERPOSITION ), hrgn );
1365        if ( withSelection ) {
1366            selectionStart.x -= xinc;
1367        }
1368    }
[65]1369
1370    if ( yinc != 0 )
1371    {
1372        SHORT remainder = yinc % VScrollStep;
1373        if ( remainder != 0 ) {
1374            SHORT add = VScrollStep - remainder;
1375            yinc += ( ( yinc > 0 ) ? add : -add );
1376        }
1377
[19]1378        vertScroll( hwnd, MPFROM2SHORT( ( ( sVscrollPos * VScrollStep ) + yinc ) / VScrollStep,
1379                                        SB_SLIDERPOSITION ), hrgn );
[2]1380        if ( withSelection ) {
1381            selectionStart.y += yinc;
1382        }
1383    }
1384}
1385
1386// handles WM_MOUSEMOVE
1387// performs text selection if mouse button pressed
1388// changes mouse ptr to 'hand' if it moves over link area
1389BOOL DocumentViewer::wmMouseMove( HWND hwnd, SHORT xpos, SHORT ypos )
1390{
1391    if ( mousePressed && ( doc != NULL ) )
1392    {
1393        selectionEnd.x = xpos;
1394        selectionEnd.y = ypos;
1395
[22]1396        if ( continuous )
1397        {
[23]1398            scrollToPos( hwnd, NULLHANDLE, xpos, ypos, true );
1399
[22]1400            RECTL selRect = {
1401                selectionStart.x < selectionEnd.x ? selectionStart.x : selectionEnd.x,
1402                selectionStart.y < selectionEnd.y ? selectionStart.y : selectionEnd.y,
1403                selectionStart.x < selectionEnd.x ? selectionEnd.x : selectionStart.x,
1404                selectionStart.y < selectionEnd.y ? selectionEnd.y : selectionStart.y
1405            };
[2]1406
[22]1407            DrawAreas *areas = findDrawAreas( &selRect );
[2]1408
[22]1409            HPS hps = WinGetPS( hwnd );
1410            GpiSetMix( hps, FM_XOR );
1411            GpiSetColor( hps, CLR_YELLOW );
[2]1412
[22]1413            for ( int i = 0; i < areas->size(); i++ )
1414            {
1415                PageDrawArea *pda = &(*areas)[ i ];
[2]1416
[23]1417                winPosToDocPos( pda, &(selection[pda->pagenum]) );
[2]1418
[59]1419                HRGN clearRegion = rectsToRegion( pda->pagenum, hps, selrects[ pda->pagenum ] );
[22]1420                LuDocument::freeRectangles( ev, selrects[ pda->pagenum ] );
[59]1421                selrects[ pda->pagenum ] = doc->getSelectionRectangles( ev, pda->pagenum, &(selection[pda->pagenum]) );
1422                HRGN selectRegion = rectsToRegion( pda->pagenum, hps, selrects[ pda->pagenum ] );
[22]1423                GpiCombineRegion( hps, selectRegion, selectRegion, clearRegion, CRGN_XOR );
1424                GpiPaintRegion( hps, selectRegion );
1425                GpiDestroyRegion( hps, clearRegion );
1426                GpiDestroyRegion( hps, selectRegion );
1427            }
1428
1429            WinReleasePS( hps );
1430            delete areas;
[2]1431        }
[22]1432        else
1433        {
[23]1434            winPosToDocPos( &selectionStart, &selectionEnd, &(selection[currentpage]) );
[22]1435
1436            HPS hps = WinGetPS( hwnd );
1437            HRGN scrolledRegion = NULLHANDLE; //GpiCreateRegion( hps, 0, NULL );
1438
1439            scrollToPos( hwnd, scrolledRegion, xpos, ypos, true );
1440
1441            // 127/191/255
1442            //LONG lclr = ( 127 << 16 ) | ( 191 << 8 ) | 255;
1443            //LONG lclr = ( 128 << 16 ) | ( 64 << 8 );
1444            //LONG ltabl[ 1 ] = { lclr };
1445            //GpiCreateLogColorTable( hps, 0, LCOLF_CONSECRGB, 100, 1, ltabl );
1446
1447            GpiSetMix( hps, FM_XOR );
1448            GpiSetColor( hps, CLR_YELLOW );
1449            //GpiSetColor( hps, 100 );
1450
[59]1451            HRGN clearRegion = rectsToRegion( currentpage, hps, selrects[ currentpage ] );
[22]1452            LuDocument::freeRectangles( ev, selrects[ currentpage ] );
1453            if ( ( selectionStart.x == selectionEnd.x ) &&
1454                 ( selectionStart.y == selectionEnd.y ) ) {
1455                selrects[ currentpage ] = NULL;
[23]1456                memset( &(selection[ currentpage ]), 0, sizeof( LuRectangle ) );
[22]1457            }
1458            else {
[59]1459                selrects[ currentpage ] = doc->getSelectionRectangles( ev, currentpage, &(selection[currentpage]) );
[22]1460            }
[59]1461            HRGN selectRegion = rectsToRegion( currentpage, hps, selrects[ currentpage ] );
[22]1462            GpiCombineRegion( hps, selectRegion, selectRegion, clearRegion, CRGN_XOR );
1463            //GpiCombineRegion( hps, selectRegion, selectRegion, scrolledRegion, CRGN_DIFF );
1464            GpiPaintRegion( hps, selectRegion );
1465            GpiDestroyRegion( hps, clearRegion );
1466            GpiDestroyRegion( hps, selectRegion );
1467            //GpiDestroyRegion( hps, scrolledRegion );
1468
1469            WinReleasePS( hps );
[2]1470        }
1471    }
1472    else if ( links != NULL )
1473    {
[17]1474        long pg = currentpage;
1475        if ( continuous ) {
1476            double tmp;
1477            pg = posToPagenum( ypos, &tmp );
1478        }
1479
1480        if ( links[ pg ] != NULL )
[2]1481        {
[17]1482            for ( int i = 0; i < links[ pg ]->_length; i++ )
1483            {
1484                RECTL r = {0};
1485                docPosToWinPos( pg, &(links[ pg ]->_buffer[i].area), &r );
[2]1486
[17]1487                POINTL ptl = { xpos, ypos };
1488                if ( WinPtInRect( hab, &r, &ptl ) ) {
1489                    WinSetPointer( HWND_DESKTOP, handptr );
1490                    return TRUE;
1491                }
[2]1492            }
1493        }
1494    }
1495
1496    return FALSE;
1497}
1498
1499// handles WM_BUTTON1CLICK
1500BOOL DocumentViewer::wmClick( HWND hwnd, SHORT xpos, SHORT ypos )
1501{
[17]1502    if ( links == NULL ) {
1503        return FALSE;
1504    }
1505
1506    long pg = currentpage;
1507    if ( continuous ) {
1508        double tmp;
1509        pg = posToPagenum( ypos, &tmp );
1510    }
1511
1512    if ( links[ pg ] != NULL )
[2]1513    {
[17]1514        for ( int i = 0; i < links[ pg ]->_length; i++ )
[2]1515        {
1516            RECTL r = {0};
[17]1517            docPosToWinPos( pg, &(links[ pg ]->_buffer[i].area), &r );
[2]1518
1519            POINTL ptl = { xpos, ypos };
1520            if ( WinPtInRect( hab, &r, &ptl ) )
1521            {
[17]1522                if ( links[ pg ]->_buffer[i].link.type == LU_LINK_TYPE_EXTERNAL_URI )
[2]1523                {
1524                    WinMessageBox( HWND_DESKTOP, hMainFrame,
[17]1525                        links[ pg ]->_buffer[i].link.uri, "URI", 1,
[2]1526                        MB_OK | MB_INFORMATION | MB_MOVEABLE );
1527                }
[17]1528                else if ( links[ pg ]->_buffer[i].link.type == LU_LINK_TYPE_TITLE )
[2]1529                {
[17]1530                    char *title = links[ pg ]->_buffer[i].link.title;
[2]1531                    if ( title == NULL ) {
1532                        title = "???";
1533                    }
1534                    WinMessageBox( HWND_DESKTOP, hMainFrame,
1535                        title, "?", 1, MB_OK | MB_INFORMATION | MB_MOVEABLE );
1536                }
[17]1537                else if ( links[ pg ]->_buffer[i].link.type == LU_LINK_TYPE_PAGE )
[2]1538                {
[17]1539                    goToPage( links[ pg ]->_buffer[i].link.page );
[2]1540                }
1541
1542                return TRUE;
1543            }
1544        }
1545    }
1546
1547    return FALSE;
1548}
1549
1550
1551BOOL DocumentViewer::wmChar( HWND hwnd, MPARAM mp1, MPARAM mp2 )
1552{
1553    USHORT fsflags = SHORT1FROMMP( mp1 );
1554    USHORT usvk = SHORT2FROMMP( mp2 );
1555
1556    if ( ( fsflags & KC_VIRTUALKEY ) && !( fsflags & KC_KEYUP ) )
1557    {
1558        switch ( usvk )
1559        {
1560            case VK_UP:
1561                WinSendMsg( hwnd, WM_VSCROLL, MPVOID, MPFROM2SHORT( 0, SB_LINEUP ) );
1562                return TRUE;
1563
1564            case VK_DOWN:
1565                WinSendMsg( hwnd, WM_VSCROLL, MPVOID, MPFROM2SHORT( 0, SB_LINEDOWN ) );
1566                return TRUE;
1567
1568            case VK_PAGEUP:
[69]1569                if ( fsflags & KC_CTRL ) {
1570                    vertScroll( hwnd, MPFROM2SHORT( 0, SB_SLIDERPOSITION ), NULLHANDLE );
1571                } else {
1572                    WinSendMsg( hwnd, WM_VSCROLL, MPVOID, MPFROM2SHORT( 0, SB_PAGEUP ) );
1573                }
[2]1574                return TRUE;
1575
1576            case VK_PAGEDOWN:
[69]1577                if ( fsflags & KC_CTRL ) {
1578                    vertScroll( hwnd, MPFROM2SHORT( sVscrollMax, SB_SLIDERPOSITION ), NULLHANDLE );
1579                } else {
1580                    WinSendMsg( hwnd, WM_VSCROLL, MPVOID, MPFROM2SHORT( 0, SB_PAGEDOWN ) );
1581                }
[2]1582                return TRUE;
1583
1584            case VK_LEFT:
1585                WinSendMsg( hwnd, WM_HSCROLL, MPVOID, MPFROM2SHORT( 0, SB_LINELEFT ) );
1586                return TRUE;
1587
1588            case VK_RIGHT:
1589                WinSendMsg( hwnd, WM_HSCROLL, MPVOID, MPFROM2SHORT( 0, SB_LINERIGHT ) );
1590                return TRUE;
[69]1591
1592            case VK_HOME:
1593                horizScroll( hwnd, MPFROM2SHORT( 0, SB_SLIDERPOSITION ), NULLHANDLE );
1594                return TRUE;
1595
1596            case VK_END:
1597                horizScroll( hwnd, MPFROM2SHORT( sHscrollMax, SB_SLIDERPOSITION ), NULLHANDLE );
1598                return TRUE;
1599
[2]1600        }
1601    }
1602
1603    return FALSE;
1604}
1605
[22]1606// handles WM_BUTTON1DOWN
1607void DocumentViewer::wmButton1Down( HWND hwnd, SHORT xpos, SHORT ypos )
1608{
[23]1609    if ( continuous && ( doc != NULL ) )
[22]1610    {
1611        // clear selection
1612        RECTL rcl = { 0 };
1613        WinQueryWindowRect( hwnd, &rcl );
1614        DrawAreas *areas = findDrawAreas( &rcl );
[2]1615
[22]1616        HPS hps = WinGetPS( hwnd );
1617        GpiSetMix( hps, FM_XOR );
1618        GpiSetColor( hps, CLR_YELLOW );
1619
1620        for ( int i = 0; i < areas->size(); i++ )
1621        {
1622            PageDrawArea *pda = &(*areas)[ i ];
1623
[59]1624            HRGN clearRegion = rectsToRegion( pda->pagenum, hps, selrects[ pda->pagenum ] );
[22]1625            GpiPaintRegion( hps, clearRegion );
1626            GpiDestroyRegion( hps, clearRegion );
1627        }
1628        WinReleasePS( hps );
1629        delete areas;
1630
1631        freeRects( selrects );
[23]1632
1633        memset( selection, 0, sizeof( LuRectangle ) * totalpages );
[22]1634    }
1635
1636    WinSetCapture( HWND_DESKTOP, hwnd );
1637    mousePressed = true;
1638    selectionStart.x = xpos;
1639    selectionStart.y = ypos;
1640}
1641
[23]1642// handles WM_BUTTON1UP
1643void DocumentViewer::wmButton1Up()
1644{
1645    WinSetCapture( HWND_DESKTOP, NULLHANDLE );
1646    mousePressed = false;
[22]1647
[23]1648    bool haveSelection = false;
1649    for ( long i = 0; i < totalpages; i++ ) {
1650        if ( selrects[ i ] != NULL ) {
1651            haveSelection = true;
1652            break;
1653        }
1654    }
1655
1656    Lucide::enableCopy( haveSelection );
1657}
1658
[25]1659
1660// handles DM_DRAGOVER
1661MRESULT DocumentViewer::wmDragOver( PDRAGINFO dragInfo )
1662{
1663    PDRAGITEM dragItem;
1664    USHORT    usOp, usIndicator;
1665
1666    usOp = 0;
1667    usIndicator = DOR_NODROPOP;
1668
1669    DrgAccessDraginfo( dragInfo );
1670
1671    if ( dragInfo->usOperation == DO_DEFAULT )
1672    {
1673        dragItem = DrgQueryDragitemPtr( dragInfo, 0 );
1674        if ( DrgQueryDragitemCount( dragInfo ) == 1 )
1675        {
1676            if ( DrgVerifyRMF( dragItem, "DRM_OS2FILE", NULL ) &&
1677                 ( dragItem->hstrContainerName != NULLHANDLE ) &&
1678                 ( dragItem->hstrSourceName != NULLHANDLE ) )
1679            {
1680                char fname[ CCHMAXPATHCOMP ] = "";
1681                DrgQueryStrName( dragItem->hstrSourceName, CCHMAXPATHCOMP, fname );
1682                char *ext = strrchr( fname, '.' );
1683                if ( ext != NULL ) {
1684                    if ( pluginMan->createDocumentForExt( ext + 1, true ) != NULL ) {
1685                        usIndicator = DOR_DROP;
1686                        usOp = DO_UNKNOWN;
1687                    }
1688                }
1689            }
1690        }
1691    }
1692
1693    DrgFreeDraginfo( dragInfo );
1694    return MRFROM2SHORT( usIndicator, usOp );
1695}
1696
1697
1698// handles DM_DROP
1699void DocumentViewer::wmDrop( PDRAGINFO dragInfo )
1700{
1701    PDRAGITEM dragItem;
1702
1703    DrgAccessDraginfo( dragInfo );
1704    dragItem = DrgQueryDragitemPtr( dragInfo, 0 );
1705
1706    char fname[ CCHMAXPATHCOMP ] = "";
1707    char fpath[ CCHMAXPATH ] = "";
1708    DrgQueryStrName( dragItem->hstrSourceName, CCHMAXPATHCOMP, fname );
1709    DrgQueryStrName( dragItem->hstrContainerName, CCHMAXPATH, fpath );
1710    DrgFreeDraginfo( dragInfo );
1711
1712    strcat( fpath, fname );
1713    Lucide::loadDocument( fpath );
1714}
1715
[67]1716
[2]1717// static, window procedure
1718MRESULT EXPENTRY DocumentViewer::docViewProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
1719{
1720    DocumentViewer *_this = (DocumentViewer *)WinQueryWindowULong( hwnd, QWL_USER );
1721
1722    switch ( msg )
1723    {
1724        case WM_CREATE:
1725        {
1726            // Save the mp1 into our user data so that subsequent calls have
1727            // access to the parent C++ object
1728            WinSetWindowULong( hwnd, QWL_USER, (ULONG)mp1 );
1729            _this = (DocumentViewer *)mp1;
1730            return (MRESULT)FALSE;
1731        }
1732
[25]1733        case DM_DRAGOVER:
1734            return _this->wmDragOver( (PDRAGINFO)mp1 );
1735
1736        case DM_DROP:
1737            _this->wmDrop( (PDRAGINFO)mp1 );
1738            return (MRESULT)FALSE;
1739
[2]1740        case WM_ERASEBACKGROUND:
1741            return (MRESULT)TRUE;
1742
1743        case WM_SIZE:
1744            _this->wmSize( hwnd, mp2 );
1745            return (MRESULT)FALSE;
1746
1747        case WM_HSCROLL:
1748            _this->horizScroll( hwnd, mp2, NULLHANDLE );
1749            break;
1750
1751        case WM_VSCROLL:
1752            _this->vertScroll( hwnd, mp2, NULLHANDLE );
1753            break;
1754
1755        case WM_PAINT:
1756            if ( _this->enableAsynchDraw ) {
[18]1757                if ( _this->continuous ) {
1758                    _this->wmPaintContAsynch( hwnd );
1759                } else {
1760                    _this->wmPaintAsynch( hwnd );
1761                }
[2]1762            } else {
1763                if ( _this->continuous ) {
1764                    _this->wmPaintCont( hwnd );
1765                } else {
1766                    _this->wmPaint( hwnd );
1767                }
1768            }
1769            return (MRESULT)FALSE;
1770
1771        case WM_BUTTON1DOWN:
[22]1772            _this->wmButton1Down( hwnd, SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ) );
[2]1773            break;
1774
1775        case WM_BUTTON1UP:
[23]1776            _this->wmButton1Up();
[2]1777            break;
1778
1779        case WM_MOUSEMOVE:
1780            if ( _this->wmMouseMove( hwnd, SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ) ) ) {
1781                return (MRESULT)TRUE;
1782            }
1783            break;
1784
1785        case WM_BUTTON1CLICK:
1786            if ( _this->wmClick( hwnd, SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ) ) ) {
1787                return (MRESULT)TRUE;
1788            }
1789            break;
1790
1791        case WM_CHAR:
1792            if ( _this->wmChar( hwnd, mp1, mp2 ) ) {
1793                return (MRESULT)TRUE;
1794            }
1795            break;
1796    }
1797
1798    return WinDefWindowProc( hwnd, msg, mp1, mp2 );
1799}
1800
[67]1801
1802// static, window procedure
1803MRESULT EXPENTRY DocumentViewer::docFrameProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
1804{
1805    DocumentViewer *_this = (DocumentViewer *)WinQueryWindowULong( hwnd, QWL_USER );
1806
1807    switch ( msg )
1808    {
1809        case WM_SYSCOMMAND:
1810            // Send WM_SYSCOMMAND messages to main frame
1811            WinSendMsg( _this->hMainFrame, WM_SYSCOMMAND, mp1, mp2 );
1812            return (MRESULT)FALSE;
1813    }
1814
1815    return _this->oldFrameProc( hwnd, msg, mp1, mp2 );
1816}
1817
Note: See TracBrowser for help on using the repository browser.