summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmdmapper.cpp2
-rw-r--r--src/cmdmapper.h4
-rw-r--r--src/commentcnv.l6
-rw-r--r--src/commentscan.l16
-rw-r--r--src/compound.xsd2
-rw-r--r--src/config.l31
-rw-r--r--src/config.xml10
-rw-r--r--src/docbookvisitor.cpp94
-rw-r--r--src/docbookvisitor.h1
-rw-r--r--src/docparser.cpp18
-rw-r--r--src/docparser.h2
-rw-r--r--src/doctokenizer.h1
-rw-r--r--src/doctokenizer.l32
-rw-r--r--src/htmldocvisitor.cpp48
-rw-r--r--src/htmldocvisitor.h1
-rw-r--r--src/htmlentity.cpp2
-rw-r--r--src/latexdocvisitor.cpp29
-rw-r--r--src/latexdocvisitor.h1
-rw-r--r--src/libdoxygen.pro.in2
-rw-r--r--src/mandocvisitor.cpp1
-rw-r--r--src/markdown.cpp4
-rw-r--r--src/perlmodgen.cpp3
-rw-r--r--src/plantuml.cpp97
-rw-r--r--src/plantuml.h40
-rw-r--r--src/printdocvisitor.h2
-rw-r--r--src/rtfdocvisitor.cpp34
-rw-r--r--src/rtfdocvisitor.h1
-rw-r--r--src/xmldocvisitor.cpp5
28 files changed, 447 insertions, 42 deletions
diff --git a/src/cmdmapper.cpp b/src/cmdmapper.cpp
index 45469f2..b0ca85f 100644
--- a/src/cmdmapper.cpp
+++ b/src/cmdmapper.cpp
@@ -120,8 +120,10 @@ CommandMap cmdMap[] =
{ "_internalref", CMD_INTERNALREF },
{ "dot", CMD_DOT },
{ "msc", CMD_MSC },
+ { "startuml", CMD_STARTUML },
{ "enddot", CMD_ENDDOT },
{ "endmsc", CMD_ENDMSC },
+ { "enduml", CMD_ENDUML },
{ "manonly", CMD_MANONLY },
{ "endmanonly", CMD_ENDMANONLY },
{ "includelineno", CMD_INCWITHLINES },
diff --git a/src/cmdmapper.h b/src/cmdmapper.h
index d89e368..75fd8ec 100644
--- a/src/cmdmapper.h
+++ b/src/cmdmapper.h
@@ -127,7 +127,9 @@ enum CommandType
CMD_DIAFILE = 97,
CMD_LATEXINCLUDE = 98,
CMD_NDASH = 99,
- CMD_MDASH = 100
+ CMD_MDASH = 100,
+ CMD_STARTUML = 101,
+ CMD_ENDUML = 102
};
enum HtmlTagType
diff --git a/src/commentcnv.l b/src/commentcnv.l
index 4cc9da9..ec56b90 100644
--- a/src/commentcnv.l
+++ b/src/commentcnv.l
@@ -446,7 +446,7 @@ void replaceComment(int offset);
g_blockName=&yytext[1];
BEGIN(VerbatimCode);
}
-<CComment,ReadLine>[\\@]("dot"|"code"|"msc")/[^a-z_A-Z0-9] { /* start of a verbatim block */
+<CComment,ReadLine>[\\@]("dot"|"code"|"msc"|"startuml")/[^a-z_A-Z0-9] { /* start of a verbatim block */
copyToOutput(yytext,(int)yyleng);
g_lastCommentContext = YY_START;
g_javaBlock=0;
@@ -517,7 +517,7 @@ void replaceComment(int offset);
}
}
}
-<VerbatimCode>[\\@]("enddot"|"endcode"|"endmsc") { /* end of verbatim block */
+<VerbatimCode>[\\@]("enddot"|"endcode"|"endmsc"|"enduml") { /* end of verbatim block */
copyToOutput(yytext,(int)yyleng);
if (&yytext[4]==g_blockName)
{
@@ -554,7 +554,7 @@ void replaceComment(int offset);
copyToOutput(yytext,(int)yyleng);
}
<Verbatim>^[ \t]*"///" {
- if (g_blockName=="dot" || g_blockName=="msc" || g_blockName.at(0)=='f')
+ if (g_blockName=="dot" || g_blockName=="msc" || g_blockName=="startuml" || g_blockName.at(0)=='f')
{
// see bug 487871, strip /// from dot images and formulas.
int l=0;
diff --git a/src/commentscan.l b/src/commentscan.l
index a42f6ce..369349b 100644
--- a/src/commentscan.l
+++ b/src/commentscan.l
@@ -191,6 +191,7 @@ static DocCmdMap docCmdMap[] =
{ "manonly", &handleFormatBlock, FALSE },
{ "dot", &handleFormatBlock, TRUE },
{ "msc", &handleFormatBlock, TRUE },
+ { "startuml", &handleFormatBlock, TRUE },
{ "code", &handleFormatBlock, TRUE },
{ "addindex", &handleAddIndex, FALSE },
{ "if", &handleIf, FALSE },
@@ -877,7 +878,7 @@ static int yyread(char *buf,int max_size)
/* start command character */
CMD ("\\"|"@")
DCMD1 ("arg"|"attention"|"author"|"cite"|"code")
-DCMD2 ("date"|"dot"|"msc"|"dotfile"|"example")
+DCMD2 ("date"|"dot"|"msc"|"dotfile"|"example"|"startuml")
DCMD3 ("htmlinclude"|"htmlonly"|"image"|"include")
DCMD4 ("includelineno"|"internal"|"invariant")
DCMD5 ("latexinclude"|"latexonly"|"li"|"line"|"manonly"|"name")
@@ -1785,6 +1786,13 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
BEGIN(Comment);
}
}
+<FormatBlock>{CMD}"enduml" {
+ addOutput(yytext);
+ if (blockName=="startuml") // found end of the block
+ {
+ BEGIN(Comment);
+ }
+ }
<FormatBlock>[^ \@\*\/\\\n]* { // some word
addOutput(yytext);
}
@@ -1809,9 +1817,11 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
addOutput(*yytext);
}
<FormatBlock><<EOF>> {
+ QCString endTag = "@end"+blockName;
+ if (blockName=="startuml") endTag="enduml";
warn(yyFileName,yyLineNr,
- "reached end of comment while inside a @%s block; check for missing @end%s tag!",
- blockName.data(),blockName.data()
+ "reached end of comment while inside a @%s block; check for missing @%s tag!",
+ blockName.data(),endTag.data()
);
yyterminate();
}
diff --git a/src/compound.xsd b/src/compound.xsd
index dec596b..be897c3 100644
--- a/src/compound.xsd
+++ b/src/compound.xsd
@@ -386,7 +386,7 @@
<xsd:element name="rtfonly" type="xsd:string" />
<xsd:element name="latexonly" type="xsd:string" />
<xsd:element name="dot" type="xsd:string" />
- <xsd:element name="msc" type="xsd:string" />
+ <xsd:element name="plantuml" type="xsd:string" />
<xsd:element name="anchor" type="docAnchorType" />
<xsd:element name="formula" type="docFormulaType" />
<xsd:element name="ref" type="docRefTextType" />
diff --git a/src/config.l b/src/config.l
index 133bc11..a237faf 100644
--- a/src/config.l
+++ b/src/config.l
@@ -1329,6 +1329,37 @@ void Config::check()
mscgenPath="";
}
+ // check plantuml path
+ QCString &plantumlJarPath = Config_getString("PLANTUML_JAR_PATH");
+ if (!plantumlJarPath.isEmpty())
+ {
+ QFileInfo pu(plantumlJarPath);
+ if (pu.exists() && pu.isDir()) // PLANTUML_JAR_PATH is directory
+ {
+ QFileInfo jar(plantumlJarPath+portable_pathSeparator()+"plantuml.jar");
+ if (jar.exists() && jar.isFile())
+ {
+ plantumlJarPath = jar.dirPath(TRUE).utf8()+portable_pathSeparator();
+ }
+ else
+ {
+ config_err("Jar file plantuml.jar not found at location "
+ "specified via PLANTUML_JAR_PATH: '%s'\n",plantumlJarPath.data());
+ plantumlJarPath="";
+ }
+ }
+ else if (pu.exists() && pu.isFile() && plantumlJarPath.right(4)==".jar") // PLANTUML_JAR_PATH is file
+ {
+ plantumlJarPath = pu.dirPath(TRUE).utf8()+portable_pathSeparator();
+ }
+ else
+ {
+ config_err("path specified via PLANTUML_JAR_PATH does not exist or not a directory: %s\n",
+ plantumlJarPath.data());
+ plantumlJarPath="";
+ }
+ }
+
// check dia path
QCString &diaPath = Config_getString("DIA_PATH");
if (!diaPath.isEmpty())
diff --git a/src/config.xml b/src/config.xml
index 5a0af59..9020d30 100644
--- a/src/config.xml
+++ b/src/config.xml
@@ -3295,6 +3295,16 @@ to be found in the default search path.
]]>
</docs>
</option>
+ <option type='string' id='PLANTUML_JAR_PATH' format='dir' defval='' depends='HAVE_DOT'>
+ <docs>
+<![CDATA[
+ When using plantuml, the \c PLANTUML_JAR_PATH tag should be used to specify the path where
+ java can find the \c plantuml.jar file. If left blank, it is assumed PlantUML is not used or
+ called during a preprocessing step. Doxygen will generate a warning when it encounters a
+ \ref cmdstartuml "\\startuml" command in this case and will not generate output for the diagram.
+]]>
+ </docs>
+ </option>
<option type='int' id='DOT_GRAPH_MAX_NODES' minval='0' maxval='10000' defval='50' depends='HAVE_DOT'>
<docs>
<![CDATA[
diff --git a/src/docbookvisitor.cpp b/src/docbookvisitor.cpp
index 5d7aafd..9f2dbe3 100644
--- a/src/docbookvisitor.cpp
+++ b/src/docbookvisitor.cpp
@@ -34,6 +34,7 @@
#include "msc.h"
#include "dia.h"
#include "htmlentity.h"
+#include "plantuml.h"
DocbookDocVisitor::DocbookDocVisitor(FTextStream &t,CodeOutputInterface &ci)
: DocVisitor(DocVisitor_Docbook), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE)
@@ -216,35 +217,58 @@ void DocbookDocVisitor::visit(DocVerbatim *s)
}
break;
case DocVerbatim::Msc:
- static int mscindex = 1;
- QCString baseName(4096);
- QCString name;
- QCString stext = s->text();
- m_t << "<para>" << endl;
- name.sprintf("%s%d", "msc_inline_mscgraph_", mscindex);
- baseName.sprintf("%s%d",
- (Config_getString("DOCBOOK_OUTPUT")+"/inline_mscgraph_").data(),
- mscindex++
- );
- QFile file(baseName+".msc");
- if (!file.open(IO_WriteOnly))
{
- err("Could not open file %s.msc for writing\n",baseName.data());
+ static int mscindex = 1;
+ QCString baseName(4096);
+ QCString name;
+ QCString stext = s->text();
+ m_t << "<para>" << endl;
+ name.sprintf("%s%d", "msc_inline_mscgraph_", mscindex);
+ baseName.sprintf("%s%d",
+ (Config_getString("DOCBOOK_OUTPUT")+"/inline_mscgraph_").data(),
+ mscindex++
+ );
+ QFile file(baseName+".msc");
+ if (!file.open(IO_WriteOnly))
+ {
+ err("Could not open file %s.msc for writing\n",baseName.data());
+ }
+ QCString text = "msc {";
+ text+=stext;
+ text+="}";
+ file.writeBlock( text, text.length() );
+ file.close();
+ m_t << " <figure>" << endl;
+ m_t << " <title>" << name << "</title>" << endl;
+ m_t << " <mediaobject>" << endl;
+ m_t << " <imageobject>" << endl;
+ writeMscFile(baseName);
+ m_t << " </imageobject>" << endl;
+ m_t << " </mediaobject>" << endl;
+ m_t << " </figure>" << endl;
+ m_t << "</para>" << endl;
+ }
+ break;
+ case DocVerbatim::PlantUML:
+ {
+ static QCString docbookOutput = Config_getString("DOCBOOK_OUTPUT");
+ QCString baseName = writePlantUMLSource(docbookOutput,s->exampleFile(),s->text());
+ QCString shortName = baseName;
+ int i;
+ if ((i=shortName.findRev('/'))!=-1)
+ {
+ shortName=shortName.right(shortName.length()-i-1);
+ }
+ m_t << " <figure>" << endl;
+ m_t << " <title>" << shortName << "</title>" << endl;
+ m_t << " <mediaobject>" << endl;
+ m_t << " <imageobject>" << endl;
+ writePlantUMLFile(baseName);
+ m_t << " </imageobject>" << endl;
+ m_t << " </mediaobject>" << endl;
+ m_t << " </figure>" << endl;
+ m_t << "</para>" << endl;
}
- QCString text = "msc {";
- text+=stext;
- text+="}";
- file.writeBlock( text, text.length() );
- file.close();
- m_t << " <figure>" << endl;
- m_t << " <title>" << name << "</title>" << endl;
- m_t << " <mediaobject>" << endl;
- m_t << " <imageobject>" << endl;
- writeMscFile(baseName);
- m_t << " </imageobject>" << endl;
- m_t << " </mediaobject>" << endl;
- m_t << " </figure>" << endl;
- m_t << "</para>" << endl;
break;
}
}
@@ -1195,6 +1219,22 @@ void DocbookDocVisitor::writeMscFile(const QCString &baseName)
m_t << "</imagedata>" << endl;
}
+void DocbookDocVisitor::writePlantUMLFile(const QCString &baseName)
+{
+ QCString shortName = baseName;
+ int i;
+ if ((i=shortName.findRev('/'))!=-1)
+ {
+ shortName=shortName.right(shortName.length()-i-1);
+ }
+ QCString outDir = Config_getString("DOCBOOK_OUTPUT");
+ generatePlantUMLOutput(baseName,outDir,PUML_BITMAP);
+ m_t << " <imagedata";
+ m_t << " width=\"50%\"";
+ m_t << " align=\"center\" valign=\"middle\" scalefit=\"1\" fileref=\"" << shortName << ".png" << "\">";
+ m_t << "</imagedata>" << endl;
+}
+
void DocbookDocVisitor::startMscFile(const QCString &fileName,
const QCString &width,
const QCString &height,
diff --git a/src/docbookvisitor.h b/src/docbookvisitor.h
index 20d424e..dd67aba 100644
--- a/src/docbookvisitor.h
+++ b/src/docbookvisitor.h
@@ -156,6 +156,7 @@ class DocbookDocVisitor : public DocVisitor
const QCString &height, bool hasCaption);
void endDotFile(bool hasCaption);
void writeDotFile(const QCString &fileName);
+ void writePlantUMLFile(const QCString &fileName);
//--------------------------------------
// state variables
//--------------------------------------
diff --git a/src/docparser.cpp b/src/docparser.cpp
index 6d788fd..bab0c75 100644
--- a/src/docparser.cpp
+++ b/src/docparser.cpp
@@ -5569,6 +5569,23 @@ int DocPara::handleCommand(const QCString &cmdName)
doctokenizerYYsetStatePara();
}
break;
+ case CMD_STARTUML:
+ {
+ static QCString jarPath = Config_getString("PLANTUML_JAR_PATH");
+ doctokenizerYYsetStatePlantUML();
+ retval = doctokenizerYYlex();
+ if (jarPath.isEmpty())
+ {
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"ignoring startuml command because PLANTUML_JAR_PATH is not set");
+ }
+ else
+ {
+ m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::PlantUML,FALSE,g_token->sectionId));
+ }
+ if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"startuml section ended without end marker");
+ doctokenizerYYsetStatePara();
+ }
+ break;
case CMD_ENDPARBLOCK:
retval=RetVal_EndParBlock;
break;
@@ -5583,6 +5600,7 @@ int DocPara::handleCommand(const QCString &cmdName)
case CMD_ENDVERBATIM:
case CMD_ENDDOT:
case CMD_ENDMSC:
+ case CMD_ENDUML:
warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected command %s",qPrint(g_token->name));
break;
case CMD_PARAM:
diff --git a/src/docparser.h b/src/docparser.h
index 17f296b..3dc3d84 100644
--- a/src/docparser.h
+++ b/src/docparser.h
@@ -433,7 +433,7 @@ class DocWhiteSpace : public DocNode
class DocVerbatim : public DocNode
{
public:
- enum Type { Code, HtmlOnly, ManOnly, LatexOnly, RtfOnly, XmlOnly, Verbatim, Dot, Msc, DocbookOnly };
+ enum Type { Code, HtmlOnly, ManOnly, LatexOnly, RtfOnly, XmlOnly, Verbatim, Dot, Msc, DocbookOnly, PlantUML };
DocVerbatim(DocNode *parent,const QCString &context,
const QCString &text, Type t,bool isExample,
const QCString &exampleFile,bool isBlock=FALSE,const QCString &lang=QCString());
diff --git a/src/doctokenizer.h b/src/doctokenizer.h
index 1db764e..c95230b 100644
--- a/src/doctokenizer.h
+++ b/src/doctokenizer.h
@@ -160,5 +160,6 @@ void doctokenizerYYpushBackHtmlTag(const char *tag);
void doctokenizerYYsetStateSnippet();
void doctokenizerYYstartAutoList();
void doctokenizerYYendAutoList();
+void doctokenizerYYsetStatePlantUML();
#endif
diff --git a/src/doctokenizer.l b/src/doctokenizer.l
index 3bd2058..ea4a1a4 100644
--- a/src/doctokenizer.l
+++ b/src/doctokenizer.l
@@ -417,6 +417,8 @@ REFWORD {LABELID}|{REFWORD2}|{REFWORD3}|{LNKWORD2}
%x St_Verbatim
%x St_Dot
%x St_Msc
+%x St_PlantUMLOpt
+%x St_PlantUML
%x St_Param
%x St_XRefItem
%x St_XRefItem2
@@ -843,7 +845,7 @@ REFWORD {LABELID}|{REFWORD2}|{REFWORD3}|{LNKWORD2}
<St_Dot>. { /* dot text */
g_token->verb+=yytext;
}
-<St_Msc>{CMD}("endmsc"|"endvhdlflow") {
+<St_Msc>{CMD}("endmsc") {
return RetVal_OK;
}
<St_Msc>[^\\@\n]+ |
@@ -851,6 +853,23 @@ REFWORD {LABELID}|{REFWORD2}|{REFWORD3}|{LNKWORD2}
<St_Msc>. { /* msc text */
g_token->verb+=yytext;
}
+<St_PlantUMLOpt>\n {
+ g_token->sectionId=g_token->sectionId.stripWhiteSpace();
+ BEGIN(St_PlantUML);
+ }
+<St_PlantUMLOpt>["{}] { // skip curly brackets or quotes around the optional image name
+ }
+<St_PlantUMLOpt>. {
+ g_token->sectionId += yytext;
+ }
+<St_PlantUML>{CMD}"enduml" {
+ return RetVal_OK;
+ }
+<St_PlantUML>[^\\@\n]+ |
+<St_PlantUML>\n |
+<St_PlantUML>. { /* plantuml text */
+ g_token->verb+=yytext;
+ }
<St_Title>"\"" { // quoted title
BEGIN(St_TitleQ);
}
@@ -1121,6 +1140,10 @@ REFWORD {LABELID}|{REFWORD2}|{REFWORD3}|{LNKWORD2}
g_endMarker="endmsc";
BEGIN(St_SecSkip);
}
+<St_Sections>{CMD}"startuml"/[^a-z_A-Z0-9] {
+ g_endMarker="enduml";
+ BEGIN(St_SecSkip);
+ }
<St_Sections>{CMD}"htmlonly"/[^a-z_A-Z0-9] {
g_endMarker="endhtmlonly";
BEGIN(St_SecSkip);
@@ -1318,6 +1341,13 @@ void doctokenizerYYsetStateMsc()
BEGIN(St_Msc);
}
+void doctokenizerYYsetStatePlantUML()
+{
+ g_token->verb="";
+ g_token->sectionId="";
+ BEGIN(St_PlantUMLOpt);
+}
+
void doctokenizerYYsetStateParam()
{
BEGIN(St_Param);
diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp
index bd94232..e319a1f 100644
--- a/src/htmldocvisitor.cpp
+++ b/src/htmldocvisitor.cpp
@@ -34,6 +34,7 @@
#include "filedef.h"
#include "memberdef.h"
#include "htmlentity.h"
+#include "plantuml.h"
static const int NUM_HTML_LIST_TYPES = 4;
static const char types[][NUM_HTML_LIST_TYPES] = {"1", "a", "i", "A"};
@@ -429,9 +430,21 @@ void HtmlDocVisitor::visit(DocVerbatim *s)
m_t << "<div align=\"center\">" << endl;
writeMscFile(baseName+".msc",s->relPath(),s->context());
if (Config_getBool("DOT_CLEANUP")) file.remove();
+ m_t << "</div>" << endl;
+ forceStartParagraph(s);
+ }
+ break;
+ case DocVerbatim::PlantUML:
+ {
+ forceEndParagraph(s);
+
+ static QCString htmlOutput = Config_getString("HTML_OUTPUT");
+ QCString baseName = writePlantUMLSource(htmlOutput,s->exampleFile(),s->text());
+ m_t << "<div align=\"center\">" << endl;
+ writePlantUMLFile(baseName,s->relPath(),s->context());
+ m_t << "</div>" << endl;
+ forceStartParagraph(s);
}
- m_t << "</div>" << endl;
- forceStartParagraph(s);
break;
}
}
@@ -1976,6 +1989,37 @@ void HtmlDocVisitor::writeDiaFile(const QCString &fileName,
m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />" << endl;
}
+void HtmlDocVisitor::writePlantUMLFile(const QCString &fileName,
+ const QCString &relPath,
+ const QCString &)
+{
+ QCString baseName=fileName;
+ int i;
+ if ((i=baseName.findRev('/'))!=-1) // strip path
+ {
+ baseName=baseName.right(baseName.length()-i-1);
+ }
+ if ((i=baseName.findRev('.'))!=-1) // strip extension
+ {
+ baseName=baseName.left(i);
+ }
+ static QCString outDir = Config_getString("HTML_OUTPUT");
+ static QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
+ if (imgExt=="svg")
+ {
+ generatePlantUMLOutput(fileName,outDir,PUML_SVG);
+ //m_t << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" << relPath << baseName << ".svg" << "\" />" << endl;
+ //m_t << "<p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p>";
+ //m_t << "</iframe>" << endl;
+ m_t << "<object type=\"image/svg+xml\" data=\"" << relPath << baseName << ".svg\"></object>" << endl;
+ }
+ else
+ {
+ generatePlantUMLOutput(fileName,outDir,PUML_BITMAP);
+ m_t << "<img src=\"" << relPath << baseName << ".png" << "\" />" << endl;
+ }
+}
+
/** Used for items found inside a paragraph, which due to XHTML restrictions
* have to be outside of the paragraph. This method will forcefully end
* the current paragraph and forceStartParagraph() will restart it.
diff --git a/src/htmldocvisitor.h b/src/htmldocvisitor.h
index ddefecd..00ae09e 100644
--- a/src/htmldocvisitor.h
+++ b/src/htmldocvisitor.h
@@ -153,6 +153,7 @@ class HtmlDocVisitor : public DocVisitor
void writeDotFile(const QCString &fileName,const QCString &relPath,const QCString &context);
void writeMscFile(const QCString &fileName,const QCString &relPath,const QCString &context);
void writeDiaFile(const QCString &fileName,const QCString &relPath,const QCString &context);
+ void writePlantUMLFile(const QCString &fileName,const QCString &relPath,const QCString &context);
void pushEnabled();
void popEnabled();
diff --git a/src/htmlentity.cpp b/src/htmlentity.cpp
index c49491e..216b65c 100644
--- a/src/htmlentity.cpp
+++ b/src/htmlentity.cpp
@@ -462,7 +462,7 @@ const DocSymbol::PerlSymb *HtmlEntityMapper::perl(DocSymbol::SymType symb) const
/*!
* @brief Give code of the requested HTML entity name
- * @param symName HTML entity name without \c & and \c;
+ * @param symName HTML entity name without \c & and \c ;
* @return the code for the requested HTML entity name,
* in case the requested HTML item does not exist `DocSymbol::Sym_unknown` is returned.
*/
diff --git a/src/latexdocvisitor.cpp b/src/latexdocvisitor.cpp
index dd23d60..af1a5fd 100644
--- a/src/latexdocvisitor.cpp
+++ b/src/latexdocvisitor.cpp
@@ -32,6 +32,7 @@
#include "filedef.h"
#include "config.h"
#include "htmlentity.h"
+#include "plantuml.h"
static QCString escapeLabelName(const char *s)
{
@@ -321,6 +322,16 @@ void LatexDocVisitor::visit(DocVerbatim *s)
if (Config_getBool("DOT_CLEANUP")) file.remove();
}
break;
+ case DocVerbatim::PlantUML:
+ {
+ QCString latexOutput = Config_getString("LATEX_OUTPUT");
+ QCString baseName = writePlantUMLSource(latexOutput,s->exampleFile(),s->text());
+
+ m_t << "\\begin{center}\n";
+ writePlantUMLFile(baseName);
+ m_t << "\\end{center}\n";
+ }
+ break;
}
}
@@ -1743,6 +1754,7 @@ void LatexDocVisitor::writeMscFile(const QCString &baseName)
m_t << "\\end{DoxyImageNoCaption}\n";
}
+
void LatexDocVisitor::startDiaFile(const QCString &fileName,
const QCString &width,
const QCString &height,
@@ -1834,3 +1846,20 @@ void LatexDocVisitor::writeDiaFile(const QCString &baseName)
m_t << "\\end{DoxyImageNoCaption}\n";
}
+void LatexDocVisitor::writePlantUMLFile(const QCString &baseName)
+{
+ QCString shortName = baseName;
+ int i;
+ if ((i=shortName.findRev('/'))!=-1)
+ {
+ shortName=shortName.right(shortName.length()-i-1);
+ }
+ QCString outDir = Config_getString("LATEX_OUTPUT");
+ generatePlantUMLOutput(baseName,outDir,PUML_EPS);
+ m_t << "\n\\begin{DoxyImageNoCaption}"
+ " \\mbox{\\includegraphics";
+ m_t << "{" << shortName << "}";
+ m_t << "}\n"; // end mbox
+ m_t << "\\end{DoxyImageNoCaption}\n";
+}
+
diff --git a/src/latexdocvisitor.h b/src/latexdocvisitor.h
index d386569..64560b9 100644
--- a/src/latexdocvisitor.h
+++ b/src/latexdocvisitor.h
@@ -176,6 +176,7 @@ class LatexDocVisitor : public DocVisitor
const QCString &height, bool hasCaption);
void endDiaFile(bool hasCaption);
void writeDiaFile(const QCString &fileName);
+ void writePlantUMLFile(const QCString &fileName);
void pushEnabled();
void popEnabled();
diff --git a/src/libdoxygen.pro.in b/src/libdoxygen.pro.in
index f50f987..703b885 100644
--- a/src/libdoxygen.pro.in
+++ b/src/libdoxygen.pro.in
@@ -87,6 +87,7 @@ HEADERS = arguments.h \
pagedef.h \
perlmodgen.h \
lodepng.h \
+ plantuml.h \
pre.h \
printdocvisitor.h \
pycode.h \
@@ -165,6 +166,7 @@ SOURCES = arguments.cpp \
layout.cpp \
lodepng.cpp \
logos.cpp \
+ plantuml.cpp \
mandocvisitor.cpp \
mangen.cpp \
sqlite3gen.cpp \
diff --git a/src/mandocvisitor.cpp b/src/mandocvisitor.cpp
index 5403324..1fe5409 100644
--- a/src/mandocvisitor.cpp
+++ b/src/mandocvisitor.cpp
@@ -208,6 +208,7 @@ void ManDocVisitor::visit(DocVerbatim *s)
case DocVerbatim::DocbookOnly:
case DocVerbatim::Dot:
case DocVerbatim::Msc:
+ case DocVerbatim::PlantUML:
/* nothing */
break;
}
diff --git a/src/markdown.cpp b/src/markdown.cpp
index 291e1dc..11b01ea 100644
--- a/src/markdown.cpp
+++ b/src/markdown.cpp
@@ -208,6 +208,10 @@ static QCString isBlockCommand(const char *data,int offset,int size)
{
return "end"+blockName;
}
+ else if (blockName=="startuml")
+ {
+ return "enduml";
+ }
else if (blockName=="f" && end<size)
{
if (data[end]=='$')
diff --git a/src/perlmodgen.cpp b/src/perlmodgen.cpp
index 948836b..c636cdf 100644
--- a/src/perlmodgen.cpp
+++ b/src/perlmodgen.cpp
@@ -662,8 +662,9 @@ void PerlModDocVisitor::visit(DocVerbatim *s)
case DocVerbatim::LatexOnly: type = "latexonly"; break;
case DocVerbatim::XmlOnly: type = "xmlonly"; break;
case DocVerbatim::DocbookOnly: type = "docbookonly"; break;
- case DocVerbatim::Dot: type = "dot"; break;
+ case DocVerbatim::Dot: type = "dot"; break;
case DocVerbatim::Msc: type = "msc"; break;
+ case DocVerbatim::PlantUML: type = "plantuml"; break;
}
openItem(type);
m_output.addFieldQuotedString("content", s->text());
diff --git a/src/plantuml.cpp b/src/plantuml.cpp
new file mode 100644
index 0000000..18f028b
--- /dev/null
+++ b/src/plantuml.cpp
@@ -0,0 +1,97 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1997-2014 by Dimitri van Heesch.
+ *
+ * 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 "plantuml.h"
+#include "portable.h"
+#include "config.h"
+#include "message.h"
+
+#include <qdir.h>
+
+//static const int maxCmdLine = 40960;
+
+QCString writePlantUMLSource(const QCString &outDir,const QCString &fileName,const QCString &content)
+{
+ QCString baseName(4096);
+ static int umlindex=1;
+
+ if (fileName.isEmpty()) // generate name
+ {
+ baseName = outDir+"/inline_umlgraph_"+QCString().setNum(umlindex++);
+ }
+ else // user specified name
+ {
+ baseName = fileName;
+ int i=baseName.findRev('.');
+ if (i!=-1) baseName = baseName.left(i);
+ baseName.prepend(outDir+"/");
+ }
+ QFile file(baseName+".pu");
+ if (!file.open(IO_WriteOnly))
+ {
+ err("Could not open file %s for writing\n",baseName.data());
+ }
+ QCString text = "@startuml\n";
+ text+=content;
+ text+="@enduml\n";
+ file.writeBlock( text, text.length() );
+ file.close();
+ return baseName;
+}
+
+void generatePlantUMLOutput(const char *baseName,const char *outDir,PlantUMLOutputFormat format)
+{
+ static QCString plantumlJarPath = Config_getString("PLANTUML_JAR_PATH");
+
+ QCString pumlExe = "java";
+ QCString pumlArgs = "-Djava.awt.headless=true -jar \""+plantumlJarPath+"plantuml.jar\" ";
+ pumlArgs+="-o \"";
+ pumlArgs+=outDir;
+ pumlArgs+="\" ";
+ QCString extension;
+ switch (format)
+ {
+ case PUML_BITMAP:
+ pumlArgs+="-tpng";
+ extension=".png";
+ break;
+ case PUML_EPS:
+ pumlArgs+="-teps";
+ extension=".eps";
+ break;
+ case PUML_SVG:
+ pumlArgs+="-tsvg";
+ extension=".svg";
+ break;
+ }
+ pumlArgs+=" \"";
+ pumlArgs+=baseName;
+ pumlArgs+=".pu\" ";
+ int exitCode;
+ //printf("*** running: %s %s outDir:%s %s\n",pumlExe.data(),pumlArgs.data(),outDir,outFile);
+ msg("Running PlantUML on generated file %s.pu\n",baseName);
+ portable_sysTimerStart();
+ if ((exitCode=portable_system(pumlExe,pumlArgs,FALSE))!=0)
+ {
+ err("Problems running PlantUML. Verify that the command 'java -jar \"%splantuml.jar\" -h' works from the command line\n",
+ plantumlJarPath.data());
+ }
+ else if (Config_getBool("DOT_CLEANUP"))
+ {
+ QFile(QCString(baseName)+".pu").remove();
+ }
+ portable_sysTimerStop();
+}
+
diff --git a/src/plantuml.h b/src/plantuml.h
new file mode 100644
index 0000000..27626d1
--- /dev/null
+++ b/src/plantuml.h
@@ -0,0 +1,40 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1997-2014 by Dimitri van Heesch.
+ *
+ * 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.
+ *
+ */
+
+#ifndef PLANTUML_H
+#define PLANTUML_H
+
+class QCString;
+
+/** Plant UML output image formats */
+enum PlantUMLOutputFormat { PUML_BITMAP, PUML_EPS, PUML_SVG };
+
+/** Write a PlantUML compatible file.
+ * @param[in] outDir the output directory to write the file to.
+ * @param[in] fileName the name of the file. If empty a name will be chosen automatically.
+ * @param[in] content the contents of the PlantUML file.
+ * @returns The name of the generated file.
+ */
+QCString writePlantUMLSource(const QCString &outDir,const QCString &fileName,const QCString &content);
+
+/** Convert a PlantUML file to an image.
+ * @param[in] baseName the name of the generated file (as returned by writePlantUMLSource())
+ * @param[in] outDir the directory to write the resulting image into.
+ * @param[in] format the image format to generate.
+ */
+void generatePlantUMLOutput(const char *baseName,const char *outDir,PlantUMLOutputFormat format);
+
+#endif
+
diff --git a/src/printdocvisitor.h b/src/printdocvisitor.h
index ee2ae3f..1d384b1 100644
--- a/src/printdocvisitor.h
+++ b/src/printdocvisitor.h
@@ -134,6 +134,7 @@ class PrintDocVisitor : public DocVisitor
case DocVerbatim::DocbookOnly: printf("<docbookonly>"); break;
case DocVerbatim::Dot: printf("<dot>"); break;
case DocVerbatim::Msc: printf("<msc>"); break;
+ case DocVerbatim::PlantUML: printf("<plantuml>"); break;
}
printf("%s",s->text().data());
switch(s->type())
@@ -148,6 +149,7 @@ class PrintDocVisitor : public DocVisitor
case DocVerbatim::DocbookOnly: printf("</docbookonly>"); break;
case DocVerbatim::Dot: printf("</dot>"); break;
case DocVerbatim::Msc: printf("</msc>"); break;
+ case DocVerbatim::PlantUML: printf("</plantuml>"); break;
}
}
void visit(DocAnchor *a)
diff --git a/src/rtfdocvisitor.cpp b/src/rtfdocvisitor.cpp
index 0d17208..5e27137 100644
--- a/src/rtfdocvisitor.cpp
+++ b/src/rtfdocvisitor.cpp
@@ -16,6 +16,8 @@
*
*/
+#include <qfileinfo.h>
+
#include "rtfdocvisitor.h"
#include "docparser.h"
#include "language.h"
@@ -26,13 +28,13 @@
#include "util.h"
#include "rtfstyle.h"
#include "message.h"
-#include <qfileinfo.h>
#include "parserintf.h"
#include "msc.h"
#include "dia.h"
#include "filedef.h"
#include "config.h"
#include "htmlentity.h"
+#include "plantuml.h"
//#define DBG_RTF(x) m_t << x
#define DBG_RTF(x) do {} while(0)
@@ -317,6 +319,16 @@ void RTFDocVisitor::visit(DocVerbatim *s)
if (Config_getBool("DOT_CLEANUP")) file.remove();
}
break;
+ case DocVerbatim::PlantUML:
+ {
+ static QCString rtfOutput = Config_getString("RTF_OUTPUT");
+ QCString baseName = writePlantUMLSource(rtfOutput,s->exampleFile(),s->text());
+
+ m_t << "\\par{\\qc "; // center picture
+ writePlantUMLFile(baseName);
+ m_t << "} ";
+ }
+ break;
}
m_lastIsPara=FALSE;
}
@@ -1704,3 +1716,23 @@ void RTFDocVisitor::writeDiaFile(const QCString &fileName)
m_lastIsPara=TRUE;
}
+void RTFDocVisitor::writePlantUMLFile(const QCString &fileName)
+{
+ QCString baseName=fileName;
+ int i;
+ if ((i=baseName.findRev('/'))!=-1)
+ {
+ baseName=baseName.right(baseName.length()-i-1);
+ }
+ QCString outDir = Config_getString("RTF_OUTPUT");
+ generatePlantUMLOutput(fileName,outDir,PUML_BITMAP);
+ if (!m_lastIsPara) m_t << "\\par" << endl;
+ m_t << "{" << endl;
+ m_t << rtf_Style_Reset;
+ m_t << "\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"";
+ m_t << baseName << ".png";
+ m_t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl;
+ m_t << "}" << endl;
+ m_lastIsPara=TRUE;
+}
+
diff --git a/src/rtfdocvisitor.h b/src/rtfdocvisitor.h
index efc9d21..c50802d 100644
--- a/src/rtfdocvisitor.h
+++ b/src/rtfdocvisitor.h
@@ -155,6 +155,7 @@ class RTFDocVisitor : public DocVisitor
void writeDotFile(const QCString &fileName);
void writeMscFile(const QCString &fileName);
void writeDiaFile(const QCString &fileName);
+ void writePlantUMLFile(const QCString &fileName);
//--------------------------------------
// state variables
diff --git a/src/xmldocvisitor.cpp b/src/xmldocvisitor.cpp
index 343926c..f2da28c 100644
--- a/src/xmldocvisitor.cpp
+++ b/src/xmldocvisitor.cpp
@@ -209,6 +209,11 @@ void XmlDocVisitor::visit(DocVerbatim *s)
filter(s->text());
m_t << "</msc>";
break;
+ case DocVerbatim::PlantUML:
+ m_t << "<plantuml>";
+ filter(s->text());
+ m_t << "</plantuml>";
+ break;
}
}