#pragma hdrstop
#endif
+#include "wx/textwrapper.h"
#include "wx/private/stattext.h"
#ifndef WX_PRECOMP
#include "wx/containr.h"
#endif
-#if wxUSE_STATTEXT
-
const wxChar *wxMarkupEntities[][wxMARKUP_ENTITY_MAX] =
{
// the entities handled by SetLabel() when wxST_MARKUP is used and their referenced string
{ wxT("&"), wxT("<"), wxT(">"), wxT("'"), wxT("\"") }
};
+#if wxUSE_STATTEXT
// ----------------------------------------------------------------------------
// wxTextWrapper
void wxTextWrapper::Wrap(wxWindow *win, const wxString& text, int widthMax)
{
- const wxChar *lastSpace = NULL;
wxString line;
- const wxChar *lineStart = text.c_str();
- for ( const wxChar *p = lineStart; ; p++ )
+ wxString::const_iterator lastSpace = text.end();
+ wxString::const_iterator lineStart = text.begin();
+ for ( wxString::const_iterator p = lineStart; ; ++p )
{
if ( IsStartOfNewLine() )
{
OnNewLine();
- lastSpace = NULL;
+ lastSpace = text.end();
line.clear();
lineStart = p;
}
- if ( *p == _T('\n') || *p == _T('\0') )
+ if ( p == text.end() || *p == wxT('\n') )
{
DoOutputLine(line);
- if ( *p == _T('\0') )
+ if ( p == text.end() )
break;
}
else // not EOL
{
- if ( *p == _T(' ') )
+ if ( *p == wxT(' ') )
lastSpace = p;
line += *p;
- if ( widthMax >= 0 && lastSpace )
+ if ( widthMax >= 0 && lastSpace != text.end() )
{
int width;
win->GetTextExtent(line, &width, NULL);
virtual void OnNewLine()
{
- m_text += _T('\n');
+ m_text += wxT('\n');
}
private:
return RemoveMnemonics(ret);
}
-/*static*/
+void wxStaticTextBase::SetLabelText(const wxString& text)
+{
+ wxString str = text;
+
+ if (HasFlag(wxST_MARKUP))
+ str = EscapeMarkup(str); // escapes markup and the & characters (which are also mnemonics)
+ else
+ str = EscapeMnemonics(text); // escape only the mnemonics
+ SetLabel(str);
+}
+
+/* static */
+wxString wxStaticTextBase::GetLabelText(const wxString& label)
+{
+ wxString ret = RemoveMarkup(label);
+ // always remove the markup (this function is static
+ // and cannot check for wxST_MARKUP presence/absence)
+
+ return RemoveMnemonics(ret);
+}
+
+/* static */
wxString wxStaticTextBase::RemoveMarkup(const wxString& text)
{
// strip out of "text" the markup for platforms which don't support it natively
bool inside_tag = false;
wxString label;
- const wxChar *source = text;
- for (size_t i=0, max=text.length(); i<max; i++)
+ for ( wxString::const_iterator source = text.begin();
+ source != text.end(); ++source )
{
- switch (source[i])
+ switch ( (*source).GetValue() )
{
case wxT('<'):
if (inside_tag)
case wxT('&'):
{
- if (i == max-1)
+ if ( source+1 == text.end() )
{
wxLogDebug(wxT("Cannot use & as last character of the string '%s'"),
text.c_str());
// is this ampersand introducing a mnemonic or rather an entity?
bool isMnemonic = true;
+ size_t distanceFromEnd = text.end() - source;
for (size_t j=0; j < wxMARKUP_ENTITY_MAX; j++)
{
const wxChar *entity = wxMarkupEntities[wxMARKUP_ELEMENT_NAME][j];
size_t entityLen = wxStrlen(entity);
- if (max - i >= entityLen &&
- wxStrncmp(entity, &source[i], entityLen) == 0)
+ if (distanceFromEnd >= entityLen &&
+ wxString(source, source + entityLen) == entity)
{
// replace the &entity; string with the entity reference
label << wxMarkupEntities[wxMARKUP_ELEMENT_VALUE][j];
-
- // little exception: when the entity reference is "&"
- // (i.e. when entity is "&"), substitute it with &&
- // instead of a single ampersand:
+ // little exception: when the entity reference is
+ // "&" (i.e. when entity is "&"), substitute it
+ // with && instead of a single ampersand:
if (*wxMarkupEntities[wxMARKUP_ELEMENT_VALUE][j] == wxT('&'))
label << wxT('&');
- i += entityLen - 1; // the -1 is because main for()
- // loop already increments i
+ // the -1 is because main for() loop already
+ // increments i:
+ source += entityLen - 1;
isMnemonic = false;
break;
}
}
if (isMnemonic)
- label << text[i];
+ label << *source;
}
break;
default:
if (!inside_tag)
- label << text[i];
+ label << *source;
}
}
{
wxString ret;
- for (const wxChar *source = text; *source != wxT('\0'); source++)
+ for (wxString::const_iterator source = text.begin();
+ source != text.end(); ++source)
{
bool isEntity = false;
}
-
// ----------------------------------------------------------------------------
// wxStaticTextBase - generic implementation for wxST_ELLIPSIZE_* support
// ----------------------------------------------------------------------------
// we need to touch the "real" label (i.e. the text set inside the control,
// using port-specific functions) instead of the string returned by GetLabel().
//
- // In fact, we must be careful not to touch the original label passed to
+ // In fact, we must be careful not to touch the original label passed to
// SetLabel() otherwise GetLabel() will behave in a strange way to the user
// (e.g. returning a "Ver...ing" instead of "Very long string") !
if (newlabel == DoGetLabel())
DoSetLabel(newlabel);
}
+wxString wxStaticTextBase::GetLabelWithoutMarkup() const
+{
+ wxString ret(m_labelOrig);
+
+ if (HasFlag(wxST_MARKUP))
+ ret = RemoveMarkup(ret);
+
+ // unlike GetLabelText() we don't remove the mnemonics here!
+ return ret;
+}
+
wxString wxStaticTextBase::GetEllipsizedLabelWithoutMarkup() const
{
// this function should be used only by ports which do not support
return ret;
}
-#define wxELLIPSE_REPLACEMENT wxT("...")
-
wxString wxStaticTextBase::Ellipsize(const wxString& label) const
{
wxSize sz(GetSize());
return label;
}
- wxClientDC dc(wx_const_cast(wxStaticTextBase*, this));
+ wxClientDC dc(const_cast<wxStaticTextBase*>(this));
dc.SetFont(GetFont());
- wxArrayInt charOffsets;
- wxString ret;
-
- // these cannot be cached as they can change because of e.g. a font change
- int replacementWidth = dc.GetTextExtent(wxELLIPSE_REPLACEMENT).GetWidth();
- int marginWidth = dc.GetCharWidth()*2;
-
- // handle correctly labels with newlines
- wxString curLine;
- wxSize reqsize;
- size_t len;
- for ( const wxChar *pc = label; ; pc++ )
+ wxEllipsizeMode mode;
+ if ( HasFlag(wxST_ELLIPSIZE_START) )
+ mode = wxELLIPSIZE_START;
+ else if ( HasFlag(wxST_ELLIPSIZE_MIDDLE) )
+ mode = wxELLIPSIZE_MIDDLE;
+ else if ( HasFlag(wxST_ELLIPSIZE_END) )
+ mode = wxELLIPSIZE_END;
+ else
{
- switch ( *pc )
- {
- case _T('\n'):
- case _T('\0'):
- len = curLine.length();
- if (len > 0 &&
- dc.GetPartialTextExtents(curLine, charOffsets))
- {
- wxASSERT(charOffsets.GetCount() == len);
-
- size_t totalWidth = charOffsets.Last();
- if ( totalWidth > (size_t)sz.GetWidth() )
- {
- // we need to ellipsize this row
- int excessPixels = totalWidth - sz.GetWidth() +
- replacementWidth +
- marginWidth; // security margin (NEEDED!)
-
- // remove characters in excess
- size_t initialChar, // index of first char to erase
- nChars; // how many chars do we need to erase?
- if (HasFlag(wxST_ELLIPSIZE_START))
- {
- initialChar = 0;
- for (nChars=0;
- nChars < len && charOffsets[nChars] < excessPixels;
- nChars++)
- ;
- }
- else if (HasFlag(wxST_ELLIPSIZE_MIDDLE))
- {
- // the start & end of the removed span of chars
- initialChar = len/2;
- size_t endChar = len/2;
-
- int removed = 0;
- for ( ; removed < excessPixels; )
- {
- if (initialChar > 0)
- {
- // width of the initialChar-th character
- int width = charOffsets[initialChar] -
- charOffsets[initialChar-1];
-
- // remove the initialChar-th character
- removed += width;
- initialChar--;
- }
-
- if (endChar < len - 1 &&
- removed < excessPixels)
- {
- // width of the (endChar+1)-th character
- int width = charOffsets[endChar+1] -
- charOffsets[endChar];
-
- // remove the endChar-th character
- removed += width;
- endChar++;
- }
-
- if (initialChar == 0 && endChar == len-1)
- {
- nChars = len+1;
- break;
- }
- }
-
- initialChar++;
- nChars = endChar - initialChar + 1;
- }
- else
- {
- wxASSERT(HasFlag(wxST_ELLIPSIZE_END));
- wxASSERT(len > 0);
+ wxFAIL_MSG( "should only be called if have one of wxST_ELLIPSIZE_XXX" );
- int maxWidth = totalWidth - excessPixels;
- for (initialChar=0;
- initialChar < len &&
- charOffsets[initialChar] < maxWidth;
- initialChar++)
- ;
-
- if (initialChar == 0)
- {
- nChars = len;
- }
- else
- {
- initialChar--; // go back one character
- nChars = len - initialChar;
- }
- }
-
- if (nChars > len)
- {
- // need to remove the entire row!
- curLine.clear();
- }
- else
- {
- // erase nChars characters after initialChar (included):
- curLine.erase(initialChar, nChars+1);
-
- // if there is space for the replacement dots, add them
- if (sz.GetWidth() > replacementWidth)
- curLine.insert(initialChar, wxELLIPSE_REPLACEMENT);
- }
-
- // if everything was ok, we should have shortened this line
- // enough to make it fit in sz.GetWidth():
- wxASSERT(dc.GetTextExtent(curLine).GetWidth() < sz.GetWidth());
- }
- }
-
- // add this (ellipsized) row to the rest of the label
- ret << curLine << *pc;
- curLine.clear();
-
- if ( *pc == _T('\0') )
- return ret;
-
- break;
-
- // we need to remove mnemonics from the label for
- // correct calculations
- case _T('&'):
- // pc+1 is safe: at worst we'll hit the \0
- if (*(pc+1) == _T('&'))
- curLine += _T('&'); // && becomes &
- //else: remove this ampersand
-
- break;
-
- // we need also to expand tabs to properly calc their size
- case _T('\t'):
- // Windows natively expands the TABs to 6 spaces. Do the same:
- curLine += wxT(" ");
- break;
-
- default:
- curLine += *pc;
- }
+ return label;
}
- //return ret;
+ return wxControl::Ellipsize(label, dc, mode, sz.GetWidth());
}
#endif // wxUSE_STATTEXT