source: trunk/Lucide/gui/lucide.cpp @ 450

Last change on this file since 450 was 450, checked in by Silvan Scherrer, 11 years ago

fixes ticket:190

File size: 57.9 KB
Line 
1/* ***** BEGIN47 LICENSE BLOCK *****
2 * Version: CDDL 1.0/LGPL 2.1
3 *
4 * The contents of this file are subject to the COMMON DEVELOPMENT AND
5 * DISTRIBUTION LICENSE (CDDL) Version 1.0 (the "License"); you may not use
6 * this file except in compliance with the License. You may obtain a copy of
7 * the License at http://www.sun.com/cddl/
8 *
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
13 *
14 * The Initial Developer of the Original Code is
15 * Eugene Romanenko, netlabs.org.
16 * Portions created by the Initial Developer are Copyright (C) 2006
17 * the Initial Developer. All Rights Reserved.
18 *
19 * Contributor(s):
20 *
21 * Alternatively, the contents of this file may be used under the terms of
22 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
23 * in which case the provisions of the LGPL are applicable instead of those
24 * above. If you wish to allow use of your version of this file only under the
25 * terms of the LGPL, and not to allow others to use your version of this file
26 * under the terms of the CDDL, indicate your decision by deleting the
27 * provisions above and replace them with the notice and other provisions
28 * required by the LGPL. If you do not delete the provisions above, a recipient
29 * may use your version of this file under the terms of any one of the CDDL
30 * or the LGPL.
31 *
32 * ***** END LICENSE BLOCK ***** */
33
34
35#define INCL_SPL
36#define INCL_SPLDOSPRINT
37#include "os2all.h"
38
39#include <string>
40#include <vector>
41#include <algorithm>
42#include <stdio.h>
43#include <stdlib.h>
44#include <process.h>
45#if defined(__WATCOM__)
46#include <dos.h>
47#define find_t_name(find_t) find_t.name
48#else
49#include <unistd.h>
50#include <emx/syscalls.h>
51typedef _find find_t;
52#define find_t_name(find_t) find_t.szName
53#define _dos_findfirst __findfirst
54#define _dos_findnext __findnext
55#define _dos_findclose(a) do {} while(0)
56#endif
57
58#include <ludoc.xh>
59
60#include "Lucide.h"
61#include "pluginman.h"
62#include "pluginViewDlg.h"
63#include "fontsInfoDlg.h"
64#include "docInfoDlg.h"
65#include "findDlg.h"
66#include "printDlg.h"
67#include "progressDlg.h"
68#include "settingsDlg.h"
69#include "passwordDlg.h"
70#include "docViewer.h"
71#include "indexWindow.h"
72#include "recent.h"
73#include "lusettings.h"
74#include "luutils.h"
75#include "tb_spl.h"
76#include "Lucide_res.h"
77#include "messages.h"
78
79
80#define ID_SPLITTER 1
81
82const char *appName    = "Lucide";
83const char *appVersion = VERSION;
84const char *appBuild   = BUILD;
85const char *appDate    = VERSIONDATE;
86const char *prfFwp     = "FrameWindowPos";
87const char *prfLvd     = "LastViewedDir";
88const char *prfSplpos  = "SplitterPos";
89const char *prfShowind = "ShowIndex";
90const char *prfFullscreen   = "FullScreen";
91const char *prfPresentation = "Presentation";
92
93HWND createToolbar( HWND hwnd );
94void AboutBox( HWND hWndFrame );
95void initPipeMon( HWND hWndFrame );
96void unInitPipeMon();
97HWND LcdFileDlg( HWND hwndP, HWND hwndO, FILEDLG *pfild );
98
99
100HAB   hab            = NULLHANDLE;
101HWND  hWndFrame      = NULLHANDLE;
102HWND  hWndMenu       = NULLHANDLE;
103HWND  hToolBar       = NULLHANDLE;
104HWND  hVertSplitter  = NULLHANDLE;
105HWND  hHorizSplitter = NULLHANDLE;
106HWND  hFrameSysmenu  = NULLHANDLE;
107HWND  hFrameTitlebar = NULLHANDLE;
108HWND  hFrameMinMax   = NULLHANDLE;
109
110Environment    *ev        = somGetGlobalEnvironment();
111LuDocument     *doc       = NULL;
112PluginManager  *pluginMan = NULL;
113DocumentViewer *docViewer = NULL;
114IndexWindow    *indexWin  = NULL;
115FindDlg        *findDlg   = NULL;
116LuSettings     *settings  = NULL;
117RecentFiles    *recent    = NULL;
118char           *title     = NULL;
119
120
121bool         Lucide::dontSwitchPage                = false;
122SHORT        Lucide::splitterPos                   = 100;
123bool         Lucide::showIndex                     = true;
124bool         Lucide::isFullscreen                  = false;
125bool         Lucide::isPresentation                = false;
126LuWindowPos  Lucide::winPos                        = {0};
127char         Lucide::docFullName[ CCHMAXPATH ]     = "";
128char         Lucide::docFileName[ CCHMAXPATHCOMP ] = "";
129char         Lucide::docDirName[ CCHMAXPATHCOMP ]  = "";
130char        *Lucide::password                      = NULL;
131ActiveWindow Lucide::activeWindow                  = AwView;
132// static data for asynch loading document
133ProgressDlg *Lucide::loadProgressDlg               = NULL;
134bool         Lucide::docLoaded                     = false;;
135char        *Lucide::loadError                     = NULL;
136long         Lucide::loadErrorCode                 = LU_LDERR_NO_ERROR;
137char        *Lucide::thumbnailData                 = NULL;
138int          Lucide::thumbnailDataLen              = 0;
139
140// List of files in current directory
141static std::vector<std::string> fileList;
142static std::vector<std::string>::const_iterator fileListIterator;
143
144HMODULE _hmod = NULLHANDLE;
145
146unsigned APIENTRY LibMain( unsigned hmod, unsigned termination )
147{
148    if ( termination ) {
149        // DLL is detaching from process
150    } else {
151        // DLL is attaching to process
152        _hmod = hmod;
153    }
154    return( 1 );
155}
156
157#if !defined(__WATCOM__)
158extern "C" unsigned long _System _DLL_InitTerm( unsigned long mod_handle,
159                                                unsigned long flag )
160{
161    int _CRT_init();
162    void _CRT_term();
163    void __ctordtorInit();
164    void __ctordtorTerm();
165
166    switch ( flag ) {
167        case 0:
168            if ( _CRT_init() != 0 )
169                return 0;
170            __ctordtorInit();
171            return LibMain( mod_handle, flag );
172        case 1:
173            __ctordtorTerm();
174            _CRT_term ();
175            return LibMain( mod_handle, flag );
176        default:
177            return 0;
178    }
179}
180#endif
181
182
183// stolen from xWorkplace sources
184static
185APIRET my_DosQueryProcAddr(PCSZ pcszModuleName, ULONG ulOrdinal, PFN *ppfn)
186{
187    HMODULE hmod = NULL;
188    APIRET rc = 0;
189    if (!(rc = DosQueryModuleHandle( (PSZ)pcszModuleName, &hmod))) {
190        if ((rc = DosQueryProcAddr( hmod, ulOrdinal, NULL, ppfn))) {
191            // the CP programming guide and reference says use
192            // DosLoadModule if DosQueryProcAddr fails with this error
193            if (rc == ERROR_INVALID_HANDLE) {
194                if (!(rc = DosLoadModule(NULL, 0, (PSZ) pcszModuleName,
195                                         &hmod))) {
196                    rc = DosQueryProcAddr(hmod, ulOrdinal, NULL, ppfn);
197                }
198            }
199        }
200    }
201    return rc;
202}
203
204
205PFNWP pOldFrameProc = NULL;
206PFNWP pOldSplProc   = NULL;
207
208void Lucide::enableCopy( bool enable )
209{
210    WinEnableMenuItem( hWndMenu, CM_COPY, enable );
211}
212
213void Lucide::setOfPages( long pages )
214{
215    char *pgfrm = newstrdupL( TB_PAGENUM );
216    char pgnum[ 32 ];
217    snprintf( pgnum, sizeof( pgnum ), pgfrm, pages );
218    delete pgfrm;
219    WinSetDlgItemText( hToolBar, TBID_OFPAGES, pgnum );
220
221    // if pages are 0 also set limits to 0
222    long pageLimit = (pages >= 1 ? 1:0);
223    WinSendDlgItemMsg( hToolBar, TBID_PAGENUM, SPBM_SETLIMITS,
224                       MPFROMLONG( pages ), MPFROMLONG( pageLimit ) );
225}
226
227void Lucide::checkNavigationMenus()
228{
229    WinEnableMenuItem( hWndMenu, CM_GOTOPAGE, TRUE );
230    BOOL enfirst = ( docViewer->getCurrentPage() != 0 );
231    BOOL enlast = ( docViewer->getCurrentPage() != ( doc->getPageCount( ev ) - 1 ) );
232    WinEnableMenuItem( hWndMenu, CM_FIRSTPAGE, enfirst );
233    WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_FIRSTPAGE), (MPARAM)enfirst );
234    WinEnableMenuItem( hWndMenu, CM_PREVPAGE, enfirst );
235    WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_PREVPAGE), (MPARAM)enfirst );
236    WinEnableMenuItem( hWndMenu, CM_NEXTPAGE, enlast );
237    WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_NEXTPAGE), (MPARAM)enlast );
238    WinEnableMenuItem( hWndMenu, CM_LASTPAGE, enlast );
239    WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_LASTPAGE), (MPARAM)enlast );
240
241    bool tmp = dontSwitchPage;
242    dontSwitchPage = true;
243    WinSendDlgItemMsg( hToolBar, TBID_PAGENUM, SPBM_SETCURRENTVALUE,
244                       MPFROMLONG( docViewer->getCurrentPage() + 1 ), MPVOID );
245    dontSwitchPage = tmp;
246    indexWin->goToPage( NULL, docViewer->getCurrentPage() );
247}
248
249void Lucide::enableZoomMenus()
250{
251    BOOL scalable = doc->isScalable( ev );
252    WinEnableMenuItem( hWndMenu, CM_FITWINDOW, scalable );
253    WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_FITWINDOW), (MPARAM)scalable );
254    WinEnableMenuItem( hWndMenu, CM_ACTSIZE, scalable );
255    WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_ACTSIZE), (MPARAM)scalable );
256    WinEnableMenuItem( hWndMenu, CM_FITWIDTH, scalable );
257    WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_FITWIDTH), (MPARAM)scalable );
258    WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_ZOOM_IN_OUT), (MPARAM)scalable );
259    WinEnableMenuItem( hWndMenu, CM_ZOOM_IN, scalable );
260    WinEnableMenuItem( hWndMenu, CM_ZOOM_OUT, scalable );
261    WinEnableControl( hToolBar, TBID_ZOOM, scalable );
262    BOOL rotable = doc->isRotable( ev );
263    WinEnableMenuItem( hWndMenu, CM_ROTATE90CW, rotable );
264    WinEnableMenuItem( hWndMenu, CM_ROTATE90CCW, rotable );
265}
266
267
268void Lucide::setZoomChecks( SHORT cmd, SHORT cbind, double zoom )
269{
270    if ( cmd != -1 )
271    {
272        WinCheckMenuItem( hWndMenu, cmd, TRUE );
273        WinSendMsg( hToolBar, TBM_SETCHECK, MPFROMSHORT( cmd ), (MPARAM)TRUE );
274    }
275
276    if ( cbind != -1 )
277    {
278        char buf[ 255 ] = "";
279        WinSendDlgItemMsg( hToolBar, TBID_ZOOM, LM_QUERYITEMTEXT,
280                           MPFROM2SHORT( cbind, sizeof( buf ) ), MPFROMP( buf ) );
281        WinSetDlgItemText( hToolBar, TBID_ZOOM, buf );
282    }
283
284    if ( zoom != 0 )
285    {
286        std::string z = str( zoom * 100.0 ) + "%";
287        WinSetDlgItemText( hToolBar, TBID_ZOOM, z.c_str() );
288    }
289}
290
291void Lucide::checkZoomMenus()
292{
293    double zoom = docViewer->getZoom();
294
295    WinCheckMenuItem( hWndMenu, CM_FITWINDOW, FALSE );
296    WinSendMsg( hToolBar, TBM_SETCHECK, MPFROMSHORT(CM_FITWINDOW), (MPARAM)FALSE );
297    WinCheckMenuItem( hWndMenu, CM_ACTSIZE, FALSE );
298    WinSendMsg( hToolBar, TBM_SETCHECK, MPFROMSHORT(CM_ACTSIZE), (MPARAM)FALSE );
299    WinCheckMenuItem( hWndMenu, CM_FITWIDTH, FALSE );
300    WinSendMsg( hToolBar, TBM_SETCHECK, MPFROMSHORT(CM_FITWIDTH), (MPARAM)FALSE );
301
302    if ( zoom == -2 ) {
303        setZoomChecks( CM_FITWINDOW, 1, 0 );
304    } else if ( zoom == -1 ) {
305        setZoomChecks( CM_FITWIDTH, 2, 0 );
306    } else if ( zoom == 1 ) {
307        setZoomChecks( CM_ACTSIZE, 0, 0 );
308    } else {
309        setZoomChecks( -1, -1, zoom );
310    }
311}
312
313void Lucide::checkMenus( bool initial )
314{
315    if ( initial )
316    {
317        // pre-set "Actual size"
318        setZoomChecks( CM_ACTSIZE, 0, 0 );
319    }
320
321    if ( doc == NULL )
322    {
323        if ( initial )
324        {
325            // "single page" mode by default
326            WinCheckMenuItem( hWndMenu, CM_SINGLEPAGE, TRUE );
327        }
328
329        WinEnableMenuItem( hWndMenu, CM_SAVEAS, FALSE );
330        WinEnableMenuItem( hWndMenu, CM_CLOSE, FALSE );
331        WinEnableMenuItem( hWndMenu, CM_PRINT, FALSE );
332        WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_PRINT), (MPARAM)FALSE );
333        WinEnableMenuItem( hWndMenu, CM_DOCINFO, FALSE );
334        WinEnableMenuItem( hWndMenu, CM_FONTSINFO, FALSE );
335
336        WinEnableMenuItem( hWndMenu, CM_COPY, FALSE );
337        WinEnableMenuItem( hWndMenu, CM_SELECTALL, FALSE );
338        WinEnableMenuItem( hWndMenu, CM_FIND, FALSE );
339        WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_FIND), (MPARAM)FALSE );
340        WinEnableMenuItem( hWndMenu, CM_FINDAGAIN, FALSE );
341        WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_FINDAGAIN), (MPARAM)FALSE );
342
343        WinEnableMenuItem( hWndMenu, CM_FIRSTPAGE, FALSE );
344        WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_FIRSTPAGE), (MPARAM)FALSE );
345        WinEnableMenuItem( hWndMenu, CM_PREVPAGE, FALSE );
346        WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_PREVPAGE), (MPARAM)FALSE );
347        WinEnableMenuItem( hWndMenu, CM_NEXTPAGE, FALSE );
348        WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_NEXTPAGE), (MPARAM)FALSE );
349        WinEnableMenuItem( hWndMenu, CM_LASTPAGE, FALSE );
350        WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_LASTPAGE), (MPARAM)FALSE );
351        WinEnableMenuItem( hWndMenu, CM_GOTOPAGE, FALSE );
352
353        WinEnableMenuItem( hWndMenu, CM_FITWINDOW, FALSE );
354        WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_FITWINDOW), (MPARAM)FALSE );
355        WinEnableMenuItem( hWndMenu, CM_ACTSIZE, FALSE );
356        WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_ACTSIZE), (MPARAM)FALSE );
357        WinEnableMenuItem( hWndMenu, CM_FITWIDTH, FALSE );
358        WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_FITWIDTH), (MPARAM)FALSE );
359        WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_ZOOM_IN_OUT), (MPARAM)FALSE );
360        WinEnableMenuItem( hWndMenu, CM_ZOOM_IN, FALSE );
361        WinEnableMenuItem( hWndMenu, CM_ZOOM_OUT, FALSE );
362        WinEnableControl( hToolBar, TBID_ZOOM, FALSE );
363
364        WinEnableMenuItem( hWndMenu, CM_ROTATE90CW, FALSE );
365        WinEnableMenuItem( hWndMenu, CM_ROTATE90CCW, FALSE );
366        WinEnableMenuItem( hWndMenu, CM_SINGLEPAGE, FALSE );
367        WinEnableMenuItem( hWndMenu, CM_CONTINUOUS, FALSE );
368
369        setOfPages( 0 );
370        return;
371    }
372
373
374    checkNavigationMenus();
375    enableZoomMenus();
376    checkZoomMenus();
377
378    WinEnableMenuItem( hWndMenu, CM_PRINT, TRUE );
379    WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_PRINT), (MPARAM)TRUE );
380    WinEnableMenuItem( hWndMenu, CM_SAVEAS, doc->isSaveable( ev ) );
381    WinEnableMenuItem( hWndMenu, CM_CLOSE, TRUE );
382    setOfPages( doc->getPageCount( ev ) );
383    WinEnableMenuItem( hWndMenu, CM_FONTSINFO, doc->isHaveFontInfo( ev ) );
384    WinEnableMenuItem( hWndMenu, CM_DOCINFO, TRUE );
385
386    BOOL haveText = doc->isHaveText( ev );
387    WinEnableMenuItem( hWndMenu, CM_FIND, haveText );
388    WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_FIND), (MPARAM)haveText );
389    WinEnableMenuItem( hWndMenu, CM_SELECTALL, haveText );
390
391    WinEnableMenuItem( hWndMenu, CM_SINGLEPAGE, TRUE );
392    WinEnableMenuItem( hWndMenu, CM_CONTINUOUS, TRUE );
393}
394
395void Lucide::goToPage( long page )
396{
397    if ( docViewer != NULL ) {
398        docViewer->goToPage( page );
399    }
400}
401
402void Lucide::setZoom( double zoom )
403{
404    if ( docViewer != NULL ) {
405        docViewer->setZoom( zoom );
406        checkZoomMenus();
407    }
408}
409
410void Lucide::setDocument( LuDocument *_doc )
411{
412    docViewer->setDocument( _doc );
413    indexWin->setDocument( _doc );
414    checkMenus( false );
415}
416
417void Lucide::setPageLayout( PgLayout layout )
418{
419    if ( layout == SinglePage ) {
420        WinCheckMenuItem( hWndMenu, CM_SINGLEPAGE, TRUE );
421        WinCheckMenuItem( hWndMenu, CM_CONTINUOUS, FALSE );
422    }
423    else {
424        WinCheckMenuItem( hWndMenu, CM_SINGLEPAGE, FALSE );
425        WinCheckMenuItem( hWndMenu, CM_CONTINUOUS, TRUE );
426    }
427
428    docViewer->setPageLayout( layout );
429}
430
431
432bool Lucide::closeDocument( bool force )
433{
434    if ( doc != NULL ) {
435        if ( !docViewer->close( force ) && !force )
436            return false;
437        delete doc;
438        doc = NULL;
439        WinSetWindowText( hWndFrame, title );
440        checkMenus( false );
441    }
442
443    if ( thumbnailData != NULL ) {
444        writeThumbnail( docFullName );
445        delete thumbnailData;
446        thumbnailData = NULL;
447        thumbnailDataLen = 0;
448    }
449
450    // clear the index
451    indexWin->clear( NULL );
452
453    return true;
454}
455
456void Lucide::loadthread( void* )
457{
458    HAB thab = WinInitialize( 0 );
459    HMQ thmq = WinCreateMsgQueue( thab, 0 );
460
461    docLoaded = doc->loadFile( ev, docFullName, password, &loadErrorCode, &loadError );
462    if ( docLoaded ) {
463        if ( doc->isCreateFileThumbnail( ev ) && isThumbNeeded( docFullName ) ) {
464            loadProgressDlg->setText( getLocalizedString( MSGS_CREATING_THUMBNAIL ).c_str() );
465            createThumbnail( doc );
466        }
467    }
468    loadProgressDlg->hide();
469
470    WinDestroyMsgQueue( thmq );
471    WinTerminate( thab );
472    _endthread();
473}
474
475void Lucide::loadDocument( const char *fn )
476{
477    // test if file supported and then close previous opened document
478    if ( pluginMan->createDocumentForFile( fn, true ) == NULL )
479    {
480        char *msg = newstrdupL( MSGS_NO_SUIT_PLUG );
481        WinMessageBox( HWND_DESKTOP, hWndFrame, msg,
482                       NULL, 0, MB_OK | MB_ICONEXCLAMATION | MB_MOVEABLE );
483        delete msg;
484    }
485    else
486    {
487        if ( !closeDocument() )
488            return;
489
490        doc = pluginMan->createDocumentForFile( fn, false );
491        if ( doc == NULL )
492        {
493            char *msg = newstrdupL( MSGS_NO_SUIT_PLUG );
494            WinMessageBox( HWND_DESKTOP, hWndFrame, msg,
495                           NULL, 0, MB_OK | MB_ICONEXCLAMATION | MB_MOVEABLE );
496            delete msg;
497        }
498        else
499        {
500            _fullpath( docFullName, fn, CCHMAXPATH );
501
502            if ( password != NULL ) {
503                delete password;
504                password = NULL;
505            }
506            bool once = true;
507            while ( once || ( password != NULL ) )
508            {
509                once = false;
510                docLoaded = false;
511                loadError = NULL;
512
513                // Load document asynchronously
514                loadProgressDlg = new ProgressDlg( hWndFrame );
515                char *ldmsg = newstrdupL( MSGS_LOADING_DOCUMENT );
516                loadProgressDlg->setText( ldmsg );
517                delete ldmsg;
518                loadProgressDlg->show( loadthread, NULL ); // doc will be loaded
519                delete loadProgressDlg;
520
521                if ( password != NULL ) {
522                    delete password;
523                    password = NULL;
524                }
525
526                if ( docLoaded )
527                {
528                    char *t = new char[ 2048 ];
529                    char _dr[ _MAX_DRIVE ];
530                    char _di[ _MAX_DIR ];
531                    char _fn[ _MAX_FNAME ];
532                    char _ex[ _MAX_EXT ];
533                    _splitpath( docFullName, _dr, _di, _fn, _ex );
534                    strcpy( docDirName, _dr );
535                    strcat( docDirName, _di );
536                    strcpy( docFileName, _fn );
537                    strcat( docFileName, _ex );
538                    snprintf( t, 2048, "%s - %s", docFileName, title );
539                    WinSetWindowText( hWndFrame, t );
540                    delete t;
541                    recent->addFile( docFullName );
542                    setDocument( doc );
543                }
544                else
545                {
546                    if ( loadErrorCode == LU_LDERR_NO_ERROR )
547                    {
548                        char *m = newstrdupL( MSGS_FILE_LOAD_ERROR );
549                        WinMessageBox( HWND_DESKTOP, hWndFrame, m,
550                                       NULL, 0, MB_OK | MB_ICONEXCLAMATION | MB_MOVEABLE );
551                        delete m;
552                    }
553                    else
554                    {
555                        std::string msgTempl = getLocalizedString( MSGS_LDERR );
556
557                        const int errmsgLen = 1024;
558                        char *errmsg = new char[ errmsgLen ];
559                        memset( errmsg, 0, errmsgLen );
560
561                        if ( loadErrorCode == LU_LDERR_CUSTOM )
562                        {
563                            snprintf( errmsg, errmsgLen, msgTempl.c_str(), loadError );
564                            SOMFree( loadError );
565                        }
566                        else
567                        {
568                            const char *lmsg = NULL;
569                            switch ( loadErrorCode )
570                            {
571                                case LU_LDERR_OUT_OF_MEMORY:
572                                    lmsg = MSGS_LDERR_OUT_OF_MEMORY;
573                                    break;
574                                case LU_LDERR_OPEN_ERROR:
575                                    lmsg = MSGS_LDERR_OPEN_ERROR;
576                                    break;
577                                case LU_LDERR_READ_ERROR:
578                                    lmsg = MSGS_LDERR_READ_ERROR;
579                                    break;
580                                case LU_LDERR_DAMAGED:
581                                    lmsg = MSGS_LDERR_DAMAGED;
582                                    break;
583                                case LU_LDERR_WRONG_FORMAT:
584                                    lmsg = MSGS_LDERR_WRONG_FORMAT;
585                                    break;
586                                case LU_LDERR_ENCRYPTED:
587                                    {
588                                        lmsg = MSGS_LDERR_ENCRYPTED;
589
590                                        PasswordDlg *pd = new PasswordDlg( hWndFrame );
591                                        if ( pd->showDialog() == DID_OK ) {
592                                            password = newstrdup( pd->getPassword() );
593                                        }
594                                        delete pd;
595                                    }
596                                    break;
597                            }
598
599                            if ( lmsg != NULL ) {
600                                snprintf( errmsg, errmsgLen, msgTempl.c_str(),
601                                          getLocalizedString( lmsg ).c_str() );
602                            }
603                        }
604
605                        if ( password == NULL )
606                        {
607                            WinMessageBox( HWND_DESKTOP, hWndFrame, errmsg, NULL, 0,
608                                           MB_OK | MB_ICONEXCLAMATION | MB_MOVEABLE );
609                        }
610                        delete errmsg;
611                    } // ( loadErrorCode == LU_LDERR_NO_ERROR )
612
613                    if ( password == NULL ) {
614                        delete doc;
615                        doc = NULL;
616                    }
617                } // ( docLoaded )
618            } // while ( once || ( password != NULL ) )
619        } // ( doc == NULL )
620    } // ( pluginMan->createDocumentForFile( fn, true ) == NULL )
621
622    loadFileList();
623}
624
625void Lucide::readMask( const char *mask )
626{
627    char *buf = new char[ CCHMAXPATH ];
628    strcpy( buf, docFullName );
629    char *r = buf + strlen( buf );
630    while ( r >= buf && *r != '\\' && *r != '/')
631        --r;
632    if ( r >= buf )
633    {
634        *( r + 1 ) = 0;
635        strcat( buf, mask );
636
637        find_t ffblk;
638        unsigned done = _dos_findfirst( buf, _A_RDONLY | _A_NORMAL, &ffblk );
639        while ( done == 0 )
640        {
641            fileList.push_back( find_t_name( ffblk ) );
642            done = _dos_findnext( &ffblk );
643        }
644        _dos_findclose( &ffblk );
645
646    }
647    delete buf;
648}
649
650// comparison, not case sensitive.
651bool compare_nocase( const std::string &first, const std::string &second)
652{
653    // note: stricmp is locale aware in kLIBC
654    return stricmp( first.c_str(), second.c_str() ) < 0;
655}
656
657void Lucide::loadFileList()
658{
659    fileList.clear();
660
661    char *exts = newstrdup( pluginMan->getExtsMask().c_str() );
662
663    char *p = strtok( exts, ";" );
664    while ( p != NULL )
665    {
666        readMask( p );
667        p = strtok( NULL, ";" );
668    }
669    delete exts;
670
671    std::sort( fileList.begin(), fileList.end(), compare_nocase );
672    fileListIterator = std::find( fileList.begin(), fileList.end(), docFileName );
673}
674
675void Lucide::openDocument()
676{
677    PFILEDLG fd = new FILEDLG;
678    memset( fd, 0, sizeof( FILEDLG ) );
679    fd->cbSize = sizeof( FILEDLG );
680    fd->fl = FDS_CENTER | FDS_OPEN_DIALOG;
681    PrfQueryProfileString( HINI_USERPROFILE, appName, prfLvd, "",
682                           fd->szFullFile, sizeof( fd->szFullFile ) );
683    LcdFileDlg( HWND_DESKTOP, hWndFrame, fd );
684    if ( fd->lReturn == DID_OK )
685    {
686        char drv[ _MAX_DRIVE ] = "";
687        char dir[ _MAX_PATH ] = "";
688        char buf[ _MAX_PATH ] = "";
689        _splitpath( fd->szFullFile, drv, dir, NULL, NULL );
690        _makepath( buf, drv, dir, NULL, NULL );
691        PrfWriteProfileString( HINI_USERPROFILE, appName, prfLvd, buf );
692
693        loadDocument( fd->szFullFile );
694    }
695    delete fd;
696}
697
698bool Lucide::saveDocumentAs()
699{
700    bool saved = false;
701
702    char dirbuf[ CCHMAXPATH ];
703    PFILEDLG fd = new FILEDLG;
704    memset( fd, 0, sizeof( FILEDLG ) );
705    fd->cbSize = sizeof( FILEDLG );
706    fd->fl = FDS_CENTER | FDS_SAVEAS_DIALOG;
707    PrfQueryProfileString( HINI_USERPROFILE, appName, prfLvd, "",
708                           dirbuf, sizeof( dirbuf ) );
709    char fil[ _MAX_FNAME ] = "";
710    char ext[ _MAX_EXT ] = "";
711    _splitpath( docFullName, NULL, NULL, fil, ext );
712    char filcopy[ _MAX_FNAME ] = "";
713    snprintf( filcopy, sizeof( filcopy ),
714              getLocalizedString( MSGS_FILE_COPY_SUFFIX ).c_str(), fil );
715    snprintf( fd->szFullFile, sizeof( fd->szFullFile ),
716              "%s%s%s", dirbuf, filcopy, ext );
717    WinFileDlg( HWND_DESKTOP, hWndFrame, fd );
718    if ( fd->lReturn == DID_OK )
719    {
720        bool doSave = true;
721        if ( access( fd->szFullFile, F_OK ) == 0 )
722        {
723            char *t = newstrdupL( MSGS_WARNING );
724            char *m = newstrdupL( MSGS_OVERWRITE_FILE );
725            ULONG response = WinMessageBox( HWND_DESKTOP, hWndFrame, m, t,
726                                            0, MB_YESNO | MB_WARNING | MB_MOVEABLE );
727            delete m;
728            delete t;
729
730            doSave = ( response == MBID_YES );
731        }
732        if ( doSave )
733        {
734            // @todo poppler has troubles saving to the same file name
735            // (some locking issues) so forbid it for now
736            if ( ( saved = false, stricmp( docFullName, fd->szFullFile ) == 0 ) ||
737                 !( saved = doc->saveAs( ev, fd->szFullFile ) ) )
738            {
739                char *m = newstrdupL( MSGS_FILE_SAVE_ERROR );
740                WinMessageBox( HWND_DESKTOP, hWndFrame, m, NULL,
741                               0, MB_OK | MB_ERROR | MB_MOVEABLE );
742                delete m;
743            }
744            else
745            {
746                if ( stricmp( docFullName, fd->szFullFile ) == 0 )
747                    docViewer->resetModifiedState();
748            }
749        }
750    }
751    delete fd;
752
753    return saved;
754}
755
756void Lucide::checkNavpane()
757{
758    if ( Lucide::showIndex ) {
759        WinCheckMenuItem( hWndMenu, CM_NAVPANE, TRUE );
760        WinSendMsg( hToolBar, TBM_SETCHECK, MPFROMSHORT( CM_NAVPANE ), (MPARAM)TRUE );
761    }
762    else {
763        WinCheckMenuItem( hWndMenu, CM_NAVPANE, FALSE );
764        WinSendMsg( hToolBar, TBM_SETCHECK, MPFROMSHORT( CM_NAVPANE ), (MPARAM)FALSE );
765    }
766}
767
768
769void Lucide::toggleFullscreenEx( bool presentation, bool atStartup )
770{
771    enum TriState { NoChange, On, Off };
772    TriState fullscreenState = NoChange;
773    TriState presentationState = NoChange;
774
775    if ( !presentation )
776    {
777        // fullscreen command issued
778        if ( !isFullscreen )
779        {
780            if ( isPresentation ) {
781                presentationState = Off;
782                isPresentation = false;
783            } else {
784                fullscreenState = On;
785            }
786            isFullscreen = true;
787        }
788        else
789        {
790            if ( isPresentation ) {
791                presentationState = Off;
792                isPresentation = false;
793            } else {
794                fullscreenState = Off;
795                isFullscreen = false;
796            }
797        }
798    }
799    else
800    {
801        // presentation command issued
802        if ( !isPresentation )
803        {
804            presentationState = On;
805            if ( !isFullscreen )
806                fullscreenState = On;
807        }
808        else
809        {
810            presentationState = Off;
811            if ( !isFullscreen )
812                fullscreenState = Off;
813        }
814
815        isPresentation = !isPresentation;
816    }
817
818    ULONG ulFrameStyle = WinQueryWindowULong( hWndFrame, QWL_STYLE );
819
820    if ( presentationState == Off )
821    {
822        docViewer->setPresentation( false );
823        WinSetParent( hWndMenu, hWndFrame, FALSE );
824    }
825    else if ( presentationState == On )
826    {
827        docViewer->setPresentation( true );
828        WinSetParent( hWndMenu, HWND_OBJECT, FALSE );
829    }
830
831    if ( fullscreenState == Off )
832    {
833        WinSetParent( hFrameSysmenu,  hWndFrame, FALSE );
834        WinSetParent( hFrameTitlebar, hWndFrame, FALSE );
835        WinSetParent( hFrameMinMax,   hWndFrame, FALSE );
836        ulFrameStyle |= FS_SIZEBORDER;
837
838        // PM does not synchronize the title bar hilite state when it is added
839        // to the frame window. Do it ourselves
840        BOOL active = WinQueryActiveWindow( HWND_DESKTOP ) == hWndFrame;
841        WinSendMsg( hFrameTitlebar, TBM_SETHILITE,
842                    MPFROMSHORT( active ), MPVOID );
843
844        // reset the fullscreen menu check
845        WinCheckMenuItem( hWndMenu, CM_FULLSCREEN, FALSE );
846        WinSendMsg( hToolBar, TBM_SETCHECK, MPFROMSHORT( CM_FULLSCREEN ), (MPARAM)FALSE );
847
848    }
849    else if ( fullscreenState == On )
850    {
851        if ( !atStartup )
852        {
853            WinQueryWindowPos( hWndFrame, &winPos.Swp );
854            winPos.XRestore  = WinQueryWindowUShort( hWndFrame, QWS_XRESTORE );
855            winPos.YRestore  = WinQueryWindowUShort( hWndFrame, QWS_YRESTORE );
856            winPos.CXRestore = WinQueryWindowUShort( hWndFrame, QWS_CXRESTORE );
857            winPos.CYRestore = WinQueryWindowUShort( hWndFrame, QWS_CYRESTORE );
858            winPos.XMinimize = WinQueryWindowUShort( hWndFrame, QWS_XMINIMIZE );
859            winPos.YMinimize = WinQueryWindowUShort( hWndFrame, QWS_YMINIMIZE );
860        }
861
862        // set the fullscreen menu check
863        WinCheckMenuItem( hWndMenu, CM_FULLSCREEN, TRUE );
864        WinSendMsg( hToolBar, TBM_SETCHECK, MPFROMSHORT( CM_FULLSCREEN ), (MPARAM)TRUE );
865
866        WinSetParent( hFrameSysmenu,  HWND_OBJECT, FALSE );
867        WinSetParent( hFrameTitlebar, HWND_OBJECT, FALSE );
868        WinSetParent( hFrameMinMax,   HWND_OBJECT, FALSE );
869        ulFrameStyle &= ~FS_SIZEBORDER;
870    }
871
872    if ( fullscreenState != NoChange || presentationState != NoChange )
873    {
874        WinSetWindowULong( hWndFrame, QWL_STYLE, ulFrameStyle );
875        WinSendMsg( hWndFrame, WM_UPDATEFRAME, MPVOID, MPVOID );
876    }
877
878    if ( presentationState == Off )
879    {
880        WinSendMsg( hVertSplitter, SBM_SETSPLITTERSIZE, MPFROMSHORT( -1 ), MPVOID );
881        WinSendMsg( hVertSplitter, SBM_SETSPLITTERPOS,
882                    MPFROMSHORT( Lucide::showIndex ? Lucide::splitterPos : 0 ), MPVOID );
883        WinSendMsg( hHorizSplitter, SBM_SETFIXEDSIZE,
884            MPFROMSHORT( DEFAULT_PICTSIZE + TOOLBAR_HEIGHT_ADD ), MPVOID );
885
886        // reset the presentation menu check
887        WinCheckMenuItem( hWndMenu, CM_PRESENTATION, FALSE );
888        WinSendMsg( hToolBar, TBM_SETCHECK, MPFROMSHORT( CM_PRESENTATION ), (MPARAM)FALSE );
889
890    }
891    else if ( presentationState == On )
892    {
893        WinSendMsg( hHorizSplitter, SBM_SETSPLITTERPOS, 0, MPVOID );
894        WinSendMsg( hVertSplitter, SBM_SETSPLITTERPOS, 0, MPVOID );
895        WinSendMsg( hVertSplitter, SBM_SETSPLITTERSIZE, 0, MPVOID );
896
897        // set the presentation menu check
898        WinCheckMenuItem( hWndMenu, CM_PRESENTATION, TRUE );
899        WinSendMsg( hToolBar, TBM_SETCHECK, MPFROMSHORT( CM_PRESENTATION ), (MPARAM)TRUE );
900    }
901
902    if ( fullscreenState == Off )
903    {
904        WinSetWindowUShort( hWndFrame, QWS_XRESTORE,  winPos.XRestore );
905        WinSetWindowUShort( hWndFrame, QWS_YRESTORE,  winPos.YRestore );
906        WinSetWindowUShort( hWndFrame, QWS_CXRESTORE, winPos.CXRestore );
907        WinSetWindowUShort( hWndFrame, QWS_CYRESTORE, winPos.CYRestore );
908        WinSetWindowUShort( hWndFrame, QWS_XMINIMIZE, winPos.XMinimize );
909        WinSetWindowUShort( hWndFrame, QWS_YMINIMIZE, winPos.YMinimize );
910        WinSetWindowPos( hWndFrame, NULLHANDLE,
911                         winPos.Swp.x, winPos.Swp.y, winPos.Swp.cx, winPos.Swp.cy,
912                         SWP_SIZE | SWP_MOVE | SWP_SHOW );
913    }
914    else if ( fullscreenState == On )
915    {
916        WinSetWindowPos( hWndFrame, NULLHANDLE, 0, 0,
917                         WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN ),
918                         WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ),
919                         SWP_SIZE | SWP_MOVE | SWP_SHOW );
920    }
921}
922
923
924void Lucide::focusDocview()
925{
926    WinSetFocus( HWND_DESKTOP, docViewer->getViewHWND() );
927}
928
929void Lucide::focusIndex()
930{
931    WinSetFocus( HWND_DESKTOP, indexWin->getIndexHWND() );
932}
933
934void Lucide::cmdSwitchWindow()
935{
936    if ( activeWindow == AwIndex ) {
937        focusDocview();
938    } else {
939        focusIndex();
940    }
941}
942
943void Lucide::toggleZoom()
944{
945    if ( ( doc != NULL ) && doc->isScalable( ev ) )
946    {
947        bool isZoom = !docViewer->isZoomMode();
948        WinSendMsg( hToolBar, TBM_SETCHECK, MPFROMSHORT( CM_ZOOM_IN_OUT ), (MPARAM)isZoom );
949        docViewer->setZoomMode( isZoom );
950    }
951}
952
953void Lucide::cmdMinimize()
954{
955    if ( isFullscreen ) {
956        toggleFullscreen();
957    }
958    WinSetWindowPos( hWndFrame, HWND_TOP, 0, 0, 0, 0, SWP_MINIMIZE );
959}
960
961void Lucide::cmdSwitchToPresentation()
962{
963    if ( !isPresentation )
964    {
965        SWP pos = {0};
966        WinQueryWindowPos( hWndFrame, &pos );
967
968        if ( pos.fl & SWP_MINIMIZE ) {
969            WinSetWindowPos( hWndFrame, HWND_TOP, 0, 0, 0, 0,
970                    SWP_SHOW | SWP_ACTIVATE | SWP_RESTORE | SWP_ZORDER );
971        }
972        togglePresentation();
973    }
974}
975
976void Lucide::newWindow( char *file, bool addDir )
977{
978    char *param = NULL;
979
980    if ( file != NULL )
981    {
982        if ( addDir )
983        {
984            param = new char[ CCHMAXPATH ];
985            strcpy( param, docFullName );
986            char *lastSlash = strrchr( param, '\\' );
987            if ( lastSlash != NULL ) {
988                *( lastSlash + 1 ) = 0;
989            }
990            strcat( param, file );
991        }
992        else {
993            param = newstrdup( file );
994        }
995    }
996
997#if defined(__WATCOM__)
998    const char *execname = __argv[0];
999#else
1000    char execname[ _MAX_PATH ];
1001    _execname( execname, sizeof(execname) );
1002#endif
1003
1004    PROGDETAILS pd;
1005    pd.Length                      = sizeof( PROGDETAILS );
1006    pd.progt.progc                 = PROG_DEFAULT;
1007    pd.progt.fbVisible             = SHE_VISIBLE;
1008    pd.pszTitle                    = NULL;
1009    pd.pszExecutable               = execname;
1010    pd.pszParameters               = NULL;
1011    pd.pszStartupDir               = NULL;
1012    pd.pszIcon                     = NULL;
1013    pd.pszEnvironment              = NULL;
1014    pd.swpInitial.fl               = SWP_ACTIVATE;
1015    pd.swpInitial.cy               = 0;
1016    pd.swpInitial.cx               = 0;
1017    pd.swpInitial.y                = 0;
1018    pd.swpInitial.x                = 0;
1019    pd.swpInitial.hwndInsertBehind = HWND_TOP;
1020    pd.swpInitial.hwnd             = NULLHANDLE;
1021    pd.swpInitial.ulReserved1      = 0;
1022    pd.swpInitial.ulReserved2      = 0;
1023
1024    WinStartApp( NULLHANDLE, &pd, param, NULL, 0 );
1025
1026    delete param;
1027}
1028
1029void Lucide::gotoFile( FileList file )
1030{
1031    if ( fileList.size() == 0 ) {
1032        return;
1033    }
1034
1035    if ( fileListIterator == fileList.end() ) {
1036        // If viewed file extension not in supported extensions
1037        //   list - fileListIterator will equal fileList.end()
1038        fileListIterator = fileList.begin();
1039    }
1040
1041    if ( file == ListFirst ) {
1042        fileListIterator = fileList.begin();
1043    }
1044    else if ( file == ListPrevious )
1045    {
1046        if ( fileListIterator == fileList.begin() ) {
1047            fileListIterator = fileList.end();
1048        }
1049        fileListIterator--;
1050    }
1051    else if ( file == ListNext )
1052    {
1053        fileListIterator++;
1054        if ( fileListIterator == fileList.end() ) {
1055            fileListIterator = fileList.begin();
1056        }
1057    }
1058    else if ( file == ListLast ) {
1059        fileListIterator = fileList.end();
1060        fileListIterator--;
1061    }
1062
1063    std::string fname = *fileListIterator;
1064    char *fn = new char[ CCHMAXPATH ];
1065    strcpy( fn, docDirName );
1066    strcat( fn, fname.c_str() );
1067
1068    loadDocument( fn );
1069    delete fn;
1070}
1071
1072void Lucide::savePosition()
1073{
1074    if ( !WinIsWindow( hab, hWndFrame ) )
1075        return;
1076
1077    char valbuf[ 3 ] = "";
1078    PrfWriteProfileString( HINI_USERPROFILE, appName, prfSplpos,
1079                           itoa( Lucide::splitterPos, valbuf, 10 ) );
1080    PrfWriteProfileString( HINI_USERPROFILE, appName, prfShowind,
1081                           itoa( Lucide::showIndex, valbuf, 10 ) );
1082
1083    if ( isFullscreen )
1084        PrfWriteProfileString( HINI_USERPROFILE, appName, prfFullscreen, "1" );
1085    else
1086        PrfWriteProfileString( HINI_USERPROFILE, appName, prfFullscreen, NULL );
1087
1088    if ( isPresentation )
1089        PrfWriteProfileString( HINI_USERPROFILE, appName, prfPresentation, "1" );
1090    else
1091        PrfWriteProfileString( HINI_USERPROFILE, appName, prfPresentation, NULL );
1092
1093    if ( !isFullscreen && !isPresentation ) {
1094        WinQueryWindowPos( hWndFrame, &winPos.Swp );
1095        winPos.XRestore  = WinQueryWindowUShort( hWndFrame, QWS_XRESTORE );
1096        winPos.YRestore  = WinQueryWindowUShort( hWndFrame, QWS_YRESTORE );
1097        winPos.CXRestore = WinQueryWindowUShort( hWndFrame, QWS_CXRESTORE );
1098        winPos.CYRestore = WinQueryWindowUShort( hWndFrame, QWS_CYRESTORE );
1099        winPos.XMinimize = WinQueryWindowUShort( hWndFrame, QWS_XMINIMIZE );
1100        winPos.YMinimize = WinQueryWindowUShort( hWndFrame, QWS_YMINIMIZE );
1101    }
1102
1103    PrfWriteProfileData( HINI_USERPROFILE, appName, prfFwp, &winPos, sizeof( winPos ) );
1104}
1105
1106void Lucide::restorePosition()
1107{
1108    splitterPos = PrfQueryProfileInt( HINI_USERPROFILE, appName, prfSplpos,
1109                                      Lucide::splitterPos );
1110    showIndex = PrfQueryProfileInt( HINI_USERPROFILE, appName, prfShowind,
1111                                    Lucide::showIndex );
1112
1113    WinSendMsg( hVertSplitter, SBM_SETSPLITTERPOS,
1114                MPFROMSHORT( showIndex ? splitterPos : 0 ), MPVOID );
1115
1116    bool fullscreen = PrfQueryProfileInt( HINI_USERPROFILE, appName,
1117                                          prfFullscreen, 0 ) == 1;
1118    bool presentation = PrfQueryProfileInt( HINI_USERPROFILE, appName,
1119                                            prfPresentation, 0 ) == 1;
1120
1121    LONG sx, sy;
1122    sx = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN );
1123    sy = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN );
1124
1125    ULONG SwpOptions = SWP_MOVE | SWP_SIZE | SWP_ACTIVATE | SWP_SHOW;
1126    bool atStartup = true;
1127
1128    ULONG ulWpSize = sizeof( winPos );
1129    if ( PrfQueryProfileData( HINI_USERPROFILE, appName, prfFwp, &winPos, &ulWpSize ) )
1130    {
1131        if ( winPos.Swp.fl & SWP_MAXIMIZE ) {
1132            SwpOptions |= SWP_MAXIMIZE;
1133        }
1134        else if ( winPos.Swp.fl & SWP_MINIMIZE ) {
1135            SwpOptions |= SWP_MINIMIZE;
1136        }
1137
1138        LONG sx, sy;
1139        sx = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN );
1140        sy = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN );
1141
1142        if ( winPos.Swp.x > sx ) {
1143            winPos.Swp.x = sx - winPos.Swp.cx;
1144        }
1145        if ( winPos.Swp.y > sy ) {
1146            winPos.Swp.y = sy - winPos.Swp.cy;
1147        }
1148
1149        // Just a note: the FID_CLIENT window is only resized by WinSetWindowPos()
1150        // on the frame if the size is actually changed *and* the SWP_SHOW flag
1151        // is present (PM bug?). Therefore, when the saved normal size the same
1152        // as fullscreen and we should go fullscreen at startup, WinSetWindowPos()
1153        // issued from toggleFullscreenEx() will not resize FID_CLIENT even
1154        // though it will contain SWP_SHOW
1155
1156        if ( !fullscreen && !presentation ) {
1157            // only set the normal size if no if fullscreen or presentation is
1158            // requested, to avoid flicker. We could also avoid flicker by
1159            // omitting SWP_SHOW but see the note above
1160            WinSetWindowPos( hWndFrame, NULLHANDLE,
1161                             winPos.Swp.x, winPos.Swp.y, winPos.Swp.cx, winPos.Swp.cy,
1162                             SwpOptions );
1163        }
1164
1165        WinSetWindowUShort( hWndFrame, QWS_XRESTORE,  winPos.XRestore );
1166        WinSetWindowUShort( hWndFrame, QWS_YRESTORE,  winPos.YRestore );
1167        WinSetWindowUShort( hWndFrame, QWS_CXRESTORE, winPos.CXRestore );
1168        WinSetWindowUShort( hWndFrame, QWS_CYRESTORE, winPos.CYRestore );
1169        WinSetWindowUShort( hWndFrame, QWS_XMINIMIZE, winPos.XMinimize );
1170        WinSetWindowUShort( hWndFrame, QWS_YMINIMIZE, winPos.YMinimize );
1171
1172        // we don't the app to be minimized at startup
1173        if ( SwpOptions & SWP_MINIMIZE )
1174            WinSetWindowPos( hWndFrame, NULLHANDLE, 0, 0, 0, 0, SWP_RESTORE );
1175    }
1176    else
1177    {
1178        typedef
1179        BOOL ( APIENTRY *WinQueryDesktopWorkArea_T ) ( HWND hwndDesktop,
1180                                                       PRECTL pwrcWorkArea );
1181        static WinQueryDesktopWorkArea_T WinQueryDesktopWorkArea =
1182            (WinQueryDesktopWorkArea_T) ~0;
1183
1184        if ( (ULONG) WinQueryDesktopWorkArea == (ULONG) ~0 ) {
1185            if ( my_DosQueryProcAddr( "PMMERGE", 5469,
1186                                      (PFN *) &WinQueryDesktopWorkArea ) )
1187                WinQueryDesktopWorkArea = NULL;
1188        }
1189
1190        SWP swp;
1191        RECTL rcl;
1192        if ( WinQueryDesktopWorkArea &&
1193             WinQueryDesktopWorkArea( HWND_DESKTOP, &rcl ) ) {
1194            swp.x = rcl.xLeft;
1195            swp.y = rcl.yBottom;
1196            swp.cx = rcl.xRight - rcl.xLeft;
1197            swp.cy = rcl.yTop - rcl.yBottom;
1198        } else {
1199            swp.x = 0;
1200            swp.y = 0;
1201            swp.cx = sx;
1202            swp.cy = sy;
1203        }
1204
1205        swp.x += 16;
1206        swp.y += 16;
1207        swp.cx -= 32;
1208        swp.cy -= 32;
1209
1210        WinSetWindowPos( hWndFrame, NULLHANDLE, swp.x, swp.y, swp.cx, swp.cy,
1211                         SwpOptions );
1212
1213        // we don't initialize winPos here so reset atStartup to let
1214        // toggleFullscreenEx() do this
1215        atStartup = false;
1216    }
1217
1218    if ( fullscreen )
1219    {
1220        toggleFullscreenEx( false, atStartup );
1221        isFullscreen = fullscreen;
1222    }
1223    else if ( presentation )
1224    {
1225        toggleFullscreenEx( true, atStartup );
1226    }
1227}
1228
1229static MRESULT EXPENTRY frameProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
1230{
1231    switch ( msg )
1232    {
1233        case WM_TRANSLATEACCEL:
1234        {
1235            // change the accel logic by first letting the focus window process
1236            // WM_CHAR and only translate it to accel if not handled (this makes
1237            // sure that keyboard shortcuts in input fields work even if we
1238            // defined our own accelerators from these shortcuts). Make an
1239            // exception for VK_TAB since it's always eaten by the standard
1240            // window procedure and therefore the accel table will never be
1241            // called
1242            PQMSG pqmsg = (PQMSG)mp1;
1243            if ( !( SHORT1FROMMP( pqmsg->mp1 ) & KC_VIRTUALKEY ) ||
1244                 !( SHORT2FROMMP( pqmsg->mp2 ) == VK_TAB ) )
1245            {
1246                HWND focus = WinQueryFocus( HWND_DESKTOP );
1247                if ( focus == pqmsg->hwnd && focus != hwnd ) {
1248                    if ( WinDispatchMsg( hab, pqmsg ) ) {
1249                        pqmsg->msg = WM_NULL;
1250                        return (MRESULT)TRUE;
1251                    }
1252                }
1253            }
1254            // in presentation mode, we hide the menu which effectively makes
1255            // all disabled items work through accelerators which is completely
1256            // unexpected. Fix it by translating accels manually and checking
1257            // if they are disabled in the hidden menu
1258            if ( WinTranslateAccel( hab, hwnd, WinQueryAccelTable( hab, hwnd ),
1259                                    pqmsg ) )
1260            {
1261                if ( pqmsg->msg == WM_COMMAND ) {
1262                    SHORT cm = SHORT1FROMMP(pqmsg->mp1);
1263                    if ( !WinIsMenuItemEnabled( hWndMenu, cm ) )
1264                        pqmsg->msg = WM_NULL;
1265                }
1266                return (MRESULT)TRUE;
1267            }
1268            return (MRESULT)FALSE;
1269        }
1270
1271        case WM_SYSCOMMAND:
1272        {
1273            if ( SHORT1FROMMP(mp1) == SC_CLOSE ) {
1274                // the system menu is disabled in fullscreen/presentation mode
1275                // but we still want to exit with Alt-F4 so always handle it here
1276                WinPostMsg( hWndFrame, WM_CLOSE, NULL, NULL );
1277                return (MRESULT)FALSE;
1278            }
1279        }
1280        break;
1281    }
1282
1283    return pOldFrameProc( hwnd, msg, mp1, mp2 );
1284}
1285
1286static MRESULT EXPENTRY splProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
1287{
1288    switch ( msg )
1289    {
1290        case WM_CONTROL:
1291        {
1292            if ( ( SHORT1FROMMP( mp1 ) == ID_SPLITTER ) &&
1293                 ( SHORT2FROMMP( mp1 ) == SBN_POSITIONCHANGED ) )
1294            {
1295                SHORT pos = SHORT1FROMMP( mp2 );
1296                if ( pos > 0 ) {
1297                    Lucide::splitterPos = pos;
1298                    Lucide::showIndex = true;
1299                }
1300                else {
1301                    Lucide::showIndex = false;
1302                }
1303                Lucide::checkNavpane();
1304            }
1305        }
1306        break;
1307
1308        case WM_COMMAND:
1309        {
1310            switch ( SHORT1FROMMP(mp1) )
1311            {
1312                case CM_NEW_WINDOW:
1313                    Lucide::newWindow( NULL, false );
1314                    return (MRESULT)FALSE;
1315
1316                case CM_OPEN:
1317                    Lucide::openDocument();
1318                    return (MRESULT)FALSE;
1319
1320                case CM_FILEFIRST:
1321                    Lucide::gotoFile( ListFirst );
1322                    return (MRESULT)FALSE;
1323
1324                case CM_FILEPREVIOUS:
1325                    Lucide::gotoFile( ListPrevious );
1326                    return (MRESULT)FALSE;
1327
1328                case CM_FILENEXT:
1329                    Lucide::gotoFile( ListNext );
1330                    return (MRESULT)FALSE;
1331
1332                case CM_FILELAST:
1333                    Lucide::gotoFile( ListLast );
1334                    return (MRESULT)FALSE;
1335
1336                case CM_RECENT + 1:
1337                case CM_RECENT + 2:
1338                case CM_RECENT + 3:
1339                case CM_RECENT + 4:
1340                case CM_RECENT + 5:
1341                case CM_RECENT + 6:
1342                case CM_RECENT + 7:
1343                case CM_RECENT + 8:
1344                case CM_RECENT + 9:
1345                {
1346                    std::string f = recent->getFile( SHORT1FROMMP(mp1) );
1347                    Lucide::loadDocument( f.c_str() );
1348                    return (MRESULT)FALSE;
1349                }
1350
1351                case CM_RECENTCLEAR:
1352                    recent->clear();
1353                    return (MRESULT)FALSE;
1354
1355                case CM_SAVEAS:
1356                    Lucide::saveDocumentAs();
1357                    return (MRESULT)FALSE;
1358
1359                case CM_CLOSE:
1360                    Lucide::closeDocument();
1361                    return (MRESULT)FALSE;
1362
1363                case CM_PRINT:
1364                {
1365                    PrintDlg *d = new PrintDlg( hWndFrame, doc, Lucide::docFileName,
1366                                                docViewer->getCurrentPage() + 1 );
1367                    if ( d->showDialog() == DID_OK )
1368                    {
1369                        // print
1370                        PrintSetup *p = new PrintSetup;
1371                        memset( p, 0, sizeof( PrintSetup ) );
1372                        d->getPrintSetup( p );
1373                        printDocument( hWndFrame, doc, Lucide::docFileName, p );
1374                        delete p;
1375                    }
1376                    delete d;
1377                    return (MRESULT)FALSE;
1378                }
1379
1380                case CM_EXIT:
1381                    WinPostMsg( hWndFrame, WM_CLOSE, NULL, NULL );
1382                    return (MRESULT)FALSE;
1383
1384                case CM_DOCINFO:
1385                {
1386                    LuDocumentInfo *dinfo = doc->getDocumentInfo( ev );
1387                    DocInfoDlg *d = new DocInfoDlg( hWndFrame, dinfo );
1388                    d->doDialog();
1389                    LuDocument::freeDocumentInfo( ev, dinfo );
1390                    return (MRESULT)FALSE;
1391                }
1392
1393                case CM_FONTSINFO:
1394                {
1395                    FontsInfoDlg *d = new FontsInfoDlg( hWndFrame, doc );
1396                    d->doDialog();
1397                    return (MRESULT)FALSE;
1398                }
1399
1400                case CM_PLUGINSLIST:
1401                {
1402                    PluginViewDlg *d = new PluginViewDlg( hWndFrame,
1403                                                pluginMan->getPluginsList() );
1404                    d->doDialog();
1405                    return (MRESULT)FALSE;
1406                }
1407
1408                case CM_COPY:
1409                    docViewer->copyToClipbrd();
1410                    return (MRESULT)FALSE;
1411
1412                case CM_SELECTALL:
1413                    docViewer->selectAll();
1414                    return (MRESULT)FALSE;
1415
1416                case CM_FIND:
1417                    if ( findDlg->showDialog() == DID_OK ) {
1418                        if ( strlen( findDlg->getSearchString() ) > 0 )
1419                        {
1420                            docViewer->searchDocument( findDlg->getSearchString(),
1421                                            findDlg->isCaseSensitive(), false, findDlg->doFindBack() );
1422
1423                            WinEnableMenuItem( hWndMenu, CM_FINDAGAIN, TRUE );
1424                            WinSendMsg( hToolBar, TBM_ENABLEITEM, MPFROMSHORT(CM_FINDAGAIN), (MPARAM)TRUE );
1425                        }
1426                    }
1427                    return (MRESULT)FALSE;
1428
1429                case CM_FINDAGAIN:
1430                    docViewer->searchDocument( findDlg->getSearchString(),
1431                                               findDlg->isCaseSensitive(), true, findDlg->doFindBack() );
1432                    return (MRESULT)FALSE;
1433
1434                case CM_SETTINGS:
1435                {
1436                    SettingsDlg *d = new SettingsDlg( hWndFrame, settings );
1437                    d->doDialog();
1438                    return (MRESULT)FALSE;
1439                }
1440
1441                case CM_FIRSTPAGE:
1442                    Lucide::goToPage( 0 );
1443                    return (MRESULT)FALSE;
1444
1445                case CM_NEXTPAGE:
1446                    Lucide::goToPage( docViewer->getCurrentPage() + 1 );
1447                    return (MRESULT)FALSE;
1448
1449                case CM_PREVPAGE:
1450                    Lucide::goToPage( docViewer->getCurrentPage() - 1 );
1451                    return (MRESULT)FALSE;
1452
1453                case CM_LASTPAGE:
1454                    Lucide::goToPage( doc->getPageCount( ev ) - 1 );
1455                    return (MRESULT)FALSE;
1456
1457                case CM_GOTOPAGE:
1458                {
1459                    GotoDlg *d = new GotoDlg( hWndFrame, doc->getPageCount( ev ),
1460                                                docViewer->getCurrentPage() + 1 );
1461                    if ( d->showDialog() == DID_OK ) {
1462                        long pg = d->getPage();
1463                        if ( pg > 0 ) {
1464                            Lucide::goToPage( pg - 1 );
1465                        }
1466                    }
1467                    delete d;
1468                    return (MRESULT)FALSE;
1469                }
1470
1471                case CM_FITWINDOW:
1472                    Lucide::setZoom( -2 );
1473                    return (MRESULT)FALSE;
1474
1475                case CM_ACTSIZE:
1476                    Lucide::setZoom( 1 );
1477                    return (MRESULT)FALSE;
1478
1479                case CM_FITWIDTH:
1480                    Lucide::setZoom( -1 );
1481                    return (MRESULT)FALSE;
1482
1483                case CM_ZOOM_IN_OUT:
1484                    Lucide::toggleZoom();
1485                    return (MRESULT)FALSE;
1486
1487                case CM_ZOOM_IN:
1488                    docViewer->zoomInOut( true );
1489                    return (MRESULT)FALSE;
1490
1491                case CM_ZOOM_OUT:
1492                    docViewer->zoomInOut( false );
1493                    return (MRESULT)FALSE;
1494
1495                case CM_SINGLEPAGE:
1496                    Lucide::setPageLayout( SinglePage );
1497                    return (MRESULT)FALSE;
1498
1499                case CM_CONTINUOUS:
1500                    Lucide::setPageLayout( Continuous );
1501                    return (MRESULT)FALSE;
1502
1503                case CM_ROTATE90CW:
1504                    docViewer->setRotation( docViewer->getRotation() + 90 );
1505                    return (MRESULT)FALSE;
1506
1507                case CM_ROTATE90CCW:
1508                    docViewer->setRotation( docViewer->getRotation() - 90 );
1509                    return (MRESULT)FALSE;
1510
1511                case CM_NAVPANE:
1512                    {
1513                        Lucide::showIndex = !Lucide::showIndex;
1514                        Lucide::checkNavpane();
1515                        WinSendMsg( hVertSplitter, SBM_SETSPLITTERPOS,
1516                            MPFROMSHORT( Lucide::showIndex ? Lucide::splitterPos : 0 ), MPVOID );
1517                        if ( !Lucide::showIndex ) {
1518                            Lucide::focusDocview();
1519                        }
1520                    }
1521                    return (MRESULT)FALSE;
1522
1523                case CM_FULLSCREEN:
1524                    Lucide::toggleFullscreen();
1525                    return (MRESULT)FALSE;
1526
1527                case CM_PRESENTATION:
1528                    Lucide::togglePresentation();
1529                    return (MRESULT)FALSE;
1530
1531                case CM_PRODINFO:
1532                    AboutBox( hWndFrame );
1533                    return (MRESULT)FALSE;
1534
1535                case CM_MINIMIZE:
1536                    Lucide::cmdMinimize();
1537                    return (MRESULT)FALSE;
1538
1539                case CM_TOPRESENTATION:
1540                    Lucide::cmdSwitchToPresentation();
1541                    return (MRESULT)FALSE;
1542
1543                case CM_SWITCHWINDOW:
1544                    Lucide::cmdSwitchWindow();
1545                    return (MRESULT)FALSE;
1546            }
1547        }
1548        break;
1549
1550        case WM_CLOSE:
1551            if ( !Lucide::closeDocument() )
1552                return (MRESULT)FALSE;
1553        break;
1554    }
1555    return pOldSplProc( hwnd, msg, mp1, mp2 );
1556}
1557
1558
1559char deffont[] = "9.WarpSans";
1560int deffontlen = sizeof( deffont );
1561
1562__declspec(dllexport) _System APIRET APIENTRY LucideMain( int argc, char *argv[] )
1563{
1564    HMQ   hmq;
1565    QMSG  qmsg;
1566    hab = WinInitialize( 0 );
1567    hmq = WinCreateMsgQueue( hab, 0 );
1568
1569    loadLang();
1570
1571    settings = new LuSettings;
1572    settings->load();
1573
1574    pluginMan = new PluginManager;
1575
1576    InitPMSplitterClass( hab );
1577    InitPMToolbarClass( hab );
1578
1579    ULONG ulFrameFlags = FCF_TITLEBAR | FCF_SIZEBORDER | FCF_SYSMENU |
1580                         FCF_MINMAX | FCF_TASKLIST | FCF_NOBYTEALIGN | FCF_ICON;
1581    title = newstrdupL( MSGS_MAIN_WIN_TITLE );
1582    hWndFrame = WinCreateStdWindow( HWND_DESKTOP, 0, &ulFrameFlags, NULL, title,
1583                                    WS_SYNCPAINT|WS_VISIBLE, _hmod, IDI_MAIN_ICON, NULL );
1584    pOldFrameProc = WinSubclassWindow( hWndFrame, frameProc );
1585
1586    hFrameSysmenu  = WinWindowFromID( hWndFrame, FID_SYSMENU );
1587    hFrameTitlebar = WinWindowFromID( hWndFrame, FID_TITLEBAR );
1588    hFrameMinMax   = WinWindowFromID( hWndFrame, FID_MINMAX );
1589    WinSetAccelTable( hab, WinLoadAccelTable( hab, _hmod, IDA_MAINACCEL ), hWndFrame );
1590    hWndMenu = WinLoadMenu( hWndFrame, _hmod, IDM_MAINMENU );
1591    localizeMenu( hWndMenu );
1592    WinSetWindowUShort( hWndMenu, QWS_ID, FID_MENU );
1593
1594    // Vertical splitter and his windows - Index and Document view
1595    hVertSplitter = WinCreateWindow( hWndFrame, WC_ER_SPLITTER, "",
1596                                     WS_VISIBLE | SBS_VSPLIT,
1597                                     0, 0, 0, 0, hWndFrame, HWND_TOP,
1598                                     ID_SPLITTER, NULL, NULL );
1599
1600    indexWin = new IndexWindow( hWndFrame );
1601
1602    DocumentViewer::registerClass();
1603
1604    docViewer = new DocumentViewer( hWndFrame );
1605
1606    WinSendMsg( hVertSplitter, SBM_SETWINDOWS,
1607                MPFROMHWND( indexWin->getHWND() ), MPFROMHWND( docViewer->getFrameHWND() ) );
1608
1609    // Horizontal splitter and its windows - Toolbar and Vertical splitter
1610    // Horizontal splitter is client window
1611    hHorizSplitter = WinCreateWindow( hWndFrame, WC_ER_SPLITTER, "",
1612                                      WS_VISIBLE | SBS_HSPLIT | SBS_SECONDFIXED,
1613                                      0, 0, 0, 0, hWndFrame, HWND_TOP,
1614                                      FID_CLIENT, NULL, NULL );
1615    pOldSplProc = WinSubclassWindow( hHorizSplitter, splProc );
1616
1617    hToolBar = createToolbar( hWndFrame );
1618
1619    WinSendMsg( hHorizSplitter, SBM_SETWINDOWS,
1620                MPFROMHWND( hVertSplitter ), MPFROMHWND( hToolBar ) );
1621    // ᅵᅵ⠭ᅵᅵᅵᅵᅵ 䚪ᅵ஢ᅵᅵᅵᅵ ࠧᅵᅵᅵ ᅵᅵᅵ ᅵ㫡ᅵᅵ
1622    WinSendMsg( hHorizSplitter, SBM_SETFIXEDSIZE,
1623                MPFROMSHORT( DEFAULT_PICTSIZE + TOOLBAR_HEIGHT_ADD ), MPVOID );
1624
1625    Lucide::checkMenus( true );
1626    Lucide::setPageLayout( settings->layout );
1627    Lucide::setZoom( settings->zoom );
1628
1629    findDlg = new FindDlg( hWndFrame );
1630    recent  = new RecentFiles( hWndMenu );
1631
1632    Lucide::restorePosition();
1633
1634    Lucide::focusDocview();
1635
1636    if ( argc > 1 ) {
1637        Lucide::loadDocument( argv[1] );
1638    }
1639
1640    Lucide::checkNavpane();
1641    initPipeMon( hWndFrame );
1642
1643    // Messsage loop
1644    while ( WinGetMsg( hab, &qmsg, 0, 0, 0 ) ) {
1645        WinDispatchMsg( hab, &qmsg );
1646    }
1647
1648    Lucide::savePosition();
1649
1650    WinDestroyWindow( hWndFrame );
1651
1652    recent->save();
1653
1654    Lucide::closeDocument( true );
1655    delete docViewer;
1656    delete indexWin;
1657
1658    // must be freed _after_ document
1659    delete pluginMan;
1660
1661    delete findDlg;
1662    delete recent;
1663    delete title;
1664    delete settings;
1665    unInitPipeMon();
1666
1667    WinDestroyMsgQueue( hmq );
1668    WinTerminate( hab );
1669    return 0;
1670}
1671
Note: See TracBrowser for help on using the repository browser.