Doxygen
Loading...
Searching...
No Matches
rtfstyle.cpp
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Copyright (C) 1997-2021 by Dimitri van Heesch.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
15
16// own header
17#include "rtfstyle.h"
18
19// standard includes
20#include <string>
21#include <fstream>
22#include <map>
23
24// other includes
25#include "message.h"
26#include "regex.h"
27
38
39static std::map<std::string,DString &> g_styleMap =
40{
41 { "Title", rtf_title },
42 { "Subject", rtf_subject },
43 { "Comments", rtf_comments },
44 { "Company", rtf_company },
45 { "LogoFilename", rtf_logoFilename },
46 { "Author", rtf_author },
47 { "Manager", rtf_manager },
48 { "DocumentType", rtf_documentType },
49 { "DocumentId", rtf_documentId },
50 { "Keywords", rtf_keywords }
51};
52
53
54char rtf_Style_Reset[] = "\\pard\\plain ";
55
56#define RTF_LatexToc(lvl,nest,nxt,pos,twps) \
57 \
58 { "LatexTOC"#lvl, \
59 "\\s"#nest"\\li"#pos"\\sa"#twps"\\sb"#twps"\\widctlpar\\tqr\\tldot\\tx8640\\adjustright \\fs20\\cgrid ",\
60 "\\sbasedon0 \\snext"#nxt" LatexTOC "#lvl \
61 }
62
63#define RTF_ListBullet(lvl,nest,nxt,pos,lvl2) \
64 { "ListBullet"#lvl, \
65 "\\s"#nest"\\fi-360\\li"#pos"\\widctlpar\\jclisttab\\tx"#pos"{\\*\\pn \\pnlvlbody\\ilvl0\\ls"#lvl2"\\pnrnot0\\pndec }\\ls1\\adjustright \\fs20\\cgrid ", \
66 "\\sbasedon0 \\snext"#nxt" \\sautoupd List Bullet "#lvl \
67 }
68
69#define RTF_ListEnum(lvl,nest,nxt,pos) \
70 { "ListEnum"#lvl, \
71 "\\s"#nest"\\fi-360\\li"#pos"\\widctlpar\\fs20\\cgrid ", \
72 "\\sbasedon0 \\snext"#nxt" \\sautoupd List Enum "#lvl \
73 }
74
75#define RTF_CodeExample(lvl,nest,nxt,pos) \
76 { "CodeExample"#lvl, \
77 "\\s"#nest"\\li"#pos"\\widctlpar\\adjustright \\shading1000\\cbpat8 \\f2\\fs16\\cgrid ", \
78 "\\sbasedon0 \\snext"#nxt" Code Example "#lvl \
79 }
80
81#define RTF_ListContinue(lvl,nest,nxt,pos) \
82 { "ListContinue"#lvl, \
83 "\\s"#nest"\\li"#pos"\\sa60\\sb30\\qj\\widctlpar\\qj\\adjustright \\fs20\\cgrid ", \
84 "\\sbasedon0 \\snext"#nxt" List Continue "#lvl \
85 }
86
87#define RTF_DescContinue(lvl,nest,nxt,pos) \
88 { "DescContinue"#lvl, \
89 "\\s"#nest"\\li"#pos"\\widctlpar\\ql\\adjustright \\fs20\\cgrid ", \
90 "\\sbasedon0 \\snext"#nxt" DescContinue "#lvl \
91 }
92
94{
95 { "Heading1",
96 "\\s1\\sb240\\sa60\\keepn\\widctlpar\\adjustright \\b\\f1\\fs36\\kerning36\\cgrid ",
97 "\\sbasedon0 \\snext0 heading 1"
98 },
99 { "Heading2",
100 "\\s2\\sb240\\sa60\\keepn\\widctlpar\\adjustright \\b\\f1\\fs28\\kerning28\\cgrid ",
101 "\\sbasedon0 \\snext0 heading 2"
102 },
103 { "Heading3",
104 "\\s3\\sb240\\sa60\\keepn\\widctlpar\\adjustright \\b\\f1\\cgrid ",
105 "\\sbasedon0 \\snext0 heading 3"
106 },
107 { "Heading4",
108 "\\s4\\sb240\\sa60\\keepn\\widctlpar\\adjustright \\b\\f1\\fs20\\cgrid ",
109 "\\sbasedon0 \\snext0 heading 4;}{\\*\\cs10 \\additive Default Paragraph Font"
110 },
111 { "Heading5",
112 "\\s5\\sb90\\sa30\\keepn\\widctlpar\\adjustright \\b\\f1\\fs16\\cgrid ",
113 "\\sbasedon0 \\snext0 heading 5;}{\\*\\cs10 \\additive Default Paragraph Font"
114 },
115 { "Heading6",
116 "\\s6\\sb90\\sa30\\keepn\\widctlpar\\adjustright \\b\\f1\\fs12\\cgrid ",
117 "\\sbasedon0 \\snext0 heading 6;}{\\*\\cs10 \\additive Default Paragraph Font"
118 },
119 { "Title",
120 "\\s15\\qc\\sb240\\sa60\\widctlpar\\outlinelevel0\\adjustright \\b\\f1\\fs32\\kerning28\\cgrid ",
121 "\\sbasedon0 \\snext15 Title"
122 },
123 { "SubTitle",
124 "\\s16\\qc\\sa60\\widctlpar\\outlinelevel1\\adjustright \\f1\\cgrid ",
125 "\\sbasedon0 \\snext16 Subtitle"
126 },
127 { "BodyText",
128 "\\s17\\sa60\\sb30\\widctlpar\\qj \\fs22\\cgrid ",
129 "\\sbasedon0 \\snext17 BodyText"
130 },
131 { "DenseText",
132 "\\s18\\widctlpar\\fs22\\cgrid ",
133 "\\sbasedon0 \\snext18 DenseText"
134 },
135 { "Header",
136 "\\s28\\widctlpar\\tqc\\tx4320\\tqr\\tx8640\\adjustright \\fs20\\cgrid ",
137 "\\sbasedon0 \\snext28 header"
138 },
139 { "Footer",
140 "\\s29\\widctlpar\\tqc\\tx4320\\tqr\\tx8640\\qr\\adjustright \\fs20\\cgrid ",
141 "\\sbasedon0 \\snext29 footer"
142 },
143 { "GroupHeader",
144 "\\s30\\li360\\sa60\\sb120\\keepn\\widctlpar\\adjustright \\b\\f1\\fs20\\cgrid ",
145 "\\sbasedon0 \\snext30 GroupHeader"
146 },
147
148 RTF_CodeExample( 0, 40, 41, 0),
149 RTF_CodeExample( 1, 41, 42, 360),
150 RTF_CodeExample( 2, 42, 43, 720),
151 RTF_CodeExample( 3, 43, 44,1080),
152 RTF_CodeExample( 4, 44, 45,1440),
153 RTF_CodeExample( 5, 45, 46,1800),
154 RTF_CodeExample( 6, 46, 47,2160),
155 RTF_CodeExample( 7, 47, 48,2520),
156 RTF_CodeExample( 8, 48, 49,2880),
157 RTF_CodeExample( 9, 49, 50,3240),
158 RTF_CodeExample(10, 50, 51,3600),
159 RTF_CodeExample(11, 51, 52,3960),
160 RTF_CodeExample(12, 52, 53,4320),
161 RTF_CodeExample(13, 53, 53,4680),
162
163 RTF_ListContinue( 0, 60, 61, 0),
164 RTF_ListContinue( 1, 61, 62, 360),
165 RTF_ListContinue( 2, 62, 63, 720),
166 RTF_ListContinue( 3, 63, 64,1080),
167 RTF_ListContinue( 4, 64, 65,1440),
168 RTF_ListContinue( 5, 65, 66,1800),
169 RTF_ListContinue( 6, 66, 67,2160),
170 RTF_ListContinue( 7, 67, 68,2520),
171 RTF_ListContinue( 8, 68, 69,2880),
172 RTF_ListContinue( 9, 69, 70,3240),
173 RTF_ListContinue(10, 70, 71,3600),
174 RTF_ListContinue(11, 71, 72,3960),
175 RTF_ListContinue(12, 72, 73,4320),
176 RTF_ListContinue(13, 73, 73,4680),
177
178 RTF_DescContinue( 0, 80, 81, 0),
179 RTF_DescContinue( 1, 81, 82, 360),
180 RTF_DescContinue( 2, 82, 83, 720),
181 RTF_DescContinue( 3, 83, 84,1080),
182 RTF_DescContinue( 4, 84, 85,1440),
183 RTF_DescContinue( 5, 85, 86,1800),
184 RTF_DescContinue( 6, 86, 87,2160),
185 RTF_DescContinue( 7, 87, 88,2520),
186 RTF_DescContinue( 8, 88, 89,2880),
187 RTF_DescContinue( 9, 89, 90,3240),
188 RTF_DescContinue(10, 90, 91,3600),
189 RTF_DescContinue(11, 91, 92,3960),
190 RTF_DescContinue(12, 92, 93,4320),
191 RTF_DescContinue(13, 93, 93,4680),
192
193 RTF_LatexToc( 0,100,101, 0,30),
194 RTF_LatexToc( 1,101,102, 360,27),
195 RTF_LatexToc( 2,102,103, 720,24),
196 RTF_LatexToc( 3,103,104,1080,21),
197 RTF_LatexToc( 4,104,105,1440,18),
198 RTF_LatexToc( 5,105,106,1800,15),
199 RTF_LatexToc( 6,106,107,2160,12),
200 RTF_LatexToc( 7,107,108,2520, 9),
201 RTF_LatexToc( 8,108,109,2880, 6),
202 RTF_LatexToc( 9,109,110,3240, 3),
203 RTF_LatexToc(10,110,111,3600, 3),
204 RTF_LatexToc(11,111,112,3960, 3),
205 RTF_LatexToc(12,112,113,4320, 3),
206 RTF_LatexToc(13,113,113,4680, 3),
207
208 RTF_ListBullet( 0,120,121, 360, 1),
209 RTF_ListBullet( 1,121,122, 720, 2),
210 RTF_ListBullet( 2,122,123,1080, 3),
211 RTF_ListBullet( 3,123,124,1440, 4),
212 RTF_ListBullet( 4,124,125,1800, 5),
213 RTF_ListBullet( 5,125,126,2160, 6),
214 RTF_ListBullet( 6,126,127,2520, 7),
215 RTF_ListBullet( 7,127,128,2880, 8),
216 RTF_ListBullet( 8,128,129,3240, 9),
217 RTF_ListBullet( 9,129,130,3600,10),
218 RTF_ListBullet(10,130,131,3960,11),
219 RTF_ListBullet(11,131,132,4320,12),
220 RTF_ListBullet(12,132,133,4680,13),
221 RTF_ListBullet(13,133,133,5040,14),
222
223 RTF_ListEnum( 0,140,141, 360),
224 RTF_ListEnum( 1,141,142, 720),
225 RTF_ListEnum( 2,142,143,1080),
226 RTF_ListEnum( 3,143,144,1440),
227 RTF_ListEnum( 4,144,145,1800),
228 RTF_ListEnum( 5,145,146,2160),
229 RTF_ListEnum( 6,146,147,2520),
230 RTF_ListEnum( 7,147,148,2880),
231 RTF_ListEnum( 8,148,149,3240),
232 RTF_ListEnum( 9,149,150,3600),
233 RTF_ListEnum(10,150,151,3960),
234 RTF_ListEnum(11,151,152,4320),
235 RTF_ListEnum(12,152,153,4680),
236 RTF_ListEnum(13,153,153,5040),
237
238 { nullptr,
239 nullptr,
240 nullptr
241 }
242};
243
244#define RTF_ListElement(id,lvl,pos,chr) \
245 { id, lvl, \
246 "\\listlevel\\levelnfc23\\leveljc0\\levelstartat1\\levelfollow0{\\leveltext \\'01\\u"#chr" ?;}{\\levelnumbers;}\\f8\\dbch\\af3\\fi-360\\li"#pos, \
247 "{\\*\\hyphen2\\hyphlead2\\hyphtrail2\\hyphmax0}\\nowidctlpar\\cf0\\hich\\af0\\langfe2052\\dbch\\af0\\afs24\\lang1081\\loch\\f0\\fs24\\lang1033{\\listtext\\pard\\plain \\hich\\af3\\dbch\\af3\\loch\\f8 \\'01\\u"#chr"\\tab}\\ilvl"#lvl"\\ls"#id" \\li0\\ri0\\lin0\\rin0\\fi-360\\tx"#pos"\\li"#pos"\\ri0\\lin"#pos"\\rin0\\fi-360\\kerning1\\hich\\af4\\dbch\\af5\\rtlch \\ltrch\\loch\\fs20" \
248 }
249
251{
252 RTF_ListElement( 1,0, 360, 8226),
253 RTF_ListElement( 1,1, 720, 9702),
254 RTF_ListElement( 1,2,1080, 9642),
255 RTF_ListElement( 1,3,1440, 8226),
256 RTF_ListElement( 1,4,1800, 9702),
257 RTF_ListElement( 1,5,2160, 9642),
258 RTF_ListElement( 1,6,2520, 8662),
259 RTF_ListElement( 1,7,2880, 9702),
260 RTF_ListElement( 1,8,3600, 9642),
261
262 RTF_ListElement( 2,0, 360, 9744),
263 RTF_ListElement( 2,1, 720, 9744),
264 RTF_ListElement( 2,2,1080, 9744),
265 RTF_ListElement( 2,3,1440, 9744),
266 RTF_ListElement( 2,4,1800, 9744),
267 RTF_ListElement( 2,5,2160, 9744),
268 RTF_ListElement( 2,6,2520, 9744),
269 RTF_ListElement( 2,7,2880, 9744),
270 RTF_ListElement( 2,8,3600, 9744),
271
272 RTF_ListElement( 3,0, 360, 9746),
273 RTF_ListElement( 3,1, 720, 9746),
274 RTF_ListElement( 3,2,1080, 9746),
275 RTF_ListElement( 3,3,1440, 9746),
276 RTF_ListElement( 3,4,1800, 9746),
277 RTF_ListElement( 3,5,2160, 9746),
278 RTF_ListElement( 3,6,2520, 9746),
279 RTF_ListElement( 3,7,2880, 9746),
280 RTF_ListElement( 3,8,3600, 9746),
281
282 { 0,
283 0,
284 nullptr,
285 nullptr
286 }
287};
288
289static const reg::Ex s_clause(R"(\\s(\d+)\s*)"); // match, e.g. '\s30' and capture '30'
290
292{
293 reg::Match match;
294 if (reg::search(reference.str(),match,s_clause))
295 {
296 m_index = static_cast<int>(std::stoul(match[1].str()));
297 }
298 else // error
299 {
300 m_index = 0;
301 }
304}
305
306bool StyleData::setStyle(const DString &command, const DString &styleName)
307{
308 reg::Match match;
309 if (!reg::search(command.str(),match,s_clause))
310 {
311 err("Style sheet '{}' contains no '\\s' clause.\n{{{}}}\n", styleName, command);
312 return false;
313 }
314 m_index = static_cast<int>(std::stoul(match[1].str()));
315
316 if (size_t index = command.find("\\sbasedon"); index!=DString::npos)
317 {
318 m_reference = command.left(index);
319 m_definition = command.mid(index);
320 }
321
322 return true;
323}
324
325
326void loadStylesheet(const DString &name, StyleDataMap& map)
327{
328 std::ifstream file(name.str());
329 if (!file.is_open())
330 {
331 err("Can't open RTF style sheet file {}. Using defaults.\n",name);
332 return;
333 }
334 msg("Loading RTF style sheet {}...\n",name);
335
336 uint32_t lineNr=1;
337
338 for (std::string line ; getline(file,line) ; ) // for each line
339 {
340 if (line.empty() || line[0]=='#') continue; // skip blanks & comments
341 static const reg::Ex assignment_splitter(R"(\s*=\s*)");
342 reg::Match match;
343 if (reg::search(line,match,assignment_splitter))
344 {
345 DString key = match.prefix().str();
346 DString value = match.suffix().str();
347 auto it = map.find(key.str());
348 if (it!=map.end())
349 {
350 StyleData& styleData = it->second;
351 styleData.setStyle(value,key);
352 }
353 else
354 {
355 warn(name,lineNr,"Unknown style sheet name {} ignored.",key);
356 }
357 }
358 else
359 {
360 warn(name,lineNr,"Assignment of style sheet name expected line='{}'!",line);
361 }
362 lineNr++;
363 }
364}
365
367
368void loadExtensions(const DString &name)
369{
370 std::ifstream file(name.str());
371 if (!file.is_open())
372 {
373 err("Can't open RTF extensions file {}. Using defaults.\n",name);
374 return;
375 }
376 msg("Loading RTF extensions {}...\n",name);
377
378 uint32_t lineNr=1;
379
380 for (std::string line ; getline(file,line) ; ) // for each line
381 {
382 if (line.empty() || line[0]=='#') continue; // skip blanks & comments
383 static const reg::Ex assignment_splitter(R"(\s*=\s*)");
384 reg::Match match;
385 if (reg::search(line,match,assignment_splitter))
386 {
387 std::string key = match.prefix().str();
388 std::string value = match.suffix().str();
389 auto it = g_styleMap.find(key);
390 if (it!=g_styleMap.end())
391 {
392 it->second = value;
393 }
394 else
395 {
396 warn(name,lineNr,"Ignoring unknown extension key '{}'...",key);
397 }
398 }
399 else
400 {
401 warn(name,lineNr,"Assignment of style sheet name expected!");
402 }
403 lineNr++;
404 }
405}
406
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Definition dstring.h:84
DString mid(size_t index, size_t len=npos) const
Definition dstring.h:318
static constexpr size_t npos
value used to indicate 'not found' or 'to the end of the string', matching std::string::npos
Definition dstring.h:178
size_t find(char c, size_t pos=0) const
Definition dstring.h:239
DString left(size_t len) const
Definition dstring.h:306
const std::string & str() const
Definition dstring.h:645
Class representing a regular expression.
Definition regex.h:39
Object representing the matching results.
Definition regex.h:154
#define warn(file, line, fmt,...)
Definition message.h:97
#define msg(fmt,...)
Definition message.h:94
#define err(fmt,...)
Definition message.h:127
bool search(std::string_view str, Match &match, const Ex &re, size_t pos)
Search in a given string str starting at position pos for a match against regular expression re.
Definition regex.cpp:850
DString rtf_author
Definition rtfstyle.cpp:33
DString rtf_documentId
Definition rtfstyle.cpp:36
#define RTF_ListEnum(lvl, nest, nxt, pos)
Definition rtfstyle.cpp:69
StyleDataMap rtf_Style
Definition rtfstyle.cpp:366
Rtf_Style_Default rtf_Style_Default[]
Definition rtfstyle.cpp:93
DString rtf_comments
Definition rtfstyle.cpp:30
#define RTF_CodeExample(lvl, nest, nxt, pos)
Definition rtfstyle.cpp:75
char rtf_Style_Reset[]
Definition rtfstyle.cpp:54
DString rtf_subject
Definition rtfstyle.cpp:29
#define RTF_LatexToc(lvl, nest, nxt, pos, twps)
Definition rtfstyle.cpp:56
void loadExtensions(const DString &name)
Definition rtfstyle.cpp:368
DString rtf_logoFilename
Definition rtfstyle.cpp:32
void loadStylesheet(const DString &name, StyleDataMap &map)
Definition rtfstyle.cpp:326
static const reg::Ex s_clause(R"(\\s(\d+)\s*)")
DString rtf_manager
Definition rtfstyle.cpp:34
#define RTF_DescContinue(lvl, nest, nxt, pos)
Definition rtfstyle.cpp:87
#define RTF_ListContinue(lvl, nest, nxt, pos)
Definition rtfstyle.cpp:81
Rtf_Table_Default rtf_Table_Default[]
Definition rtfstyle.cpp:250
#define RTF_ListElement(id, lvl, pos, chr)
Definition rtfstyle.cpp:244
DString rtf_documentType
Definition rtfstyle.cpp:35
#define RTF_ListBullet(lvl, nest, nxt, pos, lvl2)
Definition rtfstyle.cpp:63
DString rtf_title
Definition rtfstyle.cpp:28
DString rtf_company
Definition rtfstyle.cpp:31
static std::map< std::string, DString & > g_styleMap
Definition rtfstyle.cpp:39
DString rtf_keywords
Definition rtfstyle.cpp:37
std::map< std::string, StyleData > StyleDataMap
Definition rtfstyle.h:79
DString reference() const
Definition rtfstyle.h:69
StyleData()=default
DString m_reference
Definition rtfstyle.h:75
uint32_t m_index
Definition rtfstyle.h:74
DString definition() const
Definition rtfstyle.h:70
uint32_t index() const
Definition rtfstyle.h:71
DString m_definition
Definition rtfstyle.h:76
bool setStyle(const DString &command, const DString &styleName)
Definition rtfstyle.cpp:306