tdf#38194 tdf#106556 Enhancement to highlight direct formatting,

paragraph style, and character style use in Writer documents

Initial commit to realize direct formatting, paragraph style, and
character style highlighting enhancement requests.

Highlighting of character direct formatting is turned on/off using
.uno:HighlightCharDF. Highlighting of paragraph styles and character
styles is turned on/off using a check box in the Sidebar Styles panel.
Closing the Sidebar also turns paragraph and character style
highlighting off. Paragraph direct formatting is indicated by a hatch
pattern over the paragraph style highlight bar and also by "+ Paragraph
Direct Formatting" appended to the tooltip that appears showing the
name of the paragraph style when the mouse pointer is over the style
highlight bar.

Colors used for styles highlighting are determined by a hash of the
style name. Lightgray is used for character direct formatting.

Known issue:

Tooltip doesn't show for paragraph style highlighting in tables and in
frames where the highlighting bar is drawn outside of the frame.

Change-Id: I6e00ee38c1c169bc7c6542a1782c03b2593e1891
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150451
Tested-by: Jenkins
Reviewed-by: Heiko Tietze <heiko.tietze@documentfoundation.org>
diff --git a/include/sfx2/viewsh.hxx b/include/sfx2/viewsh.hxx
index 8589b9b..a9713eb 100644
--- a/include/sfx2/viewsh.hxx
+++ b/include/sfx2/viewsh.hxx
@@ -35,6 +35,7 @@
#include <editeng/outliner.hxx>
#include <functional>
#include <unordered_set>
#include <unordered_map>

class SfxTabPage;
class SfxBaseController;
@@ -152,6 +153,8 @@ template<class T> bool checkSfxViewShell(const SfxViewShell* pShell)
    return dynamic_cast<const T*>(pShell) != nullptr;
}

typedef std::unordered_map<OUString, std::pair<Color, int>> StylesHighlighterColorMap;

/**
 * One SfxViewShell more or less represents one edit window for a document, there can be multiple
 * ones for a single opened document (SfxObjectShell).
@@ -180,6 +183,9 @@ friend class SfxPrinterController;
    /// Used for async export
    std::shared_ptr<SfxStoringHelper> m_xHelper;

    StylesHighlighterColorMap ParaStylesColorMap;
    StylesHighlighterColorMap CharStylesColorMap;

protected:
    virtual void                Activate(bool IsMDIActivate) override;
    virtual void                Deactivate(bool IsMDIActivate) override;
@@ -457,6 +463,9 @@ public:
    bool isBlockedCommand(OUString command);

    void SetStoringHelper(std::shared_ptr<SfxStoringHelper> xHelper) { m_xHelper = xHelper; }

    StylesHighlighterColorMap& GetStylesHighlighterParaColorMap() { return ParaStylesColorMap; }
    StylesHighlighterColorMap& GetStylesHighlighterCharColorMap() { return CharStylesColorMap; }
};

#endif // INCLUDED_SFX2_VIEWSH_HXX
diff --git a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
index b5db1d6..f3f9032 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
@@ -425,6 +425,14 @@
          <value>1</value>
        </prop>
      </node>
      <node oor:name=".uno:HighlightCharDF" oor:op="replace">
        <prop oor:name="Label" oor:type="xs:string">
          <value xml:lang="en-US">Spotlight Character Direct Formatting</value>
        </prop>
        <prop oor:name="Properties" oor:type="xs:int">
          <value>1</value>
        </prop>
      </node>
      <node oor:name=".uno:ShowChangesInMargin" oor:op="replace">
        <prop oor:name="Label" oor:type="xs:string">
          <value xml:lang="en-US">Show tracked deletions in margin</value>
diff --git a/sfx2/source/dialog/StyleList.cxx b/sfx2/source/dialog/StyleList.cxx
index dd84750..ce2d2f9 100644
--- a/sfx2/source/dialog/StyleList.cxx
+++ b/sfx2/source/dialog/StyleList.cxx
@@ -62,6 +62,8 @@

#include <StyleList.hxx>

#include <vcl/virdev.hxx>

using namespace css;
using namespace css::beans;
using namespace css::frame;
@@ -90,6 +92,50 @@ public:
    }
};

namespace
{
Color ColorHash(const OUString& rString)
{
    // method 1
    //Color aColor(rString.hashCode() & 0xFFFFFF);

    // method 2 borrowed from https://github.com/RolandR/ColorHash/blob/master/colorhash.js
    //sal_Int32 nSum = 0;

    //for (int i = 0; i < rString.getLength(); i++)
    //{
    //    nSum += rString[i];
    //}

    //sal_uInt8 nRed = OUString("0." + OUString(OUString::number(std::sin(nSum + 1))).copy(6)).toDouble() * 256;
    //sal_uInt8 nGreen = OUString("0." + OUString(OUString::number(std::sin(nSum + 2))).copy(6)).toDouble() * 256;
    //sal_uInt8 nBlue = OUString("0." + OUString(OUString::number(std::sin(nSum + 3))).copy(6)).toDouble() * 256;

    //Color aColor(nRed, nGreen, nBlue);

    // method 3 std::hash
    //const std::hash<OUString> hasher;
    //Color aColor(hasher(rString) & 0xFFFFFF);

    // method 4
    sal_uInt32 nLen = rString.getLength();
    sal_uInt32 nHashCode = nLen;
    while (nLen > 0)
    {
        nHashCode = (nHashCode * 107) + rString[nLen - 1];
        nLen--;
    }
    sal_uInt32 nColor = nHashCode & 0xFFFFFF;
    Color aColor(ColorTransparency, nColor);
    aColor.ApplyTintOrShade(5000);

    return aColor;
}

// used to disallow the default character style in the styles highlighter character styles color map
std::optional<OUString> sDefaultCharStyleUIName;
}

// Constructor

StyleList::StyleList(weld::Builder* pBuilder, SfxBindings* pBindings,
@@ -121,6 +167,11 @@ StyleList::StyleList(weld::Builder* pBuilder, SfxBindings* pBindings,
    , m_pContainer(pC)
{
    m_xFmtLb->set_help_id(HID_TEMPLATE_FMT);

    uno::Reference<frame::XFrame> xFrame
        = m_pBindings->GetDispatcher()->GetFrame()->GetFrame().GetFrameInterface();
    m_bModuleHasStylesHighlighterFeature
        = vcl::CommandInfoProvider::GetModuleIdentifier(xFrame) == "com.sun.star.text.TextDocument";
}

// Destructor
@@ -199,6 +250,8 @@ IMPL_LINK_NOARG(StyleList, ReadResource, void*, size_t)
        {
            m_nActFilter = m_pCurObjShell->GetAutoStyleFilterIndex();
        }
        if (m_bModuleHasStylesHighlighterFeature)
            sDefaultCharStyleUIName = getDefaultStyleName(SfxStyleFamily::Char);
    }
    size_t nCount = m_xStyleFamilies->size();
    m_pBindings->ENTERREGISTRATIONS();
@@ -357,8 +410,8 @@ void StyleList::Initialize()
    m_xTreeBox->connect_custom_get_size(LINK(this, StyleList, CustomGetSizeHdl));
    m_xTreeBox->connect_custom_render(LINK(this, StyleList, CustomRenderHdl));
    bool bCustomPreview = officecfg::Office::Common::StylesAndFormatting::Preview::get();
    m_xFmtLb->set_column_custom_renderer(0, bCustomPreview);
    m_xTreeBox->set_column_custom_renderer(0, bCustomPreview);
    m_xFmtLb->set_column_custom_renderer(1, bCustomPreview);
    m_xTreeBox->set_column_custom_renderer(1, bCustomPreview);

    m_xFmtLb->set_visible(!m_bHierarchical);
    m_xTreeBox->set_visible(m_bHierarchical);
@@ -659,16 +712,63 @@ static bool IsExpanded_Impl(const std::vector<OUString>& rEntries, std::u16strin
    return false;
}

static void lcl_Insert(weld::TreeView& rTreeView, const OUString& rName, SfxStyleFamily eFam,
                       const weld::TreeIter* pParent, weld::TreeIter* pRet, SfxViewShell* pViewSh)
{
    Color aColor(ColorHash(rName));

    int nColor;
    if (eFam == SfxStyleFamily::Para)
    {
        StylesHighlighterColorMap& rParaStylesColorMap
            = pViewSh->GetStylesHighlighterParaColorMap();
        nColor = rParaStylesColorMap.size();
        rParaStylesColorMap[rName] = std::pair(aColor, nColor);
    }
    else
    {
        StylesHighlighterColorMap& rCharStylesColorMap
            = pViewSh->GetStylesHighlighterCharColorMap();
        nColor = rCharStylesColorMap.size();
        rCharStylesColorMap[rName] = std::pair(aColor, nColor);
        // don't show a color or number for default character style 'No Character Style' entry
        if (rName == sDefaultCharStyleUIName.value() /*"No Character Style"*/)
        {
            rTreeView.insert(pParent, -1, &rName, &rName, nullptr, nullptr, false, pRet);
            return;
        }
    }

    // draw the color rectangle and number image
    const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
    Size aImageSize = rStyleSettings.GetListBoxPreviewDefaultPixelSize();
    ScopedVclPtrInstance<VirtualDevice> xDevice;
    xDevice->SetOutputSize(aImageSize);
    xDevice->SetFillColor(aColor);
    const tools::Rectangle aRect(Point(0, 0), aImageSize);
    xDevice->DrawRect(aRect);
    xDevice->SetTextColor(COL_BLACK);
    xDevice->DrawText(aRect, OUString::number(nColor),
                      DrawTextFlags::Center | DrawTextFlags::VCenter);

    rTreeView.insert(pParent, -1, &rName, &rName, nullptr, xDevice.get(), false, pRet);
}

