]> git.saurik.com Git - wxWidgets.git/blobdiff - src/richtext/richtexthtml.cpp
Fix for handling of invalid gifs, patch 1587754 Noel Byron.
[wxWidgets.git] / src / richtext / richtexthtml.cpp
index 4326e33e154e340f46c59949040bd92587ee8b9f..c1722d2281acad3a96c252cb64a759a61a04366a 100644 (file)
 #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
 {
@@ -51,6 +58,8 @@ bool wxRichTextHTMLHandler::DoLoadFile(wxRichTextBuffer *WXUNUSED(buffer), wxInp
 
 bool wxRichTextHTMLHandler::DoSaveFile(wxRichTextBuffer *buffer, wxOutputStream& stream)
 {
+    ClearTemporaryImageLocations();
+
     buffer->Defragment();
 
     wxTextOutputStream str(stream);
@@ -60,32 +69,12 @@ bool wxRichTextHTMLHandler::DoSaveFile(wxRichTextBuffer *buffer, wxOutputStream&
 
     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=\"%s\" >"),
-        currentParaStyle.GetFont().GetFaceName().c_str(), Pt_To_Size( currentParaStyle.GetFont().GetPointSize() ),
+        currentParaStyle.GetFont().GetFaceName().c_str(), PtToSize(currentParaStyle.GetFont().GetPointSize()),
         currentParaStyle.GetTextColour().GetAsString(wxC2S_HTML_SYNTAX).c_str());
 
-    //wxString align = GetAlignment( currentParaStyle.GetAlignment() );
-    //str << wxString::Format(wxT("<p align=\"%s\">"), align );
-
     m_font = false;
     m_indent = 0;
     m_list = false;
@@ -119,12 +108,11 @@ bool wxRichTextHTMLHandler::DoSaveFile(wxRichTextBuffer *buffer, wxOutputStream&
 
                 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();
     }
@@ -138,30 +126,27 @@ void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& current
 {
     wxTextOutputStream str(stream);
 
-    //Is the item bulleted one?
-    if( paraStyle.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
+            // 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
+            // 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
+                // And renavigate to new list's horizontal position
                 NavigateToListPosition(paraStyle, str);
-                //Ok it's done
 
-                //Get the appropriate tag, an ol for numerical values, an ul for dot, square etc.
+                // Get the appropriate tag, an ol for numerical values, an ul for dot, square etc.
                 wxString tag;
                 TypeOfList(paraStyle, tag);
                 str << tag << wxT("<li>");
@@ -169,47 +154,47 @@ void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& current
         }
         else
         {
-            //No there isn't a list
-
-            //navigate to new list's horizontal position(indent)
+            // 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.
+            // Get the appropriate tag, an ol for numerical values, an ul for dot, square etc.
             wxString 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( paraStyle.GetLeftIndent() )
     {
-        if( paraStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_NONE )
+        if (paraStyle.GetBulletStyle() == wxTEXT_ATTR_BULLET_STYLE_NONE)
         {
-            if( m_indent )
+            if (m_indent)
             {
-                if( (paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent()) == m_indent )
+                if ((paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent()) == m_indent)
                 {
-                    if( paraStyle.GetLeftSubIndent() < 0 )
+                    if (paraStyle.GetLeftSubIndent() < 0)
                     {
                         str << SymbolicIndent(~paraStyle.GetLeftSubIndent());
                     }
                 }
                 else
                 {
-                    if( paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent() > m_indent )
+                    if (paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent() > m_indent)
                     {
                         Indent(paraStyle, str);
                         m_indent = paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent();
@@ -218,9 +203,9 @@ void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& current
                     else
                     {
                         int i = m_indents.size() - 1;
-                        for(; i > -1; i--)
+                        for (; i > -1; i--)
                         {
-                            if( m_indent < (paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent()) )
+                            if (m_indent < (paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent()))
                             {
                                 Indent(paraStyle, str);
                                 m_indent = paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent();
@@ -228,9 +213,9 @@ void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& current
 
                                 break;
                             }
-                            else if( m_indent == (paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent()) )
+                            else if (m_indent == (paraStyle.GetLeftIndent() + paraStyle.GetLeftSubIndent()))
                             {
-                                if( paraStyle.GetLeftSubIndent() < 0 )
+                                if (paraStyle.GetLeftSubIndent() < 0)
                                 {
                                     str << SymbolicIndent(~paraStyle.GetLeftSubIndent());
                                 }
@@ -242,7 +227,10 @@ void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& current
 
                                 m_indents.RemoveAt(i);
 
-                                if( i < 1 ){m_indent=0; break;}
+                                if(i < 1)
+                                {
+                                    m_indent=0; break;
+                                }
                                 m_indent = m_indents[i-1];
                             }
                         }
@@ -257,12 +245,11 @@ void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& current
             }
         }
     }
-    else if( m_indent )
+    else if (m_indent)
     {
-        //The item is not indented and there is a table(s) what should be closed now.
+        // The item is not indented and there is a table(s) that should be closed now.
 
-        //So close them
-        for(unsigned int i = 0; i < m_indents.size(); i++ )
+        for (unsigned int i = 0; i < m_indents.size(); i++)
             str << wxT("</td></tr></table>");
 
         m_indent = 0;
@@ -272,40 +259,52 @@ void wxRichTextHTMLHandler::BeginCharacterFormatting(const wxTextAttrEx& current
 
     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=\"%s\""), thisStyle.GetTextColour().GetAsString(wxC2S_HTML_SYNTAX).c_str());
+    // 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() )
+    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, 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,83 +314,83 @@ 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());
     }
 }
 
 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
+    // 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() )
+    // 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
         //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.
-
+    //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
 
-    //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
+    // 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>");
 
@@ -399,7 +398,7 @@ void wxRichTextHTMLHandler::Indent( const wxTextAttrEx& thisStyle, wxTextOutputS
     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,28 +406,28 @@ 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
+    // 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->|
+    // 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>");
@@ -440,19 +439,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 +477,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();
+#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:?");
 
-    wxChar* data = b64enc( image->GetImageBlock().GetData(), image->GetImageBlock().GetDataSize() );
-    str << data;
+        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:?");
 
-    delete[] data;
+        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,13 +590,13 @@ 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;
@@ -588,5 +641,37 @@ wxChar* wxRichTextHTMLHandler::b64enc( unsigned char* input, size_t in_len )
 #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
+