summaryrefslogtreecommitdiffstats
path: root/sw/source/uibase/docvw/edtwin2.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
commit940b4d1848e8c70ab7642901a68594e8016caffc (patch)
treeeb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /sw/source/uibase/docvw/edtwin2.cxx
parentInitial commit. (diff)
downloadlibreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz
libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sw/source/uibase/docvw/edtwin2.cxx')
-rw-r--r--sw/source/uibase/docvw/edtwin2.cxx441
1 files changed, 441 insertions, 0 deletions
diff --git a/sw/source/uibase/docvw/edtwin2.cxx b/sw/source/uibase/docvw/edtwin2.cxx
new file mode 100644
index 000000000..b48b18ec4
--- /dev/null
+++ b/sw/source/uibase/docvw/edtwin2.cxx
@@ -0,0 +1,441 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <doc.hxx>
+#include <osl/thread.h>
+#include <vcl/help.hxx>
+#include <tools/urlobj.hxx>
+#include <fmtrfmrk.hxx>
+#include <svl/urihelper.hxx>
+#include <sfx2/sfxhelp.hxx>
+#include <svx/svdview.hxx>
+#include <svx/svdpagv.hxx>
+#include <swmodule.hxx>
+#include <modcfg.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <docsh.hxx>
+#include <edtwin.hxx>
+#include <dpage.hxx>
+#include <docufld.hxx>
+#include <reffld.hxx>
+#include <cellatr.hxx>
+#include <shdwcrsr.hxx>
+#include <fmtinfmt.hxx>
+#include <fmtftn.hxx>
+#include <redline.hxx>
+#include <tox.hxx>
+#include <txatbase.hxx>
+#include <uitool.hxx>
+#include <viewopt.hxx>
+#include <strings.hrc>
+
+#include <IDocumentMarkAccess.hxx>
+#include <txtfrm.hxx>
+#include <ndtxt.hxx>
+
+static OUString lcl_GetRedlineHelp( const SwRangeRedline& rRedl, bool bBalloon )
+{
+ const char* pResId = nullptr;
+ switch( rRedl.GetType() )
+ {
+ case RedlineType::Insert: pResId = STR_REDLINE_INSERT; break;
+ case RedlineType::Delete: pResId = STR_REDLINE_DELETE; break;
+ case RedlineType::Format: pResId = STR_REDLINE_FORMAT; break;
+ case RedlineType::Table: pResId = STR_REDLINE_TABLE; break;
+ case RedlineType::FmtColl: pResId = STR_REDLINE_FMTCOLL; break;
+ case RedlineType::ParagraphFormat: pResId = STR_REDLINE_PARAGRAPH_FORMAT; break;
+ case RedlineType::TableRowInsert: pResId = STR_REDLINE_TABLE_ROW_INSERT; break;
+ case RedlineType::TableRowDelete: pResId = STR_REDLINE_TABLE_ROW_DELETE; break;
+ case RedlineType::TableCellInsert: pResId = STR_REDLINE_TABLE_CELL_INSERT; break;
+ case RedlineType::TableCellDelete: pResId = STR_REDLINE_TABLE_CELL_DELETE; break;
+ default: break;
+ }
+
+ OUStringBuffer sBuf;
+ if (pResId)
+ {
+ sBuf.append(SwResId(pResId));
+ sBuf.append(": ");
+ sBuf.append(rRedl.GetAuthorString());
+ sBuf.append(" - ");
+ sBuf.append(GetAppLangDateTimeString(rRedl.GetTimeStamp()));
+ if( bBalloon && !rRedl.GetComment().isEmpty() )
+ sBuf.append('\n').append(rRedl.GetComment());
+ }
+ return sBuf.makeStringAndClear();
+}
+
+OUString SwEditWin::ClipLongToolTip(const OUString& rText)
+{
+ OUString sDisplayText(rText);
+ long nTextWidth = GetTextWidth(sDisplayText);
+ long nMaxWidth = GetDesktopRectPixel().GetWidth() * 2 / 3;
+ nMaxWidth = PixelToLogic(Size(nMaxWidth, 0)).Width();
+ if (nTextWidth > nMaxWidth)
+ sDisplayText = GetEllipsisString(sDisplayText, nMaxWidth, DrawTextFlags::CenterEllipsis);
+ return sDisplayText;
+}
+
+void SwEditWin::RequestHelp(const HelpEvent &rEvt)
+{
+ SwWrtShell &rSh = m_rView.GetWrtShell();
+ bool bQuickBalloon = bool(rEvt.GetMode() & ( HelpEventMode::QUICK | HelpEventMode::BALLOON ));
+ if(bQuickBalloon && !rSh.GetViewOptions()->IsShowContentTips())
+ return;
+ bool bContinue = true;
+ SET_CURR_SHELL(&rSh);
+ OUString sText;
+ Point aPos( PixelToLogic( ScreenToOutputPixel( rEvt.GetMousePosPixel() ) ));
+ bool bBalloon = bool(rEvt.GetMode() & HelpEventMode::BALLOON);
+
+ SdrView *pSdrView = rSh.GetDrawView();
+
+ if( bQuickBalloon && pSdrView )
+ {
+ SdrPageView* pPV = pSdrView->GetSdrPageView();
+ SwDPage* pPage = pPV ? static_cast<SwDPage*>(pPV->GetPage()) : nullptr;
+ bContinue = pPage && pPage->RequestHelp(this, pSdrView, rEvt);
+ }
+
+ if( bContinue && bQuickBalloon)
+ {
+ SwRect aFieldRect;
+ SwContentAtPos aContentAtPos( IsAttrAtPos::Field |
+ IsAttrAtPos::InetAttr |
+ IsAttrAtPos::Ftn |
+ IsAttrAtPos::Redline |
+ IsAttrAtPos::ToxMark |
+ IsAttrAtPos::RefMark |
+ IsAttrAtPos::SmartTag |
+#ifdef DBG_UTIL
+ IsAttrAtPos::TableBoxValue |
+ ( bBalloon ? IsAttrAtPos::CurrAttrs : IsAttrAtPos::NONE) |
+#endif
+ IsAttrAtPos::TableBoxFml );
+
+ if( rSh.GetContentAtPos( aPos, aContentAtPos, false, &aFieldRect ) )
+ {
+ QuickHelpFlags nStyle = QuickHelpFlags::NONE; // style of quick help
+ switch( aContentAtPos.eContentAtPos )
+ {
+ case IsAttrAtPos::TableBoxFml:
+ sText = "= " + static_cast<const SwTableBoxFormula*>(aContentAtPos.aFnd.pAttr)->GetFormula();
+ break;
+#ifdef DBG_UTIL
+ case IsAttrAtPos::TableBoxValue:
+ {
+ sText = OStringToOUString(OString::number(
+ static_cast<const SwTableBoxValue*>(aContentAtPos.aFnd.pAttr)->GetValue()),
+ osl_getThreadTextEncoding());
+ break;
+ }
+ case IsAttrAtPos::CurrAttrs:
+ sText = aContentAtPos.sStr;
+ break;
+#endif
+
+ case IsAttrAtPos::InetAttr:
+ {
+ sText = static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr)->GetValue();
+ sText = URIHelper::removePassword( sText,
+ INetURLObject::EncodeMechanism::WasEncoded,
+ INetURLObject::DecodeMechanism::Unambiguous);
+ //#i63832# remove the link target type
+ sal_Int32 nFound = sText.indexOf(cMarkSeparator);
+ if( nFound != -1 && (++nFound) < sText.getLength() )
+ {
+ OUString sSuffix( sText.copy(nFound) );
+ if( sSuffix == "table" ||
+ sSuffix == "frame" ||
+ sSuffix == "region" ||
+ sSuffix == "outline" ||
+ sSuffix == "text" ||
+ sSuffix == "graphic" ||
+ sSuffix == "ole" )
+ sText = sText.copy( 0, nFound - 1);
+ }
+ // #i104300#
+ // special handling if target is a cross-reference bookmark
+ {
+ OUString sTmpSearchStr = sText.copy( 1 );
+ IDocumentMarkAccess* pMarkAccess = rSh.getIDocumentMarkAccess();
+ IDocumentMarkAccess::const_iterator_t ppBkmk =
+ pMarkAccess->findBookmark( sTmpSearchStr );
+ if ( ppBkmk != pMarkAccess->getBookmarksEnd() &&
+ IDocumentMarkAccess::GetType(**ppBkmk)
+ == IDocumentMarkAccess::MarkType::CROSSREF_HEADING_BOOKMARK )
+ {
+ SwTextNode* pTextNode = (*ppBkmk)->GetMarkStart().nNode.GetNode().GetTextNode();
+ if ( pTextNode )
+ {
+ sText = sw::GetExpandTextMerged(rSh.GetLayout(), *pTextNode, true, false, ExpandMode(0));
+
+ if( !sText.isEmpty() )
+ {
+ OUStringBuffer sTmp(sText.replaceAll(u"\u00ad", ""));
+ for (sal_Int32 i = 0; i < sTmp.getLength(); ++i)
+ {
+ if (sTmp[i] < 0x20)
+ sTmp[i] = 0x20;
+ else if (sTmp[i] == 0x2011)
+ sTmp[i] = '-';
+ }
+ sText = sTmp.makeStringAndClear();
+ }
+ }
+ }
+ }
+ // #i80029#
+ bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
+ if ( !bExecHyperlinks )
+ {
+ sText = SfxHelp::GetURLHelpText(sText);
+ }
+ break;
+ }
+ case IsAttrAtPos::SmartTag:
+ {
+ vcl::KeyCode aCode( KEY_SPACE );
+ vcl::KeyCode aModifiedCode( KEY_SPACE, KEY_MOD1 );
+ OUString aModStr( aModifiedCode.GetName() );
+ aModStr = aModStr.replaceFirst(aCode.GetName(), "");
+ aModStr = aModStr.replaceAll("+", "");
+ sText = SwResId(STR_SMARTTAG_CLICK).replaceAll("%s", aModStr);
+ break;
+ }
+
+ case IsAttrAtPos::Ftn:
+ if( aContentAtPos.pFndTextAttr && aContentAtPos.aFnd.pAttr )
+ {
+ const SwFormatFootnote* pFootnote = static_cast<const SwFormatFootnote*>(aContentAtPos.aFnd.pAttr);
+ OUString sTmp(pFootnote->GetFootnoteText(*rSh.GetLayout()));
+ sText = SwResId( pFootnote->IsEndNote()
+ ? STR_ENDNOTE : STR_FTNNOTE ) + sTmp;
+ bBalloon = true;
+ if( aContentAtPos.IsInRTLText() )
+ nStyle |= QuickHelpFlags::BiDiRtl;
+ }
+ break;
+
+ case IsAttrAtPos::Redline:
+ {
+ const bool bShowTrackChanges = IDocumentRedlineAccess::IsShowChanges( m_rView.GetDocShell()->GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags() );
+ const bool bShowInlineTooltips = rSh.GetViewOptions()->IsShowInlineTooltips();
+ if ( bShowTrackChanges && bShowInlineTooltips )
+ sText = lcl_GetRedlineHelp(*aContentAtPos.aFnd.pRedl, bBalloon);
+ break;
+ }
+
+ case IsAttrAtPos::ToxMark:
+ sText = aContentAtPos.sStr;
+ if( !sText.isEmpty() && aContentAtPos.pFndTextAttr )
+ {
+ const SwTOXType* pTType = aContentAtPos.pFndTextAttr->
+ GetTOXMark().GetTOXType();
+ if( pTType && !pTType->GetTypeName().isEmpty() )
+ {
+ sText = ": " + sText;
+ sText = pTType->GetTypeName() + sText;
+ }
+ }
+ break;
+
+ case IsAttrAtPos::RefMark:
+ if(aContentAtPos.aFnd.pAttr)
+ {
+ sText = SwResId(STR_CONTENT_TYPE_SINGLE_REFERENCE) + ": ";
+ sText += static_cast<const SwFormatRefMark*>(aContentAtPos.aFnd.pAttr)->GetRefName();
+ }
+ break;
+
+ default:
+ {
+ SwModuleOptions* pModOpt = SW_MOD()->GetModuleConfig();
+ if(!pModOpt->IsHideFieldTips())
+ {
+ const SwField* pField = aContentAtPos.aFnd.pField;
+ switch( pField->Which() )
+ {
+ case SwFieldIds::SetExp:
+ case SwFieldIds::Table:
+ case SwFieldIds::GetExp:
+ {
+ sal_uInt16 nOldSubType = pField->GetSubType();
+ const_cast<SwField*>(pField)->SetSubType(nsSwExtendedSubType::SUB_CMD);
+ sText = pField->ExpandField(true, rSh.GetLayout());
+ const_cast<SwField*>(pField)->SetSubType(nOldSubType);
+ }
+ break;
+
+ case SwFieldIds::Postit:
+ {
+ break;
+ }
+ case SwFieldIds::Input: // BubbleHelp, because the suggestion could be quite long
+ bBalloon = true;
+ [[fallthrough]];
+ case SwFieldIds::Dropdown:
+ case SwFieldIds::JumpEdit:
+ sText = pField->GetPar2();
+ break;
+
+ case SwFieldIds::Database:
+ sText = pField->GetFieldName();
+ break;
+
+ case SwFieldIds::User:
+ case SwFieldIds::HiddenText:
+ sText = pField->GetPar1();
+ break;
+
+ case SwFieldIds::DocStat:
+ break;
+
+ case SwFieldIds::Macro:
+ sText = static_cast<const SwMacroField*>(pField)->GetMacro();
+ break;
+
+ case SwFieldIds::GetRef:
+ {
+ // #i85090#
+ const SwGetRefField* pRefField( dynamic_cast<const SwGetRefField*>(pField) );
+ OSL_ENSURE( pRefField,
+ "<SwEditWin::RequestHelp(..)> - unexpected type of <pField>" );
+ if ( pRefField )
+ {
+ if ( pRefField->IsRefToHeadingCrossRefBookmark() ||
+ pRefField->IsRefToNumItemCrossRefBookmark() )
+ {
+ sText = pRefField->GetExpandedTextOfReferencedTextNode(*rSh.GetLayout());
+ if ( sText.getLength() > 80 )
+ {
+ sText = sText.copy(0, 80) + "...";
+ }
+ }
+ else
+ {
+ sText = static_cast<const SwGetRefField*>(pField)->GetSetRefName();
+ }
+ }
+ break;
+ }
+
+ default: break;
+ }
+ }
+
+ if( sText.isEmpty() )
+ {
+ const bool bShowTrackChanges = IDocumentRedlineAccess::IsShowChanges( m_rView.GetDocShell()->GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags() );
+ const bool bShowInlineTooltips = rSh.GetViewOptions()->IsShowInlineTooltips();
+ if ( bShowTrackChanges && bShowInlineTooltips )
+ {
+ aContentAtPos.eContentAtPos = IsAttrAtPos::Redline;
+ if( rSh.GetContentAtPos( aPos, aContentAtPos, false, &aFieldRect ) )
+ sText = lcl_GetRedlineHelp(*aContentAtPos.aFnd.pRedl, bBalloon);
+ }
+ }
+ }
+ }
+ if (!sText.isEmpty())
+ {
+ tools::Rectangle aRect( aFieldRect.SVRect() );
+ Point aPt( OutputToScreenPixel( LogicToPixel( aRect.TopLeft() )));
+ aRect.SetLeft( aPt.X() );
+ aRect.SetTop( aPt.Y() );
+ aPt = OutputToScreenPixel( 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);
+
+ if( bBalloon )
+ Help::ShowBalloon( this, rEvt.GetMousePosPixel(), aRect, sText );
+ else
+ {
+ // the show the help
+ OUString sDisplayText(ClipLongToolTip(sText));
+ Help::ShowQuickHelp(this, aRect, sDisplayText, nStyle);
+ }
+ }
+
+ bContinue = false;
+ }
+
+ }
+
+ if( bContinue )
+ Window::RequestHelp( rEvt );
+}
+
+void SwEditWin::PrePaint(vcl::RenderContext& /*rRenderContext*/)
+{
+ SwWrtShell* pWrtShell = GetView().GetWrtShellPtr();
+
+ if(pWrtShell)
+ {
+ pWrtShell->PrePaint();
+ }
+}
+
+void SwEditWin::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
+{
+ SwWrtShell* pWrtShell = GetView().GetWrtShellPtr();
+ if(!pWrtShell)
+ return;
+ bool bPaintShadowCursor = false;
+ if( m_pShadCursor )
+ {
+ tools::Rectangle aRect( m_pShadCursor->GetRect());
+ // fully resides inside?
+ if( rRect.IsInside( aRect ) )
+ {
+ // then cancel
+ m_pShadCursor.reset();
+ }
+ else if( rRect.IsOver( aRect ))
+ {
+ // resides somewhat above, then everything is clipped outside
+ // and we have to make the "inner part" at the end of the
+ // Paint visible again. Otherwise Paint errors occur!
+ bPaintShadowCursor = true;
+ }
+ }
+
+ if ( GetView().GetVisArea().GetWidth() <= 0 ||
+ GetView().GetVisArea().GetHeight() <= 0 )
+ Invalidate( rRect );
+ else
+ {
+ pWrtShell->setOutputToWindow(true);
+ pWrtShell->Paint(rRenderContext, rRect);
+ pWrtShell->setOutputToWindow(false);
+ }
+
+ if( bPaintShadowCursor )
+ m_pShadCursor->Paint();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */