1
/* This is RTF to HTML converter, implemented as a text filter, generally.
2
Copyright (C) 2003 Valentin Lavrinenko, vlavrinenko@users.sourceforge.net
4
available at http://rtf2html.sf.net
6
Original available under the terms of the GNU LGPL2, and according
7
to those terms, relicensed under the GNU GPL2 for inclusion in Tellico */
9
/***************************************************************************
11
* This program is free software; you can redistribute it and/or modify *
12
* it under the terms of version 2 of the GNU General Public License as *
13
* published by the Free Software Foundation; *
15
***************************************************************************/
18
#include "rtf_table.h"
19
#include "rtf_tools.h"
20
#include "rtf_keyword.h"
29
using Tellico::RTF2HTML;
32
RTF2HTML::RTF2HTML(const QString& text) : m_text(text) {
35
QString RTF2HTML::toHTML() const {
36
std::string str_in = m_text;
38
std::string::iterator buf_in=str_in.begin(), buf_in_end=str_in.end();
45
formatting_options cur_options;
47
html_text par_html(cur_options);
49
/* CellDefs in rtf are really queer. We'll keep a list of them in main()
50
and will give an iterator into this list to a row */
51
table_cell_defs_list CellDefsList;
52
table_cell_defs_list::iterator CurCellDefs;
53
table_cell_def* tcdCurCellDef=new table_cell_def;
54
table_cell* tcCurCell=new table_cell;
55
table_row* trCurRow=new table_row;
56
table* tblCurTable=new table;
57
int iLastRowLeft=0, iLastRowHeight=0;
63
while(buf_in!=buf_in_end)
69
rtf_keyword kw(++buf_in);
70
if (kw.is_control_char())
71
switch (kw.control_char())
73
case '\\': case '{': case '}':
74
par_html.write(kw.control_char());
78
std::string stmp(1,*buf_in++);
80
int code=std::strtol(stmp.c_str(), NULL, 16);
84
par_html.write("•");
87
par_html.write("…");
90
par_html.write((char)code);
98
par_html.write(" ");
101
par_html.write("<br><br>");
104
else //kw.is_control_char
112
switch (kw.keyword())
114
case rtf_keyword::rkw_filetbl:
115
case rtf_keyword::rkw_stylesheet:
116
case rtf_keyword::rkw_header:
117
case rtf_keyword::rkw_footer: case rtf_keyword::rkw_headerf:
118
case rtf_keyword::rkw_footerf: case rtf_keyword::rkw_pict:
119
case rtf_keyword::rkw_object:
120
// we'll skip such groups
124
case rtf_keyword::rkw_info:
130
// std::cout<<std::string(buf_in).substr(0,20)<<"\t"<<depth<<std::endl;
135
rtf_keyword kw(++buf_in);
136
if (kw.keyword()==rtf_keyword::rkw_title)
140
case '{': ++depth; ++buf_in; break;
141
case '}': --depth; ++buf_in; in_title=false; break;
142
default: if (in_title) title+=*buf_in; ++buf_in; break;
148
case rtf_keyword::rkw_colortbl:
157
rtf_keyword kw(++buf_in);
158
switch (kw.keyword())
160
case rtf_keyword::rkw_red:
161
clr.r=kw.parameter();
163
case rtf_keyword::rkw_green:
164
clr.g=kw.parameter();
166
case rtf_keyword::rkw_blue:
167
clr.b=kw.parameter();
174
colortbl.push_back(clr);
186
case rtf_keyword::rkw_fonttbl:
190
bool full_name=false;
192
while (! (*buf_in=='}' && !in_font))
198
rtf_keyword kw(++buf_in);
199
if (kw.is_control_char() && kw.control_char()=='*')
202
switch (kw.keyword())
204
case rtf_keyword::rkw_f:
205
font_num=kw.parameter();
207
case rtf_keyword::rkw_fprq:
208
fnt.pitch=kw.parameter();
210
case rtf_keyword::rkw_fcharset:
211
fnt.charset=kw.parameter();
213
case rtf_keyword::rkw_fnil:
214
fnt.family=font::ff_none;
216
case rtf_keyword::rkw_froman:
217
fnt.family=font::ff_serif;
219
case rtf_keyword::rkw_fswiss:
220
fnt.family=font::ff_sans_serif;
222
case rtf_keyword::rkw_fmodern:
223
fnt.family=font::ff_monospace;
225
case rtf_keyword::rkw_fscript:
226
fnt.family=font::ff_cursive;
228
case rtf_keyword::rkw_fdecor:
229
fnt.family=font::ff_fantasy;
241
fonttbl.insert(std::make_pair(font_num, fnt));
251
if (!full_name && in_font)
260
// special characters
261
case rtf_keyword::rkw_line: case rtf_keyword::rkw_softline:
262
par_html.write("<br>");
264
case rtf_keyword::rkw_tab:
265
par_html.write(" "); // maybe, this can be done better
267
case rtf_keyword::rkw_enspace: case rtf_keyword::rkw_emspace:
268
par_html.write(" ");
270
case rtf_keyword::rkw_qmspace:
271
par_html.write(" ");
273
case rtf_keyword::rkw_endash:
274
par_html.write("–");
276
case rtf_keyword::rkw_emdash:
277
par_html.write("—");
279
case rtf_keyword::rkw_bullet:
280
par_html.write("•");
282
case rtf_keyword::rkw_lquote:
283
par_html.write("‘");
285
case rtf_keyword::rkw_rquote:
286
par_html.write("’");
288
case rtf_keyword::rkw_ldblquote:
289
par_html.write("“");
291
case rtf_keyword::rkw_rdblquote:
292
par_html.write("”");
294
// paragraph formatting
295
case rtf_keyword::rkw_ql:
296
cur_options.papAlign=formatting_options::align_left;
298
case rtf_keyword::rkw_qr:
299
cur_options.papAlign=formatting_options::align_right;
301
case rtf_keyword::rkw_qc:
302
cur_options.papAlign=formatting_options::align_center;
304
case rtf_keyword::rkw_qj:
305
cur_options.papAlign=formatting_options::align_justify;
307
case rtf_keyword::rkw_fi:
308
cur_options.papFirst=(int)rint(kw.parameter()/20);
310
case rtf_keyword::rkw_li:
311
cur_options.papLeft=(int)rint(kw.parameter()/20);
313
case rtf_keyword::rkw_ri:
314
cur_options.papRight=(int)rint(kw.parameter()/20);
316
case rtf_keyword::rkw_sb:
317
cur_options.papBefore=(int)rint(kw.parameter()/20);
319
case rtf_keyword::rkw_sa:
320
cur_options.papAfter=(int)rint(kw.parameter()/20);
322
case rtf_keyword::rkw_pard:
323
cur_options.papBefore=cur_options.papAfter=0;
324
cur_options.papLeft=cur_options.papRight=0;
325
cur_options.papFirst=0;
326
cur_options.papAlign=formatting_options::align_left;
327
cur_options.papInTbl=false;
329
case rtf_keyword::rkw_par:
330
case rtf_keyword::rkw_sect:
331
t_str=cur_options.get_par_str()+par_html.str()
332
+" "+par_html.close()+"</p>\n";
339
if (cur_options.papInTbl)
341
tcCurCell->Text+=t_str;
345
html+=tblCurTable->make()+t_str;
347
tblCurTable=new table;
352
// character formatting
353
case rtf_keyword::rkw_super:
354
cur_options.chpVAlign=
355
kw.parameter()==0?formatting_options::va_normal
356
:formatting_options::va_sup;
358
case rtf_keyword::rkw_sub:
359
cur_options.chpVAlign=
360
kw.parameter()==0?formatting_options::va_normal
361
:formatting_options::va_sub;
363
case rtf_keyword::rkw_b:
364
cur_options.chpBold=!(kw.parameter()==0);
366
case rtf_keyword::rkw_i:
367
cur_options.chpItalic=!(kw.parameter()==0);
369
case rtf_keyword::rkw_ul:
370
cur_options.chpUnderline=!(kw.parameter()==0);
372
case rtf_keyword::rkw_ulnone:
373
cur_options.chpUnderline=false;
375
case rtf_keyword::rkw_fs:
376
cur_options.chpFontSize=kw.parameter();
378
case rtf_keyword::rkw_cf:
379
cur_options.chpFColor=colortbl[kw.parameter()];
381
case rtf_keyword::rkw_cb:
382
cur_options.chpBColor=colortbl[kw.parameter()];
384
case rtf_keyword::rkw_highlight:
385
cur_options.chpHighlight=kw.parameter();
387
case rtf_keyword::rkw_f:
388
cur_options.chpFont=fonttbl[kw.parameter()];
390
case rtf_keyword::rkw_plain:
391
cur_options.chpBold=cur_options.chpItalic
392
=cur_options.chpUnderline=false;
393
cur_options.chpVAlign=formatting_options::va_normal;
394
cur_options.chpFontSize=cur_options.chpHighlight=0;
395
cur_options.chpFColor=cur_options.chpBColor=color();
396
cur_options.chpFont=font();
399
case rtf_keyword::rkw_intbl:
400
cur_options.papInTbl=true;
402
case rtf_keyword::rkw_trowd:
403
CurCellDefs=CellDefsList.insert(CellDefsList.end(),
405
case rtf_keyword::rkw_row:
406
if (!trCurRow->Cells.empty())
408
trCurRow->CellDefs=CurCellDefs;
409
if (trCurRow->Left==-1000)
410
trCurRow->Left=iLastRowLeft;
411
if (trCurRow->Height==-1000)
412
trCurRow->Height=iLastRowHeight;
413
tblCurTable->push_back(trCurRow);
414
trCurRow=new table_row;
418
case rtf_keyword::rkw_cell:
419
t_str=cur_options.get_par_str()+par_html.str()
420
+" "+par_html.close()+"</p>\n";
421
tcCurCell->Text+=t_str;
423
trCurRow->Cells.push_back(tcCurCell);
424
tcCurCell=new table_cell;
426
case rtf_keyword::rkw_cellx:
427
tcdCurCellDef->Right=kw.parameter();
428
CurCellDefs->push_back(tcdCurCellDef);
429
tcdCurCellDef=new table_cell_def;
431
case rtf_keyword::rkw_trleft:
432
trCurRow->Left=kw.parameter();
433
iLastRowLeft=kw.parameter();
435
case rtf_keyword::rkw_trrh:
436
trCurRow->Height=kw.parameter();
437
iLastRowHeight=kw.parameter();
439
case rtf_keyword::rkw_clvmgf:
440
tcdCurCellDef->FirstMerged=true;
442
case rtf_keyword::rkw_clvmrg:
443
tcdCurCellDef->Merged=true;
445
case rtf_keyword::rkw_clbrdrb:
446
tcdCurCellDef->BorderBottom=true;
447
tcdCurCellDef->ActiveBorder=&(tcdCurCellDef->BorderBottom);
449
case rtf_keyword::rkw_clbrdrt:
450
tcdCurCellDef->BorderTop=true;
451
tcdCurCellDef->ActiveBorder=&(tcdCurCellDef->BorderTop);
453
case rtf_keyword::rkw_clbrdrl:
454
tcdCurCellDef->BorderLeft=true;
455
tcdCurCellDef->ActiveBorder=&(tcdCurCellDef->BorderLeft);
457
case rtf_keyword::rkw_clbrdrr:
458
tcdCurCellDef->BorderRight=true;
459
tcdCurCellDef->ActiveBorder=&(tcdCurCellDef->BorderRight);
461
case rtf_keyword::rkw_brdrnone:
462
if (tcdCurCellDef->ActiveBorder!=NULL)
464
*(tcdCurCellDef->ActiveBorder)=false;
467
case rtf_keyword::rkw_clvertalt:
468
tcdCurCellDef->VAlign=table_cell_def::valign_top;
470
case rtf_keyword::rkw_clvertalc:
471
tcdCurCellDef->VAlign=table_cell_def::valign_center;
473
case rtf_keyword::rkw_clvertalb:
474
tcdCurCellDef->VAlign=table_cell_def::valign_bottom;
477
case rtf_keyword::rkw_paperw:
478
iDocWidth=kw.parameter();
480
case rtf_keyword::rkw_margl:
481
iMarginLeft=kw.parameter();
489
// perform group opening actions here
490
foStack.push(cur_options);
494
// perform group closing actions here
495
cur_options=foStack.top();
504
par_html.write("<");
508
par_html.write(">");
512
par_html.write(" ");
516
par_html.write(*buf_in++);
520
t_str=cur_options.get_par_str()+par_html.str()
521
+" "+par_html.close()+"</p>\n";
527
delete tcdCurCellDef;