From fa520f975a0893c0d123c1cafec63206bf737794 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Sun, 16 Feb 2020 16:36:19 +0100 Subject: Restructure citation handling --- src/cite.cpp | 277 ++++++++++++++++++++++++++++-------------------- src/cite.h | 81 ++++++-------- src/commentscan.l | 2 +- src/docparser.cpp | 23 ++-- src/doxygen.cpp | 9 +- src/doxygen.h | 1 - src/latexdocvisitor.cpp | 3 +- src/latexgen.cpp | 4 +- 8 files changed, 214 insertions(+), 186 deletions(-) diff --git a/src/cite.cpp b/src/cite.cpp index 797881f..612ddc1 100644 --- a/src/cite.cpp +++ b/src/cite.cpp @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright (C) 2011 by Dimitri van Heesch + * Copyright (C) 2020 by Dimitri van Heesch * Based on a patch by David Munger * * Permission to use, copy, modify, and distribute this software and its @@ -15,116 +15,112 @@ */ #include "cite.h" -#include "portable.h" #include "config.h" -#include "message.h" -#include "util.h" -#include "language.h" #include "ftextstream.h" +#include "language.h" +#include "message.h" +#include "portable.h" #include "resourcemgr.h" -#include "doxygen.h" +#include "util.h" + +#include +#include #include -//-------------------------------------------------------------------------- +#include +#include + +// Remove the temporary files +#define RM_TMP_FILES (true) +//#define RM_TMP_FILES (false) + +const char *bibTmpFile = "bibTmpFile_"; +const char *bibTmpDir = "bibTmpDir/"; + +class CiteInfoImpl : public CiteInfo +{ + public: + CiteInfoImpl(const char *label, const char *text=0) + : m_label(label), m_text(text) { } + + virtual QCString label() const { return m_label; } + virtual QCString text() const { return m_text; } + + void setText(const char *s) { m_text = s; } -const QCString CiteConsts::fileName("citelist"); -/* when changing this also take doxygen.bst into account */ -const QCString CiteConsts::anchorPrefix("CITEREF_"); -const QCString bibTmpFile("bibTmpFile_"); -const QCString bibTmpDir("bibTmpDir/"); + private: + QCString m_label; + QCString m_text; +}; -//-------------------------------------------------------------------------- +struct CitationManager::Private +{ + std::map< std::string,std::unique_ptr > entries; +}; -CiteDict::CiteDict(int size) : m_entries(size, FALSE) -{ - m_entries.setAutoDelete(TRUE); +CitationManager &CitationManager::instance() +{ + static CitationManager ct; + return ct; } -void CiteDict::writeLatexBibliography(FTextStream &t) +CitationManager::CitationManager() : p(new Private) { - if (m_entries.isEmpty()) - return; +} - QCString style = Config_getString(LATEX_BIB_STYLE); - if (style.isEmpty()) - style="plain"; - QCString unit; - if (Config_getBool(COMPACT_LATEX)) - unit = "section"; - else - unit = "chapter"; - t << "% Bibliography\n" - "\\newpage\n" - "\\phantomsection\n"; - bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); - if (!pdfHyperlinks) - { - t << "\\clearemptydoublepage\n"; - t << "\\addcontentsline{toc}{" << unit << "}{" << theTranslator->trCiteReferences() << "}\n"; - } - t << "\\bibliographystyle{" << style << "}\n" - "\\bibliography{"; - QStrList &citeDataList = Config_getList(CITE_BIB_FILES); - int i = 0; - const char *bibdata = citeDataList.first(); - while (bibdata) - { - QCString bibFile = bibdata; - // Note: file can now have multiple dots - if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib"; - QFileInfo fi(bibFile); - if (fi.exists()) - { - if (!bibFile.isEmpty()) - { - if (i) t << ","; - i++; - t << bibTmpFile << QCString().setNum(i); - } - } - bibdata = citeDataList.next(); - } - t << "}\n"; - if (pdfHyperlinks) +void CitationManager::insert(const char *label) +{ + p->entries.insert( + std::make_pair( + std::string(label), + std::make_unique(label) + )); +} + +const CiteInfo *CitationManager::find(const char *label) const +{ + auto it = p->entries.find(label); + if (it!=p->entries.end()) { - t << "\\addcontentsline{toc}{" << unit << "}{" << theTranslator->trCiteReferences() << "}\n"; + return it->second.get(); } - t << "\n"; + return 0; } -void CiteDict::insert(const char *label) +void CitationManager::clear() { - m_entries.insert(label,new CiteInfo(label)); + p->entries.clear(); } -CiteInfo *CiteDict::find(const char *label) const +bool CitationManager::isEmpty() const { - return label ? m_entries.find(label) : 0; + int numFiles = Config_getList(CITE_BIB_FILES).count(); + return (numFiles==0 || p->entries.empty()); } -void CiteDict::clear() +const char *CitationManager::fileName() const { - m_entries.clear(); + return "citelist"; } -bool CiteDict::isEmpty() const +const char *CitationManager::anchorPrefix() const { - QStrList &citeBibFiles = Config_getList(CITE_BIB_FILES); - return (citeBibFiles.count()==0 || m_entries.isEmpty()); + return "CITEREF_"; } -void CiteDict::generatePage() const +void CitationManager::generatePage() { - //printf("** CiteDict::generatePage() count=%d\n",m_ordering.count()); + //printf("** CitationManager::generatePage() count=%d\n",m_ordering.count()); // do not generate an empty citations page if (isEmpty()) return; // nothing to cite // 0. add cross references from the bib files to the cite dictionary QFile f; - QStrList &citeDataList = Config_getList(CITE_BIB_FILES); - const char *bibdata = citeDataList.first(); - while (bibdata) + const QStrList &citeDataList = Config_getList(CITE_BIB_FILES); + QStrListIterator li(citeDataList); + const char *bibdata = 0; + for (li.toFirst() ; (bibdata = li.current()) ; ++li) { QCString bibFile = bibdata; if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib"; @@ -144,11 +140,11 @@ void CiteDict::generatePage() const f.readBlock(input.rawData(),fi.size()); f.close(); input.at(fi.size())='\0'; - int p=0,s; - while ((s=input.find('\n',p))!=-1) + int pos=0,s; + while ((s=input.find('\n',pos))!=-1) { - QCString line = input.mid(p,s-p); - p=s+1; + QCString line = input.mid(pos,s-pos); + pos=s+1; int i; if ((i = line.find("crossref")) != -1) /* assumption cross reference is on one line and the only item */ @@ -158,7 +154,10 @@ void CiteDict::generatePage() const if (j!=-1 && k!=-1) { QCString label = line.mid(j+1,k-j-1); - if (!m_entries.find(label)) Doxygen::citeDict->insert(label.data()); + if (p->entries.find(label.data())==p->entries.end()) // not found yet + { + insert(label); + } } } } @@ -168,7 +167,6 @@ void CiteDict::generatePage() const { err("bib file %s not found!\n",bibFile.data()); } - bibdata = citeDataList.next(); } // 1. generate file with markers and citations to OUTPUT_DIRECTORY @@ -182,11 +180,9 @@ void CiteDict::generatePage() const FTextStream t(&f); t << "" << endl; t << "" << endl; t << "" << endl; @@ -210,9 +206,8 @@ void CiteDict::generatePage() const QCString bibOutputFiles = ""; QDir thisDir; thisDir.mkdir(bibOutputDir); - bibdata = citeDataList.first(); int i = 0; - while (bibdata) + for (li.toFirst() ; (bibdata = li.current()) ; ++li) { QCString bibFile = bibdata; if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib"; @@ -226,7 +221,6 @@ void CiteDict::generatePage() const bibOutputFiles = bibOutputFiles + " " + bibTmpDir + bibTmpFile + QCString().setNum(i) + ".bib"; } } - bibdata = citeDataList.next(); } QString oldDir = QDir::currentDirPath(); @@ -260,13 +254,13 @@ void CiteDict::generatePage() const f.readBlock(input.rawData(),fi.size()); f.close(); input.at(fi.size())='\0'; - int p=0,s; + int pos=0,s; //printf("input=[%s]\n",input.data()); - while ((s=input.find('\n',p))!=-1) + while ((s=input.find('\n',pos))!=-1) { - QCString line = input.mid(p,s-p); - //printf("p=%d s=%d line=[%s]\n",p,s,line.data()); - p=s+1; + QCString line = input.mid(pos,s-pos); + //printf("pos=%d s=%d line=[%s]\n",pos,s,line.data()); + pos=s+1; if (line.find("