]> git.saurik.com Git - wxWidgets.git/blobdiff - src/richtext/richtexthtml.cpp
Fix a couple of small errors.
[wxWidgets.git] / src / richtext / richtexthtml.cpp
index 9a01d9e656816aacf92893e33b6d92eb84e66a22..965bbd4630618ca49521b674cbc9655c1449a115 100644 (file)
@@ -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
 #include "wx/richtext/richtexthtml.h"
 
 #ifndef WX_PRECOMP
-  #include "wx/wx.h"
 #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;
+
 /// Can we handle this filename (if using files)? By default, checks the extension.
 bool wxRichTextHTMLHandler::CanHandle(const wxString& filename) const
 {
@@ -52,56 +58,39 @@ bool wxRichTextHTMLHandler::DoLoadFile(wxRichTextBuffer *WXUNUSED(buffer), wxInp
 
 bool wxRichTextHTMLHandler::DoSaveFile(wxRichTextBuffer *buffer, wxOutputStream& stream)
 {
+    ClearTemporaryImageLocations();
+
     buffer->Defragment();
-    
+
     wxTextOutputStream str(stream);
-    
+
     wxTextAttrEx currentParaStyle = buffer->GetAttributes();
     wxTextAttrEx currentCharStyle = buffer->GetAttributes();
-    
+
     str << wxT("<html><head></head><body>\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("<table border=0 cellpadding=0 cellspacing=0><tr><td>");
-      
-        wxString left_indent = SymbolicIndent(currentParaStyle.GetLeftIndent());
-        wxString right_indent = SymbolicIndent(currentParaStyle.GetRightIndent());
-        
-          str << wxString::Format(wxT("%s</td><td></td><td>%s</td></tr><tr>"),
-          left_indent.c_str(), //Document-Wide Left Indent
-          right_indent.c_str()); //Document-Wide Right Indent
-          
-            str << wxT("<td></td><td width=\"100%\">");
-    */
-    
+
     str << wxT("<table border=0 cellpadding=0 cellspacing=0><tr><td width=\"100%\">");
-    
-    str << wxString::Format(wxT("<font face=\"%s\" size=\"%ld\" color=\"#%02X%02X%02X\" >"),
-        currentParaStyle.GetFont().GetFaceName().c_str(), Pt_To_Size( currentParaStyle.GetFont().GetPointSize() ), 
-        currentParaStyle.GetTextColour().Red(), currentParaStyle.GetTextColour().Green(),
-        currentParaStyle.GetTextColour().Blue());
-    
-    //wxString align = GetAlignment( currentParaStyle.GetAlignment() );
-    //str << wxString::Format(wxT("<p align=\"%s\">"), align );
-    
+
+    str << wxString::Format(wxT("<font face=\"%s\" size=\"%ld\" color=\"%s\" >"),
+        currentParaStyle.GetFont().GetFaceName().c_str(), PtToSize(currentParaStyle.GetFont().GetPointSize()),
+        currentParaStyle.GetTextColour().GetAsString(wxC2S_HTML_SYNTAX).c_str());
+
     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,139 +98,144 @@ bool wxRichTextHTMLHandler::DoSaveFile(wxRichTextBuffer *buffer, wxOutputStream&
                 wxRichTextPlainText* textObj = wxDynamicCast(obj, wxRichTextPlainText);
                 if (textObj && !textObj->IsEmpty())
                 {
-                    BeginCharacterFormatting(currentCharStyle, obj->GetAttributes(), stream);
-                    
-                    str << textObj->GetText();
+                    wxTextAttrEx charStyle(para->GetCombinedAttributes(obj->GetAttributes()));
+                    BeginCharacterFormatting(currentCharStyle, charStyle, paraStyle, stream);
                     
-                    EndCharacterFormatting(currentCharStyle, obj->GetAttributes(), stream);
+                    wxString text = textObj->GetText();
+
+                    if (charStyle.HasTextEffects() && (charStyle.GetTextEffects() & wxTEXT_ATTR_EFFECT_CAPITALS))
+                        text.MakeUpper();
+
+                    str << text;
+
+                    EndCharacterFormatting(currentCharStyle, charStyle, paraStyle, stream);
                 }
-                
+
                 wxRichTextImage* image = wxDynamicCast(obj, wxRichTextImage);
                 if( image && !image->IsEmpty())
-                    Image_to_Base64( image, stream );
-                
+                    WriteImage( image, stream );
+
                 node2 = node2->GetNext();
             }
             str << wxT("\n");
-            //OutputParagraphFormatting(currentParaStyle, para->GetAttributes(), stream, false);
         }
         node = node->GetNext();
     }
-    
+
     str << wxT("</font></td></tr></table></body></html>\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 )
+
+    // Is the item a bulleted one?
+    if ( paraStyle.GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE )
     {
-        //Is there any opened list?
-        if( m_list )
+        // 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) )
-                str << wxT("<li>");//Yes it is
+            // Yes there is
+
+            // Is the item among the previous ones?
+            // Is the item one of the previous list tag's child items?            
+            if ((paraStyle.GetLeftIndent() == (m_indent + 100)) || (paraStyle.GetLeftIndent() < 100))
+                str << wxT("<li>"); //Yes it is
             else
             {
-                //No it isn't
-                
-                //So we should close the list tag
+                // No it isn't, so we should close the list tag
                 str << (m_is_ul ? wxT("</ul>") : wxT("</ol>"));
-                
-                //And renavigate to new list's horizontal position
-                NavigateToListPosition(thisStyle, str);
-                //Ok it's done
-                
-                //Get the appropriate tag, an ol for numerical values, an ul for dot, square etc.
+
+                // And renavigate to new list's horizontal position
+                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("<li>");
             }
         }
         else
         {
-            //No there isn't a list
-            
-            //navigate to new list's horizontal position(indent)
-            NavigateToListPosition(thisStyle, str);                            
-            
-            //Get the appropriate tag, an ol for numerical values, an ul for dot, square etc.
+            // No there isn't a list.
+            // navigate to new list's horizontal position(indent)
+            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("<li>");
-            
-            //Now we have a list, mark it.
+
+            // 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.        
-        //So close the list
+        // The item is not bulleted and there is a list what should be closed now.
+        // So close the list
 
         str << (m_is_ul ? wxT("</ul>") : wxT("</ol>"));
-        //And mark as there is no an opened list
+
+        // 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 (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
                     {
                         int i = m_indents.size() - 1;
-                        for(; i > -1; i--)
+                        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("</td></tr></table>");
-                                
+
                                 m_indents.RemoveAt(i);
-                                
-                                if( i < 1 ){m_indent=0; break;}
+
+                                if(i < 1)
+                                {
+                                    m_indent=0; break;
+                                }
                                 m_indent = m_indents[i-1];
                             }
                         }
@@ -250,62 +244,72 @@ 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 );
             }
         }
     }
