diff --git a/article_netmgr.cc b/article_netmgr.cc index 7ca15408..6d0d3f5c 100644 --- a/article_netmgr.cc +++ b/article_netmgr.cc @@ -198,9 +198,6 @@ QNetworkReply * ArticleNetworkAccessManager::getArticleReply( QNetworkRequest co QUrl refererUrl = QUrl::fromEncoded( referer ); - //GD_DPRINTF( "Considering %s vs %s\n", getHostBase( req.url() ).toUtf8().data(), - // getHostBase( refererUrl ).toUtf8().data() ); - if ( !url.host().endsWith( refererUrl.host() ) && getHostBaseFromUrl( url ) != getHostBaseFromUrl( refererUrl ) && !url.scheme().startsWith("data") ) { @@ -449,7 +446,7 @@ qint64 ArticleResourceReply::readData( char * out, qint64 maxSize ) qint64 left = avail - alreadyRead; qint64 toRead = maxSize < left ? maxSize : left; - GD_DPRINTF( "====reading %d bytes\n", (int)toRead ); + GD_DPRINTF( "====reading %d bytes", (int)toRead ); try { @@ -457,7 +454,7 @@ qint64 ArticleResourceReply::readData( char * out, qint64 maxSize ) } catch( std::exception & e ) { - qWarning( "getDataSlice error: %s\n", e.what() ); + qWarning( "getDataSlice error: %s", e.what() ); } alreadyRead += toRead; diff --git a/articleview.cc b/articleview.cc index 4f997a8d..a5443044 100644 --- a/articleview.cc +++ b/articleview.cc @@ -402,6 +402,9 @@ void ArticleView::showDefinition( Config::InputPhrase const & phrase, unsigned g if ( scrollTo.size() ) Utils::Url::addQueryItem( req, "scrollto", scrollTo ); + if(delayedHighlightText.size()) + Utils::Url::addQueryItem( req, "regexp", delayedHighlightText ); + Contexts::Iterator pos = contexts.find( "gdanchor" ); if( pos != contexts.end() ) { @@ -579,6 +582,12 @@ void ArticleView::loadFinished( bool result ) } if( Utils::Url::hasQueryItem( ui.definition->url(), "regexp" ) ) highlightFTSResults(); + + if( !delayedHighlightText.isEmpty() ) + { + // findText( delayedHighlightText, QWebEnginePage::FindCaseSensitively ,[](bool){}); + delayedHighlightText.clear(); + } } void ArticleView::loadProgress(int ){ @@ -1592,6 +1601,11 @@ void ArticleView::setSelectionBySingleClick( bool set ) ui.definition->setSelectionBySingleClick( set ); } +void ArticleView::setDelayedHighlightText(QString const & text) +{ + delayedHighlightText = text; +} + void ArticleView::back() { // Don't allow navigating back to page 0, which is usually the initial @@ -1712,6 +1726,7 @@ void ArticleView::contextMenuRequested( QPoint const & pos ) QAction * sendWordToInputLineAction = 0; QAction * saveImageAction = 0; QAction * saveSoundAction = 0; + QAction * saveBookmark = 0; #if( QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) ) const QWebEngineContextMenuData * menuData = &(r->contextMenuData()); @@ -1832,6 +1847,13 @@ void ArticleView::contextMenuRequested( QPoint const & pos ) } } + if(text.size()) + { + // avoid too long in the menu ,use left 30 characters. + saveBookmark = new QAction( tr( "Save &Bookmark \"%1...\"" ).arg( text.left( 30 ) ), &menu ); + menu.addAction( saveBookmark ); + } + // add anki menu if( !text.isEmpty() && cfg.preferences.ankiConnectServer.enabled ) { @@ -1931,7 +1953,11 @@ void ArticleView::contextMenuRequested( QPoint const & pos ) QDesktopServices::openUrl( targetUrl ); else if ( result == lookupSelection ) - showDefinition( selectedText, getGroup( ui.definition->url() ), getCurrentArticle() ); + showDefinition( text, getGroup( ui.definition->url() ), getCurrentArticle() ); + else if( result == saveBookmark ) + { + emit saveBookmarkSignal( text.left( 60 ) ); + } else if( result == sendToAnkiAction ) { sendToAnki( ui.definition->title(), ui.definition->selectedText() ); @@ -2333,42 +2359,44 @@ void ArticleView::performFindOperation( bool restart, bool backwards, bool check if ( backwards ) f |= QWebEnginePage::FindBackward; - bool setMark = text.size() && !findText(text, f); + findText( text, + f, + [ &text, this ]( bool match ) + { + bool setMark = !text.isEmpty() && !match; - if ( ui.searchText->property( "noResults" ).toBool() != setMark ) - { - ui.searchText->setProperty( "noResults", setMark ); + if( ui.searchText->property( "noResults" ).toBool() != setMark ) + { + ui.searchText->setProperty( "noResults", setMark ); - // Reload stylesheet - reloadStyleSheet(); - } + // Reload stylesheet + reloadStyleSheet(); + } + } ); } -bool ArticleView::findText(QString& text, const QWebEnginePage::FindFlags& f) +void ArticleView::findText( QString & text, + const QWebEnginePage::FindFlags & f, + const std::function< void( bool match ) > & callback ) { - bool r; - // turn async to sync invoke. - QSharedPointer loop = QSharedPointer(new QEventLoop()); - QTimer::singleShot(1000, loop.data(), &QEventLoop::quit); -#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) - ui.definition->findText(text, f, [&](const QWebEngineFindTextResult& result) +#if( QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) ) + ui.definition->findText( text, + f, + [ callback ]( const QWebEngineFindTextResult & result ) { - if(loop->isRunning()){ - r = result.numberOfMatches()>0; - loop->quit(); - } }); + auto r = result.numberOfMatches() > 0; + if( callback ) + callback( r ); + } ); #else - ui.definition->findText(text, f, [&](bool result) + ui.definition->findText( text, + f, + [ callback ]( bool result ) { - if(loop->isRunning()){ - r = result; - loop->quit(); - } }); + if( callback ) + callback( result ); + } ); #endif - - - loop->exec(); - return r; } void ArticleView::reloadStyleSheet() diff --git a/articleview.hh b/articleview.hh index 35aa99a1..e2a570d0 100644 --- a/articleview.hh +++ b/articleview.hh @@ -79,6 +79,8 @@ class ArticleView: public QFrame bool ftsSearchIsOpened, ftsSearchMatchCase; int ftsPosition; + QString delayedHighlightText; + void highlightFTSResults(); void highlightAllFtsOccurences( QWebEnginePage::FindFlags flags ); void performFtsFindOperation( bool backwards ); @@ -157,6 +159,8 @@ public: /// Called when preference changes void setSelectionBySingleClick( bool set ); + void setDelayedHighlightText(QString const & text); + public slots: /// Goes back in history @@ -227,6 +231,10 @@ public: ResourceToSaveHandler * saveResource( const QUrl & url, const QString & fileName ); ResourceToSaveHandler * saveResource( const QUrl & url, const QUrl & ref, const QString & fileName ); + void findText( QString & text, + const QWebEnginePage::FindFlags & f, + const std::function< void( bool match ) > & callback = nullptr ); + signals: void iconChanged( ArticleView *, QIcon const & icon ); @@ -285,6 +293,8 @@ signals: void inspectSignal(QWebEngineView * view); + void saveBookmarkSignal( const QString & bookmark ); + public slots: void on_searchPrevious_clicked(); @@ -391,7 +401,6 @@ private: void performFindOperation( bool restart, bool backwards, bool checkHighlight = false ); - bool findText(QString& text, const QWebEnginePage::FindFlags& f); void reloadStyleSheet(); diff --git a/epwing_book.cc b/epwing_book.cc index 89aa6959..3abe85b4 100644 --- a/epwing_book.cc +++ b/epwing_book.cc @@ -857,7 +857,7 @@ bool EpwingBook::getNextHeadword( EpwingHeadword & head ) { EB_Position pos; - QRegularExpression badLinks( "#(v|n)\\d" ); + QRegularExpression badLinks( "#(v|n)\\d", QRegularExpression::UseUnicodePropertiesOption); // At first we check references queue while( !LinksQueue.isEmpty() ) diff --git a/ftshelpers.cc b/ftshelpers.cc index c1a8f08f..1b7942cb 100644 --- a/ftshelpers.cc +++ b/ftshelpers.cc @@ -71,8 +71,8 @@ bool parseSearchString( QString const & str, QStringList & indexWords, { searchWords.clear(); indexWords.clear(); - QRegularExpression spacesRegExp( "\\W+" ); - QRegularExpression wordRegExp( QString( "\\w{" ) + QString::number( FTS::MinimumWordSize ) + ",}" ); + QRegularExpression spacesRegExp( "\\W+", QRegularExpression::UseUnicodePropertiesOption ); + QRegularExpression wordRegExp( QString( "\\w{" ) + QString::number( FTS::MinimumWordSize ) + ",}", QRegularExpression::UseUnicodePropertiesOption ); QRegularExpression setsRegExp( "\\[[^\\]]+\\]", QRegularExpression::CaseInsensitiveOption ); QRegularExpression regexRegExp( "\\\\[afnrtvdDwWsSbB]|\\\\x([0-9A-Fa-f]{4})|\\\\0([0-7]{3})", QRegularExpression::CaseInsensitiveOption); diff --git a/gddebug.cc b/gddebug.cc index 9fce9dd3..59958bc0 100644 --- a/gddebug.cc +++ b/gddebug.cc @@ -4,61 +4,30 @@ #include #include "gddebug.hh" #include -#if(QT_VERSION >= QT_VERSION_CHECK(6,0,0)) +#if( QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) ) #include #else #include #endif QFile * logFilePtr; -static QTextCodec * utf8Codec; -void gdWarning(const char *msg, ...) +void gdWarning( const char * msg, ... ) { -va_list ap; -va_start(ap, msg); -QTextCodec *localeCodec = 0; - - if( logFilePtr && logFilePtr->isOpen() ) - { - if( utf8Codec == 0 ) - utf8Codec = QTextCodec::codecForName( "UTF8" ); - - localeCodec = QTextCodec::codecForLocale(); - QTextCodec::setCodecForLocale( utf8Codec ); - } + va_list ap; + va_start( ap, msg ); qWarning() << QString().vasprintf( msg, ap ); - if( logFilePtr && logFilePtr->isOpen() ) - { - QTextCodec::setCodecForLocale( localeCodec ); - } - - va_end(ap); + va_end( ap ); } -void gdDebug(const char *msg, ...) +void gdDebug( const char * msg, ... ) { -va_list ap; -va_start(ap, msg); -// QTextCodec *localeCodec = 0; - - // if( logFilePtr && logFilePtr->isOpen() ) - // { - // if( utf8Codec == 0 ) - // utf8Codec = QTextCodec::codecForName( "UTF8" ); - - // localeCodec = QTextCodec::codecForLocale(); - // QTextCodec::setCodecForLocale( utf8Codec ); - // } + va_list ap; + va_start( ap, msg ); qDebug().noquote() << QString().vasprintf( msg, ap ); - // if( logFilePtr && logFilePtr->isOpen() ) - // { - // QTextCodec::setCodecForLocale( localeCodec ); - // } - - va_end(ap); + va_end( ap ); } diff --git a/goldendict.pro b/goldendict.pro index 7ff16554..d7fd2c34 100644 --- a/goldendict.pro +++ b/goldendict.pro @@ -12,7 +12,29 @@ system(git describe --tags --always --dirty): hasGit=1 !isEmpty(hasGit){ GIT_HASH=$$system(git rev-parse --short=8 HEAD ) } -system(echo $${VERSION}.$${GIT_HASH} > version.txt) + +win32{ +# date /T output is locale aware. + DD=$$system(date /T) + DATE =$$replace(DD, / , ) +} +else{ + DATE=$$system(date '+%y%m%d') +} + +system(echo $${VERSION}.$${GIT_HASH} on $${DATE} > version.txt) + +!CONFIG( verbose_build_output ) { + !win32|*-msvc* { + # Reduce build log verbosity except for MinGW builds (mingw-make cannot + # execute "@echo ..." commands inserted by qmake). + CONFIG += silent + } +} + +CONFIG( release, debug|release ) { + DEFINES += NDEBUG +} # DEPENDPATH += . generators INCLUDEPATH += . diff --git a/indexedzip.cc b/indexedzip.cc index c5b77713..438700eb 100644 --- a/indexedzip.cc +++ b/indexedzip.cc @@ -64,7 +64,7 @@ bool IndexedZip::loadFile( uint32_t offset, vector< char > & data ) if ( !ZipFile::readLocalHeader( zip, header ) ) { - GD_DPRINTF( "Failed to load header\n" ); + GD_DPRINTF( "Failed to load header" ); return false; } @@ -73,13 +73,13 @@ bool IndexedZip::loadFile( uint32_t offset, vector< char > & data ) switch( header.compressionMethod ) { case ZipFile::Uncompressed: - GD_DPRINTF( "Uncompressed\n" ); + GD_DPRINTF( "Uncompressed" ); data.resize( header.uncompressedSize ); return (size_t) zip.read( &data.front(), data.size() ) == data.size(); case ZipFile::Deflated: { - GD_DPRINTF( "Deflated\n" ); + GD_DPRINTF( "Deflated" ); // Now do the deflation diff --git a/locale/zh_CN.ts b/locale/zh_CN.ts index 832cea28..1fbe59c3 100644 --- a/locale/zh_CN.ts +++ b/locale/zh_CN.ts @@ -329,7 +329,12 @@ 引用的音频播放程序不存在。 - + + Save &Bookmark "%1..." + 保存为书签(&S)“%1...” + + + &Send "%1" to anki with selected text. 将“%1”发送到anki并附带选择的文本。 diff --git a/mainwindow.cc b/mainwindow.cc index 2ba00eb2..f8103eae 100644 --- a/mainwindow.cc +++ b/mainwindow.cc @@ -1690,6 +1690,7 @@ ArticleView * MainWindow::createNewTab( bool switchToIt, connect( view, SIGNAL( zoomIn()), this, SLOT( zoomin() ) ); connect( view, SIGNAL( zoomOut()), this, SLOT( zoomout() ) ); + connect( view, &ArticleView::saveBookmarkSignal, this, &MainWindow::addBookmarkToFavorite ); view->setSelectionBySingleClick( cfg.preferences.selectWordBySingleClick ); @@ -3503,7 +3504,7 @@ void MainWindow::on_saveArticle_triggered() // MDict anchors QRegularExpression anchorLinkRe( "(<\\s*a\\s+[^>]*\\b(?:name|id)\\b\\s*=\\s*[\"']*g[0-9a-f]{32}_)([0-9a-f]+_)(?=[^\"'])", - QRegularExpression::PatternOption::CaseInsensitiveOption ); + QRegularExpression::PatternOption::CaseInsensitiveOption|QRegularExpression::UseUnicodePropertiesOption ); html.replace( anchorLinkRe, "\\1" ); if( complete ) @@ -4656,6 +4657,15 @@ void MainWindow::addWordToFavorites( QString const & word, unsigned groupId ) ui.favoritesPaneWidget->addHeadword( folder, word ); } +void MainWindow::addBookmarkToFavorite( QString const & text ) +{ + // get current tab word. + QString word = unescapeTabHeader( ui.tabWidget->tabText( ui.tabWidget->currentIndex() ) ); + const auto bookmark = QString( "%1~~~%2" ).arg( word, text ); + + ui.favoritesPaneWidget->addHeadword( nullptr, bookmark ); +} + void MainWindow::addAllTabsToFavorites() { QString folder; @@ -4728,8 +4738,22 @@ void MainWindow::headwordFromFavorites( QString const & headword, } // Show headword without lost of focus on Favorites tree - setTranslateBoxTextAndClearSuffix( headword, EscapeWildcards, DisablePopup ); - showTranslationFor(headword ); + // bookmark cases: the favorite item may like this "word~~~selectedtext" + auto words = headword.split( "~~~" ); + + setTranslateBoxTextAndClearSuffix( words[0], EscapeWildcards, DisablePopup ); + + //must be a bookmark. + if(words.size()>1) + { + auto view = getCurrentArticleView(); + if(view) + { + view->setDelayedHighlightText(words[1]);// findText( words[ 1 ], QWebEnginePage::FindCaseSensitively ); + } + } + + showTranslationFor( words[ 0 ] ); } #ifdef Q_OS_WIN32 diff --git a/mainwindow.hh b/mainwindow.hh index 4e3e4831..882dc1ae 100644 --- a/mainwindow.hh +++ b/mainwindow.hh @@ -462,6 +462,8 @@ private slots: void addWordToFavorites( QString const & word, unsigned groupId ); + void addBookmarkToFavorite( QString const & text ); + bool isWordPresentedInFavorites( QString const & word, unsigned groupId ); void sendWordToInputLine( QString const & word ); diff --git a/zim.cc b/zim.cc index 5fcdad4f..2de86d08 100644 --- a/zim.cc +++ b/zim.cc @@ -78,7 +78,8 @@ enum CompressionType struct ZIM_header { quint32 magicNumber; - quint32 version; + quint16 majorVersion; + quint16 minorVersion; quint8 uuid[ 16 ]; quint32 articleCount; quint32 clusterCount; @@ -125,7 +126,7 @@ __attribute__((packed)) enum { Signature = 0x584D495A, // ZIMX on little-endian, XMIZ on big-endian - CurrentFormatVersion = 1 + BtreeIndexing::FormatVersion + Folding::Version + CurrentFormatVersion = 3 + BtreeIndexing::FormatVersion + Folding::Version }; struct IdxHeader @@ -158,13 +159,15 @@ struct Cache quint32 clusterNumber; int stamp; int count, size; + unsigned blobs_offset_size; Cache() : data( 0 ), clusterNumber( 0 ), stamp( -1 ), count( 0 ), - size( 0 ) + size( 0 ), + blobs_offset_size( 0 ) {} }; @@ -184,13 +187,25 @@ public: } const ZIM_header & header() const { return zimHeader; } - string getClusterData( quint32 cluster_nom ); + + string getClusterData( quint32 cluster_nom, unsigned & blob_offset_size ); + + const QString getMimeType( quint16 nom ) + { return mimeTypes.value( nom ); } + + bool isArticleMime( quint16 mime_type ) + { return getMimeType( mime_type ).startsWith( "text/html", Qt::CaseInsensitive ) + || getMimeType( mime_type ).startsWith( "text/plain", Qt::CaseInsensitive ); } + + + quint16 redirectedMimeType( RedirectEntry const & redEntry ); private: ZIM_header zimHeader; Cache cache[ CACHE_SIZE ]; int stamp; QVector< QPair< quint64, quint32 > > clusterOffsets; + QStringList mimeTypes; void clearCache(); }; @@ -291,10 +306,33 @@ bool ZimFile::open() std::sort( clusterOffsets.begin(), clusterOffsets.end() ); +// Read mime types + + string type; + char ch; + + seek( zimHeader.mimeListPos ); + + for( ; ; ) + { + type.clear(); + while( getChar( &ch ) ) + { + if( ch == 0 ) + break; + type.push_back( ch ); + } + if( type.empty() ) + break; + + QString s = QString::fromUtf8( type.c_str(), type.size() ); + mimeTypes.append( s ); + } + return true; } -string ZimFile::getClusterData( quint32 cluster_nom ) +string ZimFile::getClusterData( quint32 cluster_nom, unsigned & blobs_offset_size ) { // Check cache int target = 0; @@ -328,6 +366,7 @@ string ZimFile::getClusterData( quint32 cluster_nom ) if( found ) { // Cache hit + blobs_offset_size = cache[ target ].blobs_offset_size; return string( cache[ target ].data, cache[ target ].count ); } @@ -353,9 +392,11 @@ string ZimFile::getClusterData( quint32 cluster_nom ) seek( clusterOffsets.at( nom ).first ); - char compressionType; - if( !getChar( &compressionType ) ) + char compressionType, cluster_info; + if( !getChar( &cluster_info ) ) return string(); + compressionType = cluster_info & 0x0F; + blobs_offset_size = cluster_info & 0x10 && zimHeader.majorVersion >= 6 ? 8 : 4; string decompressedData; @@ -384,9 +425,16 @@ string ZimFile::getClusterData( quint32 cluster_nom ) // Check BLOBs number in the cluster // We cache multi-element clusters only - quint32 firstOffset; - memcpy( &firstOffset, decompressedData.data(), sizeof(firstOffset) ); - quint32 blobCount = ( firstOffset - 4 ) / 4; + quint32 firstOffset32; + quint64 firstOffset; + if( blobs_offset_size == 8 ) + memcpy( &firstOffset, decompressedData.data(), sizeof(firstOffset) ); + else + { + memcpy( &firstOffset32, decompressedData.data(), sizeof(firstOffset32) ); + firstOffset = firstOffset32; + } + quint32 blobCount = ( firstOffset - blobs_offset_size ) / blobs_offset_size; if( blobCount > 1 ) { @@ -410,12 +458,52 @@ string ZimFile::getClusterData( quint32 cluster_nom ) memcpy( cache[ target ].data, decompressedData.c_str(), size ); cache[ target ].count = size; cache[ target ].clusterNumber = cluster_nom; + cache[ target ].blobs_offset_size = blobs_offset_size; } } return decompressedData; } +quint16 ZimFile::redirectedMimeType( RedirectEntry const & redEntry ) +{ + RedirectEntry current_entry = redEntry; + quint64 current_pos = pos(); + quint16 mimetype = 0xFFFF; + + for( ; ; ) + { + quint32 current_nom = current_entry.redirectIndex; + + seek( zimHeader.urlPtrPos + (quint64)current_nom * 8 ); + quint64 new_pos; + if( read( reinterpret_cast< char * >( &new_pos ), sizeof(new_pos) ) != sizeof(new_pos) ) + break; + + seek( new_pos ); + quint16 new_mimetype; + if( read( reinterpret_cast< char * >( &new_mimetype ), sizeof(new_mimetype) ) != sizeof(new_mimetype) ) + break; + + if( new_mimetype == 0xFFFF ) // Redirect to other article + { + if( read( reinterpret_cast< char * >( ¤t_entry ) + 2, sizeof( current_entry ) - 2 ) != sizeof( current_entry ) - 2 ) + break; + if( current_nom == current_entry.redirectIndex ) + break; + } + else + { + mimetype = new_mimetype; + break; + } + } + + seek( current_pos ); + return mimetype; +} + + // Some supporting functions bool indexIsOldOrBad( string const & indexFile ) @@ -516,23 +604,42 @@ quint32 readArticle( ZimFile & file, quint32 articleNumber, string & result, // Read cluster data - string decompressedData = file.getClusterData( artEntry.clusterNumber ); + unsigned offset_size = 0; + string decompressedData = file.getClusterData( artEntry.clusterNumber, offset_size ); if( decompressedData.empty() ) break; // Take article data from cluster - quint32 firstOffset; - memcpy( &firstOffset, decompressedData.data(), sizeof(firstOffset) ); - quint32 blobCount = ( firstOffset - 4 ) / 4; + quint32 firstOffset32; + quint64 firstOffset; + + if( offset_size == 8 ) + memcpy( &firstOffset, decompressedData.data(), sizeof(firstOffset) ); + else + { + memcpy( &firstOffset32, decompressedData.data(), sizeof(firstOffset32) ); + firstOffset = firstOffset32; + } + quint32 blobCount = ( firstOffset - offset_size ) / offset_size; if( artEntry.blobNumber > blobCount ) break; - quint32 offsets[ 2 ]; - memcpy( offsets, decompressedData.data() + artEntry.blobNumber * 4, sizeof(offsets) ); - quint32 size = offsets[ 1 ] - offsets[ 0 ]; - - result.append( decompressedData, offsets[ 0 ], size ); + quint32 size; + if( offset_size == 8 ) + { + quint64 offsets[ 2 ]; + memcpy( offsets, decompressedData.data() + artEntry.blobNumber * 8, sizeof(offsets) ); + size = offsets[ 1 ] - offsets[ 0 ]; + result.append( decompressedData, offsets[ 0 ], size ); + } + else + { + quint32 offsets[ 2 ]; + memcpy( offsets, decompressedData.data() + artEntry.blobNumber * 4, sizeof(offsets) ); + size = offsets[ 1 ] - offsets[ 0 ]; + result.append( decompressedData, offsets[ 0 ], size ); + } return articleNumber; } @@ -1437,6 +1544,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries( df.open(); ZIM_header const & zh = df.header(); + bool new_namespaces = ( zh.majorVersion >= 6 && zh.minorVersion >= 1 ); if( zh.magicNumber != 0x44D495A ) throw exNotZimFile( i->c_str() ); @@ -1473,7 +1581,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries( } const quint64 * ptr; - quint16 mimetype; + quint16 mimetype, redirected_mime = 0xFFFF; ArticleEntry artEntry; RedirectEntry redEntry; string url, title; @@ -1490,6 +1598,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries( if( ret != sizeof(RedirectEntry) - 2 ) throw exCantReadFile( i->c_str() ); + redirected_mime = df.redirectedMimeType( redEntry ); nameSpace = redEntry.nameSpace; } else @@ -1501,7 +1610,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries( nameSpace = artEntry.nameSpace; - if( nameSpace == 'A' ) + if( ( nameSpace == 'A' || ( nameSpace == 'C' && new_namespaces ) ) && df.isArticleMime( mimetype ) ) articleCount++; } @@ -1524,7 +1633,8 @@ vector< sptr< Dictionary::Class > > makeDictionaries( title.push_back( ch ); } - if( nameSpace == 'A' ) + if( nameSpace == 'A' || ( nameSpace == 'C' && new_namespaces && ( df.isArticleMime( mimetype ) + || ( mimetype == 0xFFFF && df.isArticleMime( redirected_mime ) ) ) ) ) { wstring word; if( !title.empty() ) @@ -1532,16 +1642,26 @@ vector< sptr< Dictionary::Class > > makeDictionaries( else word = Utf8::decode( url ); - if( maxHeadwordsToExpand && zh.articleCount >= maxHeadwordsToExpand ) - indexedWords.addSingleWord( word, n ); + if( df.isArticleMime( mimetype ) + || ( mimetype == 0xFFFF && df.isArticleMime( redirected_mime ) ) ) + { + if( maxHeadwordsToExpand && zh.articleCount >= maxHeadwordsToExpand ) + indexedWords.addSingleWord( word, n ); + else + indexedWords.addWord( word, n ); + wordCount++; + } else - indexedWords.addWord( word, n ); - wordCount++; + { + url.insert( url.begin(), '/' ); + url.insert( url.begin(), nameSpace ); + indexedResources.addSingleWord( Utf8::decode( url ), n ); + } } else if( nameSpace == 'M' ) { - if( url.compare( "Title") == 0 ) + if( url.compare( "Title" ) == 0 ) { idxHeader.namePtr = n; string name; @@ -1549,10 +1669,10 @@ vector< sptr< Dictionary::Class > > makeDictionaries( initializing.indexingDictionary( name ); } else - if( url.compare( "Description") == 0 ) + if( url.compare( "Description" ) == 0 ) idxHeader.descriptionPtr = n; else - if( url.compare( "Language") == 0 ) + if( url.compare( "Language" ) == 0 ) { string lang; readArticle( df, n, lang ); @@ -1565,6 +1685,11 @@ vector< sptr< Dictionary::Class > > makeDictionaries( } } else + if( nameSpace == 'X' ) + { + continue; + } + else { url.insert( url.begin(), '/' ); url.insert( url.begin(), nameSpace );