static void FillBox_Impl(weld::TreeView& rBox, StyleTree_Impl* pEntry,
                         const std::vector<OUString>& rEntries, SfxStyleFamily eStyleFamily,
                         const weld::TreeIter* pParent)
                         const weld::TreeIter* pParent, bool blcl_insert, SfxViewShell* pViewShell)
{
    std::unique_ptr<weld::TreeIter> xResult = rBox.make_iterator();
    const OUString& rName = pEntry->getName();
    rBox.insert(pParent, -1, &rName, &rName, nullptr, nullptr, false, xResult.get());

    if (blcl_insert)
        lcl_Insert(rBox, rName, eStyleFamily, pParent, xResult.get(), pViewShell);
    else
        rBox.insert(pParent, -1, &rName, &rName, nullptr, nullptr, false, xResult.get());

    for (size_t i = 0; i < pEntry->getChildren().size(); ++i)
        FillBox_Impl(rBox, pEntry->getChildren()[i].get(), rEntries, eStyleFamily, xResult.get());
        FillBox_Impl(rBox, pEntry->getChildren()[i].get(), rEntries, eStyleFamily, xResult.get(),
                     blcl_insert, pViewShell);
}

namespace SfxTemplate
@@ -788,8 +888,16 @@ IMPL_LINK(StyleList, SetWaterCanState, const SfxBoolItem*, pItem, void)
    m_pBindings->LeaveRegistrations();
}

void StyleList::FamilySelect(sal_uInt16 nEntry)
void StyleList::FamilySelect(sal_uInt16 nEntry, bool bRefresh)
{
    if (bRefresh)
    {
        bool bCustomPreview = officecfg::Office::Common::StylesAndFormatting::Preview::get();
        m_xFmtLb->clear();
        m_xFmtLb->set_column_custom_renderer(1, bCustomPreview);
        m_xTreeBox->clear();
        m_xTreeBox->set_column_custom_renderer(1, bCustomPreview);
    }
    m_nActFamily = nEntry;
    SfxDispatcher* pDispat = m_pBindings->GetDispatcher_Impl();
    SfxUInt16Item const aItem(SID_STYLE_FAMILY,
@@ -944,18 +1052,40 @@ void StyleList::FillTreeBox(SfxStyleFamily eFam)
    m_xTreeBox->clear();
    const sal_uInt16 nCount = aArr.size();

    SfxViewShell* pViewShell = m_pCurObjShell->GetViewShell();
    if (pViewShell && m_bModuleHasStylesHighlighterFeature)
    {
        if (eFam == SfxStyleFamily::Para)
            pViewShell->GetStylesHighlighterParaColorMap().clear();
        else if (eFam == SfxStyleFamily::Char)
            pViewShell->GetStylesHighlighterCharColorMap().clear();
    }

    bool blcl_insert = pViewShell && m_bModuleHasStylesHighlighterFeature
                       && ((eFam == SfxStyleFamily::Para && m_bHighlightParaStyles)
                           || (eFam == SfxStyleFamily::Char && m_bHighlightCharStyles));

    for (sal_uInt16 i = 0; i < nCount; ++i)
    {
        FillBox_Impl(*m_xTreeBox, aArr[i].get(), aEntries, eFam, nullptr);
        FillBox_Impl(*m_xTreeBox, aArr[i].get(), aEntries, eFam, nullptr, blcl_insert, pViewShell);
        aArr[i].reset();
    }

    m_xTreeBox->columns_autosize();

    m_pParentDialog->EnableItem("watercan", false);

    SfxTemplateItem* pState = m_pFamilyState[m_nActFamily - 1].get();

    m_xTreeBox->thaw();

    // hack for x11 to make view update
    if (pViewShell && m_bModuleHasStylesHighlighterFeature)
    {
        SfxViewFrame* pViewFrame = m_pBindings->GetDispatcher_Impl()->GetFrame();
        pViewFrame->Resize(true);
    }

    std::unique_ptr<weld::TreeIter> xEntry = m_xTreeBox->make_iterator();
    bool bEntry = m_xTreeBox->get_iter_first(*xEntry);
    if (bEntry && nCount)
@@ -1084,7 +1214,6 @@ void StyleList::UpdateStyles(StyleFlags nFlags)
    SfxStyleSheetBase* pStyle = m_pStyleSheetPool->First(eFam, nFilter);

    std::unique_ptr<weld::TreeIter> xEntry = m_xFmtLb->make_iterator();
    bool bEntry = m_xFmtLb->get_iter_first(*xEntry);
    std::vector<OUString> aStrings;

    comphelper::string::NaturalStringSorter aSorter(
@@ -1112,25 +1241,46 @@ void StyleList::UpdateStyles(StyleFlags nFlags)
                  return aSorter.compare(rLHS, rRHS) < 0;
              });

    // Fill the display box
    m_xFmtLb->freeze();
    m_xFmtLb->clear();

    SfxViewShell* pViewShell = m_pCurObjShell->GetViewShell();
    if (pViewShell && m_bModuleHasStylesHighlighterFeature)
    {
        if (eFam == SfxStyleFamily::Para)
            pViewShell->GetStylesHighlighterParaColorMap().clear();
        else if (eFam == SfxStyleFamily::Char)
            pViewShell->GetStylesHighlighterCharColorMap().clear();
    }

    size_t nCount = aStrings.size();
    size_t nPos = 0;
    while (nPos < nCount && bEntry && aStrings[nPos] == m_xFmtLb->get_text(*xEntry))

    if (pViewShell && m_bModuleHasStylesHighlighterFeature
        && ((eFam == SfxStyleFamily::Para && m_bHighlightParaStyles)
            || (eFam == SfxStyleFamily::Char && m_bHighlightCharStyles)))
    {
        ++nPos;
        bEntry = m_xFmtLb->iter_next(*xEntry);
        for (nPos = 0; nPos < nCount; ++nPos)
            lcl_Insert(*m_xFmtLb, aStrings[nPos], eFam, nullptr, nullptr, pViewShell);
    }

    if (nPos < nCount || bEntry)
    else
    {
        // Fills the display box
        m_xFmtLb->freeze();
        m_xFmtLb->clear();

        for (nPos = 0; nPos < nCount; ++nPos)
            m_xFmtLb->append(aStrings[nPos], aStrings[nPos]);

        m_xFmtLb->thaw();
    }

    m_xFmtLb->columns_autosize();

    m_xFmtLb->thaw();

    // hack for x11 to make view update
    if (pViewShell && m_bModuleHasStylesHighlighterFeature)
    {
        SfxViewFrame* pViewFrame = m_pBindings->GetDispatcher_Impl()->GetFrame();
        pViewFrame->Resize(true);
    }

    // Selects the current style if any
    SfxTemplateItem* pState = m_pFamilyState[m_nActFamily - 1].get();
    OUString aStyle;
@@ -1327,6 +1477,15 @@ IMPL_LINK_NOARG(StyleList, EnableDelete, void*, void)

IMPL_LINK_NOARG(StyleList, Clear, void*, void)
{
    if (m_pCurObjShell && m_bModuleHasStylesHighlighterFeature)
    {
        SfxViewShell* pViewShell = m_pCurObjShell->GetViewShell();
        if (pViewShell)
        {
            pViewShell->GetStylesHighlighterParaColorMap().clear();
            pViewShell->GetStylesHighlighterCharColorMap().clear();
        }
    }
    m_xStyleFamilies.reset();
    for (auto& i : m_pFamilyState)
        i.reset();
@@ -1508,7 +1667,6 @@ IMPL_LINK(StyleList, QueryTooltipHdl, const weld::TreeIter&, rEntry, OUString)
    if (!pItem)
        return sQuickHelpText;
    SfxStyleSheetBase* pStyle = m_pStyleSheetPool->Find(aTemplName, pItem->GetFamily());

    if (pStyle && pStyle->IsUsed()) // pStyle is in use in the document?
    {
        OUString sUsedBy;
@@ -1730,14 +1888,6 @@ void StyleList::Update()
    m_pParentDialog->EnableNew(m_bCanNew, this);
}

void StyleList::EnablePreview(bool bCustomPreview)
{
    m_xFmtLb->clear();
    m_xFmtLb->set_column_custom_renderer(0, bCustomPreview);
    m_xTreeBox->clear();
    m_xTreeBox->set_column_custom_renderer(0, bCustomPreview);
}

const SfxStyleFamilyItem& StyleList::GetFamilyItemByIndex(size_t i) const
{
    return m_xStyleFamilies->at(i);
diff --git a/sfx2/source/dialog/templdlg.cxx b/sfx2/source/dialog/templdlg.cxx
index 9001ee0..6b2c258 100644
--- a/sfx2/source/dialog/templdlg.cxx
+++ b/sfx2/source/dialog/templdlg.cxx
@@ -134,6 +134,27 @@ namespace SfxTemplate
            default:                     return 0xffff;
        }
    }
    // converts from 1-6 to SFX_STYLE_FAMILY Ids
    static SfxStyleFamily NIdToSfxFamilyId(sal_uInt16 nId)
    {
        switch (nId)
        {
            case 1:
                return SfxStyleFamily::Char;
            case 2:
                return SfxStyleFamily::Para;
            case 3:
                return SfxStyleFamily::Frame;
            case 4:
                return SfxStyleFamily::Page;
            case 5:
                return SfxStyleFamily::Pseudo;
            case 6:
                return SfxStyleFamily::Table;
            default:
                return SfxStyleFamily::All;
        }
    }
}