-    else if( m_indent )
+    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++ )
+        // The item is not indented and there is a table(s) that should be closed now.
+
+        for (unsigned int i = 0; i < m_indents.size(); i++)
             str << wxT("</td></tr></table>");
-        
+
         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());
-    
-    if( style.size() )
+
+    // 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("<font %s >"), style.c_str());
         m_font = true;
     }
-    
-    if( thisStyle.GetFont().GetWeight() == wxBOLD )
+
+    if (thisStyle.GetFont().GetWeight() == wxBOLD)
         str << wxT("<b>");
-    if( thisStyle.GetFont().GetStyle() == wxITALIC )
+    if (thisStyle.GetFont().GetStyle() == wxITALIC)
         str << wxT("<i>");
-    if( thisStyle.GetFont().GetUnderlined() )
+    if (thisStyle.GetFont().GetUnderlined())
         str << wxT("<u>");
+    
+    if (thisStyle.HasURL())
+        str << wxT("<a href=\"") << thisStyle.GetURL() << 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() )
+
+    if (thisStyle.HasURL())
+        str << wxT("</a>");
+
+    if (thisStyle.GetFont().GetUnderlined())
         str << wxT("</u>");
-    if( thisStyle.GetFont().GetStyle() == wxITALIC )
+    if (thisStyle.GetFont().GetStyle() == wxITALIC)
         str << wxT("</i>");
-    if( thisStyle.GetFont().GetWeight() == wxBOLD )
+    if (thisStyle.GetFont().GetWeight() == wxBOLD)
         str << wxT("</b>");
-    
-    if( m_font )
+
+    if (m_font)
     {
         m_font = false;
         str << wxT("</font>");
@@ -315,91 +319,97 @@ void wxRichTextHTMLHandler::EndCharacterFormatting(const wxTextAttrEx& WXUNUSED(
 /// Output paragraph formatting
 void wxRichTextHTMLHandler::OutputParagraphFormatting(const wxTextAttrEx& WXUNUSED(currentStyle), const wxTextAttrEx& thisStyle, wxOutputStream& stream)
 {
-    //If there is no opened list currently, insert a <p> after every paragraph
-    if(!m_list)
+    // If there is no opened list currently, insert a <p> after every paragraph
+    if (!m_list)
     {
         wxTextOutputStream str(stream);
-        wxString align = GetAlignment( thisStyle );
+        wxString align = GetAlignment(thisStyle);
         str << wxString::Format(wxT("<p align=\"%s\">"), align.c_str());
     }
+    
+    if (thisStyle.HasPageBreak())
+    {
+        wxTextOutputStream str(stream);
+        str << wxT("<div style=\"page-break-after:always\"></div>\n");
+    }
 }
 
 void wxRichTextHTMLHandler::NavigateToListPosition(const wxTextAttrEx& thisStyle, wxTextOutputStream& str)
 {
-    //indenting an item using an ul/ol tag is equal to inserting 5 x &nbsp; 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 
-    //of the item, horizontally?
-    if( m_indent + 100 < thisStyle.GetLeftIndent() )
+    // indenting an item using an ul/ol tag is equal to inserting 5 x &nbsp; 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
+    // of the item, horizontally?
+    if (m_indent + 100 < thisStyle.GetLeftIndent())
     {
-        //yes it is
+        // yes it is
         LIndent(thisStyle, str);
         m_indent = thisStyle.GetLeftIndent() - 100;
         m_indents.Add( m_indent );
         return;
     }
-    //No it isn't
-    
+    // No it isn't
+
     int i = m_indents.size() - 1;
-    for(; i > -1; i--)
+    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() )
+        if (m_indent + 100 < thisStyle.GetLeftIndent())
         {
-            //Yes it is
+            // Yes it is
             LIndent(thisStyle, str);
             m_indent = thisStyle.GetLeftIndent() - 100;
             m_indents.Add( m_indent );
             break;
         }
-        else if( m_indent + 100 == thisStyle.GetLeftIndent() )
-            break;//exact match
+        else if (m_indent + 100 == thisStyle.GetLeftIndent())
+            break; //exact match
         else
         {
-            //No it is not, the second td's left wall of the current indentaion table is at the
+            // 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("</td></tr></table>");
-            
+
             m_indents.RemoveAt(i);
-            
-            if( i < 1 ){m_indent=0; break;}
+
+            if (i < 1)
+            {
+                m_indent=0; break;
+            }
             m_indent = m_indents[i-1];
         }
     }
 }
 void wxRichTextHTMLHandler::Indent( const wxTextAttrEx& thisStyle, wxTextOutputStream& str )
 {
-    //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
-    //LI = Left Indent - LSI
+    //There is no way to indent an item in HTML, 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
+    // LI = Left Indent - LSI
     //
-    //-------------------------------------------
-    //|&nbsp;&nbsp;nbsp;|nbsp;nbsp;Hello World  |
-    //|                   |        |    |                  | 
-    //|        V        |    V                  |
-    //|      --LI--     | --LSI--               |
-    //-------------------------------------------
-    
+    // -------------------------------------------
+    // |&nbsp;&nbsp;nbsp;|nbsp;nbsp;Hello World  |
+    // |      |          |    |                  |
+    // |        V        |    V                  |
+    // |      --LI--     | --LSI--               |
+    // -------------------------------------------
+
     str << wxT("<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr>");
-    
+
     wxString symbolic_indent = SymbolicIndent( (thisStyle.GetLeftIndent() + thisStyle.GetLeftSubIndent()) - m_indent );
     str << wxString::Format( wxT("<td>%s</td>"), symbolic_indent.c_str() );
     str << wxT("<td width=\"100%\">");
-    
-    if( thisStyle.GetLeftSubIndent() < 0 )
+
+    if (thisStyle.GetLeftSubIndent() < 0)
     {
         str << SymbolicIndent(~thisStyle.GetLeftSubIndent());
     }
@@ -407,32 +417,32 @@ void wxRichTextHTMLHandler::Indent( const wxTextAttrEx& thisStyle, wxTextOutputS
 
 void wxRichTextHTMLHandler::LIndent( const wxTextAttrEx& thisStyle, wxTextOutputStream& str )
 {
-    //Code:
-    //r.BeginNumberedBullet(1, 200, 60);
-    //r.Newline();
-    //r.WriteText(wxT("first item"));
-    //r.EndNumberedBullet();
-    //r.BeginNumberedBullet(2, 200, 60);
-    //r.Newline();
-    //r.WriteText(wxT("second item."));
-    //r.EndNumberedBullet();
+    // Code:
+    // r.BeginNumberedBullet(1, 200, 60);
+    // r.Newline();
+    // r.WriteText(wxT("first item"));
+    // r.EndNumberedBullet();
+    // r.BeginNumberedBullet(2, 200, 60);
+    // r.Newline();
+    // r.WriteText(wxT("second item."));
+    // 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;nbsp;&nbsp;nbsp;|<ul>                   |
-    //|                                       |<-ULI-><li>first item  | 
-    //|                            |<-ULI-><li>second item |
-    //|                            |</ul>                  |
-    //------------------------------------------------------
-    //                             |<-100->|   
-    
-    
+    // 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;nbsp;&nbsp;nbsp;|<ul>                   |
+    // |                            |<-ULI-><li>first item  |
+    // |                            |<-ULI-><li>second item |
+    // |                            |</ul>                  |
+    // ------------------------------------------------------
+    //                              |<-100->|
+
+
     str << wxT("<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr>");
-    
+
     wxString symbolic_indent = SymbolicIndent( (thisStyle.GetLeftIndent() - m_indent) - 100);
     str << wxString::Format( wxT("<td>%s</td>"), symbolic_indent.c_str() );
     str << wxT("<td width=\"100%\">");
@@ -440,19 +450,19 @@ 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. 
-    //also wxHtmlWindow doesn't support type attribute.
-    
+    // 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;
-    ifthisStyle.GetBulletStyle() == (wxTEXT_ATTR_BULLET_STYLE_ARABIC|wxTEXT_ATTR_BULLET_STYLE_PERIOD))
+    if (thisStyle.GetBulletStyle() == (wxTEXT_ATTR_BULLET_STYLE_ARABIC|wxTEXT_ATTR_BULLET_STYLE_PERIOD))
         tag = wxT("<ol type=\"1\">");
-    else if( thisStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER )
+    else if (thisStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER)
         tag = wxT("<ol type=\"A\">");
-    else if( thisStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER )
+    else if (thisStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER)
         tag = wxT("<ol type=\"a\">");
-    else if( thisStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER )
+    else if (thisStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER)
         tag = wxT("<ol type=\"I\">");
-    else if( thisStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER )
+    else if (thisStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER)
         tag = wxT("<ol type=\"i\">");
     else
     {
@@ -478,30 +488,84 @@ wxString wxRichTextHTMLHandler::GetAlignment( const wxTextAttrEx& thisStyle )
     }
 }
 
-void wxRichTextHTMLHandler::Image_to_Base64(wxRichTextImage* image, wxOutputStream& stream)
+void wxRichTextHTMLHandler::WriteImage(wxRichTextImage* image, wxOutputStream& stream)
 {
     wxTextOutputStream str(stream);
-    
+
     str << wxT("<img src=\"");
-    str << wxT("data:");
-    str << GetMimeType(image->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;
-    
+
+#if wxUSE_FILESYSTEM
+    if (GetFlags() & wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_MEMORY)
+    {
+        if (!image->GetImage().Ok() && image->GetImageBlock().GetData())
+            image->LoadFromBlock();
+        if (image->GetImage().Ok() && !image->GetImageBlock().GetData())
+            image->MakeBlock();
+
+        if (image->GetImage().Ok())
+        {        
+            wxString ext(image->GetImageBlock().GetExtension());
+            wxString tempFilename(wxString::Format(wxT("image%d.%s"), sm_fileCounter, (const wxChar*) ext));
+            wxMemoryFSHandler::AddFile(tempFilename, image->GetImage(), image->GetImageBlock().GetImageType());
+            
+            m_imageLocations.Add(tempFilename);
+            
+            str << wxT("memory:") << tempFilename;
+        }
+        else
+            str << wxT("memory:?");
+
+        sm_fileCounter ++;
+    }
+    else if (GetFlags() & wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_FILES)
+    {
+        if (!image->GetImage().Ok() && image->GetImageBlock().GetData())
+            image->LoadFromBlock();
+        if (image->GetImage().Ok() && !image->GetImageBlock().GetData())
+            image->MakeBlock();
+
+        if (image->GetImage().Ok())
+        {        
+            wxString tempDir(GetTempDir());
+            if (tempDir.IsEmpty())
+                tempDir = wxFileName::GetTempDir();
+            
+            wxString ext(image->GetImageBlock().GetExtension());
+            wxString tempFilename(wxString::Format(wxT("%s/image%d.%s"), (const wxChar*) tempDir, sm_fileCounter, (const wxChar*) ext));
+            image->GetImageBlock().Write(tempFilename);
+            
+            m_imageLocations.Add(tempFilename);
+            
+            str << wxFileSystem::FileNameToURL(tempFilename);            
+        }
+        else
+            str << wxT("file:?");
+
+        sm_fileCounter ++;
+    }
+    else // if (GetFlags() & wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_BASE64) // this is implied
+#endif
+    {
+        str << wxT("data:");
+        str << GetMimeType(image->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("\" />");
 }
 
-long wxRichTextHTMLHandler::Pt_To_Size(long size)
+long wxRichTextHTMLHandler::PtToSize(long size)
 {
-    //return most approximate size
-    if(size < 9 ) return 1;
+    // return approximate size
+    if (size < 9 ) return 1;
     else if( size < 11 ) return 2;
     else if( size < 14 ) return 3;
     else if( size < 18 ) return 4;
@@ -537,57 +601,88 @@ const wxChar* wxRichTextHTMLHandler::GetMimeType(int imageType)
     }
 }
 
-//exim-style base64 encoder
+// exim-style base64 encoder
 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? 
+    // 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?
     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
 // wxUSE_STREAMS
 
+/// Delete the in-memory or temporary files generated by the last operation
+bool wxRichTextHTMLHandler::DeleteTemporaryImages()
+{
+    return DeleteTemporaryImages(GetFlags(), m_imageLocations);
+}
+
+/// Delete the in-memory or temporary files generated by the last operation
+bool wxRichTextHTMLHandler::DeleteTemporaryImages(int flags, const wxArrayString& imageLocations)
+{
+    size_t i;
+    for (i = 0; i < imageLocations.GetCount(); i++)
+    {
+        wxString location = imageLocations[i];
+        
+        if (flags & wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_MEMORY)
+        {
+#if wxUSE_FILESYSTEM
+            wxMemoryFSHandler::RemoveFile(location);
+#endif
+        }
+        else if (flags & wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_FILES)
+        {
+            if (wxFileExists(location))
+                wxRemoveFile(location);
+        }
+    }
+    
+    return true;
+}
+
+
 #endif
 // wxUSE_RICHTEXT