+ wxColour fg = info.GetState().GetFgColour();
+ wxColour bg = info.GetState().GetBgColour();
+
+ if ( toSelection )
+ {
+ dc.SetBackgroundMode(wxBRUSHSTYLE_SOLID);
+ dc.SetTextForeground(info.GetStyle().GetSelectedTextColour(fg));
+ dc.SetTextBackground(info.GetStyle().GetSelectedTextBgColour(bg));
+ dc.SetBackground(wxBrush(info.GetStyle().GetSelectedTextBgColour(bg),
+ wxBRUSHSTYLE_SOLID));
+ }
+ else
+ {
+ dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
+ dc.SetTextForeground(fg);
+ dc.SetTextBackground(bg);
+ dc.SetBackground(wxBrush(bg, wxBRUSHSTYLE_SOLID));
+ }
+}
+
+
+void wxHtmlWordCell::Draw(wxDC& dc, int x, int y,
+ int WXUNUSED(view_y1), int WXUNUSED(view_y2),
+ wxHtmlRenderingInfo& info)
+{
+#if 0 // useful for debugging
+ dc.SetPen(*wxBLACK_PEN);
+ dc.DrawRectangle(x+m_PosX,y+m_PosY,m_Width /* VZ: +1? */ ,m_Height);
+#endif
+
+ bool drawSelectionAfterCell = false;
+
+ if ( info.GetState().GetSelectionState() == wxHTML_SEL_CHANGING )
+ {
+ // Selection changing, we must draw the word piecewise:
+ wxHtmlSelection *s = info.GetSelection();
+ wxString txt;
+ 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:
+ if ( priv == wxDefaultPosition )
+ {
+ SetSelectionPrivPos(dc, s);
+ priv = (this == s->GetFromCell()) ?
+ s->GetFromPrivPos() : s->GetToPrivPos();
+ }
+
+ int part1 = priv.x;
+ int part2 = priv.y;
+
+ if ( part1 > 0 )
+ {
+ txt = m_Word.Mid(0, part1);
+ dc.DrawText(txt, x + m_PosX, y + m_PosY);
+ dc.GetTextExtent(txt, &w, &h);
+ ofs += w;
+ }
+
+ SwitchSelState(dc, info, true);
+
+ txt = m_Word.Mid(part1, part2-part1);
+ dc.DrawText(txt, ofs + x + m_PosX, y + m_PosY);
+
+ if ( (size_t)part2 < m_Word.length() )
+ {
+ dc.GetTextExtent(txt, &w, &h);
+ ofs += w;
+ SwitchSelState(dc, info, false);
+ txt = m_Word.Mid(part2);
+ dc.DrawText(txt, ofs + x + m_PosX, y + m_PosY);
+ }
+ else
+ drawSelectionAfterCell = true;
+ }
+ else
+ {
+ wxHtmlSelectionState selstate = info.GetState().GetSelectionState();
+ // Not changing selection state, draw the word in single mode:
+ if ( selstate != wxHTML_SEL_OUT &&
+ dc.GetBackgroundMode() != wxBRUSHSTYLE_SOLID )
+ {
+ SwitchSelState(dc, info, true);
+ }
+ else if ( selstate == wxHTML_SEL_OUT &&
+ dc.GetBackgroundMode() == wxBRUSHSTYLE_SOLID )
+ {
+ SwitchSelState(dc, info, false);
+ }
+ dc.DrawText(m_Word, x + m_PosX, y + m_PosY);
+ drawSelectionAfterCell = (selstate != wxHTML_SEL_OUT);
+ }
+
+ // NB: If the text is justified then there is usually some free space
+ // between adjacent cells and drawing the selection only onto cells
+ // would result in ugly unselected spaces. The code below detects
+ // this special case and renders the selection *outside* the sell,
+ // too.
+ if ( m_Parent->GetAlignHor() == wxHTML_ALIGN_JUSTIFY &&
+ drawSelectionAfterCell )
+ {
+ wxHtmlCell *nextCell = m_Next;
+ while ( nextCell && nextCell->IsFormattingCell() )
+ nextCell = nextCell->GetNext();
+ if ( nextCell )
+ {
+ int nextX = nextCell->GetPosX();
+ if ( m_PosX + m_Width < nextX )
+ {
+ dc.SetBrush(dc.GetBackground());
+ dc.SetPen(*wxTRANSPARENT_PEN);
+ dc.DrawRectangle(x + m_PosX + m_Width, y + m_PosY,
+ nextX - m_PosX - m_Width, m_Height);
+ }
+ }
+ }
+}
+
+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()) )
+ {
+ 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
+ // seems to be the case now) and so it makes sense to select the
+ // entire contents of the cell in this case
+ //
+ // TODO: but this really needs to be fixed in some better way later...
+ if ( priv != wxDefaultPosition )
+ {
+ 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 GetAllAsText();
+}
+
+wxString wxHtmlWordWithTabsCell::GetAllAsText() const
+{
+ 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 )
+ {
+ if ( *i == '\t' )
+ {
+ pos += 8 - (m_linepos + pos) % SPACES_PER_TAB;
+ if ( pos >= begin )
+ {
+ sel += '\t';
+ }
+ }
+ else
+ {
+ ++pos;
+ }
+ }
+
+ // copy the content until we reach 'end':
+ for ( ; pos < end; ++i )
+ {
+ const wxChar c = *i;
+ sel += c;
+
+ if ( c == '\t' )
+ pos += 8 - (m_linepos + pos) % SPACES_PER_TAB;
+ else
+ ++pos;
+ }
+
+ return sel;