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

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

Avoid additional redraw on opening file

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