Coverage Report

Created: 2026-08-14 10:22

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