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

Last change on this file since 423 was 423, checked in by dmik, 11 years ago

Do case-insensitive locale-aware file name comparison when building the file navigation list.

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