From 329a4ddc036ac9dfe72b11d62cb4043bc8488c20 Mon Sep 17 00:00:00 2001 From: albert-github Date: Fri, 28 Nov 2014 14:44:07 +0100 Subject: Limit images sizes and make more uniform (LaTeX) This patch adjusts some problems regarding image sizes in LaTeX output of doxygen (a.o. Bug 738299 - When using msc or PlantUML, the default latex for the created image should include [width=\linewidth]) this has been done is such a way that all the "image" commands (i.e. image, dot, dotfile, msc, mscfile, diafile, startuml) operate in a similar way / have the same possibilities. - commands.doc Adjusted documentation to reflect changes. - cmdmapper.cpp - cmdmapper.h Added utility function to map command id back to command name - doctokenizer.h - doctokenizer.l Handle Caption and Size indication. Required also that some other rules had to be tightened a bit (like usage of {} in startuml and usage of "" for captions. This was already described in the documentation in this way). - docparser.cpp - docparser.h Created routine to uniformly handle the Caption and size indications and store them in a general way. - latexgen.cpp Replaced graphicx package by adjustbox package (includes graphicx) to support "min width" etc. - doxygen.sty templates\latex Added commands to make commands with and without caption behave similar. - docbookvisitor.cpp - docbookvisitor.h - htmldocvisitor.cpp - latexdocvisitor.cpp - latexdocvisitor.h - printdocvisitor.h - xmldocvisitor.cpp Created routine to uniformly handle the Caption and size indications in a general way. - indexpage.xml (testing\022) - indexpage.xml (testing\031) - class_receiver.xml (testing\037) - class_sender.xml (testing\037) Adjusted example output. --- doc/commands.doc | 107 ++++++++--- src/cmdmapper.cpp | 10 ++ src/cmdmapper.h | 1 + src/docbookvisitor.cpp | 272 ++++++++++------------------ src/docbookvisitor.h | 8 +- src/docparser.cpp | 398 +++++++++++++++++++---------------------- src/docparser.h | 13 +- src/doctokenizer.h | 3 + src/doctokenizer.l | 84 ++++++++- src/htmldocvisitor.cpp | 76 ++++++-- src/latexdocvisitor.cpp | 317 ++++++++++++-------------------- src/latexdocvisitor.h | 6 +- src/latexgen.cpp | 2 +- src/printdocvisitor.h | 2 +- src/xmldocvisitor.cpp | 115 ++++++++---- templates/latex/doxygen.sty | 2 + testing/022/indexpage.xml | 5 +- testing/031/indexpage.xml | 2 +- testing/037/class_receiver.xml | 5 +- testing/037/class_sender.xml | 5 +- 20 files changed, 731 insertions(+), 702 deletions(-) diff --git a/doc/commands.doc b/doc/commands.doc index 1b3f2bd..603b2ca 100644 --- a/doc/commands.doc +++ b/doc/commands.doc @@ -2451,13 +2451,25 @@ only copy the detailed documentation, not the brief description. \ref cmdhtmlonly "\\htmlonly".
-\section cmddot \\dot +\section cmddot \\dot ["caption"] [=] \addindex \\dot Starts a text fragment which should contain a valid description of a dot graph. The text fragment ends with \ref cmdenddot "\\enddot". Doxygen will pass the text on to dot and include the resulting image (and image map) into the output. + + The first argument is optional and can be used to specify the caption + that is displayed below the image. This argument has to be specified + between quotes even if it does not contain any spaces. The quotes are + stripped before the caption is displayed. + + The second argument is also optional and can be used to specify the + width or height of the image. + For a descriptionm of the possibilities see the paragraph + \ref image_sizeindicator "Size indication" with the + \ref cmdimage "\\image" command. + The nodes of a graph can be made clickable by using the URL attribute. By using the command \ref cmdref "\\ref" inside the URL value you can conveniently link to an item inside doxygen. Here is an example: @@ -2485,12 +2497,24 @@ class C {}; \endcode
-\section cmdmsc \\msc +\section cmdmsc \\msc ["caption"] [=] \addindex \\msc Starts a text fragment which should contain a valid description of a message sequence chart. See http://www.mcternan.me.uk/mscgen/ for examples. The text fragment ends with \ref cmdendmsc "\\endmsc". + + The first argument is optional and can be used to specify the caption + that is displayed below the image. This argument has to be specified + between quotes even if it does not contain any spaces. The quotes are + stripped before the caption is displayed. + + The second argument is also optional and can be used to specify the + width or height of the image. + For a descriptionm of the possibilities see the paragraph + \ref image_sizeindicator "Size indication" with the + \ref cmdimage "\\image" command. + \note The text fragment should only include the part of the message sequence chart that is within the msc {...} block. @@ -2534,7 +2558,7 @@ class Receiver \sa section \ref cmdmscfile "\\mscfile".
-\section cmdstartuml \\startuml +\section cmdstartuml \\startuml [{file}] ["caption"] [=] \addindex \\startuml Starts a text fragment which should contain a valid description of a @@ -2544,6 +2568,28 @@ class Receiver if you want to use this command. The location of the jar file should be specified using \ref cfg_plantuml_jar_path "PLANTUML_JAR_PATH". + The first argument is optional and is for compatibility with running PlantUML as a preprocessing + step before running doxygen, you can also add the name of the image file after \c \\startuml + and inside curly brackets, i.e. + \verbatim + @startuml{myimage.png} + Alice -> Bob : Hello + @enduml + \endverbatim + When the name of the image is specified, doxygen will generate an image with that name. + Without the name doxygen will choose a name automatically. + + The second argument is optional and can be used to specify the caption + that is displayed below the image. This argument has to be specified + between quotes even if it does not contain any spaces. The quotes are + stripped before the caption is displayed. + + The third argument is also optional and can be used to specify the + width or height of the image. + For a descriptionm of the possibilities see the paragraph + \ref image_sizeindicator "Size indication" with the + \ref cmdimage "\\image" command. + Here is an example of the use of the \c \\startuml command. \code /** Sender class. Can be used to send a command to the server. @@ -2575,19 +2621,8 @@ class Receiver }; \endcode -\note For compatibility with running PlantUML as a preprocessing step before -running doxygen, you can also add the name of the image file after \c \\startuml -and inside curly brackets, i.e. -\verbatim -@startuml{myimage.png} -Alice -> Bob : Hello -@enduml -\endverbatim -When the name of the image is specified, doxygen will generate an image with that name. -Without the name doxygen will choose a name automatically. -
-\section cmddotfile \\dotfile ["caption"] +\section cmddotfile \\dotfile ["caption"] [=] \addindex \\dotfile Inserts an image generated by dot from \ into the documentation. @@ -2604,8 +2639,16 @@ Without the name doxygen will choose a name automatically. between quotes even if it does not contain any spaces. The quotes are stripped before the caption is displayed. + The third argument is also optional and can be used to specify the + width or height of the image. + For a descriptionm of the possibilities see the paragraph + \ref image_sizeindicator "Size indication" with the + \ref cmdimage "\\image" command. + + \sa section \ref cmddot "\\dot". +
-\section cmdmscfile \\mscfile ["caption"] +\section cmdmscfile \\mscfile ["caption"] [=] \addindex \\mscfile Inserts an image generated by mscgen from \ into the documentation. @@ -2623,10 +2666,16 @@ Without the name doxygen will choose a name automatically. between quotes even if it does not contain any spaces. The quotes are stripped before the caption is displayed. + The third argument is also optional and can be used to specify the + width or height of the image. + For a descriptionm of the possibilities see the paragraph + \ref image_sizeindicator "Size indication" with the + \ref cmdimage "\\image" command. + \sa section \ref cmdmsc "\\msc".
-\section cmddiafile \\diafile ["caption"] +\section cmddiafile \\diafile ["caption"] [=] \addindex \\diafile Inserts an image made in dia from \ into the documentation. @@ -2643,6 +2692,12 @@ Without the name doxygen will choose a name automatically. between quotes even if it does not contain any spaces. The quotes are stripped before the caption is displayed. + The third argument is also optional and can be used to specify the + width or height of the image. + For a descriptionm of the possibilities see the paragraph + \ref image_sizeindicator "Size indication" with the + \ref cmdimage "\\image" command. +
\section cmde \\e @@ -2843,7 +2898,7 @@ Without the name doxygen will choose a name automatically. format you'll have to repeat this command for each format. The first argument specifies the output format. Currently, the - following values are supported: \c html, \c latex and \c rtf. + following values are supported: \c html, \c latex, \c docbook and \c rtf. The second argument specifies the file name of the image. doxygen will look for files in the paths (or files) that you specified @@ -2859,12 +2914,16 @@ Without the name doxygen will choose a name automatically. spaces. The quotes are stripped before the caption is displayed. The fourth argument is also optional and can be used to specify the - width or height of the image. This is only useful - for \LaTeX output - (i.e. format=latex). The \c sizeindication can be - either \c width or \c height. The size should be a valid - size specifier in \LaTeX (for example 10cm or - 6in or a symbolic width like \\textwidth). + width or height of the image. This can be useful for \LaTeX output + (i.e. format=latex). + \anchor image_sizeindicator \par Size indication + The \c sizeindication can + specify the width or height to be used )or a combination). Possible + values are (width, analogous for height): + `width` or `max with` or `min width`. The size should be a valid + size specifier in \LaTeX (for example `10cm` or + `6in` or a symbolic width like `\\textwidth`). (The `max width` etc. + are based on the \LaTeX package `adjustbox`) Here is example of a comment block: diff --git a/src/cmdmapper.cpp b/src/cmdmapper.cpp index b0ca85f..3782ff3 100644 --- a/src/cmdmapper.cpp +++ b/src/cmdmapper.cpp @@ -226,6 +226,16 @@ int Mapper::map(const char *n) return !name.isEmpty() && (result=m_map.find(name)) ? *result: 0; } +QString Mapper::map(const int n) +{ + QDictIterator mapIterator(m_map); + for (int *curVal = mapIterator.toFirst();curVal = mapIterator.current();++mapIterator) + { + if (*curVal == n || (*curVal == (n | SIMPLESECT_BIT))) return mapIterator.currentKey(); + } + return NULL; +} + Mapper::Mapper(const CommandMap *cm,bool caseSensitive) : m_map(89), m_cs(caseSensitive) { m_map.setAutoDelete(TRUE); diff --git a/src/cmdmapper.h b/src/cmdmapper.h index 75fd8ec..f741290 100644 --- a/src/cmdmapper.h +++ b/src/cmdmapper.h @@ -201,6 +201,7 @@ class Mapper { public: int map(const char *n); + QString map(const int n); Mapper(const CommandMap *cm,bool caseSensitive); private: QDict m_map; diff --git a/src/docbookvisitor.cpp b/src/docbookvisitor.cpp index a227dd8..0d5f260 100644 --- a/src/docbookvisitor.cpp +++ b/src/docbookvisitor.cpp @@ -36,6 +36,68 @@ #include "htmlentity.h" #include "plantuml.h" +static void visitPreStart(FTextStream &t, const bool hasCaption, QCString name, QCString width, QCString height) +{ + QCString tmpStr; + t << "
" << endl; + t << " " << endl; + t << " " << endl; + t << " " << endl; + t << " "; + t << "" << endl; + t << " " << endl; + if (hasCaption) + { + t << " " << endl; + } +} + +static void visitPostEnd(FTextStream &t, const bool hasCaption) +{ + t << endl; + if (hasCaption) + { + t << " " << endl; + } + t << " " << endl; + t << "
" << endl; +} + +static void visitCaption(DocbookDocVisitor *parent, QList children) +{ + QListIterator cli(children); + DocNode *n; + for (cli.toFirst();(n=cli.current());++cli) n->accept(parent); +} + DocbookDocVisitor::DocbookDocVisitor(FTextStream &t,CodeOutputInterface &ci) : DocVisitor(DocVisitor_Docbook), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE) { @@ -205,14 +267,7 @@ void DocbookDocVisitor::visit(DocVerbatim *s) } file.writeBlock( stext, stext.length() ); file.close(); - m_t << "
" << endl; - m_t << " " << name << "" << endl; - m_t << " " << endl; - m_t << " " << endl; - writeDotFile(baseName); - m_t << " " << endl; - m_t << " " << endl; - m_t << "
" << endl; + writeDotFile(baseName, s); m_t << "" << endl; } break; @@ -238,14 +293,7 @@ void DocbookDocVisitor::visit(DocVerbatim *s) text+="}"; file.writeBlock( text, text.length() ); file.close(); - m_t << "
" << endl; - m_t << " " << name << "" << endl; - m_t << " " << endl; - m_t << " " << endl; - writeMscFile(baseName); - m_t << " " << endl; - m_t << " " << endl; - m_t << "
" << endl; + writeMscFile(baseName,s); m_t << "" << endl; } break; @@ -259,14 +307,8 @@ void DocbookDocVisitor::visit(DocVerbatim *s) { shortName=shortName.right(shortName.length()-i-1); } - m_t << "
" << endl; - m_t << " " << shortName << "" << endl; - m_t << " " << endl; - m_t << " " << endl; - writePlantUMLFile(baseName); - m_t << " " << endl; - m_t << " " << endl; - m_t << "
" << endl; + m_t << "" << endl; + writePlantUMLFile(baseName,s); m_t << "" << endl; } break; @@ -850,8 +892,13 @@ void DocbookDocVisitor::visitPre(DocImage *img) { if (m_hide) return; m_t << endl; - m_t << "
" << endl; - m_t << " "; + QCString baseName=img->name(); + int i; + if ((i=baseName.findRev('/'))!=-1 || (i=baseName.findRev('\\'))!=-1) + { + baseName=baseName.right(baseName.length()-i-1); + } + visitPreStart(m_t, img -> hasCaption(), baseName, img -> width(), img -> height()); } else { @@ -865,39 +912,14 @@ void DocbookDocVisitor::visitPost(DocImage *img) if (img->type()==DocImage::DocBook) { if (m_hide) return; - QCString typevar; - m_t << "" << endl; - m_t << " " << endl; - m_t << " " << endl; + visitPostEnd(m_t, img -> hasCaption()); + // copy the image to the output dir QCString baseName=img->name(); int i; if ((i=baseName.findRev('/'))!=-1 || (i=baseName.findRev('\\'))!=-1) { baseName=baseName.right(baseName.length()-i-1); } - m_t << " width().isEmpty()) - { - m_t << " width=\""; - filter(img->width()); - m_t << "\""; - } - else - { - m_t << " width=\"50%\""; - } - if (!img->height().isEmpty()) - { - m_t << " depth=\""; - filter(img->height()); - m_t << "\""; - } - m_t << " align=\"center\" valign=\"middle\" scalefit=\"1\" fileref=\"" << baseName << "\">"; - m_t << "" << endl; - m_t << " " << endl; - m_t << " " << endl; - m_t << "
" << endl; - // copy the image to the output dir QCString m_file; bool ambig; FileDef *fd=findFileDef(Doxygen::imageNameDict, baseName, ambig); @@ -1203,7 +1225,7 @@ void DocbookDocVisitor::popEnabled() delete v; } -void DocbookDocVisitor::writeMscFile(const QCString &baseName) +void DocbookDocVisitor::writeMscFile(const QCString &baseName, DocVerbatim *s) { QCString shortName = baseName; int i; @@ -1213,13 +1235,12 @@ void DocbookDocVisitor::writeMscFile(const QCString &baseName) } QCString outDir = Config_getString("DOCBOOK_OUTPUT"); writeMscGraphFromFile(baseName+".msc",outDir,shortName,MSC_BITMAP); - m_t << " "; - m_t << "" << endl; + visitPreStart(m_t, s->hasCaption(), shortName, s->width(),s->height()); + visitCaption(this, s->m_children); + visitPostEnd(m_t, s->hasCaption()); } -void DocbookDocVisitor::writePlantUMLFile(const QCString &baseName) +void DocbookDocVisitor::writePlantUMLFile(const QCString &baseName, DocVerbatim *s) { QCString shortName = baseName; int i; @@ -1229,10 +1250,9 @@ void DocbookDocVisitor::writePlantUMLFile(const QCString &baseName) } QCString outDir = Config_getString("DOCBOOK_OUTPUT"); generatePlantUMLOutput(baseName,outDir,PUML_BITMAP); - m_t << " "; - m_t << "" << endl; + visitPreStart(m_t, s->hasCaption(), shortName, s->width(),s->height()); + visitCaption(this, s->m_children); + visitPostEnd(m_t, s->hasCaption()); } void DocbookDocVisitor::startMscFile(const QCString &fileName, @@ -1255,50 +1275,17 @@ void DocbookDocVisitor::startMscFile(const QCString &fileName, QCString outDir = Config_getString("DOCBOOK_OUTPUT"); writeMscGraphFromFile(fileName,outDir,baseName,MSC_BITMAP); m_t << "" << endl; - m_t << "
" << endl; - m_t << " " << endl; - m_t << " " << endl; - m_t << " " << endl; - m_t << " "; - m_t << "" << endl; - m_t << " " << endl; - if (hasCaption) - { - m_t << " " << endl; - } + visitPreStart(m_t, hasCaption, baseName + ".png", width, height); } void DocbookDocVisitor::endMscFile(bool hasCaption) { if (m_hide) return; - m_t << "endl"; - if (hasCaption) - { - m_t << " " << endl; - } - m_t << " " << endl; - m_t << "
" << endl; + visitPostEnd(m_t, hasCaption); m_t << "
" << endl; } -void DocbookDocVisitor::writeDiaFile(const QCString &baseName) +void DocbookDocVisitor::writeDiaFile(const QCString &baseName, DocVerbatim *s) { QCString shortName = baseName; int i; @@ -1308,9 +1295,9 @@ void DocbookDocVisitor::writeDiaFile(const QCString &baseName) } QCString outDir = Config_getString("DOCBOOK_OUTPUT"); writeDiaGraphFromFile(baseName+".dia",outDir,shortName,DIA_BITMAP); - m_t << " "; - m_t << "" << endl; + visitPreStart(m_t, s->hasCaption(), shortName, s->width(),s->height()); + visitCaption(this, s->m_children); + visitPostEnd(m_t, s->hasCaption()); } void DocbookDocVisitor::startDiaFile(const QCString &fileName, @@ -1333,46 +1320,17 @@ void DocbookDocVisitor::startDiaFile(const QCString &fileName, QCString outDir = Config_getString("DOCBOOK_OUTPUT"); writeDiaGraphFromFile(fileName,outDir,baseName,DIA_BITMAP); m_t << "" << endl; - m_t << "
" << endl; - m_t << " " << endl; - m_t << " " << endl; - m_t << " " << endl; - m_t << " "; - m_t << "" << endl; - m_t << " " << endl; - if (hasCaption) - { - m_t << " " << endl; - } + visitPreStart(m_t, hasCaption, baseName + ".png", width, height); } void DocbookDocVisitor::endDiaFile(bool hasCaption) { if (m_hide) return; - m_t << "endl"; - if (hasCaption) - { - m_t << " " << endl; - } - m_t << " " << endl; - m_t << "
" << endl; + visitPostEnd(m_t, hasCaption); m_t << "
" << endl; } -void DocbookDocVisitor::writeDotFile(const QCString &baseName) +void DocbookDocVisitor::writeDotFile(const QCString &baseName, DocVerbatim *s) { QCString shortName = baseName; int i; @@ -1383,11 +1341,9 @@ void DocbookDocVisitor::writeDotFile(const QCString &baseName) QCString outDir = Config_getString("DOCBOOK_OUTPUT"); QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT"); writeDotGraphFromFile(baseName+".dot",outDir,shortName,GOF_BITMAP); - m_t << " "; - m_t << "" << endl; + visitPreStart(m_t, s->hasCaption(), baseName + ".dot", s->width(),s->height()); + visitCaption(this, s->m_children); + visitPostEnd(m_t, s->hasCaption()); } void DocbookDocVisitor::startDotFile(const QCString &fileName, @@ -1411,46 +1367,14 @@ void DocbookDocVisitor::startDotFile(const QCString &fileName, QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT"); writeDotGraphFromFile(fileName,outDir,baseName,GOF_BITMAP); m_t << "" << endl; - m_t << "
" << endl; - m_t << " " << endl; - m_t << " " << endl; - m_t << " " << endl; - m_t << " "; - m_t << "" << endl; - m_t << " " << endl; - if (hasCaption) - { - m_t << " " << endl; - } + visitPreStart(m_t, hasCaption, baseName + "." + imgExt, width, height); } void DocbookDocVisitor::endDotFile(bool hasCaption) { if (m_hide) return; - m_t << "endl"; - if (hasCaption) - { - m_t << " " << endl; - } - m_t << " " << endl; - m_t << "
" << endl; + m_t << endl; + visitPostEnd(m_t, hasCaption); m_t << "
" << endl; } diff --git a/src/docbookvisitor.h b/src/docbookvisitor.h index dd67aba..3796d8a 100644 --- a/src/docbookvisitor.h +++ b/src/docbookvisitor.h @@ -147,16 +147,16 @@ class DocbookDocVisitor : public DocVisitor void startMscFile(const QCString &fileName,const QCString &width, const QCString &height, bool hasCaption); void endMscFile(bool hasCaption); - void writeMscFile(const QCString &fileName); + void writeMscFile(const QCString &fileName, DocVerbatim *s); void startDiaFile(const QCString &fileName,const QCString &width, const QCString &height, bool hasCaption); void endDiaFile(bool hasCaption); - void writeDiaFile(const QCString &fileName); + void writeDiaFile(const QCString &fileName, DocVerbatim *s); void startDotFile(const QCString &fileName,const QCString &width, const QCString &height, bool hasCaption); void endDotFile(bool hasCaption); - void writeDotFile(const QCString &fileName); - void writePlantUMLFile(const QCString &fileName); + void writeDotFile(const QCString &fileName, DocVerbatim *s); + void writePlantUMLFile(const QCString &fileName, DocVerbatim *s); //-------------------------------------- // state variables //-------------------------------------- diff --git a/src/docparser.cpp b/src/docparser.cpp index b21c15c..34018d1 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -818,6 +818,8 @@ static bool findDocsForMemberOrCompound(const char *commandName, static bool defaultHandleToken(DocNode *parent,int tok, QList &children,bool handleWord=TRUE); +static void defaultHandleCaptionSize(const int cmd, DocNode *parent, QList &children, + QCString &height, QCString &width); static int handleStyleArgument(DocNode *parent,QList &children, @@ -1220,6 +1222,135 @@ static DocAnchor *handleAnchor(DocNode *parent) } +/* Helper function that deals with the Caption and size argument. + * @param parent Parent node, owner of the children list passed as + * the third argument. + * @param children The list of child nodes to which the node representing + * the token can be added. + * @param height Storagre for, optional, height + * @param width Storagre for, optional, width + */ +static void defaultHandleCaptionSize(const int cmd, DocNode *parent, QList &children, QCString &height, QCString &width) +{ + QCString preamble = ""; + int insideString = 0; + g_nodeStack.push(parent); + + // parse title + doctokenizerYYsetStateCaption(); + int tok; + while ((tok=doctokenizerYYlex())) + { + if (tok==TK_WORD && g_token->name=="width=") + { + // special case: no title, but we do have a size indicator + doctokenizerYYsetStateTitleAttr(); + // strip = + width=preamble + g_token->name + g_token->chars; + g_token->chars = ""; + g_token->name = ""; + preamble = ""; + do + { + tok=doctokenizerYYlex(); + } while (tok == TK_WHITESPACE); + break; + } + if (tok==TK_WORD && g_token->name=="height=") + { + // special case: no title, but we do have a size indicator + doctokenizerYYsetStateTitleAttr(); + // strip = + height=preamble + g_token->name + g_token->chars; + g_token->chars = ""; + g_token->name = ""; + preamble = ""; + do + { + tok=doctokenizerYYlex(); + } while (tok == TK_WHITESPACE); + break; + } + if (tok==TK_WORD && (g_token->name=="min" || g_token->name=="max")) + { + // special case: no title, but we do have a size indicator min or max + if (!insideString) + { + preamble = g_token->name + " "; + break; + } + } + insideString = 1; + if (!defaultHandleToken(parent,tok,children)) + { + switch (tok) + { + case TK_COMMAND: + warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\%s", + qPrint(g_token->name), Mappers::cmdMapper->map(cmd).data()); + break; + case TK_SYMBOL: + warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found", + qPrint(g_token->name)); + break; + default: + warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s", + tokToString(tok)); + break; + } + } + } + // parse size attributes + if (tok == 0) + { + tok=doctokenizerYYlex(); + } + while (tok==TK_WORD) // there are values following the title + { + if (g_token->name=="width") + { + if (!width.isEmpty()) width += ","; + width+=preamble + "width=" + g_token->chars; + preamble = ""; + doctokenizerYYsetStateTitleAttr(); + } + else if (g_token->name=="height") + { + if (!height.isEmpty()) height += ","; + height+=preamble + "height=" + g_token->chars; + preamble = ""; + doctokenizerYYsetStateTitleAttr(); + } + else if (g_token->name=="max") + { + preamble = "max "; + } + else if (g_token->name=="min") + { + preamble = "min "; + } + else + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Unknown option %s after \\%s command", + qPrint(g_token->name), Mappers::cmdMapper->map(cmd).data()); + } + + do + { + tok=doctokenizerYYlex(); + if (tok==TK_WORD && (g_token->name=="width=" || g_token->name=="height=")) + { + g_token->name=g_token->name.left(g_token->name.length()-1); + tok=doctokenizerYYlex(); + } + } while (tok == TK_WHITESPACE); + } + doctokenizerYYsetStatePara(); + + handlePendingStyleCommands(parent,children); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==parent); +} /* Helper function that deals with the most common tokens allowed in * title like sections. * @param parent Parent node, owner of the children list passed as @@ -2619,53 +2750,7 @@ DocDotFile::DocDotFile(DocNode *parent,const QCString &name,const QCString &cont void DocDotFile::parse() { - g_nodeStack.push(this); - DBG(("DocDotFile::parse() start\n")); - - doctokenizerYYsetStateTitle(); - int tok; - while ((tok=doctokenizerYYlex())) - { - if (!defaultHandleToken(this,tok,m_children)) - { - switch (tok) - { - case TK_COMMAND: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\dotfile", - qPrint(g_token->name)); - break; - case TK_SYMBOL: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found", - qPrint(g_token->name)); - break; - default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s", - tokToString(tok)); - break; - } - } - } - tok=doctokenizerYYlex(); - while (tok==TK_WORD) // there are values following the title - { - if (g_token->name=="width") - { - m_width=g_token->chars; - } - else if (g_token->name=="height") - { - m_height=g_token->chars; - } - else - { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unknown option %s after image title", - qPrint(g_token->name)); - } - tok=doctokenizerYYlex(); - } - ASSERT(tok==0); - doctokenizerYYsetStatePara(); - handlePendingStyleCommands(this,m_children); + defaultHandleCaptionSize(CMD_DOTFILE,this,m_children,m_height, m_width); bool ambig; FileDef *fd = findFileDef(Doxygen::dotFileNameDict,m_name,ambig); @@ -2689,10 +2774,6 @@ void DocDotFile::parse() warn_doc_error(g_fileName,doctokenizerYYlineno,"included dot file %s is not found " "in any of the paths specified via DOTFILE_DIRS!",qPrint(m_name)); } - - DBG(("DocDotFile::parse() end\n")); - DocNode *n=g_nodeStack.pop(); - ASSERT(n==this); } DocMscFile::DocMscFile(DocNode *parent,const QCString &name,const QCString &context) : @@ -2703,53 +2784,7 @@ DocMscFile::DocMscFile(DocNode *parent,const QCString &name,const QCString &cont void DocMscFile::parse() { - g_nodeStack.push(this); - DBG(("DocMscFile::parse() start\n")); - - doctokenizerYYsetStateTitle(); - int tok; - while ((tok=doctokenizerYYlex())) - { - if (!defaultHandleToken(this,tok,m_children)) - { - switch (tok) - { - case TK_COMMAND: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\mscfile", - qPrint(g_token->name)); - break; - case TK_SYMBOL: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found", - qPrint(g_token->name)); - break; - default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s", - tokToString(tok)); - break; - } - } - } - tok=doctokenizerYYlex(); - while (tok==TK_WORD) // there are values following the title - { - if (g_token->name=="width") - { - m_width=g_token->chars; - } - else if (g_token->name=="height") - { - m_height=g_token->chars; - } - else - { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unknown option %s after image title", - qPrint(g_token->name)); - } - tok=doctokenizerYYlex(); - } - ASSERT(tok==0); - doctokenizerYYsetStatePara(); - handlePendingStyleCommands(this,m_children); + defaultHandleCaptionSize(CMD_MSCFILE,this,m_children,m_height, m_width); bool ambig; FileDef *fd = findFileDef(Doxygen::mscFileNameDict,m_name,ambig); @@ -2773,10 +2808,6 @@ void DocMscFile::parse() warn_doc_error(g_fileName,doctokenizerYYlineno,"included msc file %s is not found " "in any of the paths specified via MSCFILE_DIRS!",qPrint(m_name)); } - - DBG(("DocMscFile::parse() end\n")); - DocNode *n=g_nodeStack.pop(); - ASSERT(n==this); } //--------------------------------------------------------------------------- @@ -2789,53 +2820,7 @@ DocDiaFile::DocDiaFile(DocNode *parent,const QCString &name,const QCString &cont void DocDiaFile::parse() { - g_nodeStack.push(this); - DBG(("DocDiaFile::parse() start\n")); - - doctokenizerYYsetStateTitle(); - int tok; - while ((tok=doctokenizerYYlex())) - { - if (!defaultHandleToken(this,tok,m_children)) - { - switch (tok) - { - case TK_COMMAND: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\diafile", - qPrint(g_token->name)); - break; - case TK_SYMBOL: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found", - qPrint(g_token->name)); - break; - default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s", - tokToString(tok)); - break; - } - } - } - tok=doctokenizerYYlex(); - while (tok==TK_WORD) // there are values following the title - { - if (g_token->name=="width") - { - m_width=g_token->chars; - } - else if (g_token->name=="height") - { - m_height=g_token->chars; - } - else - { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unknown option %s after image title", - qPrint(g_token->name)); - } - tok=doctokenizerYYlex(); - } - ASSERT(tok==0); - doctokenizerYYsetStatePara(); - handlePendingStyleCommands(this,m_children); + defaultHandleCaptionSize(CMD_DIAFILE,this,m_children,m_height, m_width); bool ambig; FileDef *fd = findFileDef(Doxygen::diaFileNameDict,m_name,ambig); @@ -2859,10 +2844,6 @@ void DocDiaFile::parse() warn_doc_error(g_fileName,doctokenizerYYlineno,"included dia file %s is not found " "in any of the paths specified via DIAFILE_DIRS!",qPrint(m_name)); } - - DBG(("DocDiaFile::parse() end\n")); - DocNode *n=g_nodeStack.pop(); - ASSERT(n==this); } //--------------------------------------------------------------------------- @@ -2925,66 +2906,7 @@ DocImage::DocImage(DocNode *parent,const HtmlAttribList &attribs,const QCString void DocImage::parse() { - g_nodeStack.push(this); - DBG(("DocImage::parse() start\n")); - - // parse title - doctokenizerYYsetStateTitle(); - int tok; - while ((tok=doctokenizerYYlex())) - { - if (tok==TK_WORD && (g_token->name=="width=" || g_token->name=="height=")) - { - // special case: no title, but we do have a size indicator - doctokenizerYYsetStateTitleAttrValue(); - // strip = - g_token->name=g_token->name.left(g_token->name.length()-1); - break; - } - if (!defaultHandleToken(this,tok,m_children)) - { - switch (tok) - { - case TK_COMMAND: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\image", - qPrint(g_token->name)); - break; - case TK_SYMBOL: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found", - qPrint(g_token->name)); - break; - default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s", - tokToString(tok)); - break; - } - } - } - // parse size attributes - tok=doctokenizerYYlex(); - while (tok==TK_WORD) // there are values following the title - { - if (g_token->name=="width") - { - m_width=g_token->chars; - } - else if (g_token->name=="height") - { - m_height=g_token->chars; - } - else - { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unknown option %s after image title", - qPrint(g_token->name)); - } - tok=doctokenizerYYlex(); - } - doctokenizerYYsetStatePara(); - - handlePendingStyleCommands(this,m_children); - DBG(("DocImage::parse() end\n")); - DocNode *n=g_nodeStack.pop(); - ASSERT(n==this); + defaultHandleCaptionSize(CMD_IMAGE,this,m_children,m_height, m_width); } @@ -5563,18 +5485,44 @@ int DocPara::handleCommand(const QCString &cmdName) break; case CMD_DOT: { + /* + * need a temporary variable to store information for width, height and caption + * which will be written into te right variable. + */ + DocVerbatim *tmp_dv = new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Dot,g_isExample,g_exampleName); + doctokenizerYYsetStatePara(); + defaultHandleCaptionSize(CMD_DOT,tmp_dv,tmp_dv->m_children,tmp_dv->m_height,tmp_dv-> m_width); + doctokenizerYYsetStateDot(); retval = doctokenizerYYlex(); - m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Dot,g_isExample,g_exampleName)); + DocVerbatim *dv = new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Dot,g_isExample,g_exampleName); + dv -> m_width = tmp_dv -> m_width; + dv -> m_height = tmp_dv -> m_height; + dv -> m_children = tmp_dv -> m_children; + delete tmp_dv; + m_children.append(dv); if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"dot section ended without end marker"); doctokenizerYYsetStatePara(); } break; case CMD_MSC: { + /* + * need a temporary variable to store information for width, height and caption + * which will be written into te right variable. + */ + DocVerbatim *tmp_dv = new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Msc,g_isExample,g_exampleName); + doctokenizerYYsetStatePara(); + defaultHandleCaptionSize(CMD_MSC,tmp_dv,tmp_dv->m_children,tmp_dv->m_height,tmp_dv-> m_width); + doctokenizerYYsetStateMsc(); retval = doctokenizerYYlex(); - m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Msc,g_isExample,g_exampleName)); + DocVerbatim *dv = new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Msc,g_isExample,g_exampleName); + dv -> m_width = tmp_dv -> m_width; + dv -> m_height = tmp_dv -> m_height; + dv -> m_children = tmp_dv -> m_children; + delete tmp_dv; + m_children.append(dv); if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"msc section ended without end marker"); doctokenizerYYsetStatePara(); } @@ -5582,15 +5530,31 @@ int DocPara::handleCommand(const QCString &cmdName) case CMD_STARTUML: { static QCString jarPath = Config_getString("PLANTUML_JAR_PATH"); + doctokenizerYYsetStatePlantUMLOpt(); + retval = doctokenizerYYlex(); + QCString plantFile(g_token->sectionId); + /* + * need a temporary variable to store information for width, height and caption + * which will be written into te right variable. + */ + DocVerbatim *tmp_dv = new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Msc,g_isExample,g_exampleName); + doctokenizerYYsetStatePara(); + defaultHandleCaptionSize(CMD_STARTUML,tmp_dv,tmp_dv->m_children,tmp_dv->m_height,tmp_dv-> m_width); + doctokenizerYYsetStatePlantUML(); retval = doctokenizerYYlex(); if (jarPath.isEmpty()) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"ignoring startuml command because PLANTUML_JAR_PATH is not set"); + 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)); + DocVerbatim *dv = new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::PlantUML,FALSE,plantFile); + dv -> m_width = tmp_dv -> m_width; + dv -> m_height = tmp_dv -> m_height; + dv -> m_children = tmp_dv -> m_children; + delete tmp_dv; + m_children.append(dv); } if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"startuml section ended without end marker"); doctokenizerYYsetStatePara(); diff --git a/src/docparser.h b/src/docparser.h index 3dc3d84..83312c4 100644 --- a/src/docparser.h +++ b/src/docparser.h @@ -447,6 +447,11 @@ class DocVerbatim : public DocNode QCString relPath() const { return m_relPath; } QCString language() const { return m_lang; } bool isBlock() const { return m_isBlock; } + bool hasCaption() const { return !m_children.isEmpty(); } + QCString width() const { return m_width; } + QCString height() const { return m_height; } + const QList &children() const { return m_children; } + QList &children() { return m_children; } private: QCString m_context; @@ -457,6 +462,10 @@ class DocVerbatim : public DocNode QCString m_relPath; QCString m_lang; bool m_isBlock; + public: + QCString m_width; + QCString m_height; + QList m_children; }; @@ -668,7 +677,7 @@ class DocXRefItem : public CompAccept, public DocNode class DocImage : public CompAccept, public DocNode { public: - enum Type { Html, Latex, Rtf, DocBook }; + enum Type { None, Html, Latex, Rtf, DocBook }; DocImage(DocNode *parent,const HtmlAttribList &attribs, const QCString &name,Type t,const QCString &url=QCString()); Kind kind() const { return Kind_Image; } @@ -686,7 +695,7 @@ class DocImage : public CompAccept, public DocNode private: HtmlAttribList m_attribs; QCString m_name; - Type m_type; + Type m_type; QCString m_width; QCString m_height; QCString m_relPath; diff --git a/src/doctokenizer.h b/src/doctokenizer.h index c95230b..1b734ec 100644 --- a/src/doctokenizer.h +++ b/src/doctokenizer.h @@ -131,8 +131,10 @@ void doctokenizerYYpushContext(); bool doctokenizerYYpopContext(); int doctokenizerYYlex(); void doctokenizerYYsetStatePara(); +void doctokenizerYYsetStateCaption(); void doctokenizerYYsetStateTitle(); void doctokenizerYYsetStateTitleAttrValue(); +void doctokenizerYYsetStateTitleAttr(); void doctokenizerYYsetStateCode(); void doctokenizerYYsetStateXmlCode(); void doctokenizerYYsetStateHtmlOnly(); @@ -161,5 +163,6 @@ void doctokenizerYYsetStateSnippet(); void doctokenizerYYstartAutoList(); void doctokenizerYYendAutoList(); void doctokenizerYYsetStatePlantUML(); +void doctokenizerYYsetStatePlantUMLOpt(); #endif diff --git a/src/doctokenizer.l b/src/doctokenizer.l index e0e72a7..9fd3c46 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -400,6 +400,7 @@ REFWORD {LABELID}|{REFWORD2}|{REFWORD3}|{LNKWORD2} %x St_Para %x St_Comment %x St_Title +%x St_Caption %x St_TitleN %x St_TitleQ %x St_TitleA @@ -853,14 +854,18 @@ REFWORD {LABELID}|{REFWORD2}|{REFWORD3}|{LNKWORD2} . { /* msc text */ g_token->verb+=yytext; } -\n { - g_token->sectionId=g_token->sectionId.stripWhiteSpace(); - BEGIN(St_PlantUML); - } -["{}] { // skip curly brackets or quotes around the optional image name +{BLANK}*"{"[^}]*"}" { // skip curly brackets around the optional image name + g_token->sectionId = yytext; + g_token->sectionId = g_token->sectionId.stripWhiteSpace(); + g_token->sectionId = g_token->sectionId.left(g_token->sectionId.length()-1); + g_token->sectionId = g_token->sectionId.right(g_token->sectionId.length()-1); + g_token->sectionId = g_token->sectionId.stripWhiteSpace(); + return RetVal_OK; } . { - g_token->sectionId += yytext; + g_token->sectionId = ""; + unput(*yytext); + return RetVal_OK; } {CMD}"enduml" { return RetVal_OK; @@ -870,6 +875,19 @@ REFWORD {LABELID}|{REFWORD2}|{REFWORD3}|{LNKWORD2} . { /* plantuml text */ g_token->verb+=yytext; } +"\"" { // quoted title + BEGIN(St_TitleQ); + return TK_WORD; + } +[ \t]+ { + g_token->name=""; + g_token->chars=yytext; + return TK_WHITESPACE; + } +\n { + unput(*yytext); + return 0; + } "\"" { // quoted title BEGIN(St_TitleQ); } @@ -940,10 +958,38 @@ REFWORD {LABELID}|{REFWORD2}|{REFWORD3}|{LNKWORD2} unput(*yytext); return 0; } +{BLANK}*"min"{BLANK}* { // title special case min / max + g_token->name = "min"; + BEGIN(St_TitleA); + return TK_WORD; + } +{BLANK}*"max"{BLANK}* { // title special case min / max + g_token->name = "max"; + BEGIN(St_TitleA); + return TK_WORD; + } +{BLANK}*"width="{BLANK}* { // title attribute + g_token->name = yytext; + g_token->name = g_token->name.stripWhiteSpace(); + BEGIN(St_TitleV); + } +{BLANK}*"height="{BLANK}* { // title attribute + g_token->name = yytext; + g_token->name = g_token->name.stripWhiteSpace(); + BEGIN(St_TitleV); + } +{BLANK}*"min"{BLANK}* { // title special case min / max + g_token->name = "min"; + return TK_WORD; + } +{BLANK}*"max"{BLANK}* { // title special case min / max + g_token->name = "max"; + return TK_WORD; + } {BLANK}*{ID}{BLANK}*"="{BLANK}* { // title attribute g_token->name = yytext; g_token->name = g_token->name.left( - g_token->name.find('=')).stripWhiteSpace(); + g_token->name.find('=')).stripWhiteSpace(); BEGIN(St_TitleV); } [^ \t\r\n]+ { // attribute value @@ -951,6 +997,10 @@ REFWORD {LABELID}|{REFWORD2}|{REFWORD3}|{LNKWORD2} BEGIN(St_TitleN); return TK_WORD; } +[ \t] { + g_token->chars=yytext; + return TK_WHITESPACE; + } . { unput(*yytext); return 0; @@ -1224,7 +1274,7 @@ REFWORD {LABELID}|{REFWORD2}|{REFWORD3}|{LNKWORD2} return TK_COMMAND; } <*>. { - warn(g_fileName,yylineno,"Unexpected character `%s'",yytext); + warn(g_fileName,yylineno,"Unexpected character `%s'",yytext); } %% @@ -1267,6 +1317,16 @@ void doctokenizerYYsetStateTitle() BEGIN(St_Title); } +void doctokenizerYYsetStateCaption() +{ + BEGIN(St_Caption); +} + +void doctokenizerYYsetStateTitleAttr() +{ + BEGIN(St_TitleA); +} + void doctokenizerYYsetStateTitleAttrValue() { BEGIN(St_TitleV); @@ -1341,13 +1401,19 @@ void doctokenizerYYsetStateMsc() BEGIN(St_Msc); } -void doctokenizerYYsetStatePlantUML() +void doctokenizerYYsetStatePlantUMLOpt() { g_token->verb=""; g_token->sectionId=""; BEGIN(St_PlantUMLOpt); } +void doctokenizerYYsetStatePlantUML() +{ + g_token->verb=""; + BEGIN(St_PlantUML); +} + void doctokenizerYYsetStateParam() { BEGIN(St_Param); diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp index e319a1f..4d61ca7 100644 --- a/src/htmldocvisitor.cpp +++ b/src/htmldocvisitor.cpp @@ -325,6 +325,32 @@ void HtmlDocVisitor::visit(DocStyleChange *s) } +static void visitPreCaption(FTextStream &t, DocVerbatim *s) +{ + if (s->hasCaption()) + { + t << "
" << endl; + } +} + + +static void visitPostCaption(FTextStream &t, DocVerbatim *s) +{ + if (s->hasCaption()) + { + t << "
" << endl; + } +} + + +static void visitCaption(HtmlDocVisitor *parent, QList children) +{ + QListIterator cli(children); + DocNode *n; + for (cli.toFirst();(n=cli.current());++cli) n->accept(parent); +} + + void HtmlDocVisitor::visit(DocVerbatim *s) { if (m_hide) return; @@ -382,6 +408,7 @@ void HtmlDocVisitor::visit(DocVerbatim *s) static int dotindex = 1; QCString fileName(4096); + forceEndParagraph(s); fileName.sprintf("%s%d%s", (Config_getString("HTML_OUTPUT")+"/inline_dotgraph_").data(), dotindex++, @@ -392,16 +419,21 @@ void HtmlDocVisitor::visit(DocVerbatim *s) { err("Could not open file %s for writing\n",fileName.data()); } - file.writeBlock( s->text(), s->text().length() ); - file.close(); + else + { + file.writeBlock( s->text(), s->text().length() ); + file.close(); - forceEndParagraph(s); - m_t << "
" << endl; - writeDotFile(fileName,s->relPath(),s->context()); - m_t << "
" << endl; - forceStartParagraph(s); + m_t << "
" << endl; + writeDotFile(fileName,s->relPath(),s->context()); + visitPreCaption(m_t, s); + visitCaption(this, s->m_children); + visitPostCaption(m_t, s); + m_t << "
" << endl; - if (Config_getBool("DOT_CLEANUP")) file.remove(); + if (Config_getBool("DOT_CLEANUP")) file.remove(); + } + forceStartParagraph(s); } break; case DocVerbatim::Msc: @@ -420,17 +452,24 @@ void HtmlDocVisitor::visit(DocVerbatim *s) { err("Could not open file %s.msc for writing\n",baseName.data()); } - QCString text = "msc {"; - text+=s->text(); - text+="}"; + else + { + QCString text = "msc {"; + text+=s->text(); + text+="}"; - file.writeBlock( text, text.length() ); - file.close(); + file.writeBlock( text, text.length() ); + file.close(); - m_t << "
" << endl; - writeMscFile(baseName+".msc",s->relPath(),s->context()); - if (Config_getBool("DOT_CLEANUP")) file.remove(); - m_t << "
" << endl; + m_t << "
" << endl; + writeMscFile(baseName+".msc",s->relPath(),s->context()); + visitPreCaption(m_t, s); + visitCaption(this, s->m_children); + visitPostCaption(m_t, s); + m_t << "
" << endl; + + if (Config_getBool("DOT_CLEANUP")) file.remove(); + } forceStartParagraph(s); } break; @@ -442,6 +481,9 @@ void HtmlDocVisitor::visit(DocVerbatim *s) QCString baseName = writePlantUMLSource(htmlOutput,s->exampleFile(),s->text()); m_t << "
" << endl; writePlantUMLFile(baseName,s->relPath(),s->context()); + visitPreCaption(m_t, s); + visitCaption(this, s->m_children); + visitPostCaption(m_t, s); m_t << "
" << endl; forceStartParagraph(s); } diff --git a/src/latexdocvisitor.cpp b/src/latexdocvisitor.cpp index af1a5fd..c53a45a 100644 --- a/src/latexdocvisitor.cpp +++ b/src/latexdocvisitor.cpp @@ -71,6 +71,75 @@ static const char *getSectionName(int level) return secLabels[QMIN(maxLevels-1,l)]; } +static void visitPreStart(FTextStream &t, const bool hasCaption, QCString name, QCString width, QCString height) +{ + if (hasCaption) + { + t << "\n\\begin{DoxyImage}\n"; + } + else + { + t << "\n\\begin{DoxyImageNoCaption}\n" + " \\mbox{"; + } + + t << "\\includegraphics"; + if (!width.isEmpty() || !height.isEmpty()) + { + t << "["; + } + if (!width.isEmpty()) + { + t << width; + } + if (!width.isEmpty() && !height.isEmpty()) + { + t << ","; + } + if (!height.isEmpty()) + { + t << height; + } + if (width.isEmpty() && height.isEmpty()) + { + /* default setting */ + t << "[width=\\textwidth,height=\\textheight/2,keepaspectratio=true]"; + } + else + { + t << "]"; + } + + t << "{" << name << "}"; + + if (hasCaption) + { + t << "\n\\caption{"; + } +} + + + +static void visitPostEnd(FTextStream &t, const bool hasCaption) +{ + t << "}\n"; // end mbox or caption + if (hasCaption) + { + t << "\\end{DoxyImage}\n"; + } + else{ + t << "\\end{DoxyImageNoCaption}\n"; + } +} + + +static void visitCaption(LatexDocVisitor *parent, QList children) +{ + QListIterator cli(children); + DocNode *n; + for (cli.toFirst();(n=cli.current());++cli) n->accept(parent); +} + QCString LatexDocVisitor::escapeMakeIndexChars(const char *s) { QCString result; @@ -284,15 +353,17 @@ void LatexDocVisitor::visit(DocVerbatim *s) { err("Could not open file %s for writing\n",fileName.data()); } - file.writeBlock( s->text(), s->text().length() ); - file.close(); + else + { + file.writeBlock( s->text(), s->text().length() ); + file.close(); - m_t << "\\begin{center}\n"; - startDotFile(fileName,"","",FALSE); - endDotFile(FALSE); - m_t << "\\end{center}\n"; + startDotFile(fileName,s->width(),s->height(),s->hasCaption()); + visitCaption(this, s->m_children); + endDotFile(s->hasCaption()); - if (Config_getBool("DOT_CLEANUP")) file.remove(); + if (Config_getBool("DOT_CLEANUP")) file.remove(); + } } break; case DocVerbatim::Msc: @@ -309,17 +380,18 @@ void LatexDocVisitor::visit(DocVerbatim *s) { err("Could not open file %s.msc for writing\n",baseName.data()); } - QCString text = "msc {"; - text+=s->text(); - text+="}"; - file.writeBlock( text, text.length() ); - file.close(); + else + { + QCString text = "msc {"; + text+=s->text(); + text+="}"; + file.writeBlock( text, text.length() ); + file.close(); - m_t << "\\begin{center}\n"; - writeMscFile(baseName); - m_t << "\\end{center}\n"; + writeMscFile(baseName, s); - if (Config_getBool("DOT_CLEANUP")) file.remove(); + if (Config_getBool("DOT_CLEANUP")) file.remove(); + } } break; case DocVerbatim::PlantUML: @@ -327,9 +399,7 @@ void LatexDocVisitor::visit(DocVerbatim *s) 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"; + writePlantUMLFile(baseName, s); } break; } @@ -1098,40 +1168,18 @@ void LatexDocVisitor::visitPost(DocHtmlHeader *) if (m_hide) return; m_t << "}"; } - void LatexDocVisitor::visitPre(DocImage *img) { if (img->type()==DocImage::Latex) { if (m_hide) return; - if (img->hasCaption()) - { - m_t << "\n\\begin{DoxyImage}\n"; - } - else - { - m_t << "\n\\begin{DoxyImageNoCaption}\n" - " \\mbox{"; - } QCString gfxName = img->name(); if (gfxName.right(4)==".eps" || gfxName.right(4)==".pdf") { gfxName=gfxName.left(gfxName.length()-4); } - m_t << "\\includegraphics"; - if (!img->width().isEmpty()) - { - m_t << "[width=" << img->width() << "]"; - } - else if (!img->height().isEmpty()) - { - m_t << "[height=" << img->height() << "]"; - } - m_t << "{" << gfxName << "}"; - if (img->hasCaption()) - { - m_t << "\n\\caption{"; - } + + visitPreStart(m_t,img->hasCaption(), gfxName, img->width(), img->height()); } else // other format -> skip { @@ -1145,14 +1193,7 @@ void LatexDocVisitor::visitPost(DocImage *img) if (img->type()==DocImage::Latex) { if (m_hide) return; - m_t << "}\n"; // end mbox or caption - if (img->hasCaption()) - { - m_t << "\\end{DoxyImage}\n"; - } - else{ - m_t << "\\end{DoxyImageNoCaption}\n"; - } + visitPostEnd(m_t,img->hasCaption()); } else // other format { @@ -1610,57 +1651,13 @@ void LatexDocVisitor::startDotFile(const QCString &fileName, QCString outDir = Config_getString("LATEX_OUTPUT"); QCString name = fileName; writeDotGraphFromFile(name,outDir,baseName,GOF_EPS); - if (hasCaption) - { - m_t << "\n\\begin{DoxyImage}\n"; - } - else - { - m_t << "\n\\begin{DoxyImageNoCaption}\n" - " \\mbox{"; - } - m_t << "\\includegraphics"; - if (!width.isEmpty()) - { - m_t << "[width=" << width << "]"; - } - else if (!height.isEmpty()) - { - m_t << "[height=" << height << "]"; - } - else - { - m_t << "[width=\\textwidth,height=\\textheight/2,keepaspectratio=true]"; - } - m_t << "{" << baseName; - //if (Config_getBool("USE_PDFLATEX")) - //{ - // m_t << ".pdf"; - //} - //else - //{ - // m_t << ".eps"; - //} - m_t << "}"; - - if (hasCaption) - { - m_t << "\n\\caption{"; - } + visitPreStart(m_t,hasCaption, baseName, width, height); } void LatexDocVisitor::endDotFile(bool hasCaption) { if (m_hide) return; - m_t << "}\n"; // end caption or mbox - if (hasCaption) - { - m_t << "\\end{DoxyImage}\n"; - } - else - { - m_t << "\\end{DoxyImageNoCaption}\n"; - } + visitPostEnd(m_t,hasCaption); } void LatexDocVisitor::startMscFile(const QCString &fileName, @@ -1683,61 +1680,17 @@ void LatexDocVisitor::startMscFile(const QCString &fileName, QCString outDir = Config_getString("LATEX_OUTPUT"); writeMscGraphFromFile(fileName,outDir,baseName,MSC_EPS); - if (hasCaption) - { - m_t << "\n\\begin{DoxyImage}\n"; - } - else - { - m_t << "\n\\begin{DoxyImageNoCaption}\n" - " \\mbox{"; - } - m_t << "\\includegraphics"; - if (!width.isEmpty()) - { - m_t << "[width=" << width << "]"; - } - else if (!height.isEmpty()) - { - m_t << "[height=" << height << "]"; - } - else - { - m_t << "[width=\\textwidth,height=\\textheight/2,keepaspectratio=true]"; - } - m_t << "{" << baseName; - //if (Config_getBool("USE_PDFLATEX")) - //{ - // m_t << ".pdf"; - //} - //else - //{ - // m_t << ".eps"; - //} - m_t << "}"; - - if (hasCaption) - { - m_t << "\n\\caption{"; - } + visitPreStart(m_t,hasCaption, baseName, width, height); } void LatexDocVisitor::endMscFile(bool hasCaption) { if (m_hide) return; - m_t << "}\n"; // end caption or mbox - if (hasCaption) - { - m_t << "\\end{DoxyImage}\n"; - } - else - { - m_t << "\\end{DoxyImageNoCaption}\n"; - } + visitPostEnd(m_t,hasCaption); } -void LatexDocVisitor::writeMscFile(const QCString &baseName) +void LatexDocVisitor::writeMscFile(const QCString &baseName, DocVerbatim *s) { QCString shortName = baseName; int i; @@ -1747,11 +1700,9 @@ void LatexDocVisitor::writeMscFile(const QCString &baseName) } QCString outDir = Config_getString("LATEX_OUTPUT"); writeMscGraphFromFile(baseName+".msc",outDir,shortName,MSC_EPS); - m_t << "\n\\begin{DoxyImageNoCaption}" - " \\mbox{\\includegraphics"; - m_t << "{" << shortName << "}"; - m_t << "}\n"; // end mbox - m_t << "\\end{DoxyImageNoCaption}\n"; + visitPreStart(m_t, s->hasCaption(), shortName, s->width(),s->height()); + visitCaption(this, s->m_children); + visitPostEnd(m_t, s->hasCaption()); } @@ -1775,61 +1726,17 @@ void LatexDocVisitor::startDiaFile(const QCString &fileName, QCString outDir = Config_getString("LATEX_OUTPUT"); writeDiaGraphFromFile(fileName,outDir,baseName,DIA_EPS); - if (hasCaption) - { - m_t << "\n\\begin{DoxyImage}\n"; - } - else - { - m_t << "\n\\begin{DoxyImageNoCaption}\n" - " \\mbox{"; - } - m_t << "\\includegraphics"; - if (!width.isEmpty()) - { - m_t << "[width=" << width << "]"; - } - else if (!height.isEmpty()) - { - m_t << "[height=" << height << "]"; - } - else - { - m_t << "[width=\\textwidth,height=\\textheight/2,keepaspectratio=true]"; - } - m_t << "{" << baseName; - //if (Config_getBool("USE_PDFLATEX")) - //{ - // m_t << ".pdf"; - //} - //else - //{ - // m_t << ".eps"; - //} - m_t << "}"; - - if (hasCaption) - { - m_t << "\n\\caption{"; - } + visitPreStart(m_t,hasCaption, baseName, width, height); } void LatexDocVisitor::endDiaFile(bool hasCaption) { if (m_hide) return; - m_t << "}\n"; // end caption or mbox - if (hasCaption) - { - m_t << "\\end{DoxyImage}\n"; - } - else - { - m_t << "\\end{DoxyImageNoCaption}\n"; - } + visitPostEnd(m_t,hasCaption); } -void LatexDocVisitor::writeDiaFile(const QCString &baseName) +void LatexDocVisitor::writeDiaFile(const QCString &baseName, DocVerbatim *s) { QCString shortName = baseName; int i; @@ -1839,14 +1746,12 @@ void LatexDocVisitor::writeDiaFile(const QCString &baseName) } QCString outDir = Config_getString("LATEX_OUTPUT"); writeDiaGraphFromFile(baseName+".dia",outDir,shortName,DIA_EPS); - m_t << "\n\\begin{DoxyImageNoCaption}" - " \\mbox{\\includegraphics"; - m_t << "{" << shortName << "}"; - m_t << "}\n"; // end mbox - m_t << "\\end{DoxyImageNoCaption}\n"; + visitPreStart(m_t, s->hasCaption(), shortName, s->width(), s->height()); + visitCaption(this, s->m_children); + visitPostEnd(m_t, s->hasCaption()); } -void LatexDocVisitor::writePlantUMLFile(const QCString &baseName) +void LatexDocVisitor::writePlantUMLFile(const QCString &baseName, DocVerbatim *s) { QCString shortName = baseName; int i; @@ -1856,10 +1761,8 @@ void LatexDocVisitor::writePlantUMLFile(const QCString &baseName) } 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"; + visitPreStart(m_t, s->hasCaption(), shortName, s->width(), s->height()); + visitCaption(this, s->m_children); + visitPostEnd(m_t, s->hasCaption()); } diff --git a/src/latexdocvisitor.h b/src/latexdocvisitor.h index 64560b9..0391dcd 100644 --- a/src/latexdocvisitor.h +++ b/src/latexdocvisitor.h @@ -170,13 +170,13 @@ class LatexDocVisitor : public DocVisitor void startMscFile(const QCString &fileName,const QCString &width, const QCString &height, bool hasCaption); void endMscFile(bool hasCaption); - void writeMscFile(const QCString &fileName); + void writeMscFile(const QCString &fileName, DocVerbatim *s); void startDiaFile(const QCString &fileName,const QCString &width, const QCString &height, bool hasCaption); void endDiaFile(bool hasCaption); - void writeDiaFile(const QCString &fileName); - void writePlantUMLFile(const QCString &fileName); + void writeDiaFile(const QCString &fileName, DocVerbatim *s); + void writePlantUMLFile(const QCString &fileName, DocVerbatim *s); void pushEnabled(); void popEnabled(); diff --git a/src/latexgen.cpp b/src/latexgen.cpp index 874b485..244d416 100644 --- a/src/latexgen.cpp +++ b/src/latexgen.cpp @@ -270,7 +270,7 @@ static void writeDefaultHeaderPart1(FTextStream &t) "\\usepackage{fixltx2e}\n" // for \textsubscript "\\usepackage{calc}\n" "\\usepackage{doxygen}\n" - "\\usepackage{graphicx}\n" + "\\usepackage[export]{adjustbox} % also loads graphicx\n" "\\usepackage[utf8]{inputenc}\n" "\\usepackage{makeidx}\n" "\\usepackage{multicol}\n" diff --git a/src/printdocvisitor.h b/src/printdocvisitor.h index 1d384b1..43b6bde 100644 --- a/src/printdocvisitor.h +++ b/src/printdocvisitor.h @@ -483,7 +483,7 @@ class PrintDocVisitor : public DocVisitor case DocImage::Rtf: printf("rtf"); break; case DocImage::DocBook: printf("docbook"); break; } - printf("\" width=%s height=%s>\n",img->width().data(),img->height().data()); + printf("\" %s %s>\n",img->width().data(),img->height().data()); } void visitPost(DocImage *) { diff --git a/src/xmldocvisitor.cpp b/src/xmldocvisitor.cpp index f2da28c..66f455e 100644 --- a/src/xmldocvisitor.cpp +++ b/src/xmldocvisitor.cpp @@ -32,6 +32,71 @@ #include "config.h" #include "htmlentity.h" +static void visitCaption(XmlDocVisitor *parent, QList children) +{ + QListIterator cli(children); + DocNode *n; + for (cli.toFirst();(n=cli.current());++cli) n->accept(parent); +} + +static void visitPreStart(FTextStream &t, const char *cmd, const bool doCaption, XmlDocVisitor *parent, QList children, QCString name, DocImage::Type type, QCString width, QCString height) +{ + QCString tmpStr; + + t << "<" << cmd; + if (type != DocImage::None) + { + t << " type=\""; + switch(type) + { + case DocImage::Html: t << "html"; break; + case DocImage::Latex: t << "latex"; break; + case DocImage::Rtf: t << "rtf"; break; + case DocImage::DocBook: t << "docbook"; break; + } + t << "\""; + } + if (!name.isEmpty()) + { + t << " name=\"" << name << "\""; + } + if (!width.isEmpty()) + { + tmpStr = width; + tmpStr = tmpStr.replace(QRegExp("min *width"),"minwidth"); + tmpStr = tmpStr.replace(QRegExp("max *width"),"maxwidth"); + tmpStr = tmpStr.replace(QRegExp("="),"=\""); + tmpStr = tmpStr.replace(QRegExp(","),"\" ") + "\""; + tmpStr = tmpStr.replace(QRegExp("\"\""),"\""); + tmpStr = tmpStr.replace(QRegExp("\\"),"\\\\"); + t << " " << tmpStr; + } + if (!height.isEmpty()) + { + tmpStr = height; + tmpStr = tmpStr.replace(QRegExp("min *height"),"minheight"); + tmpStr = tmpStr.replace(QRegExp("max *height"),"maxheight"); + tmpStr = tmpStr.replace(QRegExp("="),"=\""); + tmpStr = tmpStr.replace(QRegExp(","),"\" ") + "\""; + tmpStr = tmpStr.replace(QRegExp("\"\""),"\""); + tmpStr = tmpStr.replace(QRegExp("\\"),"\\\\"); + t << " " << tmpStr; + } + + if (doCaption) + { + t << " caption=\""; + visitCaption(parent, children); + t << "\""; + } + t << ">"; +} + +static void visitPostEnd(FTextStream &t, const char *cmd, const bool doCaption) +{ + t << "" << endl; +} + XmlDocVisitor::XmlDocVisitor(FTextStream &t,CodeOutputInterface &ci) : DocVisitor(DocVisitor_XML), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE) { @@ -200,19 +265,19 @@ void XmlDocVisitor::visit(DocVerbatim *s) m_t << ""; break; case DocVerbatim::Dot: - m_t << ""; + visitPreStart(m_t, "dot", s->hasCaption(), this, s->children(), QCString(""), DocImage::None, s->width(), s->height()); filter(s->text()); - m_t << ""; + visitPostEnd(m_t, "dot", s->hasCaption()); break; case DocVerbatim::Msc: - m_t << ""; + visitPreStart(m_t, "msc", s->hasCaption(), this, s->children(), QCString(""), DocImage::None, s->width(), s->height()); filter(s->text()); - m_t << ""; + visitPostEnd(m_t, "msc", s->hasCaption()); break; case DocVerbatim::PlantUML: - m_t << ""; + visitPreStart(m_t, "plantuml", s->hasCaption(), this, s->children(), QCString(""), DocImage::None, s->width(), s->height()); filter(s->text()); - m_t << ""; + visitPostEnd(m_t, "plantuml", s->hasCaption()); break; } } @@ -682,15 +747,6 @@ void XmlDocVisitor::visitPost(DocHtmlHeader *) void XmlDocVisitor::visitPre(DocImage *img) { if (m_hide) return; - m_t << "type()) - { - case DocImage::Html: m_t << "html"; break; - case DocImage::Latex: m_t << "latex"; break; - case DocImage::Rtf: m_t << "rtf"; break; - case DocImage::DocBook: m_t << "docbook"; break; - } - m_t << "\""; QCString baseName=img->name(); int i; @@ -698,20 +754,7 @@ void XmlDocVisitor::visitPre(DocImage *img) { baseName=baseName.right(baseName.length()-i-1); } - m_t << " name=\"" << baseName << "\""; - if (!img->width().isEmpty()) - { - m_t << " width=\""; - filter(img->width()); - m_t << "\""; - } - else if (!img->height().isEmpty()) - { - m_t << " height=\""; - filter(img->height()); - m_t << "\""; - } - m_t << ">"; + visitPreStart(m_t, "image", FALSE, this, img->children(), baseName, img->type(), img->width(), img->height()); // copy the image to the output dir QFile inImage(img->name()); @@ -732,43 +775,43 @@ void XmlDocVisitor::visitPre(DocImage *img) void XmlDocVisitor::visitPost(DocImage *) { if (m_hide) return; - m_t << "" << endl; + visitPostEnd(m_t, "image", FALSE); } void XmlDocVisitor::visitPre(DocDotFile *df) { if (m_hide) return; - m_t << "file() << "\">"; + visitPreStart(m_t, "dotfile", FALSE, this, df->children(), df->file(), DocImage::None, df->width(), df->height()); } void XmlDocVisitor::visitPost(DocDotFile *) { if (m_hide) return; - m_t << "" << endl; + visitPostEnd(m_t, "dotfile", FALSE); } void XmlDocVisitor::visitPre(DocMscFile *df) { if (m_hide) return; - m_t << "file() << "\">"; + visitPreStart(m_t, "mscfile", FALSE, this, df->children(), df->file(), DocImage::None, df->width(), df->height()); } void XmlDocVisitor::visitPost(DocMscFile *) { if (m_hide) return; - m_t << "" << endl; + visitPostEnd(m_t, "mscfile", FALSE); } void XmlDocVisitor::visitPre(DocDiaFile *df) { if (m_hide) return; - m_t << "file() << "\">"; + visitPreStart(m_t, "diafile", FALSE, this, df->children(), df->file(), DocImage::None, df->width(), df->height()); } void XmlDocVisitor::visitPost(DocDiaFile *) { if (m_hide) return; - m_t << "" << endl; + visitPostEnd(m_t, "diafile", FALSE); } void XmlDocVisitor::visitPre(DocLink *lnk) diff --git a/templates/latex/doxygen.sty b/templates/latex/doxygen.sty index c423e12..acd68e4 100644 --- a/templates/latex/doxygen.sty +++ b/templates/latex/doxygen.sty @@ -142,7 +142,9 @@ % Used by @image, @dotfile, @dot ... @enddot, and @msc ... @endmsc % (only if no caption is specified) \newenvironment{DoxyImageNoCaption}{% + \begin{center}% }{% + \end{center}% } % Used by @attention diff --git a/testing/022/indexpage.xml b/testing/022/indexpage.xml index 83ed868..afcf23a 100644 --- a/testing/022/indexpage.xml +++ b/testing/022/indexpage.xml @@ -4,14 +4,15 @@ index My Project - Class relations expressed via an inline dot graph: + Class relations expressed via an inline dot graph: digraph example { node [shape=record, fontname=Helvetica, fontsize=10]; b [ label="class B" URL="\ref B"]; c [ label="class C" URL="\ref C"]; b -> c [ arrowhead="open", style="dashed" ]; } - + + diff --git a/testing/031/indexpage.xml b/testing/031/indexpage.xml index a0297fa..a6ffb36 100644 --- a/testing/031/indexpage.xml +++ b/testing/031/indexpage.xml @@ -6,7 +6,7 @@ Some text. Doxygen logo - More text. +More text. diff --git a/testing/037/class_receiver.xml b/testing/037/class_receiver.xml index eb37d47..2fcde6d 100644 --- a/testing/037/class_receiver.xml +++ b/testing/037/class_receiver.xml @@ -25,11 +25,12 @@ - Receiver class. Can be used to receive and execute commands. After execution of a command, the receiver will send an acknowledgement + Receiver class. Can be used to receive and execute commands. After execution of a command, the receiver will send an acknowledgement Receiver,Sender; Receiver<-Sender [label="Command()", URL="\ref Command()"]; Receiver->Sender [label="Ack()", URL="\ref Sender::Ack()", ID="1"]; - + + diff --git a/testing/037/class_sender.xml b/testing/037/class_sender.xml index 117ed93..b77017a 100644 --- a/testing/037/class_sender.xml +++ b/testing/037/class_sender.xml @@ -25,11 +25,12 @@ - Sender class. Can be used to send a command to the server. The receiver will acknowledge the command by calling Ack(). + Sender class. Can be used to send a command to the server. The receiver will acknowledge the command by calling Ack(). Sender,Receiver; Sender->Receiver [label="Command()", URL="\ref Receiver::Command()"]; Sender<-Receiver [label="Ack()", URL="\ref Ack()", ID="1"]; - + + -- cgit v0.12