Skip to main content

The rtfgen.cpp File Reference

Included Headers

#include <mutex> #include <stdlib.h> #include <algorithm> #include <unordered_map> #include "rtfgen.h" #include "config.h" #include "message.h" #include "doxygen.h" #include "util.h" #include "diagram.h" #include "language.h" #include "dot.h" #include "dotcallgraph.h" #include "dotclassgraph.h" #include "dotdirdeps.h" #include "dotincldepgraph.h" #include "version.h" #include "pagedef.h" #include "rtfstyle.h" #include "rtfdocvisitor.h" #include "docparser.h" #include "dirdef.h" #include "vhdldocgen.h" #include "portable.h" #include "groupdef.h" #include "classlist.h" #include "filename.h" #include "namespacedef.h" #include "dir.h" #include "utf8.h" #include "debug.h" #include "datetime.h" #include "outputlist.h" #include "moduledef.h"

Functions Index

static QCStringdateToRTFDateString ()
static QCStringdocifyToString (const QCString &str)
static QCStringmakeIndexName (const QCString &s, int i)
static QCStringobjectLinkToString (const QCString &ref, const QCString &f, const QCString &anchor, const QCString &text)
boolisLeadBytes (int c)
static voidencodeForOutput (TextStream &t, const QCString &s)
static boolpreProcessFile (Dir &d, const QCString &infName, TextStream &t, bool bIncludeHeader=true, bool removeFile=true)

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

voidtestRTFOutput (const QCString &name)

Tests the integrity of the result by counting brackets. More...

QCStringrtfFormatBmkStr (const QCString &name)

Variables Index

static StringSetremoveSet
static std::mutexg_rtfFormatMutex
static std::unordered_map< std::string, std::string >g_tagMap
static QCStringg_nextTag("AAAAAAAAAA")

Macro Definitions Index

#defineDBG_RTF(x)

Functions

dateToRTFDateString()

QCString dateToRTFDateString ()
static

Definition at line 59 of file rtfgen.cpp.

60{
61 auto tm = getCurrentDateTime();
62 QCString result;
63 switch (Config_getEnum(TIMESTAMP))
64 {
65 case TIMESTAMP_t::YES:
66 case TIMESTAMP_t::DATETIME:
67 result.sprintf("\\yr%d\\mo%d\\dy%d\\hr%d\\min%d\\sec%d",
68 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
69 tm.tm_hour, tm.tm_min, tm.tm_sec);
70 break;
71 case TIMESTAMP_t::DATE:
72 result.sprintf("\\yr%d\\mo%d\\dy%d",
73 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday);
74 break;
75 case TIMESTAMP_t::NO:
76 return "";
77 }
78 return "{\\creatim " + result + "}\n";
79}

References Config_getEnum, getCurrentDateTime and QCString::sprintf.

Referenced by RTFGenerator::endIndexSection.

docifyToString()

QCString docifyToString (const QCString & str)
static

Definition at line 81 of file rtfgen.cpp.

82{
83 QCString result;
84 result.reserve(str.length());
85 if (!str.isEmpty())
86 {
87 const char *p=str.data();
88 while (*p)
89 {
90 char c=*p++;
91
92 switch (c)
93 {
94 case '{': result += "\\{"; break;
95 case '}': result += "\\}"; break;
96 case '\\': result += "\\\\"; break;
97 default: result += c; break;
98 }
99 }
100 }
101 return result;
102}

References QCString::data, QCString::isEmpty, QCString::length and QCString::reserve.

Referenced by objectLinkToString.

encodeForOutput()

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

Definition at line 2182 of file rtfgen.cpp.

