Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/editeng/source/outliner/overflowingtxt.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 <rtl/ustring.hxx>
21
#include <sal/log.hxx>
22
23
#include <editeng/overflowingtxt.hxx>
24
#include <editeng/outliner.hxx>
25
#include <editeng/outlobj.hxx>
26
#include <editeng/editeng.hxx>
27
#include <editeng/editobj.hxx>
28
29
#include <EditSelection.hxx>
30
#include <utility>
31
32
33
std::optional<OutlinerParaObject> TextChainingUtils::JuxtaposeParaObject(
34
        css::uno::Reference< css::datatransfer::XTransferable > const & xOverflowingContent,
35
        Outliner *pOutl,
36
        OutlinerParaObject const *pNextPObj)
37
0
{
38
0
    if (!pNextPObj) {
39
0
        pOutl->SetToEmptyText();
40
0
    } else {
41
0
        pOutl->SetText(*pNextPObj);
42
0
    }
43
44
    // Special case: if only empty text remove it at the end
45
0
    bool bOnlyOneEmptyPara = !pNextPObj ||
46
0
                             (pOutl->GetParagraphCount() == 1 &&
47
0
                              !pNextPObj->GetTextObject().HasText(0));
48
49
0
    EditEngine &rEditEngine = const_cast<EditEngine &>(pOutl->GetEditEngine());
50
51
    // XXX: this code should be moved in Outliner directly
52
    //          creating Outliner::InsertText(...transferable...)
53
0
    EditSelection aStartSel(rEditEngine.CreateSelection(ESelection(0,0)));
54
0
    EditSelection aNewSel = rEditEngine.InsertText(xOverflowingContent,
55
0
                                                    OUString(),
56
0
                                                    aStartSel.Min(),
57
0
                                                    true);
58
59
0
    if (!bOnlyOneEmptyPara) {
60
        // Separate Paragraphs
61
0
        rEditEngine.InsertParaBreak(aNewSel);
62
0
    }
63
64
65
0
    return pOutl->CreateParaObject();
66
0
}
67
68
std::optional<OutlinerParaObject> TextChainingUtils::DeeplyMergeParaObject(
69
        css::uno::Reference< css::datatransfer::XTransferable > const & xOverflowingContent,
70
        Outliner *pOutl,
71
        OutlinerParaObject const *pNextPObj)
72
0
{
73
0
    if (!pNextPObj) {
74
0
        pOutl->SetToEmptyText();
75
0
    } else {
76
0
        pOutl->SetText(*pNextPObj);
77
0
    }
78
79
0
    EditEngine &rEditEngine = const_cast<EditEngine &>(pOutl->GetEditEngine());
80
81
    // XXX: this code should be moved in Outliner directly
82
    //          creating Outliner::InsertText(...transferable...)
83
0
    EditSelection aStartSel(rEditEngine.CreateSelection(ESelection(0,0)));
84
    // We don't need to mark the selection
85
    // EditSelection aNewSel =
86
0
    rEditEngine.InsertText(xOverflowingContent,
87
0
                            OUString(),
88
0
                            aStartSel.Min(),
89
0
                            true);
90
91
0
    return pOutl->CreateParaObject();
92
0
}
93
94
css::uno::Reference< css::datatransfer::XTransferable > TextChainingUtils::CreateTransferableFromText(Outliner const *pOutl)
95
0
{
96
0
    EditEngine& rEditEngine = const_cast<EditEngine &>(pOutl->GetEditEngine());
97
0
    sal_Int32 nLastPara = pOutl->GetParagraphCount()-1;
98
0
    ESelection aWholeTextSel(0, 0, nLastPara, rEditEngine.GetTextLen(nLastPara));
99
100
0
    return rEditEngine.CreateTransferable(aWholeTextSel);
101
0
}
102
103
104
105
OverflowingText::OverflowingText(css::uno::Reference< css::datatransfer::XTransferable > xOverflowingContent) :
106
0
        mxOverflowingContent(std::move(xOverflowingContent))
107
0
{
108
109
0
}
110
111
112
113
NonOverflowingText::NonOverflowingText(const ESelection &aSel, bool bLastParaInterrupted)
114
0
    : maContentSel(aSel)
115
0
    , mbLastParaInterrupted(bLastParaInterrupted)
