[Git][wxwidgets/wxwidgets][master] 3 commits: Fix broken link to manifest documentation in high DPI overview

2 views
Skip to first unread message

Vadim Zeitlin (@_VZ_)

unread,
Jan 29, 2026, 2:33:27 PMJan 29
to wx-commi...@googlegroups.com

Vadim Zeitlin pushed to branch master at wxWidgets / wxWidgets

Commits:

  • 5b02ee84
    by Vadim Zeitlin at 2026-01-29T14:20:45+01:00
    Fix broken link to manifest documentation in high DPI overview
    
    This was inadvertently removed in d3db9fd755 (Try to make wxMSW high DPI
    manifest documentation more useful, 2024-09-17).
    
  • 98aea070
    by Vadim Zeitlin at 2026-01-29T20:02:16+01:00
    Regenerate nmake makefile broken by recent change
    
    This got somehow broken by 6228eaf449 (Add support for using LunaSVG for
    SVG rasterization, 2025-08-27), rebake to fix it.
    
    Closes #26128.
    
  • c9696340
    by Joshua Lee Ockert at 2026-01-29T20:11:54+01:00
    wxRichTextCtrl: Fix selection jitter on macOS
    
    On macOS, selecting text in wxRichTextCtrl caused visible horizontal
    jitter as the text shifted left and right during selection. This was
    caused by splitting DrawText() calls at selection boundaries, which
    made each text chunk get shaped independently with different kerning.
    
    This commit changes DrawTabbedString() to render text in a single pass
    (splitting only at tabs), eliminating the kerning discontinuities that
    caused jitter under macOS.
    
    It also has the side-effect of cleaning up a lot of the non-Mac-specific
    code to be clearer and easier to understand.
    
    The implementation matches native macOS behavior where selected text
    maintains its original styling (like TextEdit in Rich Text mode), with
    the selection highlight drawn as a background rectangle that completely
    overrides any text background colors in the selected range.
    
    See #22771 (unable to reproduce on Windows, but confirmed on macOS)
    
    Closes #26105.
    

4 changed files:

