Skip to content
Browse files

Merge branch 'master' of git://github.com/goldendict/goldendict into …

…scanpopup

Conflicts:
	stardict.cc
	xdxf2html.cc
	xdxf2html.hh
  • Loading branch information...
2 parents d65348b + c81e6ca commit 568c2c1ac56c048b30e2cd9381d0d57ca4b1707b @tindzk committed
Showing with 15,460 additions and 2,595 deletions.
  1. +4 −2 CREDITS.txt
  2. +1 −1 LICENSE.txt
  3. +910 −0 aard.cc
  4. +23 −0 aard.hh
  5. +1 −1 about.cc
  6. +1 −1 about.hh
  7. +1 −1 about.ui
  8. +40 −0 article-style.css
  9. +28 −4 article_maker.cc
  10. +3 −3 article_maker.hh
  11. +1 −1 article_netmgr.cc
  12. +1 −1 article_netmgr.hh
  13. +1 −1 articleview.cc
  14. +1 −1 articleview.hh
  15. +1 −1 articlewebview.cc
  16. +1 −1 articlewebview.hh
  17. +1 −1 atomic_rename.cc
  18. +1 −1 atomic_rename.hh
  19. +11 −4 audiolink.cc
  20. +4 −1 audiolink.hh
  21. +1 −4 bgl.cc
  22. +1 −1 bgl.hh
  23. +1 −1 broken_xrecord.cc
  24. +1 −1 broken_xrecord.hh
  25. +3 −7 btreeidx.cc
  26. +1 −1 btreeidx.hh
  27. +1 −1 chunkedstorage.cc
  28. +1 −1 chunkedstorage.hh
  29. +10 −2 config.cc
  30. +3 −1 config.hh
  31. +1 −1 country.cc
  32. +72 −0 decompress.cc
  33. +12 −0 decompress.hh
  34. +3 −15 dictdfiles.cc
  35. +1 −1 dictdfiles.hh
  36. +1 −1 dictionary.cc
  37. +1 −1 dictionary.hh
  38. +1 −1 dictspanewidget.hh
  39. +25 −136 dsl.cc
  40. +1 −1 dsl.hh
  41. +3 −14 dsl_details.cc
  42. +1 −1 dsl_details.hh
  43. +1 −1 editdictionaries.cc
  44. +1 −1 editdictionaries.hh
  45. +1 −1 ex.hh
  46. +1 −1 externalviewer.cc
  47. +1 −1 externalviewer.hh
  48. +26 −1 file.cc
  49. +7 −1 file.hh
  50. +1 −1 filetype.cc
  51. +1 −1 filetype.hh
  52. +1 −0 flags.qrc
  53. BIN flags/wi.png
  54. +1 −1 folding.cc
  55. +1 −1 folding.hh
  56. +1 −1 forvo.cc
  57. +1 −1 forvo.hh
  58. +1 −1 fsencoding.cc
  59. +1 −1 fsencoding.hh
  60. +1 −1 gdappstyle.cc
  61. +1 −1 gdappstyle.hh
  62. +1 −1 german.cc
  63. +1 −1 german.hh
  64. +21 −5 goldendict.pro
  65. +1 −1 groupcombobox.cc
  66. +1 −1 groupcombobox.hh
  67. +1 −1 groups.cc
  68. +1 −1 groups.hh
  69. +1 −1 groups_widgets.cc
  70. +1 −1 groups_widgets.hh
  71. +8 −3 history.cc
  72. +12 −1 history.hh
  73. +1 −1 hotkeyedit.cc
  74. +1 −1 hotkeyedit.hh
  75. +1 −1 htmlescape.cc
  76. +1 −1 htmlescape.hh
  77. +1 −1 hunspell.cc
  78. +1 −1 hunspell.hh
  79. BIN icons/icon32_aard.png
  80. BIN icons/icon32_sdict.png
  81. +1 −1 iconv.cc
  82. +1 −1 iconv.hh
  83. +100 −1 indexedzip.cc
  84. +4 −1 indexedzip.hh
  85. +1 −1 initializing.cc
  86. +1 −1 initializing.hh
  87. +1 −1 instances.cc
  88. +1 −1 instances.hh
  89. +1 −1 keyboardstate.cc
  90. +1 −1 keyboardstate.hh
  91. +14 −0 langcoder.cc
  92. +189 −187 langcoder.hh
  93. +1 −1 language.hh
  94. +27 −2 loaddictionaries.cc
  95. +1 −1 loaddictionaries.hh
  96. +133 −84 locale/ar_SA.ts
  97. +42 −2 locale/bg_BG.ts
  98. +42 −2 locale/cs_CZ.ts
  99. +136 −84 locale/de_DE.ts
  100. +133 −84 locale/el_GR.ts
  101. +133 −84 locale/es_AR.ts
  102. +4,121 −0 locale/es_BO.ts
  103. +3,271 −0 locale/es_ES.ts
  104. +212 −169 locale/it_IT.ts
  105. +133 −84 locale/ja_JP.ts
  106. +157 −108 locale/lt_LT.ts
  107. +197 −138 locale/pl_PL.ts
  108. +608 −1,044 locale/pt_BR.ts
  109. +4,122 −0 locale/qu_WI.ts
  110. +126 −85 locale/ru_RU.ts
  111. +133 −84 locale/sk_SK.ts
  112. +133 −84 locale/sq_AL.ts
