1 /******************************************************************************
3 * Copyright (C) 2011 by Dimitri van Heesch
4 * Based on a patch by David Munger
6 * Permission to use, copy, modify, and distribute this software and its
7 * documentation under the terms of the GNU General Public License is hereby
8 * granted. No representations are made about the suitability of this software
9 * for any purpose. It is provided "as is" without express or implied warranty.
10 * See the GNU General Public License for more details.
12 * Documents produced by Doxygen are derivative works derived from the
13 * input used in their production; they are not affected by this license.
23 #include "ftextstream.h"
24 #include "resourcemgr.h"
27 //--------------------------------------------------------------------------
29 const QCString CiteConsts::fileName("citelist");
30 const QCString CiteConsts::anchorPrefix("CITEREF_");
31 const QCString bibTmpFile("bibTmpFile_");
32 const QCString bibTmpDir("bibTmpDir/");
34 //--------------------------------------------------------------------------
36 CiteDict::CiteDict(int size) : m_entries(size, FALSE)
38 m_entries.setAutoDelete(TRUE);
41 void CiteDict::writeLatexBibliography(FTextStream &t)
43 if (m_entries.isEmpty())
46 QCString style = Config_getString(LATEX_BIB_STYLE);
50 if (Config_getBool(COMPACT_LATEX))
54 t << "% Bibliography\n"
57 bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
60 t << "\\clearemptydoublepage\n";
61 t << "\\addcontentsline{toc}{" << unit << "}{" << theTranslator->trCiteReferences() << "}\n";
63 t << "\\bibliographystyle{" << style << "}\n"
65 QStrList &citeDataList = Config_getList(CITE_BIB_FILES);
67 const char *bibdata = citeDataList.first();
70 QCString bibFile = bibdata;
71 // Note: file can now have multiple dots
72 if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib";
73 QFileInfo fi(bibFile);
76 if (!bibFile.isEmpty())
80 t << bibTmpFile << QString().setNum(i);
83 bibdata = citeDataList.next();
88 t << "\\addcontentsline{toc}{" << unit << "}{" << theTranslator->trCiteReferences() << "}\n";
93 void CiteDict::insert(const char *label)
95 m_entries.insert(label,new CiteInfo(label));
98 CiteInfo *CiteDict::find(const char *label) const
100 return label ? m_entries.find(label) : 0;
103 void CiteDict::clear()
108 bool CiteDict::isEmpty() const
110 QStrList &citeBibFiles = Config_getList(CITE_BIB_FILES);
111 return (citeBibFiles.count()==0 || m_entries.isEmpty());
114 void CiteDict::generatePage() const
116 //printf("** CiteDict::generatePage() count=%d\n",m_ordering.count());
118 // do not generate an empty citations page
119 if (isEmpty()) return; // nothing to cite
121 // 1. generate file with markers and citations to OUTPUT_DIRECTORY
123 QCString outputDir = Config_getString(OUTPUT_DIRECTORY);
124 QCString citeListFile = outputDir+"/citelist.doc";
125 f.setName(citeListFile);
126 if (!f.open(IO_WriteOnly))
128 err("could not open file %s for writing\n",citeListFile.data());
131 t << "<!-- BEGIN CITATIONS -->" << endl;
133 QDictIterator<CiteInfo> it(m_entries);
135 for (it.toFirst();(ci=it.current());++it)
137 t << "\\citation{" << ci->label << "}" << endl;
140 t << "<!-- END CITATIONS -->" << endl;
141 t << "<!-- BEGIN BIBLIOGRAPHY -->" << endl;
142 t << "<!-- END BIBLIOGRAPHY -->" << endl;
145 // 2. generate bib2xhtml
146 QCString bib2xhtmlFile = outputDir+"/bib2xhtml.pl";
147 ResourceMgr::instance().copyResource("bib2xhtml.pl",outputDir);
149 // 3. generate doxygen.bst
150 QCString doxygenBstFile = outputDir+"/doxygen.bst";
151 ResourceMgr::instance().copyResource("doxygen.bst",outputDir);
153 // 4. for all formats we just copy the bib files to as special output directory
154 // so bibtex can find them without path (bibtex doesn't support paths or
155 // filenames with spaces!)
156 // Strictly not required when only latex is generated
157 QStrList &citeDataList = Config_getList(CITE_BIB_FILES);
158 QCString bibOutputDir = outputDir+"/"+bibTmpDir;
159 QCString bibOutputFiles = "";
161 thisDir.mkdir(bibOutputDir);
162 const char *bibdata = citeDataList.first();
166 QCString bibFile = bibdata;
167 if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib";
168 QFileInfo fi(bibFile);
171 if (!bibFile.isEmpty())
174 copyFile(bibFile,bibOutputDir + bibTmpFile + QCString().setNum(i) + ".bib");
175 bibOutputFiles = bibOutputFiles + " " + bibTmpDir + bibTmpFile + QCString().setNum(i) + ".bib";
178 else if (!fi.exists())
180 err("bib file %s not found!\n",bibFile.data());
182 bibdata = citeDataList.next();
185 QString oldDir = QDir::currentDirPath();
186 QDir::setCurrent(outputDir);
188 // 5. run bib2xhtml perl script on the generated file which will insert the
189 // bibliography in citelist.doc
191 portable_sysTimerStop();
192 if ((exitCode=portable_system("perl","\""+bib2xhtmlFile+"\" "+bibOutputFiles+" \""+
193 citeListFile+"\"")) != 0)
195 err("Problems running bibtex. Verify that the command 'perl --version' works from the command line. Exit code: %d\n",
198 portable_sysTimerStop();
200 QDir::setCurrent(oldDir);
202 // 6. read back the file
203 f.setName(citeListFile);
204 if (!f.open(IO_ReadOnly))
206 err("could not open file %s for reading\n",citeListFile.data());
208 bool insideBib=FALSE;
211 QFileInfo fi(citeListFile);
212 QCString input(fi.size()+1);
213 f.readBlock(input.rawData(),fi.size());
215 input.at(fi.size())='\0';
217 //printf("input=[%s]\n",input.data());
218 while ((s=input.find('\n',p))!=-1)
220 QCString line = input.mid(p,s-p);
221 //printf("p=%d s=%d line=[%s]\n",p,s,line.data());
224 if (line.find("<!-- BEGIN BIBLIOGRAPHY")!=-1) insideBib=TRUE;
225 else if (line.find("<!-- END BIBLIOGRAPH")!=-1) insideBib=FALSE;
226 else if (insideBib) doc+=line+"\n";
228 // determine text to use at the location of the @cite command
229 if (insideBib && (i=line.find("name=\"CITEREF_"))!=-1)
231 int j=line.find("\">[");
232 int k=line.find("]</a>");
235 QCString label = line.mid(i+14,j-i-14);
236 QCString number = line.mid(j+2,k-j-1);
237 CiteInfo *ci = m_entries.find(label);
238 //printf("label='%s' number='%s' => %p\n",label.data(),number.data(),ci);
246 //printf("doc=[%s]\n",doc.data());
248 // 7. add it as a page
249 addRelatedPage(CiteConsts::fileName,
250 theTranslator->trCiteReferences(),doc,0,CiteConsts::fileName,1,0,0,0);
252 // 8. for latex we just copy the bib files to the output and let
253 // latex do this work.
254 if (Config_getBool(GENERATE_LATEX))
256 // copy bib files to the latex output dir
257 QStrList &citeDataList = Config_getList(CITE_BIB_FILES);
258 QCString latexOutputDir = Config_getString(LATEX_OUTPUT)+"/";
260 const char *bibdata = citeDataList.first();
263 QCString bibFile = bibdata;
264 // Note: file can now have multiple dots
265 if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib";
266 QFileInfo fi(bibFile);
269 if (!bibFile.isEmpty())
271 // bug_700510, multile times the same name were overwriting; creating new names
272 // also for names with spaces
274 copyFile(bibFile,latexOutputDir + bibTmpFile + QCString().setNum(i) + ".bib");
279 err("bib file %s not found!\n",bibFile.data());
281 bibdata = citeDataList.next();
285 // 9. Remove temporary files
286 thisDir.remove(citeListFile);
287 thisDir.remove(doxygenBstFile);
288 thisDir.remove(bib2xhtmlFile);
289 // we might try to remove too many files as empty files didn't get a corresponding new file
290 // but the remove function does not emit an error for it and we don't catch the error return
292 for (unsigned int j = 1; j <= citeDataList.count(); j++)
294 thisDir.remove(bibOutputDir + bibTmpFile + QCString().setNum(j) + ".bib");
296 thisDir.rmdir(bibOutputDir);