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

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

update makefiles, remove absolute paths, update djvulibre to version 3.5.17

File size: 39.4 KB
Line 
1#define INCL_DOS
2#define INCL_WIN
3#define INCL_GPI
4#include <os2.h>
5
6#include <process.h>
7#include <stdio.h>
8
9#include <ludoc.xh>
10#include "lucide.h"
11#include "docViewer.h"
12#include "progressDlg.h"
13#include "luutils.h"
14#include "lucide_res.h"
15#include "messages.h"
16
17
18// OpenWatcom headers doesn't have GpiDrawBits() declaration
19extern "C" {
20    LONG APIENTRY GpiDrawBits(HPS hps, PVOID pBits, PBITMAPINFO2 pbmiInfoTable,
21                              LONG lCount, PPOINTL aptlPoints, LONG lRop, ULONG flOptions);
22}
23
24typedef LuDocument_LuRectSequence    *PLuRectSequence;
25typedef LuDocument_LuLinkMapSequence *PLuLinkMapSequence;
26
27#define LINE_HEIGHT     16
28
29// DocumentViewer constructor
30DocumentViewer::DocumentViewer( HAB _hab, HWND hWndFrame )
31{
32    hab         = _hab;
33    hMainFrame  = hWndFrame;
34    sHscrollMax = 0;
35    sVscrollMax = 0;
36    sHscrollPos = 0;
37    sVscrollPos = 0;
38    sVscrollInc = 0;
39    sHscrollInc = 0;
40    cxClient    = 0;
41    cyClient    = 0;
42    hWndDoc     = NULLHANDLE;
43    doc         = NULL;
44    totalpages  = 0;
45    currentpage = 0;
46    hpsBuffer   = NULLHANDLE;
47    hdcBuffer   = NULLHANDLE;
48    width       = 0;
49    height      = 0;
50    fullwidth   = 0;
51    fullheight  = 0;
52    zoom        = 1.0;
53    realzoom    = 1.0;
54    ev          = somGetGlobalEnvironment();
55    pixbuf      = NULL;
56    spos_x      = 0;
57    spos_y      = 0;
58    progressDlg = new ProgressDlg( hWndFrame );
59    drawareas   = NULL;
60    drawareaIndex = 0;
61    // continuous view
62    continuous  = false;
63    pagesizes   = NULL;
64    realVscrollMax = 0;
65    VScrollStep = 1;
66    // asynch draw
67    abortAsynch = false;
68    termdraw    = false;
69    enableAsynchDraw = false;
70    DosCreateMutexSem( NULL, &todrawAccess, 0, FALSE );
71    DosCreateEventSem( NULL, &haveDraw, 0, FALSE );
72    // selection
73    mousePressed = false;
74    selectionStart.x = 0;  selectionStart.y = 0;
75    selectionEnd.x = 0;  selectionEnd.y = 0;
76    selection.x1 = 0;  selection.y1 = 0;  selection.x2 = 0;  selection.y2 = 0;
77    selrects = NULL;
78    // links
79    links = NULL;
80    handptr = WinLoadPointer( HWND_DESKTOP, NULLHANDLE, IDP_HAND );
81    // search
82    foundrects = NULL;
83    searchString = NULL;
84    abortSearch = false;
85
86    // create windows
87    ULONG dfFlags = FCF_VERTSCROLL | FCF_HORZSCROLL | FCF_NOBYTEALIGN;
88    hWndDocFrame = WinCreateStdWindow( hWndFrame, WS_VISIBLE, &dfFlags, NULL, NULL,
89                                       WS_VISIBLE, NULLHANDLE, 0, NULL );
90
91    hWndDoc = WinCreateWindow( hWndDocFrame, "er.docview", NULL,
92                               WS_VISIBLE | WS_TABSTOP, 0, 0, 0, 0, hWndDocFrame,
93                               HWND_TOP, FID_CLIENT, this, NULL );
94
95    hWndHscroll = WinWindowFromID( hWndDocFrame, FID_HORZSCROLL );
96    hWndVscroll = WinWindowFromID( hWndDocFrame, FID_VERTSCROLL );
97
98    drawThreadId = _beginthread( drawthread, NULL, 65536, this );
99}
100
101// DocumentViewer destructor
102DocumentViewer::~DocumentViewer()
103{
104    termdraw    = true;
105    abortAsynch = true;
106    DosPostEventSem( haveDraw );
107    DosWaitThread( &drawThreadId, DCWW_WAIT );
108    DosCloseMutexSem( todrawAccess );
109    DosCloseEventSem( haveDraw );
110
111    if ( doc != NULL ) {
112        LuDocument::freeRectangles( ev, selrects );
113        freeLinks();
114        freeFoundrects();
115    }
116
117    WinDestroyPointer( handptr );
118
119    if ( ( hpsBuffer != NULLHANDLE ) && ( hdcBuffer != NULLHANDLE ) ) {
120        DestroyGraphicsBuffer( hpsBuffer, hdcBuffer );
121        hpsBuffer = hdcBuffer = NULLHANDLE;
122    }
123    delete pixbuf;
124    delete progressDlg;
125    delete searchString;
126    delete pagesizes;
127}
128
129
130// static, registration of a window class
131void DocumentViewer::registerClass( HAB hab )
132{
133    WinRegisterClass( hab, "er.docview", docViewProc, CS_SIZEREDRAW, sizeof( ULONG ) * 2 );
134}
135
136// sets the document for viewing
137void DocumentViewer::setDocument( LuDocument *_doc )
138{
139    doc         = _doc;
140    zoom        = 1;
141    currentpage = 0;
142    fullwidth   = 0;
143    fullheight  = 0;
144    delete pagesizes;
145    pagesizes   = NULL;
146    freeFoundrects();
147    delete foundrects;
148    foundrects  = NULL;
149    freeLinks();
150
151    if ( doc != NULL )
152    {
153        totalpages = doc->getPageCount( ev );
154
155        pagesizes = new LuSize[ totalpages ];
156        for ( long i = 0; i < totalpages; i++ ) {
157            doc->getPageSize( ev, i, &pagesizes[i].x, &pagesizes[i].y );
158            fullwidth = __max( fullwidth, pagesizes[i].x );
159            fullheight += pagesizes[i].y;
160        }
161
162        foundrects = new PLuRectSequence[ totalpages ];
163        memset( foundrects, 0, sizeof( PLuRectSequence ) * totalpages );
164        links = new PLuLinkMapSequence[ totalpages ];
165        memset( links, 0, sizeof( PLuLinkMapSequence ) * totalpages );
166        enableAsynchDraw = doc->isAsynchRenderingSupported( ev );
167        drawPage();
168    }
169}
170
171void DocumentViewer::freeFoundrects()
172{
173    if ( foundrects != NULL )
174    {
175        for ( long i = 0; i < totalpages; i++ ) {
176            if ( foundrects[ i ] != NULL ) {
177                LuDocument::freeRectangles( ev, foundrects[ i ] );
178                foundrects[ i ] = NULL;
179            }
180        }
181    }
182}
183
184void DocumentViewer::freeLinks()
185{
186    if ( links != NULL )
187    {
188        for ( long i = 0; i < totalpages; i++ ) {
189            if ( links[ i ] != NULL ) {
190                LuDocument::freeLinkMapping( ev, links[ i ] );
191                links[ i ] = NULL;
192            }
193        }
194
195        delete links;
196        links = NULL;
197    }
198}
199
200
201// switch view to specified page
202void DocumentViewer::goToPage( long page )
203{
204    if ( continuous && ( doc != NULL ) )
205    {
206        double pgpos = pagenumToPos( page ) / VScrollStep;
207        vertScroll( hWndDoc, MPFROM2SHORT( pgpos, SB_SLIDERPOSITION ), NULLHANDLE );
208        drawPage();
209    }
210    else
211    {
212        currentpage = page;
213        if ( doc != NULL ) {
214            drawPage();
215            Lucide::checkNavigationMenus();
216        }
217    }
218}
219
220// Sets the zoom level
221// _zoom - actual zoom level or:
222//         -1 - fit width
223//         -2 - fit page
224void DocumentViewer::setZoom( double _zoom )
225{
226    zoom = _zoom;
227    if ( doc != NULL ) {
228        drawPage();
229    }
230}
231
232// copy selected text to clipboard
233void DocumentViewer::copyToClipbrd()
234{
235    char *t = doc->getText( ev, currentpage, &selection );
236    textToClipbrd( hab, t );
237}
238
239// perform search in document
240void DocumentViewer::searchDocument( const char *_searchString, bool _caseSensitive,
241                                     bool _continueSearch )
242{
243    abortSearch = false;
244    if ( !continueSearch ) {
245        freeFoundrects();
246    }
247
248    delete searchString;
249    searchString = newstrdup( _searchString );
250    caseSensitive = _caseSensitive;
251    continueSearch = _continueSearch;
252
253    progressDlg->setBreakFunc( searchabort, this );
254    progressDlg->setText( "" );
255    progressDlg->show( searchthread, this );
256}
257
258// static method, cancels asynch rendering if abortAsynch is true
259void DocumentViewer::searchabort( void *data )
260{
261    ((DocumentViewer *)data)->abortSearch = true;
262}
263
264// static method, thread for asynchronous searching
265void DocumentViewer::searchthread( void *p )
266{
267    DosSetPriority( PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MINIMUM, 0 );
268    DocumentViewer *_this = (DocumentViewer *)p;
269
270    HAB thab = WinInitialize( 0 );
271    HMQ thmq = WinCreateMsgQueue( thab, 0 );
272
273    long i = _this->currentpage;
274    if ( _this->continueSearch && ( _this->currentpage < ( _this->totalpages - 1 ) ) ) {
275        i = _this->currentpage + 1;
276    }
277
278    bool found = false;
279    for ( ; i < _this->totalpages; i++ )
280    {
281        char *fmt = newstrdupL( FIND_SEARCH_PAGE_OF );
282        char *buf = new char[ 255 ];
283        snprintf( buf, 255, fmt, i + 1, _this->totalpages );
284        _this->progressDlg->setText( buf );
285        delete fmt;
286        delete buf;
287
288        _this->foundrects[ i ] = _this->doc->searchText( _this->ev, i,
289                                        (char *)_this->searchString, _this->caseSensitive );
290        if ( _this->foundrects[ i ] != NULL )
291        {
292            found = true;
293            _this->progressDlg->hide();
294            _this->goToPage( i );
295            if ( _this->foundrects[i]->_length > 0 ) {
296                RECTL r;
297                _this->docPosToWinPos( 0, &(_this->foundrects[i]->_buffer[0]), &r );
298                _this->scrollToPos( _this->hWndDoc, NULLHANDLE, r.xLeft, r.yBottom, false );
299            }
300            break;
301        }
302
303        if ( _this->abortSearch ) {
304            break;
305        }
306    }
307    _this->progressDlg->hide();
308
309    if ( !found && !_this->abortSearch )
310    {
311        char *notfound = newstrdupL( FIND_NOT_FOUND );
312        WinMessageBox( HWND_DESKTOP, _this->hMainFrame, notfound, NULL,
313                       1, MB_OK | MB_ICONEXCLAMATION | MB_MOVEABLE );
314        delete notfound;
315    }
316
317    WinDestroyMsgQueue( thmq );
318    WinTerminate( thab );
319    _endthread();
320}
321
322// count real zoom level based on specified
323void DocumentViewer::adjustSize()
324{
325    if ( doc != NULL )
326    {
327        doc->getPageSize( ev, currentpage, &width, &height );
328
329        fullwidth = 0;
330        fullheight = 0;
331        for ( long i = 0; i < totalpages; i++ ) {
332            fullwidth = __max( fullwidth, pagesizes[i].x );
333            fullheight += pagesizes[i].y;
334        }
335
336        if ( zoom == -1 ) { // fit width
337            realzoom = (double)cxClient / ( continuous ? fullwidth : width );
338        }
339        else if ( zoom == -2 ) { // fit page
340            realzoom = __min( (double)cxClient / width, (double)cyClient / height );
341        }
342        else {
343            realzoom = zoom;
344        }
345        width *= realzoom;
346        height *= realzoom;
347        fullwidth *= realzoom;
348        fullheight *= realzoom;
349    }
350}
351
352// page redraw
353void DocumentViewer::drawPage()
354{
355    if ( continuous )
356    {
357        adjustSize();
358        WinSendMsg( hWndDoc, WM_SIZE, MPFROM2SHORT( cxClient, cyClient ),
359                    MPFROM2SHORT( cxClient, cyClient ) );
360        WinInvalidateRect( hWndDoc, NULL, FALSE );
361    }
362    else
363    {
364        LuDocument::freeRectangles( ev, selrects );
365        selrects = NULL;
366        if ( links != NULL ) {
367            if ( links[ currentpage ] == NULL ) {
368                links[ currentpage ] = doc->getLinkMapping( ev, currentpage );
369            }
370        }
371        Lucide::enableCopy( false );
372        adjustSize();
373        sVscrollPos = 0;
374        WinSendMsg( hWndDoc, WM_SIZE, MPFROM2SHORT( cxClient, cyClient ),
375                    MPFROM2SHORT( cxClient, cyClient ) );
376        WinInvalidateRect( hWndDoc, NULL, FALSE );
377    }
378}
379
380
381// handles vertical scrolling
382MRESULT DocumentViewer::vertScroll( HWND hwnd, MPARAM mp2, HRGN hrgn )
383{
384    sVscrollInc = 0;
385
386    switch ( SHORT2FROMMP( mp2 ) )
387    {
388        case SB_LINEUP:
389            sVscrollInc = -LINE_HEIGHT;
390            break ;
391        case SB_LINEDOWN:
392            sVscrollInc = LINE_HEIGHT;
393            break;
394        case SB_PAGEUP:
395            sVscrollInc = __min( -1, -( cyClient - LINE_HEIGHT ) );
396            break;
397        case SB_PAGEDOWN:
398            sVscrollInc = __max( 1, cyClient + LINE_HEIGHT );
399            break;
400        case SB_SLIDERTRACK:
401        case SB_SLIDERPOSITION:
402            sVscrollInc = ( SHORT1FROMMP( mp2 ) - sVscrollPos ) * VScrollStep;
403            break;
404    }
405
406    sVscrollInc = __max( -sVscrollPos * VScrollStep, __min( sVscrollInc,
407                              ( sVscrollMax - sVscrollPos ) * VScrollStep ) );
408
409    if ( sVscrollInc != 0 )
410    {
411        sVscrollPos += (SHORT)( sVscrollInc / VScrollStep );
412        WinScrollWindow( hwnd, 0, sVscrollInc, NULL, NULL, hrgn, NULL, SW_INVALIDATERGN );
413        WinSendMsg( hWndVscroll, SBM_SETPOS, MPFROMSHORT( sVscrollPos ), MPVOID );
414        WinUpdateWindow( hwnd );
415        sVscrollInc = 0;
416    }
417    return ( MRFROMLONG( 0 ) );
418}
419
420// handles horizontal scrolling
421MRESULT DocumentViewer::horizScroll( HWND hwnd, MPARAM mp2, HRGN hrgn )
422{
423    sHscrollInc = 0;
424
425    switch ( SHORT2FROMMP( mp2 ) )
426    {
427        case SB_LINELEFT:
428            sHscrollInc = -LINE_HEIGHT;
429            break;
430        case SB_LINERIGHT:
431            sHscrollInc = LINE_HEIGHT;
432            break;
433        case SB_PAGELEFT:
434            sHscrollInc = __min( -1, -( cxClient - LINE_HEIGHT ) );
435            break;
436        case SB_PAGERIGHT:
437            sHscrollInc = __max( 1, cxClient - LINE_HEIGHT );
438            break;
439        case SB_SLIDERTRACK:
440        case SB_SLIDERPOSITION:
441            sHscrollInc = SHORT1FROMMP( mp2 ) - sHscrollPos;
442            break;
443    }
444
445    sHscrollInc = __max( -sHscrollPos, __min( sHscrollInc, sHscrollMax - sHscrollPos ) );
446
447    if ( sHscrollInc != 0 )
448    {
449        sHscrollPos += (SHORT)sHscrollInc;
450        WinScrollWindow( hwnd, -sHscrollInc, 0, NULL, NULL, hrgn, NULL, SW_INVALIDATERGN );
451        WinSendMsg( hWndHscroll, SBM_SETPOS, MPFROMSHORT( sHscrollPos ), MPVOID );
452        WinUpdateWindow( hwnd );
453        sHscrollInc = 0;
454    }
455    return ( MRFROMLONG( 0 ) );
456}
457
458
459// handles WM_SIZE message
460// creates appropriate hps buffer, sets scrollbars limits
461void DocumentViewer::wmSize( HWND hwnd, MPARAM mp2 )
462{
463    cxClient = SHORT1FROMMP( mp2 );
464    cyClient = SHORT2FROMMP( mp2 );
465
466    adjustSize();
467
468    if ( ( hpsBuffer != NULLHANDLE ) && ( hdcBuffer != NULLHANDLE ) ) {
469        DestroyGraphicsBuffer( hpsBuffer, hdcBuffer );
470        hpsBuffer = hdcBuffer = NULLHANDLE;
471    }
472
473    HPS hps = WinGetPS( hwnd );
474    RECTL rectl = { 0, 0, cxClient, cyClient };
475    CreateGraphicsBuffer( hab, &rectl, hps, &hpsBuffer, &hdcBuffer );
476    WinReleasePS( hps );
477
478    sHscrollMax = (SHORT)__max( 0, ( continuous ? fullwidth : width ) - cxClient );
479    sHscrollPos = __min( sHscrollPos, sHscrollMax );
480
481    WinSendMsg( hWndHscroll, SBM_SETSCROLLBAR,
482                MPFROMSHORT(sHscrollPos), MPFROM2SHORT(0, sHscrollMax) );
483    WinSendMsg( hWndHscroll, SBM_SETTHUMBSIZE,
484                MPFROM2SHORT( cxClient, width ), MPVOID );
485    WinEnableWindow( hWndHscroll, (BOOL)( sHscrollMax != 0 ) );
486
487    if ( continuous )
488    {
489        realVscrollMax = __max( 0, fullheight - cyClient );
490        VScrollStep = LINE_HEIGHT;
491        ULONG ssize = realVscrollMax / VScrollStep;
492        while ( ssize > 32000 ) {
493            VScrollStep += LINE_HEIGHT;
494            ssize = realVscrollMax / VScrollStep;
495        }
496
497        sVscrollMax = (SHORT)ssize;
498    }
499    else {
500        realVscrollMax = sVscrollMax = (SHORT)__max( 0, height - cyClient );
501        VScrollStep = 1;
502    }
503    sVscrollPos = __min( sVscrollPos, sVscrollMax );
504
505    WinSendMsg( hWndVscroll, SBM_SETSCROLLBAR,
506                MPFROMSHORT(sVscrollPos), MPFROM2SHORT(0, sVscrollMax) );
507    if ( continuous ) {
508        WinSendMsg( hWndVscroll, SBM_SETTHUMBSIZE,
509                    MPFROM2SHORT( cyClient/VScrollStep, fullheight/VScrollStep ), MPVOID );
510    }
511    else {
512        WinSendMsg( hWndVscroll, SBM_SETTHUMBSIZE,
513                    MPFROM2SHORT( cyClient, height ), MPVOID );
514    }
515    WinEnableWindow( hWndVscroll, (BOOL)( sVscrollMax != 0 ) );
516}
517
518// returns true if subrect inside rect
519inline bool isSubrect( PRECTL rect, PRECTL subrect )
520{
521    return ( ( subrect->xLeft >= rect->xLeft ) &&
522             ( subrect->yBottom >= rect->yBottom ) &&
523             ( subrect->xRight <= rect->xRight ) &&
524             ( subrect->yTop <= rect->yTop ) );
525}
526
527// static method, cancels asynch rendering if abortAsynch is true
528long _System DocumentViewer::asynchCallbackFnAbort( void *data )
529{
530    return (long)(((DocumentViewer *)data)->abortAsynch);
531}
532
533// static method, draws area during asynch rendering
534long _System DocumentViewer::asynchCallbackFnDraw( void *data )
535{
536    DocumentViewer *d = (DocumentViewer *)data;
537    HPS hps = WinGetPS( d->hWndDoc );
538    if ( hps != NULLHANDLE )
539    {
540        PRECTL drawRect = &((*d->drawareas)[d->drawareaIndex].drawrect);
541        LONG rclx = drawRect->xRight - drawRect->xLeft;
542        LONG rcly = drawRect->yTop - drawRect->yBottom;
543
544        POINTL aptlPoints[4]={ drawRect->xLeft, drawRect->yBottom,
545                               drawRect->xRight-1, drawRect->yTop-1,
546                               0, 0, rclx, rcly };
547
548        LONG lRop = ROP_SRCCOPY;
549        BITMAPINFO2 pbmi;
550        pbmi.cbFix = 16L;
551        pbmi.cx = rclx;
552        pbmi.cy = rcly;
553        pbmi.cPlanes = 1;
554        pbmi.cBitCount = 24;
555        GpiDrawBits( hps, d->pixbuf->getDataPtr( d->ev ), &pbmi, 4L,
556                     aptlPoints, lRop, BBO_IGNORE );
557
558        WinReleasePS( hps );
559    }
560    return 0;
561}
562
563// static method, thread for asynchronous rendering
564void DocumentViewer::drawthread( void *p )
565{
566    DosSetPriority( PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MINIMUM, 0 );
567    DocumentViewer *_this = (DocumentViewer *)p;
568
569    HAB thab = WinInitialize( 0 );
570    HMQ thmq = WinCreateMsgQueue( thab, 0 );
571
572    ULONG postCnt;
573    while ( !_this->termdraw )
574    {
575        DosWaitEventSem( _this->haveDraw, SEM_INDEFINITE_WAIT );
576        DosResetEventSem( _this->haveDraw, &postCnt );
577        _this->abortAsynch = false;
578
579        if ( ( _this->drawareas != NULL ) && ( _this->doc != NULL ) )
580        {
581            DosRequestMutexSem( _this->todrawAccess, SEM_INDEFINITE_WAIT );
582
583            for ( int i = 0; i < _this->drawareas->size(); i++ )
584            {
585                PageDrawArea *pda = &(*_this->drawareas)[ i ];
586
587                LONG rclx = pda->drawrect.xRight - pda->drawrect.xLeft;
588                LONG rcly = pda->drawrect.yTop - pda->drawrect.yBottom;
589                _this->pixbuf = new LuPixbuf( _this->ev, rclx, rcly );
590                _this->doc->renderPageToPixbufAsynch( _this->ev, pda->pagenum,
591                       pda->startpos.x, pda->startpos.y, rclx, rcly, _this->realzoom, 0,
592                       _this->pixbuf, asynchCallbackFnDraw, asynchCallbackFnAbort, p );
593                delete _this->pixbuf;
594                _this->pixbuf = NULL;
595
596                if ( _this->abortAsynch ) {
597                    break;  // TODO: remove completed areas from drawareas
598                }
599            }
600
601            if ( !_this->abortAsynch )
602            {
603                HPS hps = WinGetPS( _this->hWndDoc );
604                if ( hps != NULLHANDLE ) {
605                    //_this->drawSelection( hps, &_this->drawRect );
606                    //_this->drawFound( hps, &_this->drawRect );
607                    WinReleasePS( hps );
608                }
609                delete _this->drawareas;
610                _this->drawareas = NULL;
611            }
612
613            DosReleaseMutexSem( _this->todrawAccess );
614        }
615    }
616
617    WinDestroyMsgQueue( thmq );
618    WinTerminate( thab );
619    _endthread();
620}
621
622// handles WM_PAINT if document supports asynch rendering.
623// posts events to drawthread
624void DocumentViewer::wmPaintAsynch( HWND hwnd )
625{
626    RECTL rcl;
627    HPS hps = WinBeginPaint( hwnd, 0L, &rcl );
628    if ( hps != NULLHANDLE )
629    {
630        RECTL rclWin = { 0 };
631        WinQueryWindowRect( hwnd, &rclWin );
632        if ( WinEqualRect( hab, &rcl, &rclWin ) ) {
633            GpiErase( hps );
634        }
635        WinEndPaint( hps );
636    }
637
638    RECTL rclPage = { 0, 0, width, height };
639    if ( height < cyClient )
640    {
641        rclPage.yBottom = cyClient - height;
642        rclPage.yTop = cyClient;
643    }
644    RECTL rclDraw = { 0, 0, 0, 0 };
645    if ( WinIntersectRect( hab, &rclDraw, &rcl, &rclPage ) )
646    {
647        if ( ( drawareas != NULL ) && ( drawareas->size() > 0 ) ) {
648            if ( isSubrect( &((*drawareas)[0].drawrect), &rclDraw ) &&
649                 ( sVscrollInc == 0 ) && ( sHscrollInc == 0 ) ) {
650                return;
651            }
652        }
653
654        abortAsynch = true;
655        DosRequestMutexSem( todrawAccess, SEM_INDEFINITE_WAIT );
656
657        if ( drawareas == NULL ) {
658            drawareas = new DrawAreas;
659        }
660        if ( drawareas->size() == 0 ) {
661            PageDrawArea pda;
662            memset( &pda, 0, sizeof( pda ) );
663            pda.pagenum = currentpage;
664            drawareas->push_back( pda );
665        }
666
667        PageDrawArea *ppda = &((*drawareas)[0]);
668
669        if ( !WinIsRectEmpty( hab, &ppda->drawrect ) )
670        {
671            if ( sVscrollInc > 0 ) {
672                ppda->drawrect.yTop    += sVscrollInc;
673            } else if ( sVscrollInc < 0 ) {
674                ppda->drawrect.yBottom += sVscrollInc;
675            }
676            if ( sHscrollInc > 0 ) {
677                ppda->drawrect.xLeft  -= sHscrollInc;
678            } else if ( sHscrollInc < 0 ) {
679                ppda->drawrect.xRight -= sHscrollInc;
680            }
681        }
682        WinUnionRect( hab, &ppda->drawrect, &ppda->drawrect, &rclDraw );
683        ppda->startpos.x = sHscrollPos + ppda->drawrect.xLeft;
684        ppda->startpos.y = ( cyClient - ppda->drawrect.yTop ) + sVscrollPos;
685
686        // workaround ?
687        ppda->drawrect.xRight++;
688        ppda->drawrect.yTop++;
689
690        DosReleaseMutexSem( todrawAccess );
691        DosPostEventSem( haveDraw );
692    }
693}
694
695
696// handles WM_PAINT if single-page synchronous rendering used
697void DocumentViewer::wmPaint( HWND hwnd )
698{
699    RECTL rcl;
700    HPS hps = WinBeginPaint( hwnd, 0L, &rcl );
701    GpiErase( hpsBuffer );
702
703    RECTL rclPage = { 0, 0, width, height };
704    if ( height < cyClient )
705    {
706        rclPage.yBottom = cyClient - height;
707        rclPage.yTop = cyClient;
708    }
709    RECTL rclDraw = { 0, 0, 0, 0 };
710    if ( WinIntersectRect( hab, &rclDraw, &rcl, &rclPage ) )
711    {
712        spos_x = sHscrollPos + rclDraw.xLeft;
713        spos_y = (cyClient - rclDraw.yTop) + sVscrollPos;
714        LONG rclx = rclDraw.xRight - rclDraw.xLeft;
715        LONG rcly = rclDraw.yTop - rclDraw.yBottom;
716
717        pixbuf = new LuPixbuf( ev, rclx, rcly );
718        POINTL aptlPoints[4]={ rclDraw.xLeft, rclDraw.yBottom,
719                               rclDraw.xRight-1, rclDraw.yTop-1,
720                               0, 0, rclx, rcly };
721
722        doc->renderPageToPixbuf( ev, currentpage, spos_x, spos_y,
723                                 rclx, rcly, realzoom, 0, pixbuf );
724        LONG lRop = ROP_SRCCOPY;
725        BITMAPINFO2 pbmi;
726        pbmi.cbFix = 16L;
727        pbmi.cx = rclx;
728        pbmi.cy = rcly;
729        pbmi.cPlanes = 1;
730        pbmi.cBitCount = 24;
731        GpiDrawBits( hpsBuffer, pixbuf->getDataPtr( ev ), &pbmi, 4L,
732                     aptlPoints, lRop, BBO_IGNORE );
733
734        drawSelection( hpsBuffer, &rclDraw );
735        drawFound( hpsBuffer, &rclDraw );
736
737        BlitGraphicsBuffer( hps, hpsBuffer, &rcl );
738        delete pixbuf;
739        pixbuf = NULL;
740    }
741
742    WinEndPaint( hps );
743}
744
745
746// founds number of page at specified vertical position
747// for continuous view only
748long DocumentViewer::posToPagenum( LONG yPosWin, double *pageRest )
749{
750    double yPos = ( cyClient - yPosWin ) + ( sVscrollPos * VScrollStep );
751    double pgend = 0;
752    for ( long i = 0; i < totalpages; i++ )
753    {
754        pgend += ( pagesizes[ i ].y * realzoom );
755        if ( yPos < pgend ) {
756            *pageRest = pgend - yPos;
757            return i;
758        }
759    }
760    return 0;
761}
762
763// founds vertical position of specified
764// for continuous view only
765double DocumentViewer::pagenumToPos( long pagenum )
766{
767    double ypos = 0;
768    for ( long i = 0; i < pagenum; i++ ) {
769        ypos += pagesizes[ i ].y;
770    }
771    return ypos * realzoom;
772}
773
774// founds pages and it's areas to draw
775DrawAreas *DocumentViewer::foundDrawAreas( PRECTL r )
776{
777    DrawAreas *areas = new DrawAreas;
778    if ( doc != NULL )
779    {
780        long foundpage = -1;
781        double pageRest;
782        for ( LONG i = r->yTop; i >= r->yBottom; i-- )
783        {
784            pageRest = 0;
785            long pg = posToPagenum( i, &pageRest );
786            if ( pg != foundpage )
787            {
788                PageDrawArea pda;
789                pda.pagenum = pg;
790                pda.drawrect.xLeft   = r->xLeft;
791                pda.drawrect.yBottom = __max( i - pageRest, r->yBottom );
792                pda.drawrect.xRight  = r->xRight;
793                pda.drawrect.yTop    = i;
794
795                pda.startpos.x = 0;
796                pda.startpos.y = ( pagesizes[ pg ].y * realzoom ) - pageRest;
797
798                areas->push_back( pda );
799                foundpage = pg;
800                i -= pageRest;
801                //somPrintf( "PGSIZE: %f, (yBottom: %d, yTop: %d)  PG: %d/%f  STPOS: %f\n",
802                //  pagesizes[ pg ].y, pda.drawrect.yBottom, pda.drawrect.yTop,
803                //         pg, pageRest, pda.startpos.y );
804            }
805        }
806    }
807
808    return areas;
809}
810
811
812// found current page in continuous view mode.
813// it's a page which occupes a most larger area in the window.
814void DocumentViewer::determineCurrentPage()
815{
816    RECTL rcl = { 0 };
817    WinQueryWindowRect( hWndDoc, &rcl );
818    DrawAreas *areas = foundDrawAreas( &rcl );
819    long pg = 0;
820    long sz = 0;
821    for ( int i = 0; i < areas->size(); i++ )
822    {
823        PageDrawArea *pda = &(*areas)[ i ];
824        long pgsz = pda->drawrect.yTop - pda->drawrect.yBottom;
825        if ( pgsz > sz ) {
826            pg = pda->pagenum;
827            sz = pgsz;
828        }
829    }
830    delete areas;
831
832    if ( pg != currentpage ) {
833        currentpage = pg;
834        Lucide::checkNavigationMenus();
835    }
836}
837
838
839// handles WM_PAINT if continuous synchronous rendering used
840void DocumentViewer::wmPaintCont( HWND hwnd )
841{
842    RECTL rcl;
843    HPS hps = WinBeginPaint( hwnd, 0L, &rcl );
844    GpiErase( hpsBuffer );
845
846    delete drawareas;
847    drawareas = foundDrawAreas( &rcl );
848
849    for ( int i = 0; i < drawareas->size(); i++ )
850    {
851        PageDrawArea *pda = &(*drawareas)[ i ];
852
853        // load links for page if not loaded before
854        if ( links[ pda->pagenum ] == NULL ) {
855            links[ pda->pagenum ] = doc->getLinkMapping( ev, pda->pagenum );
856        }
857
858        RECTL rclDraw = { __min( pagesizes[ pda->pagenum ].x * realzoom,
859                                 pda->drawrect.xLeft ),
860                          pda->drawrect.yBottom,
861                          __min( pagesizes[ pda->pagenum ].x * realzoom,
862                                 pda->drawrect.xRight ),
863                          pda->drawrect.yTop };
864
865        spos_x = sHscrollPos + rclDraw.xLeft;
866        //spos_y = ( cyClient - rclDraw.yTop ) + ( sVscrollPos * VScrollStep );
867        spos_y = pda->startpos.y;
868        LONG rclx = rclDraw.xRight - rclDraw.xLeft;
869        LONG rcly = rclDraw.yTop - rclDraw.yBottom;
870
871        pixbuf = new LuPixbuf( ev, rclx, rcly );
872        POINTL aptlPoints[4]={ rclDraw.xLeft, rclDraw.yBottom,
873                               rclDraw.xRight-1, rclDraw.yTop-1,
874                               0, 0, rclx, rcly };
875
876        doc->renderPageToPixbuf( ev, pda->pagenum, spos_x, spos_y,
877                                 rclx, rcly, realzoom, 0, pixbuf );
878        LONG lRop = ROP_SRCCOPY;
879        BITMAPINFO2 pbmi;
880        pbmi.cbFix = 16L;
881        pbmi.cx = rclx;
882        pbmi.cy = rcly;
883        pbmi.cPlanes = 1;
884        pbmi.cBitCount = 24;
885        GpiDrawBits( hpsBuffer, pixbuf->getDataPtr( ev ), &pbmi, 4L,
886                     aptlPoints, lRop, BBO_IGNORE );
887
888        //drawSelection( hpsBuffer, &rclDraw );
889        //drawFound( hpsBuffer, &rclDraw );
890
891        delete pixbuf;
892        pixbuf = NULL;
893    }
894    delete drawareas;
895    drawareas = NULL;
896    BlitGraphicsBuffer( hps, hpsBuffer, &rcl );
897    WinEndPaint( hps );
898
899    determineCurrentPage();
900}
901
902
903// converts window position to document position
904void DocumentViewer::winPosToDocPos( PPOINTL startpoint, PPOINTL endpoint, LuRectangle *r )
905{
906    r->x1 = ( startpoint->x + sHscrollPos ) / realzoom;
907    r->y1 = ( ( cyClient - startpoint->y ) + sVscrollPos ) / realzoom;
908    r->x2 = ( endpoint->x + sHscrollPos ) / realzoom;
909    r->y2 = ( ( cyClient - endpoint->y ) + sVscrollPos ) / realzoom;
910}
911
912// converts document position to window position
913void DocumentViewer::docPosToWinPos( long pagenum, LuRectangle *r, PRECTL rcl )
914{
915    if ( continuous )
916    {
917        double yplus = pagenumToPos( pagenum );
918
919        rcl->xLeft   = ( r->x1 * realzoom ) - sHscrollPos;
920        rcl->yBottom = cyClient - ( ( yplus + r->y2 ) * realzoom ) +
921                            ( sVscrollPos * VScrollStep );
922        rcl->xRight  = ( r->x2 * realzoom ) - sHscrollPos;
923        rcl->yTop    = cyClient - ( ( yplus + r->y1 ) * realzoom ) +
924                            ( sVscrollPos * VScrollStep );
925    }
926    else
927    {
928        rcl->xLeft   = ( r->x1 * realzoom ) - sHscrollPos;
929        rcl->yBottom = cyClient - ( r->y2 * realzoom ) + sVscrollPos;
930        rcl->xRight  = ( r->x2 * realzoom ) - sHscrollPos;
931        rcl->yTop    = cyClient - ( r->y1 * realzoom ) + sVscrollPos;
932    }
933}
934
935// creates region from sequence of rectangles
936HRGN DocumentViewer::rectsToRegion( HPS hps, LuDocument_LuRectSequence *rects, bool useScale )
937{
938    HRGN hrgn = GpiCreateRegion( hps, 0, NULL );
939    if ( rects != NULL )
940    {
941        RECTL r = {0};
942        for ( int i = 0; i < rects->_length; i++ )
943        {
944            if ( useScale ) {
945                docPosToWinPos( 0, &(rects->_buffer[i]), &r );
946            }
947            else
948            {
949                r.xLeft = rects->_buffer[i].x1 - sHscrollPos;
950                r.yBottom = cyClient - rects->_buffer[i].y2 + sVscrollPos;
951                r.xRight = rects->_buffer[i].x2 - sHscrollPos;
952                r.yTop = cyClient - rects->_buffer[i].y1 + sVscrollPos;
953            }
954            HRGN tmprgn = GpiCreateRegion( hps, 1, &r );
955            GpiCombineRegion( hps, hrgn, hrgn, tmprgn, CRGN_OR );
956            GpiDestroyRegion( hps, tmprgn );
957        }
958    }
959    return hrgn;
960}
961
962// draws selected area in window, using XOR mix
963// drawing area may be restricted by r rectangle
964void DocumentViewer::drawSelection( HPS hps, PRECTL r )
965{
966    GpiSetMix( hps, FM_XOR );
967    GpiSetColor( hps, CLR_YELLOW );
968    HRGN selectRegion = rectsToRegion( hps, selrects, false );
969    if ( r != NULL )
970    {
971        HRGN tmprgn = GpiCreateRegion( hps, 1, r );
972        GpiCombineRegion( hps, selectRegion, selectRegion, tmprgn, CRGN_AND );
973        GpiDestroyRegion( hps, tmprgn );
974    }
975    GpiPaintRegion( hps, selectRegion );
976    GpiDestroyRegion( hps, selectRegion );
977}
978
979void DocumentViewer::drawFound( HPS hps, PRECTL r )
980{
981    GpiSetMix( hps, FM_XOR );
982    GpiSetColor( hps, CLR_CYAN );
983    HRGN selectRegion = rectsToRegion( hps, foundrects[ currentpage ], true );
984    if ( r != NULL )
985    {
986        HRGN tmprgn = GpiCreateRegion( hps, 1, r );
987        GpiCombineRegion( hps, selectRegion, selectRegion, tmprgn, CRGN_AND );
988        GpiDestroyRegion( hps, tmprgn );
989    }
990    GpiPaintRegion( hps, selectRegion );
991    GpiDestroyRegion( hps, selectRegion );
992}
993
994// scrolls window to specified pos (optionally with text selection)
995void DocumentViewer::scrollToPos( HWND hwnd, HRGN hrgn, SHORT xpos, SHORT ypos,
996                                  bool withSelection )
997{
998    SHORT xinc = 0;
999    SHORT yinc = 0;
1000
1001    if ( ( xpos < 0 ) && ( sHscrollPos > 0 ) ) {
1002        xinc = __max( sHscrollPos * -1, xpos );
1003    } else if ( ( xpos > cxClient ) && ( sHscrollPos < sHscrollMax ) ) {
1004        xinc = __min( sHscrollMax - sHscrollPos, xpos - cxClient );
1005    }
1006    if ( ( ypos < 0 ) && ( sVscrollPos < sVscrollMax ) ) {
1007        yinc = __min( sVscrollMax - sVscrollPos, ypos * -1 );
1008    }
1009    else if ( ( ypos > cyClient ) && ( sVscrollPos > 0 ) ) {
1010        yinc = __max( sVscrollPos * -1, cyClient - ypos );
1011    }
1012
1013    if ( xinc != 0 ) {
1014        horizScroll( hwnd, MPFROM2SHORT( sHscrollPos + xinc, SB_SLIDERPOSITION ), hrgn );
1015        if ( withSelection ) {
1016            selectionStart.x -= xinc;
1017        }
1018    }
1019    if ( yinc != 0 ) {
1020        vertScroll( hwnd, MPFROM2SHORT( sVscrollPos + yinc, SB_SLIDERPOSITION ), hrgn );
1021        if ( withSelection ) {
1022            selectionStart.y += yinc;
1023        }
1024    }
1025}
1026
1027// handles WM_MOUSEMOVE
1028// performs text selection if mouse button pressed
1029// changes mouse ptr to 'hand' if it moves over link area
1030BOOL DocumentViewer::wmMouseMove( HWND hwnd, SHORT xpos, SHORT ypos )
1031{
1032    if ( mousePressed && ( doc != NULL ) )
1033    {
1034        selectionEnd.x = xpos;
1035        selectionEnd.y = ypos;
1036
1037        winPosToDocPos( &selectionStart, &selectionEnd, &selection );
1038
1039        HPS hps = WinGetPS( hwnd );
1040        HRGN scrolledRegion = NULLHANDLE; //GpiCreateRegion( hps, 0, NULL );
1041
1042        scrollToPos( hwnd, scrolledRegion, xpos, ypos, true );
1043
1044        // 127/191/255
1045        //LONG lclr = ( 127 << 16 ) | ( 191 << 8 ) | 255;
1046        //LONG lclr = ( 128 << 16 ) | ( 64 << 8 );
1047        //LONG ltabl[ 1 ] = { lclr };
1048        //GpiCreateLogColorTable( hps, 0, LCOLF_CONSECRGB, 100, 1, ltabl );
1049
1050        GpiSetMix( hps, FM_XOR );
1051        GpiSetColor( hps, CLR_YELLOW );
1052        //GpiSetColor( hps, 100 );
1053
1054        HRGN clearRegion = rectsToRegion( hps, selrects, false );
1055        LuDocument::freeRectangles( ev, selrects );
1056        if ( ( selectionStart.x == selectionEnd.x ) &&
1057             ( selectionStart.y == selectionEnd.y ) ) {
1058            selrects = NULL;
1059        }
1060        else {
1061            selrects = doc->getSelectionRectangles( ev, currentpage, realzoom, &selection );
1062        }
1063        HRGN selectRegion = rectsToRegion( hps, selrects, false );
1064        GpiCombineRegion( hps, selectRegion, selectRegion, clearRegion, CRGN_XOR );
1065        //GpiCombineRegion( hps, selectRegion, selectRegion, scrolledRegion, CRGN_DIFF );
1066        GpiPaintRegion( hps, selectRegion );
1067        GpiDestroyRegion( hps, clearRegion );
1068        GpiDestroyRegion( hps, selectRegion );
1069        //GpiDestroyRegion( hps, scrolledRegion );
1070
1071        WinReleasePS( hps );
1072    }
1073    else if ( links != NULL )
1074    {
1075        long pg = currentpage;
1076        if ( continuous ) {
1077            double tmp;
1078            pg = posToPagenum( ypos, &tmp );
1079        }
1080
1081        if ( links[ pg ] != NULL )
1082        {
1083            for ( int i = 0; i < links[ pg ]->_length; i++ )
1084            {
1085                RECTL r = {0};
1086                docPosToWinPos( pg, &(links[ pg ]->_buffer[i].area), &r );
1087
1088                POINTL ptl = { xpos, ypos };
1089                if ( WinPtInRect( hab, &r, &ptl ) ) {
1090                    WinSetPointer( HWND_DESKTOP, handptr );
1091                    return TRUE;
1092                }
1093            }
1094        }
1095    }
1096
1097    return FALSE;
1098}
1099
1100// handles WM_BUTTON1CLICK
1101BOOL DocumentViewer::wmClick( HWND hwnd, SHORT xpos, SHORT ypos )
1102{
1103    if ( links == NULL ) {
1104        return FALSE;
1105    }
1106
1107    long pg = currentpage;
1108    if ( continuous ) {
1109        double tmp;
1110        pg = posToPagenum( ypos, &tmp );
1111    }
1112
1113    if ( links[ pg ] != NULL )
1114    {
1115        for ( int i = 0; i < links[ pg ]->_length; i++ )
1116        {
1117            RECTL r = {0};
1118            docPosToWinPos( pg, &(links[ pg ]->_buffer[i].area), &r );
1119
1120            POINTL ptl = { xpos, ypos };
1121            if ( WinPtInRect( hab, &r, &ptl ) )
1122            {
1123                if ( links[ pg ]->_buffer[i].link.type == LU_LINK_TYPE_EXTERNAL_URI )
1124                {
1125                    WinMessageBox( HWND_DESKTOP, hMainFrame,
1126                        links[ pg ]->_buffer[i].link.uri, "URI", 1,
1127                        MB_OK | MB_INFORMATION | MB_MOVEABLE );
1128                }
1129                else if ( links[ pg ]->_buffer[i].link.type == LU_LINK_TYPE_TITLE )
1130                {
1131                    char *title = links[ pg ]->_buffer[i].link.title;
1132                    if ( title == NULL ) {
1133                        title = "???";
1134                    }
1135                    WinMessageBox( HWND_DESKTOP, hMainFrame,
1136                        title, "?", 1, MB_OK | MB_INFORMATION | MB_MOVEABLE );
1137                }
1138                else if ( links[ pg ]->_buffer[i].link.type == LU_LINK_TYPE_PAGE )
1139                {
1140                    goToPage( links[ pg ]->_buffer[i].link.page );
1141                }
1142
1143                return TRUE;
1144            }
1145        }
1146    }
1147
1148    return FALSE;
1149}
1150
1151
1152BOOL DocumentViewer::wmChar( HWND hwnd, MPARAM mp1, MPARAM mp2 )
1153{
1154    USHORT fsflags = SHORT1FROMMP( mp1 );
1155    USHORT usvk = SHORT2FROMMP( mp2 );
1156
1157    if ( ( fsflags & KC_VIRTUALKEY ) && !( fsflags & KC_KEYUP ) )
1158    {
1159        switch ( usvk )
1160        {
1161            case VK_UP:
1162                WinSendMsg( hwnd, WM_VSCROLL, MPVOID, MPFROM2SHORT( 0, SB_LINEUP ) );
1163                return TRUE;
1164
1165            case VK_DOWN:
1166                WinSendMsg( hwnd, WM_VSCROLL, MPVOID, MPFROM2SHORT( 0, SB_LINEDOWN ) );
1167                return TRUE;
1168
1169            case VK_PAGEUP:
1170                WinSendMsg( hwnd, WM_VSCROLL, MPVOID, MPFROM2SHORT( 0, SB_PAGEUP ) );
1171                return TRUE;
1172
1173            case VK_PAGEDOWN:
1174                WinSendMsg( hwnd, WM_VSCROLL, MPVOID, MPFROM2SHORT( 0, SB_PAGEDOWN ) );
1175                return TRUE;
1176
1177            case VK_LEFT:
1178                WinSendMsg( hwnd, WM_HSCROLL, MPVOID, MPFROM2SHORT( 0, SB_LINELEFT ) );
1179                return TRUE;
1180
1181            case VK_RIGHT:
1182                WinSendMsg( hwnd, WM_HSCROLL, MPVOID, MPFROM2SHORT( 0, SB_LINERIGHT ) );
1183                return TRUE;
1184        }
1185    }
1186
1187    return FALSE;
1188}
1189
1190
1191// static, window procedure
1192MRESULT EXPENTRY DocumentViewer::docViewProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
1193{
1194    DocumentViewer *_this = (DocumentViewer *)WinQueryWindowULong( hwnd, QWL_USER );
1195
1196    switch ( msg )
1197    {
1198        case WM_CREATE:
1199        {
1200            // Save the mp1 into our user data so that subsequent calls have
1201            // access to the parent C++ object
1202            WinSetWindowULong( hwnd, QWL_USER, (ULONG)mp1 );
1203            _this = (DocumentViewer *)mp1;
1204            return (MRESULT)FALSE;
1205        }
1206
1207        case WM_ERASEBACKGROUND:
1208            return (MRESULT)TRUE;
1209
1210        case WM_SIZE:
1211            _this->wmSize( hwnd, mp2 );
1212            return (MRESULT)FALSE;
1213
1214        case WM_HSCROLL:
1215            _this->horizScroll( hwnd, mp2, NULLHANDLE );
1216            break;
1217
1218        case WM_VSCROLL:
1219            _this->vertScroll( hwnd, mp2, NULLHANDLE );
1220            break;
1221
1222        case WM_PAINT:
1223            if ( _this->enableAsynchDraw ) {
1224                _this->wmPaintAsynch( hwnd );
1225            } else {
1226                if ( _this->continuous ) {
1227                    _this->wmPaintCont( hwnd );
1228                } else {
1229                    _this->wmPaint( hwnd );
1230                }
1231            }
1232            return (MRESULT)FALSE;
1233
1234        case WM_BUTTON1DOWN:
1235            {
1236                WinSetCapture( HWND_DESKTOP, hwnd );
1237                _this->mousePressed = true;
1238                _this->selectionStart.x = SHORT1FROMMP( mp1 );
1239                _this->selectionStart.y = SHORT2FROMMP( mp1 );
1240            }
1241            break;
1242
1243        case WM_BUTTON1UP:
1244            {
1245                WinSetCapture( HWND_DESKTOP, NULLHANDLE );
1246                _this->mousePressed = false;
1247                Lucide::enableCopy( _this->selrects != NULL );
1248            }
1249            break;
1250
1251        case WM_MOUSEMOVE:
1252            if ( _this->wmMouseMove( hwnd, SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ) ) ) {
1253                return (MRESULT)TRUE;
1254            }
1255            break;
1256
1257        case WM_BUTTON1CLICK:
1258            if ( _this->wmClick( hwnd, SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ) ) ) {
1259                return (MRESULT)TRUE;
1260            }
1261            break;
1262
1263        case WM_CHAR:
1264            if ( _this->wmChar( hwnd, mp1, mp2 ) ) {
1265                return (MRESULT)TRUE;
1266            }
1267            break;
1268    }
1269
1270    return WinDefWindowProc( hwnd, msg, mp1, mp2 );
1271}
1272
Note: See TracBrowser for help on using the repository browser.