summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
Diffstat (limited to 'sw')
-rw-r--r--sw/inc/cmdid.h2
-rw-r--r--sw/inc/doc.hxx2
-rw-r--r--sw/inc/strings.hrc4
-rw-r--r--sw/inc/view.hxx4
-rw-r--r--sw/sdi/_viewsh.sdi6
-rw-r--r--sw/sdi/swriter.sdi17
-rw-r--r--sw/source/core/doc/doc.cxx55
-rw-r--r--sw/source/core/inc/txtfrm.hxx6
-rw-r--r--sw/source/core/layout/paintfrm.cxx89
-rw-r--r--sw/source/core/text/frmpaint.cxx4
-rw-r--r--sw/source/core/text/inftxt.cxx177
-rw-r--r--sw/source/core/text/inftxt.hxx2
-rw-r--r--sw/source/core/text/porexp.cxx3
-rw-r--r--sw/source/core/text/portxt.cxx2
-rw-r--r--sw/source/uibase/docvw/edtwin2.cxx203
-rw-r--r--sw/source/uibase/uiview/view0.cxx11
16 files changed, 585 insertions, 2 deletions
diff --git a/sw/inc/cmdid.h b/sw/inc/cmdid.h
index 82616e3c2340..5459c63b8ff1 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 1b008bf2bac2..7a1b2e0ee969 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 a9e5a78828e0..a29a9c9e6e52 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 ff0099ace634..60fe6fdc7303 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 020383d31abc..a3b2e5e3cdcc 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 69e41da52ccc..15d098cc996c 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 07f54882fbdd..5c686f1f8c3a 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 942867882626..2376153b40d3 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 66612ba3b840..a68f58eaf5d7 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 74ff8c968e07..b187db7ac0b1 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 a0032082dd95..895d2aba2dd7 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 8011b29b442a..62cca26ac08f 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 9251d9f84171..de435df5ae54 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 778a319d2470..ebd281c607cf 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 94febf8b1f72..a98d38cf1e79 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 ba555570044e..0a620a0a05e5 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();