116
0
{
117
0
}
118
119
bool NonOverflowingText::IsLastParaInterrupted() const
120
0
{
121
0
    return mbLastParaInterrupted;
122
0
}
123
124
125
std::optional<OutlinerParaObject> NonOverflowingText::RemoveOverflowingText(Outliner *pOutliner) const
126
0
{
127
0
    pOutliner->QuickDelete(maContentSel);
128
0
    SAL_INFO("editeng.chaining", "Deleting selection from (Para: " << maContentSel.start.nPara
129
0
             << ", Pos: " << maContentSel.start.nIndex << ") to (Para: " << maContentSel.end.nPara
130
0
             << ", Pos: " << maContentSel.end.nIndex << ")");
131
0
    return pOutliner->CreateParaObject();
132
0
}
133
134
ESelection NonOverflowingText::GetOverflowPointSel() const
135
0
{
136
    //return getLastPositionSel(mpContentTextObj);
137
138
    // return the starting point of the selection we are removing
139
0
    return ESelection(maContentSel.start); //XXX
140
0
}
141
142
// The equivalent of ToParaObject for OverflowingText. Here we are prepending the overflowing text to the old dest box's text
143
// XXX: In a sense a better name for OverflowingText and NonOverflowingText are respectively DestLinkText and SourceLinkText
144
std::optional<OutlinerParaObject> OverflowingText::JuxtaposeParaObject(Outliner *pOutl, OutlinerParaObject const *pNextPObj)
145
0
{
146
0
    return TextChainingUtils::JuxtaposeParaObject(mxOverflowingContent, pOutl, pNextPObj);
147
0
}
148
149
std::optional<OutlinerParaObject> OverflowingText::DeeplyMergeParaObject(Outliner *pOutl, OutlinerParaObject const *pNextPObj)
150
0
{
151
0
    return TextChainingUtils::DeeplyMergeParaObject(mxOverflowingContent, pOutl, pNextPObj);
152
0
}
153
154
155
OFlowChainedText::OFlowChainedText(Outliner const *pOutl, bool bIsDeepMerge)
156
0
{
157
0
    mpOverflowingTxt = pOutl->GetOverflowingText();
158
0
    mpNonOverflowingTxt = pOutl->GetNonOverflowingText();
159
160
0
    mbIsDeepMerge = bIsDeepMerge;
161
0
}
162
163
OFlowChainedText::~OFlowChainedText()
164
0
{
165
0
}
166
167
168
ESelection OFlowChainedText::GetOverflowPointSel() const
169
0
{
170
0
    return mpNonOverflowingTxt->GetOverflowPointSel();
171
0
}
172
173
std::optional<OutlinerParaObject> OFlowChainedText::InsertOverflowingText(Outliner *pOutliner, OutlinerParaObject const *pTextToBeMerged)
174
0
{
175
    // Just return the roughly merged paras for now
176
0
    if (!mpOverflowingTxt)
177
0
        return std::nullopt;
178
179
0
    if (mbIsDeepMerge) {
180
0
        SAL_INFO("editeng.chaining", "[TEXTCHAINFLOW - OF] Deep merging paras" );
181
0
        return mpOverflowingTxt->DeeplyMergeParaObject(pOutliner, pTextToBeMerged );
182
0
    } else {
183
0
        SAL_INFO("editeng.chaining", "[TEXTCHAINFLOW - OF] Juxtaposing paras" );
184
0
        return mpOverflowingTxt->JuxtaposeParaObject(pOutliner, pTextToBeMerged );
185
0
    }
186
0
}
187
188
189
std::optional<OutlinerParaObject> OFlowChainedText::RemoveOverflowingText(Outliner *pOutliner)
190
0
{
191
0
    if (!mpNonOverflowingTxt)
192
0
        return std::nullopt;
193
194
0
    return mpNonOverflowingTxt->RemoveOverflowingText(pOutliner);
195
0
}
196
197
bool OFlowChainedText::IsLastParaInterrupted() const
198
0
{
199
0
    return mpNonOverflowingTxt->IsLastParaInterrupted();
200
0
}
201
202
203
204
UFlowChainedText::UFlowChainedText(Outliner const *pOutl, bool bIsDeepMerge)
205
0
{
206
0
    mxUnderflowingTxt = TextChainingUtils::CreateTransferableFromText(pOutl);
207
0
    mbIsDeepMerge = bIsDeepMerge;
208
0
}
209
210
std::optional<OutlinerParaObject> UFlowChainedText::CreateMergedUnderflowParaObject(Outliner *pOutl, OutlinerParaObject const *pNextLinkWholeText)
211
0
{
212
0
    std::optional<OutlinerParaObject> pNewText;
213
214
0
    if (mbIsDeepMerge) {
215
0
        SAL_INFO("editeng.chaining", "[TEXTCHAINFLOW - UF] Deep merging paras" );
216
0
        pNewText = TextChainingUtils::DeeplyMergeParaObject(mxUnderflowingTxt, pOutl, pNextLinkWholeText);
217
0
    } else {
218
        // NewTextForCurBox = Txt(CurBox) ++ Txt(NextBox)
219
0
        SAL_INFO("editeng.chaining", "[TEXTCHAINFLOW - UF] Juxtaposing paras" );
220
0
        pNewText = TextChainingUtils::JuxtaposeParaObject(mxUnderflowingTxt, pOutl, pNextLinkWholeText);
221
0
    }
222
223
0
    return pNewText;
224
225
0
}
226
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */