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

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

implemented continuous view (synch/asynch), text search and selection doesn't work yet in continuous view

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