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

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

small changes

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