Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sw/source/uibase/docvw/edtwin2.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <doc.hxx>
21
#include <osl/diagnose.h>
22
#include <osl/thread.h>
23
#include <vcl/help.hxx>
24
#include <tools/json_writer.hxx>
25
#include <tools/urlobj.hxx>
26
#include <fmtrfmrk.hxx>
27
#include <svl/urihelper.hxx>
28
#include <sfx2/sfxhelp.hxx>
29
#include <svx/svdview.hxx>
30
#include <svx/svdpagv.hxx>
31
#include <swmodule.hxx>
32
#include <modcfg.hxx>
33
#include <view.hxx>
34
#include <wrtsh.hxx>
35
#include <docsh.hxx>
36
#include <edtwin.hxx>
37
#include <dpage.hxx>
38
#include <docufld.hxx>
39
#include <reffld.hxx>
40
#include <cellatr.hxx>
41
#include <shdwcrsr.hxx>
42
#include <fmtinfmt.hxx>
43
#include <fmtftn.hxx>
44
#include <redline.hxx>
45
#include <tox.hxx>
46
#include <txatbase.hxx>
47
#include <uitool.hxx>
48
#include <viewopt.hxx>
49
#include <strings.hrc>
50
51
#include <IDocumentMarkAccess.hxx>
52
#include <IDocumentRedlineAccess.hxx>
53
#include <txtfrm.hxx>
54
#include <ndtxt.hxx>
55
#include <comphelper/diagnose_ex.hxx>
56
#include <comphelper/lok.hxx>
57
#include <authfld.hxx>
58
#include <expfld.hxx>
59
60
#include <com/sun/star/text/XTextRange.hpp>
61
#include <unotextrange.hxx>
62
#include <SwStyleNameMapper.hxx>
63
#include <unoprnms.hxx>
64
#include <editeng/unoprnms.hxx>
65
#include <rootfrm.hxx>
66
#include <unomap.hxx>
67
#include <names.hxx>
68
#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
69
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
70
71
namespace {
72
73
bool HasValidPropertyValue(const uno::Any& rAny)
74
0
{
75
0
    if (bool bValue; rAny >>= bValue)
76
0
    {
77
0
        return true;
78
0
    }
79
0
    else if (OUString aValue; (rAny >>= aValue) && !(aValue.isEmpty()))
80
0
    {
81
0
        return true;
82
0
    }
83
0
    else if (awt::FontSlant eValue; rAny >>= eValue)
84
0
    {
85
0
        return true;
86
0
    }
87
0
    else if (tools::Long nValueLong; rAny >>= nValueLong)
88
0
    {
89
0
        return true;
90
0
    }
91
0
    else if (double fValue; rAny >>= fValue)
92
0
    {
93
0
        return true;
94
0
    }
95
0
    else if (short nValueShort; rAny >>= nValueShort)
96
0
    {
97
0
        return true;
98
0
    }
99
0
    else
100
0
        return false;
101
0
}
102
103
bool PSCSDFPropsQuickHelp(const HelpEvent &rEvt, SwWrtShell& rSh)
104
0
{
105
0
    UIName sText;
106
0
    SwView& rView = rSh.GetView();
107
108
0
    if (rView.IsSpotlightCharDF() || rView.IsSpotlightParaStyles()
109
0
            || rView.IsSpotlightCharStyles())
110
0
    {
111
0
        SwPosition aPos(rSh.GetDoc()->GetNodes());
112
0
        Point aPt(rSh.GetWin()->PixelToLogic(
113
0
                      rSh.GetWin()->ScreenToOutputPixel(rEvt.GetMousePosPixel())));
114
115
0
        rSh.GetLayout()->GetModelPositionForViewPoint(&aPos, aPt);
116
117
0
        if (!aPos.GetContentNode()->IsTextNode())
118
0
            return false;
119
120
0
        rtl::Reference<SwXTextRange> xRange(
121
0
                    SwXTextRange::CreateXTextRange(*(rView.GetDocShell()->GetDoc()),
122
0
                                                   aPos, &aPos));
123
0
        if (!xRange)
124
0
            throw uno::RuntimeException();
125
126
0
        SwContentFrame* pContentFrame = aPos.GetContentNode()->GetTextNode()->getLayoutFrame(
127
0
                            rSh.GetLayout());
128
129
0
        SwRect aFrameAreaRect;
130
131
0
        bool bContainsPt = false;
132
0
        do
133
0
        {
134
0
            aFrameAreaRect = pContentFrame->getFrameArea();
135
0
            if (aFrameAreaRect.Contains(aPt))
136
0
            {
137
0
                bContainsPt = true;
138
0
                break;
139
0
            }
140
0
        } while((pContentFrame = pContentFrame->GetFollow()));
141
142
0
        if (bContainsPt)
143
0
        {
144
0
            if (rView.IsSpotlightCharStyles())
145
0
            {
146
                // check if in CS formatting highlighted area
147
0
                OUString sCharStyle;
148
0
                xRange->getPropertyValue(u"CharStyleName"_ustr) >>= sCharStyle;
149
0
                if (!sCharStyle.isEmpty())
150
0
                    sText = SwStyleNameMapper::GetUIName(ProgName(sCharStyle), SwGetPoolIdFromName::ChrFmt);
151
0
            }
152
153
0
            if (sText.isEmpty() && rView.IsSpotlightCharDF())
154
0
            {
155
                // check if in direct formatting highlighted area
156
0
                const std::vector<OUString> aHiddenProperties{ UNO_NAME_RSID,
157
0
                            UNO_NAME_PARA_IS_NUMBERING_RESTART,
158
0
                            UNO_NAME_PARA_STYLE_NAME,
159
0
                            UNO_NAME_PARA_CONDITIONAL_STYLE_NAME,
160
0
                            UNO_NAME_PAGE_STYLE_NAME,
161
0
                            UNO_NAME_NUMBERING_START_VALUE,
162
0
                            UNO_NAME_NUMBERING_IS_NUMBER,
163
0
                            UNO_NAME_PARA_CONTINUEING_PREVIOUS_SUB_TREE,
164
0
                            UNO_NAME_CHAR_STYLE_NAME,
165
0
                            UNO_NAME_NUMBERING_LEVEL,
166
0
                            UNO_NAME_SORTED_TEXT_ID,
167
0
                            UNO_NAME_PARRSID,
168
0
                            UNO_NAME_CHAR_COLOR_THEME,
169
0
                            UNO_NAME_CHAR_COLOR_TINT_OR_SHADE };
170
171
0
                SfxItemPropertySet const& rPropSet(
172
0
                            *aSwMapProvider.GetPropertySet(PROPERTY_MAP_CHAR_AUTO_STYLE));
173
0
                SfxItemPropertyMap const& rMap(rPropSet.getPropertyMap());
174
175
0
                const uno::Sequence<beans::Property> aProperties
176
0
                        = xRange->getPropertySetInfo()->getProperties();
177
178
0
                for (const beans::Property& rProperty : aProperties)
179
0
                {
180
0
                    const OUString& rPropName = rProperty.Name;
181
182
0
                    if (!rMap.hasPropertyByName(rPropName))
183
0
                        continue;
184
185
0
                    if (std::find(aHiddenProperties.begin(), aHiddenProperties.end(), rPropName)
186
0
                            != aHiddenProperties.end())
187
0
                        continue;
188
189
0
                    if (xRange->getPropertyState(rPropName)
190
0
                            == beans::PropertyState_DIRECT_VALUE)
191
0
                    {
192
0
                        const uno::Any aAny = xRange->getPropertyValue(rPropName);
193
0
                        if (HasValidPropertyValue(aAny))
194
0
                        {
195
0
                            sText = UIName(SwResId(STR_CHARACTER_DIRECT_FORMATTING));
196
0
                            break;
197
0
                        }
198
0
                    }
199
0
                }
200
0
            }
201
0
        }
202
0
        else if (rView.IsSpotlightParaStyles())
203
0
        {
204
            // check if in paragraph style formatting highlighted area
205
0
            pContentFrame = aPos.GetContentNode()->GetTextNode()->getLayoutFrame(
206
0
                        rSh.GetLayout());
207
0
            do
208
0
            {
209
0
                aFrameAreaRect = pContentFrame->getFrameArea();
210
0
                if (pContentFrame->IsRightToLeft())
211
0
                {
212
0
                    aFrameAreaRect.AddRight(375);
213
0
                    aFrameAreaRect.Left(aFrameAreaRect.Right() - 300);
214
0
                }
215
0
                else
216
0
                {
217
0
                    aFrameAreaRect.AddLeft(-375);
218
0
                    aFrameAreaRect.Right(aFrameAreaRect.Left() + 300);
219
0
                }
220
0
                if (aFrameAreaRect.Contains(aPt))
221
0
                {
222
0
                    OUString sParaStyle;
223
0
                    xRange->getPropertyValue(u"ParaStyleName"_ustr) >>= sParaStyle;
224
0
                    sText = SwStyleNameMapper::GetUIName(ProgName(sParaStyle), SwGetPoolIdFromName::TxtColl);
225
                    // check for paragraph direct formatting
226
0
                    if (SwDoc::HasParagraphDirectFormatting(aPos))
227
0
                        sText = UIName(sText.toString() + " + " + SwResId(STR_PARAGRAPH_DIRECT_FORMATTING));
228
0
                    break;
229
0
                }
230
0
            } while((pContentFrame = pContentFrame->GetFollow()));
231
0
        }
232
0
    }
233
234
0
    if (!sText.isEmpty())
235
0
    {
236
0
        tools::Rectangle aRect(rSh.GetWin()->PixelToLogic(
237
0
                                   rSh.GetWin()->ScreenToOutputPixel(rEvt.GetMousePosPixel())),
238
0
                               Size(1, 1));
239
0
        Point aPt(rSh.GetWin()->OutputToScreenPixel(rSh.GetWin()->LogicToPixel(aRect.TopLeft())));
240
0
        aRect.SetLeft(aPt.X());
241
0
        aRect.SetTop(aPt.Y());
242
0
        aPt = rSh.GetWin()->OutputToScreenPixel(rSh.GetWin()->LogicToPixel(aRect.BottomRight()));
243
0
        aRect.SetRight(aPt.X());
244
0
        aRect.SetBottom(aPt.Y());
245
246
        // tdf#136336 ensure tooltip area surrounds the current mouse position with at least a pixel margin
247
0
        aRect.Union(tools::Rectangle(rEvt.GetMousePosPixel(), Size(1, 1)));
248
0
        aRect.AdjustLeft(-1);
249
0
        aRect.AdjustRight(1);
250
0
        aRect.AdjustTop(-1);
251
0
        aRect.AdjustBottom(1);
252
253
0
        QuickHelpFlags nStyle = QuickHelpFlags::NONE; //TipStyleBalloon;
254
0
        Help::ShowQuickHelp(rSh.GetWin(), aRect, sText.toString(), nStyle);
255
0
    }
256
257
0
    return !sText.isEmpty();
258
0
}
259
}
260
261
static OUString lcl_GetRedlineHelp( const SwRangeRedline& rRedl, bool bBalloon,
262
                                    bool bTableChange, bool bTableColChange )
