summaryrefslogtreecommitdiffstats
path: root/src/cite.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/cite.cpp')
-rw-r--r--src/cite.cpp356
1 files changed, 356 insertions, 0 deletions
diff --git a/src/cite.cpp b/src/cite.cpp
new file mode 100644
index 0000000..f460149
--- /dev/null
+++ b/src/cite.cpp
@@ -0,0 +1,356 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2011 by Dimitri van Heesch
+ * Based on a patch by David Munger
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * Documents produced by Doxygen are derivative works derived from the
+ * input used in their production; they are not affected by this license.
+ *
+ */
+
+#include "cite.h"
+#include "portable.h"
+#include "config.h"
+#include "message.h"
+#include "util.h"
+#include "language.h"
+#include "ftextstream.h"
+#include <qdir.h>
+
+//--------------------------------------------------------------------------
+
+static const char *doxygen_bst =
+#include "doxygen_bst.h"
+;
+
+//--------------------------------------------------------------------------
+
+const QCString CiteConsts::fileName("citelist");
+const QCString CiteConsts::anchorPrefix("CITEREF_");
+
+//--------------------------------------------------------------------------
+
+static bool writeBstFile(const QString &fileName)
+{
+ QCString bstData = doxygen_bst;
+ QFile f(fileName);
+ if (!f.open(IO_WriteOnly))
+ {
+ err("error: could not open file %s for writing\n",fileName.data());
+ return FALSE;
+ }
+ f.writeBlock(bstData, strlen(bstData));
+ return TRUE;
+}
+
+//--------------------------------------------------------------------------
+
+CiteDict::CiteDict(int size) : m_entries(size, FALSE)
+{
+ m_ordering.setAutoDelete(TRUE);
+ m_entries.setAutoDelete(TRUE);
+}
+
+bool CiteDict::writeAux()
+{
+ //msg("..writing aux file\n");
+ QCString auxFileName(m_baseFileName + ".aux");
+ QFile auxFile(auxFileName);
+ if (!auxFile.open(IO_WriteOnly))
+ // point it to something valid, because warn() relies on it
+ {
+ err("Error opening file %s for output\n", auxFileName.data());
+ return FALSE;
+ }
+ FTextStream t(&auxFile);
+
+ QDictIterator<CiteInfo> cdi(m_entries);
+ for (CiteInfo *ci = 0; (ci=cdi.current()); ++cdi)
+ {
+ t << "\\citation{" << ci->label << "}\n";
+ }
+
+ t << "\\bibstyle{" << m_baseFileName << "}\n";
+
+ t << "\\bibdata{";
+ QStrList &citeDataList = Config_getList("CITE_BIB_FILES");
+ const char *bibdata = citeDataList.first();
+ while (bibdata)
+ {
+ QCString bibFile = bibdata;
+ if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib";
+ if (!bibFile.isEmpty())
+ {
+ QFileInfo fi(bibFile);
+ if (fi.exists())
+ {
+ if (!copyFile(bibFile,m_baseFileName+"_"+bibFile))
+ {
+ return FALSE;
+ }
+ t << m_baseFileName+"_"+bibFile;
+ bibdata = citeDataList.next();
+ if (bibdata)
+ {
+ t << ",";
+ }
+ }
+ else
+ {
+ err("The file %s specified at CITE_BIB_FILES could not be read!\n",bibdata);
+ return FALSE;
+ }
+ }
+ else
+ {
+ bibdata = citeDataList.next();
+ }
+ }
+ t << "}\n";
+ return TRUE;
+}
+
+bool CiteDict::writeBst()
+{
+ //msg("..writing bst file\n");
+ QCString bstFileName = m_baseFileName + ".bst";
+ return writeBstFile(bstFileName);
+}
+
+void CiteDict::writeDefaultBibStyle()
+{
+ writeBstFile("doxygen.bst");
+ msg("wrote doxygen.bst\n");
+}
+
+void CiteDict::writeLatexBibliography(FTextStream &t)
+{
+ if (m_entries.count()==0) return;
+ QCString style = Config_getString("LATEX_BIB_STYLE");
+ if (style.isEmpty()) style="plain";
+ t << "\\newpage \\bibliographystyle{" << style << "}" << endl;
+ t << "\\bibliography{";
+ QStrList &citeDataList = Config_getList("CITE_BIB_FILES");
+ const char *bibdata = citeDataList.first();
+ while (bibdata)
+ {
+ QCString bibFile = bibdata;
+ if (!bibFile.isEmpty())
+ {
+ t << bibFile;
+ bibdata = citeDataList.next();
+ if (bibdata)
+ {
+ t << ",";
+ }
+ }
+ else
+ {
+ bibdata = citeDataList.next();
+ }
+ }
+ t << "}" << endl;
+}
+
+void CiteDict::insert(const char *label)
+{
+ m_entries.insert(label,new CiteInfo(label));
+}
+
+CiteInfo *CiteDict::find(const char *label) const
+{
+ return label ? m_entries.find(label) : 0;
+}
+
+void CiteDict::clear()
+{
+ m_entries.clear();
+ m_ordering.clear();
+}
+
+bool CiteDict::execute()
+{
+ //msg("..running bibtex\n");
+ bool result=TRUE;
+ QCString auxFileName(m_baseFileName + ".aux");
+ int splitPoint = auxFileName.findRev('/');
+ QCString dirname = auxFileName.left(splitPoint);
+ QCString basename = auxFileName.mid(splitPoint + 1);
+ QCString oldDir = convertToQCString(QDir::currentDirPath());
+ QDir::setCurrent(dirname);
+ QCString args;
+ args += "-terse ";
+ args += basename;
+ portable_system("bibtex", args);
+ int exitCode;
+ if ((exitCode=portable_system("bibtex",args))!=0)
+ {
+ err("Problems running bibtex: exit code=%d, command='bibtex', arguments='%s'\n",
+ exitCode,args.data());
+ result=FALSE;
+ }
+ QDir::setCurrent(oldDir);
+ return result;
+}
+
+void CiteDict::parse()
+{
+ //msg("..parsing bbl file\n");
+ QCString bblFileName(m_baseFileName + ".bbl");
+ QFile f(bblFileName);
+ if (!f.open(IO_ReadOnly))
+ {
+ err("error: could not open file %s\n",bblFileName.data());
+ return;
+ }
+
+ m_ordering.clear();
+
+ QTextStream t(&f);
+ QCString label;
+ QCString line;
+ while (!t.eof())
+ {
+ label=t.readLine();
+ if (label.isEmpty())
+ {
+ continue;
+ }
+
+ CiteInfo* ci = m_entries.find(label);
+ if (!ci) insert(label);
+
+ // BibTeX has its own way of sorting references,
+ // depending on the .bst file
+ m_ordering.append(new QCString(label));
+
+ ci->text=t.readLine();
+
+ while (!(line=t.readLine()).isEmpty())
+ {
+ ci->fullText += line + '\n';
+ }
+
+ // FIXME: process LaTeX-style accents properly
+ ci->fullText = substitute(substitute(substitute(ci->fullText,
+ "{", ""),
+ "}", ""),
+ "~", " ");
+
+ //printf("BIB ENTRY: %s -> %s: %s\n", ci->label.data(), ci->text.data(), ci->fullText.data());
+ }
+}
+
+void CiteDict::clean()
+{
+ // clean
+ QDir thisDir;
+ QStrList &citeDataList = Config_getList("CITE_BIB_FILES");
+ const char *bibdata = citeDataList.first();
+ while (bibdata)
+ {
+ QCString bibFile = bibdata;
+ if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib";
+ if (!bibFile.isEmpty()) thisDir.remove(m_baseFileName+"_"+bibFile);
+ bibdata = citeDataList.next();
+ }
+
+ thisDir.remove(m_baseFileName + ".aux");
+ thisDir.remove(m_baseFileName + ".bbl");
+ thisDir.remove(m_baseFileName + ".blg");
+ thisDir.remove(m_baseFileName + ".tmp");
+ thisDir.remove(m_baseFileName + ".bst");
+
+ QCString &outputDirectory = Config_getString("OUTPUT_DIRECTORY");
+ if (outputDirectory.isEmpty())
+ {
+ outputDirectory=QDir::currentDirPath();
+ }
+ QDir d(outputDirectory);
+ d.rmdir("bib");
+}
+
+void CiteDict::resolve()
+{
+ QStrList &citeBibFiles = Config_getList("CITE_BIB_FILES");
+ if (citeBibFiles.count()==0 || m_entries.count()==0) return; // nothing to cite
+
+ QCString &outputDirectory = Config_getString("OUTPUT_DIRECTORY");
+ if (outputDirectory.isEmpty())
+ {
+ outputDirectory=QDir::currentDirPath();
+ }
+ QDir d(outputDirectory);
+ d.mkdir("bib");
+
+ uint pid = portable_pid();
+ m_baseFileName.sprintf("doxygen_bibtex_%d",pid);
+ m_baseFileName.prepend(outputDirectory+"/bib/");
+
+ if (writeAux() && writeBst() && execute())
+ {
+ parse();
+ clean();
+ }
+
+ if (Config_getBool("GENERATE_LATEX"))
+ {
+ // copy bib files to the latex output dir
+ QStrList &citeDataList = Config_getList("CITE_BIB_FILES");
+ QCString latexOutputDir = Config_getString("LATEX_OUTPUT")+"/";
+ const char *bibdata = citeDataList.first();
+ while (bibdata)
+ {
+ QCString bibFile = bibdata;
+ if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib";
+ if (!bibFile.isEmpty())
+ {
+ copyFile(bibFile,latexOutputDir+bibFile);
+ }
+ bibdata = citeDataList.next();
+ }
+ }
+}
+
+bool CiteDict::isEmpty() const
+{
+ QStrList &citeBibFiles = Config_getList("CITE_BIB_FILES");
+ return (citeBibFiles.count()==0 || m_ordering.isEmpty());
+}
+
+void CiteDict::generatePage() const
+{
+ //printf("** CiteDict::generatePage() count=%d\n",m_ordering.count());
+
+ // do not generate an empty citations page
+ if (isEmpty()) return; // nothing to cite
+
+ QCString doc;
+ doc += "<dl class=\"citelist\">";
+
+ QListIterator<QCString> it(m_ordering);
+ QCString *s;
+ for (it.toFirst();(s=it.current());++it)
+ {
+ CiteInfo* ci = m_entries.find(*s);
+ doc += " <dt>";
+ doc += "\\anchor ";
+ doc += CiteConsts::anchorPrefix + ci->label;
+ doc += "\n";
+ doc += ci->text;
+ doc += "</dt><dd> ";
+ doc += ci->fullText;
+ doc += "</dd>";
+ }
+ doc += "</dl>\n";
+ //printf("addRelatedPage with doc='%s'\n",doc.data());
+ addRelatedPage(CiteConsts::fileName,
+ theTranslator->trCiteReferences(),doc,0,CiteConsts::fileName,1,0,0,0);
+}
+