1 /******************************************************************************
6 * Copyright (C) 1997-2015 by Dimitri van Heesch.
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.
14 * Documents produced by Doxygen are derivative works derived from the
15 * input used in their production; they are not affected by this license.
22 #include <qtextstream.h>
28 RTFListItemInfo rtf_listItemInfo[rtf_maxIndentLevels];
32 QCString rtf_comments;
34 QCString rtf_logoFilename;
37 QCString rtf_documentType;
38 QCString rtf_documentId;
39 QCString rtf_keywords;
41 char rtf_Style_Reset[] = "\\pard\\plain ";
43 Rtf_Style_Default rtf_Style_Default[] =
46 "\\s1\\sb240\\sa60\\keepn\\widctlpar\\adjustright \\b\\f1\\fs36\\kerning36\\cgrid ",
47 "\\sbasedon0 \\snext0 heading 1"
50 "\\s2\\sb240\\sa60\\keepn\\widctlpar\\adjustright \\b\\f1\\fs28\\kerning28\\cgrid ",
51 "\\sbasedon0 \\snext0 heading 2"
54 "\\s3\\sb240\\sa60\\keepn\\widctlpar\\adjustright \\b\\f1\\cgrid ",
55 "\\sbasedon0 \\snext0 heading 3"
58 "\\s4\\sb240\\sa60\\keepn\\widctlpar\\adjustright \\b\\f1\\fs20\\cgrid ",
59 "\\sbasedon0 \\snext0 heading 4;}{\\*\\cs10 \\additive Default Paragraph Font"
62 "\\s5\\sb90\\sa30\\keepn\\widctlpar\\adjustright \\b\\f1\\fs20\\cgrid ",
63 "\\sbasedon0 \\snext0 heading 5;}{\\*\\cs10 \\additive Default Paragraph Font"
66 "\\s15\\qc\\sb240\\sa60\\widctlpar\\outlinelevel0\\adjustright \\b\\f1\\fs32\\kerning28\\cgrid ",
67 "\\sbasedon0 \\snext15 Title"
70 "\\s16\\qc\\sa60\\widctlpar\\outlinelevel1\\adjustright \\f1\\cgrid ",
71 "\\sbasedon0 \\snext16 Subtitle"
74 "\\s17\\sa60\\sb30\\widctlpar\\qj \\fs22\\cgrid ",
75 "\\sbasedon0 \\snext17 BodyText"
78 "\\s18\\widctlpar\\fs22\\cgrid ",
79 "\\sbasedon0 \\snext18 DenseText"
82 "\\s28\\widctlpar\\tqc\\tx4320\\tqr\\tx8640\\adjustright \\fs20\\cgrid ",
83 "\\sbasedon0 \\snext28 header"
86 "\\s29\\widctlpar\\tqc\\tx4320\\tqr\\tx8640\\qr\\adjustright \\fs20\\cgrid ",
87 "\\sbasedon0 \\snext29 footer"
90 "\\s30\\li360\\sa60\\sb120\\keepn\\widctlpar\\adjustright \\b\\f1\\fs20\\cgrid ",
91 "\\sbasedon0 \\snext30 GroupHeader"
94 "\\s40\\li0\\widctlpar\\adjustright \\shading1000\\cbpat8 \\f2\\fs16\\cgrid ",
95 "\\sbasedon0 \\snext41 Code Example 0"
98 "\\s41\\li360\\widctlpar\\adjustright \\shading1000\\cbpat8 \\f2\\fs16\\cgrid ",
99 "\\sbasedon0 \\snext42 Code Example 1"
102 "\\s42\\li720\\widctlpar\\adjustright \\shading1000\\cbpat8 \\f2\\fs16\\cgrid ",
103 "\\sbasedon0 \\snext43 Code Example 2"
106 "\\s43\\li1080\\widctlpar\\adjustright \\shading1000\\cbpat8 \\f2\\fs16\\cgrid ",
107 "\\sbasedon0 \\snext44 Code Example 3"
110 "\\s44\\li1440\\widctlpar\\adjustright \\shading1000\\cbpat8 \\f2\\fs16\\cgrid ",
111 "\\sbasedon0 \\snext45 Code Example 4"
114 "\\s45\\li1800\\widctlpar\\adjustright \\shading1000\\cbpat8 \\f2\\fs16\\cgrid ",
115 "\\sbasedon0 \\snext46 Code Example 5"
118 "\\s46\\li2160\\widctlpar\\adjustright \\shading1000\\cbpat8 \\f2\\fs16\\cgrid ",
119 "\\sbasedon0 \\snext47 Code Example 6"
122 "\\s47\\li2520\\widctlpar\\adjustright \\shading1000\\cbpat8 \\f2\\fs16\\cgrid ",
123 "\\sbasedon0 \\snext48 Code Example 7"
126 "\\s48\\li2880\\widctlpar\\adjustright \\shading1000\\cbpat8 \\f2\\fs16\\cgrid ",
127 "\\sbasedon0 \\snext49 Code Example 8"
130 "\\s49\\li3240\\widctlpar\\adjustright \\shading1000\\cbpat8 \\f2\\fs16\\cgrid ",
131 "\\sbasedon0 \\snext49 Code Example 9"
134 "\\s50\\li0\\sa60\\sb30\\qj\\widctlpar\\qj\\adjustright \\fs20\\cgrid ",
135 "\\sbasedon0 \\snext51 List Continue 0"
138 "\\s51\\li360\\sa60\\sb30\\qj\\widctlpar\\qj\\adjustright \\fs20\\cgrid ",
139 "\\sbasedon0 \\snext52 List Continue 1"
142 "\\s52\\li720\\sa60\\sb30\\qj\\widctlpar\\qj\\adjustright \\fs20\\cgrid ",
143 "\\sbasedon0 \\snext53 List Continue 2"
146 "\\s53\\li1080\\sa60\\sb30\\qj\\widctlpar\\qj\\adjustright \\fs20\\cgrid ",
147 "\\sbasedon0 \\snext54 List Continue 3"
150 "\\s54\\li1440\\sa60\\sb30\\qj\\widctlpar\\qj\\adjustright \\fs20\\cgrid ",
151 "\\sbasedon0 \\snext55 List Continue 4"
154 "\\s55\\li1800\\sa60\\sb30\\qj\\widctlpar\\qj\\adjustright \\fs20\\cgrid ",
155 "\\sbasedon0 \\snext56 List Continue 5"
158 "\\s56\\li2160\\sa60\\sb30\\qj\\widctlpar\\qj\\adjustright \\fs20\\cgrid ",
159 "\\sbasedon0 \\snext57 List Continue 6"
162 "\\s57\\li2520\\sa60\\sb30\\qj\\widctlpar\\qj\\adjustright \\fs20\\cgrid ",
163 "\\sbasedon0 \\snext58 List Continue 7"
166 "\\s58\\li2880\\sa60\\sb30\\qj\\widctlpar\\qj\\adjustright \\fs20\\cgrid ",
167 "\\sbasedon0 \\snext59 List Continue 8"
170 "\\s59\\li3240\\sa60\\sb30\\qj\\widctlpar\\qj\\adjustright \\fs20\\cgrid ",
171 "\\sbasedon0 \\snext59 List Continue 9"
174 "\\s60\\li0\\widctlpar\\ql\\adjustright \\fs20\\cgrid ",
175 "\\sbasedon0 \\snext61 DescContinue 0"
178 "\\s61\\li360\\widctlpar\\ql\\adjustright \\fs20\\cgrid ",
179 "\\sbasedon0 \\snext62 DescContinue 1"
182 "\\s62\\li720\\widctlpar\\ql\\adjustright \\fs20\\cgrid ",
183 "\\sbasedon0 \\snext63 DescContinue 2"
186 "\\s63\\li1080\\widctlpar\\ql\\adjustright \\fs20\\cgrid ",
187 "\\sbasedon0 \\snext64 DescContinue 3"
190 "\\s64\\li1440\\widctlpar\\ql\\adjustright \\fs20\\cgrid ",
191 "\\sbasedon0 \\snext65 DescContinue 4"
194 "\\s65\\li1800\\widctlpar\\ql\\adjustright \\fs20\\cgrid ",
195 "\\sbasedon0 \\snext66 DescContinue 5"
198 "\\s66\\li2160\\widctlpar\\ql\\adjustright \\fs20\\cgrid ",
199 "\\sbasedon0 \\snext67 DescContinue 6"
202 "\\s67\\li2520\\widctlpar\\ql\\adjustright \\fs20\\cgrid ",
203 "\\sbasedon0 \\snext68 DescContinue 7"
206 "\\s68\\li2880\\widctlpar\\ql\\adjustright \\fs20\\cgrid ",
207 "\\sbasedon0 \\snext69 DescContinue 8"
210 "\\s69\\li3240\\widctlpar\\ql\\adjustright \\fs20\\cgrid ",
211 "\\sbasedon0 \\snext69 DescContinue 9"
214 "\\s70\\li0\\sa30\\sb30\\widctlpar\\tqr\\tldot\\tx8640\\adjustright \\fs20\\cgrid ",
215 "\\sbasedon0 \\snext81 LatexTOC 0"
218 "\\s71\\li360\\sa27\\sb27\\widctlpar\\tqr\\tldot\\tx8640\\adjustright \\fs20\\cgrid ",
219 "\\sbasedon0 \\snext82 LatexTOC 1"
222 "\\s72\\li720\\sa24\\sb24\\widctlpar\\tqr\\tldot\\tx8640\\adjustright \\fs20\\cgrid ",
223 "\\sbasedon0 \\snext83 LatexTOC 2"
226 "\\s73\\li1080\\sa21\\sb21\\widctlpar\\tqr\\tldot\\tx8640\\adjustright \\fs20\\cgrid ",
227 "\\sbasedon0 \\snext84 LatexTOC 3"
230 "\\s74\\li1440\\sa18\\sb18\\widctlpar\\tqr\\tldot\\tx8640\\adjustright \\fs20\\cgrid ",
231 "\\sbasedon0 \\snext85 LatexTOC 4"
234 "\\s75\\li1800\\sa15\\sb15\\widctlpar\\tqr\\tldot\\tx8640\\adjustright \\fs20\\cgrid ",
235 "\\sbasedon0 \\snext86 LatexTOC 5"
238 "\\s76\\li2160\\sa12\\sb12\\widctlpar\\tqr\\tldot\\tx8640\\adjustright \\fs20\\cgrid ",
239 "\\sbasedon0 \\snext87 LatexTOC 6"
242 "\\s77\\li2520\\sa9\\sb9\\widctlpar\\tqr\\tldot\\tx8640\\adjustright \\fs20\\cgrid ",
243 "\\sbasedon0 \\snext88 LatexTOC 7"
246 "\\s78\\li2880\\sa6\\sb6\\widctlpar\\tqr\\tldot\\tx8640\\adjustright \\fs20\\cgrid ",
247 "\\sbasedon0 \\snext89 LatexTOC 8"
250 "\\s79\\li3240\\sa3\\sb3\\widctlpar\\tqr\\tldot\\tx8640\\adjustright \\fs20\\cgrid ",
251 "\\sbasedon0 \\snext89 LatexTOC 9"
254 "\\s80\\fi-360\\li360\\widctlpar\\jclisttab\\tx360{\\*\\pn \\pnlvlbody\\ilvl0\\ls1\\pnrnot0\\pndec }\\ls1\\adjustright \\fs20\\cgrid ",
255 "\\sbasedon0 \\snext81 \\sautoupd List Bullet 0"
258 "\\s81\\fi-360\\li720\\widctlpar\\jclisttab\\tx720{\\*\\pn \\pnlvlbody\\ilvl0\\ls2\\pnrnot0\\pndec }\\ls2\\adjustright \\fs20\\cgrid ",
259 "\\sbasedon0 \\snext82 \\sautoupd List Bullet 1"
262 "\\s82\\fi-360\\li1080\\widctlpar\\jclisttab\\tx1080{\\*\\pn \\pnlvlbody\\ilvl0\\ls3\\pnrnot0\\pndec }\\ls3\\adjustright \\fs20\\cgrid ",
263 "\\sbasedon0 \\snext83 \\sautoupd List Bullet 2"
266 "\\s83\\fi-360\\li1440\\widctlpar\\jclisttab\\tx1440{\\*\\pn \\pnlvlbody\\ilvl0\\ls4\\pnrnot0\\pndec }\\ls4\\adjustright \\fs20\\cgrid ",
267 "\\sbasedon0 \\snext84 \\sautoupd List Bullet 3"
270 "\\s84\\fi-360\\li1800\\widctlpar\\jclisttab\\tx1800{\\*\\pn \\pnlvlbody\\ilvl0\\ls5\\pnrnot0\\pndec }\\ls5\\adjustright \\fs20\\cgrid ",
271 "\\sbasedon0 \\snext85 \\sautoupd List Bullet 4"
274 "\\s85\\fi-360\\li2160\\widctlpar\\jclisttab\\tx2160{\\*\\pn \\pnlvlbody\\ilvl0\\ls6\\pnrnot0\\pndec }\\ls6\\adjustright \\fs20\\cgrid ",
275 "\\sbasedon0 \\snext86 \\sautoupd List Bullet 5"
278 "\\s86\\fi-360\\li2520\\widctlpar\\jclisttab\\tx2520{\\*\\pn \\pnlvlbody\\ilvl0\\ls7\\pnrnot0\\pndec }\\ls7\\adjustright \\fs20\\cgrid ",
279 "\\sbasedon0 \\snext87 \\sautoupd List Bullet 6"
282 "\\s87\\fi-360\\li2880\\widctlpar\\jclisttab\\tx2880{\\*\\pn \\pnlvlbody\\ilvl0\\ls8\\pnrnot0\\pndec }\\ls8\\adjustright \\fs20\\cgrid ",
283 "\\sbasedon0 \\snext88 \\sautoupd List Bullet 7"
286 "\\s88\\fi-360\\li3240\\widctlpar\\jclisttab\\tx3240{\\*\\pn \\pnlvlbody\\ilvl0\\ls9\\pnrnot0\\pndec }\\ls9\\adjustright \\fs20\\cgrid ",
287 "\\sbasedon0 \\snext89 \\sautoupd List Bullet 8"
290 "\\s89\\fi-360\\li3600\\widctlpar\\jclisttab\\tx3600{\\*\\pn \\pnlvlbody\\ilvl0\\ls10\\pnrnot0\\pndec }\\ls10\\adjustright \\fs20\\cgrid ",
291 "\\sbasedon0 \\snext89 \\sautoupd List Bullet 9"
294 "\\s90\\fi-360\\li360\\widctlpar\\fs20\\cgrid ",
295 "\\sbasedon0 \\snext91 \\sautoupd List Enum 0"
298 "\\s91\\fi-360\\li720\\widctlpar\\fs20\\cgrid ",
299 "\\sbasedon0 \\snext92 \\sautoupd List Enum 1"
302 "\\s92\\fi-360\\li1080\\widctlpar\\fs20\\cgrid ",
303 "\\sbasedon0 \\snext93 \\sautoupd List Enum 2"
306 "\\s93\\fi-360\\li1440\\widctlpar\\fs20\\cgrid ",
307 "\\sbasedon0 \\snext94 \\sautoupd List Enum 3"
310 "\\s94\\fi-360\\li1800\\widctlpar\\fs20\\cgrid ",
311 "\\sbasedon0 \\snext95 \\sautoupd List Enum 4"
314 "\\s95\\fi-360\\li2160\\widctlpar\\fs20\\cgrid ",
315 "\\sbasedon0 \\snext96 \\sautoupd List Enum 5"
318 "\\s96\\fi-360\\li2520\\widctlpar\\fs20\\cgrid ",
319 "\\sbasedon0 \\snext96 \\sautoupd List Enum 5"
322 "\\s97\\fi-360\\li2880\\widctlpar\\fs20\\cgrid ",
323 "\\sbasedon0 \\snext98 \\sautoupd List Enum 7"
326 "\\s98\\fi-360\\li3240\\widctlpar\\fs20\\cgrid ",
327 "\\sbasedon0 \\snext99 \\sautoupd List Enum 8"
330 "\\s99\\fi-360\\li3600\\widctlpar\\fs20\\cgrid ",
331 "\\sbasedon0 \\snext99 \\sautoupd List Enum 9"
339 const QRegExp StyleData::s_clause("\\\\s[0-9]+\\s*");
341 StyleData::StyleData(const char* reference, const char* definition)
343 int start = s_clause.match(reference); ASSERT(start >= 0);
345 index = (int)atol(reference + 2); ASSERT(index > 0);
347 ASSERT(reference != 0);
348 size_t size = 1 + strlen(reference);
349 memcpy(this->reference = new char[size], reference, size);
351 ASSERT(definition != 0);
352 size = 1 + strlen(definition);
353 memcpy(this->definition = new char[size], definition, size);
356 StyleData::~StyleData()
362 bool StyleData::setStyle(const char* s, const char* styleName)
364 static const QRegExp subgroup("^{[^}]*}\\s*");
365 static const QRegExp any_clause("^\\\\[a-z][a-z0-9-]*\\s*");
367 int len = 0; // length of a particular RTF formatting control
368 int ref_len = 0; // length of the whole formatting section of a style
369 int start = s_clause.match(s, 0, &len);
372 err("Style sheet '%s' contains no '\\s' clause.\n{%s}\n", styleName, s);
376 index = (int)atol(s + 2); ASSERT(index > 0);
378 // search for the end of pure formatting codes
379 const char* end = s + len;
381 bool haveNewDefinition = TRUE;
386 // subgroups are used for \\additive
387 if (0 != subgroup.match(end, 0, &len))
395 else if (*end == '\\')
397 if (0 == qstrncmp(end, "\\snext", 6))
399 if (0 == qstrncmp(end, "\\sbasedon", 9))
401 if (0 != any_clause.match(end, 0, &len))
407 { // no style-definition part, keep default value
408 haveNewDefinition = FALSE;
411 else // plain name without leading \\snext
415 reference = new char[ref_len + 1];
416 memcpy(reference, s, ref_len);
417 reference[ref_len] = 0;
418 if (haveNewDefinition)
421 size_t size = 1 + strlen(end);
422 definition = new char[size];
423 memcpy(definition, end, size);
428 void loadStylesheet(const char *name, QDict<StyleData>& dict)
431 if (!file.open(IO_ReadOnly))
433 err("Can't open RTF style sheet file %s. Using defaults.\n",name);
436 msg("Loading RTF style sheet %s...\n",name);
438 static const QRegExp separator("[ \t]*=[ \t]*");
440 QTextStream t(&file);
441 t.setEncoding(QTextStream::UnicodeUTF8);
445 QCString s(4096); // string buffer of max line length
446 s = t.readLine().stripWhiteSpace().utf8();
447 if (s.isEmpty() || s.at(0)=='#') continue; // skip blanks & comments
449 int sepStart = separator.match(s,0,&sepLength);
450 if (sepStart<=0) // no valid assignment statement
452 warn(name,lineNr,"Assignment of style sheet name expected!\n");
455 QCString key=s.left(sepStart);
456 if (dict[key]==0) // not a valid style sheet name
458 warn(name,lineNr,"Invalid style sheet name %s ignored.\n",key.data());
461 StyleData* styleData = dict.find(key);
464 warn(name,lineNr,"Unknown style sheet name %s ignored.\n",key.data());
467 s+=" "; // add command separator
468 styleData->setStyle(s.data() + sepStart + sepLength, key.data());
473 QDict<StyleData> rtf_Style(257);
475 void loadExtensions(const char *name)
478 if (!file.open(IO_ReadOnly))
480 err("Can't open RTF extensions file %s. Using defaults.\n",name);
483 msg("Loading RTF extensions %s...\n",name);
485 static const QRegExp separator("[ \t]*=[ \t]*");
487 QTextStream t(&file);
488 t.setEncoding(QTextStream::UnicodeUTF8);
492 QCString s(4096); // string buffer of max line length
493 s = t.readLine().stripWhiteSpace().utf8();
494 if (s.length()==0 || s.at(0)=='#') continue; // skip blanks & comments
496 int sepStart = separator.match(s,0,&sepLength);
497 if (sepStart<=0) // no valid assignment statement
499 warn(name,lineNr,"Assignment of extension field expected!\n");
502 QCString key=s.left(sepStart);
503 QCString data=s.data() + sepStart + sepLength;
505 if (key == "Title") rtf_title = data.data();
506 if (key == "Subject") rtf_subject = data.data();
507 if (key == "Comments") rtf_comments = data.data();
508 if (key == "Company") rtf_company = data.data();
509 if (key == "LogoFilename") rtf_logoFilename = data.data();
510 if (key == "Author") rtf_author = data.data();
511 if (key == "Manager") rtf_manager = data.data();
512 if (key == "DocumentType") rtf_documentType = data.data();
513 if (key == "DocumentId") rtf_documentId = data.data();
514 if (key == "Keywords") rtf_keywords = data.data();