263
0
{
264
0
    TranslateId pResId;
265
0
    switch( rRedl.GetType() )
266
0
    {
267
0
    case RedlineType::Insert:   pResId = bTableChange
268
0
        ? !bTableColChange
269
0
            ? STR_REDLINE_TABLE_ROW_INSERT
270
0
            : STR_REDLINE_TABLE_COLUMN_INSERT
271
0
        :  rRedl.IsMoved()
272
0
            ? STR_REDLINE_INSERT_MOVED
273
0
            : STR_REDLINE_INSERT;
274
0
        break;
275
0
    case RedlineType::Delete:   pResId = bTableChange
276
0
        ? !bTableColChange
277
0
            ? STR_REDLINE_TABLE_ROW_DELETE
278
0
            : STR_REDLINE_TABLE_COLUMN_DELETE
279
0
        : rRedl.IsMoved()
280
0
            ? STR_REDLINE_DELETE_MOVED
281
0
            : STR_REDLINE_DELETE;
282
0
        break;
283
0
    case RedlineType::Format:   pResId = STR_REDLINE_FORMAT; break;
284
0
    case RedlineType::Table:    pResId = STR_REDLINE_TABLE; break;
285
0
    case RedlineType::FmtColl:  pResId = STR_REDLINE_FMTCOLL; break;
286
0
    case RedlineType::ParagraphFormat: pResId = STR_REDLINE_PARAGRAPH_FORMAT; break;
287
0
    case RedlineType::TableRowInsert: pResId = STR_REDLINE_TABLE_ROW_INSERT; break;
288
0
    case RedlineType::TableRowDelete: pResId = STR_REDLINE_TABLE_ROW_DELETE; break;
289
0
    case RedlineType::TableCellInsert: pResId = STR_REDLINE_TABLE_CELL_INSERT; break;
290
0
    case RedlineType::TableCellDelete: pResId = STR_REDLINE_TABLE_CELL_DELETE; break;
291
0
    default: break;
292
0
    }
293
294
0
    if (!pResId)
295
0
        return OUString();
296
0
    OUStringBuffer sBuf(SwResId(pResId)
297
0
            + ": "
298
0
            + rRedl.GetAuthorString()
299
0
            + " - "
300
0
            + GetAppLangDateTimeString(rRedl.GetTimeStamp()));
301
0
    if( bBalloon && !rRedl.GetComment().isEmpty() )
302
0
        sBuf.append("\n" + rRedl.GetComment());
303
0
    return sBuf.makeStringAndClear();
304
0
}
305
306
OUString SwEditWin::ClipLongToolTip(const OUString& rText)
307
0
{
308
0
    OUString sDisplayText(rText);
309
0
    tools::Long nTextWidth = GetTextWidth(sDisplayText);
310
0
    tools::Long nMaxWidth = GetDesktopRectPixel().GetWidth() * 2 / 3;
311
0
    nMaxWidth = PixelToLogic(Size(nMaxWidth, 0)).Width();
312
0
    if (nTextWidth > nMaxWidth)
313
0
        sDisplayText = GetOutDev()->GetEllipsisString(sDisplayText, nMaxWidth, DrawTextFlags::CenterEllipsis);
314
0
    return sDisplayText;
315
0
}
316
317
static OString getTooltipPayload(const OUString& tooltip, const SwRect& rect)
318
0
{
319
0
    tools::JsonWriter writer;
320
0
    {
321
0
        writer.put("type", "generaltooltip");
322
0
        writer.put("text", tooltip);
323
0
        writer.put("rectangle", rect.SVRect().toString());
324
0
    }
325
0
    return writer.finishAndGetAsOString();
326
0
}
327
328
namespace
329
{
330
331
/** Fetches the text enclosed by the bookmark, resolved from the internal (input) link
332
 *
333
 * If a bookmark doesn't exist, return the original string.
334
 **/
335
OUString fetchBookmarkedValueFromInternalLink(const OUString& sURL, SwWrtShell& rShell)
336
0
{
337
    // Check if the URL is an internal link (starts with '#')
338
0
    if (!sURL.startsWith("#"))
339
0
        return sURL;
340
341
0
    IDocumentMarkAccess* pMarkAccess = rShell.getIDocumentMarkAccess();
342
0
    auto ppBookmark = pMarkAccess->findBookmark(SwMarkName(sURL.copy(1)));
343
0
    if (ppBookmark != pMarkAccess->getBookmarksEnd()
344
0
        && IDocumentMarkAccess::GetType(**ppBookmark)
345
0
            == IDocumentMarkAccess::MarkType::CROSSREF_HEADING_BOOKMARK)
346
0
    {
347
0
        SwTextNode* pTextNode = (*ppBookmark)->GetMarkStart().GetNode().GetTextNode();
348
0
        if (pTextNode)
349
0
        {
350
0
            OUString sText = sw::GetExpandTextMerged(rShell.GetLayout(), *pTextNode, true, false, ExpandMode(0));
351
352
0
            if (!sText.isEmpty())
353
0
            {
354
0
                OUStringBuffer sBuffer(sText.replaceAll(u"\u00ad", ""));
355
0
                for (sal_Int32 i = 0; i < sBuffer.getLength(); ++i)
356
0
                {
357
0
                    if (sBuffer[i] < 0x20)
358
0
                        sBuffer[i] = 0x20;
359
0
                    else if (sBuffer[i] == 0x2011)
360
0
                        sBuffer[i] = '-';
361
0
                }
362
0
                return sBuffer.makeStringAndClear();
363
0
            }
364
0
        }
365
0
    }
366
0
    return sURL;
367
0
}
368
}
369
370
void SwEditWin::RequestHelp(const HelpEvent &rEvt)
371
0
{
372
0
    SwWrtShell &rSh = m_rView.GetWrtShell();
373
374
0
    if (PSCSDFPropsQuickHelp(rEvt, rSh))
375
0
        return;
376
377
0
    bool bQuickBalloon = bool(rEvt.GetMode() & ( HelpEventMode::QUICK | HelpEventMode::BALLOON ));
378
0
    if(bQuickBalloon && !rSh.GetViewOptions()->IsShowContentTips())
379
0
        return;
380
0
    bool bContinue = true;
381
0
    bool bScreenTip = false;
382
0
    CurrShell aCurr(&rSh);
383
0
    OUString sText;
384
0
    Point aPt( PixelToLogic( ScreenToOutputPixel( rEvt.GetMousePosPixel() ) ));
385
0
    bool bBalloon = bool(rEvt.GetMode() & HelpEventMode::BALLOON);
386
387
0
    SdrView *pSdrView = rSh.GetDrawView();
388
389
0
    if( bQuickBalloon && pSdrView )
390
0
    {
391
0
        SdrPageView* pPV = pSdrView->GetSdrPageView();
392
0
        SwDPage* pPage = pPV ? static_cast<SwDPage*>(pPV->GetPage()) : nullptr;
393
0
        bContinue = pPage && pPage->RequestHelp(this, pSdrView, rEvt);
394
0
    }
395
396
0
    if( bContinue && bQuickBalloon)
397
0
    {
398
0
        SwRect aFieldRect;
399
0
        SwContentAtPos aContentAtPos( IsAttrAtPos::Field |
400
0
                                    IsAttrAtPos::InetAttr |
401
0
                                    IsAttrAtPos::Footnote |
402
0
                                    IsAttrAtPos::Redline |
403
0
                                    IsAttrAtPos::ToxMark |
404
0
                                    IsAttrAtPos::RefMark |
405
0
                                    IsAttrAtPos::SmartTag |
406
#ifdef DBG_UTIL
407
                                    IsAttrAtPos::TableBoxValue |
408
                                    ( bBalloon ? IsAttrAtPos::CurrAttrs : IsAttrAtPos::NONE) |
409
#endif
410
0
                                    IsAttrAtPos::TableBoxFml |
411
0
                                    IsAttrAtPos::TableRedline |
412
0
                                    IsAttrAtPos::TableColRedline );
413
414
0
        if( rSh.GetContentAtPos( aPt, aContentAtPos, false, &aFieldRect ) )
415
0
        {
416
0
            QuickHelpFlags nStyle = QuickHelpFlags::NONE; // style of quick help
417
0
            switch( aContentAtPos.eContentAtPos )
418
0
            {
419
0
            case IsAttrAtPos::TableBoxFml:
420
0
                sText = "= " + static_cast<const SwTableBoxFormula*>(aContentAtPos.aFnd.pAttr)->GetFormula();
421
0
                break;
422
#ifdef DBG_UTIL
423
            case IsAttrAtPos::TableBoxValue:
424
            {
425
                if(aContentAtPos.aFnd.pAttr)
426
                {
427
                    sText = OUString::number(
428
                                static_cast<const SwTableBoxValue*>(aContentAtPos.aFnd.pAttr)->GetValue());
429
                }
430
                break;
431
            }
432
            case IsAttrAtPos::CurrAttrs:
433
                sText = aContentAtPos.sStr;
434
                break;
435
#endif
436
437
0
            case IsAttrAtPos::InetAttr:
438
0
            {
439
0
                sText = static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr)->GetValue();
440
0
                sText = URIHelper::removePassword( sText,
441
0
                                        INetURLObject::EncodeMechanism::WasEncoded,
442
0
                                           INetURLObject::DecodeMechanism::Unambiguous);
443
                //#i63832# remove the link target type
444
0
                sal_Int32 nFound = sText.indexOf(cMarkSeparator);
445
0
                if( nFound != -1 && (++nFound) < sText.getLength() )
446
0
                {
447
0
                    std::u16string_view sSuffix( sText.subView(nFound) );
448
0
                    if( sSuffix == u"table" ||
449
0
                        sSuffix == u"frame" ||
450
0
                        sSuffix == u"region" ||
451
0
                        sSuffix == u"outline" ||
452
0
                        sSuffix == u"text" ||
453
0
                        sSuffix == u"graphic" ||
454
0
                        sSuffix == u"ole" ||
455
0
                        sSuffix == u"drawingobject" )
456
0
                        sText = sText.copy( 0, nFound - 1);
457
0
                }
458
                // #i104300#
459
                // special handling if target is a cross-reference bookmark
460
0
                {
461
0
                    sText = fetchBookmarkedValueFromInternalLink(sText, rSh);
462
0
                }
463
                // #i80029#
464
0
                bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly();
465
0
                if ( !bExecHyperlinks )
466
0
                {
467
0
                    sText = SfxHelp::GetURLHelpText(sText);
468
469
0
                    SwPosition aPos(rSh.GetDoc()->GetNodes());
470
0
                    rSh.GetLayout()->GetModelPositionForViewPoint(&aPos, aPt);
471
                    // Do not try to create a range for non-text and non-startnode;
472
                    // see MarkManager::makeMark
473
0
                    if (!aPos.GetNode().IsTextNode() && !aPos.GetNode().IsStartNode())
474
0
                        break;
475
0
                    rtl::Reference<SwXTextRange> xRange(SwXTextRange::CreateXTextRange(
476
0
                        *(m_rView.GetDocShell()->GetDoc()), aPos, &aPos));
477
478
0
                    try
479
0
                    {
480
0
                        OUString sName;
481
0
                        xRange->getPropertyValue(u"HyperLinkName"_ustr) >>= sName;
482
0
                        if (!sName.isEmpty())
483
0
                        {
484
0
                            bScreenTip = true;
485
0
                            OUStringBuffer sStrBuffer(sName);
486
0
                            sal_Int32 nTextLen = sText.getLength();
487
0
                            sal_Int32 nNameLen = sName.getLength();
488
0
                            if (nTextLen > 0 && nNameLen > nTextLen)
489
0
                            {
490
0
                                for (sal_Int32 i = nTextLen - 1; i < nNameLen; i += nTextLen)
491
0
                                    sStrBuffer.insert(i + 1, std::u16string_view(u"\n"));
492
0
                            }
493
0
                            sText = sStrBuffer.makeStringAndClear() + "\n" + sText;
494
0
                        }
495
0
                    }
496
0
                    catch (uno::RuntimeException&)
497
0
                    {
498
0
                        DBG_UNHANDLED_EXCEPTION("sw.ui", "failed to retrieve hyperlink name");
499
0
                    }
500
0
                }
501
0
                break;
502
0
            }
503
0
            case IsAttrAtPos::SmartTag:
504
0
            {
505
0
                vcl::KeyCode aCode( KEY_SPACE );
506
0
                vcl::KeyCode aModifiedCode( KEY_SPACE, KEY_MOD1 );
507
0
                OUString aModStr( aModifiedCode.GetName() );
508
0
                aModStr = aModStr.replaceFirst(aCode.GetName(), "");
509
0
                aModStr = aModStr.replaceAll("+", "");
510
0
                sText = SwResId(STR_SMARTTAG_CLICK).replaceAll("%s", aModStr);
511
0
                break;
512
0
            }
513
514
0
            case IsAttrAtPos::Footnote:
515
0
                if( aContentAtPos.pFndTextAttr && aContentAtPos.aFnd.pAttr )
516
0
                {
517
0
                    const SwFormatFootnote* pFootnote = static_cast<const SwFormatFootnote*>(aContentAtPos.aFnd.pAttr);
518
0
                    OUString sTmp(pFootnote->GetFootnoteText(*rSh.GetLayout()));
519
0
                    sText = SwResId( pFootnote->IsEndNote()
520
0
                                    ? STR_ENDNOTE : STR_FTNNOTE ) + sTmp;
521
0
                    bBalloon = true;
522
0
                    if( aContentAtPos.IsInRTLText() )
523
0
                        nStyle |= QuickHelpFlags::BiDiRtl;
524
0
                }
525
0
                break;
526
527
0
            case IsAttrAtPos::TableRedline:
528
0
            case IsAttrAtPos::TableColRedline:
529
0
            case IsAttrAtPos::Redline:
530
0
            {
531
0
                const bool bShowTrackChanges = IDocumentRedlineAccess::IsShowChanges( m_rView.GetDocShell()->GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags() );
532
0
                const bool bShowInlineTooltips = rSh.GetViewOptions()->IsShowInlineTooltips();
533
0
                if ( bShowTrackChanges && bShowInlineTooltips )
534
0
                {
535
0
                     sText = lcl_GetRedlineHelp(*aContentAtPos.aFnd.pRedl, bBalloon,
536
0
                         IsAttrAtPos::TableRedline == aContentAtPos.eContentAtPos ||
537
0
                         IsAttrAtPos::TableColRedline == aContentAtPos.eContentAtPos,
538
0
                         IsAttrAtPos::TableColRedline == aContentAtPos.eContentAtPos);
539
0
                }
540
0
                break;
541
0
            }
542
543
0
            case IsAttrAtPos::ToxMark:
544
0
                sText = aContentAtPos.sStr;
545
0
                if( !sText.isEmpty() && aContentAtPos.pFndTextAttr )
546
0
                {
547
0
                    const SwTOXType* pTType = aContentAtPos.pFndTextAttr->
548
0
                                        GetTOXMark().GetTOXType();
549
0
                    if( pTType && !pTType->GetTypeName().isEmpty() )
550
0
                    {
551
0
                        sText = ": " + sText;
552
0
                        sText = pTType->GetTypeName() + sText;
553
0
                    }
554
0
                }
555
0
                break;
556
557
0
            case IsAttrAtPos::RefMark:
558
0
                if(aContentAtPos.aFnd.pAttr)
559
0
                {
560
0
                    sText = SwResId(STR_CONTENT_TYPE_SINGLE_REFERENCE) + ": " +
561
0
                        static_cast<const SwFormatRefMark*>(aContentAtPos.aFnd.pAttr)->GetRefName().toString();
562
0
                }
563
0
            break;
564
565
0
            default:
566
0
                {
567
0
                    SwModuleOptions* pModOpt = SwModule::get()->GetModuleConfig();
568
0
                    if(!pModOpt->IsHideFieldTips())
569
0
                    {
570
0
                        const SwField* pField = aContentAtPos.aFnd.pField;
571
0
                        switch( pField->Which() )
572
0
                        {
573
0
                        case SwFieldIds::SetExp:
574
0
                        {
575
0
                            auto pSetExpField = const_cast<SwSetExpField*>(static_cast<const SwSetExpField*>(pField));
576
0
                            SwGetSetExpType nOldSubType = pSetExpField->GetSubType();
577
0
                            pSetExpField->SetSubType(SwGetSetExpType::Command);
578
0
                            sText = pSetExpField->ExpandField(true, rSh.GetLayout());
579
0
                            pSetExpField->SetSubType(nOldSubType);
580
0
                            break;
581
0
                        }
582
0
                        case SwFieldIds::Table:
583
0
                        {
584
0
                            auto pTableField = const_cast<SwTableField*>(static_cast<const SwTableField*>(pField));
585
0
                            SwTableFieldSubType nOldSubType = pTableField->GetSubType();
586
0
                            pTableField->SetSubType(SwTableFieldSubType::Command);
587
0
                            sText = pTableField->ExpandField(true, rSh.GetLayout());
588
0
                            pTableField->SetSubType(nOldSubType);
589
0
                            break;
590
0
                        }
591
0
                        case SwFieldIds::GetExp:
592
0
                        {
593
0
                            auto pGetExpField = const_cast<SwGetExpField*>(static_cast<const SwGetExpField*>(pField));
594
0
                            SwGetSetExpType nOldSubType = pGetExpField->GetSubType();
595
0
                            pGetExpField->SetSubType(SwGetSetExpType::Command);
596
0
                            sText = pGetExpField->ExpandField(true, rSh.GetLayout());
597
0
                            pGetExpField->SetSubType(nOldSubType);
598
0
                            break;
599
0
                        }
600
601
0
                        case SwFieldIds::Postit:
602
0
                            {
603
0
                                break;
604
0
                            }
605
0
                        case SwFieldIds::Input:  // BubbleHelp, because the suggestion could be quite long
606
0
                            bBalloon = true;
607
0
                            [[fallthrough]];
608
0
                        case SwFieldIds::Dropdown:
609
0
                        case SwFieldIds::JumpEdit:
610
0
                            sText = pField->GetPar2();
611
0
                            break;
612
613
0
                        case SwFieldIds::Database:
614
0
                            sText = pField->GetFieldName();
615
0
                            break;
616
617
0
                        case SwFieldIds::User:
618
0
                        {
619
0
                            OUString aTitle = pField->GetTitle();
620
0
                            if (!aTitle.isEmpty())
621
0
                            {
622
0
                                sText = aTitle;
623
0
                            }
624
0
                            else
625
0
                            {
626
0
                                sText = pField->GetPar1();
627
0
                            }
628
0
                            break;
629
0
                        }
630
0
                        case SwFieldIds::HiddenText:
631
0
                            sText = pField->GetPar1();
632
0
                            break;
633
634
0
                        case SwFieldIds::DocStat:
635
0
                            break;
636
637
0
                        case SwFieldIds::Macro:
638
0
                            sText = static_cast<const SwMacroField*>(pField)->GetMacro();
639
0
                            break;
640
641
0
                        case SwFieldIds::GetRef:
642
0
                        {
643
                            // #i85090#
644
0
                            const SwGetRefField* pRefField( dynamic_cast<const SwGetRefField*>(pField) );
645
0
                            OSL_ENSURE( pRefField,
646
0
                                    "<SwEditWin::RequestHelp(..)> - unexpected type of <pField>" );
647
0
                            if ( pRefField )
648
0
                            {
649
0
                                if ( pRefField->IsRefToHeadingCrossRefBookmark() ||
650
0
                                     pRefField->IsRefToNumItemCrossRefBookmark() )
651
0
                                {
652
0
                                    sText = pRefField->GetExpandedTextOfReferencedTextNode(*rSh.GetLayout());
653
0
                                    if ( sText.getLength() > 80  )
654
0
                                    {
655
0
                                        sText = OUString::Concat(sText.subView(0, 80)) + "...";
656
0
                                    }
657
0
                                }
658
0
                                else
659
0
                                {
660
0
                                    sText = pRefField->GetSetRefName().toString();
661
0
                                }
662
0
                            }
663
0
                            break;
664
0
                        }
665
0
                        case SwFieldIds::TableOfAuthorities:
666
0
                        {
667
0
                            const auto pAuthorityField = static_cast<const SwAuthorityField*>(pField);
668
0
                            sText = pAuthorityField->GetAuthority(rSh.GetLayout());
669
670
0
                            if (auto t = pAuthorityField->GetTargetType();
671
0
                                t == SwAuthorityField::TargetType::UseDisplayURL
672
0
                                || t == SwAuthorityField::TargetType::UseTargetURL)
673
0
                            {
674
0
                                const OUString aURL = pAuthorityField->GetAbsoluteURL();
675
0
                                sText += "\n" + SfxHelp::GetURLHelpText(aURL);
676
0
                            }
677
678
0
                            break;
679
0
                        }
680
681
0
                        default: break;
682
0
                        }
683
0
                    }
684
685
0
                    if( sText.isEmpty() )
686
0
                    {
687
0
                        const bool bShowTrackChanges = IDocumentRedlineAccess::IsShowChanges( m_rView.GetDocShell()->GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags() );
688
0
                        const bool bShowInlineTooltips = rSh.GetViewOptions()->IsShowInlineTooltips();
689
0
                        if ( bShowTrackChanges && bShowInlineTooltips )
690
0
                        {
691
0
                            aContentAtPos.eContentAtPos = IsAttrAtPos::Redline;
692
0
                            if( rSh.GetContentAtPos( aPt, aContentAtPos, false, &aFieldRect ) )
693
0
                                sText = lcl_GetRedlineHelp(*aContentAtPos.aFnd.pRedl, bBalloon, /*bTableChange=*/false, /*bTableColChange=*/false);
694
0
                        }
695
0
                    }
696
0
                }
697
0
            }
698
0
            if (!sText.isEmpty())
699
0
            {
700
0
                if (comphelper::LibreOfficeKit::isActive())
701
0
                {
702
0
                    m_rView.libreOfficeKitViewCallback(
703
0
                        LOK_CALLBACK_TOOLTIP, getTooltipPayload(sText, aFieldRect));
704
0
                }
705
0
                else
706
0
                {
707
0
                    tools::Rectangle aRect(aFieldRect.SVRect());
708
0
                    Point aRectPt(OutputToScreenPixel(LogicToPixel(aRect.TopLeft())));
709
0
                    aRect.SetLeft(aRectPt.X());
710
0
                    aRect.SetTop(aRectPt.Y());
711
0
                    aRectPt = OutputToScreenPixel(LogicToPixel(aRect.BottomRight()));
712
0
                    aRect.SetRight(aRectPt.X());
713
0
                    aRect.SetBottom(aRectPt.Y());
714
715
                    // tdf#136336 ensure tooltip area surrounds the current mouse position with at least a pixel margin
716
0
                    aRect.Union(tools::Rectangle(rEvt.GetMousePosPixel(), Size(1, 1)));
717
0
                    aRect.AdjustLeft(-1);
718
0
                    aRect.AdjustRight(1);
719
0
                    aRect.AdjustTop(-1);
720
0
                    aRect.AdjustBottom(1);
721
722
0
                    if (bBalloon)
723
0
                        Help::ShowBalloon(this, rEvt.GetMousePosPixel(), aRect, sText);
724
0
                    else
725
0
                    {
726
                        // the show the help
727
0
                        OUString sDisplayText(sText);
728
0
                        if (!bScreenTip)
729
0
                            sDisplayText = ClipLongToolTip(sText);
730
0
                        Help::ShowQuickHelp(this, aRect, sDisplayText, nStyle);
731
0
                    }
732
0
                }
733
0
            }
734
735
0
            bContinue = false;
736
0
        }
737
738
0
    }