2182static void encodeForOutput(TextStream &t,const QCString &s)
2183{
2184 if (s==nullptr) return;
2185 QCString encoding;
2186 bool converted=FALSE;
2187 size_t l = s.length();
2188 static std::vector<char> enc;
2189 if (l*4>enc.size()) enc.resize(l*4); // worst case
2190 encoding.sprintf("CP%s",qPrint(theTranslator->trRTFansicp()));
2191 if (!encoding.isEmpty())
2192 {
2193 // convert from UTF-8 back to the output encoding
2194 void *cd = portable_iconv_open(encoding.data(),"UTF-8");
2195 if (cd!=reinterpret_cast<void *>(-1))
2196 {
2197 size_t iLeft=l;
2198 size_t oLeft=enc.size();
2199 const char *inputPtr = s.data();
2200 char *outputPtr = &enc[0];
2201 if (!portable_iconv(cd, &inputPtr, &iLeft, &outputPtr, &oLeft))
2202 {
2203 enc.resize(enc.size()-oLeft);
2204 converted=TRUE;
2205 }
2207 }
2208 }
2209 if (!converted) // if we did not convert anything, copy as is.
2210 {
2211 memcpy(enc.data(),s.data(),l);
2212 enc.resize(l);
2213 }
2214 bool multiByte = FALSE;
2215
2216 for (size_t i=0;i<enc.size();i++)
2217 {
2218 uint8_t c = static_cast<uint8_t>(enc.at(i));
2219
2220 if (c>=0x80 || multiByte)
2221 {
2222 char esc[10];
2223 qsnprintf(esc,10,"\\'%X",c); // escape sequence for SBCS and DBCS(1st&2nd bytes).
2224 t << esc;
2225
2226 if (!multiByte)
2227 {
2228 multiByte = isLeadBytes(c); // It may be DBCS Codepages.
2229 }
2230 else
2231 {
2232 multiByte = FALSE; // end of Double Bytes Character.
2233 }
2234 }
2235 else
2236 {
2237 t << c;
2238 }
2239 }
2240}

References QCString::data, FALSE, QCString::isEmpty, isLeadBytes, QCString::length, portable_iconv, portable_iconv_close, portable_iconv_open, qPrint, qsnprintf, QCString::sprintf, theTranslator and TRUE.

Referenced by preProcessFile.

isLeadBytes()

bool isLeadBytes (int c)

Definition at line 2154 of file rtfgen.cpp.

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

Reference theTranslator.

Referenced by encodeForOutput.

makeIndexName()

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

objectLinkToString()

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

Definition at line 1545 of file rtfgen.cpp.

1545static QCString objectLinkToString(const QCString &ref, const QCString &f,
1546 const QCString &anchor, const QCString &text)
1547{
1548 QCString result;
1549 if (ref.isEmpty() && Config_getBool(RTF_HYPERLINKS))
1550 {
1551 QCString refName;
1552 if (!f.isEmpty())
1553 {
1554 refName+=stripPath(f);
1555 }
1556 if (!anchor.isEmpty())
1557 {
1558 refName+='_';
1559 refName+=anchor;
1560 }
1561
1562 result += "{\\field {\\*\\fldinst { HYPERLINK \\\\l \"";
1563 result += rtfFormatBmkStr(refName);
1564 result += "\" }{}";
1565 result += "}{\\fldrslt {\\cs37\\ul\\cf2 ";
1566
1567 result += docifyToString(text);
1568
1569 result += "}}}\n";
1570 }
1571 else
1572 {
1573 result += "{\\b ";
1574 result += docifyToString(text);
1575 result += "}";
1576 }
1577 return result;
1578}

References Config_getBool, docifyToString, QCString::isEmpty, rtfFormatBmkStr and stripPath.

preProcessFile()

