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

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

fixes

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