///////////////////////////////////////////////////////////////////////////// // Name: src/richtext/richtexthtml.cpp // Purpose: HTML I/O for wxRichTextCtrl // Author: Julian Smart // Modified by: // Created: 2005-09-30 // RCS-ID: $Id$ // Copyright: (c) Julian Smart // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #if wxUSE_RICHTEXT #include "wx/richtext/richtexthtml.h" #include "wx/richtext/richtextstyles.h" #ifndef WX_PRECOMP #endif #include "wx/filename.h" #include "wx/wfstream.h" #include "wx/txtstrm.h" #if wxUSE_FILESYSTEM #include "wx/filesys.h" #include "wx/fs_mem.h" #endif IMPLEMENT_DYNAMIC_CLASS(wxRichTextHTMLHandler, wxRichTextFileHandler) int wxRichTextHTMLHandler::sm_fileCounter = 1; wxRichTextHTMLHandler::wxRichTextHTMLHandler(const wxString& name, const wxString& ext, int type) : wxRichTextFileHandler(name, ext, type), m_buffer(NULL), m_font(false), m_inTable(false) { m_fontSizeMapping.Add(8); m_fontSizeMapping.Add(10); m_fontSizeMapping.Add(13); m_fontSizeMapping.Add(17); m_fontSizeMapping.Add(22); m_fontSizeMapping.Add(30); m_fontSizeMapping.Add(100); } /// Can we handle this filename (if using files)? By default, checks the extension. bool wxRichTextHTMLHandler::CanHandle(const wxString& filename) const { wxString path, file, ext; wxSplitPath(filename, & path, & file, & ext); return (ext.Lower() == wxT("html") || ext.Lower() == wxT("htm")); } #if wxUSE_STREAMS bool wxRichTextHTMLHandler::DoLoadFile(wxRichTextBuffer *WXUNUSED(buffer), wxInputStream& WXUNUSED(stream)) { return false; } /* * We need to output only _changes_ in character formatting. */ bool wxRichTextHTMLHandler::DoSaveFile(wxRichTextBuffer *buffer, wxOutputStream& stream) { m_buffer = buffer; ClearTemporaryImageLocations(); buffer->Defragment(); wxTextOutputStream str(stream); wxTextAttrEx currentParaStyle = buffer->GetAttributes(); wxTextAttrEx currentCharStyle = buffer->GetAttributes(); if ((GetFlags() & wxRICHTEXT_HANDLER_NO_HEADER_FOOTER) == 0) str << wxT("
\n"); str << wxT("| ");
OutputFont(currentParaStyle, str);
m_font = false;
m_inTable = false;
m_indents.Clear();
m_listTypes.Clear();
wxRichTextObjectList::compatibility_iterator node = buffer->GetChildren().GetFirst();
while (node)
{
wxRichTextParagraph* para = wxDynamicCast(node->GetData(), wxRichTextParagraph);
wxASSERT (para != NULL);
if (para)
{
wxTextAttrEx paraStyle(para->GetCombinedAttributes());
BeginParagraphFormatting(currentParaStyle, paraStyle, str);
wxRichTextObjectList::compatibility_iterator node2 = para->GetChildren().GetFirst();
while (node2)
{
wxRichTextObject* obj = node2->GetData();
wxRichTextPlainText* textObj = wxDynamicCast(obj, wxRichTextPlainText);
if (textObj && !textObj->IsEmpty())
{
wxTextAttrEx charStyle(para->GetCombinedAttributes(obj->GetAttributes()));
BeginCharacterFormatting(currentCharStyle, charStyle, paraStyle, str);
wxString text = textObj->GetText();
if (charStyle.HasTextEffects() && (charStyle.GetTextEffects() & wxTEXT_ATTR_EFFECT_CAPITALS))
text.MakeUpper();
wxString toReplace = wxRichTextLineBreakChar;
text.Replace(toReplace, wxT(" ")); str << text; EndCharacterFormatting(currentCharStyle, charStyle, paraStyle, str); } wxRichTextImage* image = wxDynamicCast(obj, wxRichTextImage); if( image && !image->IsEmpty()) WriteImage( image, stream ); node2 = node2->GetNext(); } EndParagraphFormatting(currentParaStyle, paraStyle, str); str << wxT("\n"); } node = node->GetNext(); } CloseLists(-1, str); str << wxT(""); str << wxT(" |
"); if ((GetFlags() & wxRICHTEXT_HANDLER_NO_HEADER_FOOTER) == 0) str << wxT(""); str << wxT("\n"); m_buffer = NULL; return true; } void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& currentStyle, const wxTextAttrEx& thisStyle, const wxTextAttrEx& WXUNUSED(paraStyle), wxTextOutputStream& str) { wxString style; // Is there any change in the font properties of the item? if (thisStyle.GetFont().GetFaceName() != currentStyle.GetFont().GetFaceName()) { wxString faceName(thisStyle.GetFont().GetFaceName()); style += wxString::Format(wxT(" face=\"%s\""), faceName.c_str()); } if (thisStyle.GetFont().GetPointSize() != currentStyle.GetFont().GetPointSize()) style += wxString::Format(wxT(" size=\"%ld\""), PtToSize(thisStyle.GetFont().GetPointSize())); if (thisStyle.GetTextColour() != currentStyle.GetTextColour() ) { wxString color(thisStyle.GetTextColour().GetAsString(wxC2S_HTML_SYNTAX)); style += wxString::Format(wxT(" color=\"%s\""), color.c_str()); } if (style.size()) { str << wxString::Format(wxT(""), style.c_str()); m_font = true; } if (thisStyle.GetFont().GetWeight() == wxBOLD) str << wxT(""); if (thisStyle.GetFont().GetStyle() == wxITALIC) str << wxT(""); if (thisStyle.GetFont().GetUnderlined()) str << wxT(""); if (thisStyle.HasURL()) str << wxT(""); } void wxRichTextHTMLHandler::EndCharacterFormatting(const wxTextAttrEx& WXUNUSED(currentStyle), const wxTextAttrEx& thisStyle, const wxTextAttrEx& WXUNUSED(paraStyle), wxTextOutputStream& stream) { if (thisStyle.HasURL()) stream << wxT(""); if (thisStyle.GetFont().GetUnderlined()) stream << wxT(""); if (thisStyle.GetFont().GetStyle() == wxITALIC) stream << wxT(""); if (thisStyle.GetFont().GetWeight() == wxBOLD) stream << wxT(""); if (m_font) { m_font = false; stream << wxT(""); } } /// Begin paragraph formatting void wxRichTextHTMLHandler::BeginParagraphFormatting(const wxTextAttrEx& WXUNUSED(currentStyle), const wxTextAttrEx& thisStyle, wxTextOutputStream& str) { if (thisStyle.HasPageBreak()) { str << wxT(""); str << wxT("
\n"); str << wxT("| ");
}
if (thisStyle.HasLeftIndent() && thisStyle.GetLeftIndent() != 0)
{
if (thisStyle.HasBulletStyle())
{
int indent = thisStyle.GetLeftIndent();
// Close levels high than this
CloseLists(indent, str);
if (m_indents.GetCount() > 0 && indent == m_indents.Last())
{
// Same level, no need to start a new list
}
else if (m_indents.GetCount() == 0 || indent > m_indents.Last())
{
m_indents.Add(indent);
wxString tag;
int listType = TypeOfList(thisStyle, tag);
m_listTypes.Add(listType);
wxString align = GetAlignment(thisStyle);
str << wxString::Format(wxT(" "), align.c_str()); str << tag; } str << wxT(" "), align.c_str()); // Use a table int indentTenthsMM = thisStyle.GetLeftIndent() + thisStyle.GetLeftSubIndent(); // TODO: convert to pixels int indentPixels = indentTenthsMM/4; str << wxString::Format(wxT("
|