1
1
/* *****************************************************************************
2
2
*
3
- *
4
- *
5
- *
6
- * Copyright (C) 1997-2015 by Dimitri van Heesch.
3
+ * Copyright (C) 1997-2021 by Dimitri van Heesch.
7
4
*
8
5
* Permission to use, copy, modify, and distribute this software and its
9
6
* documentation under the terms of the GNU General Public License is hereby
16
13
*
17
14
*/
18
15
19
- #include < stdlib.h>
20
- #include < qfile.h>
21
- #include < qregexp.h>
22
- #include < qtextstream.h>
16
+ #include < regex>
17
+ #include < string>
18
+ #include < fstream>
23
19
24
20
#include " rtfstyle.h"
25
21
#include " message.h"
26
22
27
-
28
23
RTFListItemInfo rtf_listItemInfo[rtf_maxIndentLevels];
29
24
30
25
QCString rtf_title;
@@ -38,6 +33,21 @@ QCString rtf_documentType;
38
33
QCString rtf_documentId;
39
34
QCString rtf_keywords;
40
35
36
+ static std::map<std::string,QCString &> g_styleMap =
37
+ {
38
+ { " Title" , rtf_title },
39
+ { " Subject" , rtf_subject },
40
+ { " Comments" , rtf_comments },
41
+ { " Company" , rtf_company },
42
+ { " LogoFilename" , rtf_logoFilename },
43
+ { " Author" , rtf_author },
44
+ { " Manager" , rtf_manager },
45
+ { " DocumentType" , rtf_documentType },
46
+ { " DocumentId" , rtf_documentId },
47
+ { " Keywords" , rtf_keywords }
48
+ };
49
+
50
+
41
51
char rtf_Style_Reset[] = " \\ pard\\ plain " ;
42
52
43
53
#define RTF_LatexToc (lvl,nest,nxt,pos,twps ) \
@@ -224,116 +234,80 @@ Rtf_Style_Default rtf_Style_Default[] =
224
234
}
225
235
};
226
236
227
- static const QRegExp s_clause (" \\\\ s[0-9]+ \\ s *" );
237
+ static const std::regex s_clause (" \\\\ s([[:digit:]]+)[[:space:]] *" );
228
238
229
- StyleData::StyleData (const char * reference, const char * definition)
239
+ StyleData::StyleData (const std::string & reference, const std::string & definition)
230
240
{
231
- const char *ref = reference;
232
-
233
- int start = s_clause.match (ref); ASSERT (start >= 0 );
234
- ref += start;
235
- m_index = (int )atol (ref + 2 ); ASSERT (m_index > 0 );
236
-
237
- m_reference = ref;
241
+ std::smatch match;
242
+ if (regex_search (reference,match,s_clause))
243
+ {
244
+ m_index = static_cast <int >(std::stoul (match[1 ].str ()));
245
+ }
246
+ else // error
247
+ {
248
+ m_index = 0 ;
249
+ }
250
+ m_reference = reference;
238
251
m_definition = definition;
239
252
}
240
253
241
- bool StyleData::setStyle (const char * s , const char * styleName)
254
+ bool StyleData::setStyle (const std::string &command , const std::string & styleName)
242
255
{
243
- static const QRegExp subgroup (" ^{[^}]*}\\ s*" );
244
- static const QRegExp any_clause (" ^\\\\ [a-z][a-z0-9-]*\\ s*" );
245
-
246
- int len = 0 ; // length of a particular RTF formatting control
247
- int ref_len = 0 ; // length of the whole formatting section of a style
248
- int start = s_clause.match (s, 0 , &len);
249
- if (start < 0 )
256
+ std::smatch match;
257
+ if (!regex_search (command,match,s_clause))
250
258
{
251
- err (" Style sheet '%s' contains no '\\ s' clause.\n {%s}\n " , styleName, s);
252
- return FALSE ;
253
- }
254
- s += start;
255
- m_index = (int )atol (s + 2 ); ASSERT (m_index > 0 );
256
-
257
- // search for the end of pure formatting codes
258
- const char * end = s + len;
259
- ref_len = len;
260
- bool haveNewDefinition = TRUE ;
261
- for (;;)
262
- {
263
- if (*end == ' {' )
264
- {
265
- // subgroups are used for \\additive
266
- if (0 != subgroup.match (end, 0 , &len))
267
- break ;
268
- else
269
- {
270
- end += len;
271
- ref_len += len;
272
- }
273
- }
274
- else if (*end == ' \\ ' )
275
- {
276
- if (0 == qstrncmp (end, " \\ snext" , 6 ))
277
- break ;
278
- if (0 == qstrncmp (end, " \\ sbasedon" , 9 ))
279
- break ;
280
- if (0 != any_clause.match (end, 0 , &len))
281
- break ;
282
- end += len;
283
- ref_len += len;
284
- }
285
- else if (*end == 0 )
286
- { // no style-definition part, keep default value
287
- haveNewDefinition = FALSE ;
288
- break ;
289
- }
290
- else // plain name without leading \\snext
291
- break ;
259
+ err (" Style sheet '%s' contains no '\\ s' clause.\n {%s}" , styleName.c_str (), command.c_str ());
260
+ return false ;
292
261
}
293
- m_reference = s;
294
- if (haveNewDefinition)
262
+ m_index = static_cast <int >(std::stoul (match[1 ].str ()));
263
+
264
+ static std::regex definition_splitter (" ^(.*)(\\\\ sbasedon[[:digit:]]+.*)$" );
265
+ if (regex_match (command,match,definition_splitter))
295
266
{
296
- m_definition = end;
267
+ m_reference = match[1 ].str ();
268
+ m_definition = match[2 ].str ();
297
269
}
298
- return TRUE ;
270
+
271
+ return true ;
299
272
}
300
273
274
+
301
275
void loadStylesheet (const char *name, StyleDataMap& map)
302
276
{
303
- QFile file (name);
304
- if (!file.open (IO_ReadOnly ))
277
+ std::ifstream file (name);
278
+ if (!file.is_open ( ))
305
279
{
306
- err (" Can't open RTF style sheet file %s. Using defaults.\n " ,name);
280
+ err (" Can't open RTF style sheet file %s. Using defaults." ,name);
307
281
return ;
308
282
}
309
283
msg (" Loading RTF style sheet %s...\n " ,name);
310
284
311
- static const QRegExp separator (" [ \t ]*=[ \t ]*" );
312
285
uint lineNr=1 ;
313
- QTextStream t (&file);
314
286
315
- while (!t. eof ())
287
+ for (std::string line ; getline (file,line) ; ) // for each line
316
288
{
317
- QCString s (4096 ); // string buffer of max line length
318
- s = t.readLine ().stripWhiteSpace ().utf8 ();
319
- if (s.isEmpty () || s.at (0 )==' #' ) continue ; // skip blanks & comments
320
- int sepLength;
321
- int sepStart = separator.match (s,0 ,&sepLength);
322
- if (sepStart<=0 ) // no valid assignment statement
289
+ if (line.empty () || line[0 ]==' #' ) continue ; // skip blanks & comments
290
+ static std::regex assignment_splitter (" [[:space:]]*=[[:space:]]*" );
291
+ std::smatch match;
292
+ if (std::regex_search (line,match,assignment_splitter))
323
293
{
324
- warn (name,lineNr," Assignment of style sheet name expected!\n " );
325
- continue ;
294
+ std::string key = match.prefix ();
295
+ std::string value = match.suffix ();
296
+ auto it = map.find (key);
297
+ if (it!=map.end ())
298
+ {
299
+ StyleData& styleData = it->second ;
300
+ styleData.setStyle (value,key);
301
+ }
302
+ else
303
+ {
304
+ warn (name,lineNr," Unknown style sheet name %s ignored." ,key.data ());
305
+ }
326
306
}
327
- QCString key=s.left (sepStart);
328
- auto it = map.find (key.str ());
329
- if (it==map.end ()) // not a valid style sheet name
307
+ else
330
308
{
331
- warn (name,lineNr," Unknown style sheet name %s ignored.\n " ,key.data ());
332
- continue ;
309
+ warn (name,lineNr," Assignment of style sheet name expected line='%s'!" ,line.c_str ());
333
310
}
334
- StyleData& styleData = it->second ;
335
- s+=" " ; // add command separator
336
- styleData.setStyle (s.data () + sepStart + sepLength, key.data ());
337
311
lineNr++;
338
312
}
339
313
}
@@ -342,44 +316,39 @@ StyleDataMap rtf_Style;
342
316
343
317
void loadExtensions (const char *name)
344
318
{
345
- QFile file (name);
346
- if (!file.open (IO_ReadOnly ))
319
+ std::ifstream file (name);
320
+ if (!file.is_open ( ))
347
321
{
348
- err (" Can't open RTF extensions file %s. Using defaults.\n " ,name);
322
+ err (" Can't open RTF extensions file %s. Using defaults." ,name);
349
323
return ;
350
324
}
351
325
msg (" Loading RTF extensions %s...\n " ,name);
352
326
353
- static const QRegExp separator (" [ \t ]*=[ \t ]*" );
354
327
uint lineNr=1 ;
355
- QTextStream t (&file);
356
- t.setEncoding (QTextStream::UnicodeUTF8);
357
328
358
- while (!t. eof ())
329
+ for (std::string line ; getline (file,line) ; ) // for each line
359
330
{
360
- QCString s (4096 ); // string buffer of max line length
361
- s = t.readLine ().stripWhiteSpace ().utf8 ();
362
- if (s.length ()==0 || s.at (0 )==' #' ) continue ; // skip blanks & comments
363
- int sepLength;
364
- int sepStart = separator.match (s,0 ,&sepLength);
365
- if (sepStart<=0 ) // no valid assignment statement
331
+ if (line.empty () || line[0 ]==' #' ) continue ; // skip blanks & comments
332
+ std::smatch match;
333
+ static std::regex assignment_splitter (" [[:space:]]*=[[:space:]]*" );
334
+ if (std::regex_search (line,match,assignment_splitter))
335
+ {
336
+ std::string key = match.prefix ();
337
+ std::string value = match.suffix ();
338
+ auto it = g_styleMap.find (key);
339
+ if (it!=g_styleMap.end ())
340
+ {
341
+ it->second = value;
342
+ }
343
+ else
344
+ {
345
+ warn (name,lineNr," Ignoring unknown extension key '%s'..." ,key.c_str ());
346
+ }
347
+ }
348
+ else
366
349
{
367
- warn (name,lineNr," Assignment of extension field expected!\n " );
368
- continue ;
350
+ warn (name,lineNr," Assignment of style sheet name expected!" );
369
351
}
370
- QCString key=s.left (sepStart);
371
- QCString data=s.data () + sepStart + sepLength;
372
-
373
- if (key == " Title" ) rtf_title = data.data ();
374
- if (key == " Subject" ) rtf_subject = data.data ();
375
- if (key == " Comments" ) rtf_comments = data.data ();
376
- if (key == " Company" ) rtf_company = data.data ();
377
- if (key == " LogoFilename" ) rtf_logoFilename = data.data ();
378
- if (key == " Author" ) rtf_author = data.data ();
379
- if (key == " Manager" ) rtf_manager = data.data ();
380
- if (key == " DocumentType" ) rtf_documentType = data.data ();
381
- if (key == " DocumentId" ) rtf_documentId = data.data ();
382
- if (key == " Keywords" ) rtf_keywords = data.data ();
383
352
lineNr++;
384
353
}
385
354
}
0 commit comments