1 #include <wx/wx.h>
2 #include <wx/mstream.h>
3 #include <wx/stdpaths.h>
4
5
6 #include <crengine.h>
7 #include "cr3.h"
8 #include "wolopt.h"
9 #include "toc.h"
10 #include "optdlg.h"
11 #include "rescont.h"
12 #include "cr3.xpm"
13 #include <cr3version.h>
14
15 //scan directory
16 //scan file
17
wx2cr(wxString str)18 lString32 wx2cr( wxString str )
19 {
20 return lString32(str.utf8_str().data());
21 }
22
cr2wx(lString32 str)23 wxString cr2wx( lString32 str )
24 {
25 lString8 s8 = UnicodeToUtf8(str);
26 return wxString(s8.c_str(), wxConvUTF8);
27 }
28
29 /// author properties
30 class CRDocAuthor {
31 lString32 _firstName;
32 lString32 _lastName;
33 lString32 _middleName;
34 lString32 _nickName;
35 public:
CRDocAuthor()36 CRDocAuthor() { }
~CRDocAuthor()37 ~CRDocAuthor() { }
CRDocAuthor(const CRDocAuthor & v)38 CRDocAuthor( const CRDocAuthor & v ) {
39 _firstName = v._firstName;
40 _lastName = v._lastName;
41 _middleName = v._middleName;
42 _nickName = v._nickName;
43 }
operator =(const CRDocAuthor & v)44 CRDocAuthor & operator = ( const CRDocAuthor & v ) {
45 _firstName = v._firstName;
46 _lastName = v._lastName;
47 _middleName = v._middleName;
48 _nickName = v._nickName;
49 return *this;
50 }
getFirstName()51 lString32 getFirstName() { return _firstName; }
getLastName()52 lString32 getLastName() { return _lastName; }
getMiddleName()53 lString32 getMiddleName() { return _middleName; }
getNickName()54 lString32 getNickName() { return _nickName; }
setFirstName(lString32 fn)55 void setFirstName( lString32 fn ) { _firstName = fn; }
setLastName(lString32 ln)56 void setLastName( lString32 ln ) { _lastName = ln; }
getMiddleName(lString32 mn)57 void getMiddleName( lString32 mn ) { _middleName = mn; }
getNickName(lString32 nn)58 void getNickName( lString32 nn ) { _nickName = nn; }
59 };
60
61 /// document properties container
62 class CRDocProperties {
63 lString32 _fileName;
64 lvsize_t _fileSize;
65 doc_format_t _format;
66 lString32 _title;
67 lString32 _seriesName;
68 int _seriesNumber;
69 LVPtrVector<CRDocAuthor> _authors;
70 public:
71 /// returns array of document authors
getAuthors()72 LVPtrVector<CRDocAuthor> & getAuthors() { return _authors; }
73 /// returns document file name
getFileName()74 lString32 getFileName() { return _fileName; }
75 /// returns document file size
getFileSize()76 lvsize_t getFileSize() { return _fileSize; }
77 /// returns document format
getFormat()78 doc_format_t getFormat() { return _format; }
79 /// returns document title
getTitle()80 lString32 getTitle() { return _title; }
81 /// returns document series name
getSeriesName()82 lString32 getSeriesName() { return _seriesName; }
83 /// returns document series number
getSeriesNumber()84 int getSeriesNumber() { return _seriesNumber; }
setFileName(lString32 fn)85 void setFileName( lString32 fn ) { _fileName = fn; }
setFileSize(lvsize_t sz)86 void setFileSize( lvsize_t sz ) { _fileSize = sz; }
setFormat(doc_format_t fmt)87 void setFormat( doc_format_t fmt ) { _format = fmt; }
setTitle(lString32 title)88 void setTitle( lString32 title ) { _title = title; }
setSeriesName(lString32 sn)89 void setSeriesName( lString32 sn ) { _seriesName = sn; }
setSeriesNumber(int sn)90 void setSeriesNumber( int sn ) { _seriesNumber = sn; }
CRDocProperties()91 CRDocProperties() : _seriesNumber(0)
92 {
93 }
~CRDocProperties()94 ~CRDocProperties()
95 {
96 }
97 };
98
99 /// file properties container
100 class CRFileProperties {
101 lString32 _storageBasePath;
102 lString32 _relativePath;
103 lString32 _fileName;
104 lvsize_t _fileSize;
105 bool _isArchieve;
106 LVPtrVector<CRDocProperties> _docList;
107 lString32 _mimeType;
108 //===============================================
readDocument(lString32 fileName,LVStreamRef stream)109 bool readDocument( lString32 fileName, LVStreamRef stream )
110 {
111 return true;
112 }
readEpub(LVContainerRef arc)113 bool readEpub( LVContainerRef arc )
114 {
115 lString32 rootfilePath;
116 lString32 rootfileMediaType;
117 // read container.xml
118 {
119 LVStreamRef container_stream = arc->OpenStream(U"META-INF/container.xml", LVOM_READ);
120 if ( !container_stream.isNull() ) {
121 ldomDocument * doc = LVParseXMLStream( container_stream );
122 if ( doc ) {
123 ldomNode * rootfile = doc->nodeFromXPath( lString32("container/rootfiles/rootfile") );
124 if ( rootfile && rootfile->isElement() ) {
125 rootfilePath = rootfile->getAttributeValue("full-path");
126 rootfileMediaType = rootfile->getAttributeValue("media-type");
127 }
128 delete doc;
129 }
130 }
131 }
132 lString32 codeBase;
133 if (!rootfilePath.empty() && rootfileMediaType == "application/oebps-package+xml") {
134 //
135 {
136 int lastSlash = -1;
137 for ( int i=0; i<(int)rootfilePath.length(); i++ )
138 if ( rootfilePath[i]=='/' )
139 lastSlash = i;
140 if ( lastSlash>0 )
141 codeBase = lString32( rootfilePath.c_str(), lastSlash + 1);
142 }
143 LVStreamRef content_stream = arc->OpenStream(rootfilePath.c_str(), LVOM_READ);
144 if ( !content_stream.isNull() ) {
145 ldomDocument * doc = LVParseXMLStream( content_stream );
146 if ( doc ) {
147 lString32 title = doc->textFromXPath( lString32("package/metadata/title") );
148 lString32 authors = doc->textFromXPath( lString32("package/metadata/creator") );
149 delete doc;
150 }
151 }
152 }
153 return false;
154 }
readArchieve(LVContainerRef arc)155 bool readArchieve( LVContainerRef arc )
156 {
157 // epub support
158 LVStreamRef mtStream = arc->OpenStream(U"mimetype", LVOM_READ );
159 if ( !mtStream.isNull() ) {
160 int size = mtStream->GetSize();
161 if ( size>4 && size<100 ) {
162 LVArray<char> buf( size+1, 0 );
163 if ( mtStream->Read( buf.get(), size, NULL )==LVERR_OK ) {
164 for ( int i=0; i<size; i++ )
165 if ( buf[i]<32 || ((unsigned char)buf[i])>127 )
166 buf[i] = 0;
167 buf[size] = 0;
168 if ( buf[0] )
169 _mimeType = Utf8ToUnicode( lString8( buf.get() ) );
170 }
171 }
172 }
173 if (_mimeType == "application/epub+zip")
174 return readEpub( arc );
175 // todo: add more mime types support here
176 for ( int i=0; i<arc->GetObjectCount(); i++ ) {
177 const LVContainerItemInfo * item = arc->GetObjectInfo( i );
178 if ( !item->IsContainer() ) {
179 LVStreamRef stream = arc->OpenStream( item->GetName(), LVOM_READ );
180 if ( !stream.isNull() ) {
181 readDocument( lString32(item->GetName() ), stream );
182 }
183 }
184 }
185 return _docList.length() > 0;
186 }
187 public:
readFileProps(lString32 storageBasePath,lString32 filePathName)188 bool readFileProps( lString32 storageBasePath, lString32 filePathName )
189 {
190 LVAppendPathDelimiter( storageBasePath );
191 if ( filePathName.startsWith( storageBasePath ) ) {
192 _storageBasePath = storageBasePath;
193 _relativePath = filePathName.substr( _storageBasePath.length() );
194 _fileName = LVExtractFilename( _relativePath );
195 _relativePath = LVExtractPath( _relativePath );
196 } else {
197 _storageBasePath.clear();
198 _fileName = LVExtractFilename( filePathName );
199 _relativePath = LVExtractPath( filePathName );
200 }
201 _mimeType.clear();
202 LVStreamRef stream = LVOpenFileStream( filePathName.c_str(), LVOM_READ );
203 if ( stream.isNull() )
204 return false;
205 _fileSize = stream->GetSize();
206 LVContainerRef arc = LVOpenArchieve( stream );
207 _isArchieve = !arc.isNull();
208 if ( _isArchieve )
209 return readArchieve( arc );
210 else
211 return readDocument( _fileName, stream );
212 }
CRFileProperties()213 CRFileProperties() : _fileSize(0), _isArchieve(false)
214 {
215 }
~CRFileProperties()216 virtual ~CRFileProperties()
217 {
218 }
219 };
220
221
222 /*
223 For LINUX:
224
225 /usr/share/crengine/fonts/*.ttf -- fonts
226 /usr/share/fonts/truetype/freefont/*.ttf -- alternative font directory
227 /usr/share/fonts/truetype/msttcorefonts/ -- MS arial, times and courier fonts
228 /usr/share/crengine/fb2.css -- stylesheet
229 /usr/share/crengine/hyph/Russian_EnUS_hyphen_(Alan).pdb -- hyphenation dictionary
230
231 */
232
233
BEGIN_EVENT_TABLE(cr3Frame,wxFrame)234 BEGIN_EVENT_TABLE( cr3Frame, wxFrame )
235 EVT_MENU( Menu_File_Quit, cr3Frame::OnQuit )
236 EVT_MENU( Menu_File_About, cr3Frame::OnAbout )
237 EVT_MENU( wxID_OPEN, cr3Frame::OnFileOpen )
238 EVT_MENU( wxID_SAVE, cr3Frame::OnFileSave )
239 EVT_MENU( Menu_View_TOC, cr3Frame::OnShowTOC )
240 EVT_MENU( Menu_File_Options, cr3Frame::OnShowOptions )
241 EVT_MENU( Menu_View_History, cr3Frame::OnShowHistory )
242 EVT_MENU( Menu_View_Rotate, cr3Frame::OnRotate )
243
244
245 EVT_MENU_RANGE( 0, 0xFFFF, cr3Frame::OnCommand )
246 // EVT_UPDATE_UI_RANGE( 0, 0xFFFF, cr3Frame::OnUpdateUI )
247 EVT_COMMAND_SCROLL( Window_Id_Scrollbar, cr3Frame::OnScroll )
248 EVT_CLOSE( cr3Frame::OnClose )
249 EVT_MOUSEWHEEL( cr3Frame::OnMouseWheel )
250 EVT_INIT_DIALOG( cr3Frame::OnInitDialog )
251 EVT_LIST_ITEM_ACTIVATED(Window_Id_HistList, cr3Frame::OnHistItemActivated)
252 //EVT_SIZE ( cr3Frame::OnSize )
253 END_EVENT_TABLE()
254
255
256 BEGIN_EVENT_TABLE( cr3scroll, wxScrollBar )
257 EVT_SET_FOCUS( cr3scroll::OnSetFocus )
258 END_EVENT_TABLE()
259
260 IMPLEMENT_APP(cr3app)
261
262
263 #define USE_XPM_BITMAPS 1
264
265
266 #include "resources/cr3res.h"
267
268
269 void testHyphen( const char * str )
270 {
271 lString32 s32 = Utf8ToUnicode( lString8(str) );
272 lUInt16 widths[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
273 lUInt8 flags[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
274 HyphMan::hyphenate( s32.c_str(), s32.length(), widths, flags, 1, 15 );
275 lString8 buf( str );
276 buf << " = ";
277 for ( int i=0; i<s32.length(); i++ ) {
278 buf << str[i];
279 if ( flags[i] & LCHAR_ALLOW_HYPH_WRAP_AFTER )
280 buf << '-';
281 }
282 printf("%s\n", buf.c_str());
283 }
284
testFormatting()285 void testFormatting()
286 {
287 //
288 static char * words[] = {
289 "audition",
290 "helper",
291 "automation",
292 "constant",
293 "culture",
294 "hyphenation",
295 NULL,
296 };
297 for ( int w=0; words[w]; w++ )
298 testHyphen(words[w]);
299 class Tester {
300 public:
301 LFormattedText txt;
302 void addLine( const lChar32 * str, int flags, LVFontRef font )
303 {
304 lString32 s( str );
305 txt.AddSourceLine(
306 s.c_str(), /* pointer to unicode text string */
307 s.length(), /* number of chars in text, 0 for auto(strlen) */
308 0x000000, /* text color */
309 0xFFFFFF, /* background color */
310 font.get(), /* font to draw string */
311 NULL,
312 flags,
313 16, /* interline space, *16 (16=single, 32=double) */
314 30, /* first line margin */
315 NULL,
316 0
317 );
318 }
319 void dump()
320 {
321 formatted_text_fragment_t * buf = txt.GetBuffer();
322 for ( unsigned i=0; i<buf->frmlinecount; i++ ) {
323 formatted_line_t * frmline = buf->frmlines[i];
324 printf("line[%d]\t ", i);
325 for ( unsigned j=0; j<frmline->word_count; j++ ) {
326 formatted_word_t * word = &frmline->words[j];
327 if ( word->flags & LTEXT_WORD_IS_OBJECT ) {
328 // object
329 printf("{%d..%d} object\t", (int)word->x, (int)(word->x + word->width) );
330 } else {
331 // dump text
332 src_text_fragment_t * src = &buf->srctext[word->src_text_index];
333 lString32 txt = lString32( src->t.text, word->t.start, word->t.len );
334 lString8 txt8 = UnicodeToUtf8( txt );
335 printf("{%d..%d} \"%s\"\t", (int)word->x, (int)(word->x + word->width), (const char *)txt8.c_str() );
336 }
337 }
338 printf("\n");
339 }
340 }
341 };
342 LVFontRef font1 = fontMan->GetFont(20, 300, false, css_ff_sans_serif, lString8("Arial") );
343 LVFontRef font2 = fontMan->GetFont(20, 300, false, css_ff_serif, lString8("Times New Roman") );
344 Tester t;
345 t.addLine( U" Testing preformatted\ntext wrapping.", LTEXT_ALIGN_WIDTH|LTEXT_FLAG_OWNTEXT, font1 );
346 t.addLine( U"\nNewline.", LTEXT_FLAG_OWNTEXT, font1 );
347 t.addLine( U"\n\n2 Newlines.", LTEXT_FLAG_OWNTEXT, font1 );
348 #if 0
349 t.addLine( U"Testing thisislonglongwordto", LTEXT_ALIGN_WIDTH|LTEXT_FLAG_OWNTEXT, font1 );
350 t.addLine( U"Testing", LTEXT_ALIGN_WIDTH|LTEXT_FLAG_OWNTEXT, font1 );
351 t.addLine( U"several", LTEXT_ALIGN_LEFT|LTEXT_FLAG_OWNTEXT, font2 );
352 t.addLine( U" short", LTEXT_FLAG_OWNTEXT, font1 );
353 t.addLine( U"words!", LTEXT_FLAG_OWNTEXT, font2 );
354 t.addLine( U"Testing thisislonglongwordtohyphenate simple paragraph formatting. Just a test. ", LTEXT_ALIGN_WIDTH|LTEXT_FLAG_OWNTEXT, font1 );
355 t.addLine( U"There is seldom reason to tag a file in isolation. A more common use is to tag all the files that constitute a module with the same tag at strategic points in the development life-cycle, such as when a release is made.", LTEXT_ALIGN_WIDTH|LTEXT_FLAG_OWNTEXT, font1 );
356 t.addLine( U"There is seldom reason to tag a file in isolation. A more common use is to tag all the files that constitute a module with the same tag at strategic points in the development life-cycle, such as when a release is made.", LTEXT_ALIGN_WIDTH|LTEXT_FLAG_OWNTEXT, font1 );
357 t.addLine( U"There is seldom reason to tag a file in isolation. A more common use is to tag all the files that constitute a module with the same tag at strategic points in the development life-cycle, such as when a release is made.", LTEXT_ALIGN_WIDTH|LTEXT_FLAG_OWNTEXT, font1 );
358 t.addLine( U"Next paragraph: left-aligned. Blabla bla blabla blablabla hdjska hsdjkasld hsdjka sdjaksdl hasjkdl ahklsd hajklsdh jaksd hajks dhjksdhjshd sjkdajsh hasjdkh ajskd hjkhjksajshd hsjkadh sjk.", LTEXT_ALIGN_LEFT|LTEXT_FLAG_OWNTEXT, font1 );
359 t.addLine( U"Testing thisislonglongwordtohyphenate simple paragraph formatting. Just a test. ", LTEXT_ALIGN_WIDTH|LTEXT_FLAG_OWNTEXT, font1 );
360 t.addLine( U"Another fragment of text. ", LTEXT_FLAG_OWNTEXT, font1 );
361 t.addLine( U"And the last one written with another font", LTEXT_FLAG_OWNTEXT, font2 );
362 t.addLine( U"Next paragraph: left-aligned. ", LTEXT_ALIGN_LEFT|LTEXT_FLAG_OWNTEXT, font1 );
363 t.addLine( U"One more sentence. Second sentence.", LTEXT_FLAG_OWNTEXT, font1 );
364 int i;
365 #endif
366 // t.txt.FormatNew( 300, 400 );
367 t.dump();
368 #if 0
369 printf("Running performance test\n");
370 time_t start1 = time((time_t*)0);
371 for ( i=0; i<2000; i++ )
372 t.txt.FormatNew( 600, 800 );
373 //for ( int i=0; i<100000; i++ )
374 // t.txt.FormatNew( 400, 300 );
375 time_t end1 = time((time_t*)0);
376 #endif
377 #if 0
378 time_t start2 = time((time_t*)0);
379 for ( i=0; i<2000; i++ )
380 t.txt.FormatOld( 600, 800 );
381 //for ( int i=0; i<100000; i++ )
382 // t.txt.FormatOld( 400, 300 );
383 time_t end2 = time((time_t*)0);
384 #endif
385 #if 0
386 int time1 = (int)(end1-start1);
387 int time2 = (int)(end2-start2);
388 printf("\nNew time = %d, old time = %d, gain=%d%%\n", time1, time2, (time2-time1)*100/time2);
389 #endif
390 exit(0);
391 }
392
393
394 ResourceContainer * resources = NULL;
395
detectSlash(lString32 path)396 static lChar32 detectSlash( lString32 path )
397 {
398 for ( int i=0; i<path.length(); i++ )
399 if ( path[i]=='\\' || path[i]=='/' )
400 return path[i];
401 #ifdef _WIN32
402 return '\\';
403 #else
404 return '/';
405 #endif
406 }
407
GetConfigFileName()408 lString32 GetConfigFileName()
409 {
410 wxString wxcfgdir = wxStandardPaths::Get().GetUserDataDir();
411 if ( !wxDirExists( wxcfgdir ) )
412 ::wxMkdir( wxString( wxcfgdir ) );
413 lString32 cfgdir = wx2cr(wxcfgdir);
414 lChar32 slash = detectSlash( cfgdir );
415 cfgdir << slash;
416 return cfgdir + "cr3.ini";
417 }
418
OnUpdateUI(wxUpdateUIEvent & event)419 void cr3Frame::OnUpdateUI( wxUpdateUIEvent& event )
420 {
421 }
422
OnClose(wxCloseEvent & event)423 void cr3Frame::OnClose( wxCloseEvent& event )
424 {
425 SaveOptions();
426 _view->CloseDocument();
427 Destroy();
428 }
429
430
OnHistItemActivated(wxListEvent & event)431 void cr3Frame::OnHistItemActivated( wxListEvent& event )
432 {
433 long index = event.GetIndex();
434 if ( index == 0 && _view->getDocView()->isDocumentOpened()) {
435 SetActiveMode( am_book );
436 return;
437 }
438 if ( index>=0 && index<_view->getDocView()->getHistory()->getRecords().length() ) {
439 lString32 pathname = _view->getDocView()->getHistory()->getRecords()[index]->getFilePath() +
440 _view->getDocView()->getHistory()->getRecords()[index]->getFileName();
441 if ( !pathname.empty() ) {
442 Update();
443 SetActiveMode( am_book );
444 _view->LoadDocument( cr2wx(pathname) );
445 UpdateToolbar();
446 }
447 }
448 }
449
OnCommand(wxCommandEvent & event)450 void cr3Frame::OnCommand( wxCommandEvent& event )
451 {
452 _view->OnCommand( event );
453 switch ( event.GetId() ) {
454 case Menu_View_ToggleFullScreen:
455 _isFullscreen = !_isFullscreen;
456 _view->SetFullScreenState(_isFullscreen);
457 ShowFullScreen( _isFullscreen );
458 break;
459 case Menu_View_ZoomIn:
460 case Menu_View_ZoomOut:
461 case Menu_View_NextPage:
462 case Menu_View_PrevPage:
463 case Menu_Link_Forward:
464 case Menu_Link_Back:
465 case Menu_Link_Next:
466 case Menu_Link_Prev:
467 case Menu_Link_Go:
468 case Menu_View_Text_Format:
469 break;
470 }
471 }
472
OnMouseWheel(wxMouseEvent & event)473 void cr3Frame::OnMouseWheel(wxMouseEvent& event)
474 {
475 _view->OnMouseWheel(event);
476 }
477
OnSize(wxSizeEvent & event)478 void cr3Frame::OnSize(wxSizeEvent& event)
479 {
480 if ( _props->getBoolDef(PROP_WINDOW_SHOW_STATUSBAR, true ) ) {
481 wxStatusBar * sb = GetStatusBar();
482 if ( sb ) {
483 int width, height;
484 GetClientSize( &width, &height );
485 int sw[3] = {width-200, 100, 100};
486 sb->SetStatusWidths( 3, sw );
487 }
488 }
489 }
490
491
initHyph(const char * fname)492 bool initHyph(const char * fname)
493 {
494 //HyphMan hyphman;
495 //return;
496
497 //LVStreamRef stream = LVOpenFileStream( fname, LVOM_READ);
498 //if (!stream)
499 // {
500 // printf("Cannot load hyphenation file %s\n", fname);
501 // return false;
502 // }
503 // stream.get()
504 return HyphMan::initDictionaries( lString32(fname) );
505 }
506
readFileToString(const char * fname)507 lString8 readFileToString( const char * fname )
508 {
509 lString8 buf;
510 LVStreamRef stream = LVOpenFileStream(fname, LVOM_READ);
511 if (!stream)
512 return buf;
513 int sz = stream->GetSize();
514 if (sz>0)
515 {
516 buf.insert( 0, sz, ' ' );
517 stream->Read( buf.modify(), sz, NULL );
518 }
519 return buf;
520 }
521
522
OnExit()523 int cr3app::OnExit()
524 {
525 ShutdownFontManager();
526 delete resources;
527 HyphMan::uninit();
528 #if LDOM_USE_OWN_MEM_MAN == 1
529 //ldomFreeStorage();
530 #endif
531 return 0;
532 }
533
getIcon16x16(const lChar32 * name)534 wxBitmap cr3Frame::getIcon16x16(const lChar32 *name )
535 {
536 wxLogNull logNo; // Temporary disable warnings ( see: http://trac.wxwidgets.org/ticket/15331 )
537 lString32 dir;
538 if ( _toolbarSize==2 )
539 dir = "icons/22x22/";
540 else if ( _toolbarSize==1 )
541 dir = "icons/16x16/";
542 else
543 dir = "icons/32x32/";
544 wxBitmap icon = resources->GetBitmap( (dir + name + ".png").c_str() );
545 if ( icon.IsOk() )
546 return icon;
547 return wxNullBitmap;
548 } // ~wxLogNull called, old log sink restored
549
550 #if (USE_FREETYPE==1)
getDirectoryFonts(lString32Collection & pathList,lString32 ext,lString32Collection & fonts,bool absPath)551 bool getDirectoryFonts( lString32Collection & pathList, lString32 ext, lString32Collection & fonts, bool absPath )
552 {
553 int foundCount = 0;
554 lString32 path;
555 for ( int di=0; di<pathList.length();di++ ) {
556 path = pathList[di];
557 LVContainerRef dir = LVOpenDirectory(path.c_str());
558 if ( !dir.isNull() ) {
559 CRLog::trace("Checking directory %s", UnicodeToUtf8(path).c_str() );
560 for ( int i=0; i < dir->GetObjectCount(); i++ ) {
561 const LVContainerItemInfo * item = dir->GetObjectInfo(i);
562 lString32 fileName = item->GetName();
563 lString8 fn = UnicodeToLocal(fileName);
564 //printf(" test(%s) ", fn.c_str() );
565 if ( !item->IsContainer() && fileName.length()>4 && lString32(fileName, fileName.length()-4, 4)==ext ) {
566 lString32 fn;
567 if ( absPath ) {
568 fn = path;
569 if ( !fn.empty() && fn[fn.length()-1]!=PATH_SEPARATOR_CHAR)
570 fn << PATH_SEPARATOR_CHAR;
571 }
572 fn << fileName;
573 foundCount++;
574 fonts.add( fn );
575 }
576 }
577 }
578 }
579 return foundCount > 0;
580 }
581 #endif
582
583 bool
OnInit()584 cr3app::OnInit()
585 {
586 #if 0
587 // test property container unit test
588 {
589 CRPropRef props = LVCreatePropsContainer();
590 props->setString("test.string.values.1", lString32("string value 1"));
591 props->setString("test.string.values.2", lString32("string value 2 with extra chars(\\\r\n)"));
592 props->setBool("test.string.boolean1", true);
593 props->setBool("test.string.boolean2", false);
594 props->setString("test.string.more_values.2", lString32("string more values (2)"));
595 props->setString("test.string.values.22", lString32("string value 22"));
596 props->setInt("test.int.value1", 1 );
597 props->setInt("test.int.value2", -2 );
598 props->setInt("test.int.value3", 3 );
599 props->setInt("test.int.value4", 4 );
600 props->setInt64("test.int.big-value1", -42387267 );
601 props->setPoint("test.points.1", lvPoint(1,2) );
602 props->setPoint("test.points.2", lvPoint(3,4) );
603 props->setRect("test.rects.1", lvRect(1,2,3,4) );
604 props->setRect("test.rects.2", lvRect(-1,-2,3,4) );
605 props->setRect("test.rects.1copy", props->getRectDef("test.rects.1", lvRect()) );
606 props->setPoint("test.points.1copy", props->getPointDef("test.points.1", lvPoint()) );
607 props->setColor("test.colors.1", 0x012345);
608 props->setColor("test.colors.1copy", props->getColorDef("test.colors.1") );
609 CRPropRef sub = props->getSubProps("test.string.");
610 props->setString("test.results.values.1", sub->getStringDef("values.2"));
611 props->setInt("test.results.str-items", sub->getCount());
612 props->setString("test.results.item1-value", sub->getValue(1));
613 props->setString("test.results.item2-name", Utf8ToUnicode(lString8(sub->getName(2))));
614 props->setBool("test.results.compare-chars-eq", sub->getStringDef("values.2")==lString32("string value 2 with extra chars(\\\r\n)") );
615 LVStreamRef stream = LVOpenFileStream( "props1.ini", LVOM_WRITE );
616 props->saveToStream( stream.get() );
617 }
618 {
619 CRPropRef props = LVCreatePropsContainer();
620 LVStreamRef istream = LVOpenFileStream( "props1.ini", LVOM_READ );
621 LVStreamRef ostream = LVOpenFileStream( "props2.ini", LVOM_WRITE );
622 if ( !istream.isNull() && !ostream.isNull() ) {
623 props->loadFromStream( istream.get() );
624 props->setBool("add.test.result", props->getIntDef("test.int.value2", 0)==-2 );
625 props->saveToStream( ostream.get() );
626 }
627 }
628 #endif
629
630 #if 0
631 //CRLog::setFileLogger( "crengine.log" );
632 CRLog::setStdoutLogger();
633 CRLog::setLogLevel( CRLog::LL_DEBUG );
634 #endif
635
636 wxImage::AddHandler(new wxPNGHandler);
637 resources = new ResourceContainer();
638
639 lString32 appname = wx2cr(argv[0]);
640 int lastSlash=-1;
641 lChar32 slashChar = '/';
642 for ( int p=0; p<(int)appname.length(); p++ ) {
643 if ( appname[p]=='\\' ) {
644 slashChar = '\\';
645 lastSlash = p;
646 } else if ( appname[p]=='/' ) {
647 slashChar = '/';
648 lastSlash=p;
649 }
650 }
651
652 lString32 appPath;
653 if ( lastSlash>=0 )
654 appPath = appname.substr( 0, lastSlash+1 );
655
656 #if 0
657 {
658 LVStreamRef stream = LVOpenFileStream( "cr3res.zip", LVOM_WRITE );
659 stream->Write( cr3_icons, sizeof(cr3_icons), NULL );
660 }
661 #endif
662
663
664 if (resources->OpenFromMemory( cr3_icons, sizeof(cr3_icons) )) {
665 /*
666 LVStreamRef testStream = resources.GetStream(U"icons/16x16/signature.png");
667 if ( !testStream.isNull() ) {
668 int sz = testStream->GetSize();
669 lUInt8 * buf = new lUInt8[ sz ];
670 testStream->Read(buf, sz, NULL);
671 printf("read: %c%c%c\n", buf[0], buf[1], buf[2]);
672 }
673 wxBitmap icon = resources.GetBitmap(U"icons/16x16/signature.png");
674 if ( icon.IsOk() ) {
675 printf( "Image opened: %dx%d:%d\n", icon.GetWidth(), icon.GetHeight(), icon.GetDepth() );
676 }
677 */
678 }
679 lString32 fontDir = appPath + "fonts";
680 fontDir << slashChar;
681 lString8 fontDir8 = UnicodeToLocal(fontDir);
682 const char * fontDir8s = fontDir8.c_str();
683 //InitFontManager( fontDir8 );
684 InitFontManager(lString8::empty_str);
685
686 // Load font definitions into font manager
687 // fonts are in files font1.lbf, font2.lbf, ... font32.lbf
688 if (!fontMan->GetFontCount()) {
689
690
691 #if (USE_FREETYPE==1)
692 lString32 fontExt = U".ttf";
693 #else
694 lString32 fontExt = U".lbf";
695 #endif
696 #if (USE_FREETYPE==1)
697 lString32Collection fonts;
698 lString32Collection fontDirs;
699 fontDirs.add( fontDir );
700 static const char * msfonts[] = {
701 "arial.ttf", "arialbd.ttf", "ariali.ttf", "arialbi.ttf",
702 "cour.ttf", "courbd.ttf", "couri.ttf", "courbi.ttf",
703 "times.ttf", "timesbd.ttf", "timesi.ttf", "timesbi.ttf",
704 NULL
705 };
706 #ifdef _WIN32
707 wchar_t sd_buf[MAX_PATH];
708 sd_buf[0] = 0;
709 ::GetSystemDirectoryW(sd_buf, MAX_PATH-1);
710 lString32 sysFontDir = lString32(sd_buf) + U"\\..\\fonts\\";
711 lString8 sfd = UnicodeToLocal( sysFontDir );
712 //const char * s = sfd.c_str();
713 //CRLog::debug(s);
714 for ( int fi=0; msfonts[fi]; fi++ )
715 fonts.add( sysFontDir + lString32(msfonts[fi]) );
716 #endif
717 #ifdef _LINUX
718 fontDirs.add("/usr/local/share/cr3/fonts");
719 fontDirs.add("/usr/local/share/fonts/truetype/freefont");
720 fontDirs.add("/usr/share/cr3/fonts");
721 fontDirs.add("/usr/share/fonts/truetype/freefont");
722 //fontDirs.add( lString32(U"/usr/share/fonts/truetype/msttcorefonts") );
723 for ( int fi=0; msfonts[fi]; fi++ )
724 fonts.add( lString32("/usr/share/fonts/truetype/msttcorefonts/") + lString32(msfonts[fi]) );
725 #endif
726 getDirectoryFonts( fontDirs, fontExt, fonts, true );
727
728 // load fonts from file
729 CRLog::debug("%d font files found", fonts.length());
730 if (!fontMan->GetFontCount()) {
731 for ( int fi=0; fi<fonts.length(); fi++ ) {
732 lString8 fn = UnicodeToLocal(fonts[fi]);
733 CRLog::trace("loading font: %s", fn.c_str());
734 if ( !fontMan->RegisterFont(fn) ) {
735 CRLog::trace(" failed\n");
736 }
737 }
738 }
739 #if 0
740 LVContainerRef dir = LVOpenDirectory(fontDir.c_str());
741 for ( int i=0; i<dir->GetObjectCount(); i++ ) {
742 const LVContainerItemInfo * item = dir->GetObjectInfo(i);
743 lString32 fileName = item->GetName();
744 lString32 fileNameLower = fileName;
745 fileNameLower.lowercase();
746 lString8 fn = UnicodeToLocal(fileName);
747 const char * pfn = fn.c_str();
748 if ( !item->IsContainer() && fileNameLower.length()>4 && lString32(fileNameLower, fileNameLower.length()-4, 4)==U".ttf" ) {
749 printf("loading font: %s\n", fn.c_str());
750 if ( !fontMan->RegisterFont(fn) ) {
751 printf(" failed\n");
752 }
753 }
754 }
755 #endif
756 //fontMan->RegisterFont(lString8("arial.ttf"));
757 #else
758 #define MAX_FONT_FILE 128
759 for (int i=0; i<MAX_FONT_FILE; i++)
760 {
761 char fn[1024];
762 sprintf( fn, "font%d.lbf", i );
763 printf("try load font: %s\n", fn);
764 fontMan->RegisterFont( lString8(fn) );
765 }
766 #endif
767 }
768
769 // init hyphenation manager
770 char hyphfn[1024];
771 sprintf(hyphfn, "Russian_EnUS_hyphen_(Alan).pdb" );
772 if ( !initHyph( (UnicodeToLocal(appPath) + hyphfn).c_str() ) ) {
773 #ifdef _LINUX
774 initHyph( "/usr/share/cr3/hyph/Russian_EnUS_hyphen_(Alan).pdb" );
775 #endif
776 }
777
778 if (!fontMan->GetFontCount())
779 {
780 //error
781 #if (USE_FREETYPE==1)
782 printf("Fatal Error: Cannot open font file(s) .ttf \nCannot work without font\n" );
783 #else
784 printf("Fatal Error: Cannot open font file(s) font#.lbf \nCannot work without font\nUse FontConv utility to generate .lbf fonts from TTF\n" );
785 #endif
786 return FALSE;
787 }
788
789 printf("%d fonts loaded.\n", fontMan->GetFontCount());
790
791 int argc = wxGetApp().argc;
792 lString32 fnameToOpen;
793 for ( int i=1; i<argc; i++ ) {
794 lString32 param = wx2cr(wxGetApp().argv[1]);
795 if ( param[0]!='-' )
796 fnameToOpen = param;
797 }
798 if ( fnameToOpen == U"test_format" ) {
799 testFormatting();
800 }
801
802 #ifdef _WIN32
803 //::GetSystemMetrics()
804 RECT wrc;
805 SystemParametersInfo( SPI_GETWORKAREA, 0, &wrc, 0 );
806 int x = wrc.left;
807 int y = wrc.top;
808 int cx = wrc.right - wrc.left;
809 int cy = wrc.bottom - wrc.top;
810 #else
811 int x = 20;
812 int y = 40;
813 int cx = wxSystemSettings::GetMetric( wxSYS_SCREEN_X );
814 int cy = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y )-40;
815 #endif
816 int scale_x = cx * 256 / 620;
817 int scale_y = cy * 256 / 830;
818 int scale = scale_x < scale_y ? scale_x : scale_y;
819 cx = 610 * scale / 256;
820 cy = 830 * scale / 256;
821 cr3Frame *frame = new cr3Frame( wxT( "CoolReader " wxT(CR3_VERSION) ), wxPoint(x,y), wxSize(cx,cy), appPath );
822
823
824
825 frame->Show(TRUE);
826 SetTopWindow(frame);
827 return TRUE;
828 }
829
UpdateToolbar()830 void cr3Frame::UpdateToolbar()
831 {
832 if ( _toolbarSize==0 )
833 return;
834 bool enabled_book = _activeMode==am_book && _view->getDocView()->isDocumentOpened();
835 wxToolBar* toolBar = GetToolBar();
836 toolBar->EnableTool(wxID_SAVE, enabled_book);
837 toolBar->EnableTool(Menu_View_ZoomIn, enabled_book);
838 toolBar->EnableTool(Menu_View_ZoomOut, enabled_book);
839 toolBar->EnableTool(Menu_View_TOC, enabled_book);
840 toolBar->EnableTool(Menu_View_Rotate, enabled_book);
841 toolBar->EnableTool(Menu_View_TogglePages, enabled_book);
842 toolBar->EnableTool(Menu_View_PrevPage, enabled_book);
843 toolBar->EnableTool(Menu_View_NextPage, enabled_book);
844 }
845
SetActiveMode(active_mode_t mode)846 void cr3Frame::SetActiveMode( active_mode_t mode )
847 {
848 if ( mode==_activeMode )
849 return;
850 switch (mode) {
851 case am_book:
852 {
853 _sizer->Show(_view, true);
854 _sizer->Show(_scrollBar, true);
855 _sizer->Show(_hist, false);
856 _sizer->Layout();
857 //_hist->Show(false);
858 //SetSizer( _sizer, false );
859 //_view->Show(true);
860 //_scrollBar->Show(true);
861 _view->SetFocus();
862 }
863 break;
864 case am_history:
865 {
866 _sizer->Show(_view, false);
867 _sizer->Show(_scrollBar, false);
868 _sizer->Show(_hist, true);
869 _sizer->Layout();
870
871 //_histsizer->Show();
872 //_sizer->Hide();
873 //_view->Show(false);
874 //_scrollBar->Show(false);
875 //SetSizer( _histsizer, false );
876 //_hist->Show(true);
877 //_histsizer->Layout();
878 _view->getDocView()->savePosition();
879 _hist->SetRecords(_view->getDocView()->getHistory()->getRecords());
880 _sizer->Layout();
881 _hist->UpdateColumns();
882 _hist->SetFocus();
883 }
884 break;
885 default:
886 break;
887 }
888 _activeMode = mode;
889 UpdateToolbar();
890 }
891
SetMenu(bool visible)892 void cr3Frame::SetMenu( bool visible )
893 {
894 bool was_visible = (GetMenuBar()!=NULL);
895 if ( was_visible == visible )
896 return;
897 if ( !visible ) {
898 SetMenuBar(NULL);
899 return;
900 }
901 wxMenu *menuFile = new wxMenu;
902
903 menuFile->Append( wxID_OPEN, wxT( "&Open...\tCtrl+O" ) );
904 menuFile->Append( Menu_View_History, wxT( "Recent books list\tF4" ) );
905 menuFile->Append( wxID_SAVE, wxT( "&Save...\tCtrl+S" ) );
906 menuFile->AppendSeparator();
907 menuFile->Append( Menu_File_Options, wxT( "&Options...\tF9" ) );
908 menuFile->AppendSeparator();
909 menuFile->Append( Menu_File_About, wxT( "&About...\tF1" ) );
910 menuFile->AppendSeparator();
911 menuFile->Append( Menu_File_Quit, wxT( "E&xit\tAlt+X" ) );
912
913 wxMenu *menuView = new wxMenu;
914
915 menuView->Append( Menu_View_TOC, wxT( "Table of Contents\tF5" ) );
916 menuView->Append( Menu_View_History, wxT( "Recent Books\tF4" ) );
917 menuView->Append( Menu_View_Rotate, wxT( "Rotate\tCtrl+R" ) );
918
919 menuView->AppendSeparator();
920 menuView->Append( Menu_View_ZoomIn, wxT( "Zoom In" ) );
921 menuView->Append( Menu_View_ZoomOut, wxT( "Zoom Out" ) );
922 menuView->AppendSeparator();
923 menuView->Append( Menu_View_ToggleFullScreen, wxT( "Toggle Fullscreen\tAlt+Enter" ) );
924 menuView->Append( Menu_View_TogglePages, wxT( "Toggle Pages/Scroll\tCtrl+P" ) );
925 menuView->Append( Menu_View_TogglePageHeader, wxT( "Toggle page heading\tCtrl+H" ) );
926
927 wxMenuBar *menuBar = new wxMenuBar;
928 menuBar->Append( menuFile, wxT( "&File" ) );
929 menuBar->Append( menuView, wxT( "&View" ) );
930
931 SetMenuBar( menuBar );
932 }
933
934
SetStatus(bool visible)935 void cr3Frame::SetStatus( bool visible )
936 {
937 bool was_visible = (GetStatusBar()!=NULL);
938 if ( was_visible == visible )
939 return;
940 if ( !visible ) {
941 SetStatusBar(NULL);
942 return;
943 }
944 CreateStatusBar();
945 wxStatusBar * status = GetStatusBar();
946 int sw[3] = { -1, 100, 100 };
947 //int ss[3] = {wxSB_NORMAL, wxSB_FLAT, wxSB_FLAT};
948 status->SetFieldsCount(2, sw);
949 //status->SetStatusStyles(3, ss);
950 SetStatusText( wxT( "Welcome to CoolReader " wxT(CR3_VERSION) wxT("!") ) );
951 }
952
953
954 static const long TOOLBAR_STYLE = wxTB_FLAT | wxTB_DOCKABLE; // | wxTB_TEXT // | wxTB_DOCKABLE
955
SetToolbarSize(int size)956 void cr3Frame::SetToolbarSize( int size )
957 {
958 //if ( size == _toolbarSize )
959 // return;
960 _toolbarSize = size;
961 if ( !_toolbarSize ) {
962 SetToolBar(NULL);
963 return;
964 }
965
966 wxToolBar* toolBar = GetToolBar();
967
968 long style = toolBar ? toolBar->GetWindowStyle() : TOOLBAR_STYLE;
969 delete toolBar;
970 SetToolBar(NULL);
971 style &= ~(wxTB_HORIZONTAL | wxTB_VERTICAL | wxTB_BOTTOM | wxTB_RIGHT | wxTB_HORZ_LAYOUT);
972 int mode = _props->getIntDef( PROP_WINDOW_TOOLBAR_POSITION, 0 );
973 switch ( mode ) {
974 case 1:
975 style |= wxTB_LEFT;
976 break;
977 default:
978 style |= wxTB_TOP;
979 break;
980 case 2:
981 style |= wxTB_RIGHT;
982 break;
983 case 3:
984 style |= wxTB_BOTTOM;
985 break;
986 }
987 //style |= wxTB_NO_TOOLTIPS;
988 toolBar = CreateToolBar(style, wxID_ANY);
989 /*
990 if ( toolBar == NULL ) {
991 toolBar = CreateToolBar();
992 } else {
993 int ids[] = {
994 wxID_OPEN,
995 Menu_View_History,
996 wxID_SAVE,
997 Menu_View_ZoomIn,
998 Menu_View_ZoomOut,
999 Menu_View_TOC,
1000 Menu_View_TogglePages,
1001 Menu_View_ToggleFullScreen,
1002 Menu_View_PrevPage,
1003 Menu_View_NextPage,
1004 Menu_File_Options,
1005 Menu_File_About,
1006 -1
1007 };
1008 for ( int i=0; ids[i]!=-1; i++ ) {
1009 toolBar->DeleteTool(ids[i]);
1010 }
1011 }
1012 */
1013
1014 wxBitmap fileopenBitmap = getIcon16x16(U"fileopen");
1015
1016 int w = fileopenBitmap.GetWidth(),
1017 h = fileopenBitmap.GetHeight();
1018
1019
1020
1021 toolBar->SetToolBitmapSize(wxSize(w, h));
1022 /*
1023 toolBar->AddTool(wxID_NEW, _T("New"),
1024 toolBarBitmaps[Tool_new], wxNullBitmap, wxITEM_NORMAL,
1025 _T("New file"), _T("This is help for new file tool"));
1026 */
1027 toolBar->AddTool(wxID_OPEN, _T("Open"),
1028 fileopenBitmap,//toolBarBitmaps[Tool_open],
1029 wxNullBitmap, wxITEM_NORMAL,
1030 _T("Open file"), _T("This is help for open file tool"));
1031 toolBar->AddTool(Menu_View_History, _T("History (F5)"),
1032 getIcon16x16(U"project_open"),//toolBarBitmaps[Tool_open],
1033 wxNullBitmap, wxITEM_NORMAL,
1034 _T("Toggle recent books list"), _T("Toggle recent opened books list"));
1035
1036 toolBar->AddTool(wxID_SAVE, _T("Save"),
1037 getIcon16x16(U"filesaveas"),//toolBarBitmaps[Tool_save],
1038 wxNullBitmap, wxITEM_NORMAL,
1039 _T("Save as..."), _T("Export document"));
1040
1041 toolBar->AddSeparator();
1042 toolBar->AddTool(Menu_View_ZoomIn, _T("Zoom In"),
1043 getIcon16x16(U"viewmag+"),//toolBarBitmaps[Tool_zoomin],
1044 wxNullBitmap, wxITEM_NORMAL,
1045 _T("Zoom in"), _T("Increase font size"));
1046 toolBar->AddTool(Menu_View_ZoomOut, _T("Zoom Out"),
1047 getIcon16x16(U"viewmag-"),//toolBarBitmaps[Tool_zoomout],
1048 wxNullBitmap, wxITEM_NORMAL,
1049 _T("Zoom out"), _T("Decrease font size"));
1050 toolBar->AddTool(Menu_View_Rotate, _T("Rotate (Ctrl+R)"),
1051 getIcon16x16(U"rotate_cw"),//toolBarBitmaps[Tool_zoomout],
1052 wxNullBitmap, wxITEM_NORMAL,
1053 _T("Rotate (Ctrl+R)"), _T("Rotate text clockwise"));
1054 toolBar->AddSeparator();
1055 toolBar->AddTool(Menu_View_TOC, _T("Table of Contents (F5)"),
1056 getIcon16x16(U"player_playlist"),//toolBarBitmaps[Tool_zoomout],
1057 wxNullBitmap, wxITEM_NORMAL,
1058 _T("Table of Contents (F5)"), _T("Show Table of Contents window"));
1059 toolBar->AddTool(Menu_View_TogglePages, _T("Toggle pages (Ctrl+P)"),
1060 getIcon16x16(U"view_left_right"),//toolBarBitmaps[Tool_zoomout],
1061 wxNullBitmap, wxITEM_NORMAL,
1062 _T("Toggle pages (Ctrl+P)"), _T("Switch pages/scroll mode"));
1063 toolBar->AddTool(Menu_View_ToggleFullScreen, _T("Fullscreen (Alt+Enter)"),
1064 getIcon16x16(U"window_fullscreen"),//toolBarBitmaps[Tool_zoomout],
1065 wxNullBitmap, wxITEM_NORMAL,
1066 _T("Fullscreen (Alt+Enter)"), _T("Switch to fullscreen mode"));
1067 toolBar->AddSeparator();
1068 //Menu_View_ToggleFullScreen
1069 toolBar->AddTool(Menu_View_PrevPage, _T("Previous page"),
1070 getIcon16x16(U"previous"),//toolBarBitmaps[Tool_north],
1071 wxNullBitmap, wxITEM_NORMAL,
1072 _T("Previous page"), _T("Go to previous page"));
1073 toolBar->AddTool(Menu_View_NextPage, _T("Next page"),
1074 getIcon16x16(U"next"),//toolBarBitmaps[Tool_south],
1075 wxNullBitmap, wxITEM_NORMAL,
1076 _T("Next page"), _T("Go to next page"));
1077
1078 toolBar->AddSeparator();
1079 toolBar->AddTool(Menu_File_Options, _T("Options"), //wxID_HELP
1080 getIcon16x16(U"configure"),//toolBarBitmaps[Tool_help],
1081 wxNullBitmap, wxITEM_NORMAL,
1082 _T("Options (F9)"), _T("Options (F9)"));
1083 toolBar->AddSeparator();
1084 toolBar->AddTool(Menu_File_About, _T("Help"), //wxID_HELP
1085 getIcon16x16(U"help"),//toolBarBitmaps[Tool_help],
1086 wxNullBitmap, wxITEM_NORMAL,
1087 _T("Help"), _T("Help"));
1088
1089 // after adding the buttons to the toolbar, must call Realize() to reflect
1090 // the changes
1091 toolBar->Realize();
1092 }
1093
OnInitDialog(wxInitDialogEvent & event)1094 void cr3Frame::OnInitDialog(wxInitDialogEvent& event)
1095 {
1096 _scrollBar = new cr3scroll(_view);
1097
1098 _view->SetScrollBar( _scrollBar );
1099 _view->Create(this, Window_Id_View,
1100 wxDefaultPosition, wxDefaultSize, 0, wxT("cr3view"));
1101 _hist->Create(this, Window_Id_HistList);
1102
1103 _scrollBar->Create(this, Window_Id_Scrollbar,
1104 wxDefaultPosition, wxDefaultSize, wxSB_VERTICAL);
1105
1106
1107 wxIcon icon = wxICON(cr3);
1108 SetIcon( icon );
1109
1110 //SetMenu( true );
1111
1112 //SetStatus( true );
1113
1114 //SetToolbarSize( 3 );
1115
1116
1117 //_histsizer = new wxBoxSizer( wxHORIZONTAL );
1118
1119 _sizer = new wxBoxSizer( wxHORIZONTAL );
1120 _sizer->Add( _view,
1121 1,
1122 wxALL | wxEXPAND,
1123 0);
1124 _sizer->Add( _scrollBar,
1125 0,
1126 wxALIGN_RIGHT | wxEXPAND,
1127 0);
1128 _sizer->Add( _hist,
1129 1,
1130 wxALL | wxEXPAND,
1131 0);
1132
1133 SetSizer( _sizer );
1134
1135 _view->SetBackgroundColour( _view->getBackgroundColour() );
1136 //_scrollBar->Show( true );
1137 SetBackgroundColour( _view->getBackgroundColour() );
1138
1139 // stylesheet can be placed to file fb2.css
1140 // if not found, default stylesheet will be used
1141 //char cssfn[1024];
1142 //sprintf( cssfn, "fb2.css"); //, exedir
1143 //lString8 css = readFileToString( (UnicodeToLocal(_appDir) + cssfn).c_str() );
1144 lString8 css;
1145 LVLoadStylesheetFile( _appDir + "fb2.css", css );
1146 #ifdef _LINUX
1147 if ( css.empty() )
1148 LVLoadStylesheetFile( U"/usr/share/cr3/fb2.css", css );
1149 //css = readFileToString( "/usr/share/crengine/fb2.css" );
1150 if ( css.empty() )
1151 LVLoadStylesheetFile( U"/usr/local/share/cr3/fb2.css", css );
1152 //css = readFileToString( "/usr/local/share/crengine/fb2.css" );
1153 #endif
1154 if (css.length() > 0)
1155 {
1156 printf("Style sheet file found.\n");
1157 _view->getDocView()->setStyleSheet( css );
1158 }
1159
1160 wxAcceleratorEntry entries[40];
1161 int a=0;
1162 entries[a++].Set(wxACCEL_CTRL, (int) 'O', wxID_OPEN);
1163 entries[a++].Set(wxACCEL_CTRL, (int) 'S', wxID_SAVE);
1164 entries[a++].Set(wxACCEL_CTRL, (int) 'P', Menu_View_TogglePages);
1165 entries[a++].Set(wxACCEL_CTRL, (int) 'H', Menu_View_TogglePageHeader);
1166 entries[a++].Set(wxACCEL_CTRL, (int) 'R', Menu_View_Rotate);
1167 entries[a++].Set(wxACCEL_NORMAL, WXK_F3, wxID_OPEN);
1168 entries[a++].Set(wxACCEL_NORMAL, WXK_F2, wxID_SAVE);
1169 entries[a++].Set(wxACCEL_NORMAL, WXK_UP, Menu_View_PrevLine);
1170 entries[a++].Set(wxACCEL_NORMAL, WXK_DOWN, Menu_View_NextLine);
1171 entries[a++].Set(wxACCEL_NORMAL, WXK_SPACE, Menu_View_NextLine);
1172 entries[a++].Set(wxACCEL_NORMAL, WXK_NUMPAD_ADD, Menu_View_ZoomIn);
1173 entries[a++].Set(wxACCEL_NORMAL, WXK_NUMPAD_SUBTRACT, Menu_View_ZoomOut);
1174 entries[a++].Set(wxACCEL_NORMAL, WXK_ADD, Menu_View_ZoomIn);
1175 entries[a++].Set(wxACCEL_NORMAL, WXK_SUBTRACT, Menu_View_ZoomOut);
1176 entries[a++].Set(wxACCEL_CTRL, WXK_NUMPAD_ADD, Menu_View_ZoomIn);
1177 entries[a++].Set(wxACCEL_CTRL, WXK_NUMPAD_SUBTRACT, Menu_View_ZoomOut);
1178 entries[a++].Set(wxACCEL_NORMAL, (int) '+', Menu_View_ZoomIn);
1179 entries[a++].Set(wxACCEL_NORMAL, (int) '-', Menu_View_ZoomOut);
1180 entries[a++].Set(wxACCEL_NORMAL, (int) '=', Menu_View_ZoomIn);
1181 entries[a++].Set(wxACCEL_NORMAL, WXK_PAGEUP, Menu_View_PrevPage);
1182 entries[a++].Set(wxACCEL_NORMAL, WXK_PAGEDOWN, Menu_View_NextPage);
1183 entries[a++].Set(wxACCEL_NORMAL, WXK_HOME, Menu_View_Begin);
1184 entries[a++].Set(wxACCEL_NORMAL, WXK_END, Menu_View_End);
1185 entries[a++].Set(wxACCEL_CTRL, (int) 'T', Menu_View_Text_Format);
1186 entries[a++].Set(wxACCEL_ALT, WXK_RETURN, Menu_View_ToggleFullScreen);
1187 entries[a++].Set(wxACCEL_NORMAL, WXK_F5, Menu_View_TOC);
1188 entries[a++].Set(wxACCEL_NORMAL, WXK_F4, Menu_View_History);
1189
1190 entries[a++].Set(wxACCEL_NORMAL, WXK_F9, Menu_File_Options);
1191 entries[a++].Set(wxACCEL_NORMAL, WXK_F12, Menu_File_Quit);
1192 entries[a++].Set(wxACCEL_NORMAL, WXK_BACK, Menu_Link_Back);
1193 entries[a++].Set(wxACCEL_SHIFT, WXK_BACK, Menu_Link_Forward);
1194 entries[a++].Set(wxACCEL_NORMAL, WXK_TAB, Menu_Link_Next);
1195 entries[a++].Set(wxACCEL_NORMAL, WXK_RETURN, Menu_Link_Go);
1196 entries[a++].Set(wxACCEL_SHIFT, WXK_TAB, Menu_Link_Prev);
1197
1198 wxAcceleratorTable accel(a, entries);
1199 SetAcceleratorTable(accel);
1200 //_view->SetAcceleratorTable(accel);
1201
1202
1203 //toolBar->SetRows(!(toolBar->IsVertical()) ? m_rows : 10 / m_rows);
1204 int argc = wxGetApp().argc;
1205 lString32 fnameToOpen;
1206 lString32 formatName;
1207 lString32 outFile;
1208 bool convert = false;
1209 for ( int i=1; i<argc; i++ ) {
1210 lString32 param = wx2cr(wxGetApp().argv[i]);
1211 if ( param[0]!='-' )
1212 fnameToOpen = param;
1213 else if (param.startsWith("--convert"))
1214 convert = true;
1215 else if (param.startsWith("--format=")) {
1216 formatName = param.substr(9);
1217 } else if (param.startsWith("--out=")) {
1218 outFile = param.substr(6);
1219 }
1220 }
1221 if ( fnameToOpen == U"test_format" ) {
1222 testFormatting();
1223 }
1224 if ( !fnameToOpen.empty() && convert ) {
1225 if ( formatName.empty() )
1226 formatName = U"wol";
1227 //==U"wol"
1228 if ( outFile.empty() )
1229 outFile = fnameToOpen + ".wol";
1230 // convertor
1231 if ( !_view->LoadDocument( cr2wx(fnameToOpen) ) )
1232 exit(1);
1233 if ( !_view->getDocView()->exportWolFile( outFile.c_str(), true, 3 ) )
1234 exit(2);
1235 // no errors
1236 exit(0);
1237 }
1238 if ( fnameToOpen.empty() ) {
1239 fnameToOpen = _view->GetLastRecentFileName();
1240 }
1241
1242 if ( !fnameToOpen.empty() && fnameToOpen[0]=='\"' )
1243 fnameToOpen.erase(0, 1);
1244 if ( !fnameToOpen.empty() && fnameToOpen[fnameToOpen.length()-1]=='\"' )
1245 fnameToOpen.erase(fnameToOpen.length()-1, 1);
1246 if ( fnameToOpen == U"test_format" ) {
1247 testFormatting();
1248 Destroy();
1249 return;
1250 }
1251
1252 _view->Show( true );
1253 //_view->UpdateScrollBar();
1254
1255 RestoreOptions();
1256 if ( !fnameToOpen.empty() ) {
1257 if ( !_view->LoadDocument( cr2wx(fnameToOpen) ) )
1258 {
1259 printf("cannot open document\n");
1260 }
1261 SetActiveMode( am_book );
1262 UpdateToolbar();
1263 } else {
1264 SetActiveMode( am_history );
1265 }
1266
1267 //Show();
1268 }
1269
1270
cr3Frame(const wxString & title,const wxPoint & pos,const wxSize & size,lString32 appDir)1271 cr3Frame::cr3Frame(const wxString& title, const wxPoint& pos, const wxSize& size, lString32 appDir )
1272 : wxFrame((wxFrame *)NULL, -1, title, pos, size), _activeMode(am_none), _toolbarSize(false)
1273 {
1274 //wxStandardPaths::GetUserDataDir();
1275
1276 _props = LVCreatePropsContainer();
1277
1278
1279
1280 _appDir = appDir;
1281
1282 _isFullscreen = false;
1283
1284 {
1285 // load options from file
1286 LVStreamRef stream = LVOpenFileStream( GetConfigFileName().c_str(), LVOM_READ );
1287 if ( !stream.isNull() )
1288 _props->loadFromStream(stream.get());
1289 }
1290
1291 _view = new cr3view( _props, appDir );
1292 _hist = new HistList();
1293
1294 InitDialog();
1295 }
1296
SaveOptions()1297 void cr3Frame::SaveOptions()
1298 {
1299 //_props->setHex(PROP_FONT_COLOR, _view->getDocView()->getTextColor() );
1300 //_props->setHex(PROP_BACKGROUND_COLOR, _view->getDocView()->getBackgroundColor() );
1301 _props->setInt(PROP_CRENGINE_FONT_SIZE, _view->getDocView()->getFontSize() );
1302 _props->setBool(PROP_WINDOW_FULLSCREEN, _isFullscreen );
1303 bool maximized = IsMaximized();
1304 bool minimized = IsIconized();
1305 _props->setBool(PROP_WINDOW_MAXIMIZED, maximized );
1306 _props->setBool(PROP_WINDOW_MINIMIZED, minimized );
1307 if ( !minimized && !maximized && !_isFullscreen ) {
1308 wxRect rc = GetRect();
1309 lvRect lvrc( rc.GetLeft(), rc.GetTop(), rc.GetRight(), rc.GetBottom() );
1310 _props->setRect(PROP_WINDOW_RECT, lvrc );
1311 }
1312 {
1313 // save options to file
1314 LVStreamRef stream = LVOpenFileStream( GetConfigFileName().c_str(), LVOM_WRITE );
1315 if ( !stream.isNull() )
1316 _props->saveToStream(stream.get());
1317 }
1318 }
1319
RestoreOptions()1320 void cr3Frame::RestoreOptions()
1321 {
1322 if ( !_isFullscreen ) {
1323 SetMenu( _props->getBoolDef(PROP_WINDOW_SHOW_MENU, true) );
1324 SetStatus( _props->getBoolDef(PROP_WINDOW_SHOW_STATUSBAR, true) );
1325 int tb = _props->getIntDef(PROP_WINDOW_TOOLBAR_SIZE, 2);
1326 if ( tb<0 )
1327 tb = 0;
1328 if ( tb>3)
1329 tb = 3;
1330 SetToolbarSize( tb );
1331 lvRect lvrc;
1332 if ( _props->getRect(PROP_WINDOW_RECT, lvrc ) ) {
1333 wxRect rc( lvrc.left, lvrc.top, lvrc.width(), lvrc.height() );
1334 SetSize( rc );
1335 }
1336 if ( _props->getBoolDef(PROP_WINDOW_MAXIMIZED) )
1337 Maximize();
1338 else if ( _props->getBoolDef(PROP_WINDOW_MINIMIZED) )
1339 Iconize();
1340 }
1341 fontMan->SetAntialiasMode( _props->getIntDef( PROP_FONT_ANTIALIASING, 2 ) );
1342 _view->getDocView()->setDefaultFontFace( UnicodeToUtf8(_props->getStringDef(PROP_FONT_FACE, "Arial" )) );
1343 _view->getDocView()->setTextColor( _props->getIntDef(PROP_FONT_COLOR, 0x000060 ) );
1344 _view->getDocView()->setBackgroundColor( _props->getIntDef(PROP_BACKGROUND_COLOR, 0xFFFFE0 ) );
1345 _view->getDocView()->setFontSize( _props->getIntDef( PROP_CRENGINE_FONT_SIZE, 28 ) );
1346 _view->SetPageHeaderFlags();
1347
1348 //_view->SetPageHeaderFlags();
1349
1350 int mode = _props->getIntDef( PROP_PAGE_VIEW_MODE, 2 );
1351 _view->getDocView()->setViewMode( mode>0 ? DVM_PAGES : DVM_SCROLL, mode>0 ? mode : -1 );
1352
1353 if ( _props->getBoolDef(PROP_WINDOW_FULLSCREEN) != _isFullscreen ) {
1354 _isFullscreen = !_isFullscreen;
1355 if ( _isFullscreen )
1356 Show();
1357 ShowFullScreen( _isFullscreen );
1358 }
1359 }
1360
1361 void
OnQuit(wxCommandEvent & WXUNUSED (event))1362 cr3Frame::OnQuit( wxCommandEvent& WXUNUSED( event ) )
1363 {
1364 //SaveOptions();
1365 Close(TRUE);
1366 }
1367
1368 void
OnShowHistory(wxCommandEvent & event)1369 cr3Frame::OnShowHistory( wxCommandEvent& event )
1370 {
1371 switch ( _activeMode ) {
1372 case am_book:
1373 SetActiveMode( am_history );
1374 break;
1375 case am_history:
1376 SetActiveMode( am_book );
1377 break;
1378 default:
1379 break;
1380 }
1381 }
1382
OnOptionsChange(CRPropRef oldprops,CRPropRef newprops,CRPropRef changed)1383 void cr3Frame::OnOptionsChange( CRPropRef oldprops, CRPropRef newprops, CRPropRef changed )
1384 {
1385 if ( changed->getCount()>0 ) {
1386 _props->set( newprops );
1387 SaveOptions();
1388 RestoreOptions();
1389 }
1390 ///
1391 }
1392
1393 void
OnShowOptions(wxCommandEvent & event)1394 cr3Frame::OnShowOptions( wxCommandEvent& event )
1395 {
1396 CR3OptionsDialog dlg(_props);
1397 dlg.Create( this, Window_Id_Options );
1398 if ( dlg.ShowModal() == wxID_OK ) {
1399 // set options
1400 dlg.ControlsToProps();
1401 OnOptionsChange( dlg.getOldProps(), dlg.getNewProps(), dlg.getChangedProps() );
1402 }
1403 }
1404
1405 void
OnRotate(wxCommandEvent & event)1406 cr3Frame::OnRotate( wxCommandEvent& event )
1407 {
1408 _view->Rotate();
1409 SaveOptions();
1410 }
1411
1412 void
OnShowTOC(wxCommandEvent & event)1413 cr3Frame::OnShowTOC( wxCommandEvent& event )
1414 {
1415 LVTocItem * toc = _view->getDocView()->getToc();
1416 ldomXPointer pos = _view->getDocView()->getBookmark();
1417 if ( !toc || !toc->getChildCount() )
1418 return;
1419 TocDialog dlg( this, toc, _view->getDocView()->getTitle(), pos );
1420 if ( dlg.ShowModal() == wxID_OK ) {
1421 // go to
1422 LVTocItem * sel = dlg.getSelection();
1423 if ( sel ) {
1424 ldomXPointer ptr = sel->getXPointer();
1425 _view->goToBookmark( ptr );
1426 Update();
1427 }
1428 }
1429 }
1430
1431
1432 void
OnFileOpen(wxCommandEvent & WXUNUSED (event))1433 cr3Frame::OnFileOpen( wxCommandEvent& WXUNUSED( event ) )
1434 {
1435 wxFileDialog dlg( this, wxT( "Choose a file to open" ),
1436 wxT( "" ),
1437 wxT( "" ),//const wxString& defaultFile = "",
1438 wxT("All supported files|*.fb2;*.fbz;*.txt;*.zip;*.rtf;*.epub;*.tcr;*.html;*.htm;*.shtml;*.xhtml|FictionBook files (*.fb2)|*.fb2;*.fbz|RTF files (*.rtf)|*.rtf|Text files (*.txt, *.tcr)|*.txt;*.tcr|HTML files|*.html;*.htm;*.shtml;*.xhtml|EPUB files (*.epub)|*.epub|ZIP archieves (*.zip)|*.zip"), //const wxString& wildcard = "*.*",
1439 wxFD_OPEN | wxFD_FILE_MUST_EXIST //long style = wxFD_DEFAULT_STYLE,
1440 //const wxPoint& pos = wxDefaultPosition,
1441 //const wxSize& sz = wxDefaultSize,
1442 //const wxString& name = "filedlg"
1443 );
1444
1445 if ( dlg.ShowModal() == wxID_OK ) {
1446 //
1447 Update();
1448 SetActiveMode( am_book );
1449 wxCursor hg( wxCURSOR_WAIT );
1450 this->SetCursor( hg );
1451 wxSetCursor( hg );
1452 _view->getDocView()->savePosition();
1453 _view->LoadDocument( dlg.GetPath() );
1454 _view->getDocView()->restorePosition();
1455 _view->UpdateScrollBar();
1456 //Invalidate();
1457 Refresh();
1458 Update();
1459 UpdateToolbar();
1460 wxSetCursor( wxNullCursor );
1461 this->SetCursor( wxNullCursor );
1462 }
1463
1464 }
1465
1466 void
OnFileSave(wxCommandEvent & WXUNUSED (event))1467 cr3Frame::OnFileSave( wxCommandEvent& WXUNUSED( event ) )
1468 {
1469 wxFileDialog dlg( this, wxT( "Choose a file to open" ),
1470 wxT( "" ),
1471 wxT( "" ),//const wxString& defaultFile = "",
1472 wxT("Wolf EBook files (*.wol)|*.wol"), //const wxString& wildcard = "*.*",
1473 wxFD_SAVE | wxFD_OVERWRITE_PROMPT //long style = wxFD_DEFAULT_STYLE,
1474 //const wxPoint& pos = wxDefaultPosition,
1475 //const wxSize& sz = wxDefaultSize,
1476 //const wxString& name = "filedlg"
1477 );
1478 WolOptions opts( this );
1479 if ( dlg.ShowModal() == wxID_OK && opts.ShowModal() == wxID_OK ) {
1480 //
1481 //_view->LoadDocument( dlg.GetPath() );
1482 Refresh();
1483 Update();
1484 wxCursor hg( wxCURSOR_WAIT );
1485 this->SetCursor( hg );
1486 wxSetCursor( hg );
1487 _view->getDocView()->exportWolFile( wx2cr(dlg.GetPath()).c_str(), opts.getMode()==0, opts.getLevels() );
1488 wxSetCursor( wxNullCursor );
1489 this->SetCursor( wxNullCursor );
1490 }
1491 }
1492
1493 void
OnAbout(wxCommandEvent & WXUNUSED (event))1494 cr3Frame::OnAbout( wxCommandEvent& WXUNUSED( event ) )
1495 {
1496 wxMessageBox( wxT( "Cool Reader " wxT(CR3_VERSION) wxT("\n(c) 1998-2018 Vadim Lopatin\n" wxVERSION_STRING"\n") )
1497 wxT("\nBased on CREngine library " wxT(CR_ENGINE_VERSION) )
1498 wxT("\nThird party libraries used:")
1499 wxT("\nzlib, libpng, libjpeg, freetype2,")
1500 wxT("\nhyphenation library by Alan")
1501 wxT("\n")
1502 wxT("\nThe program is being distributed under the terms of GNU General Public License")
1503 wxT("\nproject homepage is http://www.coolreader.org/crengine.htm")
1504 wxT("\nsource codes are available at http://sourceforge.net/projects/crengine"
1505 ),
1506 wxT( "About Cool Reader" ), wxOK | wxICON_INFORMATION, this );
1507 }
1508
1509 void
OnScroll(wxScrollEvent & event)1510 cr3Frame::OnScroll(wxScrollEvent& event)
1511 {
1512 _view->OnScroll( event );
1513 }
1514
OnSetFocus(wxFocusEvent & event)1515 void cr3scroll::OnSetFocus( wxFocusEvent& event )
1516 {
1517 _view->SetFocus();
1518 }
1519
OnSetFocus(wxFocusEvent & event)1520 void cr3view::OnSetFocus( wxFocusEvent& event )
1521 {
1522 GetParent()->SetFocus();
1523 }
1524
1525 void
OnKeyDown(wxKeyEvent & event)1526 cr3Frame::OnKeyDown(wxKeyEvent& event)
1527 {
1528 if ( _activeMode==am_book )
1529 _view->OnKeyDown( event );
1530 else
1531 event.Skip();
1532 }
1533