1 /******************************************************************************
3 * $Id: htmlgen.cpp,v 1.17 1998/11/28 11:33:19 root Exp $
5 * Copyright (C) 1997-2012 by Dimitri van Heesch.
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation under the terms of the GNU General Public License is hereby
9 * granted. No representations are made about the suitability of this software
10 * for any purpose. It is provided "as is" without express or implied warranty.
11 * See the GNU General Public License for more details.
13 * Documents produced by Doxygen are derivative works derived from the
14 * input used in their production; they are not affected by this license.
18 /* http://www.cubic.org/source/archive/fileform/txt/man/ has some
19 nice introductions to groff and man pages. */
31 #include "docparser.h"
32 #include "mandocvisitor.h"
35 static QCString getExtension()
37 QCString ext = Config_getString("MAN_EXTENSION");
38 if( ext.length() >= 2 &&
41 ext = ext.mid(1, ext.length()-1);
50 ManGenerator::ManGenerator() : OutputGenerator()
52 dir=Config_getString("MAN_OUTPUT")+"/man" + getExtension();
61 ManGenerator::~ManGenerator()
65 //void ManGenerator::append(const OutputGenerator *g)
67 // QCString r=g->getContents();
73 // firstCol = r.at(r.length()-1)=='\n';
75 // firstCol = ((ManGenerator *)g)->firstCol;
76 // col+=((ManGenerator *)g)->col;
77 // inHeader=((ManGenerator *)g)->inHeader;
81 void ManGenerator::init()
83 QCString ext = getExtension();
84 QCString &manOutput = Config_getString("MAN_OUTPUT");
87 if (!d.exists() && !d.mkdir(manOutput))
89 err("Could not create output directory %s\n",manOutput.data());
92 d.setPath(manOutput+"/man"+ext);
93 if (!d.exists() && !d.mkdir(manOutput+"/man"+ext))
95 err("Could not create output directory %s/man%s\n",manOutput.data(),ext.data());
101 static QCString buildFileName(const char *name)
104 if (name==0) return "noname";
133 QCString &manExtension = Config_getString("MAN_EXTENSION");
134 if (convertToQCString(fileName.right(2))!=manExtension)
136 fileName+=manExtension;
142 void ManGenerator::startFile(const char *,const char *manName,const char *)
144 startPlainFile( buildFileName( manName ) );
148 void ManGenerator::endFile()
154 void ManGenerator::endTitleHead(const char *,const char *name)
156 t << ".TH \"" << name << "\" " << getExtension() << " \""
157 << dateToString(FALSE) << "\" \"";
158 if (!Config_getString("PROJECT_NUMBER").isEmpty())
159 t << "Version " << Config_getString("PROJECT_NUMBER") << "\" \"";
160 if (Config_getString("PROJECT_NAME").isEmpty())
163 t << Config_getString("PROJECT_NAME");
164 t << "\" \\\" -*- nroff -*-" << endl;
165 t << ".ad l" << endl;
167 t << ".SH NAME" << endl;
168 t << name << " \\- ";
173 void ManGenerator::newParagraph()
177 if (!firstCol) t << endl;
184 void ManGenerator::startParagraph()
188 if (!firstCol) t << endl;
195 void ManGenerator::endParagraph()
199 void ManGenerator::writeString(const char *text)
204 void ManGenerator::startIndexItem(const char *,const char *)
208 void ManGenerator::endIndexItem(const char *,const char *)
212 void ManGenerator::writeStartAnnoItem(const char *,const char *,
213 const char *,const char *)
217 void ManGenerator::writeObjectLink(const char *,const char *,
218 const char *, const char *name)
220 startBold(); docify(name); endBold();
223 void ManGenerator::writeCodeLink(const char *,const char *,
224 const char *, const char *name,
230 void ManGenerator::startHtmlLink(const char *)
234 void ManGenerator::endHtmlLink()
238 //void ManGenerator::writeMailLink(const char *url)
243 void ManGenerator::startGroupHeader(int)
245 if (!firstCol) t << endl;
251 void ManGenerator::endGroupHeader(int)
253 t << "\"\n.PP " << endl;
259 void ManGenerator::startMemberHeader(const char *)
261 if (!firstCol) t << endl;
265 void ManGenerator::endMemberHeader()
272 void ManGenerator::docify(const char *str)
282 case '.': t << "\\&."; break; // see bug652277
283 case '\\': t << "\\\\"; col++; break;
284 case '\n': t << "\n"; col=0; break;
285 case '\"': c = '\''; // no break!
286 default: t << c; col++; break;
290 //printf("%s",str);fflush(stdout);
295 void ManGenerator::codify(const char *str)
297 //static char spaces[]=" ";
302 int spacesToNextTabStop;
308 case '.': t << "\\&."; break; // see bug652277
309 case '\t': spacesToNextTabStop =
310 Config_getInt("TAB_SIZE") - (col%Config_getInt("TAB_SIZE"));
311 t << Doxygen::spaces.left(spacesToNextTabStop);
312 col+=spacesToNextTabStop;
314 case '\n': t << "\n"; firstCol=TRUE; col=0; break;
315 case '\\': t << "\\"; col++; break;
316 case '\"': c = '\''; // no break!
317 default: t << c; firstCol=FALSE; col++; break;
320 //printf("%s",str);fflush(stdout);
325 void ManGenerator::writeChar(char c)
328 if (firstCol) col=0; else col++;
331 case '\\': t << "\\\\"; break;
332 case '\"': c = '\''; // no break!
333 default: t << c; break;
335 //printf("%c",c);fflush(stdout);
339 void ManGenerator::startDescList(SectionTypes)
342 { t << endl << ".PP" << endl;
343 firstCol=TRUE; paragraph=TRUE;
350 void ManGenerator::startTitle()
352 if (!firstCol) t << endl;
358 void ManGenerator::endTitle()
363 void ManGenerator::startItemListItem()
365 if (!firstCol) t << endl;
372 void ManGenerator::endItemListItem()
376 void ManGenerator::startCodeFragment()
384 void ManGenerator::endCodeFragment()
386 if (!firstCol) t << endl;
393 void ManGenerator::startMemberDoc(const char *,const char *,const char *,const char *,bool)
395 if (!firstCol) t << endl;
401 void ManGenerator::startDoxyAnchor(const char *,const char *manName,
402 const char *, const char *name,
405 // something to be done?
406 if( !Config_getBool("MAN_LINKS") )
411 // the name of the link file is derived from the name of the anchor:
412 // - truncate after an (optional) ::
413 QCString baseName = name;
414 int i=baseName.findRev("::");
415 if (i!=-1) baseName=baseName.right(baseName.length()-i-2);
417 //printf("Converting man link '%s'->'%s'->'%s'\n",
418 // name,baseName.data(),buildFileName(baseName).data());
420 // - remove dangerous characters and append suffix, then add dir prefix
421 QCString fileName=dir+"/"+buildFileName( baseName );
422 QFile linkfile( fileName );
423 // - only create file if it doesn't exist already
424 if ( !linkfile.open( IO_ReadOnly ) )
426 if ( linkfile.open( IO_WriteOnly ) )
428 FTextStream linkstream;
429 linkstream.setDevice(&linkfile);
430 //linkstream.setEncoding(QTextStream::UnicodeUTF8);
431 linkstream << ".so man" << getExtension() << "/" << buildFileName( manName ) << endl;
437 void ManGenerator::endMemberDoc(bool)
442 void ManGenerator::startSubsection()
444 if (!firstCol) t << endl;
450 void ManGenerator::endSubsection()
456 void ManGenerator::startSubsubsection()
458 if (!firstCol) t << endl;
464 void ManGenerator::endSubsubsection()
469 void ManGenerator::writeSynopsis()
471 if (!firstCol) t << endl;
472 t << ".SH SYNOPSIS\n.br\n.PP\n";
477 void ManGenerator::startDescItem()
479 if (!firstCol) t << endl;
484 //void ManGenerator::endDescTitle()
490 void ManGenerator::startDescForItem()
492 if (!firstCol) t << endl;
493 if (!paragraph) t << ".in -1c" << endl;
494 t << ".in +1c" << endl;
500 void ManGenerator::endDescForItem()
504 void ManGenerator::endDescItem()
506 t << "\" 1c" << endl;
510 void ManGenerator::startAnonTypeScope(int indentLevel)
518 void ManGenerator::endAnonTypeScope(int indentLevel)
527 void ManGenerator::startMemberItem(const char *,int,const char *)
529 if (firstCol && !insideTabbing) t << ".in +1c\n";
530 t << "\n.ti -1c\n.RI \"";
534 void ManGenerator::endMemberItem()
539 void ManGenerator::startMemberList()
543 t << "\n.in +1c"; firstCol=FALSE;
547 void ManGenerator::endMemberList()
551 t << "\n.in -1c"; firstCol=FALSE;
555 void ManGenerator::startMemberGroupHeader(bool)
557 t << "\n.PP\n.RI \"\\fB";
560 void ManGenerator::endMemberGroupHeader()
562 t << "\\fP\"\n.br\n";
566 void ManGenerator::startMemberGroupDocs()
570 void ManGenerator::endMemberGroupDocs()
575 void ManGenerator::startMemberGroup()
580 void ManGenerator::endMemberGroup(bool)
586 void ManGenerator::startSection(const char *,const char *,SectionInfo::SectionType type)
592 case SectionInfo::Page: startGroupHeader(FALSE); break;
593 case SectionInfo::Section: startGroupHeader(FALSE); break;
594 case SectionInfo::Subsection: startMemberHeader(0); break;
595 case SectionInfo::Subsubsection: startMemberHeader(0); break;
596 case SectionInfo::Paragraph: startMemberHeader(0); break;
597 default: ASSERT(0); break;
602 void ManGenerator::endSection(const char *,SectionInfo::SectionType type)
608 case SectionInfo::Page: endGroupHeader(0); break;
609 case SectionInfo::Section: endGroupHeader(0); break;
610 case SectionInfo::Subsection: endMemberHeader(); break;
611 case SectionInfo::Subsubsection: endMemberHeader(); break;
612 case SectionInfo::Paragraph: endMemberHeader(); break;
613 default: ASSERT(0); break;
625 void ManGenerator::startSimpleSect(SectionTypes,const char *,
626 const char *,const char *title)
629 { t << endl << ".PP" << endl;
630 firstCol=TRUE; paragraph=TRUE;
640 void ManGenerator::endSimpleSect()
644 void ManGenerator::startParamList(ParamListTypes,const char *title)
647 { t << endl << ".PP" << endl;
648 firstCol=TRUE; paragraph=TRUE;
658 void ManGenerator::endParamList()
662 void ManGenerator::writeDoc(DocNode *n,Definition *ctx,MemberDef *)
664 ManDocVisitor *visitor = new ManDocVisitor(t,*this,ctx?ctx->getDefFileExtension():QCString(""));
671 void ManGenerator::startConstraintList(const char *header)
674 { t << endl << ".PP" << endl;
675 firstCol=TRUE; paragraph=TRUE;
685 void ManGenerator::startConstraintParam()
691 void ManGenerator::endConstraintParam()
698 void ManGenerator::startConstraintType()
703 void ManGenerator::endConstraintType()
708 void ManGenerator::startConstraintDocs()
712 void ManGenerator::endConstraintDocs()
714 t << endl; firstCol=TRUE;
717 void ManGenerator::endConstraintList()
722 void ManGenerator::startInlineHeader()
726 t << endl << ".PP" << endl << ".in -1c" << endl;
731 void ManGenerator::endInlineHeader()
733 t << "\\fP\"" << endl << ".in +1c" << endl;
737 void ManGenerator::startMemberDocSimple()
741 t << endl << ".PP" << endl;
744 docify(theTranslator->trCompoundMembers());
745 t << ":\\fP" << endl;
746 t << ".RS 4" << endl;
749 void ManGenerator::endMemberDocSimple()
751 if (!firstCol) t << endl;
757 void ManGenerator::startInlineMemberType()
761 void ManGenerator::endInlineMemberType()
766 void ManGenerator::startInlineMemberName()
771 void ManGenerator::endInlineMemberName()
776 void ManGenerator::startInlineMemberDoc()
780 void ManGenerator::endInlineMemberDoc()
782 if (!firstCol) t << endl;
788 void ManGenerator::startLabels()
792 void ManGenerator::writeLabel(const char *l,bool isLast)
794 t << "\\fC [" << l << "]\\fP";
795 if (!isLast) t << ", ";
798 void ManGenerator::endLabels()