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

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

intermediate commit, text selection in continuous view nearly works

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