2
* This code is based in the RTF output generated by Dev-C++
4
* The tests have shown some missing styles, namely style 11
7
#include "RTFExporter.h"
8
#include <configmanager.h>
9
#include <wx/fontutil.h>
16
using std::ostringstream;
27
// Helper function to convert i to a string
28
inline string to_string(int i)
37
// operator == overloaded for wxColour objects
38
bool operator == (const wxColour &left, const wxColour &right)
40
return left.Red() == right.Red() && left.Green() == right.Green() && left.Blue() == right.Blue();
43
// operator != overloaded for wxColour objects
44
bool operator != (const wxColour &left, const wxColour &right)
46
return left.Red() != right.Red() || left.Green() != right.Green() || left.Blue() != right.Blue();
49
// Helper class to append colors in RTF colortbl format to a string
50
class wxColourToRTFTbl
56
wxColourToRTFTbl(string *str)
62
void operator () (const wxColour &color)
64
(*_str) += string("\\red") + to_string(color.Red());
65
(*_str) += string("\\green") + to_string(color.Green());
66
(*_str) += string("\\blue") + to_string(color.Blue());
67
(*_str) += string(";");
72
bool RTFExporter::Style::operator == (int aValue)
74
return value == aValue;
77
string RTFExporter::RTFFontTable(int &pt)
79
string fonttbl("{\\rtf1\\ansi\\deff0\\deftab720{\\fonttbl{\\f0\\fmodern ");
80
wxString fontstring = Manager::Get()->GetConfigManager(_T("editor"))->Read(_T("/font"), wxEmptyString);
83
if (!fontstring.IsEmpty())
87
nfi.FromString(fontstring);
88
tmpFont.SetNativeFontInfo(nfi);
90
pt = tmpFont.GetPointSize();
91
wxString faceName = tmpFont.GetFaceName();
93
if (!faceName.IsEmpty())
95
fonttbl += string(faceName.mb_str());
99
fonttbl += "Courier New";
104
fonttbl += "Courier New";
112
string RTFExporter::RTFColorTable(const EditorColourSet *c_color_set, HighlightLanguage lang)
114
string colortbl("{\\colortbl");
115
vector<wxColour> color_tbl; // We'll store fore and back colors here
117
m_styles.clear(); // Be sure the styles are cleared
118
defStyleIdx = -1; // No default style
122
const int count = const_cast<EditorColourSet *>(c_color_set)->GetOptionCount(lang);
124
for (int i = 0; i < count; ++i)
126
OptionColour *optc = const_cast<EditorColourSet *>(c_color_set)->GetOptionByIndex(lang, i);
133
vector<wxColour>::iterator foreIter = find(color_tbl.begin(), color_tbl.end(), optc->fore);
135
// Is the fore color already in color_tbl?
136
if (foreIter == color_tbl.end())
138
// NO? Then push it and make foreIter point to it (it's the last one)
139
color_tbl.push_back(optc->fore);
140
foreIter = color_tbl.end() - 1;
143
int foreIdx = foreIter - color_tbl.begin();
145
vector<wxColour>::iterator backIter = find(color_tbl.begin(), color_tbl.end(), optc->back);
147
// Is the back color already in color_tbl?
148
if (backIter == color_tbl.end())
150
// NO? Then push it and make backIter point to it (it's the last one)
151
color_tbl.push_back(optc->back);
152
backIter = color_tbl.end() - 1;
154
/* TODO (Ceniza#1#): If the background color isn't set don't add it (backIdx = -1) and check for it later */
155
int backIdx = backIter - color_tbl.begin();
167
m_styles.push_back(tmpStyle);
170
if (optc->value == 0)
172
defStyleIdx = m_styles.size() - 1;
176
// We've got all the colors and all styles. Write the colors
177
for_each(color_tbl.begin(), color_tbl.end(), wxColourToRTFTbl(&colortbl));
185
const char *RTFExporter::RTFInfo = "{\\info{\\comment Generated by the Code::Blocks RTF Exporter plugin}\n";
186
const char *RTFExporter::RTFTitle = "{\\title Untitled}}\n";
188
string RTFExporter::RTFBody(const wxMemoryBuffer &styled_text, int pt)
190
string rtf_body("\n\\deflang1033\\pard\\plain\\f0");
191
const char *buffer = reinterpret_cast<char *>(styled_text.GetData());
192
const size_t buffer_size = styled_text.GetDataLen();
194
rtf_body += string("\\fs") + to_string(pt * 2) + string(" ");
196
if (buffer_size == 0)
201
// Get the current style from the first character
202
char current_style = buffer[1];
204
// If the first style happen to be the body style...
205
if (current_style == 0)
207
if (defStyleIdx != -1)
209
vector<Style>::iterator i = m_styles.begin() + defStyleIdx;
211
rtf_body += string("\\cb") + to_string(i->backIdx);
212
rtf_body += string("\\cf") + to_string(i->foreIdx);
234
vector<Style>::iterator i = find(m_styles.begin(), m_styles.end(), current_style);
236
if (i != m_styles.end())
238
rtf_body += string("\\cb") + to_string(i->backIdx);
239
rtf_body += string("\\cf") + to_string(i->foreIdx);
260
for (size_t i = 0; i < buffer_size; i += 2)
262
if (buffer[i + 1] != current_style)
264
if (!isspace(buffer[i]))
266
vector<Style>::iterator oldStyle = find(m_styles.begin(), m_styles.end(), current_style);
268
if (oldStyle != m_styles.end())
270
if (oldStyle->underlined)
275
if (oldStyle->italics)
286
current_style = buffer[i + 1];
288
vector<Style>::iterator newStyle = find(m_styles.begin(), m_styles.end(), current_style);
290
if (newStyle != m_styles.end())
292
rtf_body += string("\\cb") + to_string(newStyle->backIdx);
293
rtf_body += string("\\cf") + to_string(newStyle->foreIdx);
300
if (newStyle->italics)
305
if (newStyle->underlined)
310
else if (defStyleIdx != -1)
312
vector<Style>::iterator i = m_styles.begin() + defStyleIdx;
314
rtf_body += string("\\cb") + to_string(i->backIdx);
315
rtf_body += string("\\cf") + to_string(i->foreIdx);
351
rtf_body += "\n\\par ";
355
rtf_body += buffer[i];
363
const char *RTFExporter::RTFEnd = "\n\\par }";
365
void RTFExporter::Export(const wxString &filename, const wxString &title, const wxMemoryBuffer &styled_text, const EditorColourSet *color_set)
368
HighlightLanguage lang = const_cast<EditorColourSet *>(color_set)->GetLanguageForFilename(title);
371
rtf_code += RTFFontTable(pt);
372
rtf_code += RTFColorTable(color_set, lang);
374
rtf_code += RTFTitle;
375
rtf_code += RTFBody(styled_text, pt);
378
wxFile file(filename, wxFile::write);
379
file.Write(rtf_code.c_str(), rtf_code.size());