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

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

bitmap printing, preliminary postscript printing, export to PS for djvu plugin, other improvements

File size: 61.7 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#define PAGEBACK_COLOR  0xFFFFFFL
67#define VERT_SPACE      2
68
69// DocumentViewer constructor
70DocumentViewer::DocumentViewer( HWND hWndFrame )
71{
72    hMainFrame  = hWndFrame;
73    sHscrollMax = 0;
74    sVscrollMax = 0;
75    sHscrollPos = 0;
76    sVscrollPos = 0;
77    sVscrollInc = 0;
78    sHscrollInc = 0;
79    cxClient    = 0;
80    cyClient    = 0;
81    hWndDoc     = NULLHANDLE;
82    doc         = NULL;
83    totalpages  = 0;
84    currentpage = 0;
85    hpsBuffer   = NULLHANDLE;
86    hdcBuffer   = NULLHANDLE;
87    width       = 0;
88    height      = 0;
89    fullwidth   = 0;
90    fullheight  = 0;
91    bpp         = 0;
92    zoom        = 1.0;
93    realzoom    = 1.0;
94    rotation    = 0;
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()
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 ( isRotated() ) {
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 + VERT_SPACE );
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( 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        fullheight += ( VERT_SPACE * totalpages );
587    }
588}
589
590// page redraw
591void DocumentViewer::drawPage()
592{
593    if ( !continuous )
594    {
595        LuDocument::freeRectangles( ev, selrects[ currentpage ] );
596        selrects[ currentpage ] = NULL;
597
598        if ( links != NULL ) {
599            if ( links[ currentpage ] == NULL ) {
600                links[ currentpage ] = doc->getLinkMapping( ev, currentpage );
601            }
602        }
603
604        Lucide::enableCopy( false );
605    }
606    WinSendMsg( hWndDoc, WM_SIZE, MPFROM2SHORT( cxClient, cyClient ),
607                MPFROM2SHORT( cxClient, cyClient ) );
608    WinInvalidateRect( hWndDoc, NULL, FALSE );
609}
610
611
612// handles vertical scrolling
613MRESULT DocumentViewer::vertScroll( HWND hwnd, MPARAM mp2, HRGN hrgn )
614{
615    if ( fullscreen ) {
616        return ( MRFROMLONG( 0 ) );
617    }
618
619    sVscrollInc = 0;
620
621    switch ( SHORT2FROMMP( mp2 ) )
622    {
623        case SB_LINEUP:
624            sVscrollInc = -(__max( LINE_HEIGHT, VScrollStep ));
625            break ;
626        case SB_LINEDOWN:
627            sVscrollInc = __max( LINE_HEIGHT, VScrollStep );
628            break;
629        case SB_PAGEUP:
630            sVscrollInc = __min( -1, -( cyClient - LINE_HEIGHT ) );
631            break;
632        case SB_PAGEDOWN:
633            sVscrollInc = __max( 1, cyClient - LINE_HEIGHT );
634            break;
635        case SB_SLIDERTRACK:
636        case SB_SLIDERPOSITION:
637            sVscrollInc = ( SHORT1FROMMP( mp2 ) - sVscrollPos ) * VScrollStep;
638            break;
639    }
640
641    sVscrollInc = __max( -sVscrollPos * VScrollStep, __min( sVscrollInc,
642                              ( sVscrollMax - sVscrollPos ) * VScrollStep ) );
643    sVscrollInc = ( sVscrollInc / VScrollStep ) * VScrollStep;
644    if ( sVscrollInc != 0 )
645    {
646        sVscrollPos += (SHORT)( sVscrollInc / VScrollStep );
647        WinScrollWindow( hwnd, 0, sVscrollInc, NULL, NULL, hrgn, NULL, SW_INVALIDATERGN );
648        WinSendMsg( hWndVscroll, SBM_SETPOS, MPFROMSHORT( sVscrollPos ), MPVOID );
649        WinUpdateWindow( hwnd );
650        sVscrollInc = 0;
651    }
652    return ( MRFROMLONG( 0 ) );
653}
654
655// handles horizontal scrolling
656MRESULT DocumentViewer::horizScroll( HWND hwnd, MPARAM mp2, HRGN hrgn )
657{
658    if ( fullscreen ) {
659        return ( MRFROMLONG( 0 ) );
660    }
661
662    sHscrollInc = 0;
663
664    switch ( SHORT2FROMMP( mp2 ) )
665    {
666        case SB_LINELEFT:
667            sHscrollInc = -LINE_HEIGHT;
668            break;
669        case SB_LINERIGHT:
670            sHscrollInc = LINE_HEIGHT;
671            break;
672        case SB_PAGELEFT:
673            sHscrollInc = __min( -1, -( cxClient - LINE_HEIGHT ) );
674            break;
675        case SB_PAGERIGHT:
676            sHscrollInc = __max( 1, cxClient - LINE_HEIGHT );
677            break;
678        case SB_SLIDERTRACK:
679        case SB_SLIDERPOSITION:
680            sHscrollInc = SHORT1FROMMP( mp2 ) - sHscrollPos;
681            break;
682    }
683
684    sHscrollInc = __max( -sHscrollPos, __min( sHscrollInc, sHscrollMax - sHscrollPos ) );
685
686    if ( sHscrollInc != 0 )
687    {
688        sHscrollPos += (SHORT)sHscrollInc;
689        WinScrollWindow( hwnd, -sHscrollInc, 0, NULL, NULL, hrgn, NULL, SW_INVALIDATERGN );
690        WinSendMsg( hWndHscroll, SBM_SETPOS, MPFROMSHORT( sHscrollPos ), MPVOID );
691        WinUpdateWindow( hwnd );
692        sHscrollInc = 0;
693    }
694    return ( MRFROMLONG( 0 ) );
695}
696
697
698// handles WM_SIZE message
699// creates appropriate hps buffer, sets scrollbars limits
700void DocumentViewer::wmSize( HWND hwnd, MPARAM mp2 )
701{
702    if ( !WinIsWindowShowing( hwnd ) ) {
703        return;
704    }
705
706    cxClient = SHORT1FROMMP( mp2 );
707    cyClient = SHORT2FROMMP( mp2 );
708
709    double relativeScrollPos = ( sVscrollMax == 0 ) ? 0 :
710                                    (double)sVscrollPos / (double)sVscrollMax;
711
712    adjustSize();
713
714    if ( ( hpsBuffer != NULLHANDLE ) && ( hdcBuffer != NULLHANDLE ) ) {
715        DestroyGraphicsBuffer( hpsBuffer, hdcBuffer );
716        hpsBuffer = hdcBuffer = NULLHANDLE;
717    }
718
719    HPS hps = WinGetPS( hwnd );
720    RECTL rectl = { 0, 0, cxClient, cyClient };
721    CreateGraphicsBuffer( hab, &rectl, hps, &hpsBuffer, &hdcBuffer );
722    WinReleasePS( hps );
723
724    if ( fullscreen )
725    {
726        sHscrollMax = 0;
727        sHscrollPos = 0;
728        realVscrollMax = 0;
729        VScrollStep = 1;
730        sVscrollPos = 0;
731    }
732    else
733    {
734        sHscrollMax = (SHORT)__max( 0, ( continuous ? fullwidth : width ) - cxClient );
735        sHscrollPos = __min( sHscrollPos, sHscrollMax );
736
737        WinSendMsg( hWndHscroll, SBM_SETSCROLLBAR,
738                    MPFROMSHORT(sHscrollPos), MPFROM2SHORT(0, sHscrollMax) );
739        WinSendMsg( hWndHscroll, SBM_SETTHUMBSIZE,
740                    MPFROM2SHORT( cxClient, width ), MPVOID );
741        WinEnableWindow( hWndHscroll, (BOOL)( sHscrollMax != 0 ) );
742
743        if ( continuous )
744        {
745            realVscrollMax = __max( 0, fullheight - cyClient );
746            VScrollStep = LINE_HEIGHT;
747            ULONG ssize = realVscrollMax / VScrollStep;
748            while ( ssize > 32000 ) {
749                VScrollStep += LINE_HEIGHT;
750                ssize = realVscrollMax / VScrollStep;
751            }
752
753            sVscrollMax = (SHORT)ssize;
754        }
755        else {
756            realVscrollMax = sVscrollMax = (SHORT)__max( 0, height - cyClient );
757            VScrollStep = 1;
758        }
759        sVscrollPos = __min( sVscrollPos, sVscrollMax );
760
761        WinSendMsg( hWndVscroll, SBM_SETSCROLLBAR,
762                    MPFROMSHORT(sVscrollPos), MPFROM2SHORT(0, sVscrollMax) );
763        if ( continuous ) {
764            WinSendMsg( hWndVscroll, SBM_SETTHUMBSIZE,
765                        MPFROM2SHORT( cyClient/VScrollStep, fullheight/VScrollStep ), MPVOID );
766        }
767        else {
768            WinSendMsg( hWndVscroll, SBM_SETTHUMBSIZE,
769                        MPFROM2SHORT( cyClient, height ), MPVOID );
770        }
771        WinEnableWindow( hWndVscroll, (BOOL)( sVscrollMax != 0 ) );
772
773        SHORT realScrollPos = (SHORT)(sVscrollMax * relativeScrollPos);
774        vertScroll( hWndDoc, MPFROM2SHORT( realScrollPos, SB_SLIDERPOSITION ), NULLHANDLE );
775    }
776}
777
778// returns true if subrect inside rect
779inline bool isSubrect( PRECTL rect, PRECTL subrect )
780{
781    return ( ( subrect->xLeft >= rect->xLeft ) &&
782             ( subrect->yBottom >= rect->yBottom ) &&
783             ( subrect->xRight <= rect->xRight ) &&
784             ( subrect->yTop <= rect->yTop ) );
785}
786
787// static method, cancels asynch rendering if abortAsynch is true
788long _System DocumentViewer::asynchCallbackFnAbort( void *data )
789{
790    return (long)(((DocumentViewer *)data)->abortAsynch);
791}
792
793// static method, draws area during asynch rendering
794long _System DocumentViewer::asynchCallbackFnDraw( void *data )
795{
796    DocumentViewer *_this = (DocumentViewer *)data;
797    HPS hps = WinGetPS( _this->hWndDoc );
798    if ( hps != NULLHANDLE )
799    {
800        PRECTL drawRect = &((*_this->drawareas)[_this->drawareaIndex].drawrect);
801        LONG rclx = drawRect->xRight - drawRect->xLeft;
802        LONG rcly = drawRect->yTop - drawRect->yBottom;
803
804        POINTL aptlPoints[4]={ drawRect->xLeft, drawRect->yBottom,
805                               drawRect->xRight-1, drawRect->yTop-1,
806                               0, 0, rclx, rcly };
807
808        LONG lRop = ROP_SRCCOPY;
809        BITMAPINFO2 pbmi;
810        pbmi.cbFix = 16L;
811        pbmi.cx = rclx;
812        pbmi.cy = rcly;
813        pbmi.cPlanes = 1;
814        pbmi.cBitCount = _this->bpp * 8;
815        GpiDrawBits( hps, _this->pixbuf->getDataPtr( ev ), &pbmi, 4L,
816                     aptlPoints, lRop, BBO_IGNORE );
817
818        WinReleasePS( hps );
819    }
820    return 0;
821}
822
823// static method, thread for asynchronous rendering
824void DocumentViewer::drawthread( void *p )
825{
826    DosSetPriority( PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MINIMUM, 0 );
827    DocumentViewer *_this = (DocumentViewer *)p;
828
829    HAB thab = WinInitialize( 0 );
830    HMQ thmq = WinCreateMsgQueue( thab, 0 );
831
832    ULONG postCnt;
833    while ( !_this->termdraw )
834    {
835        DosWaitEventSem( _this->haveDraw, SEM_INDEFINITE_WAIT );
836        DosResetEventSem( _this->haveDraw, &postCnt );
837        _this->abortAsynch = false;
838
839        if ( ( _this->drawareas != NULL ) && ( _this->doc != NULL ) )
840        {
841            DosRequestMutexSem( _this->todrawAccess, SEM_INDEFINITE_WAIT );
842
843            for ( _this->drawareaIndex = 0;
844                  _this->drawareaIndex < _this->drawareas->size();
845                  _this->drawareaIndex++ )
846            {
847                PageDrawArea *pda = &(*_this->drawareas)[ _this->drawareaIndex ];
848
849                LONG rclx = pda->drawrect.xRight - pda->drawrect.xLeft;
850                LONG rcly = pda->drawrect.yTop - pda->drawrect.yBottom;
851                _this->pixbuf = new LuPixbuf( ev, rclx, rcly, _this->bpp );
852                _this->doc->renderPageToPixbufAsynch( ev, pda->pagenum,
853                       pda->startpos.x, pda->startpos.y, rclx, rcly, _this->realzoom,
854                       _this->rotation, _this->pixbuf,
855                       asynchCallbackFnDraw, asynchCallbackFnAbort, p );
856                delete _this->pixbuf;
857                _this->pixbuf = NULL;
858
859                if ( _this->abortAsynch ) {
860                    break;  // TODO: remove completed areas from drawareas
861                }
862            }
863
864            if ( !_this->abortAsynch )
865            {
866                HPS hps = WinGetPS( _this->hWndDoc );
867                if ( hps != NULLHANDLE ) {
868                    for ( int i = 0; i < _this->drawareas->size(); i++ )
869                    {
870                        PageDrawArea *pda = &(*_this->drawareas)[ i ];
871
872                        _this->drawSelection( pda->pagenum, hps, &pda->drawrect );
873                        _this->drawFound( pda->pagenum, hps, &pda->drawrect );
874                    }
875                    WinReleasePS( hps );
876                }
877                WinSetRectEmpty( thab, &_this->savedRcl );
878                delete _this->drawareas;
879                _this->drawareas = NULL;
880            }
881
882            DosReleaseMutexSem( _this->todrawAccess );
883        }
884    }
885    WinDestroyMsgQueue( thmq );
886    WinTerminate( thab );
887    _endthread();
888}
889
890// handles WM_PAINT if single-page asynchronous rendering used
891// posts events to drawthread
892void DocumentViewer::wmPaintAsynch( HWND hwnd )
893{
894    LONG xPos = 0, yPos = 0;
895    RECTL rclPage = { 0 };
896    RECTL rcl;
897    HPS hps = WinBeginPaint( hwnd, 0L, &rcl );
898    GpiCreateLogColorTable( hpsBuffer, 0, LCOLF_RGB, 0, 0, NULL );
899    WinFillRect( hpsBuffer, &rcl, BORDER_COLOR );
900    if ( doc != NULL )
901    {
902        if ( width < cxClient ) {
903            xPos = ( cxClient - width ) / 2;
904        }
905        if ( height < cyClient ) {
906            yPos = ( cyClient - height ) / 2;
907        }
908
909        rclPage.xLeft   = xPos;
910        rclPage.yBottom = yPos;
911        rclPage.xRight  = width + xPos;
912        rclPage.yTop    = height + yPos;
913        WinFillRect( hpsBuffer, &rclPage, PAGEBACK_COLOR );
914    }
915    BlitGraphicsBuffer( hps, hpsBuffer, &rcl );
916    WinEndPaint( hps );
917
918    if ( doc != NULL )
919    {
920        RECTL rclDraw = { 0 };
921        if ( WinIntersectRect( hab, &rclDraw, &rcl, &rclPage ) )
922        {
923            if ( ( drawareas != NULL ) && ( drawareas->size() > 0 ) ) {
924                if ( isSubrect( &((*drawareas)[0].drawrect), &rclDraw ) &&
925                     ( sVscrollInc == 0 ) && ( sHscrollInc == 0 ) ) {
926                    return;
927                }
928            }
929
930            abortAsynch = true;
931            DosRequestMutexSem( todrawAccess, SEM_INDEFINITE_WAIT );
932
933            if ( drawareas == NULL ) {
934                drawareas = new DrawAreas;
935            }
936            if ( drawareas->size() == 0 ) {
937                PageDrawArea pda;
938                memset( &pda, 0, sizeof( pda ) );
939                pda.pagenum = currentpage;
940                drawareas->push_back( pda );
941            }
942
943            PageDrawArea *ppda = &((*drawareas)[0]);
944
945            if ( !WinIsRectEmpty( hab, &ppda->drawrect ) )
946            {
947                if ( sVscrollInc > 0 ) {
948                    ppda->drawrect.yTop    += sVscrollInc;
949                } else if ( sVscrollInc < 0 ) {
950                    ppda->drawrect.yBottom += sVscrollInc;
951                }
952                if ( sHscrollInc > 0 ) {
953                    ppda->drawrect.xLeft  -= sHscrollInc;
954                } else if ( sHscrollInc < 0 ) {
955                    ppda->drawrect.xRight -= sHscrollInc;
956                }
957            }
958            WinUnionRect( hab, &ppda->drawrect, &ppda->drawrect, &rclDraw );
959            ppda->startpos.x = sHscrollPos + ppda->drawrect.xLeft - xPos;
960            ppda->startpos.y = ( yPos > 0 ) ? rclPage.yTop - ppda->drawrect.yTop :
961                    ( cyClient - ppda->drawrect.yTop ) + sVscrollPos;
962
963            DosReleaseMutexSem( todrawAccess );
964            DosPostEventSem( haveDraw );
965        }
966    }
967}
968
969
970// handles WM_PAINT if continuous asynchronous rendering used
971void DocumentViewer::wmPaintContAsynch( HWND hwnd )
972{
973    RECTL rcl, rclWin, rclDraw = { 0 };
974    HPS hps = WinBeginPaint( hwnd, 0L, &rcl );
975    GpiCreateLogColorTable( hpsBuffer, 0, LCOLF_RGB, 0, 0, NULL );
976    WinFillRect( hpsBuffer, &rcl, BORDER_COLOR );
977
978    if ( doc != NULL )
979    {
980        long foundpage = -1;
981        double pageRest;
982        for ( LONG i = rcl.yTop; i >= rcl.yBottom; i-- )
983        {
984            pageRest = 0;
985            long pg = posToPagenum( i, &pageRest );
986            if ( ( pg != foundpage ) && ( pg != -1 ) )
987            {
988                RECTL rclPage = { 0 };
989                LuRectangle lr = { 0, 0,
990                    isRotated() ? (pagesizes[ pg ].y - 1) : (pagesizes[ pg ].x - 1),
991                    isRotated() ? (pagesizes[ pg ].x - 1) : (pagesizes[ pg ].y - 1) };
992                docPosToWinPos( pg, &lr, &rclPage );
993                WinFillRect( hpsBuffer, &rclPage, PAGEBACK_COLOR );
994                foundpage = pg;
995                i -= pageRest;
996            }
997        }
998    }
999
1000    BlitGraphicsBuffer( hps, hpsBuffer, &rcl );
1001    WinEndPaint( hps );
1002
1003    if ( doc != NULL )
1004    {
1005        if ( isSubrect( &savedRcl, &rcl ) && ( sVscrollInc == 0 ) && ( sHscrollInc == 0 ) ) {
1006            return;
1007        }
1008
1009        abortAsynch = true;
1010        DosRequestMutexSem( todrawAccess, SEM_INDEFINITE_WAIT );
1011
1012        WinQueryWindowRect( hwnd, &rclWin );
1013        WinUnionRect( hab, &rcl, &rcl, &savedRcl );
1014
1015        if ( sVscrollInc > 0 ) {
1016            rcl.yTop    += sVscrollInc;
1017        } else if ( sVscrollInc < 0 ) {
1018            rcl.yBottom += sVscrollInc;
1019        }
1020        if ( sHscrollInc > 0 ) {
1021            rcl.xLeft  -= sHscrollInc;
1022        } else if ( sHscrollInc < 0 ) {
1023            rcl.xRight -= sHscrollInc;
1024        }
1025
1026        WinIntersectRect( hab, &rclDraw, &rcl, &rclWin );
1027        WinCopyRect( hab, &rcl, &rclDraw );
1028        WinCopyRect( hab, &savedRcl, &rcl );
1029
1030        delete drawareas;
1031        drawareas = findDrawAreas( &rcl );
1032
1033        for ( int i = 0; i < drawareas->size(); i++ )
1034        {
1035            PageDrawArea *pda = &(*drawareas)[ i ];
1036
1037            // load links for page if not loaded before
1038            if ( links[ pda->pagenum ] == NULL ) {
1039                links[ pda->pagenum ] = doc->getLinkMapping( ev, pda->pagenum );
1040            }
1041        }
1042        DosReleaseMutexSem( todrawAccess );
1043        DosPostEventSem( haveDraw );
1044
1045        determineCurrentPage();
1046    }
1047}
1048
1049
1050// handles WM_PAINT if single-page synchronous rendering used
1051void DocumentViewer::wmPaint( HWND hwnd )
1052{
1053    RECTL rcl;
1054    HPS hps = WinBeginPaint( hwnd, 0L, &rcl );
1055    GpiCreateLogColorTable( hpsBuffer, 0, LCOLF_RGB, 0, 0, NULL );
1056    WinFillRect( hpsBuffer, &rcl, BORDER_COLOR );
1057
1058    if ( doc != NULL )
1059    {
1060        LONG xPos = 0, yPos = 0;
1061        if ( width < cxClient ) {
1062            xPos = ( cxClient - width ) / 2;
1063        }
1064        if ( height < cyClient ) {
1065            yPos = ( cyClient - height ) / 2;
1066        }
1067
1068        RECTL rclPage = { xPos, yPos, width + xPos, height + yPos };
1069        RECTL rclDraw = { 0 };
1070        if ( WinIntersectRect( hab, &rclDraw, &rcl, &rclPage ) )
1071        {
1072            spos_x = sHscrollPos + rclDraw.xLeft - xPos;
1073            spos_y = ( yPos > 0 ) ? rclPage.yTop - rclDraw.yTop : (cyClient - rclDraw.yTop) + sVscrollPos;
1074            LONG rclx = rclDraw.xRight - rclDraw.xLeft;
1075            LONG rcly = rclDraw.yTop - rclDraw.yBottom;
1076
1077            if ( drawPS )
1078            {
1079                doc->renderPageToPS( ev, currentpage, spos_x, spos_y, rclx, rcly,
1080                                     realzoom, rotation, hpsBuffer, &rclDraw );
1081            }
1082            else
1083            {
1084                pixbuf = new LuPixbuf( ev, rclx, rcly, bpp );
1085                POINTL aptlPoints[4]={ rclDraw.xLeft, rclDraw.yBottom,
1086                                       rclDraw.xRight-1, rclDraw.yTop-1,
1087                                       0, 0, rclx, rcly };
1088
1089                doc->renderPageToPixbuf( ev, currentpage, spos_x, spos_y,
1090                                         rclx, rcly, realzoom, rotation, pixbuf );
1091                LONG lRop = ROP_SRCCOPY;
1092                BITMAPINFO2 pbmi;
1093                pbmi.cbFix = 16L;
1094                pbmi.cx = rclx;
1095                pbmi.cy = rcly;
1096                pbmi.cPlanes = 1;
1097                pbmi.cBitCount = bpp * 8;
1098                GpiDrawBits( hpsBuffer, pixbuf->getDataPtr( ev ), &pbmi, 4L,
1099                             aptlPoints, lRop, BBO_IGNORE );
1100                delete pixbuf;
1101                pixbuf = NULL;
1102            }
1103
1104            drawSelection( currentpage, hpsBuffer, &rclDraw );
1105            drawFound( currentpage, hpsBuffer, &rclDraw );
1106        }
1107    }
1108    BlitGraphicsBuffer( hps, hpsBuffer, &rcl );
1109    WinEndPaint( hps );
1110}
1111
1112
1113// founds number of page at specified vertical position
1114// for continuous view only
1115long DocumentViewer::posToPagenum( LONG yPosWin, double *pageRest )
1116{
1117    double yPos = ( cyClient - yPosWin ) + ( sVscrollPos * VScrollStep );
1118    double pgstart = 0;
1119    double pgend = 0;
1120    for ( long i = 0; i < totalpages; i++ )
1121    {
1122        pgend = pgstart + ( pagesizes[ i ].y * realzoom );
1123        if ( ( yPos >= pgstart ) && ( yPos < pgend ) ) {
1124            *pageRest = pgend - yPos;
1125            return i;
1126        }
1127        pgstart = ( pgend + VERT_SPACE );
1128    }
1129    return -1;
1130}
1131
1132// founds vertical position of specified
1133// for continuous view only
1134double DocumentViewer::pagenumToPos( long pagenum )
1135{
1136    double ypos = 0;
1137    for ( long i = 0; i < pagenum; i++ ) {
1138        ypos += pagesizes[ i ].y;
1139    }
1140    return ( ( ypos * realzoom ) + ( pagenum * VERT_SPACE ) );
1141}
1142
1143// founds pages and it's areas to draw
1144// for continuous view only
1145DrawAreas *DocumentViewer::findDrawAreas( PRECTL r )
1146{
1147    DrawAreas *areas = new DrawAreas;
1148    if ( doc != NULL )
1149    {
1150        long foundpage = -1;
1151        double pageRest;
1152        for ( LONG i = r->yTop; i >= r->yBottom; i-- )
1153        {
1154            pageRest = 0;
1155            long pg = posToPagenum( i, &pageRest );
1156            if ( ( pg != foundpage ) && ( pg != -1 ) )
1157            {
1158                double w = pagesizes[ pg ].x * realzoom;
1159
1160                PageDrawArea pda = {0};
1161                pda.pagenum = pg;
1162
1163                LONG xPos = 0;
1164                if ( w < cxClient ) {
1165                    xPos = ( cxClient - w ) / 2;
1166                }
1167                RECTL rclPage = { 0 };
1168                LuRectangle lr = { 0, 0,
1169                    isRotated() ? (pagesizes[ pg ].y - 1) : (pagesizes[ pg ].x - 1),
1170                    isRotated() ? (pagesizes[ pg ].x - 1) : (pagesizes[ pg ].y - 1) };
1171                docPosToWinPos( pg, &lr, &rclPage );
1172                if ( WinIntersectRect( hab, &pda.drawrect, r, &rclPage ) )
1173                {
1174                    pda.startpos.x = sHscrollPos + pda.drawrect.xLeft - xPos;
1175                    pda.startpos.y = ( pagesizes[ pg ].y * realzoom ) - pageRest;
1176                    areas->push_back( pda );
1177                }
1178                foundpage = pg;
1179                i -= pageRest;
1180            }
1181        }
1182    }
1183
1184    return areas;
1185}
1186
1187
1188// found current page in continuous view mode.
1189// it's a page which occupes a most larger area in the window.
1190void DocumentViewer::determineCurrentPage()
1191{
1192    RECTL rcl = { 0 };
1193    WinQueryWindowRect( hWndDoc, &rcl );
1194    DrawAreas *areas = findDrawAreas( &rcl );
1195    long pg = 0;
1196    long sz = 0;
1197    for ( int i = 0; i < areas->size(); i++ )
1198    {
1199        PageDrawArea *pda = &(*areas)[ i ];
1200        long pgsz = pda->drawrect.yTop - pda->drawrect.yBottom;
1201        if ( pgsz > sz ) {
1202            pg = pda->pagenum;
1203            sz = pgsz;
1204        }
1205    }
1206    delete areas;
1207
1208    if ( pg != currentpage ) {
1209        currentpage = pg;
1210        Lucide::checkNavigationMenus();
1211    }
1212}
1213
1214
1215// handles WM_PAINT if continuous synchronous rendering used
1216void DocumentViewer::wmPaintCont( HWND hwnd )
1217{
1218    RECTL rcl;
1219    HPS hps = WinBeginPaint( hwnd, 0L, &rcl );
1220    GpiCreateLogColorTable( hpsBuffer, 0, LCOLF_RGB, 0, 0, NULL );
1221    WinFillRect( hpsBuffer, &rcl, BORDER_COLOR );
1222
1223    if ( doc != NULL )
1224    {
1225        delete drawareas;
1226        drawareas = findDrawAreas( &rcl );
1227
1228        for ( int i = 0; i < drawareas->size(); i++ )
1229        {
1230            PageDrawArea *pda = &(*drawareas)[ i ];
1231
1232            // load links for page if not loaded before
1233            if ( links[ pda->pagenum ] == NULL ) {
1234                links[ pda->pagenum ] = doc->getLinkMapping( ev, pda->pagenum );
1235            }
1236
1237            spos_x = pda->startpos.x;
1238            spos_y = pda->startpos.y;
1239            LONG rclx = pda->drawrect.xRight - pda->drawrect.xLeft;
1240            LONG rcly = pda->drawrect.yTop - pda->drawrect.yBottom;
1241
1242            if ( drawPS )
1243            {
1244                doc->renderPageToPS( ev, pda->pagenum, spos_x, spos_y, rclx, rcly,
1245                                     realzoom, rotation, hpsBuffer, &(pda->drawrect) );
1246            }
1247            else
1248            {
1249                pixbuf = new LuPixbuf( ev, rclx, rcly, bpp );
1250                POINTL aptlPoints[4]={ pda->drawrect.xLeft, pda->drawrect.yBottom,
1251                                       pda->drawrect.xRight-1, pda->drawrect.yTop-1,
1252                                       0, 0, rclx, rcly };
1253                doc->renderPageToPixbuf( ev, pda->pagenum, spos_x, spos_y,
1254                                         rclx, rcly, realzoom, rotation, pixbuf );
1255                LONG lRop = ROP_SRCCOPY;
1256                BITMAPINFO2 pbmi;
1257                pbmi.cbFix = 16L;
1258                pbmi.cx = rclx;
1259                pbmi.cy = rcly;
1260                pbmi.cPlanes = 1;
1261                pbmi.cBitCount = bpp * 8;
1262                GpiDrawBits( hpsBuffer, pixbuf->getDataPtr( ev ), &pbmi, 4L,
1263                             aptlPoints, lRop, BBO_IGNORE );
1264                delete pixbuf;
1265                pixbuf = NULL;
1266            }
1267
1268            drawSelection( pda->pagenum, hpsBuffer, &pda->drawrect );
1269            drawFound( pda->pagenum, hpsBuffer, &pda->drawrect );
1270        }
1271        delete drawareas;
1272        drawareas = NULL;
1273    }
1274    BlitGraphicsBuffer( hps, hpsBuffer, &rcl );
1275    WinEndPaint( hps );
1276
1277    if ( doc != NULL ) {
1278        determineCurrentPage();
1279    }
1280}
1281
1282
1283// Rotates document rectangle
1284void DocumentViewer::rotateRectangle( long pagenum, LuRectangle *r )
1285{
1286    double tmp_x1 = r->x1;
1287    double tmp_y1 = r->y1;
1288    double tmp_x2 = r->x2;
1289    double tmp_y2 = r->y2;
1290
1291    double w = pagesizes[ pagenum ].x;
1292    double h = pagesizes[ pagenum ].y;
1293
1294    if ( rotation == 90 ) {
1295        r->x1 = tmp_y1;
1296        r->y1 = w - tmp_x1;
1297        r->x2 = tmp_y2;
1298        r->y2 = w - tmp_x2;
1299    }
1300    else if ( rotation == 180 )
1301    {
1302        r->x1 = w - tmp_x2;
1303        r->y1 = h - tmp_y2;
1304        r->x2 = w - tmp_x1;
1305        r->y2 = h - tmp_y1;
1306    }
1307    else if ( rotation == 270 )
1308    {
1309        r->x1 = h - tmp_y1;
1310        r->y1 = tmp_x1;
1311        r->x2 = h - tmp_y2;
1312        r->y2 = tmp_x2;
1313    }
1314
1315    if ( r->x1 > r->x2 ) {
1316        double tmp = r->x1;
1317        r->x1 = r->x2;
1318        r->x2 = tmp;
1319    }
1320
1321    if ( r->y1 > r->y2 ) {
1322        double tmp = r->y1;
1323        r->y1 = r->y2;
1324        r->y2 = tmp;
1325    }
1326}
1327
1328// converts window position to document position
1329// single page mode only
1330void DocumentViewer::winPosToDocPos( PPOINTL startpoint, PPOINTL endpoint, LuRectangle *r )
1331{
1332    LONG sx = startpoint->x;
1333    LONG sy = startpoint->y;
1334    LONG ex = endpoint->x;
1335    LONG ey = endpoint->y;
1336    if ( width < cxClient ) {
1337        LONG xPos = ( cxClient - width ) / 2;
1338        sx -= xPos;
1339        ex -= xPos;
1340    }
1341    if ( height < cyClient ) {
1342        LONG yPos = ( cyClient - height ) / 2;
1343        sy += yPos;
1344        ey += yPos;
1345    }
1346
1347    r->x1 = ( sx + sHscrollPos ) / realzoom;
1348    r->y1 = ( ( cyClient - sy ) + sVscrollPos ) / realzoom;
1349    r->x2 = ( ex + sHscrollPos ) / realzoom;
1350    r->y2 = ( ( cyClient - ey ) + sVscrollPos ) / realzoom;
1351
1352    rotateRectangle( currentpage, r );
1353}
1354
1355// converts window position to document position
1356// continuous view mode only
1357void DocumentViewer::winPosToDocPos( PageDrawArea *pda, LuRectangle *r )
1358{
1359    LONG sx = pda->drawrect.xLeft;
1360    LONG ex = pda->drawrect.xRight;
1361    double w = pagesizes[ pda->pagenum ].x * realzoom;
1362    if ( w < cxClient ) {
1363        LONG xPos = ( cxClient - w ) / 2;
1364        sx -= xPos;
1365        ex -= xPos;
1366    }
1367
1368    r->x1 = ( sHscrollPos + sx ) / realzoom;;
1369    r->y1 = pda->startpos.y / realzoom;
1370    r->x2 = ( ( ex - sx ) / realzoom ) + r->x1;
1371    r->y2 = ( ( pda->drawrect.yTop - pda->drawrect.yBottom ) / realzoom ) + r->y1;
1372
1373    rotateRectangle( pda->pagenum, r );
1374}
1375
1376// converts document position to window position
1377void DocumentViewer::docPosToWinPos( long pagenum, LuRectangle *r, PRECTL rcl )
1378{
1379    double yplus = continuous ? pagenumToPos( pagenum ) : 0;
1380    double w = pagesizes[ pagenum ].x;
1381    double h = pagesizes[ pagenum ].y;
1382
1383    double tmp_x1 = r->x1;
1384    double tmp_y1 = r->y1;
1385    double tmp_x2 = r->x2;
1386    double tmp_y2 = r->y2;
1387
1388    if ( rotation == 90 )
1389    {
1390        tmp_x1 = w - r->y2;
1391        tmp_y1 = r->x1;
1392        tmp_x2 = w - r->y1;
1393        tmp_y2 = r->x2;
1394    }
1395    else if ( rotation == 180 )
1396    {
1397        tmp_x1 = w - r->x2;
1398        tmp_y1 = h - r->y2;
1399        tmp_x2 = w - r->x1;
1400        tmp_y2 = h - r->y1;
1401    }
1402    else if ( rotation == 270 )
1403    {
1404        tmp_x1 = r->y1;
1405        tmp_y1 = h - r->x2;
1406        tmp_x2 = r->y2;
1407        tmp_y2 = h - r->x1;
1408    }
1409
1410    rcl->xLeft   = ( tmp_x1 * realzoom ) - sHscrollPos;
1411    rcl->yBottom = cyClient - ( yplus + ( tmp_y2 * realzoom ) ) + ( sVscrollPos * VScrollStep );
1412    rcl->xRight  = ( tmp_x2 * realzoom ) - sHscrollPos;
1413    rcl->yTop    = cyClient - ( yplus + ( tmp_y1 * realzoom ) ) + ( sVscrollPos * VScrollStep );
1414
1415    LONG pw = w * realzoom;
1416    if ( pw < cxClient ) {
1417        LONG xPos = ( cxClient - pw ) / 2;
1418        rcl->xLeft  += xPos;
1419        rcl->xRight += xPos;
1420    }
1421    if ( !continuous )
1422    {
1423        LONG ph = h * realzoom;
1424        if ( ph < cyClient ) {
1425            LONG yPos = ( cyClient - ph ) / 2;
1426            rcl->yBottom -= yPos;
1427            rcl->yTop    -= yPos;
1428        }
1429    }
1430}
1431
1432// creates region from sequence of rectangles
1433HRGN DocumentViewer::rectsToRegion( long pagenum, HPS hps, LuDocument_LuRectSequence *rects )
1434{
1435    HRGN hrgn = GpiCreateRegion( hps, 0, NULL );
1436    if ( rects != NULL )
1437    {
1438        RECTL r = {0};
1439        for ( int i = 0; i < rects->_length; i++ )
1440        {
1441            docPosToWinPos( pagenum, &(rects->_buffer[i]), &r );
1442            HRGN tmprgn = GpiCreateRegion( hps, 1, &r );
1443            GpiCombineRegion( hps, hrgn, hrgn, tmprgn, CRGN_OR );
1444            GpiDestroyRegion( hps, tmprgn );
1445        }
1446    }
1447    return hrgn;
1448}
1449
1450// draws selected area in window, using XOR mix
1451// drawing area may be restricted by r rectangle
1452void DocumentViewer::drawSelection( long pagenum, HPS hps, PRECTL r )
1453{
1454    GpiSetMix( hps, FM_XOR );
1455    GpiSetColor( hps, CLR_YELLOW );
1456    HRGN selectRegion = rectsToRegion( pagenum, hps, selrects[ pagenum ] );
1457    if ( r != NULL )
1458    {
1459        HRGN tmprgn = GpiCreateRegion( hps, 1, r );
1460        GpiCombineRegion( hps, selectRegion, selectRegion, tmprgn, CRGN_AND );
1461        GpiDestroyRegion( hps, tmprgn );
1462    }
1463    GpiPaintRegion( hps, selectRegion );
1464    GpiDestroyRegion( hps, selectRegion );
1465}
1466
1467void DocumentViewer::drawFound( long pagenum, HPS hps, PRECTL r )
1468{
1469    GpiSetMix( hps, FM_XOR );
1470    GpiSetColor( hps, CLR_CYAN );
1471    HRGN selectRegion = rectsToRegion( pagenum, hps, foundrects[ pagenum ] );
1472    if ( r != NULL )
1473    {
1474        HRGN tmprgn = GpiCreateRegion( hps, 1, r );
1475        GpiCombineRegion( hps, selectRegion, selectRegion, tmprgn, CRGN_AND );
1476        GpiDestroyRegion( hps, tmprgn );
1477    }
1478    GpiPaintRegion( hps, selectRegion );
1479    GpiDestroyRegion( hps, selectRegion );
1480}
1481
1482// scrolls window to specified pos (optionally with text selection)
1483void DocumentViewer::scrollToPos( HWND hwnd, HRGN hrgn, LONG xpos, LONG ypos,
1484                                  bool withSelection )
1485{
1486    SHORT xinc = 0;
1487    SHORT yinc = 0;
1488
1489    if ( ( xpos < 0 ) && ( sHscrollPos > 0 ) ) {
1490        xinc = __max( sHscrollPos * -1, xpos );
1491    } else if ( ( xpos > cxClient ) && ( sHscrollPos < sHscrollMax ) ) {
1492        xinc = __min( sHscrollMax - sHscrollPos, xpos - cxClient );
1493    }
1494    if ( ( ypos < 0 ) && ( sVscrollPos < sVscrollMax ) ) {
1495        yinc = __min( ( sVscrollMax - sVscrollPos ) * VScrollStep, ypos * -1 );
1496    }
1497    else if ( ( ypos > cyClient ) && ( sVscrollPos > 0 ) ) {
1498        yinc = __max( ( sVscrollPos * -1 ) * VScrollStep, cyClient - ypos );
1499    }
1500
1501    if ( xinc != 0 ) {
1502        horizScroll( hwnd, MPFROM2SHORT( sHscrollPos + xinc, SB_SLIDERPOSITION ), hrgn );
1503        if ( withSelection ) {
1504            selectionStart.x -= xinc;
1505        }
1506    }
1507
1508    if ( yinc != 0 )
1509    {
1510        SHORT remainder = yinc % VScrollStep;
1511        if ( remainder != 0 ) {
1512            SHORT add = VScrollStep - remainder;
1513            yinc += ( ( yinc > 0 ) ? add : -add );
1514        }
1515
1516        vertScroll( hwnd, MPFROM2SHORT( ( ( sVscrollPos * VScrollStep ) + yinc ) / VScrollStep,
1517                                        SB_SLIDERPOSITION ), hrgn );
1518        if ( withSelection ) {
1519            selectionStart.y += yinc;
1520        }
1521    }
1522}
1523
1524// handles WM_MOUSEMOVE
1525// performs text selection if mouse button pressed
1526// changes mouse ptr to 'hand' if it moves over link area
1527BOOL DocumentViewer::wmMouseMove( HWND hwnd, SHORT xpos, SHORT ypos )
1528{
1529    if ( mousePressed && ( doc != NULL ) )
1530    {
1531        selectionEnd.x = xpos;
1532        selectionEnd.y = ypos;
1533
1534        if ( continuous )
1535        {
1536            scrollToPos( hwnd, NULLHANDLE, xpos, ypos, true );
1537
1538            RECTL selRect = {
1539                selectionStart.x < selectionEnd.x ? selectionStart.x : selectionEnd.x,
1540                selectionStart.y < selectionEnd.y ? selectionStart.y : selectionEnd.y,
1541                selectionStart.x < selectionEnd.x ? selectionEnd.x : selectionStart.x,
1542                selectionStart.y < selectionEnd.y ? selectionEnd.y : selectionStart.y
1543            };
1544
1545            DrawAreas *areas = findDrawAreas( &selRect );
1546
1547            HPS hps = WinGetPS( hwnd );
1548            GpiSetMix( hps, FM_XOR );
1549            GpiSetColor( hps, CLR_YELLOW );
1550
1551            for ( int i = 0; i < areas->size(); i++ )
1552            {
1553                PageDrawArea *pda = &(*areas)[ i ];
1554
1555                winPosToDocPos( pda, &(selection[pda->pagenum]) );
1556
1557                HRGN clearRegion = rectsToRegion( pda->pagenum, hps, selrects[ pda->pagenum ] );
1558                LuDocument::freeRectangles( ev, selrects[ pda->pagenum ] );
1559                selrects[ pda->pagenum ] = doc->getSelectionRectangles( ev, pda->pagenum, &(selection[pda->pagenum]) );
1560                HRGN selectRegion = rectsToRegion( pda->pagenum, hps, selrects[ pda->pagenum ] );
1561                GpiCombineRegion( hps, selectRegion, selectRegion, clearRegion, CRGN_XOR );
1562                GpiPaintRegion( hps, selectRegion );
1563                GpiDestroyRegion( hps, clearRegion );
1564                GpiDestroyRegion( hps, selectRegion );
1565            }
1566
1567            WinReleasePS( hps );
1568            delete areas;
1569        }
1570        else
1571        {
1572            winPosToDocPos( &selectionStart, &selectionEnd, &(selection[currentpage]) );
1573
1574            HPS hps = WinGetPS( hwnd );
1575            HRGN scrolledRegion = NULLHANDLE; //GpiCreateRegion( hps, 0, NULL );
1576
1577            scrollToPos( hwnd, scrolledRegion, xpos, ypos, true );
1578
1579            // 127/191/255
1580            //LONG lclr = ( 127 << 16 ) | ( 191 << 8 ) | 255;
1581            //LONG lclr = ( 128 << 16 ) | ( 64 << 8 );
1582            //LONG ltabl[ 1 ] = { lclr };
1583            //GpiCreateLogColorTable( hps, 0, LCOLF_CONSECRGB, 100, 1, ltabl );
1584
1585            GpiSetMix( hps, FM_XOR );
1586            GpiSetColor( hps, CLR_YELLOW );
1587            //GpiSetColor( hps, 100 );
1588
1589            HRGN clearRegion = rectsToRegion( currentpage, hps, selrects[ currentpage ] );
1590            LuDocument::freeRectangles( ev, selrects[ currentpage ] );
1591            if ( ( selectionStart.x == selectionEnd.x ) &&
1592                 ( selectionStart.y == selectionEnd.y ) ) {
1593                selrects[ currentpage ] = NULL;
1594                memset( &(selection[ currentpage ]), 0, sizeof( LuRectangle ) );
1595            }
1596            else {
1597                selrects[ currentpage ] = doc->getSelectionRectangles( ev, currentpage, &(selection[currentpage]) );
1598            }
1599            HRGN selectRegion = rectsToRegion( currentpage, hps, selrects[ currentpage ] );
1600            GpiCombineRegion( hps, selectRegion, selectRegion, clearRegion, CRGN_XOR );
1601            //GpiCombineRegion( hps, selectRegion, selectRegion, scrolledRegion, CRGN_DIFF );
1602            GpiPaintRegion( hps, selectRegion );
1603            GpiDestroyRegion( hps, clearRegion );
1604            GpiDestroyRegion( hps, selectRegion );
1605            //GpiDestroyRegion( hps, scrolledRegion );
1606
1607            WinReleasePS( hps );
1608        }
1609    }
1610    else if ( links != NULL )
1611    {
1612        long pg = currentpage;
1613        if ( continuous ) {
1614            double tmp;
1615            pg = posToPagenum( ypos, &tmp );
1616        }
1617
1618        if ( ( pg != -1 ) && ( links[ pg ] != NULL ) )
1619        {
1620            for ( int i = 0; i < links[ pg ]->_length; i++ )
1621            {
1622                RECTL r = {0};
1623                docPosToWinPos( pg, &(links[ pg ]->_buffer[i].area), &r );
1624
1625                POINTL ptl = { xpos, ypos };
1626                if ( WinPtInRect( hab, &r, &ptl ) ) {
1627                    WinSetPointer( HWND_DESKTOP, handptr );
1628                    return TRUE;
1629                }
1630            }
1631        }
1632    }
1633
1634    return FALSE;
1635}
1636
1637// handles WM_BUTTON1CLICK
1638BOOL DocumentViewer::wmClick( HWND hwnd, SHORT xpos, SHORT ypos )
1639{
1640    if ( links == NULL ) {
1641        return FALSE;
1642    }
1643
1644    long pg = currentpage;
1645    if ( continuous ) {
1646        double tmp;
1647        pg = posToPagenum( ypos, &tmp );
1648    }
1649
1650    if ( ( pg != -1 ) && ( links[ pg ] != NULL ) )
1651    {
1652        for ( int i = 0; i < links[ pg ]->_length; i++ )
1653        {
1654            RECTL r = {0};
1655            docPosToWinPos( pg, &(links[ pg ]->_buffer[i].area), &r );
1656
1657            POINTL ptl = { xpos, ypos };
1658            if ( WinPtInRect( hab, &r, &ptl ) )
1659            {
1660                if ( links[ pg ]->_buffer[i].link.type == LU_LINK_TYPE_EXTERNAL_URI )
1661                {
1662                    WinMessageBox( HWND_DESKTOP, hMainFrame,
1663                        links[ pg ]->_buffer[i].link.uri, "URI", 1,
1664                        MB_OK | MB_INFORMATION | MB_MOVEABLE );
1665                }
1666                else if ( links[ pg ]->_buffer[i].link.type == LU_LINK_TYPE_TITLE )
1667                {
1668                    char *title = links[ pg ]->_buffer[i].link.title;
1669                    if ( title == NULL ) {
1670                        title = "???";
1671                    }
1672                    WinMessageBox( HWND_DESKTOP, hMainFrame,
1673                        title, "?", 1, MB_OK | MB_INFORMATION | MB_MOVEABLE );
1674                }
1675                else if ( links[ pg ]->_buffer[i].link.type == LU_LINK_TYPE_PAGE )
1676                {
1677                    goToPage( links[ pg ]->_buffer[i].link.page );
1678                }
1679
1680                return TRUE;
1681            }
1682        }
1683    }
1684
1685    return FALSE;
1686}
1687
1688
1689BOOL DocumentViewer::wmChar( HWND hwnd, MPARAM mp1, MPARAM mp2 )
1690{
1691    USHORT fsflags = SHORT1FROMMP( mp1 );
1692    USHORT usch = SHORT1FROMMP( mp2 );
1693    USHORT usvk = SHORT2FROMMP( mp2 );
1694
1695    if ( ( fsflags & KC_VIRTUALKEY ) && !( fsflags & KC_KEYUP ) )
1696    {
1697        switch ( usvk )
1698        {
1699            case VK_UP:
1700                WinSendMsg( hwnd, WM_VSCROLL, MPVOID, MPFROM2SHORT( 0, SB_LINEUP ) );
1701                return TRUE;
1702
1703            case VK_DOWN:
1704                WinSendMsg( hwnd, WM_VSCROLL, MPVOID, MPFROM2SHORT( 0, SB_LINEDOWN ) );
1705                return TRUE;
1706
1707            case VK_PAGEUP:
1708                if ( fsflags & KC_CTRL )
1709                {
1710                    if ( fullscreen ) {
1711                        goToPage( 0 );
1712                    } else {
1713                        vertScroll( hwnd, MPFROM2SHORT( 0, SB_SLIDERPOSITION ), NULLHANDLE );
1714                    }
1715                }
1716                else
1717                {
1718                    if ( fullscreen ) {
1719                        goToPage( currentpage - 1 );
1720                    } else {
1721                        WinSendMsg( hwnd, WM_VSCROLL, MPVOID, MPFROM2SHORT( 0, SB_PAGEUP ) );
1722                    }
1723                }
1724                return TRUE;
1725
1726            case VK_PAGEDOWN:
1727                if ( fsflags & KC_CTRL )
1728                {
1729                    if ( fullscreen ) {
1730                        goToPage( totalpages - 1 );
1731                    } else {
1732                        vertScroll( hwnd, MPFROM2SHORT( sVscrollMax, SB_SLIDERPOSITION ), NULLHANDLE );
1733                    }
1734                }
1735                else
1736                {
1737                    if ( fullscreen ) {
1738                        goToPage( currentpage + 1 );
1739                    } else {
1740                        WinSendMsg( hwnd, WM_VSCROLL, MPVOID, MPFROM2SHORT( 0, SB_PAGEDOWN ) );
1741                    }
1742                }
1743                return TRUE;
1744
1745            case VK_LEFT:
1746                WinSendMsg( hwnd, WM_HSCROLL, MPVOID, MPFROM2SHORT( 0, SB_LINELEFT ) );
1747                return TRUE;
1748
1749            case VK_RIGHT:
1750                WinSendMsg( hwnd, WM_HSCROLL, MPVOID, MPFROM2SHORT( 0, SB_LINERIGHT ) );
1751                return TRUE;
1752
1753            case VK_HOME:
1754                horizScroll( hwnd, MPFROM2SHORT( 0, SB_SLIDERPOSITION ), NULLHANDLE );
1755                return TRUE;
1756
1757            case VK_END:
1758                horizScroll( hwnd, MPFROM2SHORT( sHscrollMax, SB_SLIDERPOSITION ), NULLHANDLE );
1759                return TRUE;
1760        }
1761    }
1762
1763    // Ctrl+L
1764    if ( ( fsflags & KC_CTRL ) && !( fsflags & KC_KEYUP ) && ( toupper( usch ) == 'L' ) )
1765    {
1766        Lucide::toggleFullscreen();
1767        return TRUE;
1768    }
1769
1770    // +
1771    if ( ( fsflags & KC_CHAR ) && !( fsflags & KC_KEYUP ) && ( usch == '+' ) ) {
1772        goToPage( currentpage + 1 );
1773        return TRUE;
1774    }
1775    // -
1776    if ( ( fsflags & KC_CHAR ) && !( fsflags & KC_KEYUP ) && ( usch == '-' ) ) {
1777        goToPage( currentpage - 1 );
1778        return TRUE;
1779    }
1780
1781    return FALSE;
1782}
1783
1784// handles WM_BUTTON1DOWN
1785void DocumentViewer::wmButton1Down( HWND hwnd, SHORT xpos, SHORT ypos )
1786{
1787    if ( continuous && ( doc != NULL ) )
1788    {
1789        // clear selection
1790        RECTL rcl = { 0 };
1791        WinQueryWindowRect( hwnd, &rcl );
1792        DrawAreas *areas = findDrawAreas( &rcl );
1793
1794        HPS hps = WinGetPS( hwnd );
1795        GpiSetMix( hps, FM_XOR );
1796        GpiSetColor( hps, CLR_YELLOW );
1797
1798        for ( int i = 0; i < areas->size(); i++ )
1799        {
1800            PageDrawArea *pda = &(*areas)[ i ];
1801
1802            HRGN clearRegion = rectsToRegion( pda->pagenum, hps, selrects[ pda->pagenum ] );
1803            GpiPaintRegion( hps, clearRegion );
1804            GpiDestroyRegion( hps, clearRegion );
1805        }
1806        WinReleasePS( hps );
1807        delete areas;
1808
1809        freeRects( selrects );
1810
1811        memset( selection, 0, sizeof( LuRectangle ) * totalpages );
1812    }
1813
1814    WinSetCapture( HWND_DESKTOP, hwnd );
1815    mousePressed = true;
1816    selectionStart.x = xpos;
1817    selectionStart.y = ypos;
1818}
1819
1820// handles WM_BUTTON1UP
1821void DocumentViewer::wmButton1Up()
1822{
1823    WinSetCapture( HWND_DESKTOP, NULLHANDLE );
1824    mousePressed = false;
1825
1826    bool haveSelection = false;
1827    for ( long i = 0; i < totalpages; i++ ) {
1828        if ( selrects[ i ] != NULL ) {
1829            haveSelection = true;
1830            break;
1831        }
1832    }
1833
1834    Lucide::enableCopy( haveSelection );
1835}
1836
1837
1838// handles DM_DRAGOVER
1839MRESULT DocumentViewer::wmDragOver( PDRAGINFO dragInfo )
1840{
1841    PDRAGITEM dragItem;
1842    USHORT    usOp, usIndicator;
1843
1844    usOp = 0;
1845    usIndicator = DOR_NODROPOP;
1846
1847    DrgAccessDraginfo( dragInfo );
1848
1849    if ( dragInfo->usOperation == DO_DEFAULT )
1850    {
1851        dragItem = DrgQueryDragitemPtr( dragInfo, 0 );
1852        if ( DrgQueryDragitemCount( dragInfo ) == 1 )
1853        {
1854            if ( DrgVerifyRMF( dragItem, "DRM_OS2FILE", NULL ) &&
1855                 ( dragItem->hstrContainerName != NULLHANDLE ) &&
1856                 ( dragItem->hstrSourceName != NULLHANDLE ) )
1857            {
1858                char fname[ CCHMAXPATHCOMP ] = "";
1859                DrgQueryStrName( dragItem->hstrSourceName, CCHMAXPATHCOMP, fname );
1860                char *ext = strrchr( fname, '.' );
1861                if ( ext != NULL ) {
1862                    if ( pluginMan->createDocumentForExt( ext + 1, true ) != NULL ) {
1863                        usIndicator = DOR_DROP;
1864                        usOp = DO_UNKNOWN;
1865                    }
1866                }
1867            }
1868        }
1869    }
1870
1871    DrgFreeDraginfo( dragInfo );
1872    return MRFROM2SHORT( usIndicator, usOp );
1873}
1874
1875
1876// handles DM_DROP
1877void DocumentViewer::wmDrop( PDRAGINFO dragInfo )
1878{
1879    PDRAGITEM dragItem;
1880
1881    DrgAccessDraginfo( dragInfo );
1882    dragItem = DrgQueryDragitemPtr( dragInfo, 0 );
1883
1884    char fname[ CCHMAXPATHCOMP ] = "";
1885    char fpath[ CCHMAXPATH ] = "";
1886    DrgQueryStrName( dragItem->hstrSourceName, CCHMAXPATHCOMP, fname );
1887    DrgQueryStrName( dragItem->hstrContainerName, CCHMAXPATH, fpath );
1888    DrgFreeDraginfo( dragInfo );
1889
1890    strcat( fpath, fname );
1891    Lucide::loadDocument( fpath );
1892}
1893
1894
1895// static, window procedure
1896MRESULT EXPENTRY DocumentViewer::docViewProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
1897{
1898    DocumentViewer *_this = (DocumentViewer *)WinQueryWindowULong( hwnd, QWL_USER );
1899
1900    switch ( msg )
1901    {
1902        case WM_CREATE:
1903        {
1904            // Save the mp1 into our user data so that subsequent calls have
1905            // access to the parent C++ object
1906            WinSetWindowULong( hwnd, QWL_USER, (ULONG)mp1 );
1907            _this = (DocumentViewer *)mp1;
1908            return (MRESULT)FALSE;
1909        }
1910
1911        case DM_DRAGOVER:
1912            return _this->wmDragOver( (PDRAGINFO)mp1 );
1913
1914        case DM_DROP:
1915            _this->wmDrop( (PDRAGINFO)mp1 );
1916            return (MRESULT)FALSE;
1917
1918        case WM_ERASEBACKGROUND:
1919            return (MRESULT)TRUE;
1920
1921        case WM_SIZE:
1922            _this->wmSize( hwnd, mp2 );
1923            return (MRESULT)FALSE;
1924
1925        case WM_HSCROLL:
1926            _this->horizScroll( hwnd, mp2, NULLHANDLE );
1927            break;
1928
1929        case WM_VSCROLL:
1930            _this->vertScroll( hwnd, mp2, NULLHANDLE );
1931            break;
1932
1933        case WM_PAINT:
1934            if ( _this->enableAsynchDraw ) {
1935                if ( _this->continuous ) {
1936                    _this->wmPaintContAsynch( hwnd );
1937                } else {
1938                    _this->wmPaintAsynch( hwnd );
1939                }
1940            } else {
1941                if ( _this->continuous ) {
1942                    _this->wmPaintCont( hwnd );
1943                } else {
1944                    _this->wmPaint( hwnd );
1945                }
1946            }
1947            return (MRESULT)FALSE;
1948
1949        case WM_BUTTON1DOWN:
1950            _this->wmButton1Down( hwnd, SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ) );
1951            break;
1952
1953        case WM_BUTTON1UP:
1954            _this->wmButton1Up();
1955            break;
1956
1957        case WM_MOUSEMOVE:
1958            if ( _this->wmMouseMove( hwnd, SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ) ) ) {
1959                return (MRESULT)TRUE;
1960            }
1961            break;
1962
1963        case WM_BUTTON1CLICK:
1964            if ( _this->wmClick( hwnd, SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ) ) ) {
1965                return (MRESULT)TRUE;
1966            }
1967            break;
1968
1969        case WM_CHAR:
1970            if ( _this->wmChar( hwnd, mp1, mp2 ) ) {
1971                return (MRESULT)TRUE;
1972            }
1973            break;
1974    }
1975
1976    return WinDefWindowProc( hwnd, msg, mp1, mp2 );
1977}
1978
1979
1980// static, window procedure
1981MRESULT EXPENTRY DocumentViewer::docFrameProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
1982{
1983    DocumentViewer *_this = (DocumentViewer *)WinQueryWindowULong( hwnd, QWL_USER );
1984
1985    switch ( msg )
1986    {
1987        case WM_SYSCOMMAND:
1988            // Send WM_SYSCOMMAND messages to main frame
1989            WinSendMsg( _this->hMainFrame, WM_SYSCOMMAND, mp1, mp2 );
1990            return (MRESULT)FALSE;
1991    }
1992
1993    return _this->oldFrameProc( hwnd, msg, mp1, mp2 );
1994}
1995
Note: See TracBrowser for help on using the repository browser.