bool preProcessFile (Dir & d, const QCString & 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 2246 of file rtfgen.cpp.

2246static bool preProcessFile(Dir &d,const QCString &infName, TextStream &t, bool bIncludeHeader=true, bool removeFile = true)
2247{
2248 static bool rtfDebug = Debug::isFlagSet(Debug::Rtf);
2249 std::ifstream f = Portable::openInputStream(infName);
2250 if (!f.is_open())
2251 {
2252 err("problems opening rtf file '{}' for reading\n",infName);
2253 return false;
2254 }
2255
2256 const int maxLineLength = 10240;
2257 static QCString lineBuf(maxLineLength, QCString::ExplicitSize);
2258
2259 // scan until find end of header
2260 // this is EXTREEEEEEEMLY brittle. It works on OUR rtf
2261 // files because the first line before the body
2262 // ALWAYS contains "{\comment begin body}"
2263 std::string line;
2264 while (getline(f,line))
2265 {
2266 line+='\n';
2267 if (line.find("\\comment begin body")!=std::string::npos) break;
2268 if (bIncludeHeader) encodeForOutput(t,line.c_str());
2269 }
2270
2271 std::string prevLine;
2272 bool first=true;
2273 while (getline(f,line))
2274 {
2275 line+='\n';
2276 size_t pos=prevLine.find("INCLUDETEXT \"");
2277 if (pos!=std::string::npos)
2278 {
2279 size_t startNamePos = prevLine.find('"',pos)+1;
2280 size_t endNamePos = prevLine.find('"',startNamePos);
2281 std::string fileName = prevLine.substr(startNamePos,endNamePos-startNamePos);
2282 DBG_RTF(t << "{\\comment begin include " << fileName << "}\n")
2283 if (!preProcessFile(d,fileName.c_str(),t,FALSE)) return FALSE;
2284 DBG_RTF(t << "{\\comment end include " << fileName << "}\n")
2285 }
2286 else if (!first) // no INCLUDETEXT on this line
2287 {
2288 encodeForOutput(t,prevLine.c_str());
2289 }
2290 prevLine = line;
2291 first=false;
2292 }
2293 if (!bIncludeHeader) // skip final '}' in case we don't include headers
2294 {
2295 size_t pos = line.rfind('}');
2296 if (pos==std::string::npos)
2297 {
2298 err("Strange, the last char was not a '}}'\n");
2299 pos = line.length();
2300 }
2301 encodeForOutput(t,line.substr(0,pos).c_str());
2302 }
2303 else
2304 {
2305 encodeForOutput(t,line.c_str());
2306 }
2307 f.close();
2308 // remove temporary file
2309 if (!rtfDebug && removeFile) removeSet.insert(FileInfo(d.filePath(infName.str())).absFilePath());
2310 return TRUE;
2311}

References FileInfo::absFilePath, DBG_RTF, encodeForOutput, err, QCString::ExplicitSize, FALSE, Dir::filePath, Debug::isFlagSet, Portable::openInputStream, preProcessFile, removeSet, Debug::Rtf, QCString::str and TRUE.

Referenced by preProcessFile and RTFGenerator::preProcessFileInplace.

rtfFormatBmkStr()

QCString rtfFormatBmkStr (const QCString & name)

Definition at line 2870 of file rtfgen.cpp.

2871{
2872 std::lock_guard<std::mutex> lock(g_rtfFormatMutex);
2873
2874 // To overcome the 40-character tag limitation, we
2875 // substitute a short arbitrary string for the name
2876 // supplied, and keep track of the correspondence
2877 // between names and strings.
2878 auto it = g_tagMap.find(name.str());
2879 if (it!=g_tagMap.end()) // already known
2880 {
2881 return QCString(it->second);
2882 }
2883
2884 QCString tag = g_nextTag;
2885 auto result = g_tagMap.emplace(name.str(), g_nextTag.str());
2886
2887 if (result.second) // new item was added
2888 {
2889 // increment the next tag.
2890
2891 char* nxtTag = g_nextTag.rawData() + g_nextTag.length() - 1;
2892 for ( unsigned int i = 0; i < g_nextTag.length(); ++i, --nxtTag )
2893 {
2894 if ( ( ++(*nxtTag) ) > 'Z' )
2895 {
2896 *nxtTag = 'A';
2897 }
2898 else
2899 {
2900 // Since there was no carry, we can stop now
2901 break;
2902 }
2903 }
2904 }
2905
2906 Debug::print(Debug::Rtf,0,"Name = {} RTF_tag = {}\n",name,tag);
2907 return tag;
2908}

References g_nextTag, g_rtfFormatMutex, g_tagMap, Rtf_Style_Default::name, Debug::print and Debug::Rtf.

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 QCString & name)

Tests the integrity of the result by counting brackets.

Definition at line 2413 of file rtfgen.cpp.

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

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

Referenced by RTFGenerator::preProcessFileInplace.

Variables

g_nextTag

QCString g_nextTag("AAAAAAAAAA")
static

Definition at line 2868 of file rtfgen.cpp.

Referenced by rtfFormatBmkStr.

g_rtfFormatMutex

std::mutex g_rtfFormatMutex
static

Definition at line 2866 of file rtfgen.cpp.

2866static std::mutex g_rtfFormatMutex;

Referenced by rtfFormatBmkStr.

g_tagMap

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

Definition at line 2867 of file rtfgen.cpp.

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

Referenced by rtfFormatBmkStr.

removeSet

StringSet removeSet
static

Definition at line 57 of file rtfgen.cpp.

Referenced by preProcessFile and RTFGenerator::preProcessFileInplace.

Macro Definitions

DBG_RTF

#define DBG_RTF(x)

Definition at line 55 of file rtfgen.cpp.

55#define DBG_RTF(x)

Referenced by preProcessFile.


Generated via doxygen2docusaurus by Doxygen 1.14.0.