Changes:

  • build/msw/makefile.vc
    ... ... @@ -2046,7 +2046,7 @@ STCLIB_OBJECTS = \
    2046 2046
     	$(OBJS)\stclib_ScintillaWX.obj \
    
    2047 2047
     	$(OBJS)\stclib_xh_styledtextctrl.obj \
    
    2048 2048
     	$(OBJS)\stclib_minimap.obj
    
    2049
    -GLDLL_CXXFLAGS = /M$(__RUNTIME_LIBS_642)$(__DEBUGRUNTIME) /DWIN32 \
    
    2049
    +GLDLL_CXXFLAGS = /M$(__RUNTIME_LIBS_657)$(__DEBUGRUNTIME) /DWIN32 \
    
    2050 2050
     	/I..\..\src\tiff\libtiff /I..\..\src\jpeg /I..\..\src\png \
    
    2051 2051
     	/I..\..\3rdparty\libwebp\src $(____INC_LUNASVG_FILENAMES) /I..\..\src\zlib \
    
    2052 2052
     	/I..\..\3rdparty\pcre\src\wx /I..\..\src\expat\expat\lib $(__DEBUGINFO) \
    

  • docs/doxygen/overviews/high_dpi.md
    ... ... @@ -330,6 +330,7 @@ Windows 10 version 1703 or later. It is also possible to use
    330 330
     support for system DPI, see [MSDN documentation][msw-highdpi] for more
    
    331 331
     information about different levels of DPI awareness.
    
    332 332
     
    
    333
    +[msw-manifest]: https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests
    
    333 334
     [msw-highdpi]: https://docs.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows
    
    334 335
     
    
    335 336
     macOS                               {#high_dpi_platform_mac}
    

  • include/wx/richtext/richtextbuffer.h
    ... ... @@ -4765,7 +4765,7 @@ public:
    4765 4765
         wxNODISCARD virtual wxRichTextObject* Clone() const override { return new wxRichTextPlainText(*this); }
    
    4766 4766
     
    
    4767 4767
     private:
    
    4768
    -    bool DrawTabbedString(wxDC& dc, const wxRichTextAttr& attr, const wxRect& rect, wxString& str, wxCoord& x, wxCoord& y, bool selected);
    
    4768
    +    void DrawTabbedString(wxDC& dc, const wxRichTextAttr& attr, const wxRect& rect, wxString& str, wxCoord& x, wxCoord& y, ssize_t selStart, ssize_t selEnd);
    
    4769 4769
     
    
    4770 4770
     protected:
    
    4771 4771
         wxString    m_text;
    

  • src/richtext/richtextbuffer.cpp
    ... ... @@ -6934,234 +6934,257 @@ bool wxRichTextPlainText::Draw(wxDC& dc, wxRichTextDrawingContext& context, cons
    6934 6934
             y = rect.y + (rect.height - charHeight - (descent - m_descent));
    
    6935 6935
         }
    
    6936 6936
     
    
    6937
    -    // TODO: new selection code
    
    6938
    -
    
    6939 6937
         // (a) All selected.
    
    6940 6938
         if (allSelected)
    
    6941 6939
         {
    
    6942
    -        DrawTabbedString(dc, textAttr, rect, stringChunk, x, y, true);
    
    6940
    +        DrawTabbedString(dc, textAttr, rect, stringChunk, x, y, 0, stringChunk.length() - 1);
    
    6943 6941
         }
    
    6944 6942
         // (b) None selected.
    
    6945 6943
         else if (noneSelected)
    
    6946 6944
         {
    
    6947 6945
             // Draw all unselected
    
    6948
    -        DrawTabbedString(dc, textAttr, rect, stringChunk, x, y, false);
    
    6946
    +        DrawTabbedString(dc, textAttr, rect, stringChunk, x, y, -1, -1);
    
    6949 6947
         }
    
    6950 6948
         else
    
    6951 6949
         {
    
    6952
    -        // (c) Part selected, part not
    
    6953
    -        // Let's draw unselected chunk, selected chunk, then unselected chunk.
    
    6954
    -
    
    6955
    -        const wxString& str = stringWhole;
    
    6956
    -
    
    6957
    -        dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
    
    6958
    -
    
    6959
    -        // 1. Initial unselected chunk, if any, up until start of selection.
    
    6960
    -        if (selectionRange.GetStart() > range.GetStart() && selectionRange.GetStart() <= range.GetEnd())
    
    6961
    -        {
    
    6962
    -            int r1 = range.GetStart();
    
    6963
    -            int s1 = selectionRange.GetStart()-1;
    
    6964
    -            int fragmentLen = s1 - r1 + 1;
    
    6965
    -            if (fragmentLen < 0)
    
    6966
    -            {
    
    6967
    -                wxLogDebug(wxT("Mid(%d, %d"), (int)(r1 - offset), (int)fragmentLen);
    
    6968
    -            }
    
    6969
    -            wxString stringFragment = str.Mid(r1 - offset, fragmentLen);
    
    6970
    -
    
    6971
    -            DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, false);
    
    6972
    -
    
    6973
    -#if USE_KERNING_FIX
    
    6974
    -            if (stringChunk.Find(wxT("\t")) == wxNOT_FOUND)
    
    6975
    -            {
    
    6976
    -                // Compensate for kerning difference
    
    6977
    -                wxString stringFragment2(str.Mid(r1 - offset, fragmentLen+1));
    
    6978
    -                wxString stringFragment3(str.Mid(r1 - offset + fragmentLen, 1));
    
    6950
    +        const int selStart = wxMax(selectionRange.GetStart(), range.GetStart()) - range.GetStart();
    
    6951
    +        const int selEnd = wxMin(selectionRange.GetEnd(),   range.GetEnd()) - range.GetStart();
    
    6952
    +        DrawTabbedString(dc, textAttr, rect, stringChunk, x, y, selStart, selEnd);
    
    6953
    +    }
    
    6979 6954
     
    
    6980
    -                wxCoord w1, h1, w2, h2, w3, h3;
    
    6981
    -                dc.GetTextExtent(stringFragment,  & w1, & h1);
    
    6982
    -                dc.GetTextExtent(stringFragment2, & w2, & h2);
    
    6983
    -                dc.GetTextExtent(stringFragment3, & w3, & h3);
    
    6955
    +    return true;
    
    6956
    +}
    
    6984 6957
     
    
    6985
    -                int kerningDiff = (w1 + w3) - w2;
    
    6986
    -                x = x - kerningDiff;
    
    6987
    -            }
    
    6988
    -#endif
    
    6989
    -        }
    
    6958
    +void wxRichTextPlainText::DrawTabbedString(wxDC& dc, const wxRichTextAttr& attr, const wxRect& rect, wxString& str, wxCoord& x, wxCoord& y, ssize_t selStart, ssize_t selEnd)
    
    6959
    +{
    
    6960
    +    //////////////////////////////////////////////////////////////////////////
    
    6961
    +    // This function assumes str has uniform formatting (attr applies to    //
    
    6962
    +    // the entire string). The calling code should split text into style    //
    
    6963
    +    // runs before calling this function.                                   //
    
    6964
    +    //////////////////////////////////////////////////////////////////////////
    
    6965
    +
    
    6966
    +    wxColour selClr     = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
    
    6967
    +    wxColour txtForeClr = attr.HasTextColour() && attr.GetTextColour().IsOk()
    
    6968
    +                            ? attr.GetTextColour()
    
    6969
    +                            : wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
    
    6970
    +    wxColour txtBackClr = attr.HasBackgroundColour() && attr.GetBackgroundColour().IsOk()
    
    6971
    +                            ? attr.GetBackgroundColour()
    
    6972
    +                            : wxTransparentColour;
    
    6973
    +    int      txtBackMod = attr.HasBackgroundColour() && attr.GetBackgroundColour().IsOk()
    
    6974
    +                            ? wxBRUSHSTYLE_SOLID
    
    6975
    +                            : wxBRUSHSTYLE_TRANSPARENT;
    
    6976
    +    wxCoord  originx    = GetParent()->GetPosition().x;
    
    6977
    +    wxArrayInt startpos;  // Character starting positions
    
    6978
    +    wxArrayInt endpos;    // Character ending positions (cumulative widths)
    
    6979
    +    wxArrayInt tabstops;  // Array of tab stop positions
    
    6980
    +
    
    6981
    +    const bool strikethrough = (attr.GetTextEffects() & wxTEXT_ATTR_EFFECT_STRIKETHROUGH) != 0;
    
    6982
    +    const int strikeheight = wxRound(0.5 * rect.GetHeight() + rect.y);
    
    6983
    +    size_t effectivetabstop;
    
    6984
    +    int posadjustment;
    
    6985
    +    size_t printstart;
    
    6986
    +    size_t  i  = 0;  // initialization iterator
    
    6987
    +    size_t  si = 0;  // string iterator
    
    6988
    +    size_t  ti = 0;  // tabstop iterator
    
    6989
    +    size_t  pi = 0;  // position iterator
    
    6990
    +
    
    6991
    +
    
    6992
    +    //////////////////////////////////////////////////////////////////////////
    
    6993
    +    //                    Initial setup & early returns                     //
    
    6994
    +    //////////////////////////////////////////////////////////////////////////
    
    6995
    +
    
    6996
    +    if (str.empty())
    
    6997
    +        return;
    
    6990 6998
     
    
    6991
    -        // 2. Selected chunk, if any.
    
    6992
    -        if (selectionRange.GetEnd() >= range.GetStart())
    
    6993
    -        {
    
    6994
    -            int s1 = wxMax(selectionRange.GetStart(), range.GetStart());
    
    6995
    -            int s2 = wxMin(selectionRange.GetEnd(), range.GetEnd());
    
    6999
    +    // Get character ending positions
    
    7000
    +    dc.GetPartialTextExtents(str, endpos);
    
    7001
    +    startpos.SetCount(endpos.GetCount());
    
    6996 7002
     
    
    6997
    -            int fragmentLen = s2 - s1 + 1;
    
    6998
    -            if (fragmentLen < 0)
    
    6999
    -            {
    
    7000
    -                wxLogDebug(wxT("Mid(%d, %d"), (int)(s1 - offset), (int)fragmentLen);
    
    7001
    -            }
    
    7002
    -            wxString stringFragment = str.Mid(s1 - offset, fragmentLen);
    
    7003
    +    startpos[0] = x;
    
    7004
    +    for (i = 0; i < endpos.GetCount() - 1; i++)
    
    7005
    +    {
    
    7006
    +        endpos[i] = x + endpos[i];
    
    7007
    +        startpos[i+1] = endpos[i];
    
    7008
    +    }
    
    7009
    +    endpos[i] = x + endpos[i];
    
    7003 7010
     
    
    7004
    -            DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, true);
    
    7011
    +    // Get all of the tabstops
    
    7012
    +    tabstops = attr.GetTabs().IsEmpty()
    
    7013
    +                    ? wxRichTextParagraph::GetDefaultTabs()
    
    7014
    +                    : attr.GetTabs();
    
    7015
    +    const size_t tabcount = tabstops.GetCount();
    
    7016
    +    for (i = 0; i < tabcount; i++)
    
    7017
    +        tabstops[i] = originx + ConvertTenthsMMToPixels(dc, tabstops[i]);
    
    7005 7018
     
    
    7006
    -#if USE_KERNING_FIX
    
    7007
    -            if (stringChunk.Find(wxT("\t")) == wxNOT_FOUND)
    
    7008
    -            {
    
    7009
    -                // Compensate for kerning difference
    
    7010
    -                wxString stringFragment2(str.Mid(s1 - offset, fragmentLen+1));
    
    7011
    -                wxString stringFragment3(str.Mid(s1 - offset + fragmentLen, 1));
    
    7012 7019
     
    
    7013
    -                wxCoord w1, h1, w2, h2, w3, h3;
    
    7014
    -                dc.GetTextExtent(stringFragment,  & w1, & h1);
    
    7015
    -                dc.GetTextExtent(stringFragment2, & w2, & h2);
    
    7016
    -                dc.GetTextExtent(stringFragment3, & w3, & h3);
    
    7020
    +    //////////////////////////////////////////////////////////////////////////
    
    7021
    +    //                    Tab stop position adjustments                     //
    
    7022
    +    //////////////////////////////////////////////////////////////////////////
    
    7017 7023
     
    
    7018
    -                int kerningDiff = (w1 + w3) - w2;
    
    7019
    -                x = x - kerningDiff;
    
    7020
    -            }
    
    7021
    -#endif
    
    7022
    -        }
    
    7024
    +    // Adjust horizontal positions to account for tab stops.
    
    7025
    +    // Do this by looping through to find every tab character, calculate the
    
    7026
    +    // appropriate tab stop for it, measure the horizontal space difference,
    
    7027
    +    // and adjust the tab's ending position and the start/end positions of
    
    7028
    +    // every character after it.
    
    7029
    +    //
    
    7030
    +    // BL: Tab Char --> Tab Stop --> Pixel Adjustment --> New startpos/endpos
    
    7031
    +    //
    
    7032
    +    // NOTE: TODO: This almost certainly does not work for RTL languages
    
    7033
    +    // unless wxDC has some real x-flipping magic.
    
    7034
    +    for (si = 0; si < str.length(); si++)
    
    7035
    +    {
    
    7023 7036
     
    
    7024
    -        // 3. Remaining unselected chunk, if any
    
    7025
    -        if (selectionRange.GetEnd() < range.GetEnd())
    
    7037
    +        if (str[si] == '\t')
    
    7026 7038
             {
    
    7027
    -            int s2 = wxMin(selectionRange.GetEnd()+1, range.GetEnd());
    
    7028
    -            int r2 = range.GetEnd();
    
    7039
    +            // We have a tab. Find the next tab stop AFTER this tab's start position.
    
    7040
    +            // NOTE: ti is monotonic.
    
    7041
    +            while (ti < tabcount && tabstops[ti] <= startpos[si])
    
    7042
    +                ti++;
    
    7029 7043
     
    
    7030
    -            int fragmentLen = r2 - s2 + 1;
    
    7031
    -            if (fragmentLen < 0)
    
    7032
    -            {
    
    7033
    -                wxLogDebug(wxT("Mid(%d, %d"), (int)(s2 - offset), (int)fragmentLen);
    
    7034
    -            }
    
    7035
    -            wxString stringFragment = str.Mid(s2 - offset, fragmentLen);
    
    7036
    -
    
    7037
    -            DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, false);
    
    7038
    -        }
    
    7039
    -    }
    
    7044
    +            // If we found a valid tab stop before reaching the end of the list, use that.
    
    7045
    +            if (ti < tabcount)
    
    7046
    +                effectivetabstop = tabstops[ti];
    
    7040 7047
     
    
    7041
    -    return true;
    
    7042
    -}
    
    7043
    -
    
    7044
    -bool wxRichTextPlainText::DrawTabbedString(wxDC& dc, const wxRichTextAttr& attr, const wxRect& rect,wxString& str, wxCoord& x, wxCoord& y, bool selected)
    
    7045
    -{
    
    7046
    -    bool hasTabs = (str.Find(wxT('\t')) != wxNOT_FOUND);
    
    7048
    +            // Otherwise use the default tab width.
    
    7049
    +            else
    
    7050
    +                effectivetabstop = startpos[si] + ConvertTenthsMMToPixels(dc, WIDTH_FOR_DEFAULT_TABS);
    
    7051
    +
    
    7052
    +            // Adjust position calculations accordingly
    
    7053
    +            posadjustment = effectivetabstop - endpos[si];
    
    7054
    +            endpos[si] += posadjustment;
    
    7055
    +            for (pi = si + 1; pi < endpos.GetCount(); pi++)
    
    7056
    +            {
    
    7057
    +                startpos[pi] += posadjustment;
    
    7058
    +                endpos[pi] += posadjustment;
    
    7059
    +            }
    
    7060
    +        }
    
    7061
    +    }
    
    7062
    +
    
    7063
    +//////////////////////////////////////////////////////////////////////////////
    
    7064
    +//                   PLATFORM-SPECIFIC SELECTION HANDLING                   //
    
    7065
    +//////////////////////////////////////////////////////////////////////////////
    
    7066
    +// We face different challenges on different platforms:
    
    7067
    +//     1.  On most platforms, the text foreground color changes when selected;
    
    7068
    +//         as a result, we MUST make a separate DrawText() call for it or it
    
    7069
    +//         won't render as expected.
    
    7070
    +//     2.  On Mac, aggressive font-shaping means that breaking up DrawText()
    
    7071
    +//         calls causes kerning-induced left-right jitter as text is selected
    
    7072
    +//         (e.g., DrawText("AB") DrawText("CD") isn't the same canvas width as
    
    7073
    +//         (DrawText("ABC") DrawText("D")). However, luckily, Mac does NOT use
    
    7074
    +//         or need a different foreground color for text, so we don't NEED to
    
    7075
    +//         break up the DrawText() calls.
    
    7076
    +//     3.  However, caveat: selection highlights DO override the background
    
    7077
    +//         color on Mac, so if we use DrawText() for the background color, we
    
    7078
    +//         still need separate DrawText() calls on Mac. We address this by
    
    7079
    +//         MANUALLY drawing text backgrounds on Mac (BEFORE drawing the
    
    7080
    +//         selection highlight, so the selection highlight overwrites it),
    
    7081
    +//         rather than using DrawText()'s background drawing capability.
    
    7082
    +#ifdef __WXMAC__
    
    7083
    +    //////////////////////////////////////////////////////////////////////////
    
    7084
    +    //                      Mac: Draw text background                       //
    
    7085
    +    //////////////////////////////////////////////////////////////////////////
    
    7047 7086
     
    
    7048
    -    wxArrayInt tabArray;
    
    7049
    -    int tabCount;
    
    7050
    -    if (hasTabs)
    
    7051 7087
         {
    
    7052
    -        if (attr.GetTabs().IsEmpty())
    
    7053
    -            tabArray = wxRichTextParagraph::GetDefaultTabs();
    
    7054
    -        else
    
    7055
    -            tabArray = attr.GetTabs();
    
    7056
    -        tabCount = tabArray.GetCount();
    
    7057
    -
    
    7058
    -        for (int i = 0; i < tabCount; ++i)
    
    7059
    -        {
    
    7060
    -            int pos = tabArray[i];
    
    7061
    -            pos = ConvertTenthsMMToPixels(dc, pos);
    
    7062
    -            tabArray[i] = pos;
    
    7063
    -        }
    
    7088
    +        int backgroundWidth = endpos[endpos.GetCount() - 1] - startpos[0] + 1; // Avoid kerning gaps
    
    7089
    +        wxDCBrushChanger autobrush(dc, wxBrush(txtBackClr));
    
    7090
    +        wxDCPenChanger autopen(dc, wxPen(txtBackClr));
    
    7091
    +        dc.DrawRectangle(startpos[0], y, backgroundWidth, dc.GetTextExtent(str).y);
    
    7092
    +        txtBackMod = wxBRUSHSTYLE_TRANSPARENT;
    
    7064 7093
         }
    
    7065
    -    else
    
    7066
    -        tabCount = 0;
    
    7067 7094
     
    
    7068
    -    wxCoord w, h;
    
    7095
    +    ///////////////////////////////////////////////////////////////////////////
    
    7096
    +    //                     Mac: Draw selection rectangle                     //
    
    7097
    +    ///////////////////////////////////////////////////////////////////////////
    
    7069 7098
     
    
    7070
    -    if (selected)
    
    7099
    +    if (0 <= selStart && selStart <= selEnd && selEnd < endpos.GetCount())
    
    7071 7100
         {
    
    7072
    -        wxColour highlightColour(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT));
    
    7073
    -        wxColour highlightTextColour(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT));
    
    7074
    -
    
    7075
    -        wxCheckSetBrush(dc, wxBrush(highlightColour));
    
    7076
    -        wxCheckSetPen(dc, wxPen(highlightColour));
    
    7077
    -        dc.SetTextForeground(highlightTextColour);
    
    7078
    -        dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
    
    7101
    +        int selectionWidth = endpos[selEnd] - startpos[selStart] + 1; // Avoid kerning gaps
    
    7102
    +        wxDCBrushChanger autobrush(dc, wxBrush(selClr));
    
    7103
    +        wxDCPenChanger autopen(dc, wxPen(selClr));
    
    7104
    +        dc.DrawRectangle(startpos[selStart], rect.y, selectionWidth, rect.GetHeight());
    
    7079 7105
         }
    
    7080
    -    else
    
    7106
    +#else
    
    7107
    +    // If str is entirely selected or not selected at all, we can print it
    
    7108
    +    // out in just one DrawText() call. However, if it's PARTIALLY selected,
    
    7109
    +    // we will need separate DrawText() calls. The easiest way to do this is
    
    7110
    +    // to call ourselves re-entrantly on (1) text before the selection,
    
    7111
    +    // (2) selected text, and (3) text after the selection.
    
    7112
    +    //
    
    7113
    +    // TODO: When dealing with combined LTR and RTL text there will be a
    
    7114
    +    // portion of selected text that is not contiguous with the rest, so we
    
    7115
    +    // will need to fix that eventually. E.g., if the first six characters of
    
    7116
    +    // "Yes, حبيبي, of course" are selected, then the selection rectangle(s)
    
    7117
    +    // will cover the underlined characters:  Yes, حبيبي, of course
    
    7118
    +    //                                        -----    -
    
    7119
    +    if (selStart == -1 && selEnd == -1)
    
    7081 7120
         {
    
    7082
    -        dc.SetTextForeground(attr.GetTextColour());
    
    7121
    +        // Nothing is selected; leave existing setup in place.
    
    7122
    +    }
    
    7083 7123
     
    
    7084
    -        if (attr.HasFlag(wxTEXT_ATTR_BACKGROUND_COLOUR) && attr.GetBackgroundColour().IsOk())
    
    7085
    -        {
    
    7086
    -            dc.SetBackgroundMode(wxBRUSHSTYLE_SOLID);
    
    7087
    -            dc.SetTextBackground(attr.GetBackgroundColour());
    
    7088
    -        }
    
    7089
    -        else
    
    7090
    -            dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
    
    7124
    +    else if (selStart == 0 && selEnd == (static_cast<ssize_t>(str.length()) - 1))
    
    7125
    +    {
    
    7126
    +        // Everything is selected; change the colors we'll use to draw text.
    
    7127
    +        txtForeClr = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
    
    7128
    +        txtBackClr = selClr;
    
    7129
    +        txtBackMod = wxBRUSHSTYLE_SOLID;
    
    7091 7130
         }
    
    7092 7131
     
    
    7093
    -    wxCoord x_orig = GetParent()->GetPosition().x;
    
    7094
    -    while (hasTabs)
    
    7132
    +    else
    
    7095 7133
         {
    
    7096
    -        // the string has a tab
    
    7097
    -        // break up the string at the Tab
    
    7098
    -        wxString stringChunk = str.BeforeFirst(wxT('\t'));
    
    7099
    -        str = str.AfterFirst(wxT('\t'));
    
    7100
    -        dc.GetTextExtent(stringChunk, & w, & h);
    
    7101
    -        int tabPos;
    
    7102
    -        tabPos = x + w;
    
    7103
    -        bool not_found = true;
    
    7104
    -        for (int i = 0; i < tabCount && not_found; ++i)
    
    7105
    -        {
    
    7106
    -            int nextTabPos;
    
    7107
    -            nextTabPos = tabArray.Item(i) + x_orig;
    
    7134
    +        // Partial selection; break it up into component parts.
    
    7135
    +        wxString selPrefix = str.Mid(0, selStart);
    
    7136
    +        wxString selString = str.Mid(selStart, selEnd - selStart + 1);
    
    7137
    +        wxString selSuffix = str.Mid(selEnd + 1);
    
    7108 7138
     
    
    7109
    -            // Find the next tab position.
    
    7110
    -            // Even if we're at the end of the tab array, we must still draw the chunk.
    
    7139
    +        if (!selPrefix.empty())
    
    7140
    +            DrawTabbedString(dc, attr, rect, selPrefix, x, y, -1, -1);
    
    7111 7141
     
    
    7112
    -            if (nextTabPos > tabPos || (i == (tabCount - 1)))
    
    7113
    -            {
    
    7114
    -                if (nextTabPos <= tabPos)
    
    7115
    -                {
    
    7116
    -                    int defaultTabWidth = ConvertTenthsMMToPixels(dc, WIDTH_FOR_DEFAULT_TABS);
    
    7117
    -                    nextTabPos = tabPos + defaultTabWidth;
    
    7118
    -                }
    
    7142
    +        x = startpos[selStart];
    
    7119 7143
     
    
    7120
    -                not_found = false;
    
    7121
    -                if (selected)
    
    7122
    -                {
    
    7123
    -                    w = nextTabPos - x;
    
    7124
    -                    wxRect selRect(x, rect.y, w, rect.GetHeight());
    
    7125
    -                    dc.DrawRectangle(selRect);
    
    7126
    -                }
    
    7127
    -                dc.DrawText(stringChunk, x, y);
    
    7144
    +        if (!selString.empty())
    
    7145
    +            DrawTabbedString(dc, attr, rect, selString, x, y, 0, selString.length() - 1);
    
    7128 7146
     
    
    7129
    -                if (attr.HasTextEffects() && (attr.GetTextEffects() & wxTEXT_ATTR_EFFECT_STRIKETHROUGH))
    
    7130
    -                {
    
    7131
    -                    wxPen oldPen = dc.GetPen();
    
    7132
    -                    wxCheckSetPen(dc, wxPen(attr.GetTextColour(), 1));
    
    7133
    -                    dc.DrawLine(x, (int) (y+(h/2)+0.5), x+w, (int) (y+(h/2)+0.5));
    
    7134
    -                    wxCheckSetPen(dc, oldPen);
    
    7135
    -                }
    
    7147
    +        x = endpos[selEnd];
    
    7136 7148
     
    
    7137
    -                x = nextTabPos;
    
    7138
    -            }
    
    7139
    -        }
    
    7140
    -        hasTabs = (str.Find(wxT('\t')) != wxNOT_FOUND);
    
    7149
    +        if (!selSuffix.empty())
    
    7150
    +            DrawTabbedString(dc, attr, rect, selSuffix, x, y, -1, -1);
    
    7151
    +
    
    7152
    +        return;
    
    7141 7153
         }
    
    7154
    +#endif
    
    7142 7155
     
    
    7143
    -    if (!str.IsEmpty())
    
    7144
    -    {
    
    7145
    -        dc.GetTextExtent(str, & w, & h);
    
    7146
    -        if (selected)
    
    7147
    -        {
    
    7148
    -            wxRect selRect(x, rect.y, w, rect.GetHeight());
    
    7149
    -            dc.DrawRectangle(selRect);
    
    7150
    -        }
    
    7151
    -        dc.DrawText(str, x, y);
    
    7156
    +    //////////////////////////////////////////////////////////////////////////
    
    7157
    +    //                    Draw text (and strikethrough)                     //
    
    7158
    +    //////////////////////////////////////////////////////////////////////////
    
    7152 7159
     
    
    7153
    -        if (attr.HasTextEffects() && (attr.GetTextEffects() & wxTEXT_ATTR_EFFECT_STRIKETHROUGH))
    
    7160
    +    printstart = 0;
    
    7161
    +    dc.SetBackgroundMode(txtBackMod);
    
    7162
    +    dc.SetTextBackground(txtBackClr);
    
    7163
    +    dc.SetTextForeground(txtForeClr);
    
    7164
    +    wxDCPenChanger penWithCleanup(dc, wxPen(txtForeClr)); // For strikethrough
    
    7165
    +    for (si = 0; si < str.length(); si++)
    
    7166
    +    {
    
    7167
    +        if (str[si] == '\t')
    
    7154 7168
             {
    
    7155
    -            wxPen oldPen = dc.GetPen();
    
    7156
    -            wxCheckSetPen(dc, wxPen(attr.GetTextColour(), 1));
    
    7157
    -            dc.DrawLine(x, (int) (y+(h/2)+0.5), x+w, (int) (y+(h/2)+0.5));
    
    7158
    -            wxCheckSetPen(dc, oldPen);
    
    7169
    +            if (si - printstart > 0)
    
    7170
    +            {
    
    7171
    +                dc.DrawText(str.Mid(printstart, si-printstart), startpos[printstart], y);
    
    7172
    +                if (strikethrough)
    
    7173
    +                    dc.DrawLine(startpos[printstart], strikeheight, startpos[si], strikeheight);
    
    7174
    +            }
    
    7175
    +            // Match original behavior of only striking through SELECTED tabs.
    
    7176
    +            // TODO: Research and decide whether to keep doing this.
    
    7177
    +            if (selStart <= static_cast<ssize_t>(si) && static_cast<ssize_t>(si) <= selEnd && strikethrough)
    
    7178
    +                dc.DrawLine(startpos[si], strikeheight, endpos[si], strikeheight);
    
    7179
    +            printstart = si + 1;
    
    7159 7180
             }
    
    7160
    -
    
    7161
    -        x += w;
    
    7162 7181
         }
    
    7163
    -
    
    7164
    -    return true;
    
    7182
    +    if (printstart < str.length())
    
    7183
    +    {
    
    7184
    +        dc.DrawText(str.Mid(printstart), startpos[printstart], y);
    
    7185
    +        if (strikethrough)
    
    7186
    +            dc.DrawLine(startpos[printstart], strikeheight, endpos[endpos.GetCount()-1], strikeheight);
    
    7187
    +    }
    
    7165 7188
     }
    
    7166 7189
     
    
    7167 7190
     /// Lay the item out
    

Reply all
Reply to author
Forward
0 new messages