void SfxCommonTemplateDialog_Impl::connect_stylelist_execute_drop(
@@ -176,6 +197,7 @@ SfxCommonTemplateDialog_Impl::SfxCommonTemplateDialog_Impl(SfxBindings* pB, weld
    , m_pDeletionWatcher(nullptr)
    , m_aStyleList(pBuilder, pB, this, pC, "treeview", "flatview")
    , mxPreviewCheckbox(pBuilder->weld_check_button("showpreview"))
    , mxHighlightCheckbox(pBuilder->weld_check_button("highlightstyles"))
    , mxFilterLb(pBuilder->weld_combo_box("filter"))
    , nActFamily(0xffff)
    , nActFilter(0)
@@ -262,7 +284,13 @@ void SfxCommonTemplateDialog_Impl::Initialize()

    mxFilterLb->connect_changed(LINK(this, SfxCommonTemplateDialog_Impl, FilterSelectHdl));
    mxPreviewCheckbox->connect_toggled(LINK(this, SfxCommonTemplateDialog_Impl, PreviewHdl));
    mxHighlightCheckbox->connect_toggled(LINK(this, SfxCommonTemplateDialog_Impl, HighlightHdl));

    m_aStyleList.Initialize();

    SfxStyleFamily eFam = SfxTemplate::NIdToSfxFamilyId(nActFamily);
    mxHighlightCheckbox->set_visible(m_aStyleList.HasStylesHighlighterFeature()
                                && (eFam == SfxStyleFamily::Para || eFam == SfxStyleFamily::Char));
}

IMPL_LINK(SfxCommonTemplateDialog_Impl, UpdateStyles_Hdl, StyleFlags, nFlags, void)
@@ -460,6 +488,7 @@ bool SfxCommonTemplateDialog_Impl::Execute_Impl(
// Handler Listbox of Filter
void SfxCommonTemplateDialog_Impl::EnableHierarchical(bool const bEnable, StyleList& rStyleList)
{
    OUString aSelectedEntry = rStyleList.GetSelectedEntry();
    if (bEnable)
    {
        if (!rStyleList.IsHierarchical())
@@ -476,8 +505,9 @@ void SfxCommonTemplateDialog_Impl::EnableHierarchical(bool const bEnable, StyleL
        // If bHierarchical, then the family can have changed
        // minus one since hierarchical is inserted at the start
        m_bWantHierarchical = false; // before FilterSelect
        FilterSelect(mxFilterLb->get_active() - 1, rStyleList.IsHierarchical() );
        FilterSelect(mxFilterLb->get_active() - 1, true);
    }
    SelectStyle(aSelectedEntry, false, rStyleList);
}

// Other filters; can be switched by the users or as a result of new or
@@ -517,14 +547,27 @@ IMPL_LINK(SfxCommonTemplateDialog_Impl, FilterSelectHdl, weld::ComboBox&, rBox, 
}

// Select-Handler for the Toolbox
void SfxCommonTemplateDialog_Impl::FamilySelect(sal_uInt16 nEntry, StyleList&, bool bPreviewRefresh)
void SfxCommonTemplateDialog_Impl::FamilySelect(sal_uInt16 nEntry, StyleList&, bool bRefresh)
{
    assert((0 < nEntry && nEntry <= MAX_FAMILIES) || 0xffff == nEntry);
    if( nEntry != nActFamily || bPreviewRefresh )
    if( nEntry != nActFamily || bRefresh )
    {
        CheckItem(OUString::number(nActFamily), false);
        nActFamily = nEntry;
        m_aStyleList.FamilySelect(nEntry);
        m_aStyleList.FamilySelect(nEntry, bRefresh);

        SfxStyleFamily eFam = SfxTemplate::NIdToSfxFamilyId(nActFamily);
        mxHighlightCheckbox->set_visible(m_aStyleList.HasStylesHighlighterFeature()
                                && (eFam == SfxStyleFamily::Para || eFam == SfxStyleFamily::Char));
        if (mxHighlightCheckbox->is_visible())
        {
            bool bActive = false;
            if (eFam == SfxStyleFamily::Para)
                bActive = m_aStyleList.IsHighlightParaStyles();
            else if (eFam == SfxStyleFamily::Char)
                bActive = m_aStyleList.IsHighlightCharStyles();
            mxHighlightCheckbox->set_active(bActive);
        }
    }
}

@@ -632,8 +675,17 @@ IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl, PreviewHdl, weld::Toggleable&, voi
    officecfg::Office::Common::StylesAndFormatting::Preview::set(bCustomPreview, batch );
    batch->commit();

    m_aStyleList.EnablePreview(bCustomPreview);
    FamilySelect(nActFamily, m_aStyleList, true);
}

IMPL_LINK_NOARG(SfxCommonTemplateDialog_Impl, HighlightHdl, weld::Toggleable&, void)
{
    bool bActive = mxHighlightCheckbox->get_active();
    SfxStyleFamily eFam = SfxTemplate::NIdToSfxFamilyId(nActFamily);
    if (eFam == SfxStyleFamily::Para)
        m_aStyleList.SetHighlightParaStyles(bActive);
    else if (eFam == SfxStyleFamily::Char)
        m_aStyleList.SetHighlightCharStyles(bActive);
    FamilySelect(nActFamily, m_aStyleList, true);
}

diff --git a/sfx2/source/inc/StyleList.hxx b/sfx2/source/inc/StyleList.hxx
index 5eba936..fe4ff62 100644
--- a/sfx2/source/inc/StyleList.hxx
+++ b/sfx2/source/inc/StyleList.hxx
@@ -113,8 +113,7 @@ public:
    void Enableshow(bool canshow) { m_bCanShow = canshow; }
    void Enablenew(bool cannew) { m_bCanNew = cannew; }
    void Enableedit(bool canedit) { m_bCanEdit = canedit; }
    // Handles the enabling/Disabling of Preview
    void EnablePreview(bool bCustomPreview);

    // Used in Dialog's Execute_Impl
    // It is a necessary condition to execute a style
    bool EnableExecute();
@@ -126,11 +125,17 @@ public:
    void connect_SaveSelection(const Link<StyleList&, SfxObjectShell*> rLink);
    void connect_UpdateFamily(const Link<StyleList&, void> rLink) { m_aUpdateFamily = rLink; }

    void FamilySelect(sal_uInt16 nEntry);
    void FamilySelect(sal_uInt16 nEntry, bool bRefresh = false);
    void FilterSelect(sal_uInt16 nActFilter, bool bsetFilter);

    DECL_LINK(NewMenuExecuteAction, void*, void);

    bool HasStylesHighlighterFeature() { return m_bModuleHasStylesHighlighterFeature; }
    void SetHighlightParaStyles(bool bSet) { m_bHighlightParaStyles = bSet; }
    bool IsHighlightParaStyles() { return m_bHighlightParaStyles; }
    void SetHighlightCharStyles(bool bSet) { m_bHighlightCharStyles = bSet; }
    bool IsHighlightCharStyles() { return m_bHighlightCharStyles; }

private:
    void FillTreeBox(SfxStyleFamily eFam);

@@ -236,4 +241,8 @@ private:
    SfxModule* m_Module;
    sal_uInt16 m_nModifier;
    weld::Container* m_pContainer;

    bool m_bModuleHasStylesHighlighterFeature = false;
    bool m_bHighlightParaStyles = false;
    bool m_bHighlightCharStyles = false;
};
diff --git a/sfx2/source/inc/templdgi.hxx b/sfx2/source/inc/templdgi.hxx
index 322747b..a352b1e 100644
--- a/sfx2/source/inc/templdgi.hxx
+++ b/sfx2/source/inc/templdgi.hxx
@@ -69,6 +69,7 @@ protected:

    StyleList m_aStyleList;
    std::unique_ptr<weld::CheckButton> mxPreviewCheckbox;
    std::unique_ptr<weld::CheckButton> mxHighlightCheckbox;
    std::unique_ptr<weld::ComboBox> mxFilterLb;

    sal_uInt16 nActFamily; // Id in the ToolBox = Position - 1
@@ -97,6 +98,7 @@ protected:

    DECL_LINK(FilterSelectHdl, weld::ComboBox&, void );
    DECL_LINK(PreviewHdl, weld::Toggleable&, void);
    DECL_LINK(HighlightHdl, weld::Toggleable&, void);

    virtual void InsertFamilyItem(sal_uInt16 nId, const SfxStyleFamilyItem& rItem) = 0;
    virtual void EnableFamilyItem(sal_uInt16 nId, bool bEnabled) = 0;
@@ -138,7 +140,7 @@ public:

    // Used in StyleList::UpdateStyles, StyleList::Update
    // Whenever a new family(Eg. Character, List etc.) is selected it comes into action
    void FamilySelect(sal_uInt16 nId, StyleList& rStyleList, bool bPreviewRefresh = false);
    void FamilySelect(sal_uInt16 nId, StyleList& rStyleList, bool bRefresh = false);

    // Constructor
    SfxCommonTemplateDialog_Impl(SfxBindings* pB, weld::Container*, weld::Builder* pBuilder);
diff --git a/sfx2/uiconfig/ui/templatepanel.ui b/sfx2/uiconfig/ui/templatepanel.ui
index f4e8d98..633e9d0 100644
--- a/sfx2/uiconfig/ui/templatepanel.ui
+++ b/sfx2/uiconfig/ui/templatepanel.ui
@@ -1,9 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.36.0 -->
<!-- Generated with glade 3.40.0 -->
<interface domain="sfx">
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkTreeStore" id="liststore1">
    <columns>
      <!-- column-name image -->
      <column type="CairoSurface"/>
      <!-- column-name text -->
      <column type="gchararray"/>
      <!-- column-name id -->
@@ -12,6 +14,8 @@
  </object>
  <object class="GtkTreeStore" id="liststore2">
    <columns>
      <!-- column-name image -->
      <column type="CairoSurface"/>
      <!-- column-name text -->
      <column type="gchararray"/>
      <!-- column-name id -->
@@ -21,32 +25,33 @@
  <!-- n-columns=1 n-rows=1 -->
  <object class="GtkGrid" id="TemplatePanel">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="can-focus">False</property>
    <property name="hexpand">True</property>
    <property name="vexpand">True</property>
    <child>
      <object class="GtkBox" id="box1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="can-focus">False</property>
        <property name="hexpand">True</property>
        <property name="vexpand">True</property>
        <property name="border_width">6</property>
        <property name="border-width">6</property>
        <property name="orientation">vertical</property>
        <property name="spacing">3</property>
        <child>
          <object class="GtkBox">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="can-focus">False</property>
            <child>
              <object class="GtkToolbar" id="left">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="toolbar_style">text</property>
                <property name="show_arrow">False</property>
                <property name="can-focus">True</property>
                <property name="toolbar-style">text</property>
                <property name="show-arrow">False</property>
                <property name="icon_size">2</property>
                <child>
                  <object class="GtkToggleToolButton" id="2">
                    <property name="use_underline">True</property>
                    <property name="can-focus">False</property>
                    <property name="use-underline">True</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
@@ -55,7 +60,8 @@
                </child>
                <child>
                  <object class="GtkToggleToolButton" id="1">
                    <property name="use_underline">True</property>
                    <property name="can-focus">False</property>
                    <property name="use-underline">True</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
@@ -64,7 +70,8 @@
                </child>
                <child>
                  <object class="GtkToggleToolButton" id="3">
                    <property name="use_underline">True</property>
                    <property name="can-focus">False</property>
                    <property name="use-underline">True</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
@@ -73,7 +80,8 @@
                </child>
                <child>
                  <object class="GtkToggleToolButton" id="4">
                    <property name="use_underline">True</property>
                    <property name="can-focus">False</property>
                    <property name="use-underline">True</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
@@ -82,7 +90,8 @@
                </child>
                <child>
                  <object class="GtkToggleToolButton" id="5">
                    <property name="use_underline">True</property>
                    <property name="can-focus">False</property>
                    <property name="use-underline">True</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
@@ -91,7 +100,8 @@
                </child>
                <child>
                  <object class="GtkToggleToolButton" id="6">
                    <property name="use_underline">True</property>
                    <property name="can-focus">False</property>
                    <property name="use-underline">True</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
@@ -100,7 +110,8 @@
                </child>
                <child>
                  <object class="GtkToggleToolButton" id="65535">
                    <property name="use_underline">True</property>
                    <property name="can-focus">False</property>
                    <property name="use-underline">True</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
@@ -110,23 +121,24 @@
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">0</property>
                <property name="fill">False</property>
                <property name="position">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkToolbar" id="right">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="toolbar_style">icons</property>
                <property name="show_arrow">False</property>
                <property name="can-focus">True</property>
                <property name="toolbar-style">icons</property>
                <property name="show-arrow">False</property>
                <property name="icon_size">2</property>
                <child>
                  <object class="GtkToggleToolButton" id="watercan">
                    <property name="visible">True</property>
                    <property name="tooltip_text" translatable="yes" context="templatepanel|STR_STYLE_FILL_FORMAT_MODE">Fill Format Mode</property>
                    <property name="use_underline">True</property>
                    <property name="icon_name">res/sc05554.png</property>
                    <property name="can-focus">False</property>
                    <property name="tooltip-text" translatable="yes" context="templatepanel|STR_STYLE_FILL_FORMAT_MODE">Fill Format Mode</property>
                    <property name="use-underline">True</property>
                    <property name="icon-name">res/sc05554.png</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
@@ -136,9 +148,10 @@
                <child>
                  <object class="GtkToolButton" id="new">
                    <property name="visible">True</property>
                    <property name="tooltip_text" translatable="yes" context="templatepanel|STR_STYLE_NEW_STYLE_FROM_SELECTION">New Style from Selection</property>
                    <property name="use_underline">True</property>
                    <property name="icon_name">res/sc05555.png</property>
                    <property name="can-focus">False</property>
                    <property name="tooltip-text" translatable="yes" context="templatepanel|STR_STYLE_NEW_STYLE_FROM_SELECTION">New Style from Selection</property>
                    <property name="use-underline">True</property>
                    <property name="icon-name">res/sc05555.png</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
@@ -147,10 +160,11 @@
                </child>
                <child>
                  <object class="GtkMenuToolButton" id="newmenu">
                    <property name="no_show_all">True</property>
                    <property name="tooltip_text" translatable="yes" context="templatepanel|STR_STYLE_NEW_STYLE_ACTION">Styles actions</property>
                    <property name="use_underline">True</property>
                    <property name="icon_name">res/sc05555.png</property>
                    <property name="can-focus">False</property>
                    <property name="no-show-all">True</property>
                    <property name="tooltip-text" translatable="yes" context="templatepanel|STR_STYLE_NEW_STYLE_ACTION">Styles actions</property>
                    <property name="use-underline">True</property>
                    <property name="icon-name">res/sc05555.png</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
@@ -160,9 +174,10 @@
                <child>
                  <object class="GtkToolButton" id="update">
                    <property name="visible">True</property>
                    <property name="tooltip_text" translatable="yes" context="templatepanel|STR_STYLE_UPDATE_STYLE">Update Style</property>
                    <property name="use_underline">True</property>
                    <property name="icon_name">res/sc05556.png</property>
                    <property name="can-focus">False</property>
                    <property name="tooltip-text" translatable="yes" context="templatepanel|STR_STYLE_UPDATE_STYLE">Update Style</property>
                    <property name="use-underline">True</property>
                    <property name="icon-name">res/sc05556.png</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
@@ -173,8 +188,8 @@
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="pack_type">end</property>
                <property name="position">1</property>
                <property name="pack-type">end</property>
                <property name="position">2</property>
              </packing>
            </child>
          </object>
@@ -186,31 +201,42 @@
        </child>
        <child>
          <object class="GtkScrolledWindow">
            <property name="can_focus">True</property>
            <property name="can-focus">True</property>
            <property name="hexpand">True</property>
            <property name="vexpand">True</property>
            <property name="shadow_type">in</property>
            <property name="shadow-type">in</property>
            <child>
              <object class="GtkTreeView" id="flatview">
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <property name="no_show_all">True</property>
                <property name="has_tooltip">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
                <property name="no-show-all">True</property>
                <property name="has-tooltip">True</property>
                <property name="hexpand">True</property>
                <property name="vexpand">True</property>
                <property name="model">liststore1</property>
                <property name="headers_visible">False</property>
                <property name="search_column">0</property>
                <property name="show_expanders">False</property>
                <property name="headers-visible">False</property>
                <property name="search-column">0</property>
                <property name="show-expanders">False</property>
                <child internal-child="selection">
                  <object class="GtkTreeSelection" id="Macro Library List-selection2"/>
                </child>
                <child>
                  <object class="GtkTreeViewColumn" id="treeviewcolumn0">
                    <child>
                      <object class="GtkCellRendererPixbuf" id="cellrendererpixbuf1"/>
                      <attributes>
                        <attribute name="surface">0</attribute>
                      </attributes>
                    </child>
                  </object>
                </child>
                <child>
                  <object class="GtkTreeViewColumn" id="treeviewcolumn1">
                    <property name="resizable">True</property>
                    <child>
                      <object class="GtkCellRendererText" id="cellrenderertext1"/>
                      <attributes>
                        <attribute name="text">0</attribute>
                        <attribute name="text">1</attribute>
                      </attributes>
                    </child>
                  </object>
@@ -231,32 +257,43 @@
        </child>
        <child>
          <object class="GtkScrolledWindow">
            <property name="can_focus">True</property>
            <property name="can-focus">True</property>
            <property name="hexpand">True</property>
            <property name="vexpand">True</property>
            <property name="shadow_type">in</property>
            <property name="shadow-type">in</property>
            <child>
              <object class="GtkTreeView" id="treeview">
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <property name="no_show_all">True</property>
                <property name="has_tooltip">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
                <property name="no-show-all">True</property>
                <property name="has-tooltip">True</property>
                <property name="hexpand">True</property>
                <property name="vexpand">True</property>
                <property name="model">liststore2</property>
                <property name="headers_visible">False</property>
                <property name="headers-visible">False</property>
                <property name="reorderable">True</property>
                <property name="search_column">0</property>
                <property name="enable_tree_lines">True</property>
                <property name="search-column">1</property>
                <property name="enable-tree-lines">True</property>
                <child internal-child="selection">
                  <object class="GtkTreeSelection" id="Macro Library List-selection1"/>
                </child>
                <child>
                  <object class="GtkTreeViewColumn" id="treeviewcolumn3">
                    <child>
                      <object class="GtkCellRendererPixbuf" id="cellrendererpixbuf2"/>
                      <attributes>
                        <attribute name="surface">0</attribute>
                      </attributes>
                    </child>
                  </object>
                </child>
                <child>
                  <object class="GtkTreeViewColumn" id="treeviewcolumn2">
                    <property name="resizable">True</property>
                    <child>
                      <object class="GtkCellRendererText" id="cellrenderertext2"/>
                      <attributes>
                        <attribute name="text">0</attribute>
                        <attribute name="text">1</attribute>
                      </attributes>
                    </child>
                  </object>
@@ -276,24 +313,38 @@
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="showpreview">
            <property name="label" translatable="yes" context="commontemplate|STR_PREVIEW_CHECKBOX">Show previews</property>
          <object class="GtkBox">
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="use_underline">True</property>
            <property name="draw_indicator">True</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">3</property>
          </packing>
        </child>
        <child>
          <object class="GtkComboBoxText" id="filter">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="can-focus">False</property>
            <child>
              <object class="GtkCheckButton" id="showpreview">
                <property name="label" translatable="yes" context="commontemplate|STR_PREVIEW_CHECKBOX">Show previews</property>
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">False</property>
                <property name="use-underline">True</property>
                <property name="draw-indicator">True</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkCheckButton" id="highlightstyles">
                <property name="label" translatable="yes" context="commontemplate|STR_HIGHLIGHT_CHECKBOX">Spotlight</property>
                <property name="can-focus">True</property>
                <property name="receives-default">False</property>
                <property name="use-underline">True</property>
                <property name="draw-indicator">True</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
@@ -301,15 +352,26 @@
            <property name="position">4</property>
          </packing>
        </child>
        <child>
          <object class="GtkComboBoxText" id="filter">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">5</property>
          </packing>
        </child>
      </object>
      <packing>
        <property name="left_attach">0</property>
        <property name="top_attach">0</property>
        <property name="left-attach">0</property>
        <property name="top-attach">0</property>
      </packing>
    </child>
  </object>
  <object class="GtkMenu" id="toolmenu">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="can-focus">False</property>
  </object>
</interface>
diff --git a/sw/inc/cmdid.h b/sw/inc/cmdid.h
index 82616e3..5459c63 100644
--- a/sw/inc/cmdid.h
+++ b/sw/inc/cmdid.h
@@ -170,6 +170,8 @@ class SwUINumRuleItem;
#define FN_VIEW_FIELDNAME       (FN_VIEW + 26)  /* View field names */
#define FN_VIEW_TABLEGRID       (FN_VIEW + 27)  /* View tablegrid */

#define FN_HIGHLIGHT_CHAR_DF    (FN_VIEW + 28)

#define FN_SET_PAGE             (FN_VIEW + 29)  /* Set page template to paragraph */

#define FN_PRINT_LAYOUT         (FN_VIEW + 37)  /* print layout */
diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index 1b008bf..7a1b2e0 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -1690,6 +1690,8 @@ public:

    void SetLanguage(const LanguageType eLang, const sal_uInt16 nId);

    static bool HasParagraphDirectFormatting(const SwPosition& rPos);

private:
    // Copies master header to left / first one, if necessary - used by ChgPageDesc().
    void CopyMasterHeader(const SwPageDesc &rChged, const SwFormatHeader &rHead, SwPageDesc &pDesc, bool bLeft, bool bFirst);
diff --git a/sw/inc/strings.hrc b/sw/inc/strings.hrc
index a9e5a78..a29a9c9 100644
--- a/sw/inc/strings.hrc
+++ b/sw/inc/strings.hrc
@@ -1468,6 +1468,10 @@
#define STR_INFORODLG_FOLDED_PRIMARY            NC_("STR_INFORODLG_FOLDED_PRIMARY", "You are trying to delete folded (hidden) content.")
#define STR_INFORODLG_FOLDED_SECONDARY          NC_("STR_INFORODLG_FOLDED_SECONDARY", "To delete this content, first unfold it so you can see what you intend to delete.")

#define STR_PARAGRAPH_DIRECT_FORMATTING         NC_("STR_PARAGRAPH_DIRECT_FORMATTING", "Paragraph Direct Formatting")
#define STR_CHARACTER_DIRECT_FORMATTING         NC_("STR_CHARACTER_DIRECT_FORMATTING", "Character Direct Formatting")
#define STR_CHARACTER_DIRECT_FORMATTING_TAG     NC_("STR_CHARACTER_DIRECT_FORMATTING_TAG", "df")

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/inc/view.hxx b/sw/inc/view.hxx
index ff0099a..60fe6fd 100644
--- a/sw/inc/view.hxx
+++ b/sw/inc/view.hxx
@@ -270,6 +270,8 @@ class SW_DLLPUBLIC SwView: public SfxViewShell

    int m_nMaxOutlineLevelShown = 10;

    bool m_bIsHighlightCharDF = false;

    static constexpr sal_uInt16 MAX_ZOOM_PERCENT = 600;
    static constexpr sal_uInt16 MIN_ZOOM_PERCENT = 20;

@@ -706,6 +708,8 @@ public:
    virtual tools::Rectangle getLOKVisibleArea() const override;
    virtual void flushPendingLOKInvalidateTiles() override;
    virtual std::optional<OString> getLOKPayload(int nType, int nViewId) const override;

    bool IsHighlightCharDF() { return m_bIsHighlightCharDF; }
};

inline tools::Long SwView::GetXScroll() const
diff --git a/sw/sdi/_viewsh.sdi b/sw/sdi/_viewsh.sdi
index 020383d..a3b2e5e 100644
--- a/sw/sdi/_viewsh.sdi
+++ b/sw/sdi/_viewsh.sdi
@@ -912,6 +912,12 @@ interface BaseTextEditView
        StateMethod = StateViewOptions ;
    ]

    FN_HIGHLIGHT_CHAR_DF
    [
        ExecMethod = ExecViewOptions ;
        StateMethod = StateViewOptions ;
    ]

    FN_VIEW_META_CHARS // status()
    [
        ExecMethod = ExecViewOptions ;
diff --git a/sw/sdi/swriter.sdi b/sw/sdi/swriter.sdi
index 69e41da..15d098c 100644
--- a/sw/sdi/swriter.sdi
+++ b/sw/sdi/swriter.sdi
@@ -4070,6 +4070,23 @@ SfxBoolItem Marks FN_VIEW_MARKS
    GroupId = SfxGroupId::View;
]

SfxBoolItem HighlightCharDF FN_HIGHLIGHT_CHAR_DF

[
    AutoUpdate = TRUE,
    FastCall = FALSE,
    ReadOnlyDoc = TRUE,
    Toggle = TRUE,
    Container = FALSE,
    RecordAbsolute = FALSE,
    RecordPerSet;

    AccelConfig = TRUE,
    MenuConfig = TRUE,
    ToolBoxConfig = TRUE,
    GroupId = SfxGroupId::View;
]

