Doxygen
Loading...
Searching...
No Matches
rtfgen.cpp File Reference
#include "rtfgen.h"
#include <algorithm>
#include <mutex>
#include <stdlib.h>
#include <unordered_map>
#include "classlist.h"
#include "conceptdef.h"
#include "config.h"
#include "datetime.h"
#include "debug.h"
#include "diagram.h"
#include "dir.h"
#include "dirdef.h"
#include "docparser.h"
#include "dot.h"
#include "dotcallgraph.h"
#include "dotclassgraph.h"
#include "dotdirdeps.h"
#include "dotincldepgraph.h"
#include "doxygen.h"
#include "fileinfo.h"
#include "filename.h"
#include "groupdef.h"
#include "language.h"
#include "message.h"
#include "moduledef.h"
#include "namespacedef.h"
#include "outputlist.h"
#include "pagedef.h"
#include "portable.h"
#include "rtfdocvisitor.h"
#include "rtfstyle.h"
#include "utf8.h"
#include "util.h"
#include "version.h"
#include "vhdldocgen.h"
Include dependency graph for rtfgen.cpp:

Go to the source code of this file.

Macros

#define DBG_RTF(x)

Functions

static DString dateToRTFDateString ()
static DString docifyToString (const DString &str)
static DString makeIndexName (const DString &s, int i)
static DString objectLinkToString (const DString &ref, const DString &f, const DString &anchor, const DString &text)
bool isLeadBytes (int c)
static void encodeForOutput (TextStream &t, const DString &s)
static bool preProcessFile (Dir &d, const DString &infName, TextStream &t, bool bIncludeHeader=true, bool removeFile=true)
 VERY brittle routine inline RTF's included by other RTF's.
void testRTFOutput (const DString &name)
 Tests the integrity of the result by counting brackets.
DString rtfFormatBmkStr (const DString &name)

Variables

static StringSet removeSet
static std::mutex g_rtfFormatMutex
static std::unordered_map< std::string, std::string > g_tagMap
static DString g_nextTag ("AAAAAAAAAA")

Macro Definition Documentation

◆ DBG_RTF

#define DBG_RTF ( x)

Definition at line 58 of file rtfgen.cpp.

Referenced by preProcessFile().

Function Documentation

◆ dateToRTFDateString()

DString dateToRTFDateString ( )
static

Definition at line 62 of file rtfgen.cpp.

63{
64 auto tm = getCurrentDateTime();
65 DString result;
66 switch (Config_getEnum(TIMESTAMP))
67 {
68 case TIMESTAMP_t::YES:
69 case TIMESTAMP_t::DATETIME:
70 result.sprintf("\\yr%d\\mo%d\\dy%d\\hr%d\\min%d\\sec%d",
71 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
72 tm.tm_hour, tm.tm_min, tm.tm_sec);
73 break;
74 case TIMESTAMP_t::DATE:
75 result.sprintf("\\yr%d\\mo%d\\dy%d",
76 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday);
77 break;
78 case TIMESTAMP_t::NO:
79 return "";
80 }
81 return "{\\creatim " + result + "}\n";
82}
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Definition dstring.h:88
DString & sprintf(const char *format,...)
Definition dstring.cpp:30
#define Config_getEnum(name)
Definition config.h:35
std::tm getCurrentDateTime()
Returns the filled in std::tm for the current date and time.
Definition datetime.cpp:29

References Config_getEnum, getCurrentDateTime(), and DString::sprintf().

Referenced by RTFGenerator::endIndexSection().

◆ docifyToString()

DString docifyToString ( const DString & str)
static

Definition at line 84 of file rtfgen.cpp.

85{
86 DString result;
87 result.reserve(str.length());
88 if (!str.empty())
89 {
90 const char *p=str.data();
91 while (*p)
92 {
93 char c=*p++;
94
95 switch (c)
96 {
97 case '{': result += "\\{"; break;
98 case '}': result += "\\}"; break;
99 case '\\': result += "\\\\"; break;
100 default: result += c; break;
101 }
102 }
103 }
104 return result;
105}
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:152
void reserve(size_t size)
Reserve space for size bytes without changing the string contents.
Definition dstring.h:221
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition dstring.h:161
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition dstring.h:155

References DString::data(), DString::empty(), DString::length(), and DString::reserve().

Referenced by RTFGenerator::docify(), objectLinkToString(), and RTFGenerator::writeInheritedSectionTitle().

◆ encodeForOutput()

void encodeForOutput ( TextStream & t,
const DString & s )
static

Definition at line 2188 of file rtfgen.cpp.

