summaryrefslogtreecommitdiffstats
path: root/src/rtf2html
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 19:17:32 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 19:17:32 +0000
commite38d2351b83fa65c66ccde443777647ef5cb6cff (patch)
tree1897fc20e9f73a81c520a5b9f76f8ed042124883 /src/rtf2html
downloadtellico-e38d2351b83fa65c66ccde443777647ef5cb6cff.tar.gz
tellico-e38d2351b83fa65c66ccde443777647ef5cb6cff.zip
Added KDE3 version of Tellico
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/tellico@1097620 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/rtf2html')
-rw-r--r--src/rtf2html/Makefile.am15
-rw-r--r--src/rtf2html/common.h38
-rw-r--r--src/rtf2html/dbg_iter.h67
-rw-r--r--src/rtf2html/fmt_opts.cpp221
-rw-r--r--src/rtf2html/fmt_opts.h154
-rw-r--r--src/rtf2html/rtf2html.cpp531
-rw-r--r--src/rtf2html/rtf2html.h28
-rw-r--r--src/rtf2html/rtf_keyword.cpp107
-rw-r--r--src/rtf2html/rtf_keyword.h1
-rw-r--r--src/rtf2html/rtf_table.cpp235
-rw-r--r--src/rtf2html/rtf_table.h90
-rw-r--r--src/rtf2html/rtf_tools.h65
12 files changed, 1552 insertions, 0 deletions
diff --git a/src/rtf2html/Makefile.am b/src/rtf2html/Makefile.am
new file mode 100644
index 0000000..ea3d39f
--- /dev/null
+++ b/src/rtf2html/Makefile.am
@@ -0,0 +1,15 @@
+AM_CPPFLAGS = $(all_includes)
+
+noinst_LIBRARIES = librtf2html.a
+librtf2html_a_SOURCES = fmt_opts.cpp rtf2html.cpp rtf_keyword.cpp rtf_table.cpp
+
+librtf2html_a_METASOURCES = AUTO
+
+KDE_OPTIONS = noautodist
+
+EXTRA_DIST = common.h dbg_iter.h fmt_opts.h fmt_opts.cpp \
+rtf2html.h rtf2html.cpp rtf_keyword.h rtf_keyword.cpp \
+rtf_table.h rtf_table.cpp rtf_tools.h
+
+CLEANFILES = *~
+
diff --git a/src/rtf2html/common.h b/src/rtf2html/common.h
new file mode 100644
index 0000000..01b1f5b
--- /dev/null
+++ b/src/rtf2html/common.h
@@ -0,0 +1,38 @@
+/* This is RTF to HTML converter, implemented as a text filter, generally.
+ Copyright (C) 2003 Valentin Lavrinenko, [email protected]
+
+ available at http://rtf2html.sf.net
+
+ Original available under the terms of the GNU LGPL2, and according
+ to those terms, relicensed under the GNU GPL2 for inclusion in Tellico */
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#ifndef __COMMON_H__
+#define __COMMON_H__
+
+#include <string>
+#include <sstream>
+#include <iomanip>
+
+inline std::string from_int(int value)
+{
+ std::ostringstream buf;
+ buf<<value;
+ return buf.str();
+}
+
+inline std::string hex(unsigned int value)
+{
+ std::ostringstream buf;
+ buf<<std::setw(2)<<std::setfill('0')<<std::hex<<value;
+ return buf.str();
+}
+
+#endif
diff --git a/src/rtf2html/dbg_iter.h b/src/rtf2html/dbg_iter.h
new file mode 100644
index 0000000..dfbccf2
--- /dev/null
+++ b/src/rtf2html/dbg_iter.h
@@ -0,0 +1,67 @@
+/* This is RTF to HTML converter, implemented as a text filter, generally.
+ Copyright (C) 2003 Valentin Lavrinenko, [email protected]
+
+ available at http://rtf2html.sf.net
+
+ Original available under the terms of the GNU LGPL2, and according
+ to those terms, relicensed under the GNU GPL2 for inclusion in Tellico */
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+namespace rtf {
+
+template <class T>
+class dbg_iter_mixin : public virtual T
+{
+ public:
+ int offset;
+ dbg_iter_mixin(const T& t) : T(t)
+ {}
+ T& operator=(const T& t)
+ {
+ return T::operator=(t);
+ }
+ dbg_iter_mixin& operator++ ()
+ {
+ ++offset;
+ T::operator++();
+ return *this;
+ }
+ dbg_iter_mixin operator++ (int i)
+ {
+ ++offset;
+ return T::operator++(i);
+ }
+ char operator *() const
+ {
+ T::value_type c=T::operator*();
+// std::cerr<<offset<<":"<<c<<std::endl;
+ return c;
+ }
+};
+
+template <class T>
+class dbg_iter : public dbg_iter_mixin<T>
+{
+ public:
+ dbg_iter(const T& t) : dbg_iter_mixin<T>(t)
+ {}
+};
+
+template<class T>
+class dbg_iter<std::istreambuf_iterator<T> > :
+ public virtual std::istreambuf_iterator<T>,
+ public dbg_iter_mixin<std::istreambuf_iterator<T> >
+{
+ public:
+ dbg_iter(std::basic_streambuf<T> *buf) : std::istreambuf_iterator<T>(buf)
+ {}
+};
+
+} \ No newline at end of file
diff --git a/src/rtf2html/fmt_opts.cpp b/src/rtf2html/fmt_opts.cpp
new file mode 100644
index 0000000..25a2f24
--- /dev/null
+++ b/src/rtf2html/fmt_opts.cpp
@@ -0,0 +1,221 @@
+/* This is RTF to HTML converter, implemented as a text filter, generally.
+ Copyright (C) 2003 Valentin Lavrinenko, [email protected]
+
+ available at http://rtf2html.sf.net
+
+ Original available under the terms of the GNU LGPL2, and according
+ to those terms, relicensed under the GNU GPL2 for inclusion in Tellico */
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#include "fmt_opts.h"
+
+using namespace rtf;
+
+std::string formatting_options::get_par_str() const
+{
+ std::string style;
+ switch (papAlign)
+ {
+ case formatting_options::align_right:
+ style+="text-align:right;";
+ break;
+ case formatting_options::align_center:
+ style+="text-align:center;";
+ break;
+ case formatting_options::align_justify:
+ style+="text-align:justify;";
+ default: break;
+ }
+ if (papFirst!=0)
+ {
+ style+="text-indent:";
+ style+=from_int(papFirst);
+ style+="pt;";
+ }
+ if (papLeft!=0)
+ {
+ style+="margin-left:";
+ style+=from_int(papLeft);
+ style+="pt;";
+ }
+ if (papRight!=0)
+ {
+ style+="margin-right:";
+ style+=from_int(papRight);
+ style+="pt;";
+ }
+ if (papBefore!=0)
+ {
+ style+="margin-top:";
+ style+=from_int(papBefore);
+ style+="pt;";
+ }
+ if (papAfter!=0)
+ {
+ style+="margin-bottom:";
+ style+=from_int(papAfter);
+ style+="pt;";
+ }
+ if (style.empty())
+ return std::string("<p>");
+ else
+ {
+ style.insert(0, "<p style=\"");
+ return style+"\">";
+ }
+}
+
+std::string formatter::format(const formatting_options &_opt)
+{
+ formatting_options last_opt, opt(_opt);
+ std::string result;
+ if (!opt_stack.empty())
+ {
+ int cnt=0;
+ fo_deque::reverse_iterator i;
+ for (i=opt_stack.rbegin(); i!=opt_stack.rend(); ++i)
+ {
+ if (*i==opt)
+ break;
+ ++cnt;
+ }
+ if (cnt==0)
+ return "";
+ if (i!=opt_stack.rend())
+ {
+ while (cnt--)
+ {
+ result+="</span>";
+ opt_stack.pop_back();
+ }
+ return result;
+ }
+ last_opt=opt_stack.back();
+ }
+ if (last_opt.chpVAlign!=formatting_options::va_normal
+ && last_opt.chpVAlign!=opt.chpVAlign)
+ {
+ int cnt=0;
+ fo_deque::reverse_iterator i;
+ for (i=opt_stack.rbegin(); i!=opt_stack.rend(); ++i)
+ {
+ if (i->chpVAlign==formatting_options::va_normal)
+ break;
+ ++cnt;
+ }
+ while (cnt--)
+ {
+ result+="</span>";
+ opt_stack.pop_back();
+ }
+ last_opt=opt_stack.empty()?formatting_options():opt_stack.back();
+ }
+ std::string style;
+ if (opt.chpBold!=last_opt.chpBold)
+ {
+ style+="font-weight:";
+ style+=opt.chpBold?"bold":"normal";
+ style+=";";
+ }
+ if (opt.chpItalic!=last_opt.chpItalic)
+ {
+ style+="font-style:";
+ style+=opt.chpItalic?"italic":"normal";
+ style+=";";
+ }
+ if (opt.chpUnderline!=last_opt.chpUnderline)
+ {
+ style+="text-decoration:";
+ style+=opt.chpUnderline?"underline":"none";
+ style+=";";
+ }
+ if (opt.chpVAlign!=formatting_options::va_normal)
+ opt.chpFontSize=(int)(0.7*(opt.chpFontSize?opt.chpFontSize:24));
+ if (opt.chpFontSize!=last_opt.chpFontSize)
+ {
+ style+="font-size:";
+ style+=from_int(opt.chpFontSize/2);
+ style+="pt;";
+ }
+ if (opt.chpVAlign!=last_opt.chpVAlign)
+ {
+ style+="vertical-align:";
+ style+=opt.chpVAlign==formatting_options::va_sub?"sub":"super";
+ style+=";";
+ }
+ if (opt.chpFColor!=last_opt.chpFColor)
+ {
+ style+="color:";
+ style+=opt.chpFColor.r>0?"#"+hex(opt.chpFColor.r&0xFF)
+ +hex(opt.chpFColor.g&0xFF)
+ +hex(opt.chpFColor.b&0xFF)
+ :"WindowText";
+ style+=";";
+ }
+ if (opt.chpBColor!=last_opt.chpBColor)
+ {
+ style+="background-color:";
+ style+=opt.chpBColor.r>0?"#"+hex(opt.chpBColor.r&0xFF)
+ +hex(opt.chpBColor.g&0xFF)
+ +hex(opt.chpBColor.b&0xFF)
+ :"Window";
+ style+=";";
+ }
+ if (opt.chpHighlight!=last_opt.chpHighlight)
+ {
+ style+="background-color:";
+ switch (opt.chpHighlight)
+ {
+ case 0: style+="Window"; break;
+ case 1: style+="black"; break;
+ case 2: style+="blue"; break;
+ case 3: style+="aqua"; break;
+ case 4: style+="lime"; break;
+ case 5: style+="fuchsia"; break;
+ case 6: style+="red"; break;
+ case 7: style+="yellow"; break;
+ case 9: style+="navy"; break;
+ case 10: style+="teal"; break;
+ case 11: style+="green"; break;
+ case 12: style+="purple"; break;
+ case 13: style+="maroon"; break;
+ case 14: style+="olive"; break;
+ case 15: style+="gray"; break;
+ case 16: style+="silver"; break;
+ }
+ style+=";";
+ }
+ if (opt.chpFont!=last_opt.chpFont)
+ {
+ style+="font-family:'";
+ style+=opt.chpFont.name.empty()?"serif":opt.chpFont.name;
+ style+="'";
+ switch (opt.chpFont.family)
+ {
+ case font::ff_serif: style+=", serif"; break;
+ case font::ff_sans_serif: style+=", sans-serif"; break;
+ case font::ff_cursive: style+=", cursive"; break;
+ case font::ff_fantasy: style+=", fantasy"; break;
+ case font::ff_monospace: style+=", monospace"; break;
+ default: break;
+ }
+ style+=";";
+ }
+ opt_stack.push_back(opt);
+ return result+"<span style=\""+style+"\">";
+}
+
+std::string formatter::close()
+{
+ std::string result;
+ for (fo_deque::iterator i=opt_stack.begin(); i!=opt_stack.end(); ++i)
+ result+="</span>";
+ return result;
+}
diff --git a/src/rtf2html/fmt_opts.h b/src/rtf2html/fmt_opts.h
new file mode 100644
index 0000000..6845d60
--- /dev/null
+++ b/src/rtf2html/fmt_opts.h
@@ -0,0 +1,154 @@
+/* This is RTF to HTML converter, implemented as a text filter, generally.
+ Copyright (C) 2003 Valentin Lavrinenko, [email protected]
+
+ available at http://rtf2html.sf.net
+
+ Original available under the terms of the GNU LGPL2, and according
+ to those terms, relicensed under the GNU GPL2 for inclusion in Tellico */
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#ifndef __FMT_OPTS_H__
+#define __FMT_OPTS_H__
+
+#include "common.h"
+#include <stack>
+#include <vector>
+#include <deque>
+#include <map>
+
+namespace rtf {
+
+struct color {
+ int r, g, b;
+ color() : r(-1), g(-1), b(-1) {}
+ bool operator==(const color &clr)
+ {
+ return r==clr.r && g==clr.g && b==clr.b;
+ }
+ bool operator!=(const color &clr)
+ {
+ return !(*this==clr);
+ }
+ color &operator=(const color &clr)
+ {
+ r=clr.r; g=clr.g; b=clr.b;
+ return *this;
+ }
+};
+
+typedef std::vector<color> colorvect;
+
+struct font {
+ enum font_family {ff_none, ff_serif, ff_sans_serif, ff_cursive,
+ ff_fantasy, ff_monospace};
+ font_family family;
+ std::string name;
+ int pitch;
+ int charset;
+ font() : family(ff_none), name(), pitch(0), charset(0) {}
+ bool operator==(const font &f)
+ {
+ return family==f.family && name==f.name;
+ }
+ bool operator!=(const font &f)
+ {
+ return !(*this==f);
+ }
+ font &operator=(const font &f)
+ {
+ family=f.family; name=f.name; pitch=f.pitch; charset=f.charset;
+ return *this;
+ }
+};
+
+typedef std::map<int, font> fontmap;
+
+struct formatting_options
+{
+ enum halign {align_left, align_right, align_center, align_justify, align_error};
+ enum valign {va_normal, va_sub, va_sup};
+ bool chpBold, chpItalic, chpUnderline;
+ valign chpVAlign;
+ int chpFontSize, chpHighlight;
+ color chpFColor, chpBColor;
+ font chpFont;
+ int papLeft, papRight, papFirst;
+ int papBefore, papAfter;
+ halign papAlign;
+ bool papInTbl;
+ formatting_options()
+ {
+ chpBold=chpItalic=chpUnderline=false;
+ chpVAlign=va_normal;
+ chpFontSize=chpHighlight=0;
+ papLeft=papRight=papFirst=papBefore=papAfter=0;
+ papAlign=align_left;
+ papInTbl=false;
+ }
+ bool operator==(const formatting_options &opt) // tests only for character options
+ {
+ return chpBold==opt.chpBold && chpItalic==opt.chpItalic
+ && chpUnderline==opt.chpUnderline && chpVAlign==opt.chpVAlign
+ && chpFontSize==opt.chpFontSize
+ && chpFColor==opt.chpFColor && chpBColor==opt.chpBColor
+ && chpHighlight==opt.chpHighlight && chpFont==opt.chpFont;
+ }
+ bool operator!=(const formatting_options &opt) // tests only for character options
+ {
+ return !(*this==opt);
+ }
+ formatting_options &operator=(const formatting_options &opt)
+ {
+ chpBold=opt.chpBold; chpItalic=opt.chpItalic;
+ chpUnderline=opt.chpUnderline; chpVAlign=opt.chpVAlign;
+ chpFontSize=opt.chpFontSize;
+ chpFColor=opt.chpFColor; chpBColor=opt.chpBColor;
+ chpHighlight=opt.chpHighlight; chpFont=opt.chpFont;
+ papLeft=opt.papLeft; papRight=opt.papRight;
+ papFirst=opt.papFirst; papBefore=opt.papBefore; papAfter=opt.papAfter;
+ papAlign=opt.papAlign; papInTbl=opt.papInTbl;
+ return *this;
+ }
+ std::string get_par_str() const;
+};
+
+typedef std::stack<formatting_options> fo_stack;
+
+typedef std::deque<formatting_options> fo_deque;
+
+class formatter {
+ private:
+ fo_deque opt_stack;
+ public:
+ std::string format(const formatting_options &opt);
+ std::string close();
+ void clear() { opt_stack.clear(); }
+};
+
+class html_text {
+ private:
+ const formatting_options &opt;
+ formatter fmt;
+ std::string text;
+ public:
+ html_text(const formatting_options &_opt) : opt(_opt) {}
+ const std::string &str() { return text; }
+ template <class T> void write(T s)
+ {
+ text+=fmt.format(opt)+s;
+ }
+ std::string close() { return fmt.close(); }
+// void write(char c) { write(std::string()+c); }
+ void clear() { text.clear(); fmt.clear(); }
+};
+
+}
+#endif
+
diff --git a/src/rtf2html/rtf2html.cpp b/src/rtf2html/rtf2html.cpp
new file mode 100644
index 0000000..4f29fe7
--- /dev/null
+++ b/src/rtf2html/rtf2html.cpp
@@ -0,0 +1,531 @@
+/* This is RTF to HTML converter, implemented as a text filter, generally.
+ Copyright (C) 2003 Valentin Lavrinenko, [email protected]
+
+ available at http://rtf2html.sf.net
+
+ Original available under the terms of the GNU LGPL2, and according
+ to those terms, relicensed under the GNU GPL2 for inclusion in Tellico */
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#include "rtf2html.h"
+#include "rtf_table.h"
+#include "rtf_tools.h"
+#include "rtf_keyword.h"
+#include "fmt_opts.h"
+
+#include <cstdlib>
+#include <stdexcept>
+#include <fstream>
+#include <iostream>
+#include <string>
+
+using Tellico::RTF2HTML;
+using namespace rtf;
+
+RTF2HTML::RTF2HTML(const QString& text) : m_text(text) {
+}
+
+QString RTF2HTML::toHTML() const {
+ std::string str_in = m_text;
+
+ std::string::iterator buf_in=str_in.begin(), buf_in_end=str_in.end();
+ colorvect colortbl;
+ fontmap fonttbl;
+ std::string title;
+
+ bool bAsterisk=false;
+ fo_stack foStack;
+ formatting_options cur_options;
+ std::string html;
+ html_text par_html(cur_options);
+
+ /* CellDefs in rtf are really queer. We'll keep a list of them in main()
+ and will give an iterator into this list to a row */
+ table_cell_defs_list CellDefsList;
+ table_cell_defs_list::iterator CurCellDefs;
+ table_cell_def* tcdCurCellDef=new table_cell_def;
+ table_cell* tcCurCell=new table_cell;
+ table_row* trCurRow=new table_row;
+ table* tblCurTable=new table;
+ int iLastRowLeft=0, iLastRowHeight=0;
+ std::string t_str;
+
+ bool bInTable=false;
+ int iDocWidth=12240;
+ int iMarginLeft=1800;
+ while(buf_in!=buf_in_end)
+ {
+ switch (*buf_in)
+ {
+ case '\\':
+ {
+ rtf_keyword kw(++buf_in);
+ if (kw.is_control_char())
+ switch (kw.control_char())
+ {
+ case '\\': case '{': case '}':
+ par_html.write(kw.control_char());
+ break;
+ case '\'':
+ {
+ std::string stmp(1,*buf_in++);
+ stmp+=*buf_in++;
+ int code=std::strtol(stmp.c_str(), NULL, 16);
+ switch (code)
+ {
+ case 167:
+ par_html.write("&bull;");
+ break;
+ case 188:
+ par_html.write("&hellip;");
+ break;
+ default:
+ par_html.write((char)code);
+ }
+ break;
+ }
+ case '*':
+ bAsterisk=true;
+ break;
+ case '~':
+ par_html.write("&nbsp;");
+ break;
+ case '\n':
+ par_html.write("<br><br>");
+ break;
+ }
+ else //kw.is_control_char
+ if (bAsterisk)
+ {
+ bAsterisk=false;
+ skip_group(buf_in);
+ }
+ else
+ {
+ switch (kw.keyword())
+ {
+ case rtf_keyword::rkw_filetbl:
+ case rtf_keyword::rkw_stylesheet:
+ case rtf_keyword::rkw_header:
+ case rtf_keyword::rkw_footer: case rtf_keyword::rkw_headerf:
+ case rtf_keyword::rkw_footerf: case rtf_keyword::rkw_pict:
+ case rtf_keyword::rkw_object:
+ // we'll skip such groups
+ skip_group(buf_in);
+ break;
+ // document title
+ case rtf_keyword::rkw_info:
+ {
+ int depth=1;
+ bool in_title=false;
+ while (depth>0)
+ {
+// std::cout<<std::string(buf_in).substr(0,20)<<"\t"<<depth<<std::endl;
+ switch (*buf_in)
+ {
+ case '\\':
+ {
+ rtf_keyword kw(++buf_in);
+ if (kw.keyword()==rtf_keyword::rkw_title)
+ in_title=true;
+ break;
+ }
+ case '{': ++depth; ++buf_in; break;
+ case '}': --depth; ++buf_in; in_title=false; break;
+ default: if (in_title) title+=*buf_in; ++buf_in; break;
+ }
+ }
+ break;
+ }
+ // color table
+ case rtf_keyword::rkw_colortbl:
+ {
+ color clr;
+ while (*buf_in!='}')
+ {
+ switch (*buf_in)
+ {
+ case '\\':
+ {
+ rtf_keyword kw(++buf_in);
+ switch (kw.keyword())
+ {
+ case rtf_keyword::rkw_red:
+ clr.r=kw.parameter();
+ break;
+ case rtf_keyword::rkw_green:
+ clr.g=kw.parameter();
+ break;
+ case rtf_keyword::rkw_blue:
+ clr.b=kw.parameter();
+ break;
+ default: break;
+ }
+ break;
+ }
+ case ';':
+ colortbl.push_back(clr);
+ ++buf_in;
+ break;
+ default:
+ ++buf_in;
+ break;
+ }
+ }
+ ++buf_in;
+ break;
+ }
+ // font table
+ case rtf_keyword::rkw_fonttbl:
+ {
+ font fnt;
+ int font_num;
+ bool full_name=false;
+ bool in_font=false;
+ while (! (*buf_in=='}' && !in_font))
+ {
+ switch (*buf_in)
+ {
+ case '\\':
+ {
+ rtf_keyword kw(++buf_in);
+ if (kw.is_control_char() && kw.control_char()=='*')
+ skip_group(buf_in);
+ else
+ switch (kw.keyword())
+ {
+ case rtf_keyword::rkw_f:
+ font_num=kw.parameter();
+ break;
+ case rtf_keyword::rkw_fprq:
+ fnt.pitch=kw.parameter();
+ break;
+ case rtf_keyword::rkw_fcharset:
+ fnt.charset=kw.parameter();
+ break;
+ case rtf_keyword::rkw_fnil:
+ fnt.family=font::ff_none;
+ break;
+ case rtf_keyword::rkw_froman:
+ fnt.family=font::ff_serif;
+ break;
+ case rtf_keyword::rkw_fswiss:
+ fnt.family=font::ff_sans_serif;
+ break;
+ case rtf_keyword::rkw_fmodern:
+ fnt.family=font::ff_monospace;
+ break;
+ case rtf_keyword::rkw_fscript:
+ fnt.family=font::ff_cursive;
+ break;
+ case rtf_keyword::rkw_fdecor:
+ fnt.family=font::ff_fantasy;
+ break;
+ default: break;
+ }
+ break;
+ }
+ case '{':
+ in_font=true;
+ ++buf_in;
+ break;
+ case '}':
+ in_font=false;
+ fonttbl.insert(std::make_pair(font_num, fnt));
+ fnt=font();
+ full_name=false;
+ ++buf_in;
+ break;
+ case ';':
+ full_name=true;
+ ++buf_in;
+ break;
+ default:
+ if (!full_name && in_font)
+ fnt.name+=*buf_in;
+ ++buf_in;
+ break;
+ }
+ }
+ ++buf_in;
+ break;
+ }
+ // special characters
+ case rtf_keyword::rkw_line: case rtf_keyword::rkw_softline:
+ par_html.write("<br>");
+ break;
+ case rtf_keyword::rkw_tab:
+ par_html.write("&nbsp;&nbsp;"); // maybe, this can be done better
+ break;
+ case rtf_keyword::rkw_enspace: case rtf_keyword::rkw_emspace:
+ par_html.write("&nbsp;");
+ break;
+ case rtf_keyword::rkw_qmspace:
+ par_html.write("&thinsp;");
+ break;
+ case rtf_keyword::rkw_endash:
+ par_html.write("&ndash;");
+ break;
+ case rtf_keyword::rkw_emdash:
+ par_html.write("&mdash;");
+ break;
+ case rtf_keyword::rkw_bullet:
+ par_html.write("&bull;");
+ break;
+ case rtf_keyword::rkw_lquote:
+ par_html.write("&lsquo;");
+ break;
+ case rtf_keyword::rkw_rquote:
+ par_html.write("&rsquo;");
+ break;
+ case rtf_keyword::rkw_ldblquote:
+ par_html.write("&ldquo;");
+ break;
+ case rtf_keyword::rkw_rdblquote:
+ par_html.write("&rdquo;");
+ break;
+ // paragraph formatting
+ case rtf_keyword::rkw_ql:
+ cur_options.papAlign=formatting_options::align_left;
+ break;
+ case rtf_keyword::rkw_qr:
+ cur_options.papAlign=formatting_options::align_right;
+ break;
+ case rtf_keyword::rkw_qc:
+ cur_options.papAlign=formatting_options::align_center;
+ break;
+ case rtf_keyword::rkw_qj:
+ cur_options.papAlign=formatting_options::align_justify;
+ break;
+ case rtf_keyword::rkw_fi:
+ cur_options.papFirst=(int)rint(kw.parameter()/20);
+ break;
+ case rtf_keyword::rkw_li:
+ cur_options.papLeft=(int)rint(kw.parameter()/20);
+ break;
+ case rtf_keyword::rkw_ri:
+ cur_options.papRight=(int)rint(kw.parameter()/20);
+ break;
+ case rtf_keyword::rkw_sb:
+ cur_options.papBefore=(int)rint(kw.parameter()/20);
+ break;
+ case rtf_keyword::rkw_sa:
+ cur_options.papAfter=(int)rint(kw.parameter()/20);
+ break;
+ case rtf_keyword::rkw_pard:
+ cur_options.papBefore=cur_options.papAfter=0;
+ cur_options.papLeft=cur_options.papRight=0;
+ cur_options.papFirst=0;
+ cur_options.papAlign=formatting_options::align_left;
+ cur_options.papInTbl=false;
+ break;
+ case rtf_keyword::rkw_par:
+ case rtf_keyword::rkw_sect:
+ t_str=cur_options.get_par_str()+par_html.str()
+ +"&nbsp;"+par_html.close()+"</p>\n";
+ if (!bInTable)
+ {
+ html+=t_str;
+ }
+ else
+ {
+ if (cur_options.papInTbl)
+ {
+ tcCurCell->Text+=t_str;
+ }
+ else
+ {
+ html+=tblCurTable->make()+t_str;
+ bInTable=false;
+ tblCurTable=new table;
+ }
+ }
+ par_html.clear();
+ break;
+ // character formatting
+ case rtf_keyword::rkw_super:
+ cur_options.chpVAlign=
+ kw.parameter()==0?formatting_options::va_normal
+ :formatting_options::va_sup;
+ break;
+ case rtf_keyword::rkw_sub:
+ cur_options.chpVAlign=
+ kw.parameter()==0?formatting_options::va_normal
+ :formatting_options::va_sub;
+ break;
+ case rtf_keyword::rkw_b:
+ cur_options.chpBold=!(kw.parameter()==0);
+ break;
+ case rtf_keyword::rkw_i:
+ cur_options.chpItalic=!(kw.parameter()==0);
+ break;
+ case rtf_keyword::rkw_ul:
+ cur_options.chpUnderline=!(kw.parameter()==0);
+ break;
+ case rtf_keyword::rkw_ulnone:
+ cur_options.chpUnderline=false;
+ break;
+ case rtf_keyword::rkw_fs:
+ cur_options.chpFontSize=kw.parameter();
+ break;
+ case rtf_keyword::rkw_cf:
+ cur_options.chpFColor=colortbl[kw.parameter()];
+ break;
+ case rtf_keyword::rkw_cb:
+ cur_options.chpBColor=colortbl[kw.parameter()];
+ break;
+ case rtf_keyword::rkw_highlight:
+ cur_options.chpHighlight=kw.parameter();
+ break;
+ case rtf_keyword::rkw_f:
+ cur_options.chpFont=fonttbl[kw.parameter()];
+ break;
+ case rtf_keyword::rkw_plain:
+ cur_options.chpBold=cur_options.chpItalic
+ =cur_options.chpUnderline=false;
+ cur_options.chpVAlign=formatting_options::va_normal;
+ cur_options.chpFontSize=cur_options.chpHighlight=0;
+ cur_options.chpFColor=cur_options.chpBColor=color();
+ cur_options.chpFont=font();
+ break;
+ // table formatting
+ case rtf_keyword::rkw_intbl:
+ cur_options.papInTbl=true;
+ break;
+ case rtf_keyword::rkw_trowd:
+ CurCellDefs=CellDefsList.insert(CellDefsList.end(),
+ table_cell_defs());
+ case rtf_keyword::rkw_row:
+ if (!trCurRow->Cells.empty())
+ {
+ trCurRow->CellDefs=CurCellDefs;
+ if (trCurRow->Left==-1000)
+ trCurRow->Left=iLastRowLeft;
+ if (trCurRow->Height==-1000)
+ trCurRow->Height=iLastRowHeight;
+ tblCurTable->push_back(trCurRow);
+ trCurRow=new table_row;
+ }
+ bInTable=true;
+ break;
+ case rtf_keyword::rkw_cell:
+ t_str=cur_options.get_par_str()+par_html.str()
+ +"&nbsp;"+par_html.close()+"</p>\n";
+ tcCurCell->Text+=t_str;
+ par_html.clear();
+ trCurRow->Cells.push_back(tcCurCell);
+ tcCurCell=new table_cell;
+ break;
+ case rtf_keyword::rkw_cellx:
+ tcdCurCellDef->Right=kw.parameter();
+ CurCellDefs->push_back(tcdCurCellDef);
+ tcdCurCellDef=new table_cell_def;
+ break;
+ case rtf_keyword::rkw_trleft:
+ trCurRow->Left=kw.parameter();
+ iLastRowLeft=kw.parameter();
+ break;
+ case rtf_keyword::rkw_trrh:
+ trCurRow->Height=kw.parameter();
+ iLastRowHeight=kw.parameter();
+ break;
+ case rtf_keyword::rkw_clvmgf:
+ tcdCurCellDef->FirstMerged=true;
+ break;
+ case rtf_keyword::rkw_clvmrg:
+ tcdCurCellDef->Merged=true;
+ break;
+ case rtf_keyword::rkw_clbrdrb:
+ tcdCurCellDef->BorderBottom=true;
+ tcdCurCellDef->ActiveBorder=&(tcdCurCellDef->BorderBottom);
+ break;
+ case rtf_keyword::rkw_clbrdrt:
+ tcdCurCellDef->BorderTop=true;
+ tcdCurCellDef->ActiveBorder=&(tcdCurCellDef->BorderTop);
+ break;
+ case rtf_keyword::rkw_clbrdrl:
+ tcdCurCellDef->BorderLeft=true;
+ tcdCurCellDef->ActiveBorder=&(tcdCurCellDef->BorderLeft);
+ break;
+ case rtf_keyword::rkw_clbrdrr:
+ tcdCurCellDef->BorderRight=true;
+ tcdCurCellDef->ActiveBorder=&(tcdCurCellDef->BorderRight);
+ break;
+ case rtf_keyword::rkw_brdrnone:
+ if (tcdCurCellDef->ActiveBorder!=NULL)
+ {
+ *(tcdCurCellDef->ActiveBorder)=false;
+ }
+ break;
+ case rtf_keyword::rkw_clvertalt:
+ tcdCurCellDef->VAlign=table_cell_def::valign_top;
+ break;
+ case rtf_keyword::rkw_clvertalc:
+ tcdCurCellDef->VAlign=table_cell_def::valign_center;
+ break;
+ case rtf_keyword::rkw_clvertalb:
+ tcdCurCellDef->VAlign=table_cell_def::valign_bottom;
+ break;
+ // page formatting
+ case rtf_keyword::rkw_paperw:
+ iDocWidth=kw.parameter();
+ break;
+ case rtf_keyword::rkw_margl:
+ iMarginLeft=kw.parameter();
+ break;
+ default: break;
+ }
+ }
+ break;
+ }
+ case '{':
+ // perform group opening actions here
+ foStack.push(cur_options);
+ ++buf_in;
+ break;
+ case '}':
+ // perform group closing actions here
+ cur_options=foStack.top();
+ foStack.pop();
+ ++buf_in;
+ break;
+ case 13:
+ case 10:
+ ++buf_in;
+ break;
+ case '<':
+ par_html.write("&lt;");
+ ++buf_in;
+ break;
+ case '>':
+ par_html.write("&gt;");
+ ++buf_in;
+ break;
+/* case ' ':
+ par_html.write("&ensp;");
+ ++buf_in;
+ break;*/
+ default:
+ par_html.write(*buf_in++);
+ }
+ }
+
+ t_str=cur_options.get_par_str()+par_html.str()
+ +"&nbsp;"+par_html.close()+"</p>\n";
+ html+=t_str;
+
+ delete tcCurCell;
+ delete trCurRow;
+ delete tblCurTable;
+ delete tcdCurCellDef;
+
+ return html;
+}
+
diff --git a/src/rtf2html/rtf2html.h b/src/rtf2html/rtf2html.h
new file mode 100644
index 0000000..a4e1d2f
--- /dev/null
+++ b/src/rtf2html/rtf2html.h
@@ -0,0 +1,28 @@
+/***************************************************************************
+ copyright : (C) 2007 by Robby Stephenson
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#include <qstring.h>
+
+namespace Tellico {
+
+class RTF2HTML {
+public:
+ RTF2HTML(const QString& text);
+
+ QString toHTML() const;
+
+private:
+ QString m_text;
+};
+
+}
diff --git a/src/rtf2html/rtf_keyword.cpp b/src/rtf2html/rtf_keyword.cpp
new file mode 100644
index 0000000..ee4774c
--- /dev/null
+++ b/src/rtf2html/rtf_keyword.cpp
@@ -0,0 +1,107 @@
+/* This is RTF to HTML converter, implemented as a text filter, generally.
+ Copyright (C) 2003 Valentin Lavrinenko, [email protected]
+
+ available at http://rtf2html.sf.net
+
+ Original available under the terms of the GNU LGPL2, and according
+ to those terms, relicensed under the GNU GPL2 for inclusion in Tellico */
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#include "rtf_keyword.h"
+
+using namespace rtf;
+
+rtf_keyword::keyword_map::keyword_map() : base_class()
+{
+ insert(value_type("b", rkw_b));
+ insert(value_type("bin", rkw_bin));
+ insert(value_type("blue", rkw_blue));
+ insert(value_type("brdrnone", rkw_brdrnone));
+ insert(value_type("bullet", rkw_bullet));
+ insert(value_type("cb", rkw_cb));
+ insert(value_type("cell", rkw_cell));
+ insert(value_type("cellx", rkw_cellx));
+ insert(value_type("cf", rkw_cf));
+ insert(value_type("clbrdrb", rkw_clbrdrb));
+ insert(value_type("clbrdrl", rkw_clbrdrl));
+ insert(value_type("clbrdrr", rkw_clbrdrr));
+ insert(value_type("clbrdrt", rkw_clbrdrt));
+ insert(value_type("clvertalb", rkw_clvertalb));
+ insert(value_type("clvertalc", rkw_clvertalc));
+ insert(value_type("clvertalt", rkw_clvertalt));
+ insert(value_type("clvmgf", rkw_clvmgf));
+ insert(value_type("clvmrg", rkw_clvmrg));
+ insert(value_type("colortbl", rkw_colortbl));
+ insert(value_type("emdash", rkw_emdash));
+ insert(value_type("emspace", rkw_emspace));
+ insert(value_type("endash", rkw_endash));
+ insert(value_type("enspace", rkw_enspace));
+ insert(value_type("f", rkw_f));
+ insert(value_type("fprq", rkw_fprq));
+ insert(value_type("fcharset", rkw_fcharset));
+ insert(value_type("fnil", rkw_fnil));
+ insert(value_type("froman", rkw_froman));
+ insert(value_type("fswiss", rkw_fswiss));
+ insert(value_type("fmodern", rkw_fmodern));
+ insert(value_type("fscript", rkw_fscript));
+ insert(value_type("fdecor", rkw_fdecor));
+ insert(value_type("ftech", rkw_ftech));
+ insert(value_type("fbidi", rkw_fbidi));
+ insert(value_type("field", rkw_field));
+ insert(value_type("filetbl", rkw_filetbl));
+ insert(value_type("fldrslt", rkw_fldrslt));
+ insert(value_type("fonttbl", rkw_fonttbl));
+ insert(value_type("footer", rkw_footer));
+ insert(value_type("footerf", rkw_footerf));
+ insert(value_type("fs", rkw_fs));
+ insert(value_type("green", rkw_green));
+ insert(value_type("header", rkw_header));
+ insert(value_type("headerf", rkw_headerf));
+ insert(value_type("highlight", rkw_highlight));
+ insert(value_type("i", rkw_i));
+ insert(value_type("info", rkw_info));
+ insert(value_type("intbl", rkw_intbl));
+ insert(value_type("ldblquote", rkw_ldblquote));
+ insert(value_type("li", rkw_li));
+ insert(value_type("line", rkw_line));
+ insert(value_type("lquote", rkw_lquote));
+ insert(value_type("margl", rkw_margl));
+ insert(value_type("object", rkw_object));
+ insert(value_type("paperw", rkw_paperw));
+ insert(value_type("par", rkw_par));
+ insert(value_type("pard", rkw_pard));
+ insert(value_type("pict", rkw_pict));
+ insert(value_type("plain", rkw_plain));
+ insert(value_type("qc", rkw_qc));
+ insert(value_type("qj", rkw_qj));
+ insert(value_type("ql", rkw_ql));
+ insert(value_type("qr", rkw_qr));
+ insert(value_type("rdblquote", rkw_rdblquote));
+ insert(value_type("red", rkw_red));
+ insert(value_type("ri", rkw_ri));
+ insert(value_type("row", rkw_row));
+ insert(value_type("rquote", rkw_rquote));
+ insert(value_type("sa", rkw_sa));
+ insert(value_type("sb", rkw_sb));
+ insert(value_type("sect", rkw_sect));
+ insert(value_type("softline", rkw_softline));
+ insert(value_type("stylesheet", rkw_stylesheet));
+ insert(value_type("sub", rkw_sub));
+ insert(value_type("super", rkw_super));
+ insert(value_type("tab", rkw_tab));
+ insert(value_type("title", rkw_title));
+ insert(value_type("trleft", rkw_trleft));
+ insert(value_type("trowd", rkw_trowd));
+ insert(value_type("trrh", rkw_trrh));
+ insert(value_type("ul", rkw_ul));
+ insert(value_type("ulnone", rkw_ulnone));
+}
+
+rtf_keyword::keyword_map rtf_keyword::keymap;
diff --git a/src/rtf2html/rtf_keyword.h b/src/rtf2html/rtf_keyword.h
new file mode 100644
index 0000000..c510ea0
--- /dev/null
+++ b/src/rtf2html/rtf_keyword.h
@@ -0,0 +1 @@
+/* This is RTF to HTML converter, implemented as a text filter, generally. Copyright (C) 2003 Valentin Lavrinenko, [email protected] available at http://rtf2html.sf.net Original available under the terms of the GNU LGPL2, and according to those terms, relicensed under the GNU GPL2 for inclusion in Tellico */ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of version 2 of the GNU General Public License as * * published by the Free Software Foundation; * * * ***************************************************************************/ #ifndef __RTF_KEYWORD_H__ #define __RTF_KEYWORD_H__ #include <string> #include <map> #include <ctype.h> #include <cstdlib> namespace rtf { class rtf_keyword{ public: enum keyword_type {rkw_unknown, rkw_b, rkw_bin, rkw_blue, rkw_brdrnone, rkw_bullet, rkw_cb, rkw_cell, rkw_cellx, rkw_cf, rkw_clbrdrb, rkw_clbrdrl, rkw_clbrdrr, rkw_clbrdrt, rkw_clvertalb, rkw_clvertalc, rkw_clvertalt, rkw_clvmgf, rkw_clvmrg, rkw_colortbl, rkw_emdash, rkw_emspace, rkw_endash, rkw_enspace, rkw_fi, rkw_field, rkw_filetbl, rkw_f, rkw_fprq, rkw_fcharset, rkw_fnil, rkw_froman, rkw_fswiss, rkw_fmodern, rkw_fscript, rkw_fdecor, rkw_ftech, rkw_fbidi, rkw_fldrslt, rkw_fonttbl, rkw_footer, rkw_footerf, rkw_fs, rkw_green, rkw_header, rkw_headerf, rkw_highlight, rkw_i, rkw_info, rkw_intbl, rkw_ldblquote, rkw_li, rkw_line, rkw_lquote, rkw_margl, rkw_object, rkw_paperw, rkw_par, rkw_pard, rkw_pict, rkw_plain, rkw_qc, rkw_qj, rkw_ql, rkw_qmspace, rkw_qr, rkw_rdblquote, rkw_red, rkw_ri, rkw_row, rkw_rquote, rkw_sa, rkw_sb, rkw_sect, rkw_softline, rkw_stylesheet, rkw_sub, rkw_super, rkw_tab, rkw_title, rkw_trleft, rkw_trowd, rkw_trrh, rkw_ul, rkw_ulnone }; private: class keyword_map : public std::map<std::string, keyword_type> { private: typedef std::map<std::string, keyword_type> base_class; public: keyword_map(); }; private: static keyword_map keymap; std::string s_keyword; keyword_type e_keyword; int param; char ctrl_chr; bool is_ctrl_chr; public: // iter must point after the backslash starting the keyword. We don't check it. // after construction, iter points at the char following the keyword template <class InputIter> explicit rtf_keyword(InputIter &iter); bool is_control_char() const { return is_ctrl_chr; } const std::string &keyword_str() const { return s_keyword; } keyword_type keyword() const { return e_keyword; } int parameter() const { return param; } char control_char() const { return ctrl_chr; } }; template <class InputIter> rtf_keyword::rtf_keyword(InputIter &iter) { char curchar=*iter; is_ctrl_chr=!isalpha(curchar); if (is_ctrl_chr) { ctrl_chr=curchar; ++iter; } else { do s_keyword+=curchar; while (isalpha(curchar=*++iter)); std::string param_str; while (isdigit(curchar)||curchar=='-') { param_str+=curchar; curchar=*++iter; } if (param_str.empty()) param=-1; else param=std::atoi(param_str.c_str()); if (curchar==' ') ++iter; keyword_map::iterator kw_pos=keymap.find(s_keyword); if (kw_pos==keymap.end()) e_keyword=rkw_unknown; else e_keyword=kw_pos->second; } } } #endif \ No newline at end of file
diff --git a/src/rtf2html/rtf_table.cpp b/src/rtf2html/rtf_table.cpp
new file mode 100644
index 0000000..b5cdf7b
--- /dev/null
+++ b/src/rtf2html/rtf_table.cpp
@@ -0,0 +1,235 @@
+/* This is RTF to HTML converter, implemented as a text filter, generally.
+ Copyright (C) 2003 Valentin Lavrinenko, [email protected]
+
+ available at http://rtf2html.sf.net
+
+ Original available under the terms of the GNU LGPL2, and according
+ to those terms, relicensed under the GNU GPL2 for inclusion in Tellico */
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#include "rtf_table.h"
+#include <set>
+#include <ostream>
+#include <iostream>
+#include <stdexcept>
+#include <functional>
+#include <algorithm>
+
+using namespace rtf;
+
+typedef std::set<int> intset;
+
+template <class T, class C>
+std::basic_ostream<C>& operator<<(std::basic_ostream<C> &dest, std::set<T> &s)
+{
+ for (typename std::set<T>::iterator i=s.begin(); i!=s.end(); ++i)
+ dest<<*i<<" ";
+ return dest;
+}
+
+std::string table::make()
+{
+ std::string result;
+ intset pts;
+ iterator row, span_row, row2;
+ table_cell_defs::iterator cell_def, prev_cell_def, cell_def_2;
+ table_cells::iterator cell;
+ intset::iterator pt, ptp;
+ int left, right, colspan;
+ bool btop, bbottom, bleft, bright;
+ std::string style;
+ for (row=begin(); row!=end();)
+ {
+ if ((*row)->Cells.empty())
+ {
+ delete *row;
+ row=erase(row);
+ }
+ else
+ {
+ pts.insert((*row)->Left);
+ for (cell_def=(*row)->CellDefs->begin(); cell_def!=(*row)->CellDefs->end(); ++cell_def)
+ {
+ pts.insert((*cell_def)->Right);
+ }
+ ++row;
+ }
+ }
+ if (pts.empty())
+ {
+// throw std::logic_error("No CellDefs!");
+ }
+ pt=pts.begin();
+ ptp=pts.end();
+ ptp--;
+ result="<table border=0 width=";
+ result+=from_int((int)rint((*ptp-*pt)/15));
+ result+=" style=\"margin-left:";
+ result+=from_int((int)rint(*pt/15));
+ result+=";border-collapse: collapse;\">";
+ result+="<tr height=0>";
+ for (ptp=pt++=pts.begin(); pt!=pts.end(); ptp=pt++)
+ {
+ result+="<td width=";
+ result+=from_int((int)rint((*pt-*ptp)/15));
+ result+="></td>";
+ //coefficient may be different
+ }
+ result+="</tr>\n";
+
+ // first, we'll determine all the rowspans and leftsides
+ for (row=begin(); row!=end(); ++row)
+ {
+ if ((*row)->CellDefs->size()!=(*row)->Cells.size())
+// throw std::logic_error("Number of Cells and number of CellDefs are unequal!");
+ for (cell_def=(*row)->CellDefs->begin(), cell=(*row)->Cells.begin();
+ cell!=(*row)->Cells.end();
+ ++cell, prev_cell_def=cell_def++
+ )
+ {
+ if (cell_def==(*row)->CellDefs->begin())
+ (*cell_def)->Left=(*row)->Left;
+ else
+ (*cell_def)->Left=(*prev_cell_def)->Right;
+ if ((*cell_def)->FirstMerged)
+ {
+ for (span_row=row, ++span_row; span_row!=end();
+ ++span_row)
+ {
+ cell_def_2=
+ std::find_if((*span_row)->CellDefs->begin(),
+ (*span_row)->CellDefs->end(),
+ std::bind2nd(
+ std::mem_fun(&table_cell_def::right_equals),
+ (*cell_def)->Right));
+ if (cell_def_2==(*span_row)->CellDefs->end())
+ break;
+ if (!(*cell_def_2)->Merged)
+ break;
+ }
+ (*cell)->Rowspan=span_row-row;
+ }
+ }
+ }
+
+ for (row=begin(); row!=end(); ++row)
+ {
+ result+="<tr>";
+ pt=pts.find((*row)->Left);
+ if (pt==pts.end())
+// throw std::logic_error("No row.left point!");
+ if (pt!=pts.begin())
+ {
+ result+="<td colspan=";
+ result+=from_int(std::distance(pts.begin(), pt));
+ result+="></td>";
+ }
+ for (cell_def=(*row)->CellDefs->begin(), cell=(*row)->Cells.begin();
+ cell!=(*row)->Cells.end(); ++cell, ++cell_def)
+ {
+ ptp=pts.find((*cell_def)->Right);
+ if (ptp==pts.end())
+// throw std::logic_error("No celldef.right point!");
+ colspan=std::distance(pt, ptp);
+ pt=ptp;
+ if (!(*cell_def)->Merged)
+ {
+ result+="<td";
+ // analyzing borders
+ left=(*cell_def)->Left;
+ right=(*cell_def)->Right;
+ bbottom=(*cell_def)->BorderBottom;
+ btop=(*cell_def)->BorderTop;
+ bleft=(*cell_def)->BorderLeft;
+ bright=(*cell_def)->BorderRight;
+ span_row=row;
+ if ((*cell_def)->FirstMerged)
+ std::advance(span_row, (*cell)->Rowspan-1);
+ for (row2=row; row2!=span_row; ++row2)
+ {
+ cell_def_2=
+ std::find_if((*row2)->CellDefs->begin(),
+ (*row2)->CellDefs->end(),
+ std::bind2nd(
+ std::mem_fun(&table_cell_def::right_equals),
+ left));
+ if (cell_def_2!=(*row2)->CellDefs->end())
+ {
+ bleft=bleft && (*cell_def_2)->BorderRight;
+ }
+ cell_def_2=
+ std::find_if((*row2)->CellDefs->begin(),
+ (*row2)->CellDefs->end(),
+ std::bind2nd(
+ std::mem_fun(&table_cell_def::left_equals),
+ right));
+ if (cell_def_2!=(*row2)->CellDefs->end())
+ {
+ bright=bright && (*cell_def_2)->BorderLeft;
+ }
+ }
+
+ if (bbottom && btop && bleft && bright)
+ {
+ style="border:1px solid black;";
+ }
+ else
+ {
+ style="";
+ if (bbottom)
+ style+="border-bottom:1px solid black;";
+ if (btop)
+ style+="border-top:1px solid black;";
+ if (bleft)
+ style+="border-left:1px solid black;";
+ if (bright)
+ style+="border-right:1px solid black;";
+ }
+ if (!style.empty())
+ {
+ result+=" style=\"";
+ result+=style;
+ result+="\"";
+ }
+ if (colspan>1)
+ {
+ result+=" colspan=";
+ result+=from_int(colspan);
+ }
+ if ((*cell_def)->FirstMerged)
+ {
+ result+=" rowspan=";
+ result+=from_int((*cell)->Rowspan);
+ }
+
+ switch ((*cell_def)->VAlign)
+ {
+ case table_cell_def::valign_top:
+ result+=" valign=top";
+ break;
+ case table_cell_def::valign_bottom:
+ result+=" valign=bottom";
+ break;
+ default: break;
+ }
+
+ result+=">";
+ if ((*cell)->Text[0]>0)
+ result+=(*cell)->Text;
+ else
+ result+="&nbsp;";
+ result+="</td>";
+ }
+ }
+ result+="</tr>";
+ }
+ result+="</table>";
+ return result;
+}
diff --git a/src/rtf2html/rtf_table.h b/src/rtf2html/rtf_table.h
new file mode 100644
index 0000000..927cc40
--- /dev/null
+++ b/src/rtf2html/rtf_table.h
@@ -0,0 +1,90 @@
+/* This is RTF to HTML converter, implemented as a text filter, generally.
+ Copyright (C) 2003 Valentin Lavrinenko, [email protected]
+
+ available at http://rtf2html.sf.net
+
+ Original available under the terms of the GNU LGPL2, and according
+ to those terms, relicensed under the GNU GPL2 for inclusion in Tellico */
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#ifndef __RTF_H__
+#define __RTF_H__
+
+#include "common.h"
+#include <vector>
+#include <cmath>
+#include <list>
+#include <cstdlib>
+
+namespace rtf {
+
+struct table_cell
+{
+ int Rowspan;
+ std::string Text;
+ table_cell() : Rowspan(0) {}
+};
+
+struct table_cell_def
+{
+ enum valign {valign_top, valign_bottom, valign_center};
+ bool BorderTop, BorderBottom, BorderLeft, BorderRight;
+ bool *ActiveBorder;
+ int Right, Left;
+ bool Merged, FirstMerged;
+ valign VAlign;
+ table_cell_def()
+ {
+ BorderTop=BorderBottom=BorderLeft=BorderRight=Merged=FirstMerged=false;
+ ActiveBorder=NULL;
+ Right=Left=0;
+ VAlign=valign_top;
+ }
+ bool right_equals(int x) { return x==Right; }
+ bool left_equals(int x) { return x==Left; }
+};
+
+template <class T>
+class killing_ptr_vector : public std::vector<T*>
+{
+ public:
+ ~killing_ptr_vector()
+ {
+ for (typename killing_ptr_vector<T>::iterator i=this->begin(); i!=this->end(); ++i)
+ delete *i;
+ }
+};
+
+typedef killing_ptr_vector<table_cell> table_cells;
+typedef killing_ptr_vector<table_cell_def> table_cell_defs;
+
+typedef std::list<table_cell_defs> table_cell_defs_list;
+
+struct table_row
+{
+ table_cells Cells;
+ table_cell_defs_list::iterator CellDefs;
+ int Height;
+ int Left;
+ table_row() : Height(-1000), Left(-1000) {}
+};
+
+class table : public killing_ptr_vector<table_row>
+{
+ private:
+ typedef killing_ptr_vector<table_row> base_class;
+ public:
+ table() : base_class() {}
+ std::string make();
+};
+
+}
+
+#endif
diff --git a/src/rtf2html/rtf_tools.h b/src/rtf2html/rtf_tools.h
new file mode 100644
index 0000000..528549e
--- /dev/null
+++ b/src/rtf2html/rtf_tools.h
@@ -0,0 +1,65 @@
+/* This is RTF to HTML converter, implemented as a text filter, generally.
+ Copyright (C) 2003 Valentin Lavrinenko, [email protected]
+
+ available at http://rtf2html.sf.net
+
+ Original available under the terms of the GNU LGPL2, and according
+ to those terms, relicensed under the GNU GPL2 for inclusion in Tellico */
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#ifndef __RTF_TOOLS_H__
+#define __RTF_TOOLS_H__
+
+#include "common.h"
+#include "rtf_keyword.h"
+
+namespace rtf {
+
+template <class InputIter>
+void skip_group(InputIter &iter);
+
+
+/****************************************
+function assumes that file pointer points AFTER the opening brace
+and that the group is really closed. cs is caller's curchar.
+Returns the character that comes after the enclosing brace.
+*****************************************/
+
+template <class InputIter>
+void skip_group(InputIter &iter)
+{
+ int cnt=1;
+ while (cnt)
+ {
+ switch (*iter++)
+ {
+ case '{':
+ cnt++;
+ break;
+ case '}':
+ cnt--;
+ break;
+ case '\\':
+ {
+ rtf_keyword kw(iter);
+ if (!kw.is_control_char() && kw.keyword()==rtf_keyword::rkw_bin
+ && kw.parameter()>0)
+ {
+ std::advance(iter, kw.parameter());
+ }
+ break;
+ }
+ }
+ }
+}
+
+}
+
+#endif