SfxVoidItem MergeCells FN_TABLE_MERGE_CELLS
()
[
diff --git a/sw/source/core/doc/doc.cxx b/sw/source/core/doc/doc.cxx
index 07f5488..5c686f1 100644
--- a/sw/source/core/doc/doc.cxx
+++ b/sw/source/core/doc/doc.cxx
@@ -105,6 +105,12 @@
*/
#include <docsh.hxx>

#include <com/sun/star/text/XTextRange.hpp>
#include <editeng/unoprnms.hxx>
#include <unotextrange.hxx>
#include <unoprnms.hxx>
#include <unomap.hxx>

using namespace ::com::sun::star;

sal_Int32 SwDoc::acquire()
@@ -1859,4 +1865,53 @@ void SwDoc::SetLanguage(const LanguageType eLang, const sal_uInt16 nId)
    mpAttrPool->SetPoolDefaultItem(SvxLanguageItem(eLang, nId));
}

bool SwDoc::HasParagraphDirectFormatting(const SwPosition& rPos)
{
    uno::Reference<text::XTextRange> xRange(SwXTextRange::CreateXTextRange(rPos.GetDoc(), rPos,
                                                                           &rPos));
    uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xRange, uno::UNO_QUERY_THROW);
    uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
    uno::Reference<text::XTextRange> xThisParagraphRange(xParaEnum->nextElement(), uno::UNO_QUERY);
    if (xThisParagraphRange.is())
    {
        const std::vector<OUString> aHiddenProperties{ UNO_NAME_RSID,
                    UNO_NAME_PARA_IS_NUMBERING_RESTART,
                    UNO_NAME_PARA_STYLE_NAME,
                    UNO_NAME_PARA_CONDITIONAL_STYLE_NAME,
                    UNO_NAME_PAGE_STYLE_NAME,
                    UNO_NAME_NUMBERING_START_VALUE,
                    UNO_NAME_NUMBERING_IS_NUMBER,
                    UNO_NAME_PARA_CONTINUEING_PREVIOUS_SUB_TREE,
                    UNO_NAME_CHAR_STYLE_NAME,
                    UNO_NAME_NUMBERING_LEVEL,
                    UNO_NAME_SORTED_TEXT_ID,
                    UNO_NAME_PARRSID,
                    UNO_NAME_CHAR_COLOR_THEME,
                    UNO_NAME_CHAR_COLOR_TINT_OR_SHADE };

        SfxItemPropertySet const& rPropSet(*aSwMapProvider.GetPropertySet(
                                               PROPERTY_MAP_PARA_AUTO_STYLE));
        SfxItemPropertyMap const& rMap(rPropSet.getPropertyMap());

        uno::Reference<beans::XPropertySet> xPropertySet(xThisParagraphRange,
                                                         uno::UNO_QUERY_THROW);
        uno::Reference<beans::XPropertyState> xPropertyState(xThisParagraphRange,
                                                             uno::UNO_QUERY_THROW);
        const uno::Sequence<beans::Property> aProperties
                = xPropertySet->getPropertySetInfo()->getProperties();
        for (const beans::Property& rProperty : aProperties)
        {
            const OUString& rPropName = rProperty.Name;
            if (!rMap.hasPropertyByName(rPropName))
                continue;
            if (std::find(aHiddenProperties.begin(), aHiddenProperties.end(), rPropName)
                    != aHiddenProperties.end())
                continue;
            if (xPropertyState->getPropertyState(rPropName) == beans::PropertyState_DIRECT_VALUE)
                return true;
        }
    }
    return false;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index 9428678..2376153 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -27,6 +27,8 @@
