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"
26 //--------------------------------------------------------------------------
28 static const char *doxygen_bst =
29 #include "doxygen.bst.h"
32 static const char *bib2xhtml_pl =
33 #include "bib2xhtml.pl.h"
36 //--------------------------------------------------------------------------
38 const QCString CiteConsts::fileName("citelist");
39 const QCString CiteConsts::anchorPrefix("CITEREF_");
40 const QCString bibTmpFile("bibTmpFile_");
41 const QCString bibTmpDir("bibTmpDir/");
43 //--------------------------------------------------------------------------
45 CiteDict::CiteDict(int size) : m_entries(size, FALSE)
47 m_entries.setAutoDelete(TRUE);
50 void CiteDict::writeLatexBibliography(FTextStream &t)
52 if (m_entries.isEmpty())
55 QCString style = Config_getString("LATEX_BIB_STYLE");
59 if (Config_getBool("COMPACT_LATEX"))
63 t << "% Bibliography\n"
66 "\\addcontentsline{toc}{" << unit << "}{" << theTranslator->trCiteReferences() << "}\n"
67 "\\bibliographystyle{" << style << "}\n"
69 QStrList &citeDataList = Config_getList("CITE_BIB_FILES");
70 QCString latexOutputDir = Config_getString("LATEX_OUTPUT")+"/";
72 const char *bibdata = citeDataList.first();
75 QCString bibFile = bibdata;
76 // Note: file can now have multiple dots
77 if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib";
78 QFileInfo fi(bibFile);
81 if (!bibFile.isEmpty())
85 t << bibTmpFile << QString().setNum(i);
88 bibdata = citeDataList.next();
94 void CiteDict::insert(const char *label)
96 m_entries.insert(label,new CiteInfo(label));
99 CiteInfo *CiteDict::find(const char *label) const
101 return label ? m_entries.find(label) : 0;
104 void CiteDict::clear()
109 bool CiteDict::isEmpty() const
111 QStrList &citeBibFiles = Config_getList("CITE_BIB_FILES");
112 return (citeBibFiles.count()==0 || m_entries.isEmpty());
115 void CiteDict::generatePage() const
117 //printf("** CiteDict::generatePage() count=%d\n",m_ordering.count());
119 // do not generate an empty citations page
120 if (isEmpty()) return; // nothing to cite
122 // 1. generate file with markers and citations to OUTPUT_DIRECTORY
124 QCString outputDir = Config_getString("OUTPUT_DIRECTORY");
125 QCString citeListFile = outputDir+"/citelist.doc";
126 f.setName(citeListFile);
127 if (!f.open(IO_WriteOnly))
129 err("could not open file %s for writing\n",citeListFile.data());
132 t << "<!-- BEGIN CITATIONS -->" << endl;
134 QDictIterator<CiteInfo> it(m_entries);
136 for (it.toFirst();(ci=it.current());++it)
138 t << "\\citation{" << ci->label << "}" << endl;
141 t << "<!-- END CITATIONS -->" << endl;
142 t << "<!-- BEGIN BIBLIOGRAPHY -->" << endl;
143 t << "<!-- END BIBLIOGRAPHY -->" << endl;
146 // 2. generate bib2xhtml
147 QCString bib2xhtmlFile = outputDir+"/bib2xhtml.pl";
148 f.setName(bib2xhtmlFile);
149 QCString bib2xhtml = bib2xhtml_pl;
150 if (!f.open(IO_WriteOnly))
152 err("could not open file %s for writing\n",bib2xhtmlFile.data());
154 f.writeBlock(bib2xhtml, bib2xhtml.length());
157 // 3. generate doxygen.bst
158 QCString doxygenBstFile = outputDir+"/doxygen.bst";
159 QCString bstData = doxygen_bst;
160 f.setName(doxygenBstFile);
161 if (!f.open(IO_WriteOnly))
163 err("could not open file %s for writing\n",doxygenBstFile.data());
165 f.writeBlock(bstData, bstData.length());
168 // 4. for all formats we just copy the bib files to as special output directory
169 // so bibtex can find them without path (bibtex doesn't support paths or
170 // filenames with spaces!)
171 // Strictly not required when only latex is generated
172 QStrList &citeDataList = Config_getList("CITE_BIB_FILES");
173 QCString bibOutputDir = outputDir+"/"+bibTmpDir;
174 QCString bibOutputFiles = "";
176 thisDir.mkdir(bibOutputDir);
177 const char *bibdata = citeDataList.first();
181 QCString bibFile = bibdata;
182 if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib";
183 QFileInfo fi(bibFile);
186 if (!bibFile.isEmpty())
189 copyFile(bibFile,bibOutputDir + bibTmpFile + QCString().setNum(i) + ".bib");
190 bibOutputFiles = bibOutputFiles + " " + bibTmpDir + bibTmpFile + QCString().setNum(i) + ".bib";
193 else if (!fi.exists())
195 err("bib file %s not found!\n",bibFile.data());
197 bibdata = citeDataList.next();
200 QString oldDir = QDir::currentDirPath();
201 QDir::setCurrent(outputDir);
203 // 5. run bib2xhtml perl script on the generated file which will insert the
204 // bibliography in citelist.doc
205 portable_system("perl","\""+bib2xhtmlFile+"\" "+bibOutputFiles+" \""+
208 QDir::setCurrent(oldDir);
210 // 6. read back the file
211 f.setName(citeListFile);
212 if (!f.open(IO_ReadOnly))
214 err("could not open file %s for reading\n",citeListFile.data());
216 bool insideBib=FALSE;
219 QFileInfo fi(citeListFile);
220 QCString input(fi.size()+1);
221 f.readBlock(input.data(),fi.size());
223 input.at(fi.size())='\0';
225 //printf("input=[%s]\n",input.data());
226 while ((s=input.find('\n',p))!=-1)
228 QCString line = input.mid(p,s-p);
229 //printf("p=%d s=%d line=[%s]\n",p,s,line.data());
232 if (line.find("<!-- BEGIN BIBLIOGRAPHY")!=-1) insideBib=TRUE;
233 else if (line.find("<!-- END BIBLIOGRAPH")!=-1) insideBib=FALSE;
234 else if (insideBib) doc+=line+"\n";
236 // determine text to use at the location of the @cite command
237 if (insideBib && (i=line.find("<a name=\"CITEREF_"))!=-1)
239 int j=line.find("\">[");
240 int k=line.find("]</a>");
243 QCString label = line.mid(i+17,j-i-17);
244 QCString number = line.mid(j+2,k-j-1);
245 CiteInfo *ci = m_entries.find(label);
246 //printf("label='%s' number='%s' => %p\n",label.data(),number.data(),ci);
254 //printf("doc=[%s]\n",doc.data());
256 // 7. add it as a page
257 addRelatedPage(CiteConsts::fileName,
258 theTranslator->trCiteReferences(),doc,0,CiteConsts::fileName,1,0,0,0);
260 // 8. for latex we just copy the bib files to the output and let
261 // latex do this work.
262 if (Config_getBool("GENERATE_LATEX"))
264 // copy bib files to the latex output dir
265 QStrList &citeDataList = Config_getList("CITE_BIB_FILES");
266 QCString latexOutputDir = Config_getString("LATEX_OUTPUT")+"/";
268 const char *bibdata = citeDataList.first();
271 QCString bibFile = bibdata;
272 // Note: file can now have multiple dots
273 if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib";
274 QFileInfo fi(bibFile);
277 if (!bibFile.isEmpty())
279 // bug_700510, multile times the same name were overwriting; creating new names
280 // also for names with spaces
282 copyFile(bibFile,latexOutputDir + bibTmpFile + QCString().setNum(i) + ".bib");
287 err("bib file %s not found!\n",bibFile.data());
289 bibdata = citeDataList.next();
293 // 9. Remove temporary files
294 thisDir.remove(citeListFile);
295 thisDir.remove(doxygenBstFile);
296 thisDir.remove(bib2xhtmlFile);
297 bibdata = citeDataList.first();
298 // we might try to remove too many files as empty files didn't get a coresponding new file
299 // but the remove function does not emit an error for it and we don't catch the error return
301 for (unsigned int j = 1; j <= citeDataList.count(); j++)
303 thisDir.remove(bibOutputDir + bibTmpFile + QCString().setNum(j) + ".bib");
305 thisDir.rmdir(bibOutputDir);