Orb/Doxygen/src/rtfdocvisitor.cpp
changeset 0 42188c7ea2d9
child 4 468f4c8d3d5b
equal deleted inserted replaced
-1:000000000000 0:42188c7ea2d9
       
     1 /******************************************************************************
       
     2  *
       
     3  * 
       
     4  *
       
     5  *
       
     6  * Copyright (C) 1997-2008 by Dimitri van Heesch.
       
     7  *
       
     8  * Permission to use, copy, modify, and distribute this software and its
       
     9  * documentation under the terms of the GNU General Public License is hereby 
       
    10  * granted. No representations are made about the suitability of this software 
       
    11  * for any purpose. It is provided "as is" without express or implied warranty.
       
    12  * See the GNU General Public License for more details.
       
    13  *
       
    14  * Documents produced by Doxygen are derivative works derived from the
       
    15  * input used in their production; they are not affected by this license.
       
    16  *
       
    17  */
       
    18 
       
    19 #include "rtfdocvisitor.h"
       
    20 #include "docparser.h"
       
    21 #include "language.h"
       
    22 #include "doxygen.h"
       
    23 #include "outputgen.h"
       
    24 #include "dot.h"
       
    25 #include "util.h"
       
    26 #include "rtfstyle.h"
       
    27 #include "message.h"
       
    28 #include <qfileinfo.h> 
       
    29 #include "parserintf.h"
       
    30 #include "msc.h"
       
    31 
       
    32 
       
    33 //#define DBG_RTF(x) m_t << x
       
    34 #define DBG_RTF(x) do {} while(0)
       
    35 
       
    36 RTFDocVisitor::RTFDocVisitor(QTextStream &t,CodeOutputInterface &ci,
       
    37                              const char *langExt) 
       
    38   : DocVisitor(DocVisitor_RTF), m_t(t), m_ci(ci), m_insidePre(FALSE), 
       
    39     m_hide(FALSE), m_indentLevel(0), m_lastIsPara(FALSE), m_langExt(langExt)
       
    40 {
       
    41 }
       
    42 
       
    43 QString RTFDocVisitor::getStyle(const char *name)
       
    44 {
       
    45   QString n;
       
    46   n.sprintf("%s%d",name,m_indentLevel);
       
    47   StyleData *sd = rtf_Style[n];
       
    48   ASSERT(sd!=0);
       
    49   return sd->reference;
       
    50 }
       
    51 
       
    52 void RTFDocVisitor::incIndentLevel()
       
    53 {
       
    54   if (m_indentLevel<rtf_maxIndentLevels-1) m_indentLevel++;
       
    55 }
       
    56 
       
    57 void RTFDocVisitor::decIndentLevel()
       
    58 {
       
    59   if (m_indentLevel>0) m_indentLevel--;
       
    60 }
       
    61 
       
    62   //--------------------------------------
       
    63   // visitor functions for leaf nodes
       
    64   //--------------------------------------
       
    65 
       
    66 void RTFDocVisitor::visit(DocWord *w)
       
    67 {
       
    68   if (m_hide) return;
       
    69   DBG_RTF("{\\comment RTFDocVisitor::visit(DocWord)}\n");
       
    70   filter(w->word());
       
    71   m_lastIsPara=FALSE;
       
    72 }
       
    73 
       
    74 void RTFDocVisitor::visit(DocLinkedWord *w)
       
    75 {
       
    76   if (m_hide) return;
       
    77   DBG_RTF("{\\comment RTFDocVisitor::visit(DocLinkedWord)}\n");
       
    78   startLink(w->ref(),w->file(),w->anchor());
       
    79   filter(w->word());
       
    80   endLink(w->ref());
       
    81   m_lastIsPara=FALSE;
       
    82 }
       
    83 
       
    84 void RTFDocVisitor::visit(DocWhiteSpace *w)
       
    85 {
       
    86   if (m_hide) return;
       
    87   DBG_RTF("{\\comment RTFDocVisitor::visit(DocWhiteSpace)}\n");
       
    88   if (m_insidePre)
       
    89   {
       
    90     m_t << w->chars();
       
    91   }
       
    92   else
       
    93   {
       
    94     m_t << " ";
       
    95   }
       
    96   m_lastIsPara=FALSE;
       
    97 }
       
    98 
       
    99 void RTFDocVisitor::visit(DocSymbol *s)
       
   100 {
       
   101   if (m_hide) return;
       
   102   DBG_RTF("{\\comment RTFDocVisitor::visit(DocSymbol)}\n");
       
   103   switch(s->symbol())
       
   104   {
       
   105     case DocSymbol::BSlash:  m_t << "\\\\"; break;
       
   106     case DocSymbol::At:      m_t << "@"; break;
       
   107     case DocSymbol::Less:    m_t << "<"; break;
       
   108     case DocSymbol::Greater: m_t << ">"; break;
       
   109     case DocSymbol::Amp:     m_t << "&"; break;
       
   110     case DocSymbol::Dollar:  m_t << "$"; break;
       
   111     case DocSymbol::Hash:    m_t << "#"; break;
       
   112     case DocSymbol::Percent: m_t << "%"; break;
       
   113     case DocSymbol::Copy:    m_t << "(C)"; break;
       
   114     case DocSymbol::Tm:      m_t << "(TM)"; break;
       
   115     case DocSymbol::Reg:     m_t << "(R)"; break;
       
   116     case DocSymbol::Apos:    m_t << "'"; break;
       
   117     case DocSymbol::Quot:    m_t << "\""; break;
       
   118     case DocSymbol::Lsquo:   m_t << "`"; break;
       
   119     case DocSymbol::Rsquo:   m_t << "'"; break;
       
   120     case DocSymbol::Ldquo:   m_t << "\""; break;
       
   121     case DocSymbol::Rdquo:   m_t << "\""; break;
       
   122     case DocSymbol::Ndash:   m_t << "-"; break;
       
   123     case DocSymbol::Mdash:   m_t << "--"; break;
       
   124     case DocSymbol::Uml:     switch(s->letter())
       
   125                              {
       
   126                                case 'A' : m_t << '\304'; break;
       
   127                                case 'E' : m_t << '\313'; break;
       
   128                                case 'I' : m_t << '\317'; break;
       
   129                                case 'O' : m_t << '\326'; break;
       
   130                                case 'U' : m_t << '\334'; break;
       
   131                                case 'Y' : m_t << 'Y';    break;
       
   132                                case 'a' : m_t << '\344'; break;
       
   133                                case 'e' : m_t << '\353'; break;
       
   134                                case 'i' : m_t << '\357'; break;
       
   135                                case 'o' : m_t << '\366'; break;
       
   136                                case 'u' : m_t << '\374'; break;
       
   137                                case 'y' : m_t << '\377'; break;
       
   138                                default: m_t << '?'; break;
       
   139                              }
       
   140                              break;
       
   141     case DocSymbol::Acute:   switch(s->letter())
       
   142                              {
       
   143                                case 'A' : m_t << '\301'; break;
       
   144                                case 'E' : m_t << '\311'; break;
       
   145                                case 'I' : m_t << '\315'; break;
       
   146                                case 'O' : m_t << '\323'; break;
       
   147                                case 'U' : m_t << '\332'; break;
       
   148                                case 'Y' : m_t << '\335'; break;
       
   149                                case 'a' : m_t << '\341'; break;
       
   150                                case 'e' : m_t << '\351'; break;
       
   151                                case 'i' : m_t << '\355'; break;
       
   152                                case 'o' : m_t << '\363'; break;
       
   153                                case 'u' : m_t << '\372'; break;
       
   154                                case 'y' : m_t << '\375'; break;
       
   155                                default: m_t << '?'; break;
       
   156                              }
       
   157                              break;
       
   158     case DocSymbol::Grave:   switch(s->letter())
       
   159                              {
       
   160                                case 'A' : m_t << '\300'; break;
       
   161                                case 'E' : m_t << '\310'; break;
       
   162                                case 'I' : m_t << '\314'; break;
       
   163                                case 'O' : m_t << '\322'; break;
       
   164                                case 'U' : m_t << '\331'; break;
       
   165                                case 'a' : m_t << '\340'; break;
       
   166                                case 'e' : m_t << '\350'; break;
       
   167                                case 'i' : m_t << '\354'; break;
       
   168                                case 'o' : m_t << '\362'; break;
       
   169                                case 'u' : m_t << '\371'; break;
       
   170                                default: m_t << '?'; break;
       
   171                              }
       
   172                              break;
       
   173     case DocSymbol::Circ:    switch(s->letter())
       
   174                              {
       
   175                                case 'A' : m_t << '\302'; break;
       
   176                                case 'E' : m_t << '\312'; break;
       
   177                                case 'I' : m_t << '\316'; break;
       
   178                                case 'O' : m_t << '\324'; break;
       
   179                                case 'U' : m_t << '\333'; break;
       
   180                                case 'a' : m_t << '\342'; break;
       
   181                                case 'e' : m_t << '\352'; break;
       
   182                                case 'i' : m_t << '\356'; break;
       
   183                                case 'o' : m_t << '\364'; break;
       
   184                                case 'u' : m_t << '\373'; break;
       
   185                                default: m_t << '?'; break;
       
   186                              }
       
   187                              break;
       
   188     case DocSymbol::Tilde:   switch(s->letter())
       
   189                              {
       
   190                                case 'A' : m_t << '\303'; break;
       
   191                                case 'N' : m_t << '\321'; break;
       
   192                                case 'O' : m_t << '\325'; break;
       
   193                                case 'a' : m_t << '\343'; break;
       
   194                                case 'n' : m_t << '\361'; break;
       
   195                                case 'o' : m_t << '\365'; break;
       
   196                                default: m_t << '?'; break;
       
   197                              }
       
   198                              break;
       
   199     case DocSymbol::Cedil:   switch(s->letter())
       
   200                              {
       
   201                                case 'C' : m_t << '\307'; break;
       
   202                                case 'c' : m_t << '\347'; break;
       
   203                                default: m_t << '?'; break;
       
   204                              }
       
   205                              break;
       
   206     case DocSymbol::Slash:   switch(s->letter())
       
   207                              {
       
   208                                case 'O' : m_t << '\330'; break;
       
   209                                case 'o' : m_t << '\370'; break;
       
   210                                default: m_t << '?'; break;
       
   211                              }
       
   212                              break;
       
   213     case DocSymbol::Ring:    switch(s->letter())
       
   214                              {
       
   215                                case 'A' : m_t << '\305'; break;
       
   216                                case 'a' : m_t << '\345'; break;
       
   217                                default: m_t << '?'; break;
       
   218                              }
       
   219                              break;
       
   220     case DocSymbol::Szlig:   m_t << "\337"; break;
       
   221     case DocSymbol::Nbsp:    m_t << "\\~ "; break;
       
   222     case DocSymbol::Aelig:   m_t << "\346"; break;
       
   223     case DocSymbol::AElig:   m_t << "\306"; break;
       
   224     default:
       
   225                              err("Error: unknown symbol found\n");
       
   226   }
       
   227   m_lastIsPara=FALSE;
       
   228 }
       
   229 
       
   230 void RTFDocVisitor::visit(DocURL *u)
       
   231 {
       
   232   if (m_hide) return;
       
   233   DBG_RTF("{\\comment RTFDocVisitor::visit(DocURL)}\n");
       
   234   if (Config_getBool("RTF_HYPERLINKS"))
       
   235   {
       
   236     m_t << "{\\field "
       
   237              "{\\*\\fldinst "
       
   238                "{ HYPERLINK  \\\\l \"";
       
   239     if (u->isEmail()) m_t << "mailto:";
       
   240     m_t << u->url();
       
   241     m_t <<  "\" }"
       
   242                "{}";
       
   243     m_t <<   "}"
       
   244              "{\\fldrslt "
       
   245                "{\\cs37\\ul\\cf2 ";
       
   246     filter(u->url());
       
   247     m_t <<     "}"
       
   248              "}"
       
   249            "}" << endl;
       
   250   }
       
   251   else
       
   252   {
       
   253     m_t << "{\\f2 ";
       
   254     filter(u->url());
       
   255     m_t << "}";
       
   256   }
       
   257   m_lastIsPara=FALSE;
       
   258 }
       
   259 
       
   260 void RTFDocVisitor::visit(DocLineBreak *)
       
   261 {
       
   262   if (m_hide) return;
       
   263   DBG_RTF("{\\comment RTFDocVisitor::visit(DocLineBreak)}\n");
       
   264   m_t << "\\par";
       
   265   m_lastIsPara=TRUE;
       
   266 }
       
   267 
       
   268 void RTFDocVisitor::visit(DocHorRuler *)
       
   269 {
       
   270   if (m_hide) return;
       
   271   DBG_RTF("{\\comment RTFDocVisitor::visit(DocHorRuler)}\n");
       
   272   m_t << "{\\pard\\widctlpar\\brdrb\\brdrs\\brdrw5\\brsp20 \\adjustright \\par}" << endl;
       
   273   m_lastIsPara=TRUE;
       
   274 }
       
   275 
       
   276 void RTFDocVisitor::visit(DocStyleChange *s)
       
   277 {
       
   278   if (m_hide) return;
       
   279   m_lastIsPara=FALSE;
       
   280   DBG_RTF("{\\comment RTFDocVisitor::visit(DocStyleChange)}\n");
       
   281   switch (s->style())
       
   282   {
       
   283     case DocStyleChange::Bold:
       
   284       if (s->enable()) m_t << "{\\b ";      else m_t << "} ";
       
   285       break;
       
   286     case DocStyleChange::Italic:
       
   287       if (s->enable()) m_t << "{\\i ";     else m_t << "} ";
       
   288       break;
       
   289     case DocStyleChange::Code:
       
   290       if (s->enable()) m_t << "{\\f2 ";   else m_t << "} ";
       
   291       break;
       
   292     case DocStyleChange::Subscript:
       
   293       if (s->enable()) m_t << "{\\sub ";    else m_t << "} ";
       
   294       break;
       
   295     case DocStyleChange::Superscript:
       
   296       if (s->enable()) m_t << "{\\super ";    else m_t << "} ";
       
   297       break;
       
   298     case DocStyleChange::Center:
       
   299       if (s->enable()) m_t << "{\\qc "; else m_t << "} ";
       
   300       break;
       
   301     case DocStyleChange::Small:
       
   302       if (s->enable()) m_t << "{\\sub ";  else m_t << "} ";
       
   303       break;
       
   304     case DocStyleChange::Preformatted:
       
   305       if (s->enable())
       
   306       {
       
   307         m_t << "{" << endl;
       
   308         m_t << "\\par" << endl;
       
   309         m_t << rtf_Style_Reset << getStyle("CodeExample");
       
   310         m_insidePre=TRUE;
       
   311       }
       
   312       else
       
   313       {
       
   314         m_insidePre=FALSE;
       
   315         m_t << "\\par";
       
   316         m_t << "}" << endl;
       
   317       }
       
   318       m_lastIsPara=TRUE;
       
   319       break;
       
   320     case DocStyleChange::Div:  /* HTML only */ break;
       
   321     case DocStyleChange::Span: /* HTML only */ break;
       
   322   }
       
   323 }
       
   324 
       
   325 void RTFDocVisitor::visit(DocVerbatim *s)
       
   326 {
       
   327   if (m_hide) return;
       
   328   DBG_RTF("{\\comment RTFDocVisitor::visit(DocVerbatim)}\n");
       
   329   switch(s->type())
       
   330   {
       
   331     case DocVerbatim::Code: // fall though
       
   332       m_t << "{" << endl;
       
   333       m_t << "\\par" << endl;
       
   334       m_t << rtf_Style_Reset << getStyle("CodeExample");
       
   335       Doxygen::parserManager->getParser(m_langExt)
       
   336                             ->parseCode(m_ci,s->context(),s->text().latin1(),
       
   337                                         s->isExample(),s->exampleFile());
       
   338       //m_t << "\\par" << endl; 
       
   339       m_t << "}" << endl;
       
   340       break;
       
   341     case DocVerbatim::Verbatim: 
       
   342       m_t << "{" << endl;
       
   343       m_t << "\\par" << endl;
       
   344       m_t << rtf_Style_Reset << getStyle("CodeExample");
       
   345       filter(s->text(),TRUE);
       
   346       //m_t << "\\par" << endl; 
       
   347       m_t << "}" << endl;
       
   348       break;
       
   349     case DocVerbatim::HtmlOnly: 
       
   350     case DocVerbatim::LatexOnly: 
       
   351     case DocVerbatim::XmlOnly: 
       
   352     case DocVerbatim::ManOnly: 
       
   353       /* nothing */
       
   354       break;
       
   355     case DocVerbatim::Dot: 
       
   356       {
       
   357         static int dotindex = 1;
       
   358         QCString fileName(4096);
       
   359 
       
   360         fileName.sprintf("%s%d%s", 
       
   361             (Config_getString("RTF_OUTPUT")+"/inline_dotgraph_").data(), 
       
   362             dotindex++,
       
   363             ".dot"
       
   364            );
       
   365         QFile file(fileName);
       
   366         if (!file.open(IO_WriteOnly))
       
   367         {
       
   368           err("Could not open file %s for writing\n",fileName.data());
       
   369         }
       
   370         file.writeBlock( s->text(), s->text().length() );
       
   371         file.close();
       
   372         m_t << "\\par{\\qc "; // center picture
       
   373         writeDotFile(fileName);
       
   374         m_t << "} ";
       
   375         if (Config_getBool("DOT_CLEANUP")) file.remove();
       
   376       }
       
   377       break;
       
   378     case DocVerbatim::Msc: 
       
   379       {
       
   380         static int mscindex = 1;
       
   381         QCString baseName(4096);
       
   382 
       
   383         baseName.sprintf("%s%d", 
       
   384             (Config_getString("RTF_OUTPUT")+"/inline_mscgraph_").data(), 
       
   385             mscindex++
       
   386            );
       
   387         QFile file(baseName+".msc");
       
   388         if (!file.open(IO_WriteOnly))
       
   389         {
       
   390           err("Could not open file %s for writing\n",baseName.data());
       
   391         }
       
   392         QCString text = "msc {";
       
   393         text+=s->text();
       
   394         text+="}";
       
   395         file.writeBlock( text, text.length() );
       
   396         file.close();
       
   397         m_t << "\\par{\\qc "; // center picture
       
   398         writeMscFile(baseName);
       
   399         m_t << "} ";
       
   400         if (Config_getBool("DOT_CLEANUP")) file.remove();
       
   401       }
       
   402       break;
       
   403   }
       
   404   m_lastIsPara=FALSE;
       
   405 }
       
   406 
       
   407 void RTFDocVisitor::visit(DocAnchor *anc)
       
   408 {
       
   409   if (m_hide) return;
       
   410   DBG_RTF("{\\comment RTFDocVisitor::visit(DocAnchor)}\n");
       
   411   QString anchor;
       
   412   if (!anc->file().isEmpty())
       
   413   {
       
   414     anchor+=anc->file();
       
   415   }
       
   416   if (!anc->file().isEmpty() && !anc->anchor().isEmpty())
       
   417   {
       
   418     anchor+="_";
       
   419   }
       
   420   if (!anc->anchor().isEmpty())
       
   421   {
       
   422     anchor+=anc->anchor();
       
   423   }
       
   424   m_t << "{\\bkmkstart " << rtfFormatBmkStr(anchor) << "}" << endl;
       
   425   m_t << "{\\bkmkend " << rtfFormatBmkStr(anchor) << "}" << endl;
       
   426   m_lastIsPara=FALSE;
       
   427 }
       
   428 
       
   429 void RTFDocVisitor::visit(DocInclude *inc)
       
   430 {
       
   431   if (m_hide) return;
       
   432   DBG_RTF("{\\comment RTFDocVisitor::visit(DocInclude)}\n");
       
   433   switch(inc->type())
       
   434   {
       
   435    case DocInclude::IncWithLines:
       
   436       { 
       
   437          m_t << "{" << endl;
       
   438          m_t << "\\par" << endl;
       
   439          m_t << rtf_Style_Reset << getStyle("CodeExample");
       
   440          QFileInfo cfi( inc->file() );
       
   441          FileDef fd( cfi.dirPath(), cfi.fileName() );
       
   442          Doxygen::parserManager->getParser(inc->extension())
       
   443                                ->parseCode(m_ci,inc->context(),
       
   444                                            inc->text().latin1(),
       
   445                                            inc->isExample(),
       
   446                                            inc->exampleFile(), &fd);
       
   447          m_t << "\\par";
       
   448          m_t << "}" << endl;
       
   449       }
       
   450       break;
       
   451    case DocInclude::Include: 
       
   452       m_t << "{" << endl;
       
   453       m_t << "\\par" << endl;
       
   454       m_t << rtf_Style_Reset << getStyle("CodeExample");
       
   455       Doxygen::parserManager->getParser(inc->extension())
       
   456                             ->parseCode(m_ci,inc->context(),
       
   457                                         inc->text().latin1(),inc->isExample(),
       
   458                                         inc->exampleFile());
       
   459       m_t << "\\par";
       
   460       m_t << "}" << endl;
       
   461       break;
       
   462     case DocInclude::DontInclude: 
       
   463       break;
       
   464     case DocInclude::HtmlInclude: 
       
   465       break;
       
   466     case DocInclude::VerbInclude: 
       
   467       m_t << "{" << endl;
       
   468       m_t << "\\par" << endl;
       
   469       m_t << rtf_Style_Reset << getStyle("CodeExample");
       
   470       filter(inc->text());
       
   471       m_t << "\\par";
       
   472       m_t << "}" << endl;
       
   473       break;
       
   474   }
       
   475   m_lastIsPara=TRUE;
       
   476 }
       
   477 
       
   478 void RTFDocVisitor::visit(DocIncOperator *op)
       
   479 {
       
   480   //printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n",
       
   481   //    op->type(),op->isFirst(),op->isLast(),op->text().data());
       
   482   DBG_RTF("{\\comment RTFDocVisitor::visit(DocIncOperator)}\n");
       
   483   if (op->isFirst()) 
       
   484   {
       
   485     if (!m_hide)
       
   486     {
       
   487       m_t << "{" << endl;
       
   488       m_t << "\\par" << endl;
       
   489       m_t << rtf_Style_Reset << getStyle("CodeExample");
       
   490     }
       
   491     pushEnabled();
       
   492     m_hide = TRUE;
       
   493   }
       
   494   if (op->type()!=DocIncOperator::Skip) 
       
   495   {
       
   496     popEnabled();
       
   497     if (!m_hide) 
       
   498     {
       
   499       Doxygen::parserManager->getParser(m_langExt)
       
   500                             ->parseCode(m_ci,op->context(),op->text().latin1(),
       
   501                                         op->isExample(),op->exampleFile());
       
   502     }
       
   503     pushEnabled();
       
   504     m_hide=TRUE;
       
   505   }
       
   506   if (op->isLast())  
       
   507   {
       
   508     popEnabled();
       
   509     if (!m_hide)
       
   510     {
       
   511       m_t << "\\par";
       
   512       m_t << "}" << endl;
       
   513     }
       
   514     m_lastIsPara=TRUE;
       
   515   }
       
   516   else
       
   517   {
       
   518     if (!m_hide) m_t << endl;
       
   519     m_lastIsPara=FALSE;
       
   520   }
       
   521 }
       
   522 
       
   523 void RTFDocVisitor::visit(DocFormula *f)
       
   524 {
       
   525   if (m_hide) return;
       
   526   // TODO: do something sensible here, like including a bitmap
       
   527   DBG_RTF("{\\comment RTFDocVisitor::visit(DocFormula)}\n");
       
   528   m_t << f->text();
       
   529   m_lastIsPara=FALSE;
       
   530 }
       
   531 
       
   532 void RTFDocVisitor::visit(DocIndexEntry *i)
       
   533 {
       
   534   if (m_hide) return;
       
   535   DBG_RTF("{\\comment RTFDocVisitor::visit(DocIndexEntry)}\n");
       
   536   m_t << "{\\xe \\v " << i->entry() << "}" << endl;
       
   537   m_lastIsPara=FALSE;
       
   538 }
       
   539 
       
   540 void RTFDocVisitor::visit(DocSimpleSectSep *)
       
   541 {
       
   542 }
       
   543 
       
   544 //--------------------------------------
       
   545 // visitor functions for compound nodes
       
   546 //--------------------------------------
       
   547 
       
   548 void RTFDocVisitor::visitPre(DocAutoList *l)
       
   549 {
       
   550   if (m_hide) return;
       
   551   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocAutoList)}\n");
       
   552   m_t << "{" << endl;
       
   553   rtf_listItemInfo[m_indentLevel].isEnum = l->isEnumList();
       
   554   rtf_listItemInfo[m_indentLevel].number = 1;
       
   555   m_lastIsPara=FALSE;
       
   556 }
       
   557 
       
   558 void RTFDocVisitor::visitPost(DocAutoList *)
       
   559 {
       
   560   if (m_hide) return;
       
   561   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocAutoList)}\n");
       
   562   m_t << "\\par";
       
   563   m_t << "}" << endl;
       
   564   m_lastIsPara=TRUE;
       
   565 }
       
   566 
       
   567 void RTFDocVisitor::visitPre(DocAutoListItem *)
       
   568 {
       
   569   if (m_hide) return;
       
   570   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocAutoListItem)}\n");
       
   571   if (!m_lastIsPara) m_t << "\\par" << endl;
       
   572   m_t << rtf_Style_Reset;
       
   573   if (rtf_listItemInfo[m_indentLevel].isEnum)
       
   574   {
       
   575     m_t << getStyle("ListEnum") << endl;
       
   576     m_t << rtf_listItemInfo[m_indentLevel].number << ".\\tab ";
       
   577     rtf_listItemInfo[m_indentLevel].number++;
       
   578   }
       
   579   else
       
   580   {
       
   581     m_t << getStyle("ListBullet") << endl;
       
   582   }
       
   583   incIndentLevel();
       
   584   m_lastIsPara=FALSE;
       
   585 }
       
   586 
       
   587 void RTFDocVisitor::visitPost(DocAutoListItem *) 
       
   588 {
       
   589   decIndentLevel();
       
   590   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocAutoListItem)}\n");
       
   591 }
       
   592 
       
   593 void RTFDocVisitor::visitPre(DocPara *) 
       
   594 {
       
   595   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocPara)}\n");
       
   596 }
       
   597 
       
   598 void RTFDocVisitor::visitPost(DocPara *p)
       
   599 {
       
   600   if (m_hide) return;
       
   601   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocPara)}\n");
       
   602   if (!m_lastIsPara &&
       
   603       !p->isLast() &&            // omit <p> for last paragraph
       
   604       !(p->parent() &&           // and for parameters & sections
       
   605         p->parent()->kind()==DocNode::Kind_ParamSect
       
   606        )
       
   607      ) 
       
   608   {
       
   609     m_t << "\\par" << endl;
       
   610     m_lastIsPara=TRUE;
       
   611   }
       
   612 }
       
   613 
       
   614 void RTFDocVisitor::visitPre(DocRoot *r)
       
   615 {
       
   616   if (m_hide) return;
       
   617   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocRoot)}\n");
       
   618   if (r->indent()) incIndentLevel();
       
   619   m_t << "{" << rtf_Style["BodyText"]->reference << endl;
       
   620 }
       
   621 
       
   622 void RTFDocVisitor::visitPost(DocRoot *r)
       
   623 {
       
   624   if (m_hide) return;
       
   625   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocRoot)}\n");
       
   626   if (!m_lastIsPara && !r->singleLine()) m_t << "\\par" << endl;
       
   627   m_t << "}";
       
   628   m_lastIsPara=TRUE;
       
   629   if (r->indent()) decIndentLevel();
       
   630 }
       
   631 
       
   632 void RTFDocVisitor::visitPre(DocSimpleSect *s)
       
   633 {
       
   634   if (m_hide) return;
       
   635   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSimpleSect)}\n");
       
   636   if (!m_lastIsPara) m_t << "\\par" << endl;
       
   637   m_t << "{"; // start desc
       
   638   //m_t << "{\\b "; // start bold
       
   639   m_t << "{" << rtf_Style["Heading5"]->reference << endl;
       
   640   switch(s->type())
       
   641   {
       
   642     case DocSimpleSect::See: 
       
   643       m_t << theTranslator->trSeeAlso(); break;
       
   644     case DocSimpleSect::Return: 
       
   645       m_t << theTranslator->trReturns(); break;
       
   646     case DocSimpleSect::Author: 
       
   647       m_t << theTranslator->trAuthor(TRUE,TRUE); break;
       
   648     case DocSimpleSect::Authors: 
       
   649       m_t << theTranslator->trAuthor(TRUE,FALSE); break;
       
   650     case DocSimpleSect::Version: 
       
   651       m_t << theTranslator->trVersion(); break;
       
   652     case DocSimpleSect::Since: 
       
   653       m_t << theTranslator->trSince(); break;
       
   654     case DocSimpleSect::Date: 
       
   655       m_t << theTranslator->trDate(); break;
       
   656     case DocSimpleSect::Note: 
       
   657       m_t << theTranslator->trNote(); break;
       
   658     case DocSimpleSect::Warning:
       
   659       m_t << theTranslator->trWarning(); break;
       
   660     case DocSimpleSect::Pre:
       
   661       m_t << theTranslator->trPrecondition(); break;
       
   662     case DocSimpleSect::Post:
       
   663       m_t << theTranslator->trPostcondition(); break;
       
   664     case DocSimpleSect::Invar:
       
   665       m_t << theTranslator->trInvariant(); break;
       
   666     case DocSimpleSect::Remark:
       
   667       m_t << theTranslator->trRemarks(); break;
       
   668     case DocSimpleSect::Attention:
       
   669       m_t << theTranslator->trAttention(); break;
       
   670     case DocSimpleSect::User: break;
       
   671     case DocSimpleSect::Rcs: break;
       
   672     case DocSimpleSect::Unknown:  break;
       
   673   }
       
   674 
       
   675   // special case 1: user defined title
       
   676   if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs)
       
   677   {
       
   678     m_t << ":";
       
   679     m_t << "\\par";
       
   680     m_t << "}"; // end bold
       
   681     incIndentLevel();
       
   682     m_t << rtf_Style_Reset << getStyle("DescContinue");
       
   683   }
       
   684   m_lastIsPara=FALSE;
       
   685 }
       
   686 
       
   687 void RTFDocVisitor::visitPost(DocSimpleSect *)
       
   688 {
       
   689   if (m_hide) return;
       
   690   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSimpleSect)}\n");
       
   691   if (!m_lastIsPara) m_t << "\\par" << endl;
       
   692   decIndentLevel();
       
   693   m_t << "}"; // end desc
       
   694   m_lastIsPara=TRUE;
       
   695 }
       
   696 
       
   697 void RTFDocVisitor::visitPre(DocTitle *)
       
   698 {
       
   699   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocTitle)}\n");
       
   700 }
       
   701 
       
   702 void RTFDocVisitor::visitPost(DocTitle *)
       
   703 {
       
   704   if (m_hide) return;
       
   705   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocTitle)}\n");
       
   706   m_t << "\\par" << endl;
       
   707   m_t << "}"; // end bold
       
   708   incIndentLevel();
       
   709   m_t << rtf_Style_Reset << getStyle("DescContinue");
       
   710   m_lastIsPara=FALSE;
       
   711 }
       
   712 
       
   713 void RTFDocVisitor::visitPre(DocSimpleList *)
       
   714 {
       
   715   if (m_hide) return;
       
   716   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSimpleSect)}\n");
       
   717   m_t << "{" << endl;
       
   718   rtf_listItemInfo[m_indentLevel].isEnum = FALSE;
       
   719   m_lastIsPara=FALSE;
       
   720 }
       
   721 
       
   722 void RTFDocVisitor::visitPost(DocSimpleList *)
       
   723 {
       
   724   if (m_hide) return;
       
   725   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSimpleSect)}\n");
       
   726   if (!m_lastIsPara) m_t << "\\par" << endl;
       
   727   m_t << "}" << endl;
       
   728   m_lastIsPara=TRUE;
       
   729 }
       
   730 
       
   731 void RTFDocVisitor::visitPre(DocSimpleListItem *)
       
   732 {
       
   733   if (m_hide) return;
       
   734   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSimpleListItem)}\n");
       
   735   m_t << "\\par" << rtf_Style_Reset << getStyle("ListBullet") << endl;
       
   736   m_lastIsPara=FALSE;
       
   737   incIndentLevel();
       
   738 }
       
   739 
       
   740 void RTFDocVisitor::visitPost(DocSimpleListItem *) 
       
   741 {
       
   742   decIndentLevel();
       
   743   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSimpleListItem)}\n");
       
   744 }
       
   745 
       
   746 void RTFDocVisitor::visitPre(DocSection *s)
       
   747 {
       
   748   if (m_hide) return;
       
   749   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSection)}\n");
       
   750   if (!m_lastIsPara) m_t << "\\par" << endl;
       
   751   m_t << "{{" // start section
       
   752       << rtf_Style_Reset;
       
   753   QString heading;
       
   754   int level = QMIN(s->level()+1,4);
       
   755   heading.sprintf("Heading%d",level);
       
   756   // set style
       
   757   m_t << rtf_Style[heading]->reference << endl;
       
   758   // make table of contents entry
       
   759   filter(s->title());
       
   760   m_t << endl << "\\par" << "}" << endl;
       
   761   m_t << "{\\tc\\tcl" << level << " \\v ";
       
   762   filter(s->title());
       
   763   m_t << "}" << endl;
       
   764   m_lastIsPara=TRUE;
       
   765 }
       
   766 
       
   767 void RTFDocVisitor::visitPost(DocSection *) 
       
   768 {
       
   769   if (m_hide) return;
       
   770   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSection)}\n");
       
   771   m_t << "\\par}" << endl; // end section
       
   772   m_lastIsPara=TRUE;
       
   773 }
       
   774 
       
   775 void RTFDocVisitor::visitPre(DocHtmlList *l)
       
   776 {
       
   777   if (m_hide) return;
       
   778   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlList)}\n");
       
   779   m_t << "{" << endl;
       
   780   rtf_listItemInfo[m_indentLevel].isEnum = l->type()==DocHtmlList::Ordered; 
       
   781   rtf_listItemInfo[m_indentLevel].number = 1;
       
   782   m_lastIsPara=FALSE;
       
   783 }
       
   784 
       
   785 void RTFDocVisitor::visitPost(DocHtmlList *) 
       
   786 {
       
   787   if (m_hide) return;
       
   788   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlList)}\n");
       
   789   m_t << "\\par" << "}" << endl;
       
   790   m_lastIsPara=TRUE;
       
   791 }
       
   792 
       
   793 void RTFDocVisitor::visitPre(DocHtmlListItem *)
       
   794 {
       
   795   if (m_hide) return;
       
   796   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlListItem)}\n");
       
   797   m_t << "\\par" << endl;
       
   798   m_t << rtf_Style_Reset;
       
   799   if (rtf_listItemInfo[m_indentLevel].isEnum)
       
   800   {
       
   801     m_t << getStyle("ListEnum") << endl;
       
   802     m_t << rtf_listItemInfo[m_indentLevel].number << ".\\tab ";
       
   803     rtf_listItemInfo[m_indentLevel].number++;
       
   804   }
       
   805   else
       
   806   {
       
   807     m_t << getStyle("ListBullet") << endl;
       
   808   }
       
   809   incIndentLevel();
       
   810   m_lastIsPara=FALSE;
       
   811 }
       
   812 
       
   813 void RTFDocVisitor::visitPost(DocHtmlListItem *) 
       
   814 {
       
   815   decIndentLevel();
       
   816   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlListItem)}\n");
       
   817 }
       
   818 
       
   819 void RTFDocVisitor::visitPre(DocHtmlDescList *)
       
   820 {
       
   821   if (m_hide) return;
       
   822   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlDescList)}\n");
       
   823   //m_t << "{" << endl;
       
   824   //m_t << rtf_Style_Reset << getStyle("ListContinue");
       
   825   //m_lastIsPara=FALSE;
       
   826 }
       
   827 
       
   828 void RTFDocVisitor::visitPost(DocHtmlDescList *) 
       
   829 {
       
   830   if (m_hide) return;
       
   831   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlDescList)}\n");
       
   832   //m_t << "}" << endl;
       
   833   //m_t << "\\par" << endl;
       
   834   //m_lastIsPara=TRUE;
       
   835 }
       
   836 
       
   837 void RTFDocVisitor::visitPre(DocHtmlDescTitle *)
       
   838 {
       
   839   if (m_hide) return;
       
   840   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlDescTitle)}\n");
       
   841   //m_t << "\\par" << endl;
       
   842   //m_t << "{\\b ";
       
   843   m_t << "{" << rtf_Style["Heading5"]->reference << endl;
       
   844   m_lastIsPara=FALSE;
       
   845 }
       
   846 
       
   847 void RTFDocVisitor::visitPost(DocHtmlDescTitle *) 
       
   848 {
       
   849   if (m_hide) return;
       
   850   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlDescTitle)}\n");
       
   851   m_t << "\\par" << endl;
       
   852   m_t << "}" << endl;
       
   853   m_lastIsPara=TRUE;
       
   854 }
       
   855 
       
   856 void RTFDocVisitor::visitPre(DocHtmlDescData *)
       
   857 {
       
   858   if (m_hide) return;
       
   859   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlDescData)}\n");
       
   860   incIndentLevel();
       
   861   m_t << "{" << rtf_Style_Reset << getStyle("DescContinue");
       
   862 }
       
   863 
       
   864 void RTFDocVisitor::visitPost(DocHtmlDescData *) 
       
   865 {
       
   866   if (m_hide) return;
       
   867   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlDescData)}\n");
       
   868   m_t << "\\par";
       
   869   m_t << "}" << endl;
       
   870   decIndentLevel();
       
   871   m_lastIsPara=TRUE;
       
   872 }
       
   873 
       
   874 void RTFDocVisitor::visitPre(DocHtmlTable *)
       
   875 {
       
   876   if (m_hide) return;
       
   877   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlTable)}\n");
       
   878   if (!m_lastIsPara) m_t << "\\par" << endl;
       
   879   m_lastIsPara=TRUE;
       
   880 }
       
   881 
       
   882 void RTFDocVisitor::visitPost(DocHtmlTable *) 
       
   883 {
       
   884   if (m_hide) return;
       
   885   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlTable)}\n");
       
   886   m_t << "\\pard" << endl;
       
   887   m_lastIsPara=TRUE;
       
   888 }
       
   889 
       
   890 void RTFDocVisitor::visitPre(DocHtmlCaption *)
       
   891 {
       
   892   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlCaption)}\n");
       
   893 }
       
   894 
       
   895 void RTFDocVisitor::visitPost(DocHtmlCaption *) 
       
   896 {
       
   897   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlCaption)}\n");
       
   898 }
       
   899 
       
   900 void RTFDocVisitor::visitPre(DocHtmlRow *r)
       
   901 {
       
   902   if (m_hide) return;
       
   903   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlRow)}\n");
       
   904   uint i,columnWidth=r->numCells()>0 ? rtf_pageWidth/r->numCells() : 10;
       
   905   m_t << "\\trowd \\trgaph108\\trleft-108"
       
   906          "\\trbrdrt\\brdrs\\brdrw10 "
       
   907          "\\trbrdrl\\brdrs\\brdrw10 "
       
   908          "\\trbrdrb\\brdrs\\brdrw10 "
       
   909          "\\trbrdrr\\brdrs\\brdrw10 "
       
   910          "\\trbrdrh\\brdrs\\brdrw10 "
       
   911          "\\trbrdrv\\brdrs\\brdrw10 "<< endl;
       
   912   for (i=0;i<r->numCells();i++)
       
   913   {
       
   914     m_t << "\\clvertalt\\clbrdrt\\brdrs\\brdrw10 "
       
   915            "\\clbrdrl\\brdrs\\brdrw10 "
       
   916            "\\clbrdrb\\brdrs\\brdrw10 "
       
   917            "\\clbrdrr \\brdrs\\brdrw10 "
       
   918            "\\cltxlrtb "
       
   919            "\\cellx" << ((i+1)*columnWidth) << endl;
       
   920   }
       
   921   m_t << "\\pard \\widctlpar\\intbl\\adjustright" << endl;
       
   922   m_lastIsPara=FALSE;
       
   923 }
       
   924 
       
   925 void RTFDocVisitor::visitPost(DocHtmlRow *) 
       
   926 {
       
   927   if (m_hide) return;
       
   928   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlRow)}\n");
       
   929   m_t << endl;
       
   930   m_t << "\\pard \\widctlpar\\intbl\\adjustright" << endl;
       
   931   m_t << "{\\row }" << endl;
       
   932   m_lastIsPara=FALSE;
       
   933 }
       
   934 
       
   935 void RTFDocVisitor::visitPre(DocHtmlCell *)
       
   936 {
       
   937   if (m_hide) return;
       
   938   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlCell)}\n");
       
   939   m_t << "{";
       
   940   m_lastIsPara=FALSE;
       
   941 }
       
   942 
       
   943 void RTFDocVisitor::visitPost(DocHtmlCell *) 
       
   944 {
       
   945   if (m_hide) return;
       
   946   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlCell)}\n");
       
   947   m_t << "\\cell }";
       
   948   m_lastIsPara=FALSE;
       
   949 }
       
   950 
       
   951 void RTFDocVisitor::visitPre(DocInternal *)
       
   952 {
       
   953   if (m_hide) return;
       
   954   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocInternal)}\n");
       
   955   m_t << "{"; // start desc
       
   956   m_t << "{\\b "; // start bold
       
   957   m_t << theTranslator->trForInternalUseOnly();
       
   958   m_t << "}"; // end bold
       
   959   m_t << "\\par" << endl;
       
   960   incIndentLevel();
       
   961   m_t << rtf_Style_Reset << getStyle("DescContinue");
       
   962   m_lastIsPara=FALSE;
       
   963 }
       
   964 
       
   965 void RTFDocVisitor::visitPost(DocInternal *) 
       
   966 {
       
   967   if (m_hide) return;
       
   968   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocInternal)}\n");
       
   969   m_t << "\\par";
       
   970   decIndentLevel();
       
   971   m_t << "}"; // end desc
       
   972   m_lastIsPara=TRUE;
       
   973 }
       
   974 
       
   975 void RTFDocVisitor::visitPre(DocHRef *href)
       
   976 {
       
   977   if (m_hide) return;
       
   978   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHRef)}\n");
       
   979   if (Config_getBool("RTF_HYPERLINKS"))
       
   980   {
       
   981     m_t << "{\\field "
       
   982              "{\\*\\fldinst "
       
   983                "{ HYPERLINK  \\\\l \"" << href->url() << "\" "
       
   984                "}{}"
       
   985              "}"
       
   986              "{\\fldrslt "
       
   987                "{\\cs37\\ul\\cf2 ";
       
   988 
       
   989   }
       
   990   else
       
   991   {
       
   992     m_t << "{\\f2 ";
       
   993   }
       
   994   m_lastIsPara=FALSE;
       
   995 }
       
   996 
       
   997 void RTFDocVisitor::visitPost(DocHRef *) 
       
   998 {
       
   999   if (m_hide) return;
       
  1000   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHRef)}\n");
       
  1001   if (Config_getBool("RTF_HYPERLINKS"))
       
  1002   { 
       
  1003     m_t <<     "}"
       
  1004              "}"
       
  1005            "}";
       
  1006   }
       
  1007   else
       
  1008   {
       
  1009     m_t << "}";
       
  1010   }
       
  1011   m_lastIsPara=FALSE;
       
  1012 }
       
  1013 
       
  1014 void RTFDocVisitor::visitPre(DocHtmlHeader *header)
       
  1015 {
       
  1016   if (m_hide) return;
       
  1017   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlHeader)}\n");
       
  1018   m_t << "{" // start section
       
  1019       << rtf_Style_Reset;
       
  1020   QString heading;
       
  1021   int level = QMIN(header->level()+2,4);
       
  1022   heading.sprintf("Heading%d",level);
       
  1023   // set style
       
  1024   m_t << rtf_Style[heading]->reference;
       
  1025   // make table of contents entry
       
  1026   m_t << "{\\tc\\tcl \\v " << level << "}";
       
  1027   m_lastIsPara=FALSE;
       
  1028   
       
  1029 }
       
  1030 
       
  1031 void RTFDocVisitor::visitPost(DocHtmlHeader *) 
       
  1032 {
       
  1033   if (m_hide) return;
       
  1034   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlHeader)}\n");
       
  1035   m_t << "\\par";
       
  1036   m_t << "}" << endl; // end section
       
  1037   m_lastIsPara=TRUE;
       
  1038 }
       
  1039 
       
  1040 void RTFDocVisitor::visitPre(DocImage *img)
       
  1041 {
       
  1042   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocImage)}\n");
       
  1043   if (img->type()==DocImage::Rtf)
       
  1044   {
       
  1045     m_t << "\\par" << endl;
       
  1046     m_t << "{" << endl;
       
  1047     m_t << rtf_Style_Reset << endl;
       
  1048     m_t << "\\par\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"";
       
  1049     m_t << img->name();
       
  1050     m_t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl;
       
  1051     m_t << "}" << endl;
       
  1052     m_lastIsPara=TRUE;
       
  1053   }
       
  1054   else // other format -> skip
       
  1055   {
       
  1056   }
       
  1057   // hide caption since it is not supported at the moment
       
  1058   pushEnabled();
       
  1059   m_hide=TRUE;
       
  1060 }
       
  1061 
       
  1062 void RTFDocVisitor::visitPost(DocImage *) 
       
  1063 {
       
  1064   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocImage)}\n");
       
  1065   popEnabled();
       
  1066 }
       
  1067 
       
  1068 void RTFDocVisitor::visitPre(DocDotFile *df)
       
  1069 {
       
  1070   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocDotFile)}\n");
       
  1071   writeDotFile(df->file());
       
  1072 
       
  1073   // hide caption since it is not supported at the moment
       
  1074   pushEnabled();
       
  1075   m_hide=TRUE;
       
  1076 }
       
  1077 
       
  1078 void RTFDocVisitor::visitPost(DocDotFile *) 
       
  1079 {
       
  1080   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocDotFile)}\n");
       
  1081   popEnabled();
       
  1082 }
       
  1083 
       
  1084 void RTFDocVisitor::visitPre(DocLink *lnk)
       
  1085 {
       
  1086   if (m_hide) return;
       
  1087   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocLink)}\n");
       
  1088   startLink(lnk->ref(),lnk->file(),lnk->anchor());
       
  1089 }
       
  1090 
       
  1091 void RTFDocVisitor::visitPost(DocLink *lnk) 
       
  1092 {
       
  1093   if (m_hide) return;
       
  1094   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocLink)}\n");
       
  1095   endLink(lnk->ref());
       
  1096 }
       
  1097 
       
  1098 void RTFDocVisitor::visitPre(DocRef *ref)
       
  1099 {
       
  1100   if (m_hide) return;
       
  1101   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocRef)}\n");
       
  1102   if (!ref->file().isEmpty()) startLink(ref->ref(),ref->file(),ref->anchor());
       
  1103   if (!ref->hasLinkText()) filter(ref->targetTitle());
       
  1104 }
       
  1105 
       
  1106 void RTFDocVisitor::visitPost(DocRef *ref) 
       
  1107 {
       
  1108   if (m_hide) return;
       
  1109   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocRef)}\n");
       
  1110   if (!ref->file().isEmpty()) endLink(ref->ref());
       
  1111   m_t << " ";
       
  1112 }
       
  1113 
       
  1114 
       
  1115 void RTFDocVisitor::visitPre(DocSecRefItem *)
       
  1116 {
       
  1117   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSecRefItem)}\n");
       
  1118 }
       
  1119 
       
  1120 void RTFDocVisitor::visitPost(DocSecRefItem *) 
       
  1121 {
       
  1122   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSecRefItem)}\n");
       
  1123 }
       
  1124 
       
  1125 void RTFDocVisitor::visitPre(DocSecRefList *)
       
  1126 {
       
  1127   if (m_hide) return;
       
  1128   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSecRefList)}\n");
       
  1129   m_t << "{" << endl;
       
  1130   incIndentLevel();
       
  1131   m_t << rtf_Style_Reset << getStyle("LatexTOC") << endl;
       
  1132   m_t << "\\par" << endl;
       
  1133   m_lastIsPara=TRUE;
       
  1134 }
       
  1135 
       
  1136 void RTFDocVisitor::visitPost(DocSecRefList *) 
       
  1137 {
       
  1138   if (m_hide) return;
       
  1139   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSecRefList)}\n");
       
  1140   decIndentLevel();
       
  1141   m_t << "\\par";
       
  1142   m_t << "}" << endl;
       
  1143   m_lastIsPara=TRUE;
       
  1144 }
       
  1145 
       
  1146 //void RTFDocVisitor::visitPre(DocLanguage *l)
       
  1147 //{
       
  1148 //  DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocLanguage)}\n");
       
  1149 //  QString langId = Config_getEnum("OUTPUT_LANGUAGE");
       
  1150 //  if (l->id().lower()!=langId.lower())
       
  1151 //  {
       
  1152 //    pushEnabled();
       
  1153 //    m_hide = TRUE;
       
  1154 //  }
       
  1155 //}
       
  1156 //
       
  1157 //void RTFDocVisitor::visitPost(DocLanguage *l) 
       
  1158 //{
       
  1159 //  DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocLanguage)}\n");
       
  1160 //  QString langId = Config_getEnum("OUTPUT_LANGUAGE");
       
  1161 //  if (l->id().lower()!=langId.lower())
       
  1162 //  {
       
  1163 //    popEnabled();
       
  1164 //  }
       
  1165 //}
       
  1166 
       
  1167 void RTFDocVisitor::visitPre(DocParamSect *s)
       
  1168 {
       
  1169   if (m_hide) return;
       
  1170   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocParamSect)}\n");
       
  1171   m_t << "{"; // start param list
       
  1172   if (!m_lastIsPara) m_t << "\\par" << endl;
       
  1173   //m_t << "{\\b "; // start bold
       
  1174   m_t << "{" << rtf_Style["Heading5"]->reference << endl;
       
  1175   switch(s->type())
       
  1176   {
       
  1177     case DocParamSect::Param: 
       
  1178       m_t << theTranslator->trParameters(); break;
       
  1179     case DocParamSect::RetVal: 
       
  1180       m_t << theTranslator->trReturnValues(); break;
       
  1181     case DocParamSect::Exception: 
       
  1182       m_t << theTranslator->trExceptions(); break;
       
  1183     case DocParamSect::TemplateParam: 
       
  1184       /* TODO: add this 
       
  1185       m_t << theTranslator->trTemplateParam(); break;
       
  1186       */
       
  1187       m_t << "Template Parameters"; break;
       
  1188     default:
       
  1189       ASSERT(0);
       
  1190   }
       
  1191   m_t << ":";
       
  1192   m_t << "\\par";
       
  1193   m_t << "}" << endl;
       
  1194   incIndentLevel();
       
  1195   m_t << rtf_Style_Reset << getStyle("DescContinue");
       
  1196   m_lastIsPara=TRUE;
       
  1197 }
       
  1198 
       
  1199 void RTFDocVisitor::visitPost(DocParamSect *)
       
  1200 {
       
  1201   if (m_hide) return;
       
  1202   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocParamSect)}\n");
       
  1203   //m_t << "\\par" << endl;
       
  1204   decIndentLevel();
       
  1205   m_t << "}" << endl;
       
  1206 }
       
  1207 
       
  1208 void RTFDocVisitor::visitPre(DocParamList *pl)
       
  1209 {
       
  1210   if (m_hide) return;
       
  1211   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocParamList)}\n");
       
  1212 
       
  1213   // Put in the direction: in/out/in,out if specified.
       
  1214   if (pl->direction()!=DocParamSect::Unspecified)
       
  1215   {
       
  1216     m_t << "[";
       
  1217     if (pl->direction()==DocParamSect::In)
       
  1218     {
       
  1219       m_t << "in";
       
  1220     }
       
  1221     else if (pl->direction()==DocParamSect::Out)
       
  1222     {
       
  1223       m_t << "out";
       
  1224     }
       
  1225     else if (pl->direction()==DocParamSect::InOut)
       
  1226     {
       
  1227       m_t << "in,out";
       
  1228     }
       
  1229     m_t << "] ";
       
  1230   }
       
  1231 
       
  1232   m_t << "{\\i ";
       
  1233   //QStrListIterator li(pl->parameters());
       
  1234   //const char *s;
       
  1235   QListIterator<DocNode> li(pl->parameters());
       
  1236   DocNode *param;
       
  1237   bool first=TRUE;
       
  1238   for (li.toFirst();(param=li.current());++li)
       
  1239   {
       
  1240     if (!first) m_t << ","; else first=FALSE;
       
  1241     if (param->kind()==DocNode::Kind_Word)
       
  1242     {
       
  1243       visit((DocWord*)param); 
       
  1244     }
       
  1245     else if (param->kind()==DocNode::Kind_LinkedWord)
       
  1246     {
       
  1247       visit((DocLinkedWord*)param); 
       
  1248     }
       
  1249   }
       
  1250   m_t << "} ";
       
  1251   m_lastIsPara=TRUE;
       
  1252 }
       
  1253 
       
  1254 void RTFDocVisitor::visitPost(DocParamList *)
       
  1255 {
       
  1256   if (m_hide) return;
       
  1257   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocParamList)}\n");
       
  1258   m_t << "\\par" << endl;
       
  1259   m_lastIsPara=TRUE;
       
  1260 }
       
  1261 
       
  1262 void RTFDocVisitor::visitPre(DocXRefItem *x)
       
  1263 {
       
  1264   if (m_hide) return;
       
  1265   bool anonymousEnum = x->file()=="@";
       
  1266   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocXRefItem)}\n");
       
  1267   m_t << "{"; // start param list
       
  1268   //m_t << "{\\b "; // start bold
       
  1269   m_t << "{" << rtf_Style["Heading5"]->reference << endl;
       
  1270   if (Config_getBool("RTF_HYPERLINKS") && !anonymousEnum)
       
  1271   {
       
  1272     QString refName;
       
  1273     if (!x->file().isEmpty())
       
  1274     {
       
  1275       refName+=x->file();
       
  1276     }
       
  1277     if (!x->file().isEmpty() && !x->anchor().isEmpty())
       
  1278     {
       
  1279       refName+="_";
       
  1280     }
       
  1281     if (!x->anchor().isEmpty())
       
  1282     {
       
  1283       refName+=x->anchor();
       
  1284     }
       
  1285 
       
  1286     m_t << "{\\field "
       
  1287              "{\\*\\fldinst "
       
  1288                "{ HYPERLINK  \\\\l \"" << refName << "\" "
       
  1289                "}{}"
       
  1290              "}"
       
  1291              "{\\fldrslt "
       
  1292                "{\\cs37\\ul\\cf2 ";
       
  1293     filter(x->title());
       
  1294     m_t <<     "}"
       
  1295              "}"
       
  1296            "}";
       
  1297   }
       
  1298   else
       
  1299   {
       
  1300     filter(x->title());
       
  1301   }
       
  1302   m_t << ":";
       
  1303   m_t << "\\par";
       
  1304   m_t << "}"; // end bold
       
  1305   incIndentLevel();
       
  1306   m_t << rtf_Style_Reset << getStyle("DescContinue");
       
  1307   m_lastIsPara=FALSE;
       
  1308 }
       
  1309 
       
  1310 void RTFDocVisitor::visitPost(DocXRefItem *)
       
  1311 {
       
  1312   if (m_hide) return;
       
  1313   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocXRefItem)}\n");
       
  1314   m_t << "\\par" << endl;
       
  1315   decIndentLevel();
       
  1316   m_t << "}" << endl; // end xref item
       
  1317   m_lastIsPara=TRUE;
       
  1318 }
       
  1319 
       
  1320 void RTFDocVisitor::visitPre(DocInternalRef *ref)
       
  1321 {
       
  1322   if (m_hide) return;
       
  1323   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocInternalRef)}\n");
       
  1324   startLink("",ref->file(),ref->anchor());
       
  1325 }
       
  1326 
       
  1327 void RTFDocVisitor::visitPost(DocInternalRef *) 
       
  1328 {
       
  1329   if (m_hide) return;
       
  1330   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocInternalRef)}\n");
       
  1331   endLink("");
       
  1332   m_t << " ";
       
  1333 }
       
  1334 
       
  1335 void RTFDocVisitor::visitPre(DocCopy *)
       
  1336 {
       
  1337   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocCopy)}\n");
       
  1338 }
       
  1339 
       
  1340 void RTFDocVisitor::visitPost(DocCopy *)
       
  1341 {
       
  1342   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocCopy)}\n");
       
  1343 }
       
  1344 
       
  1345 void RTFDocVisitor::visitPre(DocText *)
       
  1346 {
       
  1347   DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocText)}\n");
       
  1348 }
       
  1349 
       
  1350 void RTFDocVisitor::visitPost(DocText *)
       
  1351 {
       
  1352   DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocText)}\n");
       
  1353 }
       
  1354 
       
  1355 //static char* getMultiByte(int c)
       
  1356 //{
       
  1357 //    static char s[10];
       
  1358 //    sprintf(s,"\\'%X",c);
       
  1359 //    return s;
       
  1360 //}
       
  1361 
       
  1362 void RTFDocVisitor::filter(const char *str,bool verbatim)
       
  1363 { 
       
  1364   if (str)
       
  1365   {
       
  1366     const unsigned char *p=(const unsigned char *)str;
       
  1367     unsigned char c;
       
  1368     unsigned char pc='\0';
       
  1369     while (*p)
       
  1370     {
       
  1371       //static bool MultiByte = FALSE;
       
  1372       c=*p++;
       
  1373 
       
  1374       //if ( MultiByte )
       
  1375       //{
       
  1376       //  m_t << getMultiByte( c );
       
  1377       //  MultiByte = FALSE;
       
  1378       //  continue;
       
  1379       //}
       
  1380       //if ( c >= 0x80 )
       
  1381       //{
       
  1382       //  MultiByte = TRUE;
       
  1383       //  m_t << getMultiByte( c );
       
  1384       //  continue;
       
  1385       //}
       
  1386 
       
  1387       switch (c)
       
  1388       {
       
  1389         case '{':  m_t << "\\{";            break;
       
  1390         case '}':  m_t << "\\}";            break;
       
  1391         case '\\': m_t << "\\\\";           break;
       
  1392         case '\n': if (verbatim)
       
  1393                    {
       
  1394                      m_t << "\\par" << endl; 
       
  1395                    }
       
  1396                    else
       
  1397                    {
       
  1398                      m_t << '\n';
       
  1399                    }
       
  1400                    break;
       
  1401         default:   m_t << (char)c;
       
  1402       }
       
  1403       pc = c;
       
  1404     }
       
  1405   }
       
  1406 }
       
  1407 
       
  1408 void RTFDocVisitor::startLink(const QString &ref,const QString &file,const QString &anchor)
       
  1409 {
       
  1410   if (ref.isEmpty() && Config_getBool("RTF_HYPERLINKS"))
       
  1411   {
       
  1412     QString refName;
       
  1413     if (!file.isEmpty())
       
  1414     {
       
  1415       refName+=file;
       
  1416     }
       
  1417     if (anchor)
       
  1418     {
       
  1419       refName+='_';
       
  1420       refName+=anchor;
       
  1421     }
       
  1422 
       
  1423     m_t << "{\\field {\\*\\fldinst { HYPERLINK  \\\\l \"";
       
  1424     m_t << rtfFormatBmkStr(refName);
       
  1425     m_t << "\" }{}";
       
  1426     m_t << "}{\\fldrslt {\\cs37\\ul\\cf2 ";
       
  1427   }
       
  1428   else
       
  1429   {
       
  1430     m_t << "{\\b ";
       
  1431   }
       
  1432   m_lastIsPara=FALSE;
       
  1433 }
       
  1434 
       
  1435 void RTFDocVisitor::endLink(const QString &ref)
       
  1436 {
       
  1437   if (ref.isEmpty() && Config_getBool("RTF_HYPERLINKS"))
       
  1438   {
       
  1439     m_t << "}}}";
       
  1440   }
       
  1441   else
       
  1442   {
       
  1443     m_t << "}";
       
  1444   }
       
  1445   m_lastIsPara=FALSE;
       
  1446 }
       
  1447 
       
  1448 void RTFDocVisitor::pushEnabled()
       
  1449 {
       
  1450   m_enabled.push(new bool(m_hide));
       
  1451 }
       
  1452 
       
  1453 void RTFDocVisitor::popEnabled()
       
  1454 {
       
  1455   bool *v=m_enabled.pop();
       
  1456   ASSERT(v!=0);
       
  1457   m_hide = *v;
       
  1458   delete v;
       
  1459 }
       
  1460 
       
  1461 void RTFDocVisitor::writeDotFile(const QString &fileName)
       
  1462 {
       
  1463   QString baseName=fileName;
       
  1464   int i;
       
  1465   if ((i=baseName.findRev('/'))!=-1)
       
  1466   {
       
  1467     baseName=baseName.right(baseName.length()-i-1);
       
  1468   } 
       
  1469   QString outDir = Config_getString("RTF_OUTPUT");
       
  1470   writeDotGraphFromFile(fileName,outDir,baseName,BITMAP);
       
  1471   if (!m_lastIsPara) m_t << "\\par" << endl;
       
  1472   m_t << "{" << endl;
       
  1473   m_t << rtf_Style_Reset;
       
  1474   m_t << "\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"";
       
  1475   m_t << baseName << "." << Config_getEnum("DOT_IMAGE_FORMAT");
       
  1476   m_t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl;
       
  1477   m_t << "}" << endl;
       
  1478   m_lastIsPara=TRUE;
       
  1479 }
       
  1480 
       
  1481 void RTFDocVisitor::writeMscFile(const QString &fileName)
       
  1482 {
       
  1483   QString baseName=fileName;
       
  1484   int i;
       
  1485   if ((i=baseName.findRev('/'))!=-1)
       
  1486   {
       
  1487     baseName=baseName.right(baseName.length()-i-1);
       
  1488   } 
       
  1489   QString outDir = Config_getString("RTF_OUTPUT");
       
  1490   writeMscGraphFromFile(fileName,outDir,baseName,MSC_BITMAP);
       
  1491   if (!m_lastIsPara) m_t << "\\par" << endl;
       
  1492   m_t << "{" << endl;
       
  1493   m_t << rtf_Style_Reset;
       
  1494   m_t << "\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"";
       
  1495   m_t << baseName << ".png";
       
  1496   m_t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl;
       
  1497   m_t << "}" << endl;
       
  1498   m_lastIsPara=TRUE;
       
  1499 }
       
  1500