X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d0c3476bd6d011315d7928c12094912995095553..ccb5db57cdb1766eefb7023dda50ede9f0d01f78:/src/richtext/richtexthtml.cpp diff --git a/src/richtext/richtexthtml.cpp b/src/richtext/richtexthtml.cpp index ccf818e371..4326e33e15 100644 --- a/src/richtext/richtexthtml.cpp +++ b/src/richtext/richtexthtml.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: richtext/richtexthtml.cpp +// Name: src/richtext/richtexthtml.cpp // Purpose: HTML I/O for wxRichTextCtrl // Author: Julian Smart // Modified by: @@ -13,7 +13,7 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop + #pragma hdrstop #endif #if wxUSE_RICHTEXT @@ -21,7 +21,6 @@ #include "wx/richtext/richtexthtml.h" #ifndef WX_PRECOMP - #include "wx/wx.h" #endif #include "wx/filename.h" @@ -53,55 +52,56 @@ bool wxRichTextHTMLHandler::DoLoadFile(wxRichTextBuffer *WXUNUSED(buffer), wxInp bool wxRichTextHTMLHandler::DoSaveFile(wxRichTextBuffer *buffer, wxOutputStream& stream) { buffer->Defragment(); - + wxTextOutputStream str(stream); - + wxTextAttrEx currentParaStyle = buffer->GetAttributes(); wxTextAttrEx currentCharStyle = buffer->GetAttributes(); - + str << wxT("\n"); - + /* wxRichText may be support paper formats like a1/a2/a3/a4 when this widget grown enough, i should turn back and support its new features but not yet - + str << wxT(""), left_indent.c_str(), //Document-Wide Left Indent right_indent.c_str()); //Document-Wide Right Indent - + str << wxT("
"); - + wxString left_indent = SymbolicIndent(currentParaStyle.GetLeftIndent()); wxString right_indent = SymbolicIndent(currentParaStyle.GetRightIndent()); - + str << wxString::Format(wxT("%s%s
"); */ - + str << wxT("
"); - - str << wxString::Format(wxT(""), - currentParaStyle.GetFont().GetFaceName().c_str(), Pt_To_Size( currentParaStyle.GetFont().GetPointSize() ), - currentParaStyle.GetTextColour().Red(), currentParaStyle.GetTextColour().Green(), - currentParaStyle.GetTextColour().Blue()); - + + str << wxString::Format(wxT(""), + currentParaStyle.GetFont().GetFaceName().c_str(), Pt_To_Size( currentParaStyle.GetFont().GetPointSize() ), + currentParaStyle.GetTextColour().GetAsString(wxC2S_HTML_SYNTAX).c_str()); + //wxString align = GetAlignment( currentParaStyle.GetAlignment() ); //str << wxString::Format(wxT("

"), align ); - + m_font = false; m_indent = 0; m_list = false; - + wxRichTextObjectList::compatibility_iterator node = buffer->GetChildren().GetFirst(); while (node) { wxRichTextParagraph* para = wxDynamicCast(node->GetData(), wxRichTextParagraph); wxASSERT (para != NULL); - + if (para) { - OutputParagraphFormatting(currentParaStyle, para->GetAttributes(), stream); + wxTextAttrEx paraStyle(para->GetCombinedAttributes()); + OutputParagraphFormatting(currentParaStyle, paraStyle, stream); + wxRichTextObjectList::compatibility_iterator node2 = para->GetChildren().GetFirst(); while (node2) { @@ -109,108 +109,110 @@ bool wxRichTextHTMLHandler::DoSaveFile(wxRichTextBuffer *buffer, wxOutputStream& wxRichTextPlainText* textObj = wxDynamicCast(obj, wxRichTextPlainText); if (textObj && !textObj->IsEmpty()) { - BeginCharacterFormatting(currentCharStyle, obj->GetAttributes(), stream); - + wxTextAttrEx charStyle(para->GetCombinedAttributes(obj->GetAttributes())); + BeginCharacterFormatting(currentCharStyle, charStyle, paraStyle, stream); + str << textObj->GetText(); - - EndCharacterFormatting(currentCharStyle, obj->GetAttributes(), stream); + + EndCharacterFormatting(currentCharStyle, charStyle, paraStyle, stream); } - + wxRichTextImage* image = wxDynamicCast(obj, wxRichTextImage); if( image && !image->IsEmpty()) Image_to_Base64( image, stream ); - + node2 = node2->GetNext(); } + str << wxT("\n"); //OutputParagraphFormatting(currentParaStyle, para->GetAttributes(), stream, false); } node = node->GetNext(); } - + str << wxT("

