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

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

Fixed scrolling problem (closing #53, #56, #64), background color changes (closing #61), updated icon

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