Doxygen
Loading...
Searching...
No Matches
rtfgen.cpp File Reference
#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"
+ Include dependency graph for rtfgen.cpp:

Go to the source code of this file.

Macros

#define DBG_RTF(x)
 

Functions

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

Variables

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

Macro Definition Documentation

◆ DBG_RTF

#define DBG_RTF ( x)

Definition at line 55 of file rtfgen.cpp.

Referenced by preProcessFile().

Function Documentation

◆ dateToRTFDateString()

static 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}
This is an alternative implementation of QCString.
Definition qcstring.h:101
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
#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:30

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

Referenced by RTFGenerator::endIndexSection().

◆ docifyToString()

static 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}
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:153
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:150
void reserve(size_t size)
Reserve space for size bytes without changing the string contents.
Definition qcstring.h:172
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition qcstring.h:159

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

Referenced by objectLinkToString().

◆ encodeForOutput()

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

Definition at line 2181 of file rtfgen.cpp.

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

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 2153 of file rtfgen.cpp.

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

References theTranslator.

Referenced by encodeForOutput().

◆ makeIndexName()

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

◆ objectLinkToString()

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

Definition at line 1545 of file rtfgen.cpp.

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}
#define Config_getBool(name)
Definition config.h:33
QCString rtfFormatBmkStr(const QCString &name)
Definition rtfgen.cpp:2869
static QCString docifyToString(const QCString &str)
Definition rtfgen.cpp:81
QCString stripPath(const QCString &s)
Definition util.cpp:5292

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

◆ preProcessFile()

static 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 2245 of file rtfgen.cpp.

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

References FileInfo::absFilePath(), QCString::data(), 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 2869 of file rtfgen.cpp.

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

References g_nextTag, g_rtfFormatMutex, g_tagMap, Rtf_Style_Default::name, Debug::print(), qPrint(), 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 2412 of file rtfgen.cpp.

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

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

Referenced by RTFGenerator::preProcessFileInplace().

Variable Documentation

◆ g_nextTag

QCString g_nextTag("AAAAAAAAAA") ( "AAAAAAAAAA" )
static

Referenced by rtfFormatBmkStr().

◆ g_rtfFormatMutex

std::mutex g_rtfFormatMutex
static

Definition at line 2865 of file rtfgen.cpp.

Referenced by rtfFormatBmkStr().

◆ g_tagMap

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

Definition at line 2866 of file rtfgen.cpp.

Referenced by rtfFormatBmkStr().

◆ removeSet

StringSet removeSet
static

Definition at line 57 of file rtfgen.cpp.

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