diff --git a/src/common/ctrlcmn.cpp b/src/common/ctrlcmn.cpp index 7768c08d70..8aabe0bfa7 100644 --- a/src/common/ctrlcmn.cpp +++ b/src/common/ctrlcmn.cpp @@ -282,7 +282,8 @@ namespace struct EllipsizeCalculator { EllipsizeCalculator(const wxString& s, const wxDC& dc, - int maxFinalWidthPx, int replacementWidthPx) + int maxFinalWidthPx, int replacementWidthPx, + int flags) : m_initialCharToRemove(0), m_nCharsToRemove(0), @@ -294,6 +295,31 @@ struct EllipsizeCalculator { m_isOk = dc.GetPartialTextExtents(s, m_charOffsetsPx); wxASSERT( m_charOffsetsPx.GetCount() == s.length() ); + + if ( flags & wxELLIPSIZE_FLAGS_PROCESS_MNEMONICS ) + { + // The ampersand itself shouldn't count for the width calculation + // as it won't be displayed: either it's an ampersand before some + // other character in which case it indicates a mnemonic, or it's + // an escaped ampersand, in which case only the second one of the + // pair of ampersands will be displayed. But we can't just remove + // the ampersand as we still need it in the final label, in order + // not to lose the mnemonics. Hence we use this hack, and pretend + // that ampersands simply have zero width. Of course, it could be + // not completely precise, but this is the best we can do without + // completely changing this code structure. + size_t n = 0; + int delta = 0; + for ( wxString::const_iterator it = s.begin(); + it != s.end(); + ++it, ++n ) + { + if ( *it == '&' ) + delta += dc.GetTextExtent(wxS('&')).GetWidth(); + + m_charOffsetsPx[n] -= delta; + } + } } bool IsOk() const { return m_isOk; } @@ -405,7 +431,7 @@ struct EllipsizeCalculator wxString DoEllipsizeSingleLine(const wxString& curLine, const wxDC& dc, wxEllipsizeMode mode, int maxFinalWidthPx, - int replacementWidthPx) + int replacementWidthPx, int flags) { wxASSERT_MSG(replacementWidthPx > 0, "Invalid parameters"); wxASSERT_LEVEL_2_MSG(!curLine.Contains('\n'), @@ -413,9 +439,6 @@ wxString DoEllipsizeSingleLine(const wxString& curLine, const wxDC& dc, wxASSERT_MSG( mode != wxELLIPSIZE_NONE, "shouldn't be called at all then" ); - // NOTE: this function assumes that any mnemonic/tab character has already - // been handled if it was necessary to handle them (see Ellipsize()) - if (maxFinalWidthPx <= 0) return wxEmptyString; @@ -423,7 +446,7 @@ wxString DoEllipsizeSingleLine(const wxString& curLine, const wxDC& dc, if (len <= 1 ) return curLine; - EllipsizeCalculator calc(curLine, dc, maxFinalWidthPx, replacementWidthPx); + EllipsizeCalculator calc(curLine, dc, maxFinalWidthPx, replacementWidthPx, flags); if ( !calc.IsOk() ) return curLine; @@ -545,7 +568,7 @@ wxString wxControlBase::Ellipsize(const wxString& label, const wxDC& dc, if ( pc == label.end() || *pc == wxS('\n') ) { curLine = DoEllipsizeSingleLine(curLine, dc, mode, maxFinalWidth, - replacementWidth); + replacementWidth, flags); // add this (ellipsized) row to the rest of the label ret << curLine; @@ -555,15 +578,6 @@ wxString wxControlBase::Ellipsize(const wxString& label, const wxDC& dc, ret << *pc; curLine.clear(); } - // we need to remove mnemonics from the label for correct calculations - else if ( *pc == wxS('&') && (flags & wxELLIPSIZE_FLAGS_PROCESS_MNEMONICS) ) - { - // pc+1 is safe: at worst we'll be at end() - wxString::const_iterator next = pc + 1; - if ( next != label.end() && *next == wxS('&') ) - curLine += wxS('&'); // && becomes & - //else: remove this ampersand - } // we need also to expand tabs to properly calc their size else if ( *pc == wxS('\t') && (flags & wxELLIPSIZE_FLAGS_EXPAND_TABS) ) {