source: branches/kmk/Lucide/gui/docViewer.cpp @ 348

Last change on this file since 348 was 348, checked in by dmik, 12 years ago

branches/kmk: Ignore field types we don't support.

File size: 82.4 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#include "os2all.h"
36
37#include <string>
38#include <algorithm>
39#include <process.h>
40#include <stdio.h>
41#include <ctype.h>
42
43#include <ludoc.xh>
44#include <luibutton.xh>
45#include <luitext.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#include "cpconv.h"
54
55
56// ASYNCH_RENDER_ENABLE, normally must be defined
57#define ASYNCH_RENDER_ENABLE
58
59typedef LuDocument_LuRectSequence    *PLuRectSequence;
60typedef LuDocument_LuLinkMapSequence *PLuLinkMapSequence;
61
62#define LINE_HEIGHT     16
63#define BORDER_COLOR    0x909090L
64#define PAGEBACK_COLOR  0xFFFFFFL
65#define VERT_SPACE      2
66#define NO_MOUSE_TIMER  1
67#define SB_PAGEDRAG     100
68
69#define DOC_ID_ENTRY    0
70#define DOC_ID_MLE      1
71
72void PageInputFields::fillCache( int i )
73{
74    LuInputField *field = fields->_buffer[ i ];
75    Cache &entry = cache[ i ];
76    entry.rect = field->getRectangle( ev );
77    entry.type = field->getType( ev );
78    entry.supported = false;
79
80    switch( entry.type ) {
81        case LuInputField_Button: {
82            LuInputButton *button = static_cast<LuInputButton *>( field );
83            if ( button->getButtonType( ev ) != LuInputButton_Check )
84                break;
85            // so far, only check boxes are supported
86            entry.supported = true;
87            break;
88        }
89        case LuInputField_Text: {
90            LuInputText *text = static_cast<LuInputText *>( field );
91            if ( text->isReadOnly( ev ) )
92                break;
93            entry.supported = true;
94            break;
95        }
96        case LuInputField_Choice:
97        case LuInputField_Signature:
98        default:
99            // these are currently not supported
100            break;
101    }
102}
103
104// DocumentViewer constructor
105DocumentViewer::DocumentViewer( HWND hWndFrame )
106{
107    hMainFrame  = hWndFrame;
108    sHscrollMax = 0;
109    sVscrollMax = 0;
110    sHscrollPos = 0;
111    sVscrollPos = 0;
112    sVscrollInc = 0;
113    sHscrollInc = 0;
114    cxClient    = 0;
115    cyClient    = 0;
116    hWndDoc     = NULLHANDLE;
117    hWndEntry   = NULLHANDLE;
118    hWndMLE     = NULLHANDLE;
119    textField   = NULL;
120    textFieldPage = 0;
121    doc         = NULL;
122    totalpages  = 0;
123    currentpage = 0;
124    hpsBuffer   = NULLHANDLE;
125    hdcBuffer   = NULLHANDLE;
126    width       = 0;
127    height      = 0;
128    fullwidth   = 0;
129    fullheight  = 0;
130    bpp         = 0;
131    zoom        = 1.0;
132    realzoom    = 1.0;
133    zoomMode    = false;
134    rotation    = 0;
135    pixbuf      = NULL;
136    spos_x      = 0;
137    spos_y      = 0;
138    progressDlg = new ProgressDlg( hWndFrame );
139    drawareas   = NULL;
140    drawareaIndex = 0;
141    closed        = true;
142    layout        = SinglePage;
143    // continuous view
144    pagesizes   = NULL;
145    realVscrollMax = 0;
146    VScrollStep = 1;
147    WinSetRectEmpty( hab, &savedRcl );
148    drawPS = false;
149    // mouse drag using right button
150    docDraggingStarted = false;
151    docDraggingStart.x = 0;  docDraggingStart.y = 0;
152    docDraggingEnd.x = 0;  docDraggingEnd.y = 0;
153    // fullscreen
154    fullscreen     = false;
155    secondsNoMouse = 0;
156    mouseHidden    = false;
157    xLastPos       = 0;
158    yLastPos       = 0;
159    // asynch draw
160    abortAsynch = false;
161    termdraw    = false;
162    enableAsynchDraw = false;
163    DosCreateMutexSem( NULL, &todrawAccess, 0, FALSE );
164    DosCreateEventSem( NULL, &haveDraw, 0, FALSE );
165    // selection
166    mousePressed = false;
167    selectionStart.x = 0;  selectionStart.y = 0;
168    selectionEnd.x = 0;  selectionEnd.y = 0;
169    selection = NULL;
170    selrects = NULL;
171    // links
172    links = NULL;
173    handPtr = WinLoadPointer( HWND_DESKTOP, _hmod, IDP_HAND );
174    handClosedPtr = WinLoadPointer( HWND_DESKTOP, _hmod, IDP_HAND_CLOSED );
175    zoomInPtr = WinLoadPointer( HWND_DESKTOP, _hmod, IDP_ZOOM_IN );
176    zoomOutPtr = WinLoadPointer( HWND_DESKTOP, _hmod, IDP_ZOOM_OUT );
177    textPtr = WinQuerySysPointer( HWND_DESKTOP, SPTR_TEXT, FALSE );
178    // input fields
179    inputFields = NULL;
180    // search
181    foundrects = NULL;
182    searchString = NULL;
183    abortSearch = false;
184
185    // create windows
186    ULONG dfFlags = FCF_VERTSCROLL | FCF_HORZSCROLL | FCF_NOBYTEALIGN;
187    hWndDocFrame = WinCreateStdWindow( hWndFrame, WS_VISIBLE, &dfFlags, NULL, NULL,
188                                       WS_VISIBLE, _hmod, 0, NULL );
189    WinSetWindowULong( hWndDocFrame, QWL_USER, (ULONG)this );
190    oldFrameProc = WinSubclassWindow( hWndDocFrame, docFrameProc );
191
192    hWndDoc = WinCreateWindow( hWndDocFrame, "er.docview", NULL,
193                               WS_VISIBLE | WS_TABSTOP | WS_CLIPCHILDREN,
194                               0, 0, 0, 0, hWndDocFrame,
195                               HWND_TOP, FID_CLIENT, this, NULL );
196
197    hWndEntry = WinCreateWindow( hWndDoc, WC_ENTRYFIELD, NULL,
198                                 ES_AUTOSCROLL | ES_MARGIN,
199                                 0, 0, 0, 0, hWndDoc,
200                                 HWND_TOP, DOC_ID_ENTRY, NULL, NULL );
201
202    hWndMLE = WinCreateWindow( hWndDoc, WC_MLE, NULL,
203                               MLS_BORDER,
204                               0, 0, 0, 0, hWndDoc,
205                               HWND_TOP, DOC_ID_MLE, NULL, NULL );
206
207    char *mleFont = "10.Helvetica Bold";
208    WinSetPresParam( hWndMLE, PP_FONTNAMESIZE, strlen( mleFont ) + 1, mleFont );
209
210    hWndHscroll = WinWindowFromID( hWndDocFrame, FID_HORZSCROLL );
211    hWndVscroll = WinWindowFromID( hWndDocFrame, FID_VERTSCROLL );
212
213    drawThreadId = _beginthread( drawthread, NULL, 262144, this );
214    WinStartTimer( hab, hWndDoc, NO_MOUSE_TIMER, 1000 );
215}
216
217// DocumentViewer destructor
218DocumentViewer::~DocumentViewer()
219{
220    termdraw    = true;
221    abortAsynch = true;
222    DosPostEventSem( haveDraw );
223    DosWaitThread( &drawThreadId, DCWW_WAIT );
224    DosCloseMutexSem( todrawAccess );
225    DosCloseEventSem( haveDraw );
226
227    if ( doc != NULL ) {
228        freeRects( selrects );
229        freeRects( foundrects );
230        freeLinks();
231        freeInputFields();
232    }
233
234    WinDestroyPointer( handPtr );
235    WinDestroyPointer( handClosedPtr );
236    WinDestroyPointer( zoomInPtr );
237    WinDestroyPointer( zoomOutPtr );
238
239    if ( ( hpsBuffer != NULLHANDLE ) && ( hdcBuffer != NULLHANDLE ) ) {
240        DestroyGraphicsBuffer( hpsBuffer, hdcBuffer );
241        hpsBuffer = hdcBuffer = NULLHANDLE;
242    }
243    delete pixbuf;
244    delete progressDlg;
245    delete searchString;
246    delete pagesizes;
247    delete selection;
248}
249
250
251// static, registration of a window class
252void DocumentViewer::registerClass()
253{
254    WinRegisterClass( hab, "er.docview", docViewProc, CS_SIZEREDRAW, sizeof( ULONG ) * 2 );
255}
256
257// sets the document for viewing
258void DocumentViewer::setDocument( LuDocument *_doc )
259{
260    close();
261    doc = _doc;
262
263    if ( doc != NULL )
264    {
265        closed = false;
266
267        totalpages = doc->getPageCount( ev );
268        bpp = doc->getBpp( ev );
269        if ( !doc->isScalable( ev ) ) {
270            zoom = 1;
271        }
272
273        pagesizes = new LuSize[ totalpages ];
274        countPagesizes();
275        adjustSize();
276
277        selrects = new PLuRectSequence[ totalpages ];
278        memset( selrects, 0, sizeof( PLuRectSequence ) * totalpages );
279
280        foundrects = new PLuRectSequence[ totalpages ];
281        memset( foundrects, 0, sizeof( PLuRectSequence ) * totalpages );
282
283        if ( doc->isHaveLinks( ev ) ) {
284            links = new PLuLinkMapSequence[ totalpages ];
285            memset( links, 0, sizeof( PLuLinkMapSequence ) * totalpages );
286        }
287
288        if ( doc->isHaveInputFields( ev ) ) {
289            inputFields = new PageInputFields[ totalpages ];
290            memset( inputFields, 0, sizeof( PageInputFields ) * totalpages );
291        }
292
293        selection = new LuRectangle[ totalpages ];
294        memset( selection, 0, sizeof( LuRectangle ) * totalpages );
295
296        drawPS = doc->isRenderIntoPS( ev );
297        if ( drawPS ) {
298            enableAsynchDraw = false;
299        }
300        else {
301#ifdef ASYNCH_RENDER_ENABLE
302            enableAsynchDraw = doc->isAsynchRenderingSupported( ev );
303#else
304            enableAsynchDraw = false;
305#endif
306        }
307        goToPage( 0 );
308    }
309}
310
311void DocumentViewer::countPagesizes()
312{
313    for ( long i = 0; i < totalpages; i++ )
314    {
315        doc->getPageSize( ev, i, &pagesizes[i].x, &pagesizes[i].y );
316        if ( isRotated() ) {
317            double tmp = pagesizes[i].x;
318            pagesizes[i].x = pagesizes[i].y;
319            pagesizes[i].y = tmp;
320        }
321        fullwidth = std::max( fullwidth, pagesizes[i].x );
322        fullheight += ( pagesizes[i].y + VERT_SPACE );
323    }
324}
325
326// closes the document
327void DocumentViewer::close()
328{
329    if ( closed ) {
330        return;
331    }
332
333    closed = true;
334    abortAsynch = true;
335    DosRequestMutexSem( todrawAccess, SEM_INDEFINITE_WAIT );
336
337    delete drawareas;
338    drawareas = NULL;
339
340    delete pagesizes;
341    pagesizes   = NULL;
342
343    delete selection;
344    selection   = NULL;
345
346    freeRects( foundrects );
347    delete foundrects;
348    foundrects  = NULL;
349
350    freeRects( selrects );
351    delete selrects;
352    selrects    = NULL;
353
354    freeLinks();
355
356    freeInputFields();
357
358    doc             = NULL;
359    totalpages      = 0;
360    currentpage     = 0;
361    fullwidth       = 0;
362    fullheight      = 0;
363
364    DosReleaseMutexSem( todrawAccess );
365
366    WinInvalidateRect( hWndDocFrame, NULL, TRUE );
367}
368
369// sets the page layout
370void DocumentViewer::setPageLayout( PgLayout _layout )
371{
372    layout = _layout;
373    if ( doc != NULL ) {
374        long pg = currentpage;
375        drawPage();
376        if ( isContinuous() ) {
377            goToPage( pg );
378        }
379    }
380}
381
382void DocumentViewer::freeRects( LuDocument_LuRectSequence **rects )
383{
384    if ( rects != NULL )
385    {
386        for ( long i = 0; i < totalpages; i++ ) {
387            if ( rects[ i ] != NULL ) {
388                LuDocument::freeRectangles( ev, rects[ i ] );
389                rects[ i ] = NULL;
390            }
391        }
392    }
393}
394
395void DocumentViewer::freeLinks()
396{
397    if ( links != NULL )
398    {
399        for ( long i = 0; i < totalpages; i++ ) {
400            if ( links[ i ] != NULL ) {
401                LuDocument::freeLinkMapping( ev, links[ i ] );
402                links[ i ] = NULL;
403            }
404        }
405
406        delete links;
407        links = NULL;
408    }
409}
410
411void DocumentViewer::freeInputFields()
412{
413    if ( inputFields != NULL )
414    {
415        for ( long i = 0; i < totalpages; i++ ) {
416            if ( inputFields[ i ].fields != NULL ) {
417                LuDocument::freeInputFields( ev, inputFields[ i ].fields );
418                inputFields[ i ].fields = NULL;
419            }
420            if ( inputFields[ i ].cache != NULL ) {
421                delete[] inputFields[ i ].cache;
422                inputFields[ i ].cache = NULL;
423            }
424        }
425
426        delete inputFields;
427        inputFields = NULL;
428    }
429}
430
431// switch view to specified page
432void DocumentViewer::goToPage( long page )
433{
434    if ( ( page < 0 ) || ( page >= totalpages ) ) {
435        return;
436    }
437
438    if ( isContinuous() && ( doc != NULL ) )
439    {
440        bool needRedraw = ( page == currentpage );
441        double pgpos = pagenumToPos( page ) / VScrollStep;
442        vertScroll( hWndDoc, MPFROM2SHORT( pgpos, SB_SLIDERPOSITION ) );
443        if ( needRedraw ) {
444            drawPage();
445        }
446    }
447    else
448    {
449        currentpage = page;
450        sVscrollPos = 0;
451        if ( doc != NULL ) {
452            drawPage();
453            Lucide::checkNavigationMenus();
454        }
455    }
456}
457
458// Sets the zoom level
459// _zoom - actual zoom level or:
460//         -1 - fit width
461//         -2 - fit page
462void DocumentViewer::setZoom( double _zoom )
463{
464    if ( ( _zoom == 0 ) || ( _zoom < -2 ) || ( ( _zoom > 0 ) && ( _zoom < 0.05 ) ) ) {
465        return;
466    }
467
468    if ( doc != NULL ) {
469        if ( doc->isScalable( ev ) ) {
470            zoom = _zoom;
471            drawPage();
472        }
473    }
474    else {
475        zoom = _zoom;
476    }
477}
478
479// Sets the rotation
480// rotation may be 0, 90, 180 or 270 degrees
481// -90 will be changed to 270, 360 to 0
482void DocumentViewer::setRotation( long _rotation )
483{
484    if ( _rotation == -90 ) {
485        _rotation = 270;
486    }
487    if ( _rotation == 360 ) {
488        _rotation = 0;
489    }
490
491    if ( doc != NULL )
492    {
493        if ( doc->isRotable( ev ) )
494        {
495            rotation = _rotation;
496            countPagesizes();
497            drawPage();
498        }
499    }
500    else {
501        rotation = _rotation;
502    }
503}
504
505void DocumentViewer::setFullscreen( bool _fullscreen )
506{
507    fullscreen = _fullscreen;
508    ULONG ulFrameStyle = WinQueryWindowULong( hWndDocFrame, QWL_STYLE );
509
510    if ( fullscreen )
511    {
512        pglSave = getPageLayout();
513        zoomSave = getZoom();
514        setPageLayout( SinglePage );
515        setZoom( -2 );
516        WinSetParent( hWndHscroll, HWND_OBJECT, FALSE );
517        WinSetParent( hWndVscroll, HWND_OBJECT, FALSE );
518        ulFrameStyle &= ~FS_SIZEBORDER;
519    }
520    else
521    {
522        setPageLayout( pglSave );
523        setZoom( zoomSave );
524        WinSetParent( hWndHscroll, hWndDocFrame, FALSE );
525        WinSetParent( hWndVscroll, hWndDocFrame, FALSE );
526        ulFrameStyle &= ~FS_SIZEBORDER;
527    }
528
529    WinSetWindowULong( hWndDocFrame, QWL_STYLE, ulFrameStyle );
530    WinSendMsg( hWndDocFrame, WM_UPDATEFRAME,
531                MPFROMLONG( FCF_VERTSCROLL | FCF_HORZSCROLL | FCF_SIZEBORDER ), MPVOID );
532
533    if ( mouseHidden ) {
534        WinShowPointer( HWND_DESKTOP, TRUE );
535        mouseHidden = false;
536    }
537}
538
539// copy selected text to clipboard
540void DocumentViewer::copyToClipbrd()
541{
542    if ( isContinuous() )
543    {
544        std::string txt = "";
545        for ( long i = 0; i < totalpages; i++ ) {
546            if ( selrects[ i ] != NULL ) {
547                txt += doc->getText( ev, i, &(selection[ i ]) );
548            }
549        }
550        textToClipbrd( hab, txt.c_str() );
551    }
552    else {
553        char *t = doc->getText( ev, currentpage, &(selection[ currentpage ]) );
554        textToClipbrd( hab, t );
555    }
556}
557
558// select all text (continuous view) or current page (single page view)
559void DocumentViewer::selectAll()
560{
561    if ( isContinuous() )
562    {
563        for ( long i = 0; i < totalpages; i++ )
564        {
565            selection[ i ].x1 = 0;
566            selection[ i ].y1 = 0;
567            selection[ i ].x2 = pagesizes[ i ].x;
568            selection[ i ].y2 = pagesizes[ i ].y;
569            LuDocument::freeRectangles( ev, selrects[ i ] );
570            selrects[ i ] = doc->getSelectionRectangles( ev, i, &(selection[i]) );
571        }
572    }
573    else
574    {
575        selection[ currentpage ].x1 = 0;
576        selection[ currentpage ].y1 = 0;
577        selection[ currentpage ].x2 = pagesizes[ currentpage ].x;
578        selection[ currentpage ].y2 = pagesizes[ currentpage ].y;
579        LuDocument::freeRectangles( ev, selrects[ currentpage ] );
580        selrects[ currentpage ] = doc->getSelectionRectangles( ev, currentpage, &(selection[currentpage]) );
581    }
582
583    Lucide::enableCopy( true );
584    WinInvalidateRect( hWndDoc, NULL, FALSE );
585}
586
587// perform search in document
588void DocumentViewer::searchDocument( const char *_searchString, bool _caseSensitive,
589                                     bool _continueSearch )
590{
591    abortSearch = false;
592    if ( !continueSearch ) {
593        freeRects( foundrects );
594    }
595
596    delete searchString;
597    searchString = newstrdup( _searchString );
598    caseSensitive = _caseSensitive;
599    continueSearch = _continueSearch;
600
601    progressDlg->setBreakFunc( searchabort, this );
602    progressDlg->setText( "" );
603    progressDlg->show( searchthread, this );
604}
605
606// static method, cancels asynch rendering if abortAsynch is true
607void DocumentViewer::searchabort( void *data )
608{
609    ((DocumentViewer *)data)->abortSearch = true;
610}
611
612// static method, thread for asynchronous searching
613void DocumentViewer::searchthread( void *p )
614{
615    DosSetPriority( PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MINIMUM, 0 );
616    DocumentViewer *_this = (DocumentViewer *)p;
617
618    HAB thab = WinInitialize( 0 );
619    HMQ thmq = WinCreateMsgQueue( thab, 0 );
620
621    long i = _this->currentpage;
622    if ( _this->continueSearch && ( _this->currentpage < ( _this->totalpages - 1 ) ) ) {
623        i = _this->currentpage + 1;
624    }
625
626    bool found = false;
627    for ( ; i < _this->totalpages; i++ )
628    {
629        char *fmt = newstrdupL( FIND_SEARCH_PAGE_OF );
630        char *buf = new char[ 255 ];
631        snprintf( buf, 255, fmt, i + 1, _this->totalpages );
632        _this->progressDlg->setText( buf );
633        delete fmt;
634        delete buf;
635
636        _this->foundrects[ i ] = _this->doc->searchText( ev, i,
637                                        (char *)_this->searchString, _this->caseSensitive );
638        if ( _this->foundrects[ i ] != NULL )
639        {
640            found = true;
641            _this->progressDlg->hide();
642            _this->goToPage( i );
643            if ( _this->foundrects[i]->_length > 0 ) {
644                RECTL r;
645                _this->docPosToWinPos( i, &(_this->foundrects[i]->_buffer[0]), &r );
646                _this->scrollToPos( _this->hWndDoc, r.xLeft, r.yBottom, false );
647            }
648            break;
649        }
650
651        if ( _this->abortSearch ) {
652            break;
653        }
654    }
655    _this->progressDlg->hide();
656
657    if ( !found && !_this->abortSearch )
658    {
659        char *notfound = newstrdupL( FIND_NOT_FOUND );
660        WinMessageBox( HWND_DESKTOP, _this->hMainFrame, notfound, NULL,
661                       1, MB_OK | MB_ICONEXCLAMATION | MB_MOVEABLE );
662        delete notfound;
663    }
664
665    WinDestroyMsgQueue( thmq );
666    WinTerminate( thab );
667    _endthread();
668}
669
670// count real zoom level based on specified
671void DocumentViewer::adjustSize()
672{
673    if ( doc != NULL )
674    {
675        width  = pagesizes[ currentpage ].x;
676        height = pagesizes[ currentpage ].y;
677
678        fullwidth = 0;
679        fullheight = 0;
680        for ( long i = 0; i < totalpages; i++ ) {
681            fullwidth = std::max( fullwidth, pagesizes[i].x );
682            fullheight += pagesizes[i].y;
683        }
684
685        if ( zoom == -1 ) { // fit width
686            realzoom = (double)cxClient / ( isContinuous() ? fullwidth : width );
687        }
688        else if ( zoom == -2 ) { // fit page
689            realzoom = std::min( (double)cxClient / width, (double)cyClient / height );
690        }
691        else {
692            realzoom = zoom;
693        }
694        width *= realzoom;
695        height *= realzoom;
696        fullwidth *= realzoom;
697        fullheight *= realzoom;
698        fullheight += ( VERT_SPACE * totalpages );
699    }
700}
701
702// page redraw
703void DocumentViewer::drawPage()
704{
705    if ( !isContinuous() )
706    {
707        LuDocument::freeRectangles( ev, selrects[ currentpage ] );
708        selrects[ currentpage ] = NULL;
709
710        if ( links != NULL ) {
711            if ( links[ currentpage ] == NULL ) {
712                links[ currentpage ] = doc->getLinkMapping( ev, currentpage );
713            }
714        }
715
716        if ( inputFields != NULL ) {
717            if ( inputFields[ currentpage ].fields == NULL ) {
718                inputFields[ currentpage ].fields = doc->getInputFields( ev, currentpage );
719                unsigned long len = inputFields[ currentpage ].fields->_length;
720                inputFields[ currentpage ].cache = new PageInputFields::Cache[ len ];
721                memset( inputFields[ currentpage ].cache, 0, sizeof( PageInputFields::Cache ) * len );
722            }
723        }
724
725        Lucide::enableCopy( false );
726    }
727    WinSendMsg( hWndDoc, WM_SIZE, MPFROM2SHORT( cxClient, cyClient ),
728                MPFROM2SHORT( cxClient, cyClient ) );
729    WinInvalidateRect( hWndDoc, NULL, FALSE );
730}
731
732
733// handles vertical scrolling
734MRESULT DocumentViewer::vertScroll( HWND hwnd, MPARAM mp2 )
735{
736    if ( fullscreen ) {
737        return ( MRFROMLONG( 0 ) );
738    }
739
740    sVscrollInc = 0;
741
742    switch ( SHORT2FROMMP( mp2 ) )
743    {
744        case SB_LINEUP:
745            sVscrollInc = -(std::max( LINE_HEIGHT, (int)VScrollStep ));
746            break ;
747        case SB_LINEDOWN:
748            sVscrollInc = std::max( LINE_HEIGHT, (int)VScrollStep );
749            break;
750        case SB_PAGEUP:
751            sVscrollInc = std::min( -1, -( (int)cyClient - LINE_HEIGHT ) );
752            break;
753        case SB_PAGEDOWN:
754            sVscrollInc = std::max( 1, (int)cyClient - LINE_HEIGHT );
755            break;
756        case SB_SLIDERTRACK:
757        case SB_SLIDERPOSITION:
758            sVscrollInc = ( SHORT1FROMMP( mp2 ) - sVscrollPos ) * VScrollStep;
759            break;
760        case SB_PAGEDRAG:
761            sVscrollInc = (SHORT)SHORT1FROMMP( mp2 );
762            break;
763    }
764
765    if ( SHORT2FROMMP( mp2 ) != SB_PAGEDRAG ) {
766        sVscrollInc = std::max( -sVscrollPos * (LONG)VScrollStep, std::min( sVscrollInc,
767                              ( sVscrollMax - sVscrollPos ) * (LONG)VScrollStep ) );
768        sVscrollInc = ( sVscrollInc / VScrollStep ) * VScrollStep;
769    }
770
771    if ( sVscrollInc != 0 )
772    {
773        sVscrollPos += (SHORT)( sVscrollInc / VScrollStep );
774        WinScrollWindow( hwnd, 0, sVscrollInc, NULL, NULL, NULLHANDLE, NULL,
775                         SW_INVALIDATERGN | SW_SCROLLCHILDREN );
776        WinSendMsg( hWndVscroll, SBM_SETPOS, MPFROMSHORT( sVscrollPos ), MPVOID );
777        WinUpdateWindow( hwnd );
778        sVscrollInc = 0;
779    }
780    return ( MRFROMLONG( 0 ) );
781}
782
783// handles horizontal scrolling
784MRESULT DocumentViewer::horizScroll( HWND hwnd, MPARAM mp2 )
785{
786    if ( fullscreen ) {
787        return ( MRFROMLONG( 0 ) );
788    }
789
790    sHscrollInc = 0;
791
792    switch ( SHORT2FROMMP( mp2 ) )
793    {
794        case SB_LINELEFT:
795            sHscrollInc = -LINE_HEIGHT;
796            break;
797        case SB_LINERIGHT:
798            sHscrollInc = LINE_HEIGHT;
799            break;
800        case SB_PAGELEFT:
801            sHscrollInc = std::min( -1, -( (int)cxClient - LINE_HEIGHT ) );
802            break;
803        case SB_PAGERIGHT:
804            sHscrollInc = std::max( 1, (int)cxClient - LINE_HEIGHT );
805            break;
806        case SB_SLIDERTRACK:
807        case SB_SLIDERPOSITION:
808            sHscrollInc = SHORT1FROMMP( mp2 ) - sHscrollPos;
809            break;
810        case SB_PAGEDRAG:
811            sHscrollInc = (SHORT)SHORT1FROMMP( mp2 );
812            break;
813    }
814
815    sHscrollInc = std::max( -(LONG)sHscrollPos, std::min( sHscrollInc, (LONG)(sHscrollMax - sHscrollPos) ) );
816
817    if ( sHscrollInc != 0 )
818    {
819        sHscrollPos += (SHORT)sHscrollInc;
820        WinScrollWindow( hwnd, -sHscrollInc, 0, NULL, NULL, NULLHANDLE, NULL,
821                         SW_INVALIDATERGN | SW_SCROLLCHILDREN );
822        WinSendMsg( hWndHscroll, SBM_SETPOS, MPFROMSHORT( sHscrollPos ), MPVOID );
823        WinUpdateWindow( hwnd );
824        sHscrollInc = 0;
825    }
826    return ( MRFROMLONG( 0 ) );
827}
828
829
830// handles WM_SIZE message
831// creates appropriate hps buffer, sets scrollbars limits
832void DocumentViewer::wmSize( HWND hwnd, MPARAM mp2 )
833{
834    if ( !WinIsWindowShowing( hwnd ) ) {
835        return;
836    }
837
838    cxClient = SHORT1FROMMP( mp2 );
839    cyClient = SHORT2FROMMP( mp2 );
840
841    double relativeScrollPos = ( sVscrollMax == 0 ) ? 0 :
842                                    (double)sVscrollPos / (double)sVscrollMax;
843
844    adjustSize();
845
846    if ( ( hpsBuffer != NULLHANDLE ) && ( hdcBuffer != NULLHANDLE ) ) {
847        DestroyGraphicsBuffer( hpsBuffer, hdcBuffer );
848        hpsBuffer = hdcBuffer = NULLHANDLE;
849    }
850
851    HPS hps = WinGetPS( hwnd );
852    RECTL rectl = { 0, 0, cxClient, cyClient };
853    CreateGraphicsBuffer( hab, &rectl, hps, &hpsBuffer, &hdcBuffer );
854    WinReleasePS( hps );
855
856    if ( fullscreen )
857    {
858        sHscrollMax = 0;
859        sHscrollPos = 0;
860        realVscrollMax = 0;
861        VScrollStep = 1;
862        sVscrollPos = 0;
863    }
864    else
865    {
866        sHscrollMax = (SHORT)std::max( 0., ( isContinuous() ? fullwidth : width ) - cxClient );
867        sHscrollPos = std::min( sHscrollPos, sHscrollMax );
868
869        WinSendMsg( hWndHscroll, SBM_SETSCROLLBAR,
870                    MPFROMSHORT(sHscrollPos), MPFROM2SHORT(0, sHscrollMax) );
871        WinSendMsg( hWndHscroll, SBM_SETTHUMBSIZE,
872                    MPFROM2SHORT( cxClient, width ), MPVOID );
873        WinEnableWindow( hWndHscroll, (BOOL)( sHscrollMax != 0 ) );
874
875        VScrollStep = 1;
876        if ( isContinuous() )
877        {
878            realVscrollMax = std::max( 0., fullheight - cyClient );
879            ULONG ssize = realVscrollMax / VScrollStep;
880            while ( ssize > 32000 ) {
881                VScrollStep += LINE_HEIGHT;
882                ssize = realVscrollMax / VScrollStep;
883            }
884
885            sVscrollMax = (SHORT)ssize;
886            if ( realVscrollMax > ( sVscrollMax * VScrollStep ) ) {
887                sVscrollMax += 1;
888            }
889        }
890        else {
891            realVscrollMax = sVscrollMax = (SHORT)std::max( 0., height - cyClient );
892        }
893        sVscrollPos = std::min( sVscrollPos, sVscrollMax );
894
895        WinSendMsg( hWndVscroll, SBM_SETSCROLLBAR,
896                    MPFROMSHORT(sVscrollPos), MPFROM2SHORT(0, sVscrollMax) );
897        if ( isContinuous() ) {
898            WinSendMsg( hWndVscroll, SBM_SETTHUMBSIZE,
899                        MPFROM2SHORT( cyClient/VScrollStep, fullheight/VScrollStep ), MPVOID );
900        }
901        else {
902            WinSendMsg( hWndVscroll, SBM_SETTHUMBSIZE,
903                        MPFROM2SHORT( cyClient, height ), MPVOID );
904        }
905        WinEnableWindow( hWndVscroll, (BOOL)( sVscrollMax != 0 ) );
906
907        SHORT realScrollPos = (SHORT)(sVscrollMax * relativeScrollPos);
908        vertScroll( hWndDoc, MPFROM2SHORT( realScrollPos, SB_SLIDERPOSITION ) );
909    }
910
911    positionTextField();
912}
913
914// returns true if subrect inside rect
915inline bool isSubrect( PRECTL rect, PRECTL subrect )
916{
917    return ( ( subrect->xLeft >= rect->xLeft ) &&
918             ( subrect->yBottom >= rect->yBottom ) &&
919             ( subrect->xRight <= rect->xRight ) &&
920             ( subrect->yTop <= rect->yTop ) );
921}
922
923// static method, cancels asynch rendering if abortAsynch is true
924long _System DocumentViewer::asynchCallbackFnAbort( void *data )
925{
926    return (long)(((DocumentViewer *)data)->abortAsynch);
927}
928
929// static method, draws area during asynch rendering
930long _System DocumentViewer::asynchCallbackFnDraw( void *data )
931{
932    DocumentViewer *_this = (DocumentViewer *)data;
933    HPS hps = WinGetPS( _this->hWndDoc );
934    if ( hps != NULLHANDLE )
935    {
936        PRECTL drawRect = &((*_this->drawareas)[_this->drawareaIndex].drawrect);
937        LONG rclx = drawRect->xRight - drawRect->xLeft;
938        LONG rcly = drawRect->yTop - drawRect->yBottom;
939
940        POINTL aptlPoints[4]={ drawRect->xLeft, drawRect->yBottom,
941                               drawRect->xRight-1, drawRect->yTop-1,
942                               0, 0, rclx, rcly };
943
944        LONG lRop = ROP_SRCCOPY;
945        BITMAPINFO2 pbmi;
946        pbmi.cbFix = 16L;
947        pbmi.cx = rclx;
948        pbmi.cy = rcly;
949        pbmi.cPlanes = 1;
950        pbmi.cBitCount = _this->bpp * 8;
951        GpiDrawBits( hps, _this->pixbuf->getDataPtr( ev ), &pbmi, 4L,
952                     aptlPoints, lRop, BBO_IGNORE );
953
954        WinReleasePS( hps );
955    }
956    return 0;
957}
958
959// static method, thread for asynchronous rendering
960void DocumentViewer::drawthread( void *p )
961{
962    DosSetPriority( PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MINIMUM, 0 );
963    DocumentViewer *_this = (DocumentViewer *)p;
964
965    HAB thab = WinInitialize( 0 );
966    HMQ thmq = WinCreateMsgQueue( thab, 0 );
967
968    ULONG postCnt;
969    while ( !_this->termdraw )
970    {
971        DosWaitEventSem( _this->haveDraw, SEM_INDEFINITE_WAIT );
972        DosResetEventSem( _this->haveDraw, &postCnt );
973        _this->abortAsynch = false;
974
975        if ( ( _this->drawareas != NULL ) && ( _this->doc != NULL ) )
976        {
977            DosRequestMutexSem( _this->todrawAccess, SEM_INDEFINITE_WAIT );
978
979            for ( _this->drawareaIndex = 0;
980                  _this->drawareaIndex < _this->drawareas->size();
981                  _this->drawareaIndex++ )
982            {
983                long renderErrorCode = LU_RERR_NO_ERROR;
984                char *renderError = NULL;
985
986                PageDrawArea *pda = &(*_this->drawareas)[ _this->drawareaIndex ];
987
988                LONG rclx = pda->drawrect.xRight - pda->drawrect.xLeft;
989                LONG rcly = pda->drawrect.yTop - pda->drawrect.yBottom;
990                _this->pixbuf = new LuPixbuf( ev, rclx, rcly, _this->bpp );
991                _this->doc->renderPageToPixbufAsynch( ev, pda->pagenum,
992                       pda->startpos.x, pda->startpos.y, rclx, rcly, _this->realzoom,
993                       _this->rotation, _this->pixbuf,
994                       (LuDocument_asynchCallbackFn)asynchCallbackFnDraw,
995                       (LuDocument_asynchCallbackFn)asynchCallbackFnAbort, p,
996                       &renderErrorCode, &renderError );
997                delete _this->pixbuf;
998                _this->pixbuf = NULL;
999
1000                if ( renderErrorCode != LU_RERR_NO_ERROR )
1001                {
1002                    // TODO: display error/warning (renderErrorCode, renderError)
1003
1004                    // ...
1005
1006                    if ( renderError != NULL ) {
1007                        SOMFree( renderError );
1008                    }
1009                }
1010
1011                if ( _this->abortAsynch ) {
1012                    break;  // TODO: remove completed areas from drawareas (?)
1013                }
1014            }
1015
1016            if ( !_this->abortAsynch )
1017            {
1018                HPS hps = WinGetPS( _this->hWndDoc );
1019                if ( hps != NULLHANDLE ) {
1020                    for ( int i = 0; i < _this->drawareas->size(); i++ )
1021                    {
1022                        PageDrawArea *pda = &(*_this->drawareas)[ i ];
1023
1024                        _this->drawSelection( pda->pagenum, hps, &pda->drawrect );
1025                        _this->drawFound( pda->pagenum, hps, &pda->drawrect );
1026                    }
1027                    WinReleasePS( hps );
1028                }
1029                WinSetRectEmpty( thab, &_this->savedRcl );
1030                delete _this->drawareas;
1031                _this->drawareas = NULL;
1032            }
1033
1034            DosReleaseMutexSem( _this->todrawAccess );
1035        }
1036    }
1037    WinDestroyMsgQueue( thmq );
1038    WinTerminate( thab );
1039    _endthread();
1040}
1041
1042// handles WM_PAINT if single-page asynchronous rendering used
1043// posts events to drawthread
1044void DocumentViewer::wmPaintAsynch( HWND hwnd )
1045{
1046    LONG xPos = 0, yPos = 0;
1047    RECTL rclPage = { 0 };
1048    RECTL rcl;
1049    HPS hps = WinBeginPaint( hwnd, 0L, &rcl );
1050    GpiCreateLogColorTable( hpsBuffer, 0, LCOLF_RGB, 0, 0, NULL );
1051    WinFillRect( hpsBuffer, &rcl, BORDER_COLOR );
1052    if ( doc != NULL )
1053    {
1054        if ( width < cxClient ) {
1055            xPos = ( cxClient - width ) / 2;
1056        }
1057        if ( height < cyClient ) {
1058            yPos = ( cyClient - height ) / 2;
1059        }
1060
1061        rclPage.xLeft   = xPos;
1062        rclPage.yBottom = yPos;
1063        rclPage.xRight  = width + xPos;
1064        rclPage.yTop    = height + yPos;
1065        WinFillRect( hpsBuffer, &rclPage, PAGEBACK_COLOR );
1066    }
1067    BlitGraphicsBuffer( hps, hpsBuffer, &rcl );
1068    WinEndPaint( hps );
1069
1070    if ( doc != NULL )
1071    {
1072        RECTL rclDraw = { 0 };
1073        if ( WinIntersectRect( hab, &rclDraw, &rcl, &rclPage ) )
1074        {
1075            if ( ( drawareas != NULL ) && ( drawareas->size() > 0 ) ) {
1076                if ( isSubrect( &((*drawareas)[0].drawrect), &rclDraw ) &&
1077                     ( sVscrollInc == 0 ) && ( sHscrollInc == 0 ) ) {
1078                    return;
1079                }
1080            }
1081
1082            abortAsynch = true;
1083            DosRequestMutexSem( todrawAccess, SEM_INDEFINITE_WAIT );
1084
1085            if ( drawareas == NULL ) {
1086                drawareas = new DrawAreas;
1087            }
1088            if ( drawareas->size() == 0 ) {
1089                PageDrawArea pda;
1090                memset( &pda, 0, sizeof( pda ) );
1091                pda.pagenum = currentpage;
1092                drawareas->push_back( pda );
1093            }
1094
1095            PageDrawArea *ppda = &((*drawareas)[0]);
1096
1097            if ( !WinIsRectEmpty( hab, &ppda->drawrect ) )
1098            {
1099                if ( sVscrollInc > 0 ) {
1100                    ppda->drawrect.yTop    += sVscrollInc;
1101                } else if ( sVscrollInc < 0 ) {
1102                    ppda->drawrect.yBottom += sVscrollInc;
1103                }
1104                if ( sHscrollInc > 0 ) {
1105                    ppda->drawrect.xLeft  -= sHscrollInc;
1106                } else if ( sHscrollInc < 0 ) {
1107                    ppda->drawrect.xRight -= sHscrollInc;
1108                }
1109            }
1110            WinUnionRect( hab, &ppda->drawrect, &ppda->drawrect, &rclDraw );
1111            ppda->startpos.x = sHscrollPos + ppda->drawrect.xLeft - xPos;
1112            ppda->startpos.y = ( yPos > 0 ) ? rclPage.yTop - ppda->drawrect.yTop :
1113                    ( cyClient - ppda->drawrect.yTop ) + sVscrollPos;
1114
1115            DosReleaseMutexSem( todrawAccess );
1116            DosPostEventSem( haveDraw );
1117        }
1118    }
1119}
1120
1121
1122// handles WM_PAINT if continuous asynchronous rendering used
1123void DocumentViewer::wmPaintContAsynch( HWND hwnd )
1124{
1125    RECTL rcl, rclWin, rclDraw = { 0 };
1126    HPS hps = WinBeginPaint( hwnd, 0L, &rcl );
1127    GpiCreateLogColorTable( hpsBuffer, 0, LCOLF_RGB, 0, 0, NULL );
1128    WinFillRect( hpsBuffer, &rcl, BORDER_COLOR );
1129
1130    if ( doc != NULL )
1131    {
1132        long foundpage = -1;
1133        double pageRest;
1134        for ( LONG i = rcl.yTop; i >= rcl.yBottom; i-- )
1135        {
1136            pageRest = 0;
1137            long pg = posToPagenum( i, &pageRest );
1138            if ( ( pg != foundpage ) && ( pg != -1 ) )
1139            {
1140                RECTL rclPage = { 0 };
1141                LuRectangle lr = { 0, 0,
1142                    isRotated() ? (pagesizes[ pg ].y - 1) : (pagesizes[ pg ].x - 1),
1143                    isRotated() ? (pagesizes[ pg ].x - 1) : (pagesizes[ pg ].y - 1) };
1144                docPosToWinPos( pg, &lr, &rclPage );
1145                WinFillRect( hpsBuffer, &rclPage, PAGEBACK_COLOR );
1146                foundpage = pg;
1147                i -= pageRest;
1148            }
1149        }
1150    }
1151
1152    BlitGraphicsBuffer( hps, hpsBuffer, &rcl );
1153    WinEndPaint( hps );
1154
1155    if ( doc != NULL )
1156    {
1157        if ( isSubrect( &savedRcl, &rcl ) && ( sVscrollInc == 0 ) && ( sHscrollInc == 0 ) ) {
1158            return;
1159        }
1160
1161        abortAsynch = true;
1162        DosRequestMutexSem( todrawAccess, SEM_INDEFINITE_WAIT );
1163
1164        WinQueryWindowRect( hwnd, &rclWin );
1165        WinUnionRect( hab, &rcl, &rcl, &savedRcl );
1166
1167        if ( sVscrollInc > 0 ) {
1168            rcl.yTop    += sVscrollInc;
1169        } else if ( sVscrollInc < 0 ) {
1170            rcl.yBottom += sVscrollInc;
1171        }
1172        if ( sHscrollInc > 0 ) {
1173            rcl.xLeft  -= sHscrollInc;
1174        } else if ( sHscrollInc < 0 ) {
1175            rcl.xRight -= sHscrollInc;
1176        }
1177
1178        WinIntersectRect( hab, &rclDraw, &rcl, &rclWin );
1179        WinCopyRect( hab, &rcl, &rclDraw );
1180        WinCopyRect( hab, &savedRcl, &rcl );
1181
1182        delete drawareas;
1183        drawareas = findDrawAreas( &rcl );
1184
1185        for ( int i = 0; i < drawareas->size(); i++ )
1186        {
1187            PageDrawArea *pda = &(*drawareas)[ i ];
1188
1189            // load links for page if not loaded before
1190            if ( links[ pda->pagenum ] == NULL ) {
1191                links[ pda->pagenum ] = doc->getLinkMapping( ev, pda->pagenum );
1192            }
1193
1194            // load input fields for page if not loaded before
1195            if ( inputFields[ pda->pagenum ].fields == NULL ) {
1196                inputFields[ pda->pagenum ].fields = doc->getInputFields( ev, pda->pagenum );
1197                unsigned long len = inputFields[ pda->pagenum ].fields->_length;
1198                inputFields[ pda->pagenum ].cache = new PageInputFields::Cache[ len ];
1199                memset( inputFields[ pda->pagenum ].cache, 0, sizeof( PageInputFields::Cache ) * len );
1200            }
1201        }
1202        DosReleaseMutexSem( todrawAccess );
1203        DosPostEventSem( haveDraw );
1204
1205        determineCurrentPage();
1206    }
1207}
1208
1209
1210// handles WM_PAINT if single-page synchronous rendering used
1211void DocumentViewer::wmPaint( HWND hwnd )
1212{
1213    RECTL rcl;
1214    HPS hps = WinBeginPaint( hwnd, 0L, &rcl );
1215    GpiCreateLogColorTable( hpsBuffer, 0, LCOLF_RGB, 0, 0, NULL );
1216    WinFillRect( hpsBuffer, &rcl, BORDER_COLOR );
1217
1218    if ( doc != NULL )
1219    {
1220        LONG xPos = 0, yPos = 0;
1221        if ( width < cxClient ) {
1222            xPos = ( cxClient - width ) / 2;
1223        }
1224        if ( height < cyClient ) {
1225            yPos = ( cyClient - height ) / 2;
1226        }
1227
1228        RECTL rclPage = { xPos, yPos, width + xPos, height + yPos };
1229        RECTL rclDraw = { 0 };
1230        if ( WinIntersectRect( hab, &rclDraw, &rcl, &rclPage ) )
1231        {
1232            spos_x = sHscrollPos + rclDraw.xLeft - xPos;
1233            spos_y = ( height < cyClient ) ? rclPage.yTop - rclDraw.yTop : (cyClient - rclDraw.yTop) + sVscrollPos;
1234            LONG rclx = rclDraw.xRight - rclDraw.xLeft;
1235            LONG rcly = rclDraw.yTop - rclDraw.yBottom;
1236
1237            long renderErrorCode = LU_RERR_NO_ERROR;
1238            char *renderError = NULL;
1239
1240            if ( drawPS )
1241            {
1242                doc->renderPageToPS( ev, currentpage, spos_x, spos_y, rclx, rcly,
1243                                     realzoom, rotation, hpsBuffer, &rclDraw,
1244                                     &renderErrorCode, &renderError );
1245            }
1246            else
1247            {
1248                pixbuf = new LuPixbuf( ev, rclx, rcly, bpp );
1249                POINTL aptlPoints[4]={ rclDraw.xLeft, rclDraw.yBottom,
1250                                       rclDraw.xRight-1, rclDraw.yTop-1,
1251                                       0, 0, rclx, rcly };
1252
1253                doc->renderPageToPixbuf( ev, currentpage, spos_x, spos_y,
1254                                         rclx, rcly, realzoom, rotation, pixbuf,
1255                                         &renderErrorCode, &renderError );
1256                LONG lRop = ROP_SRCCOPY;
1257                BITMAPINFO2 pbmi;
1258                pbmi.cbFix = 16L;
1259                pbmi.cx = rclx;
1260                pbmi.cy = rcly;
1261                pbmi.cPlanes = 1;
1262                pbmi.cBitCount = bpp * 8;
1263                GpiDrawBits( hpsBuffer, pixbuf->getDataPtr( ev ), &pbmi, 4L,
1264                             aptlPoints, lRop, BBO_IGNORE );
1265                delete pixbuf;
1266                pixbuf = NULL;
1267            }
1268
1269            if ( renderErrorCode != LU_RERR_NO_ERROR )
1270            {
1271                // TODO: display error/warning (renderErrorCode, renderError)
1272
1273                // ...
1274
1275                if ( renderError != NULL ) {
1276                    SOMFree( renderError );
1277                }
1278            }
1279
1280            drawSelection( currentpage, hpsBuffer, &rclDraw );
1281            drawFound( currentpage, hpsBuffer, &rclDraw );
1282        }
1283    }
1284    BlitGraphicsBuffer( hps, hpsBuffer, &rcl );
1285    WinEndPaint( hps );
1286}
1287
1288
1289// founds number of page at specified vertical position
1290// for continuous view only
1291long DocumentViewer::posToPagenum( LONG yPosWin, double *pageRest )
1292{
1293    double yPos = ( cyClient - yPosWin ) + ( sVscrollPos * VScrollStep );
1294    double pgstart = 0;
1295    double pgend = 0;
1296    for ( long i = 0; i < totalpages; i++ )
1297    {
1298        pgend = pgstart + ( pagesizes[ i ].y * realzoom );
1299        if ( ( yPos >= pgstart ) && ( yPos < pgend ) ) {
1300            *pageRest = pgend - yPos;
1301            return i;
1302        }
1303        pgstart = ( pgend + VERT_SPACE );
1304    }
1305    return -1;
1306}
1307
1308// founds vertical position of specified
1309// for continuous view only
1310double DocumentViewer::pagenumToPos( long pagenum )
1311{
1312    double ypos = 0;
1313    for ( long i = 0; i < pagenum; i++ ) {
1314        ypos += pagesizes[ i ].y;
1315    }
1316    return ( ( ypos * realzoom ) + ( pagenum * VERT_SPACE ) );
1317}
1318
1319void DocumentViewer::showTextField( LuInputText *text, long page, PRECTL r )
1320{
1321    // save the previous changes if any
1322    if ( textField != NULL )
1323        hideTextField();
1324
1325    textField = text;
1326    textFieldPage = page;
1327
1328    positionTextField( r );
1329
1330    HWND hwnd;
1331    if ( textField->isMultiLine( ev ) ) {
1332        hwnd = hWndMLE;
1333        WinSendMsg( hwnd, MLM_SETTEXTLIMIT, MPFROMLONG( 65520 ), NULL );
1334    } else {
1335        hwnd = hWndEntry;
1336        // @todo uncomment this once it returns anything useful
1337        // int maxLen = textField->getMaximumLength( ev );
1338        WinSendMsg( hwnd, EM_SETTEXTLIMIT, MPFROMLONG( 65520 ), NULL );
1339    }
1340
1341    const char *contents = textField->getContents( ev );
1342    char *str = uniUtf8ToSys( contents, NULL, NULL );
1343    WinSetWindowText( hwnd, str );
1344    delete[] str;
1345
1346    WinShowWindow( hwnd, TRUE );
1347    WinSetFocus( HWND_DESKTOP, hwnd );
1348}
1349
1350void DocumentViewer::positionTextField( PRECTL r )
1351{
1352    if ( textField == NULL )
1353        return;
1354
1355    RECTL r2;
1356    if ( r == NULL ) {
1357        LuRectangle *rect = textField->getRectangle( ev );
1358        docPosToWinPos( textFieldPage, rect, &r2 );
1359    } else {
1360        r2 = *r;
1361    }
1362
1363    static LONG ulDpi = 0;
1364    if ( ulDpi == 0 ) {
1365        // DPI is constant beteen reboots
1366        HPS hps = WinGetScreenPS( HWND_DESKTOP );
1367        DevQueryCaps( GpiQueryDevice( hps ), CAPS_HORIZONTAL_FONT_RES,
1368                      1, &ulDpi );
1369        WinReleasePS( hps );
1370    }
1371
1372    LONG points = -1;
1373    HWND hwnd;
1374    if ( textField->isMultiLine( ev ) ) {
1375        hwnd = hWndMLE;
1376        // the font size for multi-line text does not change
1377    } else {
1378        hwnd = hWndEntry;
1379        // reduce the rectangle to compensate for the border
1380        r2.xLeft += 3;
1381        r2.yBottom += 3;
1382        r2.xRight -= 3;
1383        r2.yTop -= 3;
1384        // set the font size to match the field height
1385        points = ( r2.yTop - r2.yBottom ) * 72 / 120 - 2;
1386        if ( points < 1 )
1387            points = 1;
1388    }
1389
1390    if (points >= 0 ) {
1391        char font[ 32 ];
1392        sprintf( font, "%d.Helvetica Bold", points );
1393        WinSetPresParam( hWndEntry, PP_FONTNAMESIZE, strlen( font ) + 1, font );
1394    }
1395
1396    WinSetWindowPos( hwnd, HWND_TOP,
1397                     r2.xLeft, r2.yBottom,
1398                     r2.xRight - r2.xLeft,
1399                     r2.yTop - r2.yBottom,
1400                     SWP_MOVE | SWP_SIZE | SWP_ZORDER );
1401}
1402
1403void DocumentViewer::hideTextField( bool apply )
1404{
1405    if ( textField != NULL ) {
1406        HWND hwnd = textField->isMultiLine( ev ) ? hWndMLE : hWndEntry;
1407        if ( apply ) {
1408            LONG len = WinQueryWindowTextLength( hwnd );
1409            char *str = new char [ len + 1 ];
1410            *str = 0;
1411            WinQueryWindowText( hwnd, len + 1, str );
1412            str[ len ] = 0;
1413            char *contents = uniSysToUtf8( str, NULL, NULL );
1414            textField->setContents( ev, contents );
1415            delete[] contents;
1416            delete[] str;
1417        }
1418        textField = NULL;
1419        SWP swp;
1420        WinQueryWindowPos( hwnd, &swp );
1421        WinShowWindow( hwnd, FALSE );
1422        // repaint little bit more (rounding errors)
1423        RECTL r = { swp.x - 1, swp.y - 1, swp.x + swp.cx + 2, swp.y + swp.cy + 2 };
1424        WinInvalidateRect( hWndDoc, &r, TRUE );
1425    }
1426}
1427
1428// founds pages and it's areas to draw
1429// for continuous view only
1430DrawAreas *DocumentViewer::findDrawAreas( PRECTL r )
1431{
1432    DrawAreas *areas = new DrawAreas;
1433    if ( doc != NULL )
1434    {
1435        long foundpage = -1;
1436        double pageRest;
1437        for ( LONG i = r->yTop; i >= r->yBottom; i-- )
1438        {
1439            pageRest = 0;
1440            long pg = posToPagenum( i, &pageRest );
1441            if ( ( pg != foundpage ) && ( pg != -1 ) )
1442            {
1443                double w = pagesizes[ pg ].x * realzoom;
1444
1445                PageDrawArea pda = {0};
1446                pda.pagenum = pg;
1447
1448                LONG xPos = 0;
1449                if ( w < cxClient ) {
1450                    xPos = ( cxClient - w ) / 2;
1451                }
1452                RECTL rclPage = { 0 };
1453                LuRectangle lr = { 0, 0,
1454                    isRotated() ? (pagesizes[ pg ].y - 1) : (pagesizes[ pg ].x - 1),
1455                    isRotated() ? (pagesizes[ pg ].x - 1) : (pagesizes[ pg ].y - 1) };
1456                docPosToWinPos( pg, &lr, &rclPage );
1457                if ( WinIntersectRect( hab, &pda.drawrect, r, &rclPage ) )
1458                {
1459                    pda.startpos.x = sHscrollPos + pda.drawrect.xLeft - xPos;
1460                    pda.startpos.y = ( pagesizes[ pg ].y * realzoom ) - pageRest;
1461                    areas->push_back( pda );
1462                }
1463                foundpage = pg;
1464                i -= pageRest;
1465            }
1466        }
1467    }
1468
1469    return areas;
1470}
1471
1472
1473// found current page in continuous view mode.
1474// it's a page which occupes a most larger area in the window.
1475void DocumentViewer::determineCurrentPage()
1476{
1477    RECTL rcl = { 0 };
1478    WinQueryWindowRect( hWndDoc, &rcl );
1479    DrawAreas *areas = findDrawAreas( &rcl );
1480    long pg = 0;
1481    long sz = 0;
1482    for ( int i = 0; i < areas->size(); i++ )
1483    {
1484        PageDrawArea *pda = &(*areas)[ i ];
1485        long pgsz = pda->drawrect.yTop - pda->drawrect.yBottom;
1486        if ( pgsz > sz ) {
1487            pg = pda->pagenum;
1488            sz = pgsz;
1489        }
1490    }
1491    delete areas;
1492
1493    if ( pg != currentpage ) {
1494        currentpage = pg;
1495        Lucide::checkNavigationMenus();
1496    }
1497}
1498
1499
1500// handles WM_PAINT if continuous synchronous rendering used
1501void DocumentViewer::wmPaintCont( HWND hwnd )
1502{
1503    RECTL rcl;
1504    HPS hps = WinBeginPaint( hwnd, 0L, &rcl );
1505    GpiCreateLogColorTable( hpsBuffer, 0, LCOLF_RGB, 0, 0, NULL );
1506    WinFillRect( hpsBuffer, &rcl, BORDER_COLOR );
1507
1508    if ( doc != NULL )
1509    {
1510        delete drawareas;
1511        drawareas = findDrawAreas( &rcl );
1512
1513        for ( int i = 0; i < drawareas->size(); i++ )
1514        {
1515            PageDrawArea *pda = &(*drawareas)[ i ];
1516
1517            // load links for page if not loaded before
1518            if ( links[ pda->pagenum ] == NULL ) {
1519                links[ pda->pagenum ] = doc->getLinkMapping( ev, pda->pagenum );
1520            }
1521
1522            // load input fields for page if not loaded before
1523            if ( inputFields[ pda->pagenum ].fields == NULL ) {
1524                inputFields[ pda->pagenum ].fields = doc->getInputFields( ev, pda->pagenum );
1525                unsigned long len = inputFields[ pda->pagenum ].fields->_length;
1526                inputFields[ pda->pagenum ].cache = new PageInputFields::Cache[ len ];
1527                memset( inputFields[ pda->pagenum ].cache, 0, sizeof( PageInputFields::Cache ) * len );
1528            }
1529
1530            spos_x = pda->startpos.x;
1531            spos_y = pda->startpos.y;
1532            LONG rclx = pda->drawrect.xRight - pda->drawrect.xLeft;
1533            LONG rcly = pda->drawrect.yTop - pda->drawrect.yBottom;
1534
1535            long renderErrorCode = LU_RERR_NO_ERROR;
1536            char *renderError = NULL;
1537
1538            if ( drawPS )
1539            {
1540                doc->renderPageToPS( ev, pda->pagenum, spos_x, spos_y, rclx, rcly,
1541                                     realzoom, rotation, hpsBuffer, &(pda->drawrect),
1542                                     &renderErrorCode, &renderError );
1543            }
1544            else
1545            {
1546                pixbuf = new LuPixbuf( ev, rclx, rcly, bpp );
1547                POINTL aptlPoints[4]={ pda->drawrect.xLeft, pda->drawrect.yBottom,
1548                                       pda->drawrect.xRight-1, pda->drawrect.yTop-1,
1549                                       0, 0, rclx, rcly };
1550                doc->renderPageToPixbuf( ev, pda->pagenum, spos_x, spos_y,
1551                                         rclx, rcly, realzoom, rotation, pixbuf,
1552                                         &renderErrorCode, &renderError );
1553                LONG lRop = ROP_SRCCOPY;
1554                BITMAPINFO2 pbmi;
1555                pbmi.cbFix = 16L;
1556                pbmi.cx = rclx;
1557                pbmi.cy = rcly;
1558                pbmi.cPlanes = 1;
1559                pbmi.cBitCount = bpp * 8;
1560                GpiDrawBits( hpsBuffer, pixbuf->getDataPtr( ev ), &pbmi, 4L,
1561                             aptlPoints, lRop, BBO_IGNORE );
1562                delete pixbuf;
1563                pixbuf = NULL;
1564            }
1565
1566            if ( renderErrorCode != LU_RERR_NO_ERROR )
1567            {
1568                // TODO: display error/warning (renderErrorCode, renderError)
1569
1570                // ...
1571
1572                if ( renderError != NULL ) {
1573                    SOMFree( renderError );
1574                }
1575            }
1576
1577            drawSelection( pda->pagenum, hpsBuffer, &pda->drawrect );
1578            drawFound( pda->pagenum, hpsBuffer, &pda->drawrect );
1579        }
1580        delete drawareas;
1581        drawareas = NULL;
1582    }
1583    BlitGraphicsBuffer( hps, hpsBuffer, &rcl );
1584    WinEndPaint( hps );
1585
1586    if ( doc != NULL ) {
1587        determineCurrentPage();
1588    }
1589}
1590
1591
1592// Rotates document rectangle
1593void DocumentViewer::rotateRectangle( long pagenum, LuRectangle *r )
1594{
1595    double tmp_x1 = r->x1;
1596    double tmp_y1 = r->y1;
1597    double tmp_x2 = r->x2;
1598    double tmp_y2 = r->y2;
1599
1600    double w = pagesizes[ pagenum ].x;
1601    double h = pagesizes[ pagenum ].y;
1602
1603    if ( rotation == 90 ) {
1604        r->x1 = tmp_y1;
1605        r->y1 = w - tmp_x1;
1606        r->x2 = tmp_y2;
1607        r->y2 = w - tmp_x2;
1608    }
1609    else if ( rotation == 180 )
1610    {
1611        r->x1 = w - tmp_x2;
1612        r->y1 = h - tmp_y2;
1613        r->x2 = w - tmp_x1;
1614        r->y2 = h - tmp_y1;
1615    }
1616    else if ( rotation == 270 )
1617    {
1618        r->x1 = h - tmp_y1;
1619        r->y1 = tmp_x1;
1620        r->x2 = h - tmp_y2;
1621        r->y2 = tmp_x2;
1622    }
1623
1624    if ( r->x1 > r->x2 ) {
1625        double tmp = r->x1;
1626        r->x1 = r->x2;
1627        r->x2 = tmp;
1628    }
1629
1630    if ( r->y1 > r->y2 ) {
1631        double tmp = r->y1;
1632        r->y1 = r->y2;
1633        r->y2 = tmp;
1634    }
1635}
1636
1637// converts window position to document position
1638// single page mode only
1639void DocumentViewer::winPosToDocPos( PPOINTL startpoint, PPOINTL endpoint, LuRectangle *r )
1640{
1641    LONG sx = startpoint->x;
1642    LONG sy = startpoint->y;
1643    LONG ex = endpoint->x;
1644    LONG ey = endpoint->y;
1645    if ( width < cxClient ) {
1646        LONG xPos = ( cxClient - width ) / 2;
1647        sx -= xPos;
1648        ex -= xPos;
1649    }
1650    if ( height < cyClient ) {
1651        LONG yPos = ( cyClient - height ) / 2;
1652        sy += yPos;
1653        ey += yPos;
1654    }
1655
1656    r->x1 = ( sx + sHscrollPos ) / realzoom;
1657    r->y1 = ( ( cyClient - sy ) + sVscrollPos ) / realzoom;
1658    r->x2 = ( ex + sHscrollPos ) / realzoom;
1659    r->y2 = ( ( cyClient - ey ) + sVscrollPos ) / realzoom;
1660
1661    rotateRectangle( currentpage, r );
1662}
1663
1664// converts window position to document position
1665// continuous view mode only
1666void DocumentViewer::winPosToDocPos( PageDrawArea *pda, LuRectangle *r )
1667{
1668    LONG sx = pda->drawrect.xLeft;
1669    LONG ex = pda->drawrect.xRight;
1670    double w = pagesizes[ pda->pagenum ].x * realzoom;
1671    if ( w < cxClient ) {
1672        LONG xPos = ( cxClient - w ) / 2;
1673        sx -= xPos;
1674        ex -= xPos;
1675    }
1676
1677    r->x1 = ( sHscrollPos + sx ) / realzoom;;
1678    r->y1 = pda->startpos.y / realzoom;
1679    r->x2 = ( ( ex - sx ) / realzoom ) + r->x1;
1680    r->y2 = ( ( pda->drawrect.yTop - pda->drawrect.yBottom ) / realzoom ) + r->y1;
1681
1682    rotateRectangle( pda->pagenum, r );
1683}
1684
1685// converts document position to window position
1686void DocumentViewer::docPosToWinPos( long pagenum, LuRectangle *r, PRECTL rcl )
1687{
1688    double yplus = isContinuous() ? pagenumToPos( pagenum ) : 0;
1689    double w = pagesizes[ pagenum ].x;
1690    double h = pagesizes[ pagenum ].y;
1691
1692    double tmp_x1 = r->x1;
1693    double tmp_y1 = r->y1;
1694    double tmp_x2 = r->x2;
1695    double tmp_y2 = r->y2;
1696
1697    if ( rotation == 90 )
1698    {
1699        tmp_x1 = w - r->y2;
1700        tmp_y1 = r->x1;
1701        tmp_x2 = w - r->y1;
1702        tmp_y2 = r->x2;
1703    }
1704    else if ( rotation == 180 )
1705    {
1706        tmp_x1 = w - r->x2;
1707        tmp_y1 = h - r->y2;
1708        tmp_x2 = w - r->x1;
1709        tmp_y2 = h - r->y1;
1710    }
1711    else if ( rotation == 270 )
1712    {
1713        tmp_x1 = r->y1;
1714        tmp_y1 = h - r->x2;
1715        tmp_x2 = r->y2;
1716        tmp_y2 = h - r->x1;
1717    }
1718
1719    rcl->xLeft   = ( tmp_x1 * realzoom ) - sHscrollPos;
1720    rcl->yBottom = cyClient - ( yplus + ( tmp_y2 * realzoom ) ) + ( sVscrollPos * VScrollStep );
1721    rcl->xRight  = ( tmp_x2 * realzoom ) - sHscrollPos;
1722    rcl->yTop    = cyClient - ( yplus + ( tmp_y1 * realzoom ) ) + ( sVscrollPos * VScrollStep );
1723
1724    LONG pw = w * realzoom;
1725    if ( pw < cxClient ) {
1726        LONG xPos = ( cxClient - pw ) / 2;
1727        rcl->xLeft  += xPos;
1728        rcl->xRight += xPos;
1729    }
1730    if ( !isContinuous() )
1731    {
1732        LONG ph = h * realzoom;
1733        if ( ph < cyClient ) {
1734            LONG yPos = ( cyClient - ph ) / 2;
1735            rcl->yBottom -= yPos;
1736            rcl->yTop    -= yPos;
1737        }
1738    }
1739}
1740
1741// creates region from sequence of rectangles
1742HRGN DocumentViewer::rectsToRegion( long pagenum, HPS hps, LuDocument_LuRectSequence *rects )
1743{
1744    HRGN hrgn = GpiCreateRegion( hps, 0, NULL );
1745    if ( rects != NULL )
1746    {
1747        RECTL r = {0};
1748        for ( int i = 0; i < rects->_length; i++ )
1749        {
1750            docPosToWinPos( pagenum, &(rects->_buffer[i]), &r );
1751            HRGN tmprgn = GpiCreateRegion( hps, 1, &r );
1752            GpiCombineRegion( hps, hrgn, hrgn, tmprgn, CRGN_OR );
1753            GpiDestroyRegion( hps, tmprgn );
1754        }
1755    }
1756    return hrgn;
1757}
1758
1759// draws selected area in window, using XOR mix
1760// drawing area may be restricted by r rectangle
1761void DocumentViewer::drawSelection( long pagenum, HPS hps, PRECTL r )
1762{
1763    GpiSetMix( hps, FM_XOR );
1764    GpiSetColor( hps, CLR_YELLOW );
1765    HRGN selectRegion = rectsToRegion( pagenum, hps, selrects[ pagenum ] );
1766    if ( r != NULL )
1767    {
1768        HRGN tmprgn = GpiCreateRegion( hps, 1, r );
1769        GpiCombineRegion( hps, selectRegion, selectRegion, tmprgn, CRGN_AND );
1770        GpiDestroyRegion( hps, tmprgn );
1771    }
1772    GpiPaintRegion( hps, selectRegion );
1773    GpiDestroyRegion( hps, selectRegion );
1774}
1775
1776void DocumentViewer::drawFound( long pagenum, HPS hps, PRECTL r )
1777{
1778    GpiSetMix( hps, FM_XOR );
1779    GpiSetColor( hps, CLR_CYAN );
1780    HRGN selectRegion = rectsToRegion( pagenum, hps, foundrects[ pagenum ] );
1781    if ( r != NULL )
1782    {
1783        HRGN tmprgn = GpiCreateRegion( hps, 1, r );
1784        GpiCombineRegion( hps, selectRegion, selectRegion, tmprgn, CRGN_AND );
1785        GpiDestroyRegion( hps, tmprgn );
1786    }
1787    GpiPaintRegion( hps, selectRegion );
1788    GpiDestroyRegion( hps, selectRegion );
1789}
1790
1791// scrolls window to specified pos (optionally with text selection)
1792void DocumentViewer::scrollToPos( HWND hwnd, LONG xpos, LONG ypos,
1793                                  bool withSelection )
1794{
1795    SHORT xinc = 0;
1796    SHORT yinc = 0;
1797
1798    if ( ( xpos < 0 ) && ( sHscrollPos > 0 ) ) {
1799        xinc = std::max( (SHORT)( -sHscrollPos ), (SHORT)xpos );
1800    } else if ( ( xpos > cxClient ) && ( sHscrollPos < sHscrollMax ) ) {
1801        xinc = std::min( (SHORT)( sHscrollMax - sHscrollPos ), (SHORT)( xpos - cxClient ) );
1802    }
1803    if ( ( ypos < 0 ) && ( sVscrollPos < sVscrollMax ) ) {
1804        yinc = std::min( (SHORT)( ( sVscrollMax - sVscrollPos ) * VScrollStep ), (SHORT)( -ypos ) );
1805    }
1806    else if ( ( ypos > cyClient ) && ( sVscrollPos > 0 ) ) {
1807        yinc = std::max( (SHORT)( ( -sVscrollPos ) * VScrollStep ), (SHORT)( cyClient - ypos ) );
1808    }
1809
1810    if ( xinc != 0 ) {
1811        horizScroll( hwnd, MPFROM2SHORT( sHscrollPos + xinc, SB_SLIDERPOSITION ) );
1812        if ( withSelection ) {
1813            selectionStart.x -= xinc;
1814        }
1815    }
1816
1817    if ( yinc != 0 )
1818    {
1819        SHORT remainder = yinc % VScrollStep;
1820        if ( remainder != 0 ) {
1821            SHORT add = VScrollStep - remainder;
1822            yinc += ( ( yinc > 0 ) ? add : -add );
1823        }
1824
1825        vertScroll( hwnd, MPFROM2SHORT( ( ( sVscrollPos * VScrollStep ) + yinc ) / VScrollStep,
1826                                        SB_SLIDERPOSITION ) );
1827        if ( withSelection ) {
1828            selectionStart.y += yinc;
1829        }
1830    }
1831}
1832
1833// handles WM_MOUSEMOVE
1834// performs text selection if mouse button pressed
1835// changes mouse ptr to 'hand' if it moves over link area
1836BOOL DocumentViewer::wmMouseMove( HWND hwnd, SHORT xpos, SHORT ypos )
1837{
1838    if ( ( xpos != xLastPos ) || ( ypos != yLastPos ) ) // only if mouse really moved
1839    {
1840        secondsNoMouse = 0;
1841        if ( fullscreen && mouseHidden )
1842        {
1843            WinShowPointer( HWND_DESKTOP, TRUE );
1844            mouseHidden = false;
1845        }
1846    }
1847    xLastPos = xpos;
1848    yLastPos = ypos;
1849
1850    if ( zoomMode )
1851    {
1852        HPOINTER ptr = zoomInPtr;
1853        if ( WinGetPhysKeyState( HWND_DESKTOP, 0x1d ) & 0x8000 ) {
1854            ptr = zoomOutPtr;
1855        }
1856        WinSetPointer( HWND_DESKTOP, ptr );
1857        return TRUE;
1858    }
1859    else
1860    {
1861        if ( mousePressed && ( doc != NULL ) )
1862        {
1863            selectionEnd.x = xpos;
1864            selectionEnd.y = ypos;
1865
1866            if ( isContinuous() )
1867            {
1868                scrollToPos( hwnd, xpos, ypos, true );
1869
1870                RECTL selRect = {
1871                    selectionStart.x < selectionEnd.x ? selectionStart.x : selectionEnd.x,
1872                    selectionStart.y < selectionEnd.y ? selectionStart.y : selectionEnd.y,
1873                    selectionStart.x < selectionEnd.x ? selectionEnd.x : selectionStart.x,
1874                    selectionStart.y < selectionEnd.y ? selectionEnd.y : selectionStart.y
1875                };
1876
1877                DrawAreas *areas = findDrawAreas( &selRect );
1878
1879                HPS hps = WinGetPS( hwnd );
1880                GpiSetMix( hps, FM_XOR );
1881                GpiSetColor( hps, CLR_YELLOW );
1882
1883                for ( int i = 0; i < areas->size(); i++ )
1884                {
1885                    PageDrawArea *pda = &(*areas)[ i ];
1886
1887                    winPosToDocPos( pda, &(selection[pda->pagenum]) );
1888
1889                    HRGN clearRegion = rectsToRegion( pda->pagenum, hps, selrects[ pda->pagenum ] );
1890                    LuDocument::freeRectangles( ev, selrects[ pda->pagenum ] );
1891                    selrects[ pda->pagenum ] = doc->getSelectionRectangles( ev, pda->pagenum, &(selection[pda->pagenum]) );
1892                    HRGN selectRegion = rectsToRegion( pda->pagenum, hps, selrects[ pda->pagenum ] );
1893                    GpiCombineRegion( hps, selectRegion, selectRegion, clearRegion, CRGN_XOR );
1894                    GpiPaintRegion( hps, selectRegion );
1895                    GpiDestroyRegion( hps, clearRegion );
1896                    GpiDestroyRegion( hps, selectRegion );
1897                }
1898
1899                WinReleasePS( hps );
1900                delete areas;
1901            }
1902            else
1903            {
1904                winPosToDocPos( &selectionStart, &selectionEnd, &(selection[currentpage]) );
1905
1906                HPS hps = WinGetPS( hwnd );
1907
1908                scrollToPos( hwnd, xpos, ypos, true );
1909
1910                // 127/191/255
1911                //LONG lclr = ( 127 << 16 ) | ( 191 << 8 ) | 255;
1912                //LONG lclr = ( 128 << 16 ) | ( 64 << 8 );
1913                //LONG ltabl[ 1 ] = { lclr };
1914                //GpiCreateLogColorTable( hps, 0, LCOLF_CONSECRGB, 100, 1, ltabl );
1915
1916                GpiSetMix( hps, FM_XOR );
1917                GpiSetColor( hps, CLR_YELLOW );
1918                //GpiSetColor( hps, 100 );
1919
1920                HRGN clearRegion = rectsToRegion( currentpage, hps, selrects[ currentpage ] );
1921                LuDocument::freeRectangles( ev, selrects[ currentpage ] );
1922                if ( ( selectionStart.x == selectionEnd.x ) &&
1923                     ( selectionStart.y == selectionEnd.y ) ) {
1924                    selrects[ currentpage ] = NULL;
1925                    memset( &(selection[ currentpage ]), 0, sizeof( LuRectangle ) );
1926                }
1927                else {
1928                    selrects[ currentpage ] = doc->getSelectionRectangles( ev, currentpage, &(selection[currentpage]) );
1929                }
1930                HRGN selectRegion = rectsToRegion( currentpage, hps, selrects[ currentpage ] );
1931                GpiCombineRegion( hps, selectRegion, selectRegion, clearRegion, CRGN_XOR );
1932                GpiPaintRegion( hps, selectRegion );
1933                GpiDestroyRegion( hps, clearRegion );
1934                GpiDestroyRegion( hps, selectRegion );
1935
1936                WinReleasePS( hps );
1937            }
1938        }
1939        else if ( docDraggingStarted && ( doc != NULL ) )
1940        {
1941            WinSetPointer( HWND_DESKTOP, handClosedPtr );
1942            docDraggingEnd.x = xpos;
1943            docDraggingEnd.y = ypos;
1944
1945            SHORT hMove = docDraggingEnd.x - docDraggingStart.x;
1946            if ( abs( hMove ) > 5 )
1947            {
1948                horizScroll( hwnd, MPFROM2SHORT( hMove, SB_PAGEDRAG ) );
1949                docDraggingStart.x = xpos;
1950            }
1951
1952            SHORT vMove = docDraggingEnd.y - docDraggingStart.y;
1953            if ( abs( vMove ) > 5 )
1954            {
1955                vertScroll( hwnd, MPFROM2SHORT( vMove, SB_PAGEDRAG ) );
1956                docDraggingStart.y = ypos;
1957            }
1958            return TRUE;
1959        }
1960        else if ( links != NULL || inputFields != NULL )
1961        {
1962            long pg = currentpage;
1963            if ( isContinuous() ) {
1964                double tmp;
1965                pg = posToPagenum( ypos, &tmp );
1966            }
1967
1968            if ( links != NULL )
1969            {
1970                if ( ( pg != -1 ) && ( links[ pg ] != NULL ) )
1971                {
1972                    for ( int i = 0; i < links[ pg ]->_length; i++ )
1973                    {
1974                        RECTL r = {0};
1975                        docPosToWinPos( pg, &(links[ pg ]->_buffer[i].area), &r );
1976
1977                        POINTL ptl = { xpos, ypos };
1978                        if ( WinPtInRect( hab, &r, &ptl ) ) {
1979                            WinSetPointer( HWND_DESKTOP, handPtr );
1980                            return TRUE;
1981                        }
1982                    }
1983                }
1984            }
1985
1986            if ( inputFields != NULL )
1987            {
1988                if ( ( pg != -1 ) && ( inputFields[ pg ].fields != NULL ) )
1989                {
1990                    for ( int i = 0; i < inputFields[ pg ].fields->_length; i++ )
1991                    {
1992                        PageInputFields::Cache &entry = inputFields[ pg ].cache[ i ];
1993                        if ( entry.rect == NULL )
1994                            inputFields[ pg ].fillCache( i );
1995
1996                        if ( entry.supported ) {
1997                            RECTL r = {0};
1998                            docPosToWinPos( pg, entry.rect, &r );
1999
2000                            POINTL ptl = { xpos, ypos };
2001                            if ( WinPtInRect( hab, &r, &ptl ) ) {
2002                                WinSetPointer( HWND_DESKTOP,
2003                                               entry.type == LuInputField_Text ?
2004                                               textPtr : handPtr );
2005                                return TRUE;
2006                            }
2007                        }
2008                    }
2009                }
2010            }
2011        }
2012    }
2013    return FALSE;
2014}
2015
2016void DocumentViewer::zoomInOut( bool zoomIn )
2017{
2018    if ( ( doc != NULL ) && doc->isScalable( ev ) )
2019    {
2020        double z = getRealZoom() / 4;
2021        double zval = 0;
2022        if ( zoomIn ) {
2023            zval = getRealZoom() + z;
2024        } else {
2025            zval = getRealZoom() - z;
2026        }
2027        zval = (long)( zval * 20.0 ) / 20.0;   // Round to 0.05 (5%)
2028        if ( zval == getRealZoom() ) {
2029            zval += ( zoomIn ? 0.01 : -0.01 );
2030        }
2031        if ( zval > 0.1 ) {
2032            Lucide::setZoom( zval );
2033        }
2034    }
2035}
2036
2037// handles WM_BUTTON1CLICK
2038BOOL DocumentViewer::wmClick( HWND hwnd, SHORT xpos, SHORT ypos )
2039{
2040    if ( zoomMode )
2041    {
2042        zoomInOut( ( WinGetPhysKeyState( HWND_DESKTOP, 0x1d ) & 0x8000 ) == 0 );
2043        return TRUE;
2044    }
2045    else
2046    {
2047        if ( links == NULL && inputFields == NULL ) {
2048            return FALSE;
2049        }
2050
2051        long pg = currentpage;
2052        if ( isContinuous() ) {
2053            double tmp;
2054            pg = posToPagenum( ypos, &tmp );
2055        }
2056
2057        if ( links != NULL )
2058        {
2059            if ( ( pg != -1 ) && ( links[ pg ] != NULL ) )
2060            {
2061                for ( int i = 0; i < links[ pg ]->_length; i++ )
2062                {
2063                    RECTL r = {0};
2064                    docPosToWinPos( pg, &(links[ pg ]->_buffer[i].area), &r );
2065
2066                    POINTL ptl = { xpos, ypos };
2067                    if ( WinPtInRect( hab, &r, &ptl ) )
2068                    {
2069                        if ( links[ pg ]->_buffer[i].link.type == LU_LINK_TYPE_EXTERNAL_URI )
2070                        {
2071                            if ( !startBrowser( links[ pg ]->_buffer[i].link.uri ) )
2072                            {
2073                                char *m = newstrdupL( MSGS_ERROR_STARTING_BROWSER );
2074                                WinMessageBox( HWND_DESKTOP, hMainFrame, m,
2075                                           NULL, 0, MB_OK | MB_ICONEXCLAMATION | MB_MOVEABLE );
2076                                delete m;
2077                            }
2078                        }
2079                        else if ( links[ pg ]->_buffer[i].link.type == LU_LINK_TYPE_EXTERNAL_FILE )
2080                        {
2081                            char *uri = links[ pg ]->_buffer[i].link.uri;
2082                            if ( uri != NULL ) {
2083                                Lucide::newWindow( uri, true );
2084                            }
2085                        }
2086                        else if ( links[ pg ]->_buffer[i].link.type == LU_LINK_TYPE_TITLE )
2087                        {
2088                            char *title = links[ pg ]->_buffer[i].link.title;
2089                            if ( title == NULL ) {
2090                                title = "???";
2091                            }
2092                            WinMessageBox( HWND_DESKTOP, hMainFrame,
2093                                title, "?", 1, MB_OK | MB_INFORMATION | MB_MOVEABLE );
2094                        }
2095                        else if ( links[ pg ]->_buffer[i].link.type == LU_LINK_TYPE_PAGE )
2096                        {
2097                            goToPage( links[ pg ]->_buffer[i].link.page );
2098                        }
2099
2100                        return TRUE;
2101                    }
2102                }
2103            }
2104        }
2105
2106        if ( inputFields != NULL )
2107        {
2108            if ( ( pg != -1 ) && ( inputFields[ pg ].fields != NULL ) )
2109            {
2110                for ( int i = 0; i < inputFields[ pg ].fields->_length; i++ )
2111                {
2112                    PageInputFields::Cache &entry = inputFields[ pg ].cache[ i ];
2113                    if ( entry.rect == NULL )
2114                        inputFields[ pg ].fillCache( i );
2115
2116                    if ( entry.supported ) {
2117                        RECTL r = {0};
2118                        docPosToWinPos( pg, entry.rect, &r );
2119
2120                        POINTL ptl = { xpos, ypos };
2121                        if ( WinPtInRect( hab, &r, &ptl ) )
2122                        {
2123                            LuInputField *field = inputFields[ pg ].fields->_buffer[ i ];
2124
2125                            switch ( entry.type )
2126                            {
2127                                case LuInputField_Button:
2128                                {
2129                                    LuInputButton *button = static_cast<LuInputButton *>( field );
2130                                    LuInputButton_ButtonType type = button->getButtonType( ev );
2131                                    if ( type == LuInputButton_Check || type == LuInputButton_Radio ) {
2132                                        boolean state = button->getState( ev );
2133                                        button->setState( ev, !state );
2134                                        WinInvalidateRect( hwnd, &r, FALSE );
2135                                    }
2136                                    break;
2137                                }
2138                                case LuInputField_Text:
2139                                {
2140                                    LuInputText *text = static_cast<LuInputText *>( field );
2141                                    showTextField( text, pg, &r );
2142                                    break;
2143                                }
2144                                default:
2145                                    break;
2146                            }
2147
2148                            return TRUE;
2149                        }
2150                    }
2151                }
2152            }
2153        }
2154    }
2155    return FALSE;
2156}
2157
2158// handles WM_BUTTON2CLICK
2159BOOL DocumentViewer::wmRightClick( HWND hwnd, SHORT xpos, SHORT ypos )
2160{
2161    if ( zoomMode )
2162    {
2163        zoomInOut( false );
2164        return TRUE;
2165    }
2166    return FALSE;
2167}
2168
2169BOOL DocumentViewer::wmChar( HWND hwnd, MPARAM mp1, MPARAM mp2 )
2170{
2171    USHORT fsflags = SHORT1FROMMP( mp1 );
2172    USHORT usch = SHORT1FROMMP( mp2 );
2173    USHORT usvk = SHORT2FROMMP( mp2 );
2174
2175    if ( ( fsflags & KC_VIRTUALKEY ) && !( fsflags & KC_KEYUP ) )
2176    {
2177        switch ( usvk )
2178        {
2179            case VK_UP:
2180                WinSendMsg( hwnd, WM_VSCROLL, MPVOID, MPFROM2SHORT( 0, SB_LINEUP ) );
2181                return TRUE;
2182
2183            case VK_DOWN:
2184                WinSendMsg( hwnd, WM_VSCROLL, MPVOID, MPFROM2SHORT( 0, SB_LINEDOWN ) );
2185                return TRUE;
2186
2187            case VK_PAGEUP:
2188                if ( fsflags & KC_CTRL )
2189                {
2190                    if ( fullscreen ) {
2191                        goToPage( 0 );
2192                    } else {
2193                        vertScroll( hwnd, MPFROM2SHORT( 0, SB_SLIDERPOSITION ) );
2194                    }
2195                }
2196                else
2197                {
2198                    bool dojump = ( !isContinuous() && ( sVscrollPos == 0 )
2199                                        && ( currentpage > 0 ) );
2200
2201                    if ( fullscreen || dojump ) {
2202                        goToPage( currentpage - 1 );
2203                        if ( dojump ) {
2204                            vertScroll( hwnd, MPFROM2SHORT( sVscrollMax, SB_SLIDERPOSITION ) );
2205                        }
2206                    } else {
2207                        WinSendMsg( hwnd, WM_VSCROLL, MPVOID, MPFROM2SHORT( 0, SB_PAGEUP ) );
2208                    }
2209                }
2210                return TRUE;
2211
2212            case VK_PAGEDOWN:
2213                if ( fsflags & KC_CTRL )
2214                {
2215                    if ( fullscreen ) {
2216                        goToPage( totalpages - 1 );
2217                    } else {
2218                        vertScroll( hwnd, MPFROM2SHORT( sVscrollMax, SB_SLIDERPOSITION ) );
2219                    }
2220                }
2221                else
2222                {
2223                    bool dojump = ( !isContinuous() && ( sVscrollPos == sVscrollMax ) );
2224
2225                    if ( fullscreen || dojump ) {
2226                        goToPage( currentpage + 1 );
2227                    } else {
2228                        WinSendMsg( hwnd, WM_VSCROLL, MPVOID, MPFROM2SHORT( 0, SB_PAGEDOWN ) );
2229                    }
2230                }
2231                return TRUE;
2232
2233            case VK_LEFT:
2234                WinSendMsg( hwnd, WM_HSCROLL, MPVOID, MPFROM2SHORT( 0, SB_LINELEFT ) );
2235                return TRUE;
2236
2237            case VK_RIGHT:
2238                WinSendMsg( hwnd, WM_HSCROLL, MPVOID, MPFROM2SHORT( 0, SB_LINERIGHT ) );
2239                return TRUE;
2240
2241            case VK_HOME:
2242                horizScroll( hwnd, MPFROM2SHORT( 0, SB_SLIDERPOSITION ) );
2243                return TRUE;
2244
2245            case VK_END:
2246                horizScroll( hwnd, MPFROM2SHORT( sHscrollMax, SB_SLIDERPOSITION ) );
2247                return TRUE;
2248
2249            case VK_ESC:
2250                if ( textField != NULL ) {
2251                    hideTextField( false );
2252                    return TRUE;
2253                }
2254                break;
2255
2256            case VK_ENTER:
2257            case VK_NEWLINE:
2258                if ( textField != NULL ) {
2259                    hideTextField();
2260                    return TRUE;
2261                }
2262                break;
2263        }
2264    }
2265
2266    //
2267    // In fullscreen mode accelerators not work, so we process these keys here.
2268    //
2269
2270    // Ctrl+L
2271    if ( ( fsflags & KC_CTRL ) && !( fsflags & KC_KEYUP ) && ( toupper( usch ) == 'L' ) )
2272    {
2273        Lucide::toggleFullscreen();
2274        return TRUE;
2275    }
2276
2277    // Esc && fullscreen
2278    if ( fullscreen && !( fsflags & KC_KEYUP ) && ( fsflags & KC_VIRTUALKEY ) && ( usvk == VK_ESC ) ) {
2279        Lucide::toggleFullscreen();
2280        return TRUE;
2281    }
2282
2283    // +
2284    if ( ( fsflags & KC_CHAR ) && !( fsflags & KC_KEYUP ) && ( usch == '+' ) ) {
2285        goToPage( currentpage + 1 );
2286        return TRUE;
2287    }
2288    // -
2289    if ( ( fsflags & KC_CHAR ) && !( fsflags & KC_KEYUP ) && ( usch == '-' ) ) {
2290        goToPage( currentpage - 1 );
2291        return TRUE;
2292    }
2293
2294    // Ctrl && zoomMode
2295    if ( ( fsflags & KC_VIRTUALKEY ) && ( usvk == VK_CTRL ) && zoomMode ) {
2296        wmMouseMove( hwnd, 0, 0 ); // to switch mouse pointer if in zoomMode
2297    }
2298
2299    return FALSE;
2300}
2301
2302// handles WM_BUTTON1DOWN
2303void DocumentViewer::wmButton1Down( HWND hwnd, SHORT xpos, SHORT ypos )
2304{
2305    if ( isContinuous() && ( doc != NULL ) )
2306    {
2307        // clear selection
2308        RECTL rcl = { 0 };
2309        WinQueryWindowRect( hwnd, &rcl );
2310        DrawAreas *areas = findDrawAreas( &rcl );
2311
2312        HPS hps = WinGetPS( hwnd );
2313        GpiSetMix( hps, FM_XOR );
2314        GpiSetColor( hps, CLR_YELLOW );
2315
2316        for ( int i = 0; i < areas->size(); i++ )
2317        {
2318            PageDrawArea *pda = &(*areas)[ i ];
2319
2320            HRGN clearRegion = rectsToRegion( pda->pagenum, hps, selrects[ pda->pagenum ] );
2321            GpiPaintRegion( hps, clearRegion );
2322            GpiDestroyRegion( hps, clearRegion );
2323        }
2324        WinReleasePS( hps );
2325        delete areas;
2326
2327        freeRects( selrects );
2328
2329        memset( selection, 0, sizeof( LuRectangle ) * totalpages );
2330    }
2331
2332    WinSetCapture( HWND_DESKTOP, hwnd );
2333    mousePressed = true;
2334    selectionStart.x = xpos;
2335    selectionStart.y = ypos;
2336}
2337
2338
2339// handles WM_BUTTON1UP
2340void DocumentViewer::wmButton1Up()
2341{
2342    WinSetCapture( HWND_DESKTOP, NULLHANDLE );
2343    mousePressed = false;
2344
2345    bool haveSelection = false;
2346    for ( long i = 0; i < totalpages; i++ ) {
2347        if ( selrects[ i ] != NULL ) {
2348            haveSelection = true;
2349            break;
2350        }
2351    }
2352
2353    Lucide::enableCopy( haveSelection );
2354}
2355
2356
2357// handles WM_BUTTON2DOWN
2358void DocumentViewer::wmButton2Down( HWND hwnd, SHORT xpos, SHORT ypos )
2359{
2360    if ( doc != NULL )
2361    {
2362        WinSetCapture( HWND_DESKTOP, hwnd );
2363        docDraggingStarted = true;
2364        docDraggingStart.x = xpos;
2365        docDraggingStart.y = ypos;
2366    }
2367}
2368
2369
2370// handles WM_BUTTON2UP
2371void DocumentViewer::wmButton2Up()
2372{
2373    if ( docDraggingStarted )
2374    {
2375        WinSetCapture( HWND_DESKTOP, NULLHANDLE );
2376        docDraggingStarted = false;
2377    }
2378}
2379
2380
2381// handles DM_DRAGOVER
2382MRESULT DocumentViewer::wmDragOver( PDRAGINFO dragInfo )
2383{
2384    PDRAGITEM dragItem;
2385    USHORT    usOp, usIndicator;
2386
2387    usOp = 0;
2388    usIndicator = DOR_NODROPOP;
2389
2390    DrgAccessDraginfo( dragInfo );
2391
2392    if ( dragInfo->usOperation == DO_DEFAULT )
2393    {
2394        dragItem = DrgQueryDragitemPtr( dragInfo, 0 );
2395        if ( DrgQueryDragitemCount( dragInfo ) == 1 )
2396        {
2397            if ( DrgVerifyRMF( dragItem, "DRM_OS2FILE", NULL ) &&
2398                 ( dragItem->hstrContainerName != NULLHANDLE ) &&
2399                 ( dragItem->hstrSourceName != NULLHANDLE ) )
2400            {
2401                char fname[ CCHMAXPATHCOMP ] = "";
2402                DrgQueryStrName( dragItem->hstrSourceName, CCHMAXPATHCOMP, fname );
2403                char *ext = strrchr( fname, '.' );
2404                if ( ext != NULL ) {
2405                    if ( pluginMan->createDocumentForExt( ext + 1, true ) != NULL ) {
2406                        usIndicator = DOR_DROP;
2407                        usOp = DO_UNKNOWN;
2408                    }
2409                }
2410            }
2411        }
2412    }
2413
2414    DrgFreeDraginfo( dragInfo );
2415    return MRFROM2SHORT( usIndicator, usOp );
2416}
2417
2418
2419// handles DM_DROP
2420void DocumentViewer::wmDrop( PDRAGINFO dragInfo )
2421{
2422    PDRAGITEM dragItem;
2423
2424    DrgAccessDraginfo( dragInfo );
2425    dragItem = DrgQueryDragitemPtr( dragInfo, 0 );
2426
2427    char fname[ CCHMAXPATHCOMP ] = "";
2428    char fpath[ CCHMAXPATH ] = "";
2429    DrgQueryStrName( dragItem->hstrSourceName, CCHMAXPATHCOMP, fname );
2430    DrgQueryStrName( dragItem->hstrContainerName, CCHMAXPATH, fpath );
2431    DrgFreeDraginfo( dragInfo );
2432
2433    strcat( fpath, fname );
2434    Lucide::loadDocument( fpath );
2435}
2436
2437// handles WM_TIMER
2438void DocumentViewer::wmTimer( USHORT idTimer )
2439{
2440    if ( idTimer == NO_MOUSE_TIMER )
2441    {
2442        secondsNoMouse++;
2443
2444        if ( fullscreen && !mouseHidden && ( secondsNoMouse > 3 ) )
2445        {
2446            WinShowPointer( HWND_DESKTOP, FALSE );
2447            mouseHidden = true;
2448        }
2449    }
2450}
2451
2452// handles WM_CONTROL
2453void DocumentViewer::wmControl( USHORT idControl, USHORT notifyCode, HWND hwndControl )
2454{
2455    if ( ( idControl == DOC_ID_ENTRY && notifyCode == EN_KILLFOCUS &&
2456           textField != NULL && !textField->isMultiLine( ev ) ) ||
2457         ( idControl == DOC_ID_MLE && notifyCode == MLN_KILLFOCUS &&
2458           textField != NULL && textField->isMultiLine( ev ) ) )
2459        hideTextField();
2460}
2461
2462// static, window procedure
2463MRESULT EXPENTRY DocumentViewer::docViewProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
2464{
2465    DocumentViewer *_this = (DocumentViewer *)WinQueryWindowULong( hwnd, QWL_USER );
2466
2467    switch ( msg )
2468    {
2469        case WM_CREATE:
2470        {
2471            // Save the mp1 into our user data so that subsequent calls have
2472            // access to the parent C++ object
2473            WinSetWindowULong( hwnd, QWL_USER, (ULONG)mp1 );
2474            _this = (DocumentViewer *)mp1;
2475            return (MRESULT)FALSE;
2476        }
2477
2478        case DM_DRAGOVER:
2479            return _this->wmDragOver( (PDRAGINFO)mp1 );
2480
2481        case DM_DROP:
2482            _this->wmDrop( (PDRAGINFO)mp1 );
2483            return (MRESULT)FALSE;
2484
2485        case WM_ERASEBACKGROUND:
2486            return (MRESULT)TRUE;
2487
2488        case WM_SIZE:
2489            _this->wmSize( hwnd, mp2 );
2490            return (MRESULT)FALSE;
2491
2492        case WM_HSCROLL:
2493            _this->horizScroll( hwnd, mp2 );
2494            break;
2495
2496        case WM_VSCROLL:
2497            _this->vertScroll( hwnd, mp2 );
2498            break;
2499
2500        case WM_PAINT:
2501            if ( _this->enableAsynchDraw ) {
2502                if ( _this->isContinuous() ) {
2503                    _this->wmPaintContAsynch( hwnd );
2504                } else {
2505                    _this->wmPaintAsynch( hwnd );
2506                }
2507            } else {
2508                if ( _this->isContinuous() ) {
2509                    _this->wmPaintCont( hwnd );
2510                } else {
2511                    _this->wmPaint( hwnd );
2512                }
2513            }
2514            return (MRESULT)FALSE;
2515
2516        case WM_BUTTON1DOWN:
2517            _this->wmButton1Down( hwnd, SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ) );
2518            break;
2519
2520        case WM_BUTTON1UP:
2521            _this->wmButton1Up();
2522            break;
2523
2524        case WM_BUTTON2DOWN:
2525            _this->wmButton2Down( hwnd, SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ) );
2526            break;
2527
2528        case WM_BUTTON2UP:
2529            _this->wmButton2Up();
2530            break;
2531
2532        case WM_MOUSEMOVE:
2533            if ( _this->wmMouseMove( hwnd, SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ) ) ) {
2534                return (MRESULT)TRUE;
2535            }
2536            break;
2537
2538        case WM_BUTTON1CLICK:
2539            if ( _this->wmClick( hwnd, SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ) ) ) {
2540                return (MRESULT)TRUE;
2541            }
2542            break;
2543
2544        case WM_BUTTON2CLICK:
2545            if ( _this->wmRightClick( hwnd, SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ) ) ) {
2546                return (MRESULT)TRUE;
2547            }
2548            break;
2549
2550        case WM_CHAR:
2551            if ( _this->wmChar( hwnd, mp1, mp2 ) ) {
2552                return (MRESULT)TRUE;
2553            }
2554            break;
2555
2556        case WM_FOCUSCHANGE:
2557            if ( SHORT1FROMMP( mp2 ) ) {
2558                Lucide::activeWindow = AwView;
2559            }
2560            break;
2561
2562        case WM_TIMER:
2563            _this->wmTimer( SHORT1FROMMP( mp1 ) );
2564            break;
2565
2566        case WM_CONTROL:
2567            _this->wmControl( SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ), HWNDFROMMP( mp2 ) );
2568            break;
2569    }
2570
2571    return WinDefWindowProc( hwnd, msg, mp1, mp2 );
2572}
2573
2574
2575// static, window procedure
2576MRESULT EXPENTRY DocumentViewer::docFrameProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
2577{
2578    DocumentViewer *_this = (DocumentViewer *)WinQueryWindowULong( hwnd, QWL_USER );
2579
2580    switch ( msg )
2581    {
2582        case WM_SYSCOMMAND:
2583            // Send WM_SYSCOMMAND messages to main frame
2584            WinSendMsg( _this->hMainFrame, WM_SYSCOMMAND, mp1, mp2 );
2585            return (MRESULT)FALSE;
2586    }
2587
2588    return _this->oldFrameProc( hwnd, msg, mp1, mp2 );
2589}
2590
Note: See TracBrowser for help on using the repository browser.