#include <set>
#include <utility>

#include <view.hxx>

namespace com::sun::star::linguistic2 { class XHyphenatedWord; }

namespace sw::mark { class IMark; }
@@ -330,6 +332,8 @@ class SW_DLLPUBLIC SwTextFrame final : public SwContentFrame
    void UpdateOutlineContentVisibilityButton(SwWrtShell* pWrtSh) const;
    void PaintOutlineContentVisibilityButton() const;

    void PaintParagraphStylesHighlighting() const;

    virtual void SwClientNotify(SwModify const& rModify, SfxHint const& rHint) override;

    /// Like GetDrawObjs(), but limit to fly frames which are allowed to split.
@@ -791,6 +795,8 @@ public:
    /// a follow, i.e. not the last in a master -> follow 1 -> ... -> last follow chain?
    bool HasNonLastSplitFlyDrawObj() const;

    static SwView* GetView();

    virtual void dumpAsXmlAttributes(xmlTextWriterPtr writer) const override;
};

diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index 66612ba..a68f58e 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -120,6 +120,10 @@
#include <vcl/GraphicLoader.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>

#include <svl/style.hxx>
#include <ndtxt.hxx>
#include <vcl/hatch.hxx>

using namespace ::editeng;
using namespace ::com::sun::star;

@@ -4332,6 +4336,90 @@ void SwFlyFrame::PaintDecorators() const
    }
}

SwView* SwTextFrame::GetView()
{
    SwWrtShell* pWrtSh = dynamic_cast<SwWrtShell*>(gProp.pSGlobalShell);

    if (!pWrtSh)
        return nullptr;

    return &pWrtSh->GetView();
}

void SwTextFrame::PaintParagraphStylesHighlighting() const
{
    // Maybe avoid the dynamic_cast and just use GetActiveWrtShell()
    // NO! Multiple windows will not dispay the highlighting correctly if GetActiveWrtShell is used.
    SwWrtShell* pWrtSh = dynamic_cast<SwWrtShell*>(gProp.pSGlobalShell);

    if (!pWrtSh)
        return;

    vcl::RenderContext* pRenderContext = pWrtSh->GetOut();
    if (!pRenderContext)
        return;

    StylesHighlighterColorMap& rParaStylesColorMap
            = pWrtSh->GetView().GetStylesHighlighterParaColorMap();

    if (rParaStylesColorMap.empty())
        return;

    //  draw styles highlighter
    OUString sStyleName = GetTextNodeFirst()->GetTextColl()->GetName();
    if (rParaStylesColorMap.find(sStyleName) != rParaStylesColorMap.end())
    {
        SwRect aFrameAreaRect(getFrameArea());

        if (IsRightToLeft())
        {
            aFrameAreaRect.AddRight(75);
            aFrameAreaRect.Left(aFrameAreaRect.Right() + 300);
        }
        else
        {
            aFrameAreaRect.AddLeft(-375);
            aFrameAreaRect.Right(aFrameAreaRect.Left() + 300);
        }

        const tools::Rectangle& rRect = aFrameAreaRect.SVRect();

        vcl::Font aFont(OutputDevice::GetDefaultFont(DefaultFontType::UI_SANS, GetAppLanguage(),
                                                     GetDefaultFontFlags::OnlyOne, pRenderContext));
        aFont.SetFontSize(Size(0, 140 * pRenderContext->GetDPIScaleFactor()));
        aFont.SetUnderline(FontLineStyle::LINESTYLE_NONE);
        aFont.SetTransparent(false);
        aFont.SetWeight(WEIGHT_NORMAL);
        aFont.SetFamily(FontFamily::FAMILY_MODERN);
        aFont.SetColor(COL_BLACK);

        pRenderContext->Push(vcl::PushFlags::ALL);

        pRenderContext->SetFillColor(rParaStylesColorMap[sStyleName].first);
        pRenderContext->SetLineColor(rParaStylesColorMap[sStyleName].first);

        pRenderContext->DrawRect(rRect);

        // draw hatch pattern if paragraph has direct formatting
        if (SwDoc::HasParagraphDirectFormatting(SwPosition(*GetTextNodeForParaProps())))
        {
            Color aHatchColor(rParaStylesColorMap[sStyleName].first);
            // make hatch line color 41% darker than the fill color
            aHatchColor.ApplyTintOrShade(-4100);
            Hatch aHatch(HatchStyle::Single, aHatchColor, 50, 450_deg10);
            pRenderContext->DrawHatch(tools::PolyPolygon(rRect), aHatch);
        }

        pRenderContext->SetFont(aFont);
        pRenderContext->SetLayoutMode(vcl::text::ComplexTextLayoutFlags::Default);
        pRenderContext->SetTextFillColor(rParaStylesColorMap[sStyleName].first);
        pRenderContext->DrawText(rRect, OUString::number(rParaStylesColorMap[sStyleName].second),
                                 DrawTextFlags::Center | DrawTextFlags::VCenter);

        pRenderContext->Pop();
    }
}

void SwTextFrame::PaintOutlineContentVisibilityButton() const
{
    SwWrtShell* pWrtSh = dynamic_cast<SwWrtShell*>(gProp.pSGlobalShell);
@@ -4339,7 +4427,6 @@ void SwTextFrame::PaintOutlineContentVisibilityButton() const
        UpdateOutlineContentVisibilityButton(pWrtSh);
}