739
740
0
    if( bContinue )
741
0
        Window::RequestHelp( rEvt );
742
0
}
743
744
void SwEditWin::PrePaint(vcl::RenderContext& /*rRenderContext*/)
745
0
{
746
0
    if (SwWrtShell* pWrtShell = GetView().GetWrtShellPtr())
747
0
        pWrtShell->PrePaint();
748
0
}
749
750
void SwEditWin::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
751
0
{
752
0
    SwWrtShell* pWrtShell = GetView().GetWrtShellPtr();
753
0
    if(!pWrtShell)
754
0
        return;
755
756
0
    if ( GetView().GetVisArea().GetWidth()  <= 0 ||
757
0
              GetView().GetVisArea().GetHeight() <= 0 )
758
0
        Invalidate( rRect );
759
0
    else
760
0
    {
761
0
        pWrtShell->setOutputToWindow(true);
762
0
        bool bTiledPainting = false;
763
0
        if (comphelper::LibreOfficeKit::isActive())
764
0
        {
765
0
            bTiledPainting = comphelper::LibreOfficeKit::isTiledPainting();
766
0
            comphelper::LibreOfficeKit::setTiledPainting(true);
767
0
        }
768
0
        pWrtShell->Paint(rRenderContext, rRect);
769
0
        if (comphelper::LibreOfficeKit::isActive())
770
0
        {
771
0
            comphelper::LibreOfficeKit::setTiledPainting(bTiledPainting);
772
0
        }
773
0
        pWrtShell->setOutputToWindow(false);
774
0
    }
775
0
}
776
777
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */