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

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

Draw fix

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