1 /**************************************************************************//**
2  * \file        ExtractDocs.cpp
3  * \author    Gary Harris
4  * \date        01-02-2010
5  *
6  * DoxyBlocks - doxygen integration for Code::Blocks. \n
7  * Copyright (C) 2010 Gary Harris.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  *----------------------------------------------------------------------------------------------- \n
23  * The initial inspiration and framework for DoxyBlocks were derived
24  * from:
25  *
26  * doxygen_docs.script by jomeggs.             \n
27  * Script for automated doxygen documentation. \n
28  * Released under GPL3.                        \n
29  * (appears to be version 04)
30  *
31  * and this code, which is where DoxyBlocks started, owes it's origins
32  * to that script and jomeggs' lead-up work.
33  *
34  * Many thanks.
35  *****************************************************************************/
36 #include "sdk.h"
37 #ifndef CB_PRECOMP
38     #include <cbproject.h>
39     #include <macrosmanager.h>
40     #include <projectfile.h>
41     #include <projectmanager.h>
42 #endif
43 #include <wx/busyinfo.h>
44 #include <wx/ffile.h>
45 #include <wx/utils.h>
46 
47 #include "DoxyBlocks.h"
48 
49 
OnExtractProject(wxCommandEvent & WXUNUSED (event))50 void DoxyBlocks::OnExtractProject(wxCommandEvent & WXUNUSED(event))
51 {
52     DoExtractProject();
53 }
54 
55 /*! \brief Extract and compile documentation for the currently active project.
56  */
DoExtractProject()57 void DoxyBlocks::DoExtractProject()
58 {
59     if(!IsProjectOpen()){
60         return;
61     }
62 
63     cbProject* prj = Manager::Get()->GetProjectManager()->GetActiveProject();
64     if(!prj){
65         wxString sMsg = _("Failed to get the active project!");
66         AppendToLog(sMsg, LOG_ERROR);
67         return;
68     }
69 
70     // Check whether AutoVersioning is active for this project.
71     if(m_bAutoVersioning){
72         // If we're using autoversion for docs, get the value.
73         if(m_pConfig->GetUseAutoVersion()){
74             m_sAutoVersion = GetAutoVersion();
75             m_pConfig->SetProjectNumber(m_sAutoVersion);
76             // Update the config object and mark the project as modified so the new version gets saved on exit.
77             SaveSettings();
78             prj->SetModified();
79         }
80     }
81 
82     AppendToLog(wxT("----------------------------------------------------------------------------------------------------"));
83     AppendToLog(_("Extracting documentation for ") + prj->GetTitle() + wxT("."));
84     AppendToLog(_("DoxyBlocks is working, please wait a few moments..."));
85 
86     {
87         wxBusyInfo running(_("Running doxygen. Please wait..."), Manager::Get()->GetAppWindow());
88         GenerateDocuments(prj);
89     } // end lifetime of wxBusyInfo.
90 
91     AppendToLog(_("\nDone.\n"));
92 }
93 
94 namespace
95 {
96 /*! \brief Converts a boolean value to a string.
97  *
98  * \param val             The boolean value to convert.
99  * \return wxString    "YES" or "NO".
100  *
101  */
BoolToString(bool val)102 wxString BoolToString(bool val)
103 {
104     return (val ? wxT("YES") : wxT("NO"));
105 }
106 }
107 
108 
109 /*! \brief Write the doxygen configuration and log files.
110  *
111  * \param    prj             cbProject*        The project.
112  * \param    sPrjName        wxString          The project's name.
113  * \param    sPrjPath        wxString          The path to the project.
114  * \param    sDoxygenDir     wxString          The relative path to the doxygen files.
115  * \param    fnDoxyfile      wxFileName        Doxyfile filename object.
116  * \param    fnDoxygenLog    wxFileName        Doxygen log filename object.
117  *
118  */
WriteConfigFiles(cbProject * prj,wxString sPrjName,wxString,wxString,wxFileName fnDoxyfile,wxFileName fnDoxygenLog)119 void DoxyBlocks::WriteConfigFiles(cbProject *prj, wxString sPrjName, wxString /*sPrjPath*/, wxString /*sDoxygenDir*/, wxFileName fnDoxyfile, wxFileName fnDoxygenLog)
120 {
121     wxArrayString sOutput;
122     wxArrayString sErrors;
123     MacrosManager    *pMacMngr = Manager::Get()->GetMacrosManager();
124 
125      // If there is no config file, create one. If it exists, check prefs.
126     bool bWrite = true;
127     if(wxFile::Exists(fnDoxyfile.GetFullPath())){
128         bWrite = false;
129         AppendToLog(_("Found existing doxyfile..."));
130         bool bOverwriteDoxyfile = m_pConfig->GetOverwriteDoxyfile();
131         if(bOverwriteDoxyfile){
132             bool bPromptB4Overwriting = m_pConfig->GetPromptBeforeOverwriting();
133             if(bPromptB4Overwriting){
134                 if(wxMessageBox(_("Overwrite existing doxyfile?"), wxT("DoxyBlocks"), wxYES_NO|wxCENTRE) == wxYES){
135                     bWrite = true;
136                 }
137             }
138             else{
139                 bWrite = true;
140             }
141         }
142     }
143 
144     if(bWrite){
145         AppendToLog(_("Writing doxyfile..."));
146         // Keep the CHM separate for easy access.
147         wxString sChmFile = wxT("../") + sPrjName + wxT(".chm");
148         // Get the list of files from which to extract documentation.
149         wxString sInputList = GetInputList(prj, fnDoxyfile);
150 
151         // Project.
152         wxString sPrjNum = m_pConfig->GetProjectNumber();
153         wxString sLanguage = m_pConfig->GetOutputLanguage();
154         // Build.
155         wxString sExtractAll = BoolToString(m_pConfig->GetExtractAll());
156         wxString sExtractPrivate = BoolToString(m_pConfig->GetExtractPrivate());
157         wxString sExtractStatic = BoolToString(m_pConfig->GetExtractStatic());
158         // Warnings.
159         wxString sWarnings = BoolToString(m_pConfig->GetWarnings());
160         wxString sWarnIfUndoc = BoolToString(m_pConfig->GetWarnIfUndocumented());
161         wxString sWarnIfDocError = BoolToString(m_pConfig->GetWarnIfDocError());
162         wxString sWarnNoParamDoc = BoolToString(m_pConfig->GetWarnNoParamdoc());
163         //  Alphabetical Class Index.
164         wxString sAlphaIndex = BoolToString(m_pConfig->GetAlphabeticalIndex());
165         // Output.
166         wxString sGenerateHTML = BoolToString(m_pConfig->GetGenerateHTML());
167         wxString sGenerateHTMLHelp = BoolToString(m_pConfig->GetGenerateHTMLHelp());
168         wxString sPathHHC = pMacMngr->ReplaceMacros(m_pConfig->GetPathHHC());
169         wxString sGenerateCHI = BoolToString(m_pConfig->GetGenerateCHI());
170         wxString sBinaryTOC = BoolToString(m_pConfig->GetBinaryTOC());
171         wxString sGenerateLatex = BoolToString(m_pConfig->GetGenerateLatex());
172         wxString sGenerateRTF = BoolToString(m_pConfig->GetGenerateRTF());
173         wxString sGenerateMan = BoolToString(m_pConfig->GetGenerateMan());
174         wxString sGenerateXML = BoolToString(m_pConfig->GetGenerateXML());
175         wxString sGenerateAutogenDef = BoolToString(m_pConfig->GetGenerateAutogenDef());
176         wxString sGeneratePerlMod = BoolToString(m_pConfig->GetGeneratePerlMod());
177         // Pre-processor.
178         wxString sEnablePreproc = BoolToString(m_pConfig->GetEnablePreprocessing());
179         // Dot.
180         wxString sClassDiag = BoolToString(m_pConfig->GetClassDiagrams());
181         wxString sHaveDot = BoolToString(m_pConfig->GetHaveDot());
182         wxString sPathDot = pMacMngr->ReplaceMacros(m_pConfig->GetPathDot());
183 
184         // Create a full doxygen 1.7.3 config file without comments.
185         wxString sText;
186         wxString nl = wxT("\n");
187         wxString qnl = wxT("\"\n");
188         sText   =  wxT("#******************************************************************************\n");
189         sText +=  wxString(wxT("# ")) + _("Base configuration for doxygen, generated by DoxyBlocks") + wxT(".\n");
190         sText +=  wxString(wxT("# ")) + _("You may change these defaults to suit your purposes") + wxT(".\n");
191         sText +=  wxT("#******************************************************************************\n\n");
192 
193         sText +=  wxT("# Doxyfile 1.7.3\n");
194         sText +=  wxT("\n");
195         sText +=  wxT("#---------------------------------------------------------------------------\n");
196         sText +=  wxT("# Project related configuration options\n");
197         sText +=  wxT("#---------------------------------------------------------------------------\n");
198         sText +=  wxT("DOXYFILE_ENCODING      = UTF-8\n");
199         sText +=  wxT("PROJECT_NAME           = ") + sPrjName + nl;
200         sText +=  wxT("PROJECT_NUMBER         = ") + sPrjNum + nl;
201         sText +=  wxT("PROJECT_BRIEF          =\n");
202         sText +=  wxT("PROJECT_LOGO           =\n");
203         sText +=  wxT("OUTPUT_DIRECTORY       =\n");
204         sText +=  wxT("CREATE_SUBDIRS         = NO\n");
205         sText +=  wxT("OUTPUT_LANGUAGE        = ") + sLanguage + nl;
206         sText +=  wxT("BRIEF_MEMBER_DESC      = YES\n");
207         sText +=  wxT("REPEAT_BRIEF           = YES\n");
208         sText +=  wxT("ABBREVIATE_BRIEF       =\n");
209         sText +=  wxT("ALWAYS_DETAILED_SEC    = NO\n");
210         sText +=  wxT("INLINE_INHERITED_MEMB  = NO\n");
211         sText +=  wxT("FULL_PATH_NAMES        = NO\n");
212         sText +=  wxT("STRIP_FROM_PATH        =\n");
213         sText +=  wxT("STRIP_FROM_INC_PATH    =\n");
214         sText +=  wxT("SHORT_NAMES            = NO\n");
215         sText +=  wxT("JAVADOC_AUTOBRIEF      = NO\n");
216         sText +=  wxT("QT_AUTOBRIEF           = NO\n");
217         sText +=  wxT("MULTILINE_CPP_IS_BRIEF = NO\n");
218         sText +=  wxT("INHERIT_DOCS           = YES\n");
219         sText +=  wxT("SEPARATE_MEMBER_PAGES  = NO\n");
220         sText +=  wxT("TAB_SIZE               = 8\n");
221         sText +=  wxT("ALIASES                =\n");
222         sText +=  wxT("OPTIMIZE_OUTPUT_FOR_C  = NO\n");
223         sText +=  wxT("OPTIMIZE_OUTPUT_JAVA   = NO\n");
224         sText +=  wxT("OPTIMIZE_FOR_FORTRAN   = NO\n");
225         sText +=  wxT("OPTIMIZE_OUTPUT_VHDL   = NO\n");
226         sText +=  wxT("EXTENSION_MAPPING      =\n");
227         sText +=  wxT("BUILTIN_STL_SUPPORT    = NO\n");
228         sText +=  wxT("CPP_CLI_SUPPORT        = NO\n");
229         sText +=  wxT("SIP_SUPPORT            = NO\n");
230         sText +=  wxT("IDL_PROPERTY_SUPPORT   = YES\n");
231         sText +=  wxT("DISTRIBUTE_GROUP_DOC   = NO\n");
232         sText +=  wxT("SUBGROUPING            = YES\n");
233         sText +=  wxT("TYPEDEF_HIDES_STRUCT   = NO\n");
234         sText +=  wxT("SYMBOL_CACHE_SIZE      = 0\n");
235 
236         sText +=  wxT("#---------------------------------------------------------------------------\n");
237         sText +=  wxT("# Build related configuration options\n");
238         sText +=  wxT("#---------------------------------------------------------------------------\n");
239         sText +=  wxT("EXTRACT_ALL            = ") + sExtractAll + nl;
240         sText +=  wxT("EXTRACT_PRIVATE        = ") + sExtractPrivate + nl;
241         sText +=  wxT("EXTRACT_STATIC         = ") + sExtractStatic + nl;
242         sText +=  wxT("EXTRACT_LOCAL_CLASSES  = YES\n");
243         sText +=  wxT("EXTRACT_LOCAL_METHODS  = NO\n");
244         sText +=  wxT("EXTRACT_ANON_NSPACES   = NO\n");
245         sText +=  wxT("HIDE_UNDOC_MEMBERS     = NO\n");
246         sText +=  wxT("HIDE_UNDOC_CLASSES     = NO\n");
247         sText +=  wxT("HIDE_FRIEND_COMPOUNDS  = NO\n");
248         sText +=  wxT("HIDE_IN_BODY_DOCS      = NO\n");
249         sText +=  wxT("INTERNAL_DOCS          = NO\n");
250         sText +=  wxT("CASE_SENSE_NAMES       = NO\n");
251         sText +=  wxT("HIDE_SCOPE_NAMES       = NO\n");
252         sText +=  wxT("SHOW_INCLUDE_FILES     = YES\n");
253         sText +=  wxT("FORCE_LOCAL_INCLUDES   = NO\n");
254         sText +=  wxT("INLINE_INFO            = YES\n");
255         sText +=  wxT("SORT_MEMBER_DOCS       = YES\n");
256         sText +=  wxT("SORT_BRIEF_DOCS        = NO\n");
257         sText +=  wxT("SORT_MEMBERS_CTORS_1ST = NO\n");
258         sText +=  wxT("SORT_GROUP_NAMES       = NO\n");
259         sText +=  wxT("SORT_BY_SCOPE_NAME     = NO\n");
260         sText +=  wxT("STRICT_PROTO_MATCHING  = NO\n");
261         sText +=  wxT("GENERATE_TODOLIST      = YES\n");
262         sText +=  wxT("GENERATE_TESTLIST      = YES\n");
263         sText +=  wxT("GENERATE_BUGLIST       = YES\n");
264         sText +=  wxT("GENERATE_DEPRECATEDLIST= YES\n");
265         sText +=  wxT("ENABLED_SECTIONS       =\n");
266         sText +=  wxT("MAX_INITIALIZER_LINES  = 30\n");
267         sText +=  wxT("SHOW_USED_FILES        = YES\n");
268         sText +=  wxT("SHOW_DIRECTORIES       = NO\n");
269         sText +=  wxT("SHOW_FILES             = YES\n");
270         sText +=  wxT("SHOW_NAMESPACES        = YES\n");
271         sText +=  wxT("FILE_VERSION_FILTER    =\n");
272         sText +=  wxT("LAYOUT_FILE            =\n");
273 
274         sText +=  wxT("#---------------------------------------------------------------------------\n");
275         sText +=  wxT("# configuration options related to warning and progress messages\n");
276         sText +=  wxT("#---------------------------------------------------------------------------\n");
277         sText +=  wxT("QUIET                  = NO\n");
278         sText +=  wxT("WARNINGS               = ") + sWarnings + nl;
279         sText +=  wxT("WARN_IF_UNDOCUMENTED   = ") + sWarnIfUndoc + nl;
280         sText +=  wxT("WARN_IF_DOC_ERROR      = ") + sWarnIfDocError + nl;
281         sText +=  wxT("WARN_NO_PARAMDOC       = ") + sWarnNoParamDoc + nl;
282         sText +=  wxT("WARN_FORMAT            = \"$file:$line: $text\"\n");
283         sText +=  wxT("WARN_LOGFILE            = \"") + fnDoxygenLog.GetFullPath() + qnl;
284 
285         sText +=  wxT("#---------------------------------------------------------------------------\n");
286         sText +=  wxT("# configuration options related to the input files\n");
287         sText +=  wxT("#---------------------------------------------------------------------------\n");
288         sText += sInputList;
289         sText +=  wxT("INPUT_ENCODING         = UTF-8\n");
290         sText +=  wxT("FILE_PATTERNS          =\n");
291         sText +=  wxT("RECURSIVE              = NO\n");
292         sText +=  wxT("EXCLUDE                =\n");
293         sText +=  wxT("EXCLUDE_SYMLINKS       = NO\n");
294         sText +=  wxT("EXCLUDE_PATTERNS       =\n");
295         sText +=  wxT("EXCLUDE_SYMBOLS        =\n");
296         sText +=  wxT("EXAMPLE_PATH           =\n");
297         sText +=  wxT("EXAMPLE_PATTERNS       =\n");
298         sText +=  wxT("EXAMPLE_RECURSIVE      = NO\n");
299         sText +=  wxT("IMAGE_PATH             =\n");
300         sText +=  wxT("INPUT_FILTER           =\n");
301         sText +=  wxT("FILTER_PATTERNS        =\n");
302         sText +=  wxT("FILTER_SOURCE_FILES    = NO\n");
303         sText +=  wxT("FILTER_SOURCE_PATTERNS =\n");
304 
305         sText +=  wxT("#---------------------------------------------------------------------------\n");
306         sText +=  wxT("# configuration options related to source browsing\n");
307         sText +=  wxT("#---------------------------------------------------------------------------\n");
308         sText +=  wxT("SOURCE_BROWSER         = NO\n");
309         sText +=  wxT("INLINE_SOURCES         = NO\n");
310         sText +=  wxT("STRIP_CODE_COMMENTS    = YES\n");
311         sText +=  wxT("REFERENCED_BY_RELATION = NO\n");
312         sText +=  wxT("REFERENCES_RELATION    = NO\n");
313         sText +=  wxT("REFERENCES_LINK_SOURCE = YES\n");
314         sText +=  wxT("USE_HTAGS              = NO\n");
315         sText +=  wxT("VERBATIM_HEADERS       = YES\n");
316 
317         sText +=  wxT("#---------------------------------------------------------------------------\n");
318         sText +=  wxT("# configuration options related to the alphabetical class index\n");
319         sText +=  wxT("#---------------------------------------------------------------------------\n");
320         sText +=  wxT("ALPHABETICAL_INDEX     = ") + sAlphaIndex + nl;
321         sText +=  wxT("COLS_IN_ALPHA_INDEX    = 5\n");
322         sText +=  wxT("IGNORE_PREFIX          =\n");
323 
324         sText +=  wxT("#---------------------------------------------------------------------------\n");
325         sText +=  wxT("# configuration options related to the HTML output\n");
326         sText +=  wxT("#---------------------------------------------------------------------------\n");
327         sText +=  wxT("GENERATE_HTML          = ") + sGenerateHTML + nl;
328         sText +=  wxT("HTML_OUTPUT            = html\n");
329         sText +=  wxT("HTML_FILE_EXTENSION    = .html\n");
330         sText +=  wxT("HTML_HEADER            =\n");
331         sText +=  wxT("HTML_FOOTER            =\n");
332         sText +=  wxT("HTML_STYLESHEET        =\n");
333         sText +=  wxT("HTML_COLORSTYLE_HUE    = 220\n");
334         sText +=  wxT("HTML_COLORSTYLE_SAT    = 100\n");
335         sText +=  wxT("HTML_COLORSTYLE_GAMMA  = 80\n");
336         sText +=  wxT("HTML_TIMESTAMP         = YES\n");
337         sText +=  wxT("HTML_ALIGN_MEMBERS     = YES\n");
338         sText +=  wxT("HTML_DYNAMIC_SECTIONS  = NO\n");
339         sText +=  wxT("GENERATE_DOCSET        = NO\n");
340         sText +=  wxT("DOCSET_FEEDNAME        = \"Doxygen generated docs\"\n");
341         sText +=  wxT("DOCSET_BUNDLE_ID       = org.doxygen.Project\n");
342         sText +=  wxT("DOCSET_PUBLISHER_ID    = org.doxygen.Publisher\n");
343         sText +=  wxT("DOCSET_PUBLISHER_NAME  = Publisher\n");
344         sText +=  wxT("GENERATE_HTMLHELP      = ") + sGenerateHTMLHelp + nl;
345         sText +=  wxT("CHM_FILE               = \"") + sChmFile    + qnl;
346         if(!sPathHHC.IsEmpty()){
347             sText +=  wxT("HHC_LOCATION           = \"") + sPathHHC + qnl;
348         }
349         else{
350             sText +=  wxT("HHC_LOCATION           =\n");
351         }
352         sText +=  wxT("GENERATE_CHI           = ") + sGenerateCHI + nl;
353         sText +=  wxT("CHM_INDEX_ENCODING     =\n");
354         sText +=  wxT("BINARY_TOC             = ") + sBinaryTOC + nl;
355         sText +=  wxT("TOC_EXPAND             = NO\n");
356         sText +=  wxT("GENERATE_QHP           = NO\n");
357         sText +=  wxT("QCH_FILE               =\n");
358         sText +=  wxT("QHP_NAMESPACE          = org.doxygen.Project\n");
359         sText +=  wxT("QHP_VIRTUAL_FOLDER     = doc\n");
360         sText +=  wxT("QHP_CUST_FILTER_NAME   =\n");
361         sText +=  wxT("QHP_CUST_FILTER_ATTRS  =\n");
362         sText +=  wxT("QHP_SECT_FILTER_ATTRS  =\n");
363         sText +=  wxT("QHG_LOCATION           =\n");
364         sText +=  wxT("GENERATE_ECLIPSEHELP   = NO\n");
365         sText +=  wxT("ECLIPSE_DOC_ID         = org.doxygen.Project\n");
366         sText +=  wxT("DISABLE_INDEX          = NO\n");
367         sText +=  wxT("ENUM_VALUES_PER_LINE   = 4\n");
368         sText +=  wxT("GENERATE_TREEVIEW      = YES\n");
369         sText +=  wxT("USE_INLINE_TREES       = NO\n");
370         sText +=  wxT("TREEVIEW_WIDTH         = 250\n");
371         sText +=  wxT("EXT_LINKS_IN_WINDOW    = NO\n");
372         sText +=  wxT("FORMULA_FONTSIZE       = 10\n");
373         sText +=  wxT("FORMULA_TRANSPARENT    = YES\n");
374         sText +=  wxT("USE_MATHJAX            = NO\n");
375         sText +=  wxT("MATHJAX_RELPATH        = http://www.mathjax.org/mathjax\n");
376         sText +=  wxT("SEARCHENGINE           = YES\n");
377         sText +=  wxT("SERVER_BASED_SEARCH    = NO\n");
378 
379         sText +=  wxT("#---------------------------------------------------------------------------\n");
380         sText +=  wxT("# configuration options related to the LaTeX output\n");
381         sText +=  wxT("#---------------------------------------------------------------------------\n");
382         sText +=  wxT("GENERATE_LATEX         = ") + sGenerateLatex + nl;
383         sText +=  wxT("LATEX_OUTPUT           = latex\n");
384         sText +=  wxT("LATEX_CMD_NAME         = latex\n");
385         sText +=  wxT("MAKEINDEX_CMD_NAME     = makeindex\n");
386         sText +=  wxT("COMPACT_LATEX          = NO\n");
387         sText +=  wxT("PAPER_TYPE             = a4\n");
388         sText +=  wxT("EXTRA_PACKAGES         =\n");
389         sText +=  wxT("LATEX_HEADER           =\n");
390         sText +=  wxT("PDF_HYPERLINKS         = YES\n");
391         sText +=  wxT("USE_PDFLATEX           = YES\n");
392         sText +=  wxT("LATEX_BATCHMODE        = NO\n");
393         sText +=  wxT("LATEX_HIDE_INDICES     = NO\n");
394         sText +=  wxT("LATEX_SOURCE_CODE      = NO\n");
395 
396         sText +=  wxT("#---------------------------------------------------------------------------\n");
397         sText +=  wxT("# configuration options related to the RTF output\n");
398         sText +=  wxT("#---------------------------------------------------------------------------\n");
399         sText +=  wxT("GENERATE_RTF           = ") + sGenerateRTF + nl;
400         sText +=  wxT("RTF_OUTPUT             = rtf\n");
401         sText +=  wxT("COMPACT_RTF            = NO\n");
402         sText +=  wxT("RTF_HYPERLINKS         = NO\n");
403         sText +=  wxT("RTF_STYLESHEET_FILE    =\n");
404         sText +=  wxT("RTF_EXTENSIONS_FILE    =\n");
405 
406         sText +=  wxT("#---------------------------------------------------------------------------\n");
407         sText +=  wxT("# configuration options related to the man page output\n");
408         sText +=  wxT("#---------------------------------------------------------------------------\n");
409         sText +=  wxT("GENERATE_MAN           = ") + sGenerateMan + nl;
410         sText +=  wxT("MAN_OUTPUT             = man\n");
411         sText +=  wxT("MAN_EXTENSION          = .3\n");
412         sText +=  wxT("MAN_LINKS              = NO\n");
413 
414         sText +=  wxT("#---------------------------------------------------------------------------\n");
415         sText +=  wxT("# configuration options related to the XML output\n");
416         sText +=  wxT("#---------------------------------------------------------------------------\n");
417         sText +=  wxT("GENERATE_XML           = ") + sGenerateXML + nl;
418         sText +=  wxT("XML_OUTPUT             = xml\n");
419         sText +=  wxT("XML_SCHEMA             =\n");
420         sText +=  wxT("XML_DTD                =\n");
421         sText +=  wxT("XML_PROGRAMLISTING     = YES\n");
422 
423         sText +=  wxT("#---------------------------------------------------------------------------\n");
424         sText +=  wxT("# configuration options for the AutoGen Definitions output\n");
425         sText +=  wxT("#---------------------------------------------------------------------------\n");
426         sText +=  wxT("GENERATE_AUTOGEN_DEF   = ") + sGenerateAutogenDef + nl;
427         sText +=  wxT("#---------------------------------------------------------------------------\n");
428 
429         sText +=  wxT("# configuration options related to the Perl module output\n");
430         sText +=  wxT("#---------------------------------------------------------------------------\n");
431         sText +=  wxT("GENERATE_PERLMOD       = ") + sGeneratePerlMod + nl;
432         sText +=  wxT("PERLMOD_LATEX          = NO\n");
433         sText +=  wxT("PERLMOD_PRETTY         = YES\n");
434         sText +=  wxT("PERLMOD_MAKEVAR_PREFIX =\n");
435         sText +=  wxT("#---------------------------------------------------------------------------\n");
436 
437         sText +=  wxT("# Configuration options related to the preprocessor\n");
438         sText +=  wxT("#---------------------------------------------------------------------------\n");
439         sText +=  wxT("ENABLE_PREPROCESSING   = ") + sEnablePreproc + nl;
440         sText +=  wxT("MACRO_EXPANSION        = YES\n");
441         sText +=  wxT("EXPAND_ONLY_PREDEF     = YES\n");
442         sText +=  wxT("SEARCH_INCLUDES        = YES\n");
443         sText +=  wxT("INCLUDE_PATH           =\n");
444         sText +=  wxT("INCLUDE_FILE_PATTERNS  =\n");
445         sText +=  wxT("PREDEFINED             = WXUNUSED()=\n");        /// TODO (Gary#1#): I should look at other macros for inclusion here.
446         sText +=  wxT("EXPAND_AS_DEFINED      =\n");
447         sText +=  wxT("SKIP_FUNCTION_MACROS   = YES\n");
448 
449         sText +=  wxT("#---------------------------------------------------------------------------\n");
450         sText +=  wxT("# Configuration::additions related to external references\n");
451         sText +=  wxT("#---------------------------------------------------------------------------\n");
452         sText +=  wxT("TAGFILES               =\n");
453         sText +=  wxT("GENERATE_TAGFILE       =\n");
454         sText +=  wxT("ALLEXTERNALS           = NO\n");
455         sText +=  wxT("EXTERNAL_GROUPS        = YES\n");
456         sText +=  wxT("PERL_PATH              = /usr/bin/perl\n");
457 
458         sText +=  wxT("#---------------------------------------------------------------------------\n");
459         sText +=  wxT("# Configuration options related to the dot tool\n");
460         sText +=  wxT("#---------------------------------------------------------------------------\n");
461         sText +=  wxT("CLASS_DIAGRAMS         = ") + sClassDiag + nl;
462         sText +=  wxT("MSCGEN_PATH            =\n");
463         sText +=  wxT("HIDE_UNDOC_RELATIONS   = YES\n");
464         sText +=  wxT("HAVE_DOT               = ") + sHaveDot + nl;
465         sText +=  wxT("DOT_NUM_THREADS        = 0\n");
466         sText +=  wxT("DOT_FONTNAME           = Helvetica\n");
467         sText +=  wxT("DOT_FONTSIZE           = 10\n");
468         sText +=  wxT("DOT_FONTPATH           =\n");
469         sText +=  wxT("CLASS_GRAPH            = YES\n");
470         sText +=  wxT("COLLABORATION_GRAPH    = YES\n");
471         sText +=  wxT("GROUP_GRAPHS           = YES\n");
472         sText +=  wxT("UML_LOOK               = NO\n");
473         sText +=  wxT("TEMPLATE_RELATIONS     = NO\n");
474         sText +=  wxT("INCLUDE_GRAPH          = YES\n");
475         sText +=  wxT("INCLUDED_BY_GRAPH      = YES\n");
476         sText +=  wxT("CALL_GRAPH             = YES\n");
477         sText +=  wxT("CALLER_GRAPH           = NO\n");
478         sText +=  wxT("GRAPHICAL_HIERARCHY    = YES\n");
479         sText +=  wxT("DIRECTORY_GRAPH        = YES\n");
480         sText +=  wxT("DOT_IMAGE_FORMAT       = png\n");
481         if(!sPathDot.IsEmpty()){
482             sText +=  wxT("DOT_PATH           = \"") + sPathDot + qnl;
483         }
484         else{
485             sText +=  wxT("DOT_PATH               =\n");
486         }
487         sText +=  wxT("DOTFILE_DIRS           =\n");
488         sText +=  wxT("MSCFILE_DIRS           =\n");
489         sText +=  wxT("DOT_GRAPH_MAX_NODES    = 50\n");
490         sText +=  wxT("MAX_DOT_GRAPH_DEPTH    = 0\n");
491         sText +=  wxT("DOT_TRANSPARENT        = NO\n");
492         sText +=  wxT("DOT_MULTI_TARGETS      = NO\n");
493         sText +=  wxT("GENERATE_LEGEND        = YES\n");
494         sText +=  wxT("DOT_CLEANUP            = YES\n");
495         sText +=  wxT("\n");
496 
497         wxFFile fileDoxyfile(fnDoxyfile.GetFullPath(), wxT("w"));
498         fileDoxyfile.Write(sText);
499     }
500 }
501 
502    /**************************************************************************
503      this is where our work is performed :)  (text stolen from Yiannis)
504    **************************************************************************/
505 
506 /*! \brief Manage the generation of the doxygen configuration and log files.
507  *
508  * \param    prj    cbProject*       The project.
509  * \return   int    0 on success, -1 on failure.
510  * \todo Revisit the path management code and add support for allowing the docs to be created in a different location
511  * to the doxyfile via the OUTPUT_PATH setting e.g. using something like ../docs.
512  */
GenerateDocuments(cbProject * prj)513 int DoxyBlocks::GenerateDocuments(cbProject *prj)
514 {
515 
516     // First, I need to change into the project directory. All following actions
517     // will work with relative pathes. This way, stored pathes in doxygen
518     // configuration files won't cause problems after moving to other places.
519     // The current path is to be restored after my actions...
520 
521     const wxString sOldPath = wxGetCwd();
522     wxFileName fnProject;
523     fnProject.Assign(prj->GetFilename(), ::wxPATH_NATIVE);
524 
525     const wxString sPrjPath = fnProject.GetPath(wxPATH_GET_VOLUME);
526     wxSetWorkingDirectory(sPrjPath);
527 
528     // project name, name and path of base config file and logfile
529     const wxString sPrjName = fnProject.GetName();
530     const wxString sOutputDir = m_pConfig->GetOutputDirectory();
531     wxString sDoxygenDir = wxT("doxygen");
532     const wxString sCfgBaseFile = wxT("doxyfile");
533     const wxString sLogFile     = wxT("doxygen.log");
534 
535     if(!sOutputDir.IsEmpty()){
536         sDoxygenDir = sOutputDir;
537     }
538 
539     wxFileName fnOutput(sDoxygenDir, wxT(""));
540     wxFileName fnDoxyfile(sDoxygenDir + wxFileName::GetPathSeparator() + sCfgBaseFile);
541     wxFileName fnDoxygenLog(sDoxygenDir + wxFileName::GetPathSeparator() + sLogFile);
542     fnOutput.Normalize();
543     fnDoxyfile.Normalize();
544     fnDoxygenLog.Normalize();
545 
546     if (!fnOutput.Mkdir(0777, wxPATH_MKDIR_FULL)){
547         const wxString sMsg = _("Failed. ") + fnOutput.GetFullPath() + _(" was not created.");
548         AppendToLog(sMsg, LOG_WARNING);
549         wxSetWorkingDirectory(sOldPath);
550         return -1;
551     }
552 
553     // I'm in the project directory, now create the doxygen configuration files
554     WriteConfigFiles(prj, sPrjName, sPrjPath, sDoxygenDir, fnDoxyfile, fnDoxygenLog);
555 
556     if(!wxFile::Exists(fnDoxyfile.GetFullPath())){
557         const wxString sMsg = _("Failed. ") + fnDoxyfile.GetFullPath() + _(" was not created.");
558         AppendToLog(sMsg, LOG_WARNING);
559         wxSetWorkingDirectory(sOldPath);
560         return -1;
561     }
562      // Drop into the doxygen dir.
563      wxSetWorkingDirectory(sPrjPath + wxFileName::GetPathSeparator() + sDoxygenDir);
564 
565     // now tango, launch doxygen...
566     wxArrayString sOutput;
567     wxArrayString sErrors;
568     // Default command.
569     wxString cmd = wxT("doxygen");
570     // If a path is configured, use that instead.
571     wxString sDoxygenPath = Manager::Get()->GetMacrosManager()->ReplaceMacros(m_pConfig->GetPathDoxygen());
572     if(!sDoxygenPath.IsEmpty()){
573         cmd = sDoxygenPath;
574     }
575     wxString doxygenFileFullPath = fnDoxyfile.GetFullPath();
576     QuoteStringIfNeeded(doxygenFileFullPath);
577     const long ret = wxExecute(cmd + wxT(" ") + doxygenFileFullPath, sOutput, sErrors);
578     if(ret != -1){
579         // Write doxygen logfile to the log or remove it if it's empty
580         if(wxFile::Exists(fnDoxygenLog.GetFullPath())){
581             wxString sText;
582             wxFFile fileLog(fnDoxygenLog.GetFullPath());
583             if(fileLog.IsOpened()){
584                 fileLog.ReadAll(&sText);
585                 fileLog.Close();
586             }
587            else{
588                 AppendToLog(_("Failed to open ") + sLogFile, LOG_WARNING);
589            }
590            if(!sText.IsEmpty()){
591                 AppendToLog(_("\nContents of doxygen's log file:"));
592                 AppendToLog(sText, LOG_WARNING);
593             }
594            else{
595                 wxRemoveFile(sLogFile);
596            }
597         }
598 
599         // Run docs if HTML was created.
600         if(m_pConfig->GetGenerateHTML()){
601             // Open the newly created HTML docs, if prefs allow.
602             if(m_pConfig->GetRunHTML()){
603                 DoRunHTML();
604             }
605             if(m_pConfig->GetGenerateHTMLHelp()){
606                 // Open the newly created CHM if prefs allow.
607                 if(m_pConfig->GetRunCHM()){
608                     RunCompiledHelp(fnDoxyfile.GetPathWithSep() , sPrjName);
609                 }
610             }
611         }
612 
613         // tell the user where to find the docs
614         const wxString sMsg = wxT("Success.\nYour documents are in: ");
615         AppendToLog(sMsg + fnDoxyfile.GetPathWithSep());
616     }
617     else{
618         // please google, install doxygen, set your path and...
619         AppendToLog(wxString::Format(_("Execution of '%s' failed."), cmd.c_str()), LOG_ERROR);
620         AppendToLog(_("Please ensure that the doxygen 'bin' directory is in your path or provide the specific path in DoxyBlocks' preferences.\n"));
621     }
622 
623     // restore to before saved path and bye...
624     wxSetWorkingDirectory(sOldPath);
625     return ret;
626 }
627 
628 /*! \brief Get the list of input files for the doxygen configuration file.
629  *
630  * \param    prj            cbProject*        The project.
631  * \param     fnDoxyfile     wxFileName    Doxyfile filename object.
632  * \return    wxString    The input file list.
633  *
634  * This function queries the cbProject object for a list of files actually attached to the project.
635  * Other  files in the project directory are ignored.
636  */
GetInputList(cbProject * prj,wxFileName fnDoxyfile)637 wxString DoxyBlocks::GetInputList(cbProject *prj, wxFileName fnDoxyfile)
638 {
639     // only files with extensions named here will be included in the documentation
640     wxArrayString asExtList;
641     asExtList.Add(wxT("*.c"));
642     asExtList.Add(wxT("*.cc"));
643     asExtList.Add(wxT("*.cxx"));
644     asExtList.Add(wxT("*.cpp"));
645     asExtList.Add(wxT("*.c++"));
646     asExtList.Add(wxT("*.java"));
647     asExtList.Add(wxT("*.ii"));
648     asExtList.Add(wxT("*.ixx"));
649     asExtList.Add(wxT("*.ipp"));
650     asExtList.Add(wxT("*.i++"));
651     asExtList.Add(wxT("*.inl"));
652     asExtList.Add(wxT("*.h"));
653     asExtList.Add(wxT("*.hh"));
654     asExtList.Add(wxT("*.hxx"));
655     asExtList.Add(wxT("*.hpp"));
656     asExtList.Add(wxT("*.h++"));
657     asExtList.Add(wxT("*.idl"));
658     asExtList.Add(wxT("*.odl"));
659     asExtList.Add(wxT("*.cs"));
660     asExtList.Add(wxT("*.php"));
661     asExtList.Add(wxT("*.php3"));
662     asExtList.Add(wxT("*.inc"));
663     asExtList.Add(wxT("*.m"));
664     asExtList.Add(wxT("*.mm"));
665     asExtList.Add(wxT("*.py"));
666     asExtList.Add(wxT("*.f90"));
667 
668      // now let's build a string containing all the project files. To be on the safe side,
669      // we will quote them all so spaces and other special chars don't break the actual
670      // command later...
671      wxString sInputList;
672      const int cntExtList = asExtList.GetCount();
673 
674      sInputList += wxT("INPUT                  = ");
675 
676     for (FilesList::iterator it = prj->GetFilesList().begin(); it != prj->GetFilesList().end(); ++it)
677     {
678         ProjectFile* prjFile = *it;
679         if(prjFile)
680         {
681             const wxString sFileName = prjFile->relativeFilename;
682             wxFileName fnFileName = prjFile->file;
683             fnFileName.MakeRelativeTo(fnDoxyfile.GetPath());
684             const wxString RelName = fnFileName.GetFullPath();
685 
686             /* if the file matches one of the abovementioned filters, add it */
687             for(int n = 0; n < cntExtList; ++n)
688             {
689                if(sFileName.Matches(asExtList.Item(n)))
690                {
691                   sInputList += wxT("\\\n\t\"") + RelName + wxT("\" ");
692                   break;
693                }
694             }
695         }
696     }
697      sInputList += wxT("\n");
698      return sInputList;
699 }
700