]> git.saurik.com Git - wxWidgets.git/blobdiff - src/html/htmlcell.cpp
fix crash which happened if you called SetAttr(NULL) followed by SetAttr(attr) (...
[wxWidgets.git] / src / html / htmlcell.cpp
index 4bed6f3f9c75b7d3a99b9d7671657fe73e1d05a2..01d92107bd956baa5bb30964eaf99dbe7f321006 100644 (file)
@@ -386,6 +386,16 @@ void wxHtmlWordCell::Split(const wxDC& dc,
     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;
@@ -398,19 +408,26 @@ void wxHtmlWordCell::Split(const wxDC& dc,
         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++ ;
-#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;
-        if ( pt1.x >= 0 )
+        if ( pt1.x >= -charW/2 )
         {
             pos1 += charW;
             i++;
@@ -419,18 +436,25 @@ void wxHtmlWordCell::Split(const wxDC& dc,
 #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++ ;
-#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;
-        if ( pt2.x >= 0 )
+        if ( pt2.x >= -charW/2 )
         {
             pos2 += charW;
             j++;
@@ -440,6 +464,8 @@ void wxHtmlWordCell::Split(const wxDC& dc,
 
     pos1 = i;
     pos2 = j;
+
+    wxASSERT( pos2 >= pos1 );
 }
 
 void wxHtmlWordCell::SetSelectionPrivPos(const wxDC& dc, wxHtmlSelection *s) const
@@ -473,18 +499,18 @@ static void SwitchSelState(wxDC& dc, wxHtmlRenderingInfo& info,
 
     if ( toSelection )
     {
-        dc.SetBackgroundMode(wxSOLID);
+        dc.SetBackgroundMode(wxBRUSHSTYLE_SOLID);
         dc.SetTextForeground(info.GetStyle().GetSelectedTextColour(fg));
         dc.SetTextBackground(info.GetStyle().GetSelectedTextBgColour(bg));
         dc.SetBackground(wxBrush(info.GetStyle().GetSelectedTextBgColour(bg),
-                                 wxSOLID));
+                                 wxBRUSHSTYLE_SOLID));
     }
     else
     {
-        dc.SetBackgroundMode(wxTRANSPARENT);
+        dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
         dc.SetTextForeground(fg);
         dc.SetTextBackground(bg);
-        dc.SetBackground(wxBrush(bg, wxSOLID));
+        dc.SetBackground(wxBrush(bg, wxBRUSHSTYLE_SOLID));
     }
 }
 
@@ -555,12 +581,12 @@ void wxHtmlWordCell::Draw(wxDC& dc, int x, int y,
         wxHtmlSelectionState selstate = info.GetState().GetSelectionState();
         // Not changing selection state, draw the word in single mode:
         if ( selstate != wxHTML_SEL_OUT &&
-             dc.GetBackgroundMode() != wxSOLID )
+             dc.GetBackgroundMode() != wxBRUSHSTYLE_SOLID )
         {
             SwitchSelState(dc, info, true);
         }
         else if ( selstate == wxHTML_SEL_OUT &&
-                  dc.GetBackgroundMode() == wxSOLID )
+                  dc.GetBackgroundMode() == wxBRUSHSTYLE_SOLID )
         {
             SwitchSelState(dc, info, false);
         }
@@ -593,6 +619,17 @@ 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
 {
@@ -610,29 +647,77 @@ wxString wxHtmlWordCell::ConvertToText(wxHtmlSelection *s) const
         // TODO: but this really needs to be fixed in some better way later...
         if ( priv != wxDefaultPosition )
         {
-            int part1 = priv.x;
-            int part2 = priv.y;
-            return m_Word.Mid(part1, part2-part1);
+            const int part1 = priv.x;
+            const int part2 = priv.y;
+            if ( part1 == part2 )
+                return wxEmptyString;
+            return GetPartAsText(part1, part2);
         }
         //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
 //-----------------------------------------------------------------------------
@@ -731,7 +816,9 @@ void wxHtmlContainerCell::Layout(int 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
@@ -987,8 +1074,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_LastLayout = w;
 }
 
 void wxHtmlContainerCell::UpdateRenderingStatePre(wxHtmlRenderingInfo& info,
@@ -1029,7 +1114,7 @@ void wxHtmlContainerCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2,
 
     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);
@@ -1041,8 +1126,8 @@ void wxHtmlContainerCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2,
 
     if (m_UseBorder)
     {
-        wxPen mypen1(m_BorderColour1, 1, wxSOLID);
-        wxPen mypen2(m_BorderColour2, 1, wxSOLID);
+        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);
@@ -1429,13 +1514,13 @@ void wxHtmlColourCell::DrawInvisible(wxDC& dc,
         if (state.GetSelectionState() != wxHTML_SEL_IN)
         {
             dc.SetTextBackground(m_Colour);
-            dc.SetBackground(wxBrush(m_Colour, wxSOLID));
+            dc.SetBackground(wxBrush(m_Colour, wxBRUSHSTYLE_SOLID));
         }
         else
         {
             wxColour c = info.GetStyle().GetSelectedTextBgColour(m_Colour);
             dc.SetTextBackground(c);
-            dc.SetBackground(wxBrush(c, wxSOLID));
+            dc.SetBackground(wxBrush(c, wxBRUSHSTYLE_SOLID));
         }
     }
 }
@@ -1501,8 +1586,15 @@ void wxHtmlWidgetCell::Draw(wxDC& WXUNUSED(dc),
         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,
+                 _T("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);
 }