void SwTabFrame::PaintSwFrame(vcl::RenderContext& rRenderContext, SwRect const& rRect, SwPrintData const*const) const
{
    const SwViewOption* pViewOption = gProp.pSGlobalShell->GetViewOptions();
diff --git a/sw/source/core/text/frmpaint.cxx b/sw/source/core/text/frmpaint.cxx
index 74ff8c9..b187db7 100644
--- a/sw/source/core/text/frmpaint.cxx
+++ b/sw/source/core/text/frmpaint.cxx
@@ -501,6 +501,8 @@ SwRect SwTextFrame::GetPaintSwRect()

bool SwTextFrame::PaintEmpty( const SwRect &rRect, bool bCheck ) const
{
    PaintParagraphStylesHighlighting();

    SwViewShell *pSh = getRootFrame()->GetCurrShell();
    if( pSh && ( pSh->GetViewOptions()->IsParagraph() || bInitFont ) )
    {
@@ -793,6 +795,8 @@ void SwTextFrame::PaintSwFrame(vcl::RenderContext& rRenderContext, SwRect const&
            rRepaint.Clear();
    }

    PaintParagraphStylesHighlighting();

    const_cast<SwRect&>(rRect) = aOldRect;

    OSL_ENSURE( ! IsSwapped(), "A frame is swapped after Paint" );
diff --git a/sw/source/core/text/inftxt.cxx b/sw/source/core/text/inftxt.cxx
index a003208..895d2ab 100644
--- a/sw/source/core/text/inftxt.cxx
+++ b/sw/source/core/text/inftxt.cxx
@@ -67,6 +67,16 @@
#include <i18nlangtag/mslangid.hxx>
#include <formatlinebreak.hxx>

#include <view.hxx>
#include <wrtsh.hxx>
#include <com/sun/star/text/XTextRange.hpp>
#include <unotextrange.hxx>
#include <SwStyleNameMapper.hxx>
#include <unoprnms.hxx>
#include <editeng/unoprnms.hxx>
#include <unomap.hxx>
#include <com/sun/star/awt/FontSlant.hpp>

using namespace ::com::sun::star;
using namespace ::com::sun::star::linguistic2;
using namespace ::com::sun::star::uno;
@@ -1305,6 +1315,173 @@ void SwTextPaintInfo::DrawBorder( const SwLinePortion &rPor ) const
    }
}

namespace {

bool HasValidPropertyValue(const uno::Any& rAny)
{
    if (bool bValue; rAny >>= bValue)
    {
        return true;
    }
    else if (OUString aValue; (rAny >>= aValue) && !(aValue.isEmpty()))
    {
        return true;
    }
    else if (awt::FontSlant eValue; rAny >>= eValue)
    {
        return true;
    }
    else if (tools::Long nValueLong; rAny >>= nValueLong)
    {
        return true;
    }
    else if (double fValue; rAny >>= fValue)
    {
        return true;
    }
    else if (short nValueShort; rAny >>= nValueShort)
    {
        return true;
    }
    else
        return false;
}
}

void SwTextPaintInfo::DrawCSDFHighlighting(const SwLinePortion &rPor) const
{
    // Don't use GetActiveView() as it does not work as expected when there are multiple open
    // documents.
    SwView* pView = SwTextFrame::GetView();
    if (!pView)
        return;

    StylesHighlighterColorMap& rCharStylesColorMap = pView->GetStylesHighlighterCharColorMap();

    if (rCharStylesColorMap.empty() && !pView->IsHighlightCharDF())
        return;

    SwRect aRect;
    CalcRect(rPor, &aRect, nullptr, true);
    if(!aRect.HasArea())
        return;

    SwTextFrame* pFrame = const_cast<SwTextFrame*>(GetTextFrame());
    if (!pFrame)
        return;

    SwPosition aPosition(pFrame->MapViewToModelPos(GetIdx()));
    SwPosition aMarkPosition(pFrame->MapViewToModelPos(GetIdx() + GetLen()));

    uno::Reference<text::XTextRange> xRange(
                SwXTextRange::CreateXTextRange(pFrame->GetDoc(), aPosition, &aMarkPosition));
    uno::Reference<beans::XPropertySet> xPropertiesSet(xRange, uno::UNO_QUERY_THROW);

    OUString sCurrentCharStyle;
    xPropertiesSet->getPropertyValue("CharStyleName") >>= sCurrentCharStyle;

    std::optional<OUString> sCSNumberOrDF; // CS number or "df" or not used
    std::optional<Color> aFillColor;

    // check for CS formatting, if not CS formatted check for direct character formatting
    if (!sCurrentCharStyle.isEmpty())
    {
        if (!rCharStylesColorMap.empty())
        {
            OUString sCharStyleDisplayName;
            sCharStyleDisplayName = SwStyleNameMapper::GetUIName(sCurrentCharStyle,
                                                                 SwGetPoolIdFromName::ChrFmt);
            if (!sCharStyleDisplayName.isEmpty()
                    && rCharStylesColorMap.find(sCharStyleDisplayName)
                    != rCharStylesColorMap.end())
            {
                aFillColor = rCharStylesColorMap[sCharStyleDisplayName].first;
                sCSNumberOrDF = OUString::number(rCharStylesColorMap[sCharStyleDisplayName].second);
            }
        }
    }
    // not character style formatted
    else if (pView->IsHighlightCharDF())
    {
        const std::vector<OUString> aHiddenProperties{ UNO_NAME_RSID,
                    UNO_NAME_PARA_IS_NUMBERING_RESTART,
                    UNO_NAME_PARA_STYLE_NAME,
                    UNO_NAME_PARA_CONDITIONAL_STYLE_NAME,
                    UNO_NAME_PAGE_STYLE_NAME,
                    UNO_NAME_NUMBERING_START_VALUE,
                    UNO_NAME_NUMBERING_IS_NUMBER,
                    UNO_NAME_PARA_CONTINUEING_PREVIOUS_SUB_TREE,
                    UNO_NAME_CHAR_STYLE_NAME,
                    UNO_NAME_NUMBERING_LEVEL,
                    UNO_NAME_SORTED_TEXT_ID,
                    UNO_NAME_PARRSID,
                    UNO_NAME_CHAR_COLOR_THEME,
                    UNO_NAME_CHAR_COLOR_TINT_OR_SHADE };

        SfxItemPropertySet const& rPropSet(
                    *aSwMapProvider.GetPropertySet(PROPERTY_MAP_CHAR_AUTO_STYLE));
        SfxItemPropertyMap const& rMap(rPropSet.getPropertyMap());


        uno::Reference<beans::XPropertyState> xPropertiesState(xRange, uno::UNO_QUERY_THROW);
        const uno::Sequence<beans::Property> aProperties
                = xPropertiesSet->getPropertySetInfo()->getProperties();

        for (const beans::Property& rProperty : aProperties)
        {
            const OUString& rPropName = rProperty.Name;

            if (!rMap.hasPropertyByName(rPropName))
                continue;

            if (std::find(aHiddenProperties.begin(), aHiddenProperties.end(), rPropName)
                    != aHiddenProperties.end())
                continue;

            if (xPropertiesState->getPropertyState(rPropName) == beans::PropertyState_DIRECT_VALUE)
            {
                const uno::Any aAny = xPropertiesSet->getPropertyValue(rPropName);
                if (HasValidPropertyValue(aAny))
                {
                    sCSNumberOrDF = SwResId(STR_CHARACTER_DIRECT_FORMATTING_TAG);
                    aFillColor = COL_LIGHTGRAY;
                    break;
                }
            }
        }
    }
    if (sCSNumberOrDF)
    {
        OutputDevice* pTmpOut = const_cast<OutputDevice*>(GetOut());
        pTmpOut->Push(vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR
                      | vcl::PushFlags::TEXTLAYOUTMODE | vcl::PushFlags::FONT);

        // draw a filled rectangle at the formatted CS or DF text
        pTmpOut->SetFillColor(aFillColor.value());
        pTmpOut->SetLineColor(aFillColor.value());
        tools::Rectangle aSVRect(aRect.SVRect());
        pTmpOut->DrawRect(aSVRect);

        // calculate size and position for the CS number or "df" text and rectangle
        tools::Long nWidth = pTmpOut->GetTextWidth(sCSNumberOrDF.value());
        tools::Long nHeight = pTmpOut->GetTextHeight();
        aSVRect.SetSize(Size(nWidth, nHeight));
        aSVRect.Move(-(nWidth / 1.5), -(nHeight / 1.5));

        vcl::Font aFont(pTmpOut->GetFont());
        aFont.SetOrientation(Degree10(0));
        pTmpOut->SetFont(aFont);

        pTmpOut->SetLayoutMode(vcl::text::ComplexTextLayoutFlags::TextOriginLeft);
        //pTmpOut->SetLayoutMode(vcl::text::ComplexTextLayoutFlags::BiDiStrong);

        pTmpOut->SetTextFillColor(aFillColor.value());
        pTmpOut->DrawText(aSVRect, sCSNumberOrDF.value(), DrawTextFlags::NONE);

        pTmpOut->Pop();
    }
}

void SwTextPaintInfo::DrawViewOpt( const SwLinePortion &rPor,
                                   PortionType nWhich, const Color *pColor ) const
{
diff --git a/sw/source/core/text/inftxt.hxx b/sw/source/core/text/inftxt.hxx
index 8011b29..62cca26 100644
--- a/sw/source/core/text/inftxt.hxx
+++ b/sw/source/core/text/inftxt.hxx
@@ -416,6 +416,8 @@ public:

    void DrawCheckBox(const SwFieldFormCheckboxPortion &rPor, bool bChecked) const;

    void DrawCSDFHighlighting(const SwLinePortion &rPor) const;

    /**
     * Calculate the rectangular area where the portion takes place.
     * @param[in]   rPor        portion for which the method specify the painting area
diff --git a/sw/source/core/text/porexp.cxx b/sw/source/core/text/porexp.cxx
index 9251d9f..de435df 100644
--- a/sw/source/core/text/porexp.cxx
+++ b/sw/source/core/text/porexp.cxx
@@ -74,12 +74,15 @@ bool SwExpandPortion::Format( SwTextFormatInfo &rInf )

void SwExpandPortion::Paint( const SwTextPaintInfo &rInf ) const
{
    rInf.DrawCSDFHighlighting(*this); // here it detects as CS and not DF

    SwTextSlot aDiffText( &rInf, this, true, true );
    const SwFont aOldFont = *rInf.GetFont();
    if( GetJoinBorderWithPrev() )
        const_cast<SwTextPaintInfo&>(rInf).GetFont()->SetLeftBorder(nullptr);
    if( GetJoinBorderWithNext() )
        const_cast<SwTextPaintInfo&>(rInf).GetFont()->SetRightBorder(nullptr);
//    rInf.DrawCSDFHighlighting(*this); // here it detects as DF and only the '/' is detected as CS

    rInf.DrawBackBrush( *this );
    rInf.DrawBorder( *this );
diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx
index 778a319..ebd281c 100644
--- a/sw/source/core/text/portxt.cxx
+++ b/sw/source/core/text/portxt.cxx
@@ -549,6 +549,8 @@ void SwTextPortion::Paint( const SwTextPaintInfo &rInf ) const
        rInf.DrawBackBrush( *this );
        rInf.DrawBorder( *this );

        rInf.DrawCSDFHighlighting(*this);

        // do we have to repaint a post it portion?
        if( rInf.OnWin() && mpNextPortion && !mpNextPortion->Width() )
            mpNextPortion->PrePaint( rInf, this );
diff --git a/sw/source/uibase/docvw/edtwin2.cxx b/sw/source/uibase/docvw/edtwin2.cxx
index 94febf8..a98d38c 100644
--- a/sw/source/uibase/docvw/edtwin2.cxx
+++ b/sw/source/uibase/docvw/edtwin2.cxx
@@ -54,6 +54,205 @@
#include <comphelper/lok.hxx>
#include <authfld.hxx>

#include <com/sun/star/text/XTextRange.hpp>
#include <unotextrange.hxx>
#include <SwStyleNameMapper.hxx>
#include <unoprnms.hxx>
#include <editeng/unoprnms.hxx>
#include <rootfrm.hxx>
#include <unomap.hxx>
#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>

namespace {

bool HasValidPropertyValue(const uno::Any& rAny)
{
    if (bool bValue; rAny >>= bValue)
    {
        return true;
    }
    else if (OUString aValue; (rAny >>= aValue) && !(aValue.isEmpty()))
    {
        return true;
    }
    else if (awt::FontSlant eValue; rAny >>= eValue)
    {
        return true;
    }
    else if (tools::Long nValueLong; rAny >>= nValueLong)
    {
        return true;
    }
    else if (double fValue; rAny >>= fValue)
    {
        return true;
    }
    else if (short nValueShort; rAny >>= nValueShort)
    {
        return true;
    }
    else
        return false;
}

bool PSCSDFPropsQuickHelp(const HelpEvent &rEvt, SwWrtShell& rSh)
{
    OUString sText;
    SwView& rView = rSh.GetView();

    if (rView.IsHighlightCharDF() || rView.GetStylesHighlighterParaColorMap().size()
            || rView.GetStylesHighlighterCharColorMap().size())
    {
        SwPosition aPos(rSh.GetDoc()->GetNodes());
        Point aPt(rSh.GetWin()->PixelToLogic(
                      rSh.GetWin()->ScreenToOutputPixel(rEvt.GetMousePosPixel())));

        rSh.GetLayout()->GetModelPositionForViewPoint(&aPos, aPt);

        if (!aPos.GetContentNode()->IsTextNode())
            return false;

        uno::Reference<text::XTextRange> xRange(
                    SwXTextRange::CreateXTextRange(*(rView.GetDocShell()->GetDoc()),
                                                   aPos, &aPos));
        uno::Reference<beans::XPropertySet> xPropertySet(xRange, uno::UNO_QUERY_THROW);

        SwContentFrame* pContentFrame = aPos.GetContentNode()->GetTextNode()->getLayoutFrame(
                            rSh.GetLayout());

        SwRect aFrameAreaRect;

        bool bContainsPt = false;
        do
        {
            aFrameAreaRect = pContentFrame->getFrameArea();
            if (aFrameAreaRect.Contains(aPt))
            {
                bContainsPt = true;
                break;
            }
        } while((pContentFrame = pContentFrame->GetFollow()));

        if (bContainsPt)
        {
            if (rView.GetStylesHighlighterCharColorMap().size())
            {
                // check if in CS formatting highlighted area
                OUString sCharStyle;
                xPropertySet->getPropertyValue("CharStyleName") >>= sCharStyle;
                if (!sCharStyle.isEmpty())
                    sText = SwStyleNameMapper::GetUIName(sCharStyle, SwGetPoolIdFromName::ChrFmt);
            }

            if (sText.isEmpty() && rView.IsHighlightCharDF())
            {
                // check if in direct formatting highlighted area
                const std::vector<OUString> aHiddenProperties{ UNO_NAME_RSID,
                            UNO_NAME_PARA_IS_NUMBERING_RESTART,
                            UNO_NAME_PARA_STYLE_NAME,
                            UNO_NAME_PARA_CONDITIONAL_STYLE_NAME,
                            UNO_NAME_PAGE_STYLE_NAME,
                            UNO_NAME_NUMBERING_START_VALUE,
                            UNO_NAME_NUMBERING_IS_NUMBER,
                            UNO_NAME_PARA_CONTINUEING_PREVIOUS_SUB_TREE,
                            UNO_NAME_CHAR_STYLE_NAME,
                            UNO_NAME_NUMBERING_LEVEL,
                            UNO_NAME_SORTED_TEXT_ID,
                            UNO_NAME_PARRSID,
                            UNO_NAME_CHAR_COLOR_THEME,
                            UNO_NAME_CHAR_COLOR_TINT_OR_SHADE };

                SfxItemPropertySet const& rPropSet(
                            *aSwMapProvider.GetPropertySet(PROPERTY_MAP_CHAR_AUTO_STYLE));
                SfxItemPropertyMap const& rMap(rPropSet.getPropertyMap());

                uno::Reference<beans::XPropertyState> xPropertiesState(xRange, uno::UNO_QUERY_THROW);
                const uno::Sequence<beans::Property> aProperties
                        = xPropertySet->getPropertySetInfo()->getProperties();

                for (const beans::Property& rProperty : aProperties)
                {
                    const OUString& rPropName = rProperty.Name;

                    if (!rMap.hasPropertyByName(rPropName))
                        continue;

                    if (std::find(aHiddenProperties.begin(), aHiddenProperties.end(), rPropName)
                            != aHiddenProperties.end())
                        continue;

                    if (xPropertiesState->getPropertyState(rPropName)
                            == beans::PropertyState_DIRECT_VALUE)
                    {
                        const uno::Any aAny = xPropertySet->getPropertyValue(rPropName);
                        if (HasValidPropertyValue(aAny))
                        {
                            sText = SwResId(STR_CHARACTER_DIRECT_FORMATTING);
                            break;
                        }
                    }
                }
            }
        }
        else if (rView.GetStylesHighlighterParaColorMap().size())
        {
            // check if in paragraph style formatting highlighted area
            pContentFrame = aPos.GetContentNode()->GetTextNode()->getLayoutFrame(
                        rSh.GetLayout());
            do
            {
                aFrameAreaRect = pContentFrame->getFrameArea();
                if (pContentFrame->IsRightToLeft())
                {
                    aFrameAreaRect.AddRight(375);
                    aFrameAreaRect.Left(aFrameAreaRect.Right() - 300);
                }
                else
                {
                    aFrameAreaRect.AddLeft(-375);
                    aFrameAreaRect.Right(aFrameAreaRect.Left() + 300);
                }
                if (aFrameAreaRect.Contains(aPt))
                {
                    OUString sParaStyle;
                    xPropertySet->getPropertyValue("ParaStyleName") >>= sParaStyle;
                    sText = SwStyleNameMapper::GetUIName(sParaStyle, SwGetPoolIdFromName::TxtColl);
                    // check for paragraph direct formatting
                    if (SwDoc::HasParagraphDirectFormatting(aPos))
                        sText = sText + " + " + SwResId(STR_PARAGRAPH_DIRECT_FORMATTING);
                    break;
                }
            } while((pContentFrame = pContentFrame->GetFollow()));
        }
    }

    if (!sText.isEmpty())
    {
        tools::Rectangle aRect(rSh.GetWin()->PixelToLogic(
                                   rSh.GetWin()->ScreenToOutputPixel(rEvt.GetMousePosPixel())),
                               Size(1, 1));
        Point aPt(rSh.GetWin()->OutputToScreenPixel(rSh.GetWin()->LogicToPixel(aRect.TopLeft())));
        aRect.SetLeft(aPt.X());
        aRect.SetTop(aPt.Y());
        aPt = rSh.GetWin()->OutputToScreenPixel(rSh.GetWin()->LogicToPixel(aRect.BottomRight()));
        aRect.SetRight(aPt.X());
        aRect.SetBottom(aPt.Y());

        // tdf#136336 ensure tooltip area surrounds the current mouse position with at least a pixel margin
        aRect.Union(tools::Rectangle(rEvt.GetMousePosPixel(), Size(1, 1)));
        aRect.AdjustLeft(-1);
        aRect.AdjustRight(1);
        aRect.AdjustTop(-1);
        aRect.AdjustBottom(1);

        QuickHelpFlags nStyle = QuickHelpFlags::NONE; //TipStyleBalloon;
        Help::ShowQuickHelp(rSh.GetWin(), aRect, sText, nStyle);
    }

    return !sText.isEmpty();
}
}

static OUString lcl_GetRedlineHelp( const SwRangeRedline& rRedl, bool bBalloon, bool bTableChange )
{
    TranslateId pResId;
@@ -108,6 +307,10 @@ OUString SwEditWin::ClipLongToolTip(const OUString& rText)
void SwEditWin::RequestHelp(const HelpEvent &rEvt)
{
    SwWrtShell &rSh = m_rView.GetWrtShell();

    if (PSCSDFPropsQuickHelp(rEvt, rSh))
        return;

    bool bQuickBalloon = bool(rEvt.GetMode() & ( HelpEventMode::QUICK | HelpEventMode::BALLOON ));
    if(bQuickBalloon && !rSh.GetViewOptions()->IsShowContentTips())
        return;
diff --git a/sw/source/uibase/uiview/view0.cxx b/sw/source/uibase/uiview/view0.cxx
index ba55557..0a620a0 100644
--- a/sw/source/uibase/uiview/view0.cxx
+++ b/sw/source/uibase/uiview/view0.cxx
@@ -225,7 +225,7 @@ void SwView::StateViewOptions(SfxItemSet &rSet)
    while(nWhich)
    {
        bool bReadonly = GetDocShell()->IsReadOnly();
        if ( bReadonly && nWhich != FN_VIEW_GRAPHIC )
        if (bReadonly && nWhich != FN_VIEW_GRAPHIC && nWhich != FN_HIGHLIGHT_CHAR_DF)
        {
            rSet.DisableItem(nWhich);
            nWhich = 0;
@@ -359,6 +359,9 @@ void SwView::StateViewOptions(SfxItemSet &rSet)
            case FN_SHOW_CHANGES_IN_MARGIN:
              aBool.SetValue( pOpt->IsShowChangesInMargin() );
            break;
            case FN_HIGHLIGHT_CHAR_DF:
              aBool.SetValue(m_bIsHighlightCharDF);
            break;
        }

        if( nWhich )
@@ -549,6 +552,12 @@ void SwView::ExecViewOptions(SfxRequest &rReq)
        lcl_SetViewMarks( *pOpt, bFlag );
        break;

    case FN_HIGHLIGHT_CHAR_DF:
        if (STATE_TOGGLE == eState)
            bFlag = !m_bIsHighlightCharDF;
        m_bIsHighlightCharDF = bFlag;
        break;

    case FN_VIEW_META_CHARS:
        if( STATE_TOGGLE == eState )
            bFlag = !pOpt->IsViewMetaChars();
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index faad9ef..f01c282 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -3700,7 +3700,7 @@ void SalInstanceTreeView::do_insert(const weld::TreeIter* pParent, int pos, cons
        pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aDummy, aDummy, false));
    }
    if (pStr)
        AddStringItem(pEntry, *pStr, 0);
        AddStringItem(pEntry, *pStr, pEntry->ItemCount());
    pEntry->SetUserData(pUserData);
    m_xTreeView->Insert(pEntry, iter, nInsertPos);