2189{
2190 if (s==nullptr) return;
2191 DString encoding;
2192 bool converted=false;
2193 size_t l = s.length();
2194 static std::vector<char> enc;
2195 if (l*4>enc.size()) enc.resize(l*4); // worst case
2196 encoding.sprintf("CP%s",qPrint(theTranslator->trRTFansicp()));
2197 if (!encoding.empty())
2198 {
2199 // convert from UTF-8 back to the output encoding
2200 void *cd = portable_iconv_open(encoding.data(),"UTF-8");
2201 if (cd!=reinterpret_cast<void *>(-1))
2202 {
2203 size_t iLeft=l;
2204 size_t oLeft=enc.size();
2205 const char *inputPtr = s.data();
2206 char *outputPtr = &enc[0];
2207 if (!portable_iconv(cd, &inputPtr, &iLeft, &outputPtr, &oLeft))
2208 {
2209 enc.resize(enc.size()-oLeft);
2210 converted=true;
2211 }
2213 }
2214 }
2215 if (!converted) // if we did not convert anything, copy as is.
2216 {
2217 memcpy(enc.data(),s.data(),l);
2218 enc.resize(l);
2219 }
2220 bool multiByte = false;
2221
2222 for (size_t i=0;i<enc.size();i++)
2223 {
2224 uint8_t c = static_cast<uint8_t>(enc.at(i));
2225
2226 if (c>=0x80 || multiByte)
2227 {
2228 char esc[10];
2229 snprintf(esc,10,"\\'%X",c); // escape sequence for SBCS and DBCS(1st&2nd bytes).
2230 t << esc;
2231
2232 if (!multiByte)
2233 {
2234 multiByte = isLeadBytes(c); // It may be DBCS Codepages.
2235 }
2236 else
2237 {
2238 multiByte = false; // end of Double Bytes Character.
2239 }
2240 }
2241 else
2242 {
2243 t << c;
2244 }
2245 }
2246}
virtual DString trRTFansicp()=0
const char * qPrint(const char *s)
Definition dstring.h:787
Translator * theTranslator
Definition language.cpp:71
int portable_iconv_close(void *cd)
size_t portable_iconv(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
void * portable_iconv_open(const char *tocode, const char *fromcode)
bool isLeadBytes(int c)
Definition rtfgen.cpp:2160

References DString::data(), DString::empty(), isLeadBytes(), DString::length(), portable_iconv(), portable_iconv_close(), portable_iconv_open(), qPrint(), DString::sprintf(), theTranslator, and Translator::trRTFansicp().

Referenced by preProcessFile().

◆ isLeadBytes()

bool isLeadBytes ( int c)

Definition at line 2160 of file rtfgen.cpp.

2161{
2162 bool result=false; // for SBCS Codepages (cp1252,1251 etc...);
2163
2164 DString codePage = theTranslator->trRTFansicp();
2165
2166 if (codePage == "932") // cp932 (Japanese Shift-JIS)
2167 {
2168 result = (0x81<=c && c<=0x9f) || (0xe0<=c && c<=0xfc);
2169 }
2170 else if (codePage == "936") // cp936 (Simplified Chinese GBK)
2171 {
2172 result = 0x81<=c && c<=0xFE;
2173 }
2174 else if (codePage == "949") // cp949 (Korean)
2175 {
2176 result = 0x81<=c && c<=0xFE;
2177 }
2178 else if (codePage == "950") // cp950 (Traditional Chinese Big5)
2179 {
2180 result = 0x81<=c && c<=0xFE;
2181 }
2182
2183 return result;
2184}

References theTranslator, and Translator::trRTFansicp().

Referenced by encodeForOutput().

◆ makeIndexName()

DString makeIndexName ( const DString & s,
int i )
static

◆ objectLinkToString()

DString objectLinkToString ( const DString & ref,
const DString & f,
const DString & anchor,
const DString & text )
static

Definition at line 1551 of file rtfgen.cpp.

1553{
1554 DString result;
1555 if (ref.empty() && Config_getBool(RTF_HYPERLINKS))
1556 {
1557 DString refName;
1558 if (!f.empty())
1559 {
1560 refName+=stripPath(f);
1561 }
1562 if (!anchor.empty())
1563 {
1564 refName+='_';
1565 refName+=anchor;
1566 }
1567
1568 result += "{\\field {\\*\\fldinst { HYPERLINK \\\\l \"";
1569 result += rtfFormatBmkStr(refName);
1570 result += "\" }{}";
1571 result += "}{\\fldrslt {\\cs37\\ul\\cf2 ";
1572
1573 result += docifyToString(text);
1574
1575 result += "}}}\n";
1576 }
1577 else
1578 {
1579 result += "{\\b ";
1580 result += docifyToString(text);
1581 result += "}";
1582 }
1583 return result;
1584}
#define Config_getBool(name)
Definition config.h:33
DString rtfFormatBmkStr(const DString &name)
Definition rtfgen.cpp:2876
static DString docifyToString(const DString &str)
Definition rtfgen.cpp:84
DString stripPath(const DString &s)
Definition util.cpp:3962

References Config_getBool, docifyToString(), DString::empty(), rtfFormatBmkStr(), and stripPath().

Referenced by RTFGenerator::writeInheritedSectionTitle(), and RTFGenerator::writeObjectLink().

◆ preProcessFile()

bool preProcessFile ( Dir & d,
const DString & infName,
TextStream & t,
bool bIncludeHeader = true,
bool removeFile = true )
static

VERY brittle routine inline RTF's included by other RTF's.

it is recursive and ugly.

Definition at line 2252 of file rtfgen.cpp.

2253{
2254 static bool rtfDebug = Debug::isFlagSet(Debug::Rtf);
2255 std::ifstream f = Portable::openInputStream(infName);
2256 if (!f.is_open())
2257 {
2258 err("problems opening rtf file '{}' for reading\n",infName);
2259 return false;
2260 }
2261
2262 const int maxLineLength = 10240;
2263 static DString lineBuf(maxLineLength, DString::ExplicitSize);
2264
2265 // scan until find end of header
2266 // this is EXTREEEEEEEMLY brittle. It works on OUR rtf
2267 // files because the first line before the body
2268 // ALWAYS contains "{\comment begin body}"
2269 std::string line;
2270 while (getline(f,line))
2271 {
2272 line+='\n';
2273 if (line.find("\\comment begin body")!=std::string::npos) break;
2274 if (bIncludeHeader) encodeForOutput(t,line);
2275 }
2276
2277 std::string prevLine;
2278 bool first=true;
2279 while (getline(f,line))
2280 {
2281 line+='\n';
2282 size_t pos=prevLine.find("INCLUDETEXT \"");
2283 if (pos!=std::string::npos)
2284 {
2285 size_t startNamePos = prevLine.find('"',pos)+1;
2286 size_t endNamePos = prevLine.find('"',startNamePos);
2287 DString fileName = prevLine.substr(startNamePos,endNamePos-startNamePos);
2288 DBG_RTF(t << "{\\comment begin include " << fileName << "}\n")
2289 if (!preProcessFile(d,fileName,t,false)) return false;
2290 DBG_RTF(t << "{\\comment end include " << fileName << "}\n")
2291 }
2292 else if (!first) // no INCLUDETEXT on this line
2293 {
2294 encodeForOutput(t,prevLine);
2295 }
2296 prevLine = line;
2297 first=false;
2298 }
2299 if (!bIncludeHeader) // skip final '}' in case we don't include headers
2300 {
2301 size_t pos = line.rfind('}');
2302 if (pos==std::string::npos)
2303 {
2304 err("Strange, the last char was not a '}}'\n");
2305 pos = line.length();
2306 }
2307 encodeForOutput(t,line.substr(0,pos));
2308 }
2309 else
2310 {
2311 encodeForOutput(t,line);
2312 }
2313 f.close();
2314 // remove temporary file
2315 if (!rtfDebug && removeFile) removeSet.insert(FileInfo(d.filePath(infName.str())).absFilePath());
2316 return true;
2317}
DString substr(size_t pos=0, size_t count=npos) const
Returns a substring of length count starting at pos.
Definition dstring.h:227
@ ExplicitSize
Definition dstring.h:135
const std::string & str() const
Definition dstring.h:649
@ Rtf
Definition debug.h:44
static bool isFlagSet(const DebugMask mask)
Definition debug.cpp:133
std::string filePath(const std::string &path, bool acceptsAbsPath=true) const
Definition dir.cpp:281
Minimal replacement for QFileInfo.
Definition fileinfo.h:26
std::string absFilePath() const
Definition fileinfo.cpp:101
#define err(fmt,...)
Definition message.h:127
std::ifstream openInputStream(const DString &name, bool binary=false, bool openAtEnd=false)
Definition portable.cpp:676
#define DBG_RTF(x)
static void encodeForOutput(TextStream &t, const DString &s)
Definition rtfgen.cpp:2188
static StringSet removeSet
Definition rtfgen.cpp:60
#define DBG_RTF(x)
Definition rtfgen.cpp:58
static bool preProcessFile(Dir &d, const DString &infName, TextStream &t, bool bIncludeHeader=true, bool removeFile=true)
VERY brittle routine inline RTF's included by other RTF's.
Definition rtfgen.cpp:2252

References FileInfo::absFilePath(), DBG_RTF, encodeForOutput(), err, DString::ExplicitSize, Dir::filePath(), Debug::isFlagSet(), Portable::openInputStream(), preProcessFile(), removeSet, Debug::Rtf, DString::str(), and DString::substr().

Referenced by preProcessFile(), and RTFGenerator::preProcessFileInplace().

◆ rtfFormatBmkStr()

DString rtfFormatBmkStr ( const DString & name)

Definition at line 2876 of file rtfgen.cpp.

2877{
2878 std::lock_guard<std::mutex> lock(g_rtfFormatMutex);
2879
2880 // To overcome the 40-character tag limitation, we
2881 // substitute a short arbitrary string for the name
2882 // supplied, and keep track of the correspondence
2883 // between names and strings.
2884 auto it = g_tagMap.find(name.str());
2885 if (it!=g_tagMap.end()) // already known
2886 {
2887 return it->second;
2888 }
2889
2890 DString tag = g_nextTag;
2891 auto result = g_tagMap.emplace(name.str(), g_nextTag.str());
2892
2893 if (result.second) // new item was added
2894 {
2895 // increment the next tag.
2896
2897 char* nxtTag = g_nextTag.rawData() + g_nextTag.length() - 1;
2898 for ( unsigned int i = 0; i < g_nextTag.length(); ++i, --nxtTag )
2899 {
2900 if ( ( ++(*nxtTag) ) > 'Z' )
2901 {
2902 *nxtTag = 'A';
2903 }
2904 else
2905 {
2906 // Since there was no carry, we can stop now
2907 break;
2908 }
2909 }
2910 }
2911
2912 Debug::print(Debug::Rtf,0,"Name = {} RTF_tag = {}\n",name,tag);
2913 return tag;
2914}
char * rawData()
Returns a writable pointer to the data.
Definition dstring.h:170
static void print(DebugMask mask, int prio, fmt::format_string< Args... > fmt, Args &&... args)
Definition debug.h:78
static std::mutex g_rtfFormatMutex
Definition rtfgen.cpp:2872
static std::unordered_map< std::string, std::string > g_tagMap
Definition rtfgen.cpp:2873
static DString g_nextTag("AAAAAAAAAA")

References g_nextTag, g_rtfFormatMutex, g_tagMap, DString::length(), Rtf_Style_Default::name, Debug::print(), DString::rawData(), Debug::Rtf, and DString::str().

Referenced by RTFGenerator::endDoxyAnchor(), objectLinkToString(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::startLink(), RTFGenerator::startTextLink(), RTFGenerator::writeAnchor(), RTFCodeGenerator::writeCodeLink(), RTFCodeGenerator::writeLineNumber(), RTFGenerator::writeRTFReference(), and RTFGenerator::writeStartAnnoItem().

◆ testRTFOutput()

void testRTFOutput ( const DString & name)

Tests the integrity of the result by counting brackets.

Definition at line 2419 of file rtfgen.cpp.

2420{
2421 int bcount=0;
2422 int line=1;
2423 int c=0;
2424 std::ifstream f = Portable::openInputStream(name);
2425 if (f.is_open())
2426 {
2427 while ((c=f.get())!=-1)
2428 {
2429 if (c=='\\') // escape char
2430 {
2431 c=f.get();
2432 if (c==-1) break;
2433 }
2434 else if (c=='{') // open bracket
2435 {
2436 bcount++;
2437 }
2438 else if (c=='}') // close bracket
2439 {
2440 bcount--;
2441 if (bcount<0)
2442 {
2443 goto err;
2444 break;
2445 }
2446 }
2447 else if (c=='\n') // newline
2448 {
2449 line++;
2450 }
2451 }
2452 }
2453 if (bcount==0) return; // file is OK.
2454err:
2455 err("RTF integrity test failed at line {:d} of {} due to a bracket mismatch.\n"
2456 " Please try to create a small code example that produces this error \n"
2457 " and send that to doxygen@gmail.com.\n",line,name);
2458}

References err, Rtf_Style_Default::name, and Portable::openInputStream().

Referenced by RTFGenerator::preProcessFileInplace().

Variable Documentation

◆ g_nextTag

DString g_nextTag("AAAAAAAAAA") ( "AAAAAAAAAA" )
static

Referenced by rtfFormatBmkStr().

◆ g_rtfFormatMutex

std::mutex g_rtfFormatMutex
static

Definition at line 2872 of file rtfgen.cpp.

Referenced by rtfFormatBmkStr().

◆ g_tagMap

std::unordered_map<std::string,std::string> g_tagMap
static

Definition at line 2873 of file rtfgen.cpp.

Referenced by rtfFormatBmkStr().

◆ removeSet

StringSet removeSet
static

Definition at line 60 of file rtfgen.cpp.

Referenced by preProcessFile(), and RTFGenerator::preProcessFileInplace().