]> git.saurik.com Git - wxWidgets.git/blobdiff - src/html/htmlcell.cpp
missing commit
[wxWidgets.git] / src / html / htmlcell.cpp
index 95d81d6abc5351d15420382d59c916efb8085a7d..53699fc856e114349f96edb6417885dfcb7cf3ea 100644 (file)
 
 #if wxUSE_HTML && wxUSE_STREAMS
 
 
 #if wxUSE_HTML && wxUSE_STREAMS
 
-#ifndef WXPRECOMP
+#ifndef WX_PRECOMP
     #include "wx/dynarray.h"
     #include "wx/brush.h"
     #include "wx/colour.h"
     #include "wx/dc.h"
     #include "wx/settings.h"
     #include "wx/module.h"
     #include "wx/dynarray.h"
     #include "wx/brush.h"
     #include "wx/colour.h"
     #include "wx/dc.h"
     #include "wx/settings.h"
     #include "wx/module.h"
+    #include "wx/wxcrtvararg.h"
 #endif
 
 #include "wx/html/htmlcell.h"
 #endif
 
 #include "wx/html/htmlcell.h"
@@ -149,7 +150,7 @@ bool wxHtmlCell::ProcessMouseClick(wxHtmlWindowInterface *window,
                                    const wxPoint& pos,
                                    const wxMouseEvent& event)
 {
                                    const wxPoint& pos,
                                    const wxMouseEvent& event)
 {
-    wxCHECK_MSG( window, false, _T("window interface must be provided") );
+    wxCHECK_MSG( window, false, wxT("window interface must be provided") );
 
 #if WXWIN_COMPATIBILITY_2_6
     // NB: this hack puts the body of ProcessMouseClick() into OnMouseClick()
 
 #if WXWIN_COMPATIBILITY_2_6
     // NB: this hack puts the body of ProcessMouseClick() into OnMouseClick()
@@ -163,7 +164,7 @@ bool wxHtmlCell::ProcessMouseClick(wxHtmlWindowInterface *window,
 
 void wxHtmlCell::OnMouseClick(wxWindow *, int, int, const wxMouseEvent& event)
 {
 
 void wxHtmlCell::OnMouseClick(wxWindow *, int, int, const wxMouseEvent& event)
 {
-    wxCHECK_RET( gs_helperOnMouseClick, _T("unexpected call to OnMouseClick") );
+    wxCHECK_RET( gs_helperOnMouseClick, wxT("unexpected call to OnMouseClick") );
     wxHtmlWindowInterface *window = gs_helperOnMouseClick->window;
     const wxPoint& pos = gs_helperOnMouseClick->pos;
 #endif // WXWIN_COMPATIBILITY_2_6
     wxHtmlWindowInterface *window = gs_helperOnMouseClick->window;
     const wxPoint& pos = gs_helperOnMouseClick->pos;
 #endif // WXWIN_COMPATIBILITY_2_6
@@ -200,11 +201,11 @@ wxCursor wxHtmlCell::GetMouseCursor(wxHtmlWindowInterface *window) const
 #if WXWIN_COMPATIBILITY_2_6
     // NB: Older versions of wx used GetCursor() virtual method in place of
     //     GetMouseCursor(interface). This code ensures that user code that
 #if WXWIN_COMPATIBILITY_2_6
     // NB: Older versions of wx used GetCursor() virtual method in place of
     //     GetMouseCursor(interface). This code ensures that user code that
-    //     overriden GetCursor() continues to work. The trick is that the base
+    //     overridden GetCursor() continues to work. The trick is that the base
     //     wxHtmlCell::GetCursor() method simply returns wxNullCursor, so we
     //     wxHtmlCell::GetCursor() method simply returns wxNullCursor, so we
-    //     know that GetCursor() was overriden iff it returns valid cursor.
+    //     know that GetCursor() was overridden iff it returns valid cursor.
     wxCursor cur = GetCursor();
     wxCursor cur = GetCursor();
-    if (cur.Ok())
+    if (cur.IsOk())
         return cur;
 #endif // WXWIN_COMPATIBILITY_2_6
 
         return cur;
 #endif // WXWIN_COMPATIBILITY_2_6
 
@@ -219,11 +220,16 @@ wxCursor wxHtmlCell::GetMouseCursor(wxHtmlWindowInterface *window) const
 }
 
 
 }
 
 
-bool wxHtmlCell::AdjustPagebreak(int *pagebreak,
-                                 wxArrayInt& WXUNUSED(known_pagebreaks)) const
+bool
+wxHtmlCell::AdjustPagebreak(int *pagebreak,
+                            const wxArrayInt& WXUNUSED(known_pagebreaks),
+                            int pageHeight) const
 {
 {
-    if ((!m_CanLiveOnPagebreak) &&
-                m_PosY < *pagebreak && m_PosY + m_Height > *pagebreak)
+    // Notice that we always break the cells bigger than the page height here
+    // as otherwise we wouldn't be able to break them at all.
+    if ( m_Height <= pageHeight &&
+            (!m_CanLiveOnPagebreak &&
+                m_PosY < *pagebreak && m_PosY + m_Height > *pagebreak) )
     {
         *pagebreak = m_PosY;
         return true;
     {
         *pagebreak = m_PosY;
         return true;
@@ -236,8 +242,7 @@ bool wxHtmlCell::AdjustPagebreak(int *pagebreak,
 
 void wxHtmlCell::SetLink(const wxHtmlLinkInfo& link)
 {
 
 void wxHtmlCell::SetLink(const wxHtmlLinkInfo& link)
 {
-    if (m_Link) delete m_Link;
-    m_Link = NULL;
+    wxDELETE(m_Link);
     if (link.GetHref() != wxEmptyString)
         m_Link = new wxHtmlLinkInfo(link);
 }
     if (link.GetHref() != wxEmptyString)
         m_Link = new wxHtmlLinkInfo(link);
 }
@@ -341,7 +346,7 @@ bool wxHtmlCell::IsBefore(wxHtmlCell *cell) const
         }
     }
 
         }
     }
 
-    wxFAIL_MSG(_T("Cells are in different trees"));
+    wxFAIL_MSG(wxT("Cells are in different trees"));
     return false;
 }
 
     return false;
 }
 
@@ -355,7 +360,11 @@ IMPLEMENT_ABSTRACT_CLASS(wxHtmlWordCell, wxHtmlCell)
 wxHtmlWordCell::wxHtmlWordCell(const wxString& word, const wxDC& dc) : wxHtmlCell()
 {
     m_Word = word;
 wxHtmlWordCell::wxHtmlWordCell(const wxString& word, const wxDC& dc) : wxHtmlCell()
 {
     m_Word = word;
-    dc.GetTextExtent(m_Word, &m_Width, &m_Height, &m_Descent);
+    wxCoord w, h, d;
+    dc.GetTextExtent(m_Word, &w, &h, &d);
+    m_Width = w;
+    m_Height = h;
+    m_Descent = d;
     SetCanLiveOnPagebreak(false);
     m_allowLinebreak = true;
 }
     SetCanLiveOnPagebreak(false);
     m_allowLinebreak = true;
 }
@@ -381,6 +390,16 @@ void wxHtmlWordCell::Split(const wxDC& dc,
     wxPoint pt2 = (selTo == wxDefaultPosition) ?
                    wxPoint(m_Width, wxDefaultCoord) : selTo - GetAbsPos();
 
     wxPoint pt2 = (selTo == wxDefaultPosition) ?
                    wxPoint(m_Width, wxDefaultCoord) : selTo - GetAbsPos();
 
+    // if the selection is entirely within this cell, make sure pt1 < pt2 in
+    // order to make the rest of this function simpler:
+    if ( selFrom != wxDefaultPosition && selTo != wxDefaultPosition &&
+         selFrom.x > selTo.x )
+    {
+        wxPoint tmp = pt1;
+        pt1 = pt2;
+        pt2 = tmp;
+    }
+
     unsigned len = m_Word.length();
     unsigned i = 0;
     pos1 = 0;
     unsigned len = m_Word.length();
     unsigned i = 0;
     pos1 = 0;
@@ -393,19 +412,26 @@ void wxHtmlWordCell::Split(const wxDC& dc,
         pt2.x = m_Width;
 
     // before selection:
         pt2.x = m_Width;
 
     // before selection:
+    // (include character under caret only if in first half of width)
 #ifdef __WXMAC__
     // implementation using PartialExtents to support fractional widths
     wxArrayInt widths ;
     dc.GetPartialTextExtents(m_Word,widths) ;
     while( i < len && pt1.x >= widths[i] )
         i++ ;
 #ifdef __WXMAC__
     // implementation using PartialExtents to support fractional widths
     wxArrayInt widths ;
     dc.GetPartialTextExtents(m_Word,widths) ;
     while( i < len && pt1.x >= widths[i] )
         i++ ;
-#else // __WXMAC__
+    if ( i < len )
+    {
+        int charW = (i > 0) ? widths[i] - widths[i-1] : widths[i];
+        if ( widths[i] - pt1.x < charW/2 )
+            i++;
+    }
+#else // !__WXMAC__
     wxCoord charW, charH;
     while ( pt1.x > 0 && i < len )
     {
         dc.GetTextExtent(m_Word[i], &charW, &charH);
         pt1.x -= charW;
     wxCoord charW, charH;
     while ( pt1.x > 0 && i < len )
     {
         dc.GetTextExtent(m_Word[i], &charW, &charH);
         pt1.x -= charW;
-        if ( pt1.x >= 0 )
+        if ( pt1.x >= -charW/2 )
         {
             pos1 += charW;
             i++;
         {
             pos1 += charW;
             i++;
@@ -414,18 +440,25 @@ void wxHtmlWordCell::Split(const wxDC& dc,
 #endif // __WXMAC__/!__WXMAC__
 
     // in selection:
 #endif // __WXMAC__/!__WXMAC__
 
     // in selection:
+    // (include character under caret only if in first half of width)
     unsigned j = i;
 #ifdef __WXMAC__
     while( j < len && pt2.x >= widths[j] )
         j++ ;
     unsigned j = i;
 #ifdef __WXMAC__
     while( j < len && pt2.x >= widths[j] )
         j++ ;
-#else // __WXMAC__
+    if ( j < len )
+    {
+        int charW = (j > 0) ? widths[j] - widths[j-1] : widths[j];
+        if ( widths[j] - pt2.x < charW/2 )
+            j++;
+    }
+#else // !__WXMAC__
     pos2 = pos1;
     pt2.x -= pos2;
     while ( pt2.x > 0 && j < len )
     {
         dc.GetTextExtent(m_Word[j], &charW, &charH);
         pt2.x -= charW;
     pos2 = pos1;
     pt2.x -= pos2;
     while ( pt2.x > 0 && j < len )
     {
         dc.GetTextExtent(m_Word[j], &charW, &charH);
         pt2.x -= charW;
-        if ( pt2.x >= 0 )
+        if ( pt2.x >= -charW/2 )
         {
             pos2 += charW;
             j++;
         {
             pos2 += charW;
             j++;
@@ -435,6 +468,8 @@ void wxHtmlWordCell::Split(const wxDC& dc,
 
     pos1 = i;
     pos2 = j;
 
     pos1 = i;
     pos2 = j;
+
+    wxASSERT( pos2 >= pos1 );
 }
 
 void wxHtmlWordCell::SetSelectionPrivPos(const wxDC& dc, wxHtmlSelection *s) const
 }
 
 void wxHtmlWordCell::SetSelectionPrivPos(const wxDC& dc, wxHtmlSelection *s) const
@@ -446,17 +481,10 @@ void wxHtmlWordCell::SetSelectionPrivPos(const wxDC& dc, wxHtmlSelection *s) con
           this == s->GetToCell() ? s->GetToPos() : wxDefaultPosition,
           p1, p2);
 
           this == s->GetToCell() ? s->GetToPos() : wxDefaultPosition,
           p1, p2);
 
-    wxPoint p(0, m_Word.length());
-
     if ( this == s->GetFromCell() )
     if ( this == s->GetFromCell() )
-        p.x = p1; // selection starts here
+        s->SetFromCharacterPos (p1); // selection starts here
     if ( this == s->GetToCell() )
     if ( this == s->GetToCell() )
-        p.y = p2; // selection ends here
-
-    if ( this == s->GetFromCell() )
-        s->SetFromPrivPos(p);
-    if ( this == s->GetToCell() )
-        s->SetToPrivPos(p);
+        s->SetToCharacterPos (p2); // selection ends here
 }
 
 
 }
 
 
@@ -472,14 +500,16 @@ static void SwitchSelState(wxDC& dc, wxHtmlRenderingInfo& info,
         dc.SetTextForeground(info.GetStyle().GetSelectedTextColour(fg));
         dc.SetTextBackground(info.GetStyle().GetSelectedTextBgColour(bg));
         dc.SetBackground(wxBrush(info.GetStyle().GetSelectedTextBgColour(bg),
         dc.SetTextForeground(info.GetStyle().GetSelectedTextColour(fg));
         dc.SetTextBackground(info.GetStyle().GetSelectedTextBgColour(bg));
         dc.SetBackground(wxBrush(info.GetStyle().GetSelectedTextBgColour(bg),
-                                 wxSOLID));
+                                 wxBRUSHSTYLE_SOLID));
     }
     else
     {
     }
     else
     {
-        dc.SetBackgroundMode(wxTRANSPARENT);
+        const int mode = info.GetState().GetBgMode();
+        dc.SetBackgroundMode(mode);
         dc.SetTextForeground(fg);
         dc.SetTextBackground(bg);
         dc.SetTextForeground(fg);
         dc.SetTextBackground(bg);
-        dc.SetBackground(wxBrush(bg, wxSOLID));
+        if ( mode != wxTRANSPARENT )
+            dc.SetBackground(wxBrush(bg, mode));
     }
 }
 
     }
 }
 
@@ -503,23 +533,18 @@ void wxHtmlWordCell::Draw(wxDC& dc, int x, int y,
         int w, h;
         int ofs = 0;
 
         int w, h;
         int ofs = 0;
 
-        wxPoint priv = (this == s->GetFromCell()) ?
-                           s->GetFromPrivPos() : s->GetToPrivPos();
-
         // NB: this is quite a hack: in order to compute selection boundaries
         //     (in word's characters) we must know current font, which is only
         //     possible inside rendering code. Therefore we update the
         //     information here and store it in wxHtmlSelection so that
         //     ConvertToText can use it later:
         // NB: this is quite a hack: in order to compute selection boundaries
         //     (in word's characters) we must know current font, which is only
         //     possible inside rendering code. Therefore we update the
         //     information here and store it in wxHtmlSelection so that
         //     ConvertToText can use it later:
-        if ( priv == wxDefaultPosition )
+        if ( !s->AreFromToCharacterPosSet () )
         {
             SetSelectionPrivPos(dc, s);
         {
             SetSelectionPrivPos(dc, s);
-            priv = (this == s->GetFromCell()) ?
-                    s->GetFromPrivPos() : s->GetToPrivPos();
         }
 
         }
 
-        int part1 = priv.x;
-        int part2 = priv.y;
+        int part1 = s->GetFromCell()==this ? s->GetFromCharacterPos() : 0;
+        int part2 = s->GetToCell()==this   ? s->GetToCharacterPos()   : m_Word.Length();
 
         if ( part1 > 0 )
         {
 
         if ( part1 > 0 )
         {
@@ -549,16 +574,7 @@ void wxHtmlWordCell::Draw(wxDC& dc, int x, int y,
     {
         wxHtmlSelectionState selstate = info.GetState().GetSelectionState();
         // Not changing selection state, draw the word in single mode:
     {
         wxHtmlSelectionState selstate = info.GetState().GetSelectionState();
         // Not changing selection state, draw the word in single mode:
-        if ( selstate != wxHTML_SEL_OUT &&
-             dc.GetBackgroundMode() != wxSOLID )
-        {
-            SwitchSelState(dc, info, true);
-        }
-        else if ( selstate == wxHTML_SEL_OUT &&
-                  dc.GetBackgroundMode() == wxSOLID )
-        {
-            SwitchSelState(dc, info, false);
-        }
+        SwitchSelState(dc, info, selstate != wxHTML_SEL_OUT);
         dc.DrawText(m_Word, x + m_PosX, y + m_PosY);
         drawSelectionAfterCell = (selstate != wxHTML_SEL_OUT);
     }
         dc.DrawText(m_Word, x + m_PosX, y + m_PosY);
         drawSelectionAfterCell = (selstate != wxHTML_SEL_OUT);
     }
@@ -588,14 +604,22 @@ void wxHtmlWordCell::Draw(wxDC& dc, int x, int y,
     }
 }
 
     }
 }
 
+wxCursor wxHtmlWordCell::GetMouseCursor(wxHtmlWindowInterface *window) const
+{
+    if ( !GetLink() )
+    {
+        return window->GetHTMLCursor(wxHtmlWindowInterface::HTMLCursor_Text);
+    }
+    else
+    {
+        return wxHtmlCell::GetMouseCursor(window);
+    }
+}
 
 wxString wxHtmlWordCell::ConvertToText(wxHtmlSelection *s) const
 {
     if ( s && (this == s->GetFromCell() || this == s->GetToCell()) )
     {
 
 wxString wxHtmlWordCell::ConvertToText(wxHtmlSelection *s) const
 {
     if ( s && (this == s->GetFromCell() || this == s->GetToCell()) )
     {
-        wxPoint priv = this == s->GetFromCell() ? s->GetFromPrivPos()
-                                                : s->GetToPrivPos();
-
         // VZ: we may be called before we had a chance to re-render ourselves
         //     and in this case GetFrom/ToPrivPos() is not set yet -- assume
         //     that this only happens in case of a double/triple click (which
         // VZ: we may be called before we had a chance to re-render ourselves
         //     and in this case GetFrom/ToPrivPos() is not set yet -- assume
         //     that this only happens in case of a double/triple click (which
@@ -603,31 +627,79 @@ wxString wxHtmlWordCell::ConvertToText(wxHtmlSelection *s) const
         //     entire contents of the cell in this case
         //
         // TODO: but this really needs to be fixed in some better way later...
         //     entire contents of the cell in this case
         //
         // TODO: but this really needs to be fixed in some better way later...
-        if ( priv != wxDefaultPosition )
+        if ( s->AreFromToCharacterPosSet() )
         {
         {
-            int part1 = priv.x;
-            int part2 = priv.y;
-            return m_Word.Mid(part1, part2-part1);
+            const int part1 = s->GetFromCell()==this ? s->GetFromCharacterPos() : 0;
+            const int part2 = s->GetToCell()==this   ? s->GetToCharacterPos()   : m_Word.Length();
+            if ( part1 == part2 )
+                return wxEmptyString;
+            return GetPartAsText(part1, part2);
         }
         //else: return the whole word below
     }
 
         }
         //else: return the whole word below
     }
 
-    return m_Word;
+    return GetAllAsText();
 }
 
 }
 
-wxCursor wxHtmlWordCell::GetMouseCursor(wxHtmlWindowInterface *window) const
+wxString wxHtmlWordWithTabsCell::GetAllAsText() const
 {
 {
-    if ( !GetLink() )
+    return m_wordOrig;
+}
+
+wxString wxHtmlWordWithTabsCell::GetPartAsText(int begin, int end) const
+{
+    // NB: The 'begin' and 'end' positions are in the _displayed_ text
+    //     (stored in m_Word) and not in the text with tabs that should
+    //     be copied to clipboard (m_wordOrig).
+    //
+    // NB: Because selection is performed on displayed text, it's possible
+    //     to select e.g. "half of TAB character" -- IOW, 'begin' and 'end'
+    //     may be in the middle of TAB character expansion into ' 's. In this
+    //     case, we copy the TAB character to clipboard once.
+
+    wxASSERT( begin < end );
+
+    const unsigned SPACES_PER_TAB = 8;
+
+    wxString sel;
+
+    int pos = 0;
+    wxString::const_iterator i = m_wordOrig.begin();
+
+    // find the beginning of text to copy:
+    for ( ; pos < begin; ++i )
     {
     {
-        return window->GetHTMLCursor(wxHtmlWindowInterface::HTMLCursor_Text);
+        if ( *i == '\t' )
+        {
+            pos += 8 - (m_linepos + pos) % SPACES_PER_TAB;
+            if ( pos >= begin )
+            {
+                sel += '\t';
+            }
+        }
+        else
+        {
+            ++pos;
+        }
     }
     }
-    else
+
+    // copy the content until we reach 'end':
+    for ( ; pos < end; ++i )
     {
     {
-        return wxHtmlCell::GetMouseCursor(window);
+        const wxChar c = *i;
+        sel += c;
+
+        if ( c == '\t' )
+            pos += 8 - (m_linepos + pos) % SPACES_PER_TAB;
+        else
+            ++pos;
     }
     }
+
+    return sel;
 }
 
 
 }
 
 
+
 //-----------------------------------------------------------------------------
 // wxHtmlContainerCell
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // wxHtmlContainerCell
 //-----------------------------------------------------------------------------
@@ -645,7 +717,7 @@ wxHtmlContainerCell::wxHtmlContainerCell(wxHtmlContainerCell *parent) : wxHtmlCe
     m_IndentLeft = m_IndentRight = m_IndentTop = m_IndentBottom = 0;
     m_WidthFloat = 100; m_WidthFloatUnits = wxHTML_UNITS_PERCENT;
     m_UseBkColour = false;
     m_IndentLeft = m_IndentRight = m_IndentTop = m_IndentBottom = 0;
     m_WidthFloat = 100; m_WidthFloatUnits = wxHTML_UNITS_PERCENT;
     m_UseBkColour = false;
-    m_UseBorder = false;
+    m_Border = 0;
     m_MinHeight = 0;
     m_MinHeightAlign = wxHTML_ALIGN_TOP;
     m_LastLayout = -1;
     m_MinHeight = 0;
     m_MinHeightAlign = wxHTML_ALIGN_TOP;
     m_LastLayout = -1;
@@ -700,11 +772,13 @@ int wxHtmlContainerCell::GetIndentUnits(int ind) const
 }
 
 
 }
 
 
-bool wxHtmlContainerCell::AdjustPagebreak(int *pagebreak,
-                                          wxArrayInt& known_pagebreaks) const
+bool
+wxHtmlContainerCell::AdjustPagebreak(int *pagebreak,
+                                     const wxArrayInt& known_pagebreaks,
+                                     int pageHeight) const
 {
     if (!m_CanLiveOnPagebreak)
 {
     if (!m_CanLiveOnPagebreak)
-        return wxHtmlCell::AdjustPagebreak(pagebreak, known_pagebreaks);
+        return wxHtmlCell::AdjustPagebreak(pagebreak, known_pagebreaks, pageHeight);
 
     wxHtmlCell *c = GetFirstChild();
     bool rt = false;
 
     wxHtmlCell *c = GetFirstChild();
     bool rt = false;
@@ -712,7 +786,7 @@ bool wxHtmlContainerCell::AdjustPagebreak(int *pagebreak,
 
     while (c)
     {
 
     while (c)
     {
-        if (c->AdjustPagebreak(&pbrk, known_pagebreaks))
+        if (c->AdjustPagebreak(&pbrk, known_pagebreaks, pageHeight))
             rt = true;
         c = c->GetNext();
     }
             rt = true;
         c = c->GetNext();
     }
@@ -726,7 +800,9 @@ void wxHtmlContainerCell::Layout(int w)
 {
     wxHtmlCell::Layout(w);
 
 {
     wxHtmlCell::Layout(w);
 
-    if (m_LastLayout == w) return;
+    if (m_LastLayout == w)
+        return;
+    m_LastLayout = w;
 
     // VS: Any attempt to layout with negative or zero width leads to hell,
     // but we can't ignore such attempts completely, since it sometimes
 
     // VS: Any attempt to layout with negative or zero width leads to hell,
     // but we can't ignore such attempts completely, since it sometimes
@@ -779,7 +855,7 @@ void wxHtmlContainerCell::Layout(int w)
 
     /*
 
 
     /*
 
-    LAYOUTING :
+    LAYOUT :
 
     */
 
 
     */
 
@@ -787,7 +863,7 @@ void wxHtmlContainerCell::Layout(int w)
     s_indent = (m_IndentLeft < 0) ? (-m_IndentLeft * m_Width / 100) : m_IndentLeft;
     s_width = m_Width - s_indent - ((m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight);
 
     s_indent = (m_IndentLeft < 0) ? (-m_IndentLeft * m_Width / 100) : m_IndentLeft;
     s_width = m_Width - s_indent - ((m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight);
 
-    // my own layouting:
+    // my own layout:
     wxHtmlCell *cell = m_Cells,
                *line = m_Cells;
     while (cell != NULL)
     wxHtmlCell *cell = m_Cells,
                *line = m_Cells;
     while (cell != NULL)
@@ -884,12 +960,12 @@ void wxHtmlContainerCell::Layout(int w)
                 if ( step > 0 )
                 {
                     // first count the cells which will get extra space
                 if ( step > 0 )
                 {
                     // first count the cells which will get extra space
-                    int total = 0;
+                    int total = -1;
 
                     const wxHtmlCell *c;
                     if ( line != cell )
                     {
 
                     const wxHtmlCell *c;
                     if ( line != cell )
                     {
-                        for ( c = line->GetNext(); c != cell; c = c->GetNext() )
+                        for ( c = line; c != cell; c = c->GetNext() )
                         {
                             if ( c->IsLinebreakAllowed() )
                             {
                         {
                             if ( c->IsLinebreakAllowed() )
                             {
@@ -901,11 +977,22 @@ void wxHtmlContainerCell::Layout(int w)
                     // and now extra space to those cells which merit it
                     if ( total )
                     {
                     // and now extra space to those cells which merit it
                     if ( total )
                     {
-                        // first cell on line is not moved:
-                        line->SetPos(line->GetPosX() + s_indent,
-                                     line->GetPosY() + ypos);
+                        // first visible cell on line is not moved:
+                        while (line !=cell && !line->IsLinebreakAllowed())
+                        {
+                            line->SetPos(line->GetPosX() + s_indent,
+                                         line->GetPosY() + ypos);
+                            line = line->GetNext();
+                        }
+
+                        if (line != cell)
+                        {
+                            line->SetPos(line->GetPosX() + s_indent,
+                                         line->GetPosY() + ypos);
+
+                            line = line->GetNext();
+                        }
 
 
-                        line = line->GetNext();
                         for ( int n = 0; line != cell; line = line->GetNext() )
                         {
                             if ( line->IsLinebreakAllowed() )
                         for ( int n = 0; line != cell; line = line->GetNext() )
                         {
                             if ( line->IsLinebreakAllowed() )
@@ -971,8 +1058,6 @@ void wxHtmlContainerCell::Layout(int w)
     m_MaxTotalWidth += s_indent + ((m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight);
     MaxLineWidth += s_indent + ((m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight);
     if (m_Width < MaxLineWidth) m_Width = MaxLineWidth;
     m_MaxTotalWidth += s_indent + ((m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight);
     MaxLineWidth += s_indent + ((m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight);
     if (m_Width < MaxLineWidth) m_Width = MaxLineWidth;
-
-    m_LastLayout = w;
 }
 
 void wxHtmlContainerCell::UpdateRenderingStatePre(wxHtmlRenderingInfo& info,
 }
 
 void wxHtmlContainerCell::UpdateRenderingStatePre(wxHtmlRenderingInfo& info,
@@ -1013,7 +1098,7 @@ void wxHtmlContainerCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2,
 
     if (m_UseBkColour)
     {
 
     if (m_UseBkColour)
     {
-        wxBrush myb = wxBrush(m_BkColour, wxSOLID);
+        wxBrush myb = wxBrush(m_BkColour, wxBRUSHSTYLE_SOLID);
 
         int real_y1 = mMax(ylocal, view_y1);
         int real_y2 = mMin(ylocal + m_Height - 1, view_y2);
 
         int real_y1 = mMax(ylocal, view_y1);
         int real_y2 = mMin(ylocal + m_Height - 1, view_y2);
@@ -1023,10 +1108,11 @@ void wxHtmlContainerCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2,
         dc.DrawRectangle(xlocal, real_y1, m_Width, real_y2 - real_y1 + 1);
     }
 
         dc.DrawRectangle(xlocal, real_y1, m_Width, real_y2 - real_y1 + 1);
     }
 
-    if (m_UseBorder)
+    if (m_Border == 1)
     {
     {
-        wxPen mypen1(m_BorderColour1, 1, wxSOLID);
-        wxPen mypen2(m_BorderColour2, 1, wxSOLID);
+        // draw thin border using lines
+        wxPen mypen1(m_BorderColour1, 1, wxPENSTYLE_SOLID);
+        wxPen mypen2(m_BorderColour2, 1, wxPENSTYLE_SOLID);
 
         dc.SetPen(mypen1);
         dc.DrawLine(xlocal, ylocal, xlocal, ylocal + m_Height - 1);
 
         dc.SetPen(mypen1);
         dc.DrawLine(xlocal, ylocal, xlocal, ylocal + m_Height - 1);
@@ -1035,7 +1121,56 @@ void wxHtmlContainerCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2,
         dc.DrawLine(xlocal + m_Width - 1, ylocal, xlocal +  m_Width - 1, ylocal + m_Height - 1);
         dc.DrawLine(xlocal, ylocal + m_Height - 1, xlocal + m_Width, ylocal + m_Height - 1);
     }
         dc.DrawLine(xlocal + m_Width - 1, ylocal, xlocal +  m_Width - 1, ylocal + m_Height - 1);
         dc.DrawLine(xlocal, ylocal + m_Height - 1, xlocal + m_Width, ylocal + m_Height - 1);
     }
-
+    else if (m_Border> 0)
+    {
+        wxBrush mybrush1(m_BorderColour1, wxBRUSHSTYLE_SOLID);
+        wxBrush mybrush2(m_BorderColour2, wxBRUSHSTYLE_SOLID);
+
+        // draw upper left corner
+        // 0---------------5
+        // |              /
+        // | 3-----------4
+        // | |
+        // | 2
+        // |/
+        // 1
+
+        wxPoint poly[6];
+        poly[0].x =m_PosX; poly[0].y = m_PosY ;
+        poly[1].x =m_PosX; poly[1].y = m_PosY + m_Height;
+        poly[2].x =m_PosX + m_Border; poly[2].y = poly[1].y - m_Border;
+        poly[3].x =poly[2].x ; poly[3].y = m_PosY + m_Border;
+        poly[4].x =m_PosX + m_Width - m_Border; poly[4].y = poly[3].y;
+        poly[5].x =m_PosX + m_Width; poly[5].y = m_PosY;
+
+        dc.SetBrush(mybrush1);
+        dc.SetPen(*wxTRANSPARENT_PEN);
+        dc.DrawPolygon(6, poly, x, y);
+
+        // draw lower right corner reusing point 1,2,4 and 5
+        //                 5
+        //                /|
+        //               4 |
+        //               | |
+        //   2-----------3 |
+        //  /              |
+        // 1---------------0
+        dc.SetBrush(mybrush2);
+        poly[0].x = poly[5].x; poly[0].y = poly[1].y;
+        poly[3].x = poly[4].x; poly[3].y = poly[2].y;
+        dc.DrawPolygon(6, poly, x, y);
+
+        // smooth color transition like firefox
+        wxColour borderMediumColour(
+            (m_BorderColour1.Red() + m_BorderColour2.Red()) /2 ,
+            (m_BorderColour1.Green() + m_BorderColour2.Green()) /2 ,
+            (m_BorderColour1.Blue() + m_BorderColour2.Blue()) /2
+            );
+        wxPen mypen3(borderMediumColour, 1, wxPENSTYLE_SOLID);
+        dc.SetPen(mypen3);
+        dc.DrawLines(2, &poly[1], x, y - 1); // between 1 and 2
+        dc.DrawLines(2, &poly[4], x, y - 1); // between 4 and 5
+    }
     if (m_Cells)
     {
         // draw container's contents:
     if (m_Cells)
     {
         // draw container's contents:
@@ -1241,7 +1376,7 @@ bool wxHtmlContainerCell::ProcessMouseClick(wxHtmlWindowInterface *window,
 void wxHtmlContainerCell::OnMouseClick(wxWindow*,
                                        int, int, const wxMouseEvent& event)
 {
 void wxHtmlContainerCell::OnMouseClick(wxWindow*,
                                        int, int, const wxMouseEvent& event)
 {
-    wxCHECK_RET( gs_helperOnMouseClick, _T("unexpected call to OnMouseClick") );
+    wxCHECK_RET( gs_helperOnMouseClick, wxT("unexpected call to OnMouseClick") );
     wxHtmlWindowInterface *window = gs_helperOnMouseClick->window;
     const wxPoint& pos = gs_helperOnMouseClick->pos;
 #endif // WXWIN_COMPATIBILITY_2_6
     wxHtmlWindowInterface *window = gs_helperOnMouseClick->window;
     const wxPoint& pos = gs_helperOnMouseClick->pos;
 #endif // WXWIN_COMPATIBILITY_2_6
@@ -1410,17 +1545,23 @@ void wxHtmlColourCell::DrawInvisible(wxDC& dc,
     if (m_Flags & wxHTML_CLR_BACKGROUND)
     {
         state.SetBgColour(m_Colour);
     if (m_Flags & wxHTML_CLR_BACKGROUND)
     {
         state.SetBgColour(m_Colour);
-        if (state.GetSelectionState() != wxHTML_SEL_IN)
-        {
-            dc.SetTextBackground(m_Colour);
-            dc.SetBackground(wxBrush(m_Colour, wxSOLID));
-        }
-        else
-        {
-            wxColour c = info.GetStyle().GetSelectedTextBgColour(m_Colour);
-            dc.SetTextBackground(c);
-            dc.SetBackground(wxBrush(c, wxSOLID));
-        }
+        state.SetBgMode(wxSOLID);
+        const wxColour c = state.GetSelectionState() == wxHTML_SEL_IN
+                         ? info.GetStyle().GetSelectedTextBgColour(m_Colour)
+                         : m_Colour;
+        dc.SetTextBackground(c);
+        dc.SetBackground(c);
+        dc.SetBackgroundMode(wxSOLID);
+    }
+    if (m_Flags & wxHTML_CLR_TRANSPARENT_BACKGROUND)
+    {
+        state.SetBgColour(m_Colour);
+        state.SetBgMode(wxTRANSPARENT);
+        const wxColour c = state.GetSelectionState() == wxHTML_SEL_IN
+                         ? info.GetStyle().GetSelectedTextBgColour(m_Colour)
+                         : m_Colour;
+        dc.SetTextBackground(c);
+        dc.SetBackgroundMode(wxTRANSPARENT);
     }
 }
 
     }
 }
 
@@ -1485,8 +1626,15 @@ void wxHtmlWidgetCell::Draw(wxDC& WXUNUSED(dc),
         c = c->GetParent();
     }
 
         c = c->GetParent();
     }
 
-    ((wxScrolledWindow*)(m_Wnd->GetParent()))->GetViewStart(&stx, &sty);
-    m_Wnd->SetSize(absx - wxHTML_SCROLL_STEP * stx, absy  - wxHTML_SCROLL_STEP * sty, m_Width, m_Height);
+    wxScrolledWindow *scrolwin =
+        wxDynamicCast(m_Wnd->GetParent(), wxScrolledWindow);
+    wxCHECK_RET( scrolwin,
+                 wxT("widget cells can only be placed in wxHtmlWindow") );
+
+    scrolwin->GetViewStart(&stx, &sty);
+    m_Wnd->SetSize(absx - wxHTML_SCROLL_STEP * stx,
+                   absy  - wxHTML_SCROLL_STEP * sty,
+                   m_Width, m_Height);
 }
 
 
 }