\n"); - + return true; } -void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& currentStyle, const wxTextAttrEx& thisStyle, wxOutputStream& stream) +void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& currentStyle, const wxTextAttrEx& thisStyle, const wxTextAttrEx& paraStyle, wxOutputStream& stream) { wxTextOutputStream str(stream); - + //Is the item bulleted one? - if( thisStyle.GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE ) + if( paraStyle.GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE ) { //Is there any opened list? if( m_list ) { //Yes there is - + //Is the item among the previous ones //Is the item one of the previous list tag's child items - if( (thisStyle.GetLeftIndent() == (m_indent + 100)) || (thisStyle.GetLeftIndent() < 100) ) + if( (paraStyle.GetLeftIndent() == (m_indent + 100)) || (paraStyle.GetLeftIndent() < 100) ) str << wxT("
  • ");//Yes it is else { //No it isn't - + //So we should close the list tag str << (m_is_ul ? wxT("") : wxT("")); - + //And renavigate to new list's horizontal position - NavigateToListPosition(thisStyle, str); + NavigateToListPosition(paraStyle, str); //Ok it's done - + //Get the appropriate tag, an ol for numerical values, an ul for dot, square etc. wxString tag; - TypeOfList(thisStyle, tag); + TypeOfList(paraStyle, tag); str << tag << wxT("
  • "); } } else { //No there isn't a list - + //navigate to new list's horizontal position(indent) - NavigateToListPosition(thisStyle, str); - + NavigateToListPosition(paraStyle, str); + //Get the appropriate tag, an ol for numerical values, an ul for dot, square etc. wxString tag; - TypeOfList(thisStyle, tag); + TypeOfList(paraStyle, tag); str << tag << wxT("
  • "); - + //Now we have a list, mark it. m_list = true; - } + } } else if( m_list ) { - //The item is not bulleted and there is a list what should be closed now. + //The item is not bulleted and there is a list what should be closed now. //So close the list str << (m_is_ul ? wxT("") : wxT("")); //And mark as there is no an opened list m_list = false; } - + // does the item have an indentation ? - if( thisStyle.GetLeftIndent() ) + if( paraStyle.GetLeftIndent() ) { - if( thisStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_NONE ) + if( paraStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_NONE ) { if( m_indent ) { - if( (thisStyle.GetLeftIndent() + thisStyle.GetLeftSubIndent()) == m_indent ) + if( (paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent()) == m_indent ) { - if( thisStyle.GetLeftSubIndent() < 0 ) + if( paraStyle.GetLeftSubIndent() < 0 ) { - str << SymbolicIndent(~thisStyle.GetLeftSubIndent()); + str << SymbolicIndent(~paraStyle.GetLeftSubIndent()); } } else { - if( thisStyle.GetLeftIndent() + thisStyle.GetLeftSubIndent() > m_indent ) + if( paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent() > m_indent ) { - Indent(thisStyle, str); - m_indent = thisStyle.GetLeftIndent() + thisStyle.GetLeftSubIndent(); + Indent(paraStyle, str); + m_indent = paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent(); m_indents.Add( m_indent ); } else @@ -218,28 +220,28 @@ void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& current int i = m_indents.size() - 1; for(; i > -1; i--) { - if( m_indent < (thisStyle.GetLeftIndent() + thisStyle.GetLeftSubIndent()) ) + if( m_indent < (paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent()) ) { - Indent(thisStyle, str); - m_indent = thisStyle.GetLeftIndent() + thisStyle.GetLeftSubIndent(); + Indent(paraStyle, str); + m_indent = paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent(); m_indents.Add( m_indent ); - + break; } - else if( m_indent == (thisStyle.GetLeftIndent() + thisStyle.GetLeftSubIndent()) ) + else if( m_indent == (paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent()) ) { - if( thisStyle.GetLeftSubIndent() < 0 ) + if( paraStyle.GetLeftSubIndent() < 0 ) { - str << SymbolicIndent(~thisStyle.GetLeftSubIndent()); + str << SymbolicIndent(~paraStyle.GetLeftSubIndent()); } break; } else { str << wxT("
  • "); - + m_indents.RemoveAt(i); - + if( i < 1 ){m_indent=0; break;} m_indent = m_indents[i-1]; } @@ -249,8 +251,8 @@ void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& current } else { - Indent(thisStyle, str); - m_indent = thisStyle.GetLeftIndent() + thisStyle.GetLeftSubIndent(); + Indent(paraStyle, str); + m_indent = paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent(); m_indents.Add( m_indent ); } } @@ -258,33 +260,32 @@ void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& current else if( m_indent ) { //The item is not indented and there is a table(s) what should be closed now. - + //So close them for(unsigned int i = 0; i < m_indents.size(); i++ ) str << wxT(""); - + m_indent = 0; m_indents.Clear(); } - - + + wxString style; - + //Is there any change on the font properties of the item if( thisStyle.GetFont().GetFaceName() != currentStyle.GetFont().GetFaceName() ) style += wxString::Format(wxT(" face=\"%s\""), thisStyle.GetFont().GetFaceName().c_str()); if( thisStyle.GetFont().GetPointSize() != currentStyle.GetFont().GetPointSize() ) style += wxString::Format(wxT(" size=\"%ld\""), Pt_To_Size(thisStyle.GetFont().GetPointSize()) ); if( thisStyle.GetTextColour() != currentStyle.GetTextColour() ) - style += wxString::Format(wxT(" color=\"#%02X%02X%02X\""), thisStyle.GetTextColour().Red(), - thisStyle.GetTextColour().Green(), thisStyle.GetTextColour().Blue()); - + style += wxString::Format(wxT(" color=\"%s\""), thisStyle.GetTextColour().GetAsString(wxC2S_HTML_SYNTAX).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 ) @@ -293,17 +294,17 @@ void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& current str << wxT(""); } -void wxRichTextHTMLHandler::EndCharacterFormatting(const wxTextAttrEx& WXUNUSED(currentStyle), const wxTextAttrEx& thisStyle, wxOutputStream& stream) +void wxRichTextHTMLHandler::EndCharacterFormatting(const wxTextAttrEx& WXUNUSED(currentStyle), const wxTextAttrEx& thisStyle, const wxTextAttrEx& WXUNUSED(paraStyle), wxOutputStream& stream) { wxTextOutputStream str(stream); - + if( thisStyle.GetFont().GetUnderlined() ) str << wxT(""); if( thisStyle.GetFont().GetStyle() == wxITALIC ) str << wxT(""); if( thisStyle.GetFont().GetWeight() == wxBOLD ) str << wxT(""); - + if( m_font ) { m_font = false; @@ -327,8 +328,8 @@ void wxRichTextHTMLHandler::NavigateToListPosition(const wxTextAttrEx& thisStyle { //indenting an item using an ul/ol tag is equal to inserting 5 x   on its left side. //so we should start from 100 point left - - //Is the second td's left wall of the current indentaion table at the 100+ point-left-side + + //Is the second td's left wall of the current indentaion table at the 100+ point-left-side //of the item, horizontally? if( m_indent + 100 < thisStyle.GetLeftIndent() ) { @@ -339,11 +340,11 @@ void wxRichTextHTMLHandler::NavigateToListPosition(const wxTextAttrEx& thisStyle return; } //No it isn't - + int i = m_indents.size() - 1; for(; i > -1; i--) { - //Is the second td's left wall of the current indentaion table at the 100+ point-left-side + //Is the second td's left wall of the current indentaion table at the 100+ point-left-side //of the item ? if( m_indent + 100 < thisStyle.GetLeftIndent() ) { @@ -360,9 +361,9 @@ void wxRichTextHTMLHandler::NavigateToListPosition(const wxTextAttrEx& thisStyle //No it is not, the second td's left wall of the current indentaion table is at the //right side of the current item horizontally, so close it. str << wxT(""); - + m_indents.RemoveAt(i); - + if( i < 1 ){m_indent=0; break;} m_indent = m_indents[i-1]; } @@ -372,14 +373,14 @@ void wxRichTextHTMLHandler::Indent( const wxTextAttrEx& thisStyle, wxTextOutputS { //As a five year experienced web developer i assure you there is no way to indent an item //in html way, but we can use tables. - - - + + + //Item -> "Hello world" //Its Left Indentation -> 100 //Its Left Sub-Indentation ->40 //A typical indentation-table for the item will be construct as the following - + //3 x nbsp = 60 //2 x nbsp = 40 //LSI = Left Sub Indent @@ -387,17 +388,17 @@ void wxRichTextHTMLHandler::Indent( const wxTextAttrEx& thisStyle, wxTextOutputS // //------------------------------------------- //|  nbsp;|nbsp;nbsp;Hello World | - //| | | | | + //| | | | | //| V | V | //| --LI-- | --LSI-- | //------------------------------------------- - + str << wxT(""); - + wxString symbolic_indent = SymbolicIndent( (thisStyle.GetLeftIndent() + thisStyle.GetLeftSubIndent()) - m_indent ); str << wxString::Format( wxT(""), symbolic_indent.c_str() ); str << wxT("
    %s"); - + if( thisStyle.GetLeftSubIndent() < 0 ) { str << SymbolicIndent(~thisStyle.GetLeftSubIndent()); @@ -417,21 +418,21 @@ void wxRichTextHTMLHandler::LIndent( const wxTextAttrEx& thisStyle, wxTextOutput //r.EndNumberedBullet(); // //A typical indentation-table for the item will be construct as the following - + //1 x nbsp = 20 point //ULI -> 100pt (UL/OL tag indents its sub element by 100 point) //<--------- 100 pt ---------->| //------------------------------------------------------ //|  nbsp; nbsp;|
      | - //| |<-ULI->
    • first item | + //| |<-ULI->
    • first item | //| |<-ULI->
    • second item | //| |
    | //------------------------------------------------------ - // |<-100->| - - + // |<-100->| + + str << wxT(""); - + wxString symbolic_indent = SymbolicIndent( (thisStyle.GetLeftIndent() - m_indent) - 100); str << wxString::Format( wxT(""), symbolic_indent.c_str() ); str << wxT("
    %s"); @@ -439,9 +440,9 @@ void wxRichTextHTMLHandler::LIndent( const wxTextAttrEx& thisStyle, wxTextOutput void wxRichTextHTMLHandler::TypeOfList( const wxTextAttrEx& thisStyle, wxString& tag ) { - //We can use number attribute of li tag but not all the browsers support it. + //We can use number attribute of li tag but not all the browsers support it. //also wxHtmlWindow doesn't support type attribute. - + m_is_ul = false; if( thisStyle.GetBulletStyle() == (wxTEXT_ATTR_BULLET_STYLE_ARABIC|wxTEXT_ATTR_BULLET_STYLE_PERIOD)) tag = wxT("
      "); @@ -480,17 +481,20 @@ wxString wxRichTextHTMLHandler::GetAlignment( const wxTextAttrEx& thisStyle ) void wxRichTextHTMLHandler::Image_to_Base64(wxRichTextImage* image, wxOutputStream& stream) { wxTextOutputStream str(stream); - + str << wxT("GetImageBlock().GetImageType()); str << wxT(";base64,"); - + + if (image->GetImage().Ok() && !image->GetImageBlock().GetData()) + image->MakeBlock(); + wxChar* data = b64enc( image->GetImageBlock().GetData(), image->GetImageBlock().GetDataSize() ); str << data; - + delete[] data; - + str << wxT("\" />"); } @@ -539,46 +543,46 @@ wxChar* wxRichTextHTMLHandler::b64enc( unsigned char* input, size_t in_len ) //elements of enc64 array must be 8 bit values //otherwise encoder will fail //hmmm.. Does wxT macro define a char as 16 bit value - //when compiling with UNICODE option? + //when compiling with UNICODE option? static const wxChar enc64[] = wxT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); wxChar* output = new wxChar[4*((in_len+2)/3)+1]; wxChar* p = output; - + while( in_len-- > 0 ) { register wxChar a, b; - + a = *input++; - + *p++ = enc64[ (a >> 2) & 0x3f ]; - - if( in_len-- <= 0 ) + + if( in_len-- == 0 ) { *p++ = enc64[ (a << 4 ) & 0x30 ]; *p++ = '='; *p++ = '='; break; } - + b = *input++; - + *p++ = enc64[(( a << 4 ) | ((b >> 4) &0xf )) & 0x3f]; - - if( in_len-- <= 0 ) + + if( in_len-- == 0 ) { *p++ = enc64[ (b << 2) & 0x3f ]; *p++ = '='; break; } - + a = *input++; - + *p++ = enc64[ ((( b << 2 ) & 0x3f ) | ((a >> 6)& 0x3)) & 0x3f ]; - + *p++ = enc64[ a & 0x3f ]; } *p = 0; - + return output; } #endif @@ -586,4 +590,3 @@ wxChar* wxRichTextHTMLHandler::b64enc( unsigned char* input, size_t in_len ) #endif // wxUSE_RICHTEXT -