tdf#169791 sw: Fix trampled ruby base text with adding selection
Handling for non-contiguous selections in the Asian Phonetic Guide was broken by the change that introduced base text grouping. This change restores the lost functionality. Regression from commit3d9b8701cbAuthor: Jonathan Clark <jonathan@libreoffice.org> Date: Tue Sep 10 09:06:51 2024 -0600 Change-Id: Id3129f370fa72ab180f41a9816f9cd4d8718f847 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195112 Tested-by: Jenkins Reviewed-by: Jonathan Clark <jonathan@libreoffice.org> (cherry picked from commit1e275b2e0f) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195259 Reviewed-by: Adolfo Jayme Barrientos <fitojb@ubuntu.com>
This commit is contained in:
committed by
Adolfo Jayme Barrientos
parent
12a6b103fd
commit
1cf5e10ad9
@@ -67,6 +67,7 @@ constexpr OUString cRubyText = u"RubyText"_ustr;
|
||||
constexpr OUString cRubyAdjust = u"RubyAdjust"_ustr;
|
||||
constexpr OUString cRubyPosition = u"RubyPosition"_ustr;
|
||||
constexpr OUString cRubyCharStyleName = u"RubyCharStyleName"_ustr;
|
||||
constexpr OUString cRubySequence = u"RubySequenceNumber"_ustr;
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
@@ -125,66 +126,116 @@ public:
|
||||
virtual void SAL_CALL selectionChanged(const css::lang::EventObject& aEvent) override;
|
||||
virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
|
||||
|
||||
bool IsSelectionGrouped() { return aRubyValues.getLength() < 2; }
|
||||
bool IsSelectionGrouped()
|
||||
{
|
||||
auto nLastSequence = std::numeric_limits<sal_Int32>::lowest();
|
||||
for (const PropertyValues& rVals : aRubyValues)
|
||||
{
|
||||
for (const PropertyValue& rVal : rVals)
|
||||
{
|
||||
sal_Int32 nValue;
|
||||
if ((rVal.Name == cRubySequence) && (rVal.Value >>= nValue))
|
||||
{
|
||||
if (nValue <= nLastSequence)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
nLastSequence = nValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MakeSelectionGrouped()
|
||||
{
|
||||
if (aRubyValues.getLength() < 2)
|
||||
if (IsSelectionGrouped())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sal_Int32 nSequences = 0;
|
||||
for (const PropertyValue& rVal : aRubyValues[aRubyValues.size() - 1])
|
||||
{
|
||||
if (rVal.Name == cRubySequence)
|
||||
{
|
||||
rVal.Value >>= nSequences;
|
||||
}
|
||||
}
|
||||
|
||||
++nSequences;
|
||||
|
||||
Sequence<PropertyValues> aNewRubyValues{ nSequences };
|
||||
PropertyValues* pNewRubyValues = aNewRubyValues.getArray();
|
||||
|
||||
OUString sBaseTmp;
|
||||
OUStringBuffer aBaseString;
|
||||
for (const PropertyValues& rVals : aRubyValues)
|
||||
{
|
||||
sBaseTmp.clear();
|
||||
for (const PropertyValue& rVal : rVals)
|
||||
OUStringBuffer aRubyString;
|
||||
sal_Int32 nCurrSequence = 0;
|
||||
bool bAtStartOfSequence = true;
|
||||
|
||||
auto fnFinishSequence = [&] {
|
||||
for (PropertyValue& rVal : asNonConstRange(pNewRubyValues[nCurrSequence]))
|
||||
{
|
||||
if (rVal.Name == cRubyBaseText)
|
||||
{
|
||||
rVal.Value >>= sBaseTmp;
|
||||
sBaseTmp = aBaseString.makeStringAndClear();
|
||||
rVal.Value <<= sBaseTmp;
|
||||
}
|
||||
else if (rVal.Name == cRubyText)
|
||||
{
|
||||
sBaseTmp = aRubyString.makeStringAndClear();
|
||||
rVal.Value <<= sBaseTmp;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
aBaseString.append(sBaseTmp);
|
||||
}
|
||||
|
||||
Sequence<PropertyValues> aNewRubyValues{ 1 };
|
||||
PropertyValues* pNewRubyValues = aNewRubyValues.getArray();
|
||||
|
||||
// Copy some reasonable style values from the previous ruby array
|
||||
pNewRubyValues[0] = aRubyValues[0];
|
||||
for (const PropertyValues& rVals : aRubyValues)
|
||||
{
|
||||
// Check for advance
|
||||
for (const PropertyValue& rVal : rVals)
|
||||
{
|
||||
if (rVal.Name == cRubyText)
|
||||
if (rVal.Name == cRubySequence)
|
||||
{
|
||||
rVal.Value >>= sBaseTmp;
|
||||
if (!sBaseTmp.isEmpty())
|
||||
sal_Int32 nSeq = nCurrSequence;
|
||||
rVal.Value >>= nSeq;
|
||||
if (nSeq > nCurrSequence)
|
||||
{
|
||||
pNewRubyValues[0] = rVals;
|
||||
fnFinishSequence();
|
||||
nCurrSequence = nSeq;
|
||||
bAtStartOfSequence = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bAtStartOfSequence)
|
||||
{
|
||||
// Copy some reasonable style values from the previous ruby array
|
||||
pNewRubyValues[nCurrSequence] = rVals;
|
||||
bAtStartOfSequence = false;
|
||||
}
|
||||
|
||||
for (const PropertyValue& rVal : rVals)
|
||||
{
|
||||
if (rVal.Name == cRubyBaseText)
|
||||
{
|
||||
sBaseTmp.clear();
|
||||
rVal.Value >>= sBaseTmp;
|
||||
aBaseString.append(sBaseTmp);
|
||||
}
|
||||
else if (rVal.Name == cRubyText)
|
||||
{
|
||||
sBaseTmp.clear();
|
||||
rVal.Value >>= sBaseTmp;
|
||||
aRubyString.append(sBaseTmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PropertyValue* pNewValues = pNewRubyValues[0].getArray();
|
||||
for (sal_Int32 i = 0; i < pNewRubyValues[0].getLength(); ++i)
|
||||
{
|
||||
if (pNewValues[i].Name == cRubyBaseText)
|
||||
{
|
||||
sBaseTmp = aBaseString;
|
||||
pNewValues[i].Value <<= sBaseTmp;
|
||||
}
|
||||
else if (pNewValues[i].Name == cRubyText)
|
||||
{
|
||||
sBaseTmp.clear();
|
||||
pNewValues[i].Value <<= sBaseTmp;
|
||||
}
|
||||
}
|
||||
fnFinishSequence();
|
||||
|
||||
aRubyValues = std::move(aNewRubyValues);
|
||||
}
|
||||
@@ -363,13 +414,14 @@ void SvxRubyData_Impl::AssertOneEntry()
|
||||
{
|
||||
aRubyValues.realloc(1);
|
||||
Sequence<PropertyValue>& rValues = aRubyValues.getArray()[0];
|
||||
rValues.realloc(5);
|
||||
rValues.realloc(6);
|
||||
PropertyValue* pValues = rValues.getArray();
|
||||
pValues[0].Name = cRubyBaseText;
|
||||
pValues[1].Name = cRubyText;
|
||||
pValues[2].Name = cRubyAdjust;
|
||||
pValues[3].Name = cRubyPosition;
|
||||
pValues[4].Name = cRubyCharStyleName;
|
||||
pValues[5].Name = cRubySequence;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ class SwRubyListEntry
|
||||
{
|
||||
OUString m_sText;
|
||||
SwFormatRuby m_aRubyAttr;
|
||||
sal_Int32 m_nSequence = 0;
|
||||
|
||||
public:
|
||||
SwRubyListEntry() : m_aRubyAttr( OUString() ) {}
|
||||
|
||||
@@ -34,6 +36,9 @@ public:
|
||||
const SwFormatRuby& GetRubyAttr() const { return m_aRubyAttr; }
|
||||
SwFormatRuby& GetRubyAttr() { return m_aRubyAttr; }
|
||||
void SetRubyAttr( const SwFormatRuby& rAttr ) { m_aRubyAttr = rAttr; }
|
||||
|
||||
void SetSequence(sal_Int32 nSequence) { m_nSequence = nSequence; }
|
||||
sal_Int32 GetSequence() const { return m_nSequence; }
|
||||
};
|
||||
|
||||
#endif //_ INCLUDED_SW_INC_RUBYLIST_HXX
|
||||
|
||||
@@ -624,6 +624,7 @@ inline constexpr OUString UNO_NAME_RUBY_ADJUST = u"RubyAdjust"_ustr;
|
||||
inline constexpr OUString UNO_NAME_RUBY_CHAR_STYLE_NAME = u"RubyCharStyleName"_ustr;
|
||||
inline constexpr OUString UNO_NAME_RUBY_IS_ABOVE = u"RubyIsAbove"_ustr;
|
||||
inline constexpr OUString UNO_NAME_RUBY_POSITION = u"RubyPosition"_ustr;
|
||||
inline constexpr OUString UNO_NAME_RUBY_SEQUENCE_NUMBER = u"RubySequenceNumber"_ustr;
|
||||
inline constexpr OUString UNO_NAME_FOOTNOTE_HEIGHT = u"FootnoteHeight"_ustr;
|
||||
inline constexpr OUString UNO_NAME_FOOTNOTE_LINE_WEIGHT = u"FootnoteLineWeight"_ustr;
|
||||
inline constexpr OUString UNO_NAME_FOOTNOTE_LINE_COLOR = u"FootnoteLineColor"_ustr;
|
||||
|
||||
+77
-1
@@ -2019,6 +2019,11 @@ void SwDocTest::testFillRubyList()
|
||||
for (auto const& rRuby : aRubies)
|
||||
{
|
||||
aTemp.append(rRuby->GetText() + u"["_ustr + rRuby->GetRubyAttr().GetText() + u"]"_ustr);
|
||||
|
||||
if (rRuby->GetSequence())
|
||||
{
|
||||
aTemp.append(u"("_ustr + OUString::number(rRuby->GetSequence()) + u")"_ustr);
|
||||
}
|
||||
}
|
||||
|
||||
return aTemp.makeStringAndClear();
|
||||
@@ -2162,6 +2167,34 @@ void SwDocTest::testFillRubyList()
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(u"学校[]"_ustr, fnGetCombinedString(aPaM));
|
||||
}
|
||||
|
||||
// tdf#169791: Characteristic test for ruby with non-contiguous selection
|
||||
{
|
||||
fnAppendJapanese(u"学校に行こう"_ustr);
|
||||
|
||||
SwPaM aPaM0{ *aPaM.GetPoint(), *aPaM.GetPoint() };
|
||||
aPaM0.GetMark()->AdjustContent(2);
|
||||
|
||||
SwPaM aPaM1{ *aPaM.GetPoint(), *aPaM.GetPoint(), &aPaM0 };
|
||||
aPaM1.GetPoint()->AdjustContent(3);
|
||||
aPaM1.GetMark()->AdjustContent(4);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(u"学校[]行[](1)"_ustr, fnGetCombinedString(aPaM1));
|
||||
}
|
||||
|
||||
// tdf#169791: Another non-contiguous selection
|
||||
{
|
||||
fnAppendJapanese(u"経済学者の経済学者"_ustr);
|
||||
|
||||
SwPaM aPaM0{ *aPaM.GetPoint(), *aPaM.GetPoint() };
|
||||
aPaM0.GetMark()->AdjustContent(4);
|
||||
|
||||
SwPaM aPaM1{ *aPaM.GetPoint(), *aPaM.GetPoint(), &aPaM0 };
|
||||
aPaM1.GetPoint()->AdjustContent(5);
|
||||
aPaM1.GetMark()->AdjustContent(9);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(u"経済[]学者[]経済[](1)学者[](1)"_ustr, fnGetCombinedString(aPaM1));
|
||||
}
|
||||
}
|
||||
|
||||
void SwDocTest::testSetRubyList()
|
||||
@@ -2191,11 +2224,13 @@ void SwDocTest::testSetRubyList()
|
||||
CPPUNIT_ASSERT_EQUAL(rText, aPaM.GetText());
|
||||
};
|
||||
|
||||
auto fnAppendRuby = [](SwRubyList* rList, OUString aBase, OUString aRuby)
|
||||
auto fnAppendRuby
|
||||
= [](SwRubyList* rList, OUString aBase, OUString aRuby, sal_Int32 nSequence = 0)
|
||||
{
|
||||
auto pEnt = std::make_unique<SwRubyListEntry>();
|
||||
pEnt->SetText(std::move(aBase));
|
||||
pEnt->SetRubyAttr(SwFormatRuby{ std::move(aRuby) });
|
||||
pEnt->SetSequence(nSequence);
|
||||
|
||||
rList->push_back(std::move(pEnt));
|
||||
};
|
||||
@@ -2559,6 +2594,47 @@ void SwDocTest::testSetRubyList()
|
||||
CPPUNIT_ASSERT_EQUAL(u"学森林[しんりん]海上[かいじょう]地面[じめん]校"_ustr,
|
||||
fnGetCombinedString());
|
||||
}
|
||||
|
||||
// tdf#169791: Characteristic test for ruby with non-contiguous selection
|
||||
{
|
||||
fnAppendJapanese(u"学校に行こう"_ustr);
|
||||
|
||||
SwPaM aPaM0{ *aPaM.GetPoint(), *aPaM.GetPoint() };
|
||||
aPaM0.GetMark()->AdjustContent(2);
|
||||
|
||||
SwPaM aPaM1{ *aPaM.GetPoint(), *aPaM.GetPoint(), &aPaM0 };
|
||||
aPaM1.GetPoint()->AdjustContent(3);
|
||||
aPaM1.GetMark()->AdjustContent(4);
|
||||
|
||||
SwRubyList rList;
|
||||
fnAppendRuby(&rList, u"学校"_ustr, u"がっこう"_ustr, /*nSequence*/ 0);
|
||||
fnAppendRuby(&rList, u"行"_ustr, u"い"_ustr, /*nSequence*/ 1);
|
||||
|
||||
m_pDoc->SetRubyList(aPaM1, rList);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(u"学校[がっこう]に行[い]こう"_ustr, fnGetCombinedString());
|
||||
}
|
||||
|
||||
// tdf#169791: Test for ruby with non-contiguous selection and deleted inner subsequence
|
||||
{
|
||||
fnAppendJapanese(u"経済学者の経済学者"_ustr);
|
||||
|
||||
SwPaM aPaM0{ *aPaM.GetPoint(), *aPaM.GetPoint() };
|
||||
aPaM0.GetMark()->AdjustContent(4);
|
||||
|
||||
SwPaM aPaM1{ *aPaM.GetPoint(), *aPaM.GetPoint(), &aPaM0 };
|
||||
aPaM1.GetPoint()->AdjustContent(5);
|
||||
aPaM1.GetMark()->AdjustContent(9);
|
||||
|
||||
SwRubyList rList;
|
||||
fnAppendRuby(&rList, u"経済学者"_ustr, u"けいざいがくしゃ"_ustr, /*nSequence*/ 0);
|
||||
fnAppendRuby(&rList, u"経済学者"_ustr, u"けいざいがくしゃ"_ustr, /*nSequence*/ 1);
|
||||
|
||||
m_pDoc->SetRubyList(aPaM1, rList);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(u"経済学者[けいざいがくしゃ]の経済学者[けいざいがくしゃ]"_ustr,
|
||||
fnGetCombinedString());
|
||||
}
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(SwDocTest);
|
||||
|
||||
+117
-103
@@ -49,6 +49,7 @@ constexpr int nMaxBaseTexts = 30;
|
||||
*/
|
||||
sal_uInt16 SwDoc::FillRubyList( const SwPaM& rPam, SwRubyList& rList )
|
||||
{
|
||||
sal_Int32 nCurrSequence = 0;
|
||||
const SwPaM *_pStartCursor = rPam.GetNext(),
|
||||
*_pStartCursor2 = _pStartCursor;
|
||||
bool bCheckEmpty = &rPam != _pStartCursor;
|
||||
@@ -59,6 +60,7 @@ sal_uInt16 SwDoc::FillRubyList( const SwPaM& rPam, SwRubyList& rList )
|
||||
SwPaM aPam( *pStart );
|
||||
do {
|
||||
std::unique_ptr<SwRubyListEntry> pNew(new SwRubyListEntry);
|
||||
pNew->SetSequence(nCurrSequence);
|
||||
if( pEnd != pStart )
|
||||
{
|
||||
aPam.SetMark();
|
||||
@@ -85,6 +87,7 @@ sal_uInt16 SwDoc::FillRubyList( const SwPaM& rPam, SwRubyList& rList )
|
||||
if (nMaxBaseTexts <= rList.size())
|
||||
break;
|
||||
_pStartCursor = _pStartCursor->GetNext();
|
||||
++nCurrSequence;
|
||||
} while( _pStartCursor != _pStartCursor2 );
|
||||
|
||||
return rList.size();
|
||||
@@ -100,124 +103,135 @@ void SwDoc::SetRubyList(SwPaM& rPam, const SwRubyList& rList)
|
||||
|
||||
SwRubyList::size_type nListEntry = 0;
|
||||
int nCurrBaseTexts = 0;
|
||||
sal_Int32 nTotalContentGrowth = 0;
|
||||
sal_Int32 nCurrSequence = 0;
|
||||
|
||||
const SwPaM* pStartCursor = rPam.GetNext();
|
||||
auto [pStart, pEnd] = pStartCursor->StartEnd();
|
||||
|
||||
bool bCheckEmpty = (&rPam == pStartCursor) || (pStart != pEnd && *pStart != *pEnd);
|
||||
|
||||
// Sequentially replace as many spans as possible
|
||||
SwPaM aPam(*pStart);
|
||||
while (bCheckEmpty && nListEntry < rList.size() && nCurrBaseTexts < nMaxBaseTexts)
|
||||
const SwPaM* pStartCursor2 = pStartCursor;
|
||||
do
|
||||
{
|
||||
if (pEnd != pStart)
|
||||
auto [pStart, pEnd] = pStartCursor->StartEnd();
|
||||
|
||||
bool bCheckEmpty = (&rPam == pStartCursor) || (pStart != pEnd && *pStart != *pEnd);
|
||||
|
||||
// Sequentially replace as many spans as possible
|
||||
SwPaM aPam(*pStart);
|
||||
while (bCheckEmpty && nListEntry < rList.size()
|
||||
&& rList[nListEntry]->GetSequence() == nCurrSequence
|
||||
&& nCurrBaseTexts < nMaxBaseTexts)
|
||||
{
|
||||
aPam.SetMark();
|
||||
*aPam.GetMark() = *pEnd;
|
||||
if (pEnd != pStart)
|
||||
{
|
||||
aPam.SetMark();
|
||||
*aPam.GetMark() = *pEnd;
|
||||
}
|
||||
|
||||
SwRubyListEntry aCheckEntry;
|
||||
auto bSelected = SelectNextRubyChars(aPam, aCheckEntry);
|
||||
|
||||
if (bSelected)
|
||||
{
|
||||
++nCurrBaseTexts;
|
||||
|
||||
// Existing ruby text was located. Apply the new attributes.
|
||||
const SwRubyListEntry* pEntry = rList[nListEntry++].get();
|
||||
if (aCheckEntry.GetRubyAttr() != pEntry->GetRubyAttr())
|
||||
{
|
||||
// set/reset the attribute
|
||||
if (!pEntry->GetRubyAttr().GetText().isEmpty())
|
||||
{
|
||||
getIDocumentContentOperations().InsertPoolItem(aPam, pEntry->GetRubyAttr());
|
||||
}
|
||||
else
|
||||
{
|
||||
ResetAttrs(aPam, true, aDelArr);
|
||||
}
|
||||
}
|
||||
|
||||
if (aCheckEntry.GetText() != pEntry->GetText())
|
||||
{
|
||||
if (pEntry->GetText().isEmpty())
|
||||
{
|
||||
ResetAttrs(aPam, true, aDelArr);
|
||||
}
|
||||
|
||||
// text is changed, so replace the original
|
||||
getIDocumentContentOperations().ReplaceRange(aPam, pEntry->GetText(), false);
|
||||
aPam.Exchange();
|
||||
}
|
||||
|
||||
aPam.DeleteMark();
|
||||
}
|
||||
else
|
||||
{
|
||||
// No existing ruby text located. Advance to next paragraph.
|
||||
aPam.DeleteMark();
|
||||
aPam.Move(fnMoveForward, GoInNode);
|
||||
}
|
||||
|
||||
// Stop substituting when the cursor advances to the end of the selection.
|
||||
if (*aPam.GetPoint() >= *pEnd)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SwRubyListEntry aCheckEntry;
|
||||
auto bSelected = SelectNextRubyChars(aPam, aCheckEntry);
|
||||
|
||||
if (bSelected)
|
||||
// Delete any spans past the end of the ruby list
|
||||
while ((nListEntry == rList.size() || rList[nListEntry]->GetSequence() != nCurrSequence)
|
||||
&& nCurrBaseTexts < nMaxBaseTexts && *aPam.GetPoint() < *pEnd)
|
||||
{
|
||||
++nCurrBaseTexts;
|
||||
|
||||
// Existing ruby text was located. Apply the new attributes.
|
||||
const SwRubyListEntry* pEntry = rList[nListEntry++].get();
|
||||
if (aCheckEntry.GetRubyAttr() != pEntry->GetRubyAttr())
|
||||
if (pEnd != pStart)
|
||||
{
|
||||
// set/reset the attribute
|
||||
aPam.SetMark();
|
||||
*aPam.GetMark() = *pEnd;
|
||||
}
|
||||
|
||||
SwRubyListEntry aCheckEntry;
|
||||
auto bSelected = SelectNextRubyChars(aPam, aCheckEntry);
|
||||
|
||||
if (bSelected)
|
||||
{
|
||||
++nCurrBaseTexts;
|
||||
|
||||
ResetAttrs(aPam, true, aDelArr);
|
||||
getIDocumentContentOperations().DeleteRange(aPam);
|
||||
aPam.Exchange();
|
||||
|
||||
aPam.DeleteMark();
|
||||
}
|
||||
else
|
||||
{
|
||||
// No existing ruby text located. Advance to next paragraph.
|
||||
aPam.DeleteMark();
|
||||
aPam.Move(fnMoveForward, GoInNode);
|
||||
}
|
||||
}
|
||||
|
||||
// Insert any spans past the end of the base text list
|
||||
while (nListEntry < rList.size() && rList[nListEntry]->GetSequence() == nCurrSequence)
|
||||
{
|
||||
const SwRubyListEntry* pEntry = rList[nListEntry++].get();
|
||||
|
||||
if (!pEntry->GetText().isEmpty())
|
||||
{
|
||||
aPam.SetMark();
|
||||
getIDocumentContentOperations().InsertString(aPam, pEntry->GetText());
|
||||
aPam.GetMark()->AdjustContent(-pEntry->GetText().getLength());
|
||||
|
||||
if (!pEntry->GetRubyAttr().GetText().isEmpty())
|
||||
{
|
||||
getIDocumentContentOperations().InsertPoolItem(aPam, pEntry->GetRubyAttr());
|
||||
}
|
||||
else
|
||||
{
|
||||
ResetAttrs(aPam, true, aDelArr);
|
||||
}
|
||||
|
||||
aPam.DeleteMark();
|
||||
|
||||
nTotalContentGrowth += pEntry->GetText().getLength();
|
||||
}
|
||||
|
||||
if (aCheckEntry.GetText() != pEntry->GetText())
|
||||
{
|
||||
if (pEntry->GetText().isEmpty())
|
||||
{
|
||||
ResetAttrs(aPam, true, aDelArr);
|
||||
}
|
||||
|
||||
// text is changed, so replace the original
|
||||
getIDocumentContentOperations().ReplaceRange(aPam, pEntry->GetText(), false);
|
||||
aPam.Exchange();
|
||||
}
|
||||
|
||||
aPam.DeleteMark();
|
||||
}
|
||||
else
|
||||
{
|
||||
// No existing ruby text located. Advance to next paragraph.
|
||||
aPam.DeleteMark();
|
||||
aPam.Move(fnMoveForward, GoInNode);
|
||||
}
|
||||
|
||||
// Stop substituting when the cursor advances to the end of the selection.
|
||||
if (*aPam.GetPoint() >= *pEnd)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete any spans past the end of the ruby list
|
||||
while (nListEntry == rList.size() && nCurrBaseTexts < nMaxBaseTexts && *aPam.GetPoint() < *pEnd)
|
||||
{
|
||||
if (pEnd != pStart)
|
||||
{
|
||||
aPam.SetMark();
|
||||
*aPam.GetMark() = *pEnd;
|
||||
}
|
||||
|
||||
SwRubyListEntry aCheckEntry;
|
||||
auto bSelected = SelectNextRubyChars(aPam, aCheckEntry);
|
||||
|
||||
if (bSelected)
|
||||
{
|
||||
++nCurrBaseTexts;
|
||||
|
||||
ResetAttrs(aPam, true, aDelArr);
|
||||
getIDocumentContentOperations().DeleteRange(aPam);
|
||||
aPam.Exchange();
|
||||
|
||||
aPam.DeleteMark();
|
||||
}
|
||||
else
|
||||
{
|
||||
// No existing ruby text located. Advance to next paragraph.
|
||||
aPam.DeleteMark();
|
||||
aPam.Move(fnMoveForward, GoInNode);
|
||||
}
|
||||
}
|
||||
|
||||
// Insert any spans past the end of the base text list
|
||||
sal_Int32 nTotalContentGrowth = 0;
|
||||
while (nListEntry < rList.size())
|
||||
{
|
||||
const SwRubyListEntry* pEntry = rList[nListEntry++].get();
|
||||
|
||||
if (!pEntry->GetText().isEmpty())
|
||||
{
|
||||
aPam.SetMark();
|
||||
getIDocumentContentOperations().InsertString(aPam, pEntry->GetText());
|
||||
aPam.GetMark()->AdjustContent(-pEntry->GetText().getLength());
|
||||
|
||||
if (!pEntry->GetRubyAttr().GetText().isEmpty())
|
||||
{
|
||||
getIDocumentContentOperations().InsertPoolItem(aPam, pEntry->GetRubyAttr());
|
||||
}
|
||||
|
||||
aPam.DeleteMark();
|
||||
|
||||
nTotalContentGrowth += pEntry->GetText().getLength();
|
||||
}
|
||||
}
|
||||
pStartCursor = pStartCursor->GetNext();
|
||||
++nCurrSequence;
|
||||
} while (pStartCursor != pStartCursor2);
|
||||
|
||||
// Expand selection to account for insertion
|
||||
rPam.Normalize();
|
||||
|
||||
@@ -509,8 +509,9 @@ Sequence< Sequence< PropertyValue > > SwXTextView::getRubyList( sal_Bool /*bAuto
|
||||
|
||||
const OUString& rEntryText = pEntry->GetText();
|
||||
const SwFormatRuby& rAttr = pEntry->GetRubyAttr();
|
||||
sal_Int32 nSequence = pEntry->GetSequence();
|
||||
|
||||
pRet[n].realloc(6);
|
||||
pRet[n].realloc(7);
|
||||
PropertyValue* pValues = pRet[n].getArray();
|
||||
pValues[0].Name = UNO_NAME_RUBY_BASE_TEXT;
|
||||
pValues[0].Value <<= rEntryText;
|
||||
@@ -525,6 +526,8 @@ Sequence< Sequence< PropertyValue > > SwXTextView::getRubyList( sal_Bool /*bAuto
|
||||
pValues[4].Value <<= !rAttr.GetPosition();
|
||||
pValues[5].Name = UNO_NAME_RUBY_POSITION;
|
||||
pValues[5].Value <<= rAttr.GetPosition();
|
||||
pValues[6].Name = UNO_NAME_RUBY_SEQUENCE_NUMBER;
|
||||
pValues[6].Value <<= nSequence;
|
||||
}
|
||||
return aRet;
|
||||
}
|
||||
@@ -594,6 +597,14 @@ void SAL_CALL SwXTextView::setRubyList(
|
||||
if(rProperty.Value >>= nTmp)
|
||||
pEntry->GetRubyAttr().SetPosition( nTmp );
|
||||
}
|
||||
else if (rProperty.Name == UNO_NAME_RUBY_SEQUENCE_NUMBER)
|
||||
{
|
||||
sal_Int32 nTmp = 0;
|
||||
if (rProperty.Value >>= nTmp)
|
||||
{
|
||||
pEntry->SetSequence(nTmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
aList.push_back(std::move(pEntry));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user