Sorry, we could not display the entire diff because it was too big.
View
6 CREDITS.txt
@@ -1,4 +1,4 @@
-Konstantin Isakov <ikm\goldendict.org>: Principal author of the program
+Konstantin Isakov <ikm\goldendict.org>: Principal author of the program
Jennie Petoumenou <epetoumenou\gmail.com>: Greek transliteration and Greek translation
Mindaugas Baranauskas <embar\super.lt>: Lithuanian translation
Vit Pelcak <vit\pelcak.org>: Czech translation
@@ -12,9 +12,11 @@ Grzegorz Karpowicz <greg.karpowicz\gmail.com>: Polish translation
Nardog <alphisation\gmail.com>: Japanese translation
Maha 吳寶原, Ray Chou 周邦信, Marcus Bingenheimer: Traditional Chinese translation
Besmir Godole <bgodole\gmail.com>: Albanian translation
-Leonardo Montenegro <thesolidone\gmail.com>: Brazilian Portuguese translation
+Leonardo Montenegro <thesolidone\gmail.com>, MCHAL <MCHAL@anomail.de>: Brazilian Portuguese translation
Julian Depetris Chauvin <jdepetris\gmail.com>: Interface enhancements
Yanina Weingast <yjweingast\gmail.com>: Argentinian Spanish translation
Tvangeste <i.4m.l33t\yandex.ru>: Interface enhancements
Zdenko Podobný <zdenop\gmail.com>: Slovak translation
Şükrü Yekta Karabulut <sukruyekta\gmail.com>: Turkish translation
+Amos Batto <amosbatto\yahoo.com>: Quechua and Bolivian Spanish translations
+Carlos A. Cortijo Bon: Spanish from Spain translation
View
2 LICENSE.txt
@@ -1,5 +1,5 @@
GoldenDict, a dictionary lookup program.
- Copyright (C) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+ Copyright (C) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
View
910 aard.cc
@@ -0,0 +1,910 @@
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
+ * Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
+
+#include "aard.hh"
+#include "btreeidx.hh"
+#include "folding.hh"
+#include "utf8.hh"
+#include "chunkedstorage.hh"
+#include "langcoder.hh"
+#include "dprintf.hh"
+#include "fsencoding.hh"
+#include "decompress.hh"
+
+#include <map>
+#include <set>
+#include <string>
+
+#ifdef _MSC_VER
+#include <stub_msvc.h>
+#endif
+
+#include <QString>
+#include <QSemaphore>
+#include <QThreadPool>
+#include <QAtomicInt>
+#include <QDomDocument>
+
+#include "ufile.hh"
+#include "wstring_qt.hh"
+
+namespace Aard {
+
+using std::map;
+using std::multimap;
+using std::pair;
+using std::set;
+using std::string;
+using gd::wstring;
+
+using BtreeIndexing::WordArticleLink;
+using BtreeIndexing::IndexedWords;
+using BtreeIndexing::IndexInfo;
+
+namespace {
+
+DEF_EX_STR( exNotDctFile, "Not an Sdictionary file", Dictionary::Ex )
+DEF_EX_STR( exCantReadFile, "Can't read file", Dictionary::Ex )
+DEF_EX_STR( exWordIsTooLarge, "Enountered a word that is too large:", Dictionary::Ex )
+DEF_EX_STR( exSuddenEndOfFile, "Sudden end of file", Dictionary::Ex )
+
+#ifdef _MSC_VER
+#pragma pack( push, 1 )
+#endif
+
+// Big-Endian template
+// http://habrahabr.ru/blogs/cpp/121811/
+
+template<typename T>
+struct BigEndian
+{
+ union
+ {
+ unsigned char bytes[sizeof(T)];
+ T raw_value;
+ };
+
+ BigEndian(T t = T())
+ {
+ operator =(t);
+ }
+
+ BigEndian(const BigEndian<T> & t)
+ {
+ raw_value = t.raw_value;
+ }
+
+ operator const T() const
+ {
+ T t = T();
+ for (unsigned i = 0; i < sizeof(T); i++)
+ t |= T(bytes[sizeof(T) - 1 - i]) << (i << 3);
+ return t;
+ }
+
+ const T operator = (const T t)
+ {
+ for (unsigned i = 0; i < sizeof(T); i++)
+ bytes[sizeof(T) - 1 - i] = (unsigned char)( t >> (i << 3) );
+ return t;
+ }
+
+}
+#ifndef _MSC_VER
+__attribute__((packed))
+#endif
+;
+
+typedef BigEndian< uint16_t > uint16_be;
+typedef BigEndian< uint32_t > uint32_be;
+
+/// AAR file header
+struct AAR_header
+{
+ char signature[4];
+ char checksum[40];
+ uint16_be version;
+ char uuid[16];
+ uint16_be volume;
+ uint16_be totalVolumes;
+ uint32_be metaLength;
+ uint32_be wordsCount;
+ uint32_be articleOffset;
+ char indexItemFormat[4];
+ char keyLengthFormat[2];
+ char articleLengthFormat[2];
+}
+#ifndef _MSC_VER
+__attribute__((packed))
+#endif
+;
+
+struct IndexElement
+{
+ uint32_be wordOffset;
+ uint32_be articleOffset;
+}
+#ifndef _MSC_VER
+__attribute__((packed))
+#endif
+;
+
+enum
+{
+ Signature = 0x58524141, // AARX on little-endian, XRAA on big-endian
+ CurrentFormatVersion = 1 + BtreeIndexing::FormatVersion + Folding::Version
+};
+
+struct IdxHeader
+{
+ uint32_t signature; // First comes the signature, AARX
+ uint32_t formatVersion; // File format version (CurrentFormatVersion)
+ uint32_t chunksOffset; // The offset to chunks' storage
+ uint32_t indexBtreeMaxElements; // Two fields from IndexInfo
+ uint32_t indexRootOffset;
+ uint32_t wordCount;
+ uint32_t articleCount;
+ uint32_t langFrom; // Source language
+ uint32_t langTo; // Target language
+}
+#ifndef _MSC_VER
+__attribute__((packed))
+#endif
+;
+
+#ifdef _MSC_VER
+#pragma pack( pop, 1 )
+#endif
+
+bool indexIsOldOrBad( string const & indexFile )
+{
+ File::Class idx( indexFile, "rb" );
+
+ IdxHeader header;
+
+ return idx.readRecords( &header, sizeof( header ), 1 ) != 1 ||
+ header.signature != Signature ||
+ header.formatVersion != CurrentFormatVersion;
+}
+
+void readJSONValue( string const & source, string & str, uint32_t & pos)
+{
+ int level = 1;
+ char endChar;
+ str.push_back( source[pos] );
+ if( source[pos] == '{')
+ endChar = '}';
+ else if( source[pos] == '[' )
+ endChar = ']';
+ else if( source[pos] == '\"' )
+ {
+ str.clear();
+ endChar = '\"';
+ }
+ else
+ endChar = ',';
+
+ pos++;
+ char ch = 0;
+ char lastCh = 0;
+ while( !( ch == endChar && lastCh != '\\' && level == 0 )
+ && pos < source.size() )
+ {
+ lastCh = ch;
+ ch = source[ pos++ ];
+ if( ( ch == '{' || ch == '[' ) && lastCh != '\\' )
+ level++;
+ if( ( ch == '}' || ch == ']' ) && lastCh != '\\' )
+ level--;
+
+ if( ch == endChar &&
+ ( ( ch == '\"' && lastCh != '\\' ) || ch == ',' )
+ && level == 1)
+ break;
+ str.push_back( ch );
+ }
+}
+
+class AardDictionary: public BtreeIndexing::BtreeDictionary
+{
+ Mutex idxMutex;
+ File::Class idx;
+ IdxHeader idxHeader;
+ ChunkedStorage::Reader chunks;
+ string dictionaryName;
+ File::Class df;
+ QIcon dictionaryIcon, dictionaryNativeIcon;
+ bool dictionaryIconLoaded;
+
+ public:
+
+ AardDictionary( string const & id, string const & indexFile,
+ vector< string > const & dictionaryFiles );
+
+ ~AardDictionary();
+
+ virtual string getName() throw()
+ { return dictionaryName; }
+
+ virtual map< Dictionary::Property, string > getProperties() throw()
+ { return map< Dictionary::Property, string >(); }
+
+ virtual unsigned long getArticleCount() throw()
+ { return idxHeader.articleCount; }
+
+ virtual unsigned long getWordCount() throw()
+ { return idxHeader.wordCount; }
+
+ virtual QIcon getIcon() throw();
+
+ virtual QIcon getNativeIcon() throw();
+
+ inline virtual quint32 getLangFrom() const
+ { return idxHeader.langFrom; }
+
+ inline virtual quint32 getLangTo() const
+ { return idxHeader.langTo; }
+
+ virtual sptr< Dictionary::DataRequest > getArticle( wstring const &,
+ vector< wstring > const & alts,
+ wstring const & )
+ throw( std::exception );
+
+private:
+
+ void loadIcon();
+
+ /// Loads the article.
+ void loadArticle( uint32_t address,
+ string & articleText );
+ string convert( string const & in_data );
+
+ friend class AardArticleRequest;
+};
+
+AardDictionary::AardDictionary( string const & id,
+ string const & indexFile,
+ vector< string > const & dictionaryFiles ):
+ BtreeDictionary( id, dictionaryFiles ),
+ idx( indexFile, "rb" ),
+ idxHeader( idx.read< IdxHeader >() ),
+ chunks( idx, idxHeader.chunksOffset ),
+ df( dictionaryFiles[ 0 ], "rb" ),
+ dictionaryIconLoaded( false )
+{
+ // Read dictionary name
+
+ idx.seek( sizeof( idxHeader ) );
+ vector< char > dName( idx.read< uint32_t >() );
+ if( dName.size() )
+ {
+ idx.read( &dName.front(), dName.size() );
+ dictionaryName = string( &dName.front(), dName.size() );
+ }
+
+ // Initialize the index
+
+ openIndex( IndexInfo( idxHeader.indexBtreeMaxElements,
+ idxHeader.indexRootOffset ),
+ idx, idxMutex );
+}
+
+AardDictionary::~AardDictionary()
+{
+ df.close();
+}
+
+QIcon AardDictionary::getNativeIcon() throw()
+{
+ loadIcon();
+ return dictionaryNativeIcon;
+}
+
+QIcon AardDictionary::getIcon() throw()
+{
+ loadIcon();
+ return dictionaryIcon;
+}
+
+void AardDictionary::loadIcon()
+{
+ if ( dictionaryIconLoaded )
+ return;
+
+ QString fileName =
+ QDir::fromNativeSeparators( FsEncoding::decode( getDictionaryFilenames()[ 0 ].c_str() ) );
+
+ // Remove the extension
+
+ fileName.chop( 3 );
+ fileName += "bmp";
+ QFileInfo info( fileName );
+
+ if ( !info.exists() )
+ {
+ fileName.chop( 3 );
+ fileName += "png";
+ info = QFileInfo( fileName );
+ }
+
+ if ( info.exists() )
+ {
+ QImage img( fileName );
+
+ if ( !img.isNull() )
+ {
+ // Load successful
+
+ // Apply the color key
+
+ img.setAlphaChannel( img.createMaskFromColor( QColor( 192, 192, 192 ).rgb(),
+ Qt::MaskOutColor ) );
+
+ dictionaryNativeIcon = QIcon( QPixmap::fromImage( img ) );
+
+ // Transform it to be square
+ int max = img.width() > img.height() ? img.width() : img.height();
+
+ QImage result( max, max, QImage::Format_ARGB32 );
+ result.fill( 0 ); // Black transparent
+
+ QPainter painter( &result );
+
+ painter.drawImage( QPoint( img.width() == max ? 0 : ( max - img.width() ) / 2,
+ img.height() == max ? 0 : ( max - img.height() ) / 2 ),
+ img );
+
+ painter.end();
+
+ dictionaryIcon = QIcon( QPixmap::fromImage( result ) );
+ }
+ }
+
+ if ( dictionaryIcon.isNull() )
+ {
+ // Load failed -- use default icons
+ dictionaryNativeIcon = dictionaryIcon = QIcon(":/icons/icon32_aard.png");
+ }
+
+ dictionaryIconLoaded = true;
+}
+
+string AardDictionary::convert( const string & in )
+{
+ string inConverted;
+ char inCh, lastCh = 0;
+ bool afterEol = false;
+
+ for( string::const_iterator i = in.begin(), j = in.end(); i != j; ++i )
+ {
+ inCh = *i;
+ if( lastCh == '\\' )
+ {
+ inConverted.erase( inConverted.size() - 1 );
+ lastCh = 0;
+ if( inCh == 'n' )
+ {
+ inConverted.append( "<br/>");
+ afterEol = true;
+ continue;
+ }
+ else if( inCh == 'r')
+ continue;
+ }
+ else if( inCh == ' ' && afterEol )
+ {
+ inConverted.append( "&nbsp;" );
+ continue;
+ } else
+ lastCh = inCh;
+ afterEol = false;
+ inConverted.push_back( inCh );
+ }
+
+ QDomDocument dd;
+ QString errorStr;
+ int errorLine, errorColumn;
+
+ if( !dd.setContent( QByteArray( inConverted.c_str() ), false, &errorStr, &errorLine, &errorColumn ) )
+ {
+ FDPRINTF( stderr, "Aard article parse failed: %s at %d,%d\n", errorStr.toLocal8Bit().constData(), errorLine, errorColumn );
+ FDPRINTF( stderr, "The input was: %s\n", in.c_str() );
+ return inConverted;
+ }
+
+ QDomNodeList nodes = dd.elementsByTagName( "a" ); // References
+ for( int i = 0; i < nodes.count(); i++ )
+ {
+ QDomElement el = nodes.at( i ).toElement();
+ QString ref = el.attribute( "href", "" );
+ if( ref.size() == 0 || ref.indexOf( "http://") != -1 || ref[0] == '#' )
+ continue;
+ if( ref.indexOf( "w:") == 0 || ref.indexOf( "s:") == 0 )
+ ref.replace( 0, 2, "bword:" );
+ else
+ ref.insert( 0, "bword:" );
+ el.setAttribute( "href", ref );
+ }
+
+ return dd.toByteArray().data();
+}
+
+void AardDictionary::loadArticle( uint32_t address,
+ string & articleText )
+{
+ uint32_t articleOffset = address;
+ uint32_t articleSize;
+ uint32_be size;
+
+ vector< char > articleBody;
+
+ articleText.clear();
+
+ df.seek( articleOffset );
+ df.read( &size, sizeof(size) );
+ articleSize = size;
+ articleBody.resize( articleSize );
+ df.read( &articleBody.front(), articleSize );
+
+ if ( articleBody.empty() )
+ throw exCantReadFile( getDictionaryFilenames()[ 0 ] );
+
+ string text = decompressBzip2( articleBody.data(), articleSize );
+ if( text.empty() )
+ text = decompressZlib( articleBody.data(), articleSize );
+ if( text.empty() )
+ text = string( articleBody.data(), articleSize );
+
+ uint32_t n = 0;
+ while( n < text.size() && text[n] != '\"' )
+ n++;
+
+ if( n >= text.size() )
+ return;
+
+ readJSONValue( text, articleText, n );
+
+ if( articleText.empty() )
+ {
+ n = text.find( "\"r\"" );
+ if( n != string::npos )
+ {
+ n += 3;
+ while( n < text.size() && text[n] != '\"' )
+ n++;
+
+ if( n >= text.size() )
+ return;
+
+ string link;
+ readJSONValue( text, link, n );
+ if( !link.empty() )
+ articleText = "<a href=\"" + link + "\">" + link + "</a>";
+ }
+ }
+
+ if( !articleText.empty() )
+ articleText = convert( articleText );
+
+ articleText = "<div class=\"sdict\">" + articleText + "</div>";
+}
+
+/// AardDictionary::getArticle()
+
+class AardArticleRequest;
+
+class AardArticleRequestRunnable: public QRunnable
+{
+ AardArticleRequest & r;
+ QSemaphore & hasExited;
+
+public:
+
+ AardArticleRequestRunnable( AardArticleRequest & r_,
+ QSemaphore & hasExited_ ): r( r_ ),
+ hasExited( hasExited_ )
+ {}
+
+ ~AardArticleRequestRunnable()
+ {
+ hasExited.release();
+ }
+
+ virtual void run();
+};
+
+class AardArticleRequest: public Dictionary::DataRequest
+{
+ friend class AardArticleRequestRunnable;
+
+ wstring word;
+ vector< wstring > alts;
+ AardDictionary & dict;
+
+ QAtomicInt isCancelled;
+ QSemaphore hasExited;
+
+public:
+
+ AardArticleRequest( wstring const & word_,
+ vector< wstring > const & alts_,
+ AardDictionary & dict_ ):
+ word( word_ ), alts( alts_ ), dict( dict_ )
+ {
+ QThreadPool::globalInstance()->start(
+ new AardArticleRequestRunnable( *this, hasExited ) );
+ }
+
+ void run(); // Run from another thread by DslArticleRequestRunnable
+
+ virtual void cancel()
+ {
+ isCancelled.ref();
+ }
+
+ ~AardArticleRequest()
+ {
+ isCancelled.ref();
+ hasExited.acquire();
+ }
+};
+
+void AardArticleRequestRunnable::run()
+{
+ r.run();
+}
+
+void AardArticleRequest::run()
+{
+ if ( isCancelled )
+ {
+ finish();
+ return;
+ }
+
+ vector< WordArticleLink > chain = dict.findArticles( word );
+
+ for( unsigned x = 0; x < alts.size(); ++x )
+ {
+ /// Make an additional query for each alt
+
+ vector< WordArticleLink > altChain = dict.findArticles( alts[ x ] );
+
+ chain.insert( chain.end(), altChain.begin(), altChain.end() );
+ }
+
+ multimap< wstring, pair< string, string > > mainArticles, alternateArticles;
+
+ set< uint32_t > articlesIncluded; // Some synonims make it that the articles
+ // appear several times. We combat this
+ // by only allowing them to appear once.
+
+ wstring wordCaseFolded = Folding::applySimpleCaseOnly( word );
+
+ for( unsigned x = 0; x < chain.size(); ++x )
+ {
+ if ( isCancelled )
+ {
+ finish();
+ return;
+ }
+
+ if ( articlesIncluded.find( chain[ x ].articleOffset ) != articlesIncluded.end() )
+ continue; // We already have this article in the body.
+
+ // Now grab that article
+
+ string headword, articleText;
+
+ headword = chain[ x ].word;
+ dict.loadArticle( chain[ x ].articleOffset, articleText );
+
+ // Ok. Now, does it go to main articles, or to alternate ones? We list
+ // main ones first, and alternates after.
+
+ // We do the case-folded comparison here.
+
+ wstring headwordStripped =
+ Folding::applySimpleCaseOnly( Utf8::decode( headword ) );
+
+ multimap< wstring, pair< string, string > > & mapToUse =
+ ( wordCaseFolded == headwordStripped ) ?
+ mainArticles : alternateArticles;
+
+ mapToUse.insert( pair< wstring, pair< string, string > >(
+ Folding::applySimpleCaseOnly( Utf8::decode( headword ) ),
+ pair< string, string >( headword, articleText ) ) );
+
+ articlesIncluded.insert( chain[ x ].articleOffset );
+ }
+
+ if ( mainArticles.empty() && alternateArticles.empty() )
+ {
+ // No such word
+ finish();
+ return;
+ }
+
+ string result;
+
+ multimap< wstring, pair< string, string > >::const_iterator i;
+
+ for( i = mainArticles.begin(); i != mainArticles.end(); ++i )
+ {
+ result += "<h3>";
+ result += i->second.first;
+ result += "</h3>";
+ result += i->second.second;
+ }
+
+ for( i = alternateArticles.begin(); i != alternateArticles.end(); ++i )
+ {
+ result += "<h3>";
+ result += i->second.first;
+ result += "</h3>";
+ result += i->second.second;
+ }
+
+ Mutex::Lock _( dataMutex );
+
+ data.resize( result.size() );
+
+ memcpy( &data.front(), result.data(), result.size() );
+
+ hasAnyData = true;
+
+ finish();
+}
+
+map< string, string > parseMetaData( string const & metaData )
+{
+// Parsing JSON string
+ map< string, string > data;
+ string name, value;
+ uint32_t n = 0;
+
+ while( metaData[n] != '{' && n < metaData.length() )
+ n++;
+ while( n < metaData.length() )
+ {
+ // Skip to '"'
+ while( metaData[n] != '\"' && n < metaData.length() )
+ n++;
+ if( ++n >= metaData.length() )
+ break;
+
+ // Read name
+ while( !( ( metaData[n] == '\"' || metaData[n] == '{' ) && metaData[n-1] != '\\' )
+ && n < metaData.length() )
+ name.push_back( metaData[n++]);
+
+ // Skip to ':'
+ if( ++n >= metaData.length() )
+ break;
+ while( metaData[n] != ':' && n < metaData.length() )
+ n++;
+ if( ++n >= metaData.length() )
+ break;
+
+ // Find value start after ':'
+ while( !( ( metaData[n] == '\"'
+ || metaData[n] == '{'
+ || metaData[n] == '['
+ || ( metaData[n] >= '0' && metaData[n] <= '9' ) )
+ && metaData[n-1] != '\\' )
+ && n < metaData.length() )
+ n++;
+ if( n >= metaData.length() )
+ break;
+
+ readJSONValue( metaData, value, n);
+
+ data[name] = value;
+
+ name.clear();
+ value.clear();
+ if( ++n >= metaData.length() )
+ break;
+ }
+ return data;
+}
+
+sptr< Dictionary::DataRequest > AardDictionary::getArticle( wstring const & word,
+ vector< wstring > const & alts,
+ wstring const & )
+ throw( std::exception )
+{
+ return new AardArticleRequest( word, alts, *this );
+}
+
+} // anonymous namespace
+
+vector< sptr< Dictionary::Class > > makeDictionaries(
+ vector< string > const & fileNames,
+ string const & indicesDir,
+ Dictionary::Initializing & initializing )
+ throw( std::exception )
+{
+ vector< sptr< Dictionary::Class > > dictionaries;
+
+ for( vector< string >::const_iterator i = fileNames.begin(); i != fileNames.end();
+ ++i )
+ {
+ // Skip files with the extensions different to .aar to speed up the
+ // scanning
+ if ( i->size() < 4 ||
+ strcasecmp( i->c_str() + ( i->size() - 4 ), ".aar" ) != 0 )
+ continue;
+
+ // Got the file -- check if we need to rebuid the index
+
+ vector< string > dictFiles( 1, *i );
+
+ string dictId = Dictionary::makeDictionaryId( dictFiles );
+
+ string indexFile = indicesDir + dictId;
+
+ if ( Dictionary::needToRebuildIndex( dictFiles, indexFile ) ||
+ indexIsOldOrBad( indexFile ) )
+ {
+ try
+ {
+ File::Class df( *i, "rb" );
+
+ AAR_header dictHeader;
+
+ df.read( &dictHeader, sizeof(dictHeader) );
+ if( strncmp( dictHeader.signature, "aard", 4 )
+ || strncmp( dictHeader.indexItemFormat, ">LL", 4 )
+ || strncmp( dictHeader.keyLengthFormat, ">H", 2 )
+ || strncmp( dictHeader.articleLengthFormat, ">L", 2) )
+ {
+ DPRINTF( "File %s is not in supported aard format", i->c_str() );
+ continue;
+ }
+
+ vector< char > data;
+ uint32_t size = dictHeader.metaLength;
+
+ data.resize( size );
+ df.read( &data.front(), size );
+ string metaStr = decompressBzip2( data.data(), size );
+ if( metaStr.empty() )
+ metaStr = decompressZlib( data.data(), size );
+
+ map< string, string > meta = parseMetaData( metaStr );
+
+ if( meta.empty() )
+ {
+ DPRINTF( "File %s has invalid metadata", i->c_str() );
+ continue;
+ }
+
+ string dictName;
+ map< string, string >::const_iterator iter = meta.find( "title" );
+ if( iter != meta.end() )
+ dictName = iter->second;
+
+ uint16_t volumes = dictHeader.totalVolumes;
+ if( volumes > 1 )
+ {
+ QString ss;
+ ss.sprintf( " (%i/%i)", (uint16_t)(dictHeader.volume), volumes );
+ dictName += ss.toLocal8Bit().data();
+ }
+
+ string langFrom;
+ iter = meta.find( "index_language" );
+ if( iter != meta.end() )
+ langFrom = iter->second;
+
+ string langTo;
+ iter = meta.find( "article_language" );
+ if( iter != meta.end() )
+ langTo = iter->second;
+
+ initializing.indexingDictionary( dictName );
+
+ File::Class idx( indexFile, "wb" );
+ IdxHeader idxHeader;
+ memset( &idxHeader, 0, sizeof( idxHeader ) );
+
+ // We write a dummy header first. At the end of the process the header
+ // will be rewritten with the right values.
+
+ idx.write( idxHeader );
+
+ idx.write( (uint32_t) dictName.size() );
+ if( !dictName.empty() )
+ idx.write( dictName.data(), dictName.size() );
+
+ IndexedWords indexedWords;
+
+ ChunkedStorage::Writer chunks( idx );
+
+ uint32_t wordCount = dictHeader.wordsCount;
+ set< uint32_t > articleOffsets;
+ uint32_t pos = df.tell();
+ uint32_t wordsBase = pos + wordCount * sizeof( IndexElement );
+ uint32_t articlesBase = dictHeader.articleOffset;
+
+ for( uint32_t j = 0; j < wordCount; j++ )
+ {
+ IndexElement el;
+
+ df.seek( pos );
+ df.read( &el, sizeof(el) );
+ uint32_t articleOffset = articlesBase + el.articleOffset;
+ uint32_t wordOffset = wordsBase + el.wordOffset;
+
+ df.seek( wordOffset );
+
+ uint16_be sizeBE;
+ df.read( &sizeBE, sizeof(sizeBE) );
+ uint16_t wordSize = sizeBE;
+ data.resize( wordSize );
+ df.read( &data.front(), wordSize );
+
+ if( articleOffsets.find( articleOffset ) == articleOffsets.end() )
+ articleOffsets.insert( articleOffset );
+
+ // Insert new entry
+ indexedWords.addWord( Utf8::decode( string( data.data(), wordSize ) ), articleOffset);
+
+ pos += sizeof(el);
+ }
+ // Finish with the chunks
+
+ idxHeader.chunksOffset = chunks.finish();
+
+ // Build index
+
+ IndexInfo idxInfo = BtreeIndexing::buildIndex( indexedWords, idx );
+
+ idxHeader.indexBtreeMaxElements = idxInfo.btreeMaxElements;
+ idxHeader.indexRootOffset = idxInfo.rootOffset;
+
+ indexedWords.clear(); // Release memory -- no need for this data
+
+ // That concludes it. Update the header.
+
+ idxHeader.signature = Signature;
+ idxHeader.formatVersion = CurrentFormatVersion;
+
+ idxHeader.articleCount = articleOffsets.size();
+ idxHeader.wordCount = wordCount;
+
+ if( langFrom.size() == 3)
+ idxHeader.langFrom = LangCoder::code3toInt( langFrom.c_str() );
+ else if( langFrom.size() == 2 )
+ idxHeader.langFrom = LangCoder::code2toInt( langFrom.c_str() );
+
+ if( langTo.size() == 3)
+ idxHeader.langTo = LangCoder::code3toInt( langTo.c_str() );
+ else if( langTo.size() == 2 )
+ idxHeader.langTo = LangCoder::code2toInt( langTo.c_str() );
+
+ idx.rewind();
+
+ idx.write( &idxHeader, sizeof( idxHeader ) );
+ }
+ catch( std::exception & e )
+ {
+ FDPRINTF( stderr, "Aard dictionary indexing failed: %s, error: %s\n",
+ i->c_str(), e.what() );
+ continue;
+ }
+ catch( ... )
+ {
+ FDPRINTF( stderr, "Aard dictionary indexing failed\n" );
+ continue;
+ }
+ } // if need to rebuild
+ dictionaries.push_back( new AardDictionary( dictId,
+ indexFile,
+ dictFiles ) );
+ }
+ return dictionaries;
+}
+
+}
View
23 aard.hh
@@ -0,0 +1,23 @@
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
+ * Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
+
+#ifndef __AARD_HH_INCLUDED__
+#define __AARD_HH_INCLUDED__
+
+#include "dictionary.hh"
+
+/// Support for the aard dictionaries.
+namespace Aard {
+
+using std::vector;
+using std::string;
+
+vector< sptr< Dictionary::Class > > makeDictionaries(
+ vector< string > const & fileNames,
+ string const & indicesDir,
+ Dictionary::Initializing & )
+ throw( std::exception );
+
+}
+
+#endif
View
2 about.cc
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include "about.hh"
View
2 about.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef ABOUT_HH
View
2 about.ui
@@ -70,7 +70,7 @@
<item>
<widget class="QLabel" name="label_2">
<property name="text">
- <string>(c) 2008-2011 Konstantin Isakov (ikm@goldendict.org)</string>
+ <string>(c) 2008-2012 Konstantin Isakov (ikm@goldendict.org)</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
View
40 article-style.css
@@ -135,6 +135,10 @@ div.sdct_x
/******** XDXF markup classes *********/
+div.xdxf
+{
+}
+
/* Key -- keys shouldn't normally be present in the article's body since they
* are accounted for separately, hence we hide them */
.xdxf_k
@@ -204,6 +208,42 @@ div.sdct_x
display: none;
}
+.xdxf_headwords
+{
+ font-size: 116%;
+ font-weight: bold;
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+
+.xdxf_opt
+{
+ color: grey;
+}
+
+/******** SDictionary markup classes *********/
+
+.sdict_forms
+{
+ font-style: italic;
+}
+
+/* Transcription */
+.sdict_tr:before
+{
+ content:"[";
+}
+
+.sdict_tr:after
+{
+ content:"] ";
+}
+
+.sdict_tr
+{
+ font-weight: bold;
+}
+
/************* LSA audio archives **************/
/* A table which contains a play icon and a word's link */
View
32 article_maker.cc
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include "article_maker.hh"
@@ -153,7 +153,7 @@ sptr< Dictionary::DataRequest > ArticleMaker::makeDefinitionFor(
"<p>Should you need further help, have any questions, "
"suggestions or just wonder what the others think, you are welcome at the program's <a href=\"http://goldendict.org/forum/\">forum</a>."
"<p>Check program's <a href=\"http://goldendict.org/\">website</a> for the updates. "
-"<p>(c) 2008-2011 Konstantin Isakov. Licensed under GPLv3 or later."
+"<p>(c) 2008-2012 Konstantin Isakov. Licensed under GPLv3 or later."
).toUtf8().data();
}
@@ -285,7 +285,7 @@ ArticleRequest::ArticleRequest(
sptr< Dictionary::WordSearchRequest > s = activeDicts[ x ]->findHeadwordsForSynonym( gd::toWString( word ) );
connect( s.get(), SIGNAL( finished() ),
- this, SLOT( altSearchFinished() ) );
+ this, SLOT( altSearchFinished() ), Qt::QueuedConnection );
altSearches.push_back( s );
}
@@ -338,7 +338,7 @@ void ArticleRequest::altSearchFinished()
gd::toWString( contexts.value( QString::fromStdString( activeDicts[ x ]->getId() ) ) ) );
connect( r.get(), SIGNAL( finished() ),
- this, SLOT( bodyFinished() ) );
+ this, SLOT( bodyFinished() ), Qt::QueuedConnection );
bodyRequests.push_back( r );
}
@@ -812,3 +812,27 @@ std::string ArticleRequest::escapeSpacing( QString const & str )
return spacing.data();
}
+
+void ArticleRequest::cancel()
+{
+ if( isFinished() )
+ return;
+ if( !altSearches.empty() )
+ {
+ for( list< sptr< Dictionary::WordSearchRequest > >::iterator i =
+ altSearches.begin(); i != altSearches.end(); ++i )
+ {
+ (*i)->cancel();
+ }
+ }
+ if( !bodyRequests.empty() )
+ {
+ for( list< sptr< Dictionary::DataRequest > >::iterator i =
+ bodyRequests.begin(); i != bodyRequests.end(); ++i )
+ {
+ (*i)->cancel();
+ }
+ }
+ if( stemmedWordFinder.get() ) stemmedWordFinder->cancel();
+ finish();
+}
View
6 article_maker.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __ARTICLE_MAKER_HH_INCLUDED__
@@ -110,8 +110,8 @@ public:
std::vector< sptr< Dictionary::Class > > const & activeDicts,
std::string const & header );
- virtual void cancel()
- { finish(); } // Add our own requests cancellation here
+ virtual void cancel();
+// { finish(); } // Add our own requests cancellation here
private slots:
View
2 article_netmgr.cc
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifdef _MSC_VER
View
2 article_netmgr.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __ARTICLE_NETMGR_HH_INCLUDED__
View
2 articleview.cc
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include "articleview.hh"
View
2 articleview.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __ARTICLEVIEW_HH_INCLUDED__
View
2 articlewebview.cc
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include "articlewebview.hh"
View
2 articlewebview.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __ARTICLEWEBVIEW_HH_INCLUDED__
View
2 atomic_rename.cc
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include "atomic_rename.hh"
View
2 atomic_rename.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __ATOMIC_RENAME_HH_INCLUDED__
View
15 audiolink.cc
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include "audiolink.hh"
@@ -6,10 +6,17 @@
std::string addAudioLink( std::string const & url,
std::string const & dictionaryId )
{
- return std::string( "<script language=\"JavaScript\">var gdAudioLink; "
+ return std::string( "<script language=\"JavaScript\">" +
+ makeAudioLinkScript( url, dictionaryId ) +
+ "</script>" );
+}
+
+std::string makeAudioLinkScript( std::string const & url,
+ std::string const & dictionaryId )
+{
+ return std::string( "var gdAudioLink; "
"if ( !gdAudioLink ) gdAudioLink=" ) + url +
"; if ( typeof gdActivateAudioLink_" + dictionaryId + " != 'function' ) {"
"eval( 'function gdActivateAudioLink_" + dictionaryId + "() {"
- "gdAudioLink=" + url + "; }' ); }"
- "</script>";
+ "gdAudioLink=" + url + "; }' ); }";
}
View
5 audiolink.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __AUDIOLINK_HH_INCLUDED__
@@ -15,4 +15,7 @@
std::string addAudioLink( std::string const & url,
std::string const & dictionaryId );
+std::string makeAudioLinkScript( std::string const & url,
+ std::string const & dictionaryId );
+
#endif
View
5 bgl.cc
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include "bgl.hh"
@@ -425,9 +425,6 @@ void BglHeadwordsRequest::run()
return;
}
- sptr< Dictionary::WordSearchRequestInstant > result =
- new Dictionary::WordSearchRequestInstant;
-
vector< WordArticleLink > chain = dict.findArticles( str );
wstring caseFolded = Folding::applySimpleCaseOnly( str );
View
2 bgl.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __BGL_HH_INCLUDED__
View
2 broken_xrecord.cc
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include "broken_xrecord.hh"
View
2 broken_xrecord.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __BROKEN_XRECORD_HH_INCLUDED__
View
10 btreeidx.cc
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include "btreeidx.hh"
@@ -968,12 +968,8 @@ void IndexedWords::addWord( wstring const & word, uint32_t articleOffset )
void IndexedWords::addSingleWord( wstring const & word, uint32_t articleOffset )
{
- vector< WordArticleLink > links( 1, WordArticleLink( Utf8::encode( word ),
- articleOffset ) );
-
- insert(
- IndexedWords::value_type(
- Utf8::encode( Folding::apply( word ) ), links ) );
+ operator []( Utf8::encode( Folding::apply( word ) ) ).push_back(
+ WordArticleLink( Utf8::encode( word ), articleOffset ) );
}
IndexInfo buildIndex( IndexedWords const & indexedWords, File::Class & file )
View
2 btreeidx.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __BTREEIDX_HH_INCLUDED__
View
2 chunkedstorage.cc
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include "chunkedstorage.hh"
View
2 chunkedstorage.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __CHUNKEDSTORAGE_HH_INCLUDED__
View
12 config.cc
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include "config.hh"
@@ -121,7 +121,8 @@ Preferences::Preferences():
disallowContentFromOtherSites( false ),
enableWebPlugins( false ),
zoomFactor( 1 ),
- wordsZoomLevel( 0 )
+ wordsZoomLevel( 0 ),
+ maxStringsInHistory( 500 )
{
}
@@ -642,6 +643,9 @@ Class load() throw( exError )
if ( !preferences.namedItem( "enableWebPlugins" ).isNull() )
c.preferences.enableWebPlugins = ( preferences.namedItem( "enableWebPlugins" ).toElement().text() == "1" );
+
+ if ( !preferences.namedItem( "maxStringsInHistory" ).isNull() )
+ c.preferences.maxStringsInHistory = preferences.namedItem( "maxStringsInHistory" ).toElement().text().toUInt() ;
}
c.lastMainGroupId = root.namedItem( "lastMainGroupId" ).toElement().text().toUInt();
@@ -1192,6 +1196,10 @@ void save( Class const & c ) throw( exError )
opt = dd.createElement( "enableWebPlugins" );
opt.appendChild( dd.createTextNode( c.preferences.enableWebPlugins ? "1" : "0" ) );
preferences.appendChild( opt );
+
+ opt = dd.createElement( "maxStringsInHistory" );
+ opt.appendChild( dd.createTextNode( QString::number( c.preferences.maxStringsInHistory ) ) );
+ preferences.appendChild( opt );
}
{
View
4 config.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __CONFIG_HH_INCLUDED__
@@ -179,6 +179,8 @@ struct Preferences
qreal zoomFactor;
int wordsZoomLevel;
+ unsigned maxStringsInHistory;
+
Preferences();
};
View
2 country.cc
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include "country.hh"
View
72 decompress.cc
@@ -0,0 +1,72 @@
+#include <string.h>
+
+#include "decompress.hh"
+#include "zlib.h"
+#include "bzlib.h"
+
+string decompressZlib( char * bufptr, unsigned length )
+{
+z_stream zs;
+char buf[2048];
+string str;
+int res;
+ memset( &zs, 0, sizeof(zs) );
+ zs.next_in = (Bytef *)bufptr;
+ zs.avail_in = length;
+ while( 1 )
+ {
+ res = inflateInit( &zs );
+ if( res != Z_OK )
+ break;
+ while( res != Z_STREAM_END )
+ {
+ memset( buf, 0, sizeof(buf) );
+ zs.next_out = (Bytef *)buf;
+ zs.avail_out = 2047;
+ res = inflate( &zs, Z_SYNC_FLUSH );
+ str += buf;
+ if( res != Z_OK && res != Z_STREAM_END )
+ break;
+ }
+ break;
+ }
+ inflateEnd( &zs );
+ if( res != Z_STREAM_END )
+ str.clear();
+ return str;
+}
+
+string decompressBzip2( char * bufptr, unsigned length )
+{
+bz_stream zs;
+char buf[2048];
+string str;
+int res;
+ memset( &zs, 0, sizeof(zs) );
+ zs.next_in = bufptr;
+ zs.avail_in = length;
+ zs.total_in_lo32 = length;
+ while( 1 )
+ {
+ res = BZ2_bzDecompressInit( &zs, 0, 0 );
+ if( res != BZ_OK )
+ break;
+ while( res != BZ_STREAM_END )
+ {
+ memset( buf, 0, sizeof(buf) );
+ zs.next_out = buf;
+ zs.avail_out = 2047;
+ zs.total_out_lo32 = length;
+ res = BZ2_bzDecompress( &zs );
+ str += buf;
+ if( res != BZ_OK && res != BZ_STREAM_END )
+ break;
+ }
+ break;
+ }
+ BZ2_bzDecompressEnd( &zs );
+ if( res != BZ_STREAM_END )
+ str.clear();
+ return str;
+}
+
View
12 decompress.hh
@@ -0,0 +1,12 @@
+#ifndef __DECOMPRESS_HH_INCLUDED__
+#define __DECOMPRESS_HH_INCLUDED__
+
+#include <string>
+
+using std::string;
+
+string decompressZlib( char * bufptr, unsigned length );
+
+string decompressBzip2( char * bufptr, unsigned length );
+
+#endif // DECOMPRESS_HH
View
18 dictdfiles.cc
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include "dictdfiles.hh"
@@ -302,18 +302,6 @@ sptr< Dictionary::DataRequest > DictdDictionary::getArticle( wstring const & wor
} // anonymous namespace
-static bool tryPossibleName( string const & name, string & copyTo )
-{
- if ( File::exists( name ) )
- {
- copyTo = name;
-
- return true;
- }
- else
- return false;
-}
-
vector< sptr< Dictionary::Class > > makeDictionaries(
vector< string > const & fileNames,
string const & indicesDir,
@@ -340,8 +328,8 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
dictFiles.push_back( string() );
- if ( !tryPossibleName( baseName + "dict", dictFiles[ 1 ] ) &&
- !tryPossibleName( baseName + "dict.dz", dictFiles[ 1 ] ) )
+ if ( !File::tryPossibleName( baseName + "dict", dictFiles[ 1 ] ) &&
+ !File::tryPossibleName( baseName + "dict.dz", dictFiles[ 1 ] ) )
{
// No corresponding .dict file, skipping
continue;
View
2 dictdfiles.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __DICTDFILES_HH_INCLUDED__
View
2 dictionary.cc
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include <vector>
View
2 dictionary.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __DICTIONARY_HH_INCLUDED__
View
2 dictspanewidget.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __DICTSPANEWIDGET_HH_INCLUDED__
View
161 dsl.cc
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include "dsl.hh"
@@ -70,8 +70,8 @@ DEF_EX_STR( exCantReadFile, "Can't read file", Dictionary::Ex )
enum
{
Signature = 0x584c5344, // DSLX on little-endian, XLSD on big-endian
- CurrentFormatVersion = 14 + BtreeIndexing::FormatVersion + Folding::Version,
- CurrentZipSupportVersion = 1
+ CurrentFormatVersion = 15 + BtreeIndexing::FormatVersion + Folding::Version,
+ CurrentZipSupportVersion = 2
};
struct IdxHeader
@@ -1084,19 +1084,6 @@ sptr< Dictionary::DataRequest > DslDictionary::getArticle( wstring const & word,
return new DslArticleRequest( word, alts, *this );
}
-void loadFromFile( string const & n, vector< char > & data )
-{
- File::Class f( n, "rb" );
-
- f.seekEnd();
-
- data.resize( f.tell() );
-
- f.rewind();
-
- f.read( &data.front(), data.size() );
-}
-
//// DslDictionary::getResource()
class DslResourceRequest;
@@ -1191,7 +1178,7 @@ void DslResourceRequest::run()
{
Mutex::Lock _( dataMutex );
- loadFromFile( n, data );
+ File::loadFromFile( n, data );
}
catch( File::exCantOpen & )
{
@@ -1203,7 +1190,7 @@ void DslResourceRequest::run()
{
Mutex::Lock _( dataMutex );
- loadFromFile( n, data );
+ File::loadFromFile( n, data );
}
catch( File::exCantOpen & )
{
@@ -1275,18 +1262,6 @@ sptr< Dictionary::DataRequest > DslDictionary::getResource( string const & name
} // anonymous namespace
-static bool tryPossibleName( string const & name, string & copyTo )
-{
- if ( File::exists( name ) )
- {
- copyTo = name;
-
- return true;
- }
- else
- return false;
-}
-
#if 0
static void findCorrespondingFiles( string const & ifo,
string & idx, string & dict, string & syn,
@@ -1366,11 +1341,11 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
string abrvFileName;
- if ( tryPossibleName( baseName + "_abrv.dsl", abrvFileName ) ||
- tryPossibleName( baseName + "_abrv.dsl.dz", abrvFileName ) ||
- tryPossibleName( baseName + "_ABRV.DSL", abrvFileName ) ||
- tryPossibleName( baseName + "_ABRV.DSL.DZ", abrvFileName ) ||
- tryPossibleName( baseName + "_ABRV.DSL.dz", abrvFileName ) )
+ if ( File::tryPossibleName( baseName + "_abrv.dsl", abrvFileName ) ||
+ File::tryPossibleName( baseName + "_abrv.dsl.dz", abrvFileName ) ||
+ File::tryPossibleName( baseName + "_ABRV.DSL", abrvFileName ) ||
+ File::tryPossibleName( baseName + "_ABRV.DSL.DZ", abrvFileName ) ||
+ File::tryPossibleName( baseName + "_ABRV.DSL.dz", abrvFileName ) )
dictFiles.push_back( abrvFileName );
string dictId = Dictionary::makeDictionaryId( dictFiles );
@@ -1379,10 +1354,10 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
string zipFileName;
- if ( tryPossibleName( baseName + ".dsl.files.zip", zipFileName ) ||
- tryPossibleName( baseName + ".dsl.dz.files.zip", zipFileName ) ||
- tryPossibleName( baseName + ".DSL.FILES.ZIP", zipFileName ) ||
- tryPossibleName( baseName + ".DSL.DZ.FILES.ZIP", zipFileName ) )
+ if ( File::tryPossibleName( baseName + ".dsl.files.zip", zipFileName ) ||
+ File::tryPossibleName( baseName + ".dsl.dz.files.zip", zipFileName ) ||
+ File::tryPossibleName( baseName + ".DSL.FILES.ZIP", zipFileName ) ||
+ File::tryPossibleName( baseName + ".DSL.DZ.FILES.ZIP", zipFileName ) )
dictFiles.push_back( zipFileName );
string indexFile = indicesDir + dictId;
@@ -1576,7 +1551,11 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
break;
}
- if ( curString.empty() || isDslWs( curString[ 0 ] ) )
+ // Lingvo skips empty strings between the headwords
+ if ( curString.empty() )
+ continue;
+
+ if ( isDslWs( curString[ 0 ] ) )
break; // No more headwords
DPRINTF( "Alt headword: %ls\n", curString.c_str() );
@@ -1649,104 +1628,14 @@ vector< sptr< Dictionary::Class > > makeDictionaries(
idxHeader.hasZipFile = 1;
- QFile zipFile( QDir::fromNativeSeparators(
- FsEncoding::decode( zipFileName.c_str() ) ) );
+ IndexedWords zipFileNames;
+ IndexedZip zipFile;
+ if( zipFile.openZipFile( QDir::fromNativeSeparators(
+ FsEncoding::decode( zipFileName.c_str() ) ) ) )
+ zipFile.indexFile( zipFileNames );
- if ( !zipFile.open( QFile::ReadOnly ) )
- throw exCantReadFile( zipFileName );
-
- if ( ZipFile::positionAtCentralDir( zipFile ) )
+ if( !zipFileNames.empty() )
{
- // File seems to be a valid zip file
-
- IndexedWords zipFileNames;
-
- ZipFile::CentralDirEntry entry;
-
- while( ZipFile::readNextEntry( zipFile, entry ) )
- {
- if ( entry.compressionMethod == ZipFile::Unsupported )
- {
- DPRINTF( "Warning: compression method unsupported -- skipping file %s\n",
- entry.fileName.data() );
- continue;
- }
-
- // Check if the file name has some non-ascii letters.
-
- unsigned char const * ptr = ( unsigned char const * )
- entry.fileName.constData();
-
- bool hasNonAscii = false;
-
- for( ; ; )
- {
- if ( *ptr & 0x80 )
- {
- hasNonAscii = true;
- break;
- }
- else
- if ( !*ptr++ )
- break;
- }
-
- if ( !hasNonAscii )
- {
- // Add entry as is
-
- zipFileNames.addSingleWord( Utf8::decode( entry.fileName.data() ),
- entry.localHeaderOffset );
- }
- else
- {
- // Try assuming different encodings. Those are UTF8 and two
- // Russian ones (Windows and Windows OEM). Unfortunately, zip
- // files do not say which encoding they utilize.
-
- // Utf8
- try
- {
- wstring decoded = Utf8::decode( entry.fileName.constData() );
-
- zipFileNames.addSingleWord( decoded,
- entry.localHeaderOffset );
- }
- catch( Utf8::exCantDecode )
- {
- // Failed to decode
- }
-
- // CP866
- try
- {
- wstring decoded = Iconv::toWstring( "CP866", entry.fileName.constData(),
- entry.fileName.size() );
-
- zipFileNames.addSingleWord( decoded,
- entry.localHeaderOffset );
- }
- catch( Iconv::Ex )
- {
- // Failed to decode
- }
-
- // CP1251
- try
- {
- wstring decoded = Iconv::toWstring( "CP1251", entry.fileName.constData(),
- entry.fileName.size() );
-
- zipFileNames.addSingleWord( decoded,
- entry.localHeaderOffset );
- }
- catch( Iconv::Ex )
- {
- // Failed to decode
- }
- }
- }
-
// Build the resulting zip file index
IndexInfo idxInfo = BtreeIndexing::buildIndex( zipFileNames, idx );
View
2 dsl.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __DSL_HH_INCLUDED__
View
17 dsl_details.cc
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include "dsl_details.hh"
@@ -500,21 +500,10 @@ DslScanner::DslScanner( string const & fileName ) throw( Ex, Iconv::Ex ):
{
// Since .dz is backwards-compatible with .gz, we use gz- functions to
// read it -- they are much nicer than the dict_data- ones.
-#ifdef __WIN32
- int id = gd_open( fileName.c_str() );
- if( id == -1 )
- throw exCantOpen( fileName );
- f = gzdopen( id, "rb");
- if ( !f )
- {
- _close( id );
- throw exCantOpen( fileName );
- }
-#else
- f = gzopen( fileName.c_str(), "rb");
+
+ f = gd_gzopen( fileName.c_str() );
if ( !f )
throw exCantOpen( fileName );
-#endif
// Now try guessing the encoding by reading the first two bytes
View
2 dsl_details.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __DSL_DETAILS_HH_INCLUDED__
View
2 editdictionaries.cc
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include "editdictionaries.hh"
View
2 editdictionaries.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __EDITDICTIONARIES_HH_INCLUDED__
View
2 ex.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __EX_HH_INCLUDED__
View
2 externalviewer.cc
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include <QDir>
View
2 externalviewer.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __EXTERNALVIEWER_HH_INCLUDED__
View
27 file.cc
@@ -1,10 +1,11 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include "file.hh"
#include <cstring>
#include <cerrno>
+#include <string>
#include <sys/types.h>
#include <sys/stat.h>
@@ -25,6 +26,30 @@ enum
WriteBufferSize = 65536
};
+bool tryPossibleName( std::string const & name, std::string & copyTo )
+{
+ if ( File::exists( name ) )
+ {
+ copyTo = name;
+ return true;
+ }
+ else
+ return false;
+}
+
+void loadFromFile( std::string const & n, std::vector< char > & data )
+{
+ File::Class f( n, "rb" );
+
+ f.seekEnd();
+
+ data.resize( f.tell() );
+
+ f.rewind();
+
+ f.read( &data.front(), data.size() );
+}
+
bool exists( char const * filename ) throw()
{
#ifdef __WIN32
View
8 file.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __FILE_HH_INCLUDED__
@@ -6,6 +6,7 @@
#include <cstdio>
#include <string>
+#include <vector>
#include "ex.hh"
/// A simple wrapper over FILE * operations with added write-buffering,
@@ -20,6 +21,11 @@ DEF_EX( exWriteError, "Error writing to the file", Ex )
DEF_EX( exSeekError, "File seek error", Ex )
/// Checks if the file exists or not.
+
+bool tryPossibleName( std::string const & name, std::string & copyTo );
+
+void loadFromFile( std::string const & n, std::vector< char > & data );
+
bool exists( char const * filename ) throw();
inline bool exists( std::string const & filename ) throw()
View
2 filetype.cc
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include "filetype.hh"
View
2 filetype.hh
@@ -1,4 +1,4 @@
-/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
+/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __FILETYPE_HH_INCLUDED__
View
1 flags.qrc
@@ -243,6 +243,7 @@
<file>flags/vn.png</file>
<file>flags/vu.png</file>
<file>flags/wales.png</file>
+ <file>flags/wi.png</file>
<file>flags/wf.png</file>
<file>flags/ws.png</file>
<file>flags/ye.png</file>
View
BIN flags/wi.png
Sorry, something went wrong. Reload?
Sorry, we canno