00001 /****************************************************************************** 00002 * 00003 * $Id: $ 00004 * 00005 * 00006 * Copyright (C) 1997-2008 by Dimitri van Heesch. 00007 * 00008 * Permission to use, copy, modify, and distribute this software and its 00009 * documentation under the terms of the GNU General Public License is hereby 00010 * granted. No representations are made about the suitability of this software 00011 * for any purpose. It is provided "as is" without express or implied warranty. 00012 * See the GNU General Public License for more details. 00013 * 00014 * Documents produced by Doxygen are derivative works derived from the 00015 * input used in their production; they are not affected by this license. 00016 * 00017 */ 00018 #include <qfileinfo.h> 00019 #include "latexdocvisitor.h" 00020 #include "docparser.h" 00021 #include "language.h" 00022 #include "doxygen.h" 00023 #include "outputgen.h" 00024 #include "dot.h" 00025 #include "util.h" 00026 #include "message.h" 00027 #include "parserintf.h" 00028 #include "msc.h" 00029 00030 static QString escapeLabelName(const char *s) 00031 { 00032 QString result; 00033 const char *p=s; 00034 char c; 00035 while ((c=*p++)) 00036 { 00037 switch (c) 00038 { 00039 case '%': result+="\\%"; break; 00040 case '|': result+="\\texttt{\"|}"; break; 00041 case '!': result+="\"!"; break; 00042 default: result+=c; 00043 } 00044 } 00045 return result; 00046 } 00047 00048 const int maxLevels=5; 00049 static const char *secLabels[maxLevels] = 00050 { "section","subsection","subsubsection","paragraph","subparagraph" }; 00051 00052 static const char *getSectionName(int level) 00053 { 00054 int l = level; 00055 if (Config_getBool("COMPACT_LATEX")) l++; 00056 if (Doxygen::insideMainPage) l--; 00057 return secLabels[QMIN(maxLevels-1,l)]; 00058 } 00059 00060 QString LatexDocVisitor::escapeMakeIndexChars(const char *s) 00061 { 00062 QString result; 00063 const char *p=s; 00064 char str[2]; str[1]=0; 00065 char c; 00066 while ((c=*p++)) 00067 { 00068 switch (c) 00069 { 00070 case '!': m_t << "\"!"; break; 00071 case '"': m_t << "\"\""; break; 00072 case '@': m_t << "\"@"; break; 00073 case '|': m_t << "\\texttt{\"|}"; break; 00074 case '[': m_t << "["; break; 00075 case ']': m_t << "]"; break; 00076 default: str[0]=c; filter(str); break; 00077 } 00078 } 00079 return result; 00080 } 00081 00082 00083 LatexDocVisitor::LatexDocVisitor(QTextStream &t,CodeOutputInterface &ci, 00084 const char *langExt,bool insideTabbing) 00085 : DocVisitor(DocVisitor_Latex), m_t(t), m_ci(ci), m_insidePre(FALSE), 00086 m_insideItem(FALSE), m_hide(FALSE), m_insideTabbing(insideTabbing), 00087 m_langExt(langExt) 00088 { 00089 } 00090 00091 //-------------------------------------- 00092 // visitor functions for leaf nodes 00093 //-------------------------------------- 00094 00095 void LatexDocVisitor::visit(DocWord *w) 00096 { 00097 if (m_hide) return; 00098 filter(w->word()); 00099 } 00100 00101 void LatexDocVisitor::visit(DocLinkedWord *w) 00102 { 00103 if (m_hide) return; 00104 startLink(w->ref(),w->file(),w->anchor()); 00105 filter(w->word()); 00106 endLink(w->ref(),w->file(),w->anchor()); 00107 } 00108 00109 void LatexDocVisitor::visit(DocWhiteSpace *w) 00110 { 00111 if (m_hide) return; 00112 if (m_insidePre) 00113 { 00114 m_t << w->chars(); 00115 } 00116 else 00117 { 00118 m_t << " "; 00119 } 00120 } 00121 00122 void LatexDocVisitor::visit(DocSymbol *s) 00123 { 00124 if (m_hide) return; 00125 switch(s->symbol()) 00126 { 00127 case DocSymbol::BSlash: m_t << "$\\backslash$"; break; 00128 case DocSymbol::At: m_t << "@"; break; 00129 case DocSymbol::Less: if (m_insidePre) m_t << "<"; else m_t << "$<$"; 00130 break; 00131 case DocSymbol::Greater: if (m_insidePre) m_t << ">"; else m_t << "$>$"; break; 00132 case DocSymbol::Amp: m_t << "\\&"; break; 00133 case DocSymbol::Dollar: m_t << "\\$"; break; 00134 case DocSymbol::Hash: m_t << "\\#"; break; 00135 case DocSymbol::Percent: m_t << "\\%"; break; 00136 case DocSymbol::Copy: m_t << "\\copyright"; break; 00137 case DocSymbol::Tm: m_t << "\\texttrademark"; break; 00138 case DocSymbol::Reg: m_t << "\\textregistered"; break; 00139 case DocSymbol::Apos: m_t << "'"; break; 00140 case DocSymbol::Quot: m_t << "\""; break; 00141 case DocSymbol::Lsquo: m_t << "`"; break; 00142 case DocSymbol::Rsquo: m_t << "'"; break; 00143 case DocSymbol::Ldquo: m_t << "``"; break; 00144 case DocSymbol::Rdquo: m_t << "''"; break; 00145 case DocSymbol::Ndash: m_t << "--"; break; 00146 case DocSymbol::Mdash: m_t << "---"; break; 00147 case DocSymbol::Uml: 00148 if (s->letter()=='i') 00149 m_t << "\\\"{\\i}"; 00150 else 00151 m_t << "\\\"{" << s->letter() << "}"; 00152 break; 00153 case DocSymbol::Acute: 00154 if (s->letter()=='i') 00155 m_t << "\\'{\\i}"; 00156 else 00157 m_t << "\\'{" << s->letter() << "}"; 00158 break; 00159 case DocSymbol::Grave: 00160 if (s->letter()=='i') 00161 m_t << "\\`{\\i}"; 00162 else 00163 m_t << "\\`{" << s->letter() << "}"; 00164 break; 00165 case DocSymbol::Circ: 00166 if (s->letter()=='i') 00167 m_t << "\\^{\\i}"; 00168 else 00169 m_t << "\\^{" << s->letter() << "}"; 00170 break; 00171 case DocSymbol::Slash: if (tolower(s->letter())=='o') 00172 m_t << "\\" << s->letter(); 00173 else 00174 m_t << s->letter(); 00175 break; 00176 case DocSymbol::Tilde: m_t << "\\~{" << s->letter() << "}"; break; 00177 case DocSymbol::Szlig: m_t << "{\\ss}"; break; 00178 case DocSymbol::Cedil: m_t << "\\c{" << s->letter() << "}"; break; 00179 case DocSymbol::Ring: m_t << "\\" << s->letter() << s->letter(); break; 00180 case DocSymbol::Nbsp: m_t << "~"; break; 00181 default: 00182 err("Error: unknown symbol found\n"); 00183 } 00184 } 00185 00186 void LatexDocVisitor::visit(DocURL *u) 00187 { 00188 if (m_hide) return; 00189 if (Config_getBool("PDF_HYPERLINKS")) 00190 { 00191 m_t << "\\href{"; 00192 if (u->isEmail()) m_t << "mailto:"; 00193 m_t << u->url() << "}"; 00194 } 00195 m_t << "{\\tt "; 00196 filter(u->url()); 00197 m_t << "}"; 00198 } 00199 00200 void LatexDocVisitor::visit(DocLineBreak *) 00201 { 00202 if (m_hide) return; 00203 m_t << "\\par\n"; 00204 } 00205 00206 void LatexDocVisitor::visit(DocHorRuler *) 00207 { 00208 if (m_hide) return; 00209 m_t << "\n\n"; 00210 } 00211 00212 void LatexDocVisitor::visit(DocStyleChange *s) 00213 { 00214 if (m_hide) return; 00215 switch (s->style()) 00216 { 00217 case DocStyleChange::Bold: 00218 if (s->enable()) m_t << "{\\bf "; else m_t << "}"; 00219 break; 00220 case DocStyleChange::Italic: 00221 if (s->enable()) m_t << "{\\em "; else m_t << "\\/}"; 00222 break; 00223 case DocStyleChange::Code: 00224 if (s->enable()) m_t << "{\\tt "; else m_t << "}"; 00225 break; 00226 case DocStyleChange::Subscript: 00227 if (s->enable()) m_t << "$_{\\mbox{"; else m_t << "}}$ "; 00228 break; 00229 case DocStyleChange::Superscript: 00230 if (s->enable()) m_t << "$^{\\mbox{"; else m_t << "}}$ "; 00231 break; 00232 case DocStyleChange::Center: 00233 if (s->enable()) m_t << "\\begin{center}"; else m_t << "\\end{center} "; 00234 break; 00235 case DocStyleChange::Small: 00236 if (s->enable()) m_t << "\n\\footnotesize "; else m_t << "\n\\normalsize "; 00237 break; 00238 case DocStyleChange::Preformatted: 00239 if (s->enable()) 00240 { 00241 m_t << "\\small\\begin{alltt}"; 00242 m_insidePre=TRUE; 00243 } 00244 else 00245 { 00246 m_insidePre=FALSE; 00247 m_t << "\\end{alltt}\n\\normalsize " << endl; 00248 } 00249 break; 00250 case DocStyleChange::Div: /* HTML only */ break; 00251 case DocStyleChange::Span: /* HTML only */ break; 00252 } 00253 } 00254 00255 void LatexDocVisitor::visit(DocVerbatim *s) 00256 { 00257 if (m_hide) return; 00258 switch(s->type()) 00259 { 00260 case DocVerbatim::Code: 00261 m_t << "\n\n\\begin{Code}\\begin{verbatim}"; 00262 Doxygen::parserManager->getParser(m_langExt) 00263 ->parseCode(m_ci,s->context(),s->text().latin1(), 00264 s->isExample(),s->exampleFile()); 00265 m_t << "\\end{verbatim}\n\\end{Code}\n" << endl; 00266 break; 00267 case DocVerbatim::Verbatim: 00268 m_t << "\n\n\\footnotesize\\begin{verbatim}"; 00269 m_t << s->text(); 00270 m_t << "\\end{verbatim}\n\\normalsize" << endl; 00271 break; 00272 case DocVerbatim::HtmlOnly: 00273 case DocVerbatim::XmlOnly: 00274 case DocVerbatim::ManOnly: 00275 /* nothing */ 00276 break; 00277 case DocVerbatim::LatexOnly: 00278 m_t << s->text(); 00279 break; 00280 case DocVerbatim::Dot: 00281 { 00282 static int dotindex = 1; 00283 QCString fileName(4096); 00284 00285 fileName.sprintf("%s%d%s", 00286 (Config_getString("LATEX_OUTPUT")+"/inline_dotgraph_").data(), 00287 dotindex++, 00288 ".dot" 00289 ); 00290 QFile file(fileName); 00291 if (!file.open(IO_WriteOnly)) 00292 { 00293 err("Could not open file %s for writing\n",fileName.data()); 00294 } 00295 file.writeBlock( s->text(), s->text().length() ); 00296 file.close(); 00297 00298 m_t << "\\begin{center}\n"; 00299 startDotFile(fileName,"","",FALSE); 00300 endDotFile(FALSE); 00301 m_t << "\\end{center}\n"; 00302 00303 if (Config_getBool("DOT_CLEANUP")) file.remove(); 00304 } 00305 break; 00306 case DocVerbatim::Msc: 00307 { 00308 static int mscindex = 1; 00309 QCString baseName(4096); 00310 00311 baseName.sprintf("%s%d", 00312 (Config_getString("LATEX_OUTPUT")+"/inline_mscgraph_").data(), 00313 mscindex++ 00314 ); 00315 QFile file(baseName+".msc"); 00316 if (!file.open(IO_WriteOnly)) 00317 { 00318 err("Could not open file %s.msc for writing\n",baseName.data()); 00319 } 00320 QCString text = "msc {"; 00321 text+=s->text(); 00322 text+="}"; 00323 file.writeBlock( text, text.length() ); 00324 file.close(); 00325 00326 m_t << "\\begin{center}\n"; 00327 writeMscFile(baseName); 00328 m_t << "\\end{center}\n"; 00329 00330 if (Config_getBool("DOT_CLEANUP")) file.remove(); 00331 } 00332 break; 00333 } 00334 } 00335 00336 void LatexDocVisitor::visit(DocAnchor *anc) 00337 { 00338 if (m_hide) return; 00339 m_t << "\\label{" << anc->file() << "_" << anc->anchor() << "}" << endl; 00340 if (!anc->file().isEmpty() && Config_getBool("PDF_HYPERLINKS")) 00341 { 00342 m_t << "\\hypertarget{" << anc->file() << "_" << anc->anchor() 00343 << "}{}" << endl; 00344 } 00345 } 00346 00347 void LatexDocVisitor::visit(DocInclude *inc) 00348 { 00349 if (m_hide) return; 00350 switch(inc->type()) 00351 { 00352 case DocInclude::IncWithLines: 00353 { 00354 m_t << "\n\n\\begin{DocInclude}\\begin{verbatim}"; 00355 QFileInfo cfi( inc->file() ); 00356 FileDef fd( cfi.dirPath(), cfi.fileName() ); 00357 Doxygen::parserManager->getParser(inc->extension()) 00358 ->parseCode(m_ci,inc->context(), 00359 inc->text().latin1(), 00360 inc->isExample(), 00361 inc->exampleFile(), &fd); 00362 m_t << "\\end{verbatim}\n\\end{DocInclude}" << endl; 00363 } 00364 break; 00365 case DocInclude::Include: 00366 m_t << "\n\n\\begin{DocInclude}\\begin{verbatim}"; 00367 Doxygen::parserManager->getParser(inc->extension()) 00368 ->parseCode(m_ci,inc->context(), 00369 inc->text().latin1(),inc->isExample(), 00370 inc->exampleFile()); 00371 m_t << "\\end{verbatim}\n\\end{DocInclude}" << endl; 00372 break; 00373 case DocInclude::DontInclude: 00374 break; 00375 case DocInclude::HtmlInclude: 00376 break; 00377 case DocInclude::VerbInclude: 00378 m_t << "\n\n\\begin{VerbInclude}\\begin{verbatim}"; 00379 m_t << inc->text(); 00380 m_t << "\\end{verbatim}\n\\end{VerbInclude}" << endl; 00381 break; 00382 } 00383 } 00384 00385 void LatexDocVisitor::visit(DocIncOperator *op) 00386 { 00387 //printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n", 00388 // op->type(),op->isFirst(),op->isLast(),op->text().data()); 00389 if (op->isFirst()) 00390 { 00391 if (!m_hide) m_t << "\n\n\\begin{DocInclude}\\begin{verbatim}"; 00392 pushEnabled(); 00393 m_hide = TRUE; 00394 } 00395 if (op->type()!=DocIncOperator::Skip) 00396 { 00397 popEnabled(); 00398 if (!m_hide) 00399 { 00400 Doxygen::parserManager->getParser(m_langExt) 00401 ->parseCode(m_ci,op->context(),op->text().latin1(), 00402 op->isExample(),op->exampleFile()); 00403 } 00404 pushEnabled(); 00405 m_hide=TRUE; 00406 } 00407 if (op->isLast()) 00408 { 00409 popEnabled(); 00410 if (!m_hide) m_t << "\\end{verbatim}\n\\end{DocInclude}" << endl; 00411 } 00412 else 00413 { 00414 if (!m_hide) m_t << endl; 00415 } 00416 } 00417 00418 void LatexDocVisitor::visit(DocFormula *f) 00419 { 00420 if (m_hide) return; 00421 m_t << f->text(); 00422 } 00423 00424 void LatexDocVisitor::visit(DocIndexEntry *i) 00425 { 00426 if (m_hide) return; 00427 m_t << "\\index{" << escapeLabelName(i->entry()) << "@{"; 00428 escapeMakeIndexChars(i->entry()); 00429 m_t << "}}"; 00430 } 00431 00432 //-------------------------------------- 00433 // visitor functions for compound nodes 00434 //-------------------------------------- 00435 00436 void LatexDocVisitor::visitPre(DocAutoList *l) 00437 { 00438 if (m_hide) return; 00439 if (l->isEnumList()) 00440 { 00441 m_t << "\\begin{enumerate}" << endl; 00442 } 00443 else 00444 { 00445 m_t << "\\begin{itemize}" << endl; 00446 } 00447 } 00448 00449 void LatexDocVisitor::visitPost(DocAutoList *l) 00450 { 00451 if (m_hide) return; 00452 if (l->isEnumList()) 00453 { 00454 m_t << "\\end{enumerate}" << endl; 00455 } 00456 else 00457 { 00458 m_t << "\\end{itemize}" << endl; 00459 } 00460 } 00461 00462 void LatexDocVisitor::visitPre(DocAutoListItem *) 00463 { 00464 if (m_hide) return; 00465 m_t << "\\item "; 00466 } 00467 00468 void LatexDocVisitor::visitPost(DocAutoListItem *) 00469 { 00470 } 00471 00472 void LatexDocVisitor::visitPre(DocPara *) 00473 { 00474 } 00475 00476 void LatexDocVisitor::visitPost(DocPara *p) 00477 { 00478 if (m_hide) return; 00479 if (!p->isLast() && // omit <p> for last paragraph 00480 !(p->parent() && // and for parameter sections 00481 p->parent()->kind()==DocNode::Kind_ParamSect 00482 ) 00483 ) m_t << endl << endl; 00484 } 00485 00486 void LatexDocVisitor::visitPre(DocRoot *) 00487 { 00488 } 00489 00490 void LatexDocVisitor::visitPost(DocRoot *) 00491 { 00492 } 00493 00494 void LatexDocVisitor::visitPre(DocSimpleSect *s) 00495 { 00496 if (m_hide) return; 00497 m_t << "\\begin{Desc}\n\\item["; 00498 switch(s->type()) 00499 { 00500 case DocSimpleSect::See: 00501 filter(theTranslator->trSeeAlso()); break; 00502 case DocSimpleSect::Return: 00503 filter(theTranslator->trReturns()); break; 00504 case DocSimpleSect::Author: 00505 filter(theTranslator->trAuthor(TRUE,TRUE)); break; 00506 case DocSimpleSect::Authors: 00507 filter(theTranslator->trAuthor(TRUE,FALSE)); break; 00508 case DocSimpleSect::Version: 00509 filter(theTranslator->trVersion()); break; 00510 case DocSimpleSect::Since: 00511 filter(theTranslator->trSince()); break; 00512 case DocSimpleSect::Date: 00513 filter(theTranslator->trDate()); break; 00514 case DocSimpleSect::Note: 00515 filter(theTranslator->trNote()); break; 00516 case DocSimpleSect::Warning: 00517 filter(theTranslator->trWarning()); break; 00518 case DocSimpleSect::Pre: 00519 filter(theTranslator->trPrecondition()); break; 00520 case DocSimpleSect::Post: 00521 filter(theTranslator->trPostcondition()); break; 00522 case DocSimpleSect::Invar: 00523 filter(theTranslator->trInvariant()); break; 00524 case DocSimpleSect::Remark: 00525 filter(theTranslator->trRemarks()); break; 00526 case DocSimpleSect::Attention: 00527 filter(theTranslator->trAttention()); break; 00528 case DocSimpleSect::User: break; 00529 case DocSimpleSect::Rcs: break; 00530 case DocSimpleSect::Unknown: break; 00531 } 00532 00533 // special case 1: user defined title 00534 if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs) 00535 { 00536 m_t << ":]"; 00537 } 00538 else 00539 { 00540 m_insideItem=TRUE; 00541 } 00542 } 00543 00544 void LatexDocVisitor::visitPost(DocSimpleSect *) 00545 { 00546 if (m_hide) return; 00547 m_t << "\\end{Desc}" << endl; 00548 } 00549 00550 void LatexDocVisitor::visitPre(DocTitle *) 00551 { 00552 } 00553 00554 void LatexDocVisitor::visitPost(DocTitle *) 00555 { 00556 if (m_hide) return; 00557 m_insideItem=FALSE; 00558 m_t << "]"; 00559 } 00560 00561 void LatexDocVisitor::visitPre(DocSimpleList *) 00562 { 00563 if (m_hide) return; 00564 m_t << "\\begin{itemize}" << endl; 00565 } 00566 00567 void LatexDocVisitor::visitPost(DocSimpleList *) 00568 { 00569 if (m_hide) return; 00570 m_t << "\\end{itemize}" << endl; 00571 } 00572 00573 void LatexDocVisitor::visitPre(DocSimpleListItem *) 00574 { 00575 if (m_hide) return; 00576 m_t << "\\item "; 00577 } 00578 00579 void LatexDocVisitor::visitPost(DocSimpleListItem *) 00580 { 00581 } 00582 00583 void LatexDocVisitor::visitPre(DocSection *s) 00584 { 00585 if (m_hide) return; 00586 if (Config_getBool("PDF_HYPERLINKS")) 00587 { 00588 m_t << "\\hypertarget{" << s->file() << "_" << s->anchor() << "}{}"; 00589 } 00590 m_t << "\\" << getSectionName(s->level()) << "{"; 00591 filter(convertCharEntitiesToUTF8(s->title().data())); 00592 m_t << "}\\label{" << s->file() << "_" << s->anchor() << "}" << endl; 00593 } 00594 00595 void LatexDocVisitor::visitPost(DocSection *) 00596 { 00597 } 00598 00599 void LatexDocVisitor::visitPre(DocHtmlList *s) 00600 { 00601 if (m_hide) return; 00602 if (s->type()==DocHtmlList::Ordered) 00603 m_t << "\\begin{enumerate}" << endl; 00604 else 00605 m_t << "\\begin{itemize}" << endl; 00606 } 00607 00608 void LatexDocVisitor::visitPost(DocHtmlList *s) 00609 { 00610 if (m_hide) return; 00611 if (s->type()==DocHtmlList::Ordered) 00612 m_t << "\\end{enumerate}" << endl; 00613 else 00614 m_t << "\\end{itemize}" << endl; 00615 } 00616 00617 void LatexDocVisitor::visitPre(DocHtmlListItem *) 00618 { 00619 if (m_hide) return; 00620 m_t << "\\item "; 00621 } 00622 00623 void LatexDocVisitor::visitPost(DocHtmlListItem *) 00624 { 00625 } 00626 00627 //void LatexDocVisitor::visitPre(DocHtmlPre *) 00628 //{ 00629 // m_t << "\\small\\begin{alltt}"; 00630 // m_insidePre=TRUE; 00631 //} 00632 00633 //void LatexDocVisitor::visitPost(DocHtmlPre *) 00634 //{ 00635 // m_insidePre=FALSE; 00636 // m_t << "\\end{alltt}\\normalsize " << endl; 00637 //} 00638 00639 void LatexDocVisitor::visitPre(DocHtmlDescList *) 00640 { 00641 if (m_hide) return; 00642 m_t << "\\begin{description}" << endl; 00643 } 00644 00645 void LatexDocVisitor::visitPost(DocHtmlDescList *) 00646 { 00647 if (m_hide) return; 00648 m_t << "\\end{description}" << endl; 00649 } 00650 00651 void LatexDocVisitor::visitPre(DocHtmlDescTitle *) 00652 { 00653 if (m_hide) return; 00654 m_t << "\\item["; 00655 m_insideItem=TRUE; 00656 } 00657 00658 void LatexDocVisitor::visitPost(DocHtmlDescTitle *) 00659 { 00660 if (m_hide) return; 00661 m_insideItem=FALSE; 00662 m_t << "]"; 00663 } 00664 00665 void LatexDocVisitor::visitPre(DocHtmlDescData *) 00666 { 00667 } 00668 00669 void LatexDocVisitor::visitPost(DocHtmlDescData *) 00670 { 00671 } 00672 00673 void LatexDocVisitor::visitPre(DocHtmlTable *t) 00674 { 00675 if (m_hide) return; 00676 if (t->hasCaption()) 00677 { 00678 m_t << "\\begin{table}[h]"; 00679 } 00680 m_t << "\\begin{TabularC}{" << t->numCols() << "}\n\\hline\n"; 00681 } 00682 00683 void LatexDocVisitor::visitPost(DocHtmlTable *t) 00684 { 00685 if (m_hide) return; 00686 if (t->hasCaption()) 00687 { 00688 m_t << "\\end{table}\n"; 00689 } 00690 else 00691 { 00692 m_t << "\\end{TabularC}\n"; 00693 } 00694 } 00695 00696 void LatexDocVisitor::visitPre(DocHtmlCaption *) 00697 { 00698 if (m_hide) return; 00699 m_t << "\\end{TabularC}\n\\centering\n\\caption{"; 00700 } 00701 00702 void LatexDocVisitor::visitPost(DocHtmlCaption *) 00703 { 00704 if (m_hide) return; 00705 m_t << "}\n"; 00706 } 00707 00708 void LatexDocVisitor::visitPre(DocHtmlRow *) 00709 { 00710 } 00711 00712 void LatexDocVisitor::visitPost(DocHtmlRow *) 00713 { 00714 if (m_hide) return; 00715 m_t << "\\\\\\hline\n"; 00716 } 00717 00718 void LatexDocVisitor::visitPre(DocHtmlCell *) 00719 { 00720 } 00721 00722 void LatexDocVisitor::visitPost(DocHtmlCell *c) 00723 { 00724 if (m_hide) return; 00725 if (!c->isLast()) m_t << "&"; 00726 } 00727 00728 void LatexDocVisitor::visitPre(DocInternal *) 00729 { 00730 if (m_hide) return; 00731 m_t << "\\begin{Desc}" << endl 00732 << "\\item["; filter(theTranslator->trForInternalUseOnly()); m_t << "]" << endl; 00733 } 00734 00735 void LatexDocVisitor::visitPost(DocInternal *) 00736 { 00737 if (m_hide) return; 00738 m_t << "\\end{Desc}" << endl; 00739 } 00740 00741 void LatexDocVisitor::visitPre(DocHRef *href) 00742 { 00743 if (m_hide) return; 00744 if (Config_getBool("PDF_HYPERLINKS")) 00745 { 00746 m_t << "\\href{"; 00747 m_t << href->url(); 00748 m_t << "}"; 00749 } 00750 m_t << "{\\tt "; 00751 } 00752 00753 void LatexDocVisitor::visitPost(DocHRef *) 00754 { 00755 if (m_hide) return; 00756 m_t << "}"; 00757 } 00758 00759 void LatexDocVisitor::visitPre(DocHtmlHeader *header) 00760 { 00761 if (m_hide) return; 00762 m_t << "\\" << getSectionName(header->level()) << "*{"; 00763 } 00764 00765 void LatexDocVisitor::visitPost(DocHtmlHeader *) 00766 { 00767 if (m_hide) return; 00768 m_t << "}"; 00769 } 00770 00771 void LatexDocVisitor::visitPre(DocImage *img) 00772 { 00773 if (img->type()==DocImage::Latex) 00774 { 00775 if (m_hide) return; 00776 if (img->hasCaption()) 00777 { 00778 m_t << "\\begin{Image}" << endl; 00779 m_t << "\\begin{center}" << endl; 00780 } 00781 else 00782 { 00783 m_t << "\\begin{ImageNoCaption}\\mbox{"; 00784 } 00785 QString gfxName = img->name(); 00786 if (gfxName.right(4)==".eps" || gfxName.right(4)==".pdf") 00787 { 00788 gfxName=gfxName.left(gfxName.length()-4); 00789 } 00790 m_t << "\\includegraphics"; 00791 if (!img->width().isEmpty()) 00792 { 00793 m_t << "[width=" << img->width() << "]"; 00794 } 00795 else if (!img->height().isEmpty()) 00796 { 00797 m_t << "[height=" << img->height() << "]"; 00798 } 00799 m_t << "{" << gfxName << "}"; 00800 if (img->hasCaption()) 00801 { 00802 m_t << "\\caption{"; 00803 } 00804 } 00805 else // other format -> skip 00806 { 00807 pushEnabled(); 00808 m_hide=TRUE; 00809 } 00810 } 00811 00812 void LatexDocVisitor::visitPost(DocImage *img) 00813 { 00814 if (img->type()==DocImage::Latex) 00815 { 00816 if (m_hide) return; 00817 m_t << "}" << endl; // end mbox or caption 00818 if (img->hasCaption()) 00819 { 00820 m_t << "\\end{center}" << endl; 00821 m_t << "\\end{Image}" << endl; 00822 } 00823 else{ 00824 m_t << "\\end{ImageNoCaption}" << endl; 00825 } 00826 } 00827 else // other format 00828 { 00829 popEnabled(); 00830 } 00831 } 00832 00833 void LatexDocVisitor::visitPre(DocDotFile *df) 00834 { 00835 if (m_hide) return; 00836 startDotFile(df->file(),df->width(),df->height(),df->hasCaption()); 00837 } 00838 00839 void LatexDocVisitor::visitPost(DocDotFile *df) 00840 { 00841 if (m_hide) return; 00842 endDotFile(df->hasCaption()); 00843 } 00844 00845 void LatexDocVisitor::visitPre(DocLink *lnk) 00846 { 00847 if (m_hide) return; 00848 startLink(lnk->ref(),lnk->file(),lnk->anchor()); 00849 } 00850 00851 void LatexDocVisitor::visitPost(DocLink *lnk) 00852 { 00853 if (m_hide) return; 00854 endLink(lnk->ref(),lnk->file(),lnk->anchor()); 00855 } 00856 00857 void LatexDocVisitor::visitPre(DocRef *ref) 00858 { 00859 if (m_hide) return; 00860 if (!ref->file().isEmpty()) startLink(ref->ref(),ref->file(),ref->anchor()); 00861 if (!ref->hasLinkText()) filter(ref->targetTitle()); 00862 } 00863 00864 void LatexDocVisitor::visitPost(DocRef *ref) 00865 { 00866 if (m_hide) return; 00867 if (!ref->file().isEmpty()) endLink(ref->ref(),ref->file(),ref->anchor()); 00868 } 00869 00870 void LatexDocVisitor::visitPre(DocSecRefItem *) 00871 { 00872 if (m_hide) return; 00873 m_t << "\\item \\contentsline{section}{"; 00874 } 00875 00876 void LatexDocVisitor::visitPost(DocSecRefItem *ref) 00877 { 00878 if (m_hide) return; 00879 m_t << "}{\\ref{" << ref->file() << "_" << ref->anchor() << "}}{}" << endl; 00880 } 00881 00882 void LatexDocVisitor::visitPre(DocSecRefList *) 00883 { 00884 if (m_hide) return; 00885 m_t << "\\footnotesize" << endl; 00886 m_t << "\\begin{multicols}{2}" << endl; 00887 m_t << "\\begin{CompactList}" << endl; 00888 } 00889 00890 void LatexDocVisitor::visitPost(DocSecRefList *) 00891 { 00892 if (m_hide) return; 00893 m_t << "\\end{CompactList}" << endl; 00894 m_t << "\\end{multicols}" << endl; 00895 m_t << "\\normalsize" << endl; 00896 } 00897 00898 //void LatexDocVisitor::visitPre(DocLanguage *l) 00899 //{ 00900 // QString langId = Config_getEnum("OUTPUT_LANGUAGE"); 00901 // if (l->id().lower()!=langId.lower()) 00902 // { 00903 // pushEnabled(); 00904 // m_hide = TRUE; 00905 // } 00906 //} 00907 // 00908 //void LatexDocVisitor::visitPost(DocLanguage *l) 00909 //{ 00910 // QString langId = Config_getEnum("OUTPUT_LANGUAGE"); 00911 // if (l->id().lower()!=langId.lower()) 00912 // { 00913 // popEnabled(); 00914 // } 00915 //} 00916 00917 void LatexDocVisitor::visitPre(DocParamSect *s) 00918 { 00919 if (m_hide) return; 00920 m_t << "\\begin{Desc}" << endl; 00921 m_t << "\\item["; 00922 switch(s->type()) 00923 { 00924 case DocParamSect::Param: 00925 filter(theTranslator->trParameters()); break; 00926 case DocParamSect::RetVal: 00927 filter(theTranslator->trReturnValues()); break; 00928 case DocParamSect::Exception: 00929 filter(theTranslator->trExceptions()); break; 00930 case DocParamSect::TemplateParam: 00931 /* TODO: add this 00932 filter(theTranslator->trTemplateParam()); break; 00933 */ 00934 filter("Template Parameters"); break; 00935 default: 00936 ASSERT(0); 00937 } 00938 m_t << ":]" << endl; 00939 m_t << "\\begin{description}" << endl; 00940 } 00941 00942 void LatexDocVisitor::visitPost(DocParamSect *) 00943 { 00944 if (m_hide) return; 00945 m_t << "\\end{description}" << endl; 00946 m_t << "\\end{Desc}" << endl; 00947 } 00948 00949 void LatexDocVisitor::visitPre(DocParamList *pl) 00950 { 00951 if (m_hide) return; 00952 m_t << "\\item["; 00953 if (pl->direction()!=DocParamSect::Unspecified) 00954 { 00955 m_t << "\\mbox{"; 00956 if (pl->direction()==DocParamSect::In) 00957 { 00958 m_t << "$\\leftarrow$"; 00959 } 00960 else if (pl->direction()==DocParamSect::Out) 00961 { 00962 m_t << "$\\rightarrow$"; 00963 } 00964 else if (pl->direction()==DocParamSect::InOut) 00965 { 00966 m_t << "$\\leftrightarrow$"; 00967 } 00968 m_t << "} "; 00969 } 00970 m_t << "{\\em "; 00971 //QStrListIterator li(pl->parameters()); 00972 //const char *s; 00973 QListIterator<DocNode> li(pl->parameters()); 00974 DocNode *param; 00975 bool first=TRUE; 00976 for (li.toFirst();(param=li.current());++li) 00977 { 00978 if (!first) m_t << ","; else first=FALSE; 00979 m_insideItem=TRUE; 00980 if (param->kind()==DocNode::Kind_Word) 00981 { 00982 visit((DocWord*)param); 00983 } 00984 else if (param->kind()==DocNode::Kind_LinkedWord) 00985 { 00986 visit((DocLinkedWord*)param); 00987 } 00988 m_insideItem=FALSE; 00989 } 00990 m_t << "}]"; 00991 } 00992 00993 void LatexDocVisitor::visitPost(DocParamList *) 00994 { 00995 } 00996 00997 void LatexDocVisitor::visitPre(DocXRefItem *x) 00998 { 00999 if (m_hide) return; 01000 m_t << "\\begin{Desc}" << endl; 01001 bool anonymousEnum = x->file()=="@"; 01002 m_t << "\\item["; 01003 if (Config_getBool("PDF_HYPERLINKS") && !anonymousEnum) 01004 { 01005 m_t << "\\hyperlink{" << stripPath(x->file()) << "_" << x->anchor() << "}{"; 01006 } 01007 else 01008 { 01009 m_t << "{\\bf "; 01010 } 01011 m_insideItem=TRUE; 01012 filter(x->title()); 01013 m_insideItem=FALSE; 01014 m_t << "}]"; 01015 } 01016 01017 void LatexDocVisitor::visitPost(DocXRefItem *) 01018 { 01019 if (m_hide) return; 01020 m_t << "\\end{Desc}" << endl; 01021 } 01022 01023 void LatexDocVisitor::visitPre(DocInternalRef *ref) 01024 { 01025 if (m_hide) return; 01026 startLink(0,ref->file(),ref->anchor()); 01027 } 01028 01029 void LatexDocVisitor::visitPost(DocInternalRef *ref) 01030 { 01031 if (m_hide) return; 01032 endLink(0,ref->file(),ref->anchor()); 01033 } 01034 01035 void LatexDocVisitor::visitPre(DocCopy *) 01036 { 01037 } 01038 01039 void LatexDocVisitor::visitPost(DocCopy *) 01040 { 01041 } 01042 01043 void LatexDocVisitor::visitPre(DocText *) 01044 { 01045 } 01046 01047 void LatexDocVisitor::visitPost(DocText *) 01048 { 01049 } 01050 01051 void LatexDocVisitor::filter(const char *str) 01052 { 01053 filterLatexString(m_t,str,m_insideTabbing,m_insidePre,m_insideItem); 01054 } 01055 01056 void LatexDocVisitor::startLink(const QString &ref,const QString &file,const QString &anchor) 01057 { 01058 if (ref.isEmpty() && Config_getBool("PDF_HYPERLINKS")) // internal PDF link 01059 { 01060 if (ref.isEmpty()) { 01061 m_t << "\\hyperlink{"; 01062 if (!file.isEmpty()) m_t << stripPath(file); 01063 if (!file.isEmpty() && !anchor.isEmpty()) m_t << "_"; 01064 if (!anchor.isEmpty()) m_t << anchor; 01065 m_t << "}{"; 01066 } 01067 else 01068 { 01069 QCString *dest; 01070 m_t << "\\href{"; 01071 if ((dest=Doxygen::tagDestinationDict[ref])) m_t << *dest << "/"; 01072 if (!file.isEmpty()) m_t << file << Doxygen::htmlFileExtension; 01073 if (!anchor.isEmpty()) m_t << "#" << anchor; 01074 m_t << "}{"; 01075 } 01076 } 01077 else if (ref.isEmpty()) // internal non-PDF link 01078 { 01079 m_t << "\\doxyref{"; 01080 } 01081 else // external link 01082 { 01083 m_t << "{\\bf "; 01084 } 01085 } 01086 01087 void LatexDocVisitor::endLink(const QString &ref,const QString &file,const QString &anchor) 01088 { 01089 m_t << "}"; 01090 if (ref.isEmpty() && !Config_getBool("PDF_HYPERLINKS")) 01091 { 01092 m_t << "{"; 01093 filter(theTranslator->trPageAbbreviation()); 01094 m_t << "}{" << file; 01095 if (!anchor.isEmpty()) m_t << "_" << anchor; 01096 m_t << "}"; 01097 } 01098 } 01099 01100 void LatexDocVisitor::pushEnabled() 01101 { 01102 m_enabled.push(new bool(m_hide)); 01103 } 01104 01105 void LatexDocVisitor::popEnabled() 01106 { 01107 bool *v=m_enabled.pop(); 01108 ASSERT(v!=0); 01109 m_hide = *v; 01110 delete v; 01111 } 01112 01113 void LatexDocVisitor::startDotFile(const QString &fileName, 01114 const QString &width, 01115 const QString &height, 01116 bool hasCaption 01117 ) 01118 { 01119 QString baseName=fileName; 01120 int i; 01121 if ((i=baseName.findRev('/'))!=-1) 01122 { 01123 baseName=baseName.right(baseName.length()-i-1); 01124 } 01125 if (baseName.right(4)==".eps" || baseName.right(4)==".pdf") 01126 { 01127 baseName=baseName.left(baseName.length()-4); 01128 } 01129 if (baseName.right(4)==".dot") 01130 { 01131 baseName=baseName.left(baseName.length()-4); 01132 } 01133 QString outDir = Config_getString("LATEX_OUTPUT"); 01134 QString name = fileName; 01135 writeDotGraphFromFile(name,outDir,baseName,EPS); 01136 if (hasCaption) 01137 { 01138 m_t << "\\begin{Image}" << endl; 01139 m_t << "\\begin{center}" << endl; 01140 } 01141 else 01142 { 01143 m_t << "\\begin{ImageNoCaption}\\mbox{"; 01144 } 01145 m_t << "\\includegraphics"; 01146 if (!width.isEmpty()) 01147 { 01148 m_t << "[width=" << width << "]"; 01149 } 01150 else if (!height.isEmpty()) 01151 { 01152 m_t << "[height=" << height << "]"; 01153 } 01154 m_t << "{" << baseName << "}"; 01155 01156 if (hasCaption) 01157 { 01158 m_t << "\\caption{"; 01159 } 01160 } 01161 01162 void LatexDocVisitor::endDotFile(bool hasCaption) 01163 { 01164 if (m_hide) return; 01165 m_t << "}" << endl; // end caption or mbox 01166 if (hasCaption) 01167 { 01168 m_t << "\\end{center}" << endl; 01169 m_t << "\\end{Image}" << endl; 01170 } 01171 else 01172 { 01173 m_t << "\\end{ImageNoCaption}" << endl; 01174 } 01175 } 01176 01177 void LatexDocVisitor::writeMscFile(const QString &baseName) 01178 { 01179 QString outDir = Config_getString("LATEX_OUTPUT"); 01180 writeMscGraphFromFile(baseName,outDir,baseName,MSC_EPS); 01181 m_t << "\\begin{ImageNoCaption}\\mbox{"; 01182 m_t << "\\includegraphics"; 01183 //if (!width.isEmpty()) 01184 //{ 01185 // m_t << "[width=" << width << "]"; 01186 //} 01187 //else if (!height.isEmpty()) 01188 //{ 01189 // m_t << "[height=" << height << "]"; 01190 //} 01191 m_t << "{" << baseName << "}"; 01192 01193 m_t << "}" << endl; // end mbox 01194 m_t << "\\end{ImageNoCaption}" << endl; 01195 } 01196