tdf#162120 Implement style:writing-mode-automatic

Implements the ODF 1.2 paragraph attribute style:writing-mode-automatic,
and supporting runtime features. When set, this attribute allows
programs to automatically recompute the paragraph writing mode when the
contents of the paragraph have been edited.

The ODF standard does not suggest any particular algorithm for
automatically determining paragraph direction. This implementation uses
the rules from Unicode UAX #9 3.3.1.

Currently, LO will only automatically change the writing direction when
new text is typed or deleted. Other known interesting cases are already
tracked as separate enhancement requests.

Change-Id: I49eecea36952588dc98f2a98ebce712cd2846c0c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193547
Reviewed-by: Jonathan Clark <jonathan@libreoffice.org>
Tested-by: Jenkins
This commit is contained in:
Jonathan Clark
2025-11-13 04:45:50 +01:00
parent 177b3d2a88
commit 69e902d085
45 changed files with 804 additions and 35 deletions
+1
View File
@@ -151,6 +151,7 @@ class SvxParaAlignTabPage : public SfxTabPage
std::unique_ptr<weld::Label> m_xVertAlignSdr;
std::unique_ptr<svx::FrameDirectionListBox> m_xTextDirectionLB;
std::unique_ptr<weld::CheckButton> m_xAutoTextDirectionCB;
/// word spacing
std::unique_ptr<weld::Label> m_xLabelWordSpacing;
+22 -1
View File
@@ -32,6 +32,7 @@
#include <svx/strings.hrc>
#include <svx/dialmgr.hxx>
#include <paragrph.hxx>
#include <editeng/autodiritem.hxx>
#include <editeng/frmdiritem.hxx>
#include <editeng/lspcitem.hxx>
#include <editeng/adjustitem.hxx>
@@ -77,7 +78,8 @@ const WhichRangesContainer SvxParaAlignTabPage::pSdrAlignRanges(
svl::Items<
SDRATTR_TEXT_VERTADJUST, SDRATTR_TEXT_VERTADJUST, // 1076
SID_ATTR_PARA_ADJUST, SID_ATTR_PARA_ADJUST , // 10027
SID_ATTR_FRAMEDIRECTION, SID_ATTR_FRAMEDIRECTION // 10944
SID_ATTR_FRAMEDIRECTION, SID_ATTR_FRAMEDIRECTION, // 10944
SID_ATTR_PARA_AUTOFRAMEDIRECTION, SID_ATTR_PARA_AUTOFRAMEDIRECTION
>);
const WhichRangesContainer SvxExtParagraphTabPage::pExtRanges(svl::Items<
@@ -1282,6 +1284,7 @@ SvxParaAlignTabPage::SvxParaAlignTabPage(weld::Container* pPage, weld::DialogCon
, m_xVertAlign(m_xBuilder->weld_label(u"labelFL_VERTALIGN"_ustr))
, m_xVertAlignSdr(m_xBuilder->weld_label(u"labelST_VERTALIGN_SDR"_ustr))
, m_xTextDirectionLB(new svx::FrameDirectionListBox(m_xBuilder->weld_combo_box(u"comboLB_TEXTDIRECTION"_ustr)))
, m_xAutoTextDirectionCB(m_xBuilder->weld_check_button(u"checkCB_AUTOTEXTDIRECTION"_ustr))
, m_xLabelWordSpacing(m_xBuilder->weld_label(u"labelWordSpacing"_ustr))
, m_xLabelMinimum(m_xBuilder->weld_label(u"labelMinimum"_ustr))
, m_xLabelDesired(m_xBuilder->weld_label(u"labelDesired"_ustr))
@@ -1458,6 +1461,13 @@ bool SvxParaAlignTabPage::FillItemSet( SfxItemSet* rOutSet )
}
}
if (m_xAutoTextDirectionCB->get_state_changed_from_saved())
{
rOutSet->Put(SvxAutoFrameDirectionItem(m_xAutoTextDirectionCB->get_active(),
GetWhich(SID_ATTR_PARA_AUTOFRAMEDIRECTION)));
bModified = true;
}
return bModified;
}
@@ -1618,6 +1628,16 @@ void SvxParaAlignTabPage::Reset( const SfxItemSet* rSet )
m_xTextDirectionLB->save_value();
}
_nWhich = GetWhich(SID_ATTR_PARA_AUTOFRAMEDIRECTION);
eItemState = rSet->GetItemState(_nWhich);
if (eItemState >= SfxItemState::DEFAULT)
{
const SvxAutoFrameDirectionItem& rSnap
= static_cast<const SvxAutoFrameDirectionItem&>(rSet->Get(_nWhich));
m_xAutoTextDirectionCB->set_active(rSnap.GetValue());
}
m_xAutoTextDirectionCB->save_state();
m_xSnapToGridCB->save_state();
m_xVertAlignLB->save_value();
m_xLeft->save_state();
@@ -1642,6 +1662,7 @@ void SvxParaAlignTabPage::Reset( const SfxItemSet* rSet )
void SvxParaAlignTabPage::ChangesApplied()
{
m_xTextDirectionLB->save_value();
m_xAutoTextDirectionCB->save_state();
m_xSnapToGridCB->save_state();
m_xVertAlignLB->save_value();
m_xLeft->save_state();
+43 -17
View File
@@ -418,36 +418,62 @@
<property name="label-xalign">0</property>
<property name="shadow-type">none</property>
<child>
<object class="GtkBox" id="box3">
<!-- n-columns=1 n-rows=2 -->
<object class="GtkGrid" id="grid3">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">12</property>
<property name="margin-top">6</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label2">
<object class="GtkBox" id="box3">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes" context="paragalignpage|label2">_Text direction:</property>
<property name="use-underline">True</property>
<property name="mnemonic-widget">comboLB_TEXTDIRECTION</property>
<property name="xalign">0</property>
<property name="margin-start">12</property>
<property name="margin-top">6</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes" context="paragalignpage|label2">_Text direction:</property>
<property name="use-underline">True</property>
<property name="mnemonic-widget">comboLB_TEXTDIRECTION</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="comboLB_TEXTDIRECTION">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="comboLB_TEXTDIRECTION">
<object class="GtkCheckButton" id="checkCB_AUTOTEXTDIRECTION">
<property name="label" translatable="yes" context="paragalignpage|checkCB_AUTOTEXTDIRECTION">Automatically set direction</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="margin-start">22</property>
<property name="use-underline">True</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
</object>
+16
View File
@@ -19,6 +19,7 @@
#include <editdoc.hxx>
#include <editeng/autodiritem.hxx>
#include <editeng/tstpitem.hxx>
#include <editeng/colritem.hxx>
#include <editeng/fontitem.hxx>
@@ -1031,6 +1032,14 @@ void YrsInsertAttribImplImpl(YrsWrite const& yw, SfxPoolItem const& rItm,
attrName = "EE_PARA_WRITINGDIR";
break;
}
case EE_PARA_AUTOWRITINGDIR:
{
SvxAutoFrameDirectionItem const& rItem{ static_cast<SvxAutoFrameDirectionItem const&>(
rItm) };
attr = yinput_bool(rItem.GetValue() ? Y_TRUE : Y_FALSE);
attrName = "EE_PARA_AUTOWRITINGDIR";
break;
}
case EE_PARA_HANGINGPUNCTUATION:
{
SvxHangingPunctuationItem const& rItem{static_cast<SvxHangingPunctuationItem const&>(rItm)};
@@ -2118,6 +2127,13 @@ void YrsImplInsertAttr(SfxItemSet & rSet, ::std::vector<sal_uInt16> *const pRemo
rSet.Put(item);
break;
}
case EE_PARA_AUTOWRITINGDIR:
{
yvalidate(rValue.tag == Y_JSON_BOOL);
SvxAutoFrameDirectionitem const item{ rValue.value.flag == Y_TRUE, nWhich };
rSet.Put(item);
break;
}
case EE_PARA_HANGINGPUNCTUATION:
{
yvalidate(rValue.tag == Y_JSON_BOOL);
+2
View File
@@ -40,6 +40,7 @@
#include <vcl/svapp.hxx>
#include <vcl/virdev.hxx>
#include <editeng/autodiritem.hxx>
#include <editeng/autokernitem.hxx>
#include <editeng/contouritem.hxx>
#include <editeng/colritem.hxx>
@@ -118,6 +119,7 @@ ItemInfoPackage& getItemInfoPackageEditEngine()
{ EE_PARA_TABS, new SvxTabStopItem( 0, 0, SvxTabAdjust::Left, EE_PARA_TABS ), SID_ATTR_TABSTOP, SFX_ITEMINFOFLAG_NONE },
{ EE_PARA_JUST_METHOD, new SvxJustifyMethodItem( SvxCellJustifyMethod::Auto, EE_PARA_JUST_METHOD ), SID_ATTR_ALIGN_HOR_JUSTIFY_METHOD, SFX_ITEMINFOFLAG_NONE },
{ EE_PARA_VER_JUST, new SvxVerJustifyItem( SvxCellVerJustify::Standard, EE_PARA_VER_JUST ), SID_ATTR_ALIGN_VER_JUSTIFY, SFX_ITEMINFOFLAG_NONE },
{ EE_PARA_AUTOWRITINGDIR, new SvxAutoFrameDirectionItem( false, EE_PARA_AUTOWRITINGDIR ), SID_ATTR_PARA_AUTOFRAMEDIRECTION, SFX_ITEMINFOFLAG_NONE },
{ EE_CHAR_COLOR, new SvxColorItem( COL_AUTO, EE_CHAR_COLOR ), SID_ATTR_CHAR_COLOR, SFX_ITEMINFOFLAG_SUPPORT_SURROGATE },
// EE_CHAR_FONTINFO, EE_CHAR_FONTINFO_CJK and EE_CHAR_FONTINFO_CTL need on-demand initialization
+1
View File
@@ -1044,6 +1044,7 @@ public:
EditPaM InsertLineBreak(const EditSelection& aEditSelection);
EditPaM InsertTab(const EditSelection& rEditSelection);
EditPaM InsertField(const EditSelection& rCurSel, const SvxFieldItem& rFld);
void UpdateAutoParaDirection(const EditSelection& rCurSel);
bool UpdateFields();
ErrCode Read( SvStream& rInput, const OUString& rBaseURL, EETextFormat eFormat, SvKeyValueIterator* pHTTPHeaderAttrs = nullptr );
+59
View File
@@ -39,6 +39,7 @@
#include <editeng/ulspitem.hxx>
#include <editeng/adjustitem.hxx>
#include <editeng/frmdiritem.hxx>
#include <editeng/autodiritem.hxx>
#include <editeng/justifyitem.hxx>
#include <editeng/scripthintitem.hxx>
@@ -63,6 +64,7 @@
#include <svl/voiditem.hxx>
#include <i18nutil/unicode.hxx>
#include <i18nutil/scriptchangescanner.hxx>
#include <i18nutil/guessparadirection.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <comphelper/flagguard.hxx>
#include <comphelper/lok.hxx>
@@ -466,6 +468,9 @@ bool ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView )
mpIMEInfos->nLen = pData->GetText().getLength();
}
// tdf#162120: Automatically adjust paragraph directions after edit
UpdateAutoParaDirection(EditSelection{ mpIMEInfos->aPos });
ParaPortion* pPortion = FindParaPortion( mpIMEInfos->aPos.GetNode() );
pPortion->MarkSelectionInvalid( mpIMEInfos->aPos.GetIndex() );
FormatAndLayout( pView );
@@ -2532,6 +2537,10 @@ EditPaM ImpEditEngine::ImpDeleteSelection(const EditSelection& rCurSel)
UpdateSelectionsDelete(deleted);
UpdateSelections();
// tdf#162120: Automatically adjust paragraph directions after edit
UpdateAutoParaDirection(rCurSel);
TextModified();
return aStartPaM;
}
@@ -2763,6 +2772,9 @@ EditPaM ImpEditEngine::InsertTextUserInput( const EditSelection& rCurSel,
aPaM.SetIndex( aPaM.GetIndex()+1 ); // does not do EditDoc-Method anymore
}
// tdf#162120: Automatically adjust paragraph direction after edit
UpdateAutoParaDirection(EditSelection{ aPaM });
TextModified();
if ( bUndoAction )
@@ -2771,6 +2783,53 @@ EditPaM ImpEditEngine::InsertTextUserInput( const EditSelection& rCurSel,
return aPaM;
}
void ImpEditEngine::UpdateAutoParaDirection(const EditSelection& rCurSel)
{
EditPaM aPaM(rCurSel.Min());
auto nPara = maEditDoc.GetPos(aPaM.GetNode());
if (nPara >= GetParaPortions().Count() || !HasParaAttrib(nPara, EE_PARA_AUTOWRITINGDIR))
{
return;
}
const SvxAutoFrameDirectionItem& rItem = GetParaAttrib(nPara, EE_PARA_AUTOWRITINGDIR);
if (!rItem.GetValue())
{
return;
}
bool bIsAlreadyRtl = IsRightToLeft(nPara);
bool bShouldBeRtl = bIsAlreadyRtl;
switch (i18nutil::GuessParagraphDirection(aPaM.GetNode()->GetString()))
{
case i18nutil::ParagraphDirection::Ambiguous:
bShouldBeRtl = bIsAlreadyRtl;
break;
case i18nutil::ParagraphDirection::LeftToRight:
bShouldBeRtl = false;
break;
case i18nutil::ParagraphDirection::RightToLeft:
bShouldBeRtl = true;
break;
}
if (bShouldBeRtl == bIsAlreadyRtl)
{
return;
}
SvxFrameDirection eNeeded
= bShouldBeRtl ? SvxFrameDirection::Horizontal_RL_TB : SvxFrameDirection::Horizontal_LR_TB;
SfxItemSet aSet{ GetParaAttribs(nPara) };
aSet.Put(SvxFrameDirectionItem{ eNeeded, EE_PARA_WRITINGDIR });
SetParaAttribs(nPara, aSet);
}
EditPaM ImpEditEngine::ImpInsertText(const EditSelection& aCurSel, const OUString& rStr)
{
UndoActionStart( EDITUNDO_INSERT );
+20
View File
@@ -43,6 +43,7 @@
#include <editeng/forbiddenruleitem.hxx>
#include <editeng/paravertalignitem.hxx>
#include <editeng/pgrditem.hxx>
#include <editeng/autodiritem.hxx>
#include <rtl/ustring.hxx>
#include <sal/log.hxx>
#include <editeng/memberids.h>
@@ -1514,5 +1515,24 @@ bool SvxParaGridItem::GetPresentation(
return true;
}
SvxAutoFrameDirectionItem::SvxAutoFrameDirectionItem(bool bValue, const sal_uInt16 nId)
: SfxBoolItem(nId, bValue)
{
}
SvxAutoFrameDirectionItem* SvxAutoFrameDirectionItem::Clone(SfxItemPool*) const
{
return new SvxAutoFrameDirectionItem(*this);
}
bool SvxAutoFrameDirectionItem::GetPresentation(SfxItemPresentation /*ePres*/,
MapUnit /*eCoreMetric*/, MapUnit /*ePresMetric*/,
OUString& rText, const IntlWrapper& /*rIntl*/) const
{
rText = GetValue() ? EditResId(RID_SVXITEMS_AUTOFRAMEDIRECTION_ON)
: EditResId(RID_SVXITEMS_AUTOFRAMEDIRECTION_OFF);
return true;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+1
View File
@@ -14,6 +14,7 @@ $(eval $(call gb_CppunitTest_CppunitTest,i18nutil))
$(eval $(call gb_CppunitTest_use_sdk_api,i18nutil))
$(eval $(call gb_CppunitTest_add_exception_objects,i18nutil,\
i18nutil/qa/cppunit/test_guessparadirection \
i18nutil/qa/cppunit/test_kashida \
i18nutil/qa/cppunit/test_scriptchangescanner \
))
+1
View File
@@ -44,6 +44,7 @@ $(eval $(call gb_Library_use_libraries,i18nutil,\
$(eval $(call gb_Library_add_exception_objects,i18nutil,\
i18nutil/source/utility/casefolding \
i18nutil/source/utility/guessparadirection \
i18nutil/source/utility/kashida \
i18nutil/source/utility/oneToOneMapping \
i18nutil/source/utility/paper \
@@ -0,0 +1,75 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <sal/types.h>
#include <cppunit/TestAssert.h>
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/plugin/TestPlugIn.h>
#include <i18nutil/guessparadirection.hxx>
using namespace i18nutil;
namespace
{
class GuessParagraphDirectionTest : public CppUnit::TestFixture
{
public:
void testEmpty();
void testFirstStrongLTR();
void testFirstStrongRTL();
void testFirstStrongAR();
void testIsolate();
CPPUNIT_TEST_SUITE(GuessParagraphDirectionTest);
CPPUNIT_TEST(testEmpty);
CPPUNIT_TEST(testFirstStrongLTR);
CPPUNIT_TEST(testFirstStrongRTL);
CPPUNIT_TEST(testFirstStrongAR);
CPPUNIT_TEST(testIsolate);
CPPUNIT_TEST_SUITE_END();
};
void GuessParagraphDirectionTest::testEmpty()
{
auto aText = u""_ustr;
CPPUNIT_ASSERT_EQUAL(ParagraphDirection::Ambiguous, GuessParagraphDirection(aText));
}
void GuessParagraphDirectionTest::testFirstStrongLTR()
{
auto aText = u"..aاא.."_ustr;
CPPUNIT_ASSERT_EQUAL(ParagraphDirection::LeftToRight, GuessParagraphDirection(aText));
}
void GuessParagraphDirectionTest::testFirstStrongRTL()
{
auto aText = u"..אaا.."_ustr;
CPPUNIT_ASSERT_EQUAL(ParagraphDirection::RightToLeft, GuessParagraphDirection(aText));
}
void GuessParagraphDirectionTest::testFirstStrongAR()
{
auto aText = u"..اaא.."_ustr;
CPPUNIT_ASSERT_EQUAL(ParagraphDirection::RightToLeft, GuessParagraphDirection(aText));
}
void GuessParagraphDirectionTest::testIsolate()
{
// U+2066: LRI
// U+2067: RLI
// U+2069: PDI
auto aText = u"...\u2069.\u2067aaa\u2066אאא\u2069.\u2069.."_ustr;
CPPUNIT_ASSERT_EQUAL(ParagraphDirection::Ambiguous, GuessParagraphDirection(aText));
}
CPPUNIT_TEST_SUITE_REGISTRATION(GuessParagraphDirectionTest);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
@@ -0,0 +1,65 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <i18nutil/guessparadirection.hxx>
#include <i18nutil/unicode.hxx>
#include <unicode/uchar.h>
#include <unicode/ubidi.h>
i18nutil::ParagraphDirection i18nutil::GuessParagraphDirection(const OUString& rText)
{
// tdf#162120: This algorithm implements Unicode UAX #9 3.3.1
// for automatically determining the paragraph level without
// override from a higher-level protocol.
// The algorithm has been extended to explicitly communicate
// an ambiguous case, rather than defaulting to LTR.
sal_Int32 nBase = 0;
sal_Int32 nIsolateLevel = 0;
while (nBase < rText.getLength())
{
auto nChar = rText.iterateCodePoints(&nBase);
auto nCharDir = u_charDirection(nChar);
switch (nCharDir)
{
case U_POP_DIRECTIONAL_ISOLATE:
nIsolateLevel = std::max(sal_Int32{ 0 }, nIsolateLevel - 1);
break;
case U_LEFT_TO_RIGHT_ISOLATE:
case U_RIGHT_TO_LEFT_ISOLATE:
++nIsolateLevel;
break;
case U_LEFT_TO_RIGHT:
if (nIsolateLevel == 0)
{
return ParagraphDirection::LeftToRight;
}
break;
case U_RIGHT_TO_LEFT:
case U_RIGHT_TO_LEFT_ARABIC:
if (nIsolateLevel == 0)
{
return ParagraphDirection::RightToLeft;
}
break;
default:
break;
}
}
return ParagraphDirection::Ambiguous;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
+37
View File
@@ -0,0 +1,37 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#pragma once
#include <svl/eitem.hxx>
#include <editeng/editengdllapi.h>
class EDITENG_DLLPUBLIC SvxAutoFrameDirectionItem final : public SfxBoolItem
{
public:
DECLARE_ITEM_TYPE_FUNCTION(SvxAutoFrameDirectionItem)
SvxAutoFrameDirectionItem(const bool bValue, const sal_uInt16 nId);
virtual SvxAutoFrameDirectionItem* Clone(SfxItemPool* pPool = nullptr) const override;
virtual bool GetPresentation(SfxItemPresentation ePres, MapUnit eCoreMetric,
MapUnit ePresMetric, OUString& rText,
const IntlWrapper&) const override;
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+1
View File
@@ -160,6 +160,7 @@ class SvxScriptHintItem;
#define SID_PARA_VERTALIGN TypedWhichId<SvxParaVertAlignItem>( SID_SVX_START + 925 )
#define SID_ATTR_FRAMEDIRECTION TypedWhichId<SvxFrameDirectionItem>( SID_SVX_START + 944 )
#define SID_ATTR_PARA_SNAPTOGRID TypedWhichId<SvxParaGridItem>( SID_SVX_START + 945 )
#define SID_ATTR_PARA_AUTOFRAMEDIRECTION TypedWhichId<SvxAutoFrameDirectionItem>( SID_SVX_START + 946 )
#define SID_ATTR_PARA_LRSPACE_VERTICAL ( SID_SVX_START + 947 )
#define SID_ATTR_PARA_LEFT_TO_RIGHT ( SID_SVX_START + 950 )
#define SID_ATTR_PARA_RIGHT_TO_LEFT ( SID_SVX_START + 951 )
+2
View File
@@ -301,6 +301,8 @@
#define RID_SVXITEMS_FRMDIR_VERT_TOP_RIGHT90 NC_("RID_SVXITEMS_FRMDIR_Vert_TOP_RIGHT90", "Text direction right-to-left (vertical, all characters rotated)")
#define RID_SVXITEMS_PARASNAPTOGRID_ON NC_("RID_SVXITEMS_PARASNAPTOGRID_ON", "Paragraph snaps to text grid (if active)")
#define RID_SVXITEMS_PARASNAPTOGRID_OFF NC_("RID_SVXITEMS_PARASNAPTOGRID_OFF", "Paragraph does not snap to text grid")
#define RID_SVXITEMS_AUTOFRAMEDIRECTION_ON NC_("RID_SVXITEMS_AUTOFRAMEDIRECTION_ON", "Text direction is automatically updated")
#define RID_SVXITEMS_AUTOFRAMEDIRECTION_OFF NC_("RID_SVXITEMS_AUTOFRAMEDIRECTION_OFF", "Text direction is not automatically updated")
#define RID_SVXITEMS_CHARHIDDEN_FALSE NC_("RID_SVXITEMS_CHARHIDDEN_FALSE", "Not hidden")
#define RID_SVXITEMS_CHARHIDDEN_TRUE NC_("RID_SVXITEMS_CHARHIDDEN_TRUE", "Hidden")
+3 -1
View File
@@ -27,6 +27,7 @@ class SfxBoolItem;
class SfxGrabBagItem;
class SfxInt16Item;
class SvxAdjustItem;
class SvxAutoFrameDirectionItem;
class SvxAutoKernItem;
class SvxCaseMapItem;
class SvxCharReliefItem;
@@ -93,7 +94,8 @@ inline constexpr TypedWhichId<SvxAdjustItem> EE_PARA_JUST
inline constexpr TypedWhichId<SvxTabStopItem> EE_PARA_TABS (EE_PARA_START+17);
inline constexpr TypedWhichId<SvxJustifyMethodItem> EE_PARA_JUST_METHOD (EE_PARA_START+18);
inline constexpr TypedWhichId<SvxVerJustifyItem> EE_PARA_VER_JUST (EE_PARA_START+19);
inline constexpr sal_uInt16 EE_PARA_END (EE_PARA_START + 19);
inline constexpr TypedWhichId<SvxAutoFrameDirectionItem> EE_PARA_AUTOWRITINGDIR (EE_PARA_START+20);
inline constexpr sal_uInt16 EE_PARA_END (EE_PARA_START + 20);
// Character attributes:
inline constexpr sal_uInt16 EE_CHAR_START (EE_PARA_END + 1);
+2 -1
View File
@@ -170,7 +170,8 @@ struct SfxItemPropertyMapEntry;
{u"ParaLetterSpacingMaximum"_ustr, EE_PARA_JUST, ::cppu::UnoType<sal_Int16>::get(), 0, MID_LETTER_SPACING_MAX }, \
{u"ParaScaleWidthMinimum"_ustr, EE_PARA_JUST, ::cppu::UnoType<sal_Int16>::get(), 0, MID_SCALE_WIDTH_MIN }, \
{u"ParaScaleWidthMaximum"_ustr, EE_PARA_JUST, ::cppu::UnoType<sal_Int16>::get(), 0, MID_SCALE_WIDTH_MAX }, \
{u"WritingMode"_ustr, EE_PARA_WRITINGDIR, ::cppu::UnoType<sal_Int16>::get(), 0, 0 }
{u"WritingMode"_ustr, EE_PARA_WRITINGDIR, ::cppu::UnoType<sal_Int16>::get(), 0, 0 }, \
{u"WritingModeAutomatic"_ustr, EE_PARA_AUTOWRITINGDIR, ::cppu::UnoType<bool>::get(), 0, 0 }
class SvxFieldData;
+30
View File
@@ -0,0 +1,30 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <i18nutil/i18nutildllapi.h>
#include <com/sun/star/text/ScriptHintType.hpp>
#include <rtl/ustring.hxx>
#include <optional>
#include <memory>
#include <vector>
namespace i18nutil
{
enum class ParagraphDirection
{
Ambiguous,
LeftToRight,
RightToLeft
};
I18NUTIL_DLLPUBLIC ParagraphDirection GuessParagraphDirection(const OUString& rText);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
+1
View File
@@ -309,6 +309,7 @@ enum class SfxItemType : sal_uInt16
Svx3DTextureProjectionXItemType,
Svx3DTextureProjectionYItemType,
SvxAdjustItemType,
SvxAutoFrameDirectionItemType,
SvxAutoKernItemType,
SvxB3DVectorItemType,
SvxBitmapListItemType,
+1
View File
@@ -2214,6 +2214,7 @@ namespace xmloff::token {
XML_WRAP_CONTOUR_MODE,
XML_WRAP_OPTION,
XML_WRITING_MODE,
XML_WRITING_MODE_AUTOMATIC,
XML_WWW,
XML_X,
XML_X1,
+2
View File
@@ -161,6 +161,8 @@ class SAL_DLLPUBLIC_RTTI SwEditShell : public SwCursorShell
using SwViewShell::UpdateFields;
using sw::BroadcastingModify::GetInfo;
void UpdateSelectionAutoParaDirection();
public:
/// Edit (all selected ranges).
void Insert( sal_Unicode, bool bOnlyCurrCursor = false );
+8 -3
View File
@@ -35,6 +35,7 @@ class SwFormatContentControl;
class SvXMLAttrContainerItem;
class SwMsgPoolItem;
class SfxBoolItem;
class SvxAutoFrameDirectionItem;
class SvxColorItem;
class SvxLeftMarginItem;
class SvxTextLeftMarginItem;
@@ -314,9 +315,13 @@ inline constexpr TypedWhichId<SvxParaGridItem> RES_PARATR_SNAPTOGRID(RES_PARATR_
inline constexpr TypedWhichId<SwParaConnectBorderItem> RES_PARATR_CONNECT_BORDER(RES_PARATR_BEGIN
+ 15);
inline constexpr TypedWhichId<SfxUInt16Item> RES_PARATR_OUTLINELEVEL(RES_PARATR_BEGIN + 16);
inline constexpr TypedWhichId<SvxRsidItem> RES_PARATR_RSID(RES_PARATR_BEGIN + 17);
inline constexpr TypedWhichId<SfxGrabBagItem> RES_PARATR_GRABBAG(RES_PARATR_BEGIN + 18);
inline constexpr sal_uInt16 RES_PARATR_END(RES_PARATR_BEGIN + 19);
inline constexpr TypedWhichId<SvxAutoFrameDirectionItem> RES_PARATR_AUTOFRAMEDIR(RES_PARATR_BEGIN
+ 17);
// DocumentRedlineManager assumes RSID and GRABBAG are the last paragraph attributes.
// Insert new paragraph attributes before them.
inline constexpr TypedWhichId<SvxRsidItem> RES_PARATR_RSID(RES_PARATR_BEGIN + 18);
inline constexpr TypedWhichId<SfxGrabBagItem> RES_PARATR_GRABBAG(RES_PARATR_BEGIN + 19);
inline constexpr sal_uInt16 RES_PARATR_END(RES_PARATR_BEGIN + 20);
// list attributes for paragraphs.
// intentionally these list attributes are not contained in paragraph styles
+1
View File
@@ -275,6 +275,7 @@
#define RID_UNVISITED_CHAR_STYLE_NAME NC_("RID_ATTRIBUTE_NAMES_MAP", "Unvisited Char Style Name")
#define RID_VISITED_CHAR_STYLE_NAME NC_("RID_ATTRIBUTE_NAMES_MAP", "Visited Char Style Name")
#define RID_WRITING_MODE NC_("RID_ATTRIBUTE_NAMES_MAP", "Writing Mode")
#define RID_WRITING_MODE_AUTOMATIC NC_("RID_ATTRIBUTE_NAMES_MAP", "Para Auto Writing Mode")
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+3
View File
@@ -26,6 +26,7 @@
#include "swatrset.hxx"
#include "format.hxx"
#include "charfmt.hxx"
#include <editeng/autodiritem.hxx>
#include <editeng/adjustitem.hxx>
#include <editeng/lspcitem.hxx>
#include <editeng/spltitem.hxx>
@@ -232,6 +233,8 @@ inline const SvxParaGridItem &SwAttrSet::GetParaGrid(bool bInP) const
{ return Get( RES_PARATR_SNAPTOGRID, bInP ); }
inline const SwParaConnectBorderItem &SwAttrSet::GetParaConnectBorder(bool bInP) const
{ return Get( RES_PARATR_CONNECT_BORDER, bInP ); }
inline const SvxAutoFrameDirectionItem &SwAttrSet::GetAutoFrameDirection(bool bInP) const
{ return Get( RES_PARATR_AUTOFRAMEDIR, bInP ); }
// Implementation of paragraph-attributes methods of SwFormat
inline const SvxLineSpacingItem &SwFormat::GetLineSpacing(bool bInP) const
+2
View File
@@ -130,6 +130,7 @@ class SvxHangingPunctuationItem;
class SvxForbiddenRuleItem;
class SvxParaVertAlignItem;
class SvxParaGridItem;
class SvxAutoFrameDirectionItem;
class SwParaConnectBorderItem;
// TableBox attributes
@@ -322,6 +323,7 @@ public:
inline const SvxParaVertAlignItem &GetParaVertAlign(bool = true) const;
inline const SvxParaGridItem &GetParaGrid(bool = true) const;
inline const SwParaConnectBorderItem &GetParaConnectBorder(bool = true ) const;
inline const SvxAutoFrameDirectionItem &GetAutoFrameDirection(bool = true) const;
// Tablebox attributes - implementation in cellatr.hxx
inline const SwTableBoxNumFormat &GetTableBoxNumFormat( bool = true ) const;
+1
View File
@@ -736,6 +736,7 @@ inline constexpr OUString UNO_NAME_CELL_NAME = u"CellName"_ustr;
inline constexpr OUString UNO_NAME_PARA_USER_DEFINED_ATTRIBUTES = u"ParaUserDefinedAttributes"_ustr;
inline constexpr OUString UNO_NAME_MERGE_LAST_PARA = u"MergeLastPara"_ustr;
inline constexpr OUString UNO_NAME_WRITING_MODE = u"WritingMode"_ustr;
inline constexpr OUString UNO_NAME_PARA_WRITING_MODE_AUTOMATIC = u"WritingModeAutomatic"_ustr;
inline constexpr OUString UNO_NAME_GRID_COLOR = u"GridColor"_ustr;
inline constexpr OUString UNO_NAME_GRID_LINES = u"GridLines"_ustr;
inline constexpr OUString UNO_NAME_GRID_BASE_HEIGHT = u"GridBaseHeight"_ustr;
@@ -0,0 +1,147 @@
<?xml version='1.0' encoding='UTF-8'?>
<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.4" office:mimetype="application/vnd.oasis.opendocument.text">
<office:meta><meta:creation-date>2025-10-30T08:33:30.003457423</meta:creation-date><dc:date>2025-10-31T10:32:54.029847023</dc:date><meta:editing-duration>PT2M18S</meta:editing-duration><meta:editing-cycles>2</meta:editing-cycles><meta:generator>LibreOfficeDev/26.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/08b6c9f129d48adf1e4850742651c78f750af488</meta:generator><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="1" meta:paragraph-count="4" meta:word-count="21" meta:character-count="114" meta:non-whitespace-character-count="97"/></office:meta>
<office:font-face-decls>
<style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
<style:font-face style:name="Noto Sans1" svg:font-family="'Noto Sans'" style:font-family-generic="system" style:font-pitch="variable"/>
<style:font-face style:name="Noto Serif CJK SC" svg:font-family="'Noto Serif CJK SC'" style:font-family-generic="system" style:font-pitch="variable"/>
</office:font-face-decls>
<office:styles>
<style:default-style style:family="graphic">
<style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:writing-mode="lr-tb" style:flow-with-text="false"/>
<style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" loext:tab-stop-distance="0cm" style:font-independent-line-spacing="false">
<style:tab-stops/>
</style:paragraph-properties>
<style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="en" fo:country="CA" style:letter-kerning="true" style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Noto Sans1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/>
</style:default-style>
<style:default-style style:family="paragraph">
<style:paragraph-properties fo:orphans="2" fo:widows="2" fo:hyphenation-ladder-count="no-limit" fo:hyphenation-keep="auto" loext:hyphenation-keep-type="column" loext:hyphenation-keep-line="false" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="page"/>
<style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="en" fo:country="CA" style:letter-kerning="true" style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Noto Sans1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" loext:hyphenation-word-char-count="5" loext:hyphenation-zone="no-limit"/>
</style:default-style>
<style:default-style style:family="table">
<style:table-properties table:border-model="collapsing"/>
</style:default-style>
<style:default-style style:family="table-row">
<style:table-row-properties fo:keep-together="auto"/>
</style:default-style>
<style:style style:name="Standard" style:family="paragraph" style:class="text"/>
<style:style style:name="AutoStyle" style:family="paragraph" style:parent-style-name="Standard">
<style:paragraph-properties style:writing-mode-automatic="true"/>
</style:style>
<text:outline-style style:name="Outline">
<text:outline-level-style text:level="1" loext:num-list-format="%1%" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="2" loext:num-list-format="%2%" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="3" loext:num-list-format="%3%" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="4" loext:num-list-format="%4%" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="5" loext:num-list-format="%5%" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="6" loext:num-list-format="%6%" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="7" loext:num-list-format="%7%" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="8" loext:num-list-format="%8%" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="9" loext:num-list-format="%9%" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="10" loext:num-list-format="%10%" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
</text:outline-style>
<text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/>
<text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/>
<text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/>
</office:styles>
<office:automatic-styles>
<style:style style:name="P1" style:family="paragraph" style:parent-style-name="Standard">
<style:text-properties/>
</style:style>
<style:style style:name="P2" style:family="paragraph" style:parent-style-name="Standard">
<style:paragraph-properties style:writing-mode-automatic="true"/>
<style:text-properties/>
</style:style>
<style:style style:name="P3" style:family="paragraph">
<style:paragraph-properties style:writing-mode-automatic="true"/>
</style:style>
<style:style style:name="P4" style:family="paragraph">
<loext:graphic-properties draw:fill="none" draw:fill-color="#ffffff"/>
</style:style>
<style:style style:name="gr1" style:family="graphic">
<style:graphic-properties draw:stroke="none" svg:stroke-color="#000000" draw:fill="none" draw:fill-color="#ffffff" fo:min-height="11.933cm" loext:decorative="false" style:run-through="foreground" style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="paragraph" style:horizontal-pos="from-left" style:horizontal-rel="paragraph" draw:wrap-influence-on-position="once-concurrent" loext:allow-overlap="true" style:flow-with-text="false"/>
<style:paragraph-properties style:writing-mode="lr-tb"/>
</style:style>
<style:page-layout style:name="pm1">
<style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0cm" loext:margin-gutter="0cm">
<style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
</style:page-layout-properties>
<style:header-style/>
<style:footer-style/>
</style:page-layout>
<style:style style:name="dp1" style:family="drawing-page">
<style:drawing-page-properties draw:background-size="full"/>
</style:style>
</office:automatic-styles>
<office:master-styles>
<style:master-page style:name="Standard" style:page-layout-name="pm1" draw:style-name="dp1"/>
</office:master-styles>
<office:body>
<office:text>
<text:sequence-decls>
<text:sequence-decl text:display-outline-level="0" text:name="Illustration"/>
<text:sequence-decl text:display-outline-level="0" text:name="Table"/>
<text:sequence-decl text:display-outline-level="0" text:name="Text"/>
<text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
<text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
</text:sequence-decls>
<text:p text:style-name="P1">This paragraph is normal</text:p>
<text:p text:style-name="P1"/>
<text:p text:style-name="P2">This paragraph is auto</text:p>
<text:p text:style-name="P1"/>
<text:p text:style-name="P1">This paragraph is also normal</text:p>
<text:p text:style-name="P1"/>
<text:p text:style-name="AutoStyle">This paragraph is auto by a named style</text:p>
<text:p text:style-name="P1"/>
<text:p text:style-name="P1"><draw:frame text:anchor-type="paragraph" draw:z-index="0" draw:name="Text Frame 1" draw:style-name="gr1" draw:text-style-name="P4" svg:width="15.452cm" svg:height="11.933cm" svg:x="0.804cm" svg:y="1.589cm">
<draw:text-box>
<text:p>This paragraph is normal too</text:p>
<text:p/>
<text:p text:style-name="P3">But this one is auto</text:p>
<text:p/>
<text:p>And finally, this one is normal</text:p>
</draw:text-box>
</draw:frame></text:p>
</office:text>
</office:body>
</office:document>
+13
View File
@@ -1696,6 +1696,19 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf118350StartEndPreserved)
"text-align", u"end");
}
CPPUNIT_TEST_FIXTURE(Test, testTdf162120StyleWritingModeAutomaticSerialization)
{
loadAndReload("tdf162120-style-writing-mode-automatic.fodt");
auto pStylesDoc = parseExport(u"styles.xml"_ustr);
assertXPath(pStylesDoc, "//style:paragraph-properties[@style:writing-mode-automatic]", 1);
assertXPath(pStylesDoc, "//style:style[@style:name='AutoStyle']/style:paragraph-properties",
"writing-mode-automatic", u"true");
auto pContentDoc = parseExport(u"content.xml"_ustr);
assertXPath(pContentDoc, "//style:paragraph-properties[@style:writing-mode-automatic]", 2);
}
} // end of anonymous namespace
CPPUNIT_PLUGIN_IMPLEMENT();
@@ -0,0 +1,122 @@
<?xml version='1.0' encoding='UTF-8'?>
<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.4" office:mimetype="application/vnd.oasis.opendocument.text">
<office:meta><meta:creation-date>2025-11-06T11:23:30.187236969</meta:creation-date><dc:date>2025-11-06T11:30:37.198630783</dc:date><meta:editing-duration>PT4M9S</meta:editing-duration><meta:editing-cycles>2</meta:editing-cycles><meta:generator>LibreOfficeDev/26.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/cb898851676f98ce58e79d4ffd1c0081b0003335</meta:generator><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="1" meta:paragraph-count="1" meta:word-count="1" meta:character-count="2" meta:non-whitespace-character-count="2"/></office:meta>
<office:font-face-decls>
<style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
<style:font-face style:name="Noto Sans Arabic" svg:font-family="'Noto Sans Arabic'" style:font-adornments="Regular" style:font-family-generic="swiss" style:font-pitch="variable"/>
<style:font-face style:name="Noto Sans1" svg:font-family="'Noto Sans'" style:font-family-generic="system" style:font-pitch="variable"/>
<style:font-face style:name="Noto Serif CJK SC" svg:font-family="'Noto Serif CJK SC'" style:font-family-generic="system" style:font-pitch="variable"/>
</office:font-face-decls>
<office:styles>
<style:default-style style:family="graphic">
<style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:writing-mode="lr-tb" style:flow-with-text="false"/>
<style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" loext:tab-stop-distance="0cm" style:font-independent-line-spacing="false">
<style:tab-stops/>
</style:paragraph-properties>
<style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="en" fo:country="CA" style:letter-kerning="true" style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Noto Sans1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/>
</style:default-style>
<style:default-style style:family="paragraph">
<style:paragraph-properties fo:orphans="2" fo:widows="2" fo:hyphenation-ladder-count="no-limit" fo:hyphenation-keep="auto" loext:hyphenation-keep-type="column" loext:hyphenation-keep-line="false" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="page"/>
<style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="en" fo:country="CA" style:letter-kerning="true" style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Noto Sans1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" loext:hyphenation-word-char-count="5" loext:hyphenation-zone="no-limit"/>
</style:default-style>
<style:default-style style:family="table">
<style:table-properties table:border-model="collapsing"/>
</style:default-style>
<style:default-style style:family="table-row">
<style:table-row-properties fo:keep-together="auto"/>
</style:default-style>
<style:style style:name="Standard" style:family="paragraph" style:class="text">
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false" style:writing-mode-automatic="true"/>
<style:text-properties style:font-name-complex="Noto Sans Arabic" style:font-family-complex="'Noto Sans Arabic'" style:font-style-name-complex="Regular" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:language-complex="ar" style:country-complex="EG"/>
</style:style>
<text:outline-style style:name="Outline">
<text:outline-level-style text:level="1" loext:num-list-format="%1%" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="2" loext:num-list-format="%2%" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="3" loext:num-list-format="%3%" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="4" loext:num-list-format="%4%" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="5" loext:num-list-format="%5%" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="6" loext:num-list-format="%6%" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="7" loext:num-list-format="%7%" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="8" loext:num-list-format="%8%" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="9" loext:num-list-format="%9%" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="10" loext:num-list-format="%10%" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
</text:outline-style>
<text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/>
<text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/>
<text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/>
</office:styles>
<office:automatic-styles>
<style:style style:name="P1" style:family="paragraph" style:parent-style-name="Standard">
<style:paragraph-properties style:writing-mode="rl-tb"/>
<style:text-properties style:language-complex="ar" style:country-complex="EG"/>
</style:style>
<style:style style:name="T1" style:family="text">
<style:text-properties fo:language="en" fo:country="US"/>
</style:style>
<style:page-layout style:name="pm1">
<style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0cm" loext:margin-gutter="0cm">
<style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
</style:page-layout-properties>
<style:header-style/>
<style:footer-style/>
</style:page-layout>
<style:style style:name="dp1" style:family="drawing-page">
<style:drawing-page-properties draw:background-size="full"/>
</style:style>
</office:automatic-styles>
<office:master-styles>
<style:master-page style:name="Standard" style:page-layout-name="pm1" draw:style-name="dp1"/>
</office:master-styles>
<office:body>
<office:text>
<text:sequence-decls>
<text:sequence-decl text:display-outline-level="0" text:name="Illustration"/>
<text:sequence-decl text:display-outline-level="0" text:name="Table"/>
<text:sequence-decl text:display-outline-level="0" text:name="Text"/>
<text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
<text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
</text:sequence-decls>
<text:p text:style-name="P1">ا<text:span text:style-name="T1">a</text:span></text:p>
</office:text>
</office:body>
</office:document>
+23
View File
@@ -374,6 +374,29 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest11, testTdf108791)
}
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest11, testTdf162120AutoRTL)
{
createSwDoc("tdf162120-auto-rtl.fodt");
SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
CPPUNIT_ASSERT(pWrtShell);
// The initial direction should be RTL
CPPUNIT_ASSERT_EQUAL(short(1),
getProperty<short>(getRun(getParagraph(1), 1), u"WritingMode"_ustr));
// Insert a strong LTR character at the start of the paragraph.
// The writing mode should automatically switch to LTR.
pWrtShell->Insert(u"a"_ustr);
CPPUNIT_ASSERT_EQUAL(short(0),
getProperty<short>(getRun(getParagraph(1), 1), u"WritingMode"_ustr));
// Delete the leading LTR character.
// The writing mode should switch back to RTL.
pWrtShell->DelLeft();
CPPUNIT_ASSERT_EQUAL(short(1),
getProperty<short>(getRun(getParagraph(1), 1), u"WritingMode"_ustr));
}
} // end of anonymous namespace
CPPUNIT_PLUGIN_IMPLEMENT();
+10 -10
View File
@@ -26,7 +26,7 @@ class styleNavigator(UITestCase):
# The cursor is on text without formatting and default style
self.assertEqual(1, len(xListBox.getChild('0').getChildren()))
self.assertEqual("Default Paragraph Style\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
self.assertEqual(155, len(xListBox.getChild('0').getChild('0').getChildren()))
self.assertEqual(156, len(xListBox.getChild('0').getChild('0').getChildren()))
self.assertEqual(0, len(xListBox.getChild('1').getChildren()))
self.assertEqual(0, len(xListBox.getChild('2').getChildren()))
self.assertEqual(0, len(xListBox.getChild('3').getChildren()))
@@ -36,7 +36,7 @@ class styleNavigator(UITestCase):
# The cursor is on text with direct formatting
self.assertEqual(1, len(xListBox.getChild('0').getChildren()))
self.assertEqual("Default Paragraph Style\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
self.assertEqual(155, len(xListBox.getChild('0').getChild('0').getChildren()))
self.assertEqual(156, len(xListBox.getChild('0').getChild('0').getChildren()))
self.assertEqual(0, len(xListBox.getChild('1').getChildren()))
self.assertEqual(0, len(xListBox.getChild('2').getChildren()))
@@ -54,7 +54,7 @@ class styleNavigator(UITestCase):
# The cursor is on text with paragraph direct formatting
self.assertEqual(1, len(xListBox.getChild('0').getChildren()))
self.assertEqual("Default Paragraph Style\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
self.assertEqual(155, len(xListBox.getChild('0').getChild('0').getChildren()))
self.assertEqual(156, len(xListBox.getChild('0').getChild('0').getChildren()))
xParDirFormatting = xListBox.getChild('1')
self.assertEqual(7, len(xParDirFormatting.getChildren()))
@@ -75,7 +75,7 @@ class styleNavigator(UITestCase):
xParStyle = xListBox.getChild('0')
self.assertEqual(3, len(xParStyle.getChildren()))
self.assertEqual("Default Paragraph Style\t", get_state_as_dict(xParStyle.getChild('0'))['Text'])
self.assertEqual(155, len(xParStyle.getChild('0').getChildren()))
self.assertEqual(156, len(xParStyle.getChild('0').getChildren()))
self.assertEqual("Heading\t", get_state_as_dict(xParStyle.getChild('1'))['Text'])
self.assertEqual(28, len(xParStyle.getChild('1').getChildren()))
@@ -116,7 +116,7 @@ class styleNavigator(UITestCase):
xParStyle = xListBox.getChild('0')
self.assertEqual(3, len(xParStyle.getChildren()))
self.assertEqual("Default Paragraph Style\t", get_state_as_dict(xParStyle.getChild('0'))['Text'])
self.assertEqual(155, len(xParStyle.getChild('0').getChildren()))
self.assertEqual(156, len(xParStyle.getChild('0').getChildren()))
self.assertEqual("Body Text\t", get_state_as_dict(xParStyle.getChild('1'))['Text'])
self.assertEqual(6, len(xParStyle.getChild('1').getChildren()))
@@ -151,7 +151,7 @@ class styleNavigator(UITestCase):
# The cursor is on text without metadata
self.assertEqual(1, len(xListBox.getChild('0').getChildren()))
self.assertEqual("Default Paragraph Style\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
self.assertEqual(155, len(xListBox.getChild('0').getChild('0').getChildren()))
self.assertEqual(156, len(xListBox.getChild('0').getChild('0').getChildren()))
self.assertEqual(0, len(xListBox.getChild('1').getChildren()))
self.assertEqual(0, len(xListBox.getChild('2').getChildren()))
self.assertEqual(0, len(xListBox.getChild('3').getChildren()))
@@ -161,7 +161,7 @@ class styleNavigator(UITestCase):
# The cursor is on text with paragraph metadata showed under direct paragraph formatting
self.assertEqual(1, len(xListBox.getChild('0').getChildren()))
self.assertEqual("Default Paragraph Style\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
self.assertEqual(155, len(xListBox.getChild('0').getChild('0').getChildren()))
self.assertEqual(156, len(xListBox.getChild('0').getChild('0').getChildren()))
xParDirFormatting = xListBox.getChild('1')
self.assertEqual(1, len(xParDirFormatting.getChildren()))
@@ -214,7 +214,7 @@ class styleNavigator(UITestCase):
# The cursor is on text without metadata
self.assertEqual(1, len(xListBox.getChild('0').getChildren()))
self.assertEqual("Default Paragraph Style\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
self.assertEqual(155, len(xListBox.getChild('0').getChild('0').getChildren()))
self.assertEqual(156, len(xListBox.getChild('0').getChild('0').getChildren()))
self.assertEqual(0, len(xListBox.getChild('1').getChildren()))
self.assertEqual(0, len(xListBox.getChild('2').getChildren()))
self.assertEqual(0, len(xListBox.getChild('3').getChildren()))
@@ -224,7 +224,7 @@ class styleNavigator(UITestCase):
# The cursor is on text with paragraph metadata showed under direct paragraph formatting
self.assertEqual(1, len(xListBox.getChild('1').getChildren()))
self.assertEqual("Default Paragraph Style\t", get_state_as_dict(xListBox.getChild('1').getChild('0'))['Text'])
self.assertEqual(155, len(xListBox.getChild('1').getChild('0').getChildren()))
self.assertEqual(156, len(xListBox.getChild('1').getChild('0').getChildren()))
# Outer bookmark
xBookmarkFormatting = xListBox.getChild('0')
@@ -271,7 +271,7 @@ class styleNavigator(UITestCase):
# The cursor is on text without metadata
self.assertEqual(1, len(xListBox.getChild('0').getChildren()))
self.assertEqual("Default Paragraph Style\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
self.assertEqual(155, len(xListBox.getChild('0').getChild('0').getChildren()))
self.assertEqual(156, len(xListBox.getChild('0').getChild('0').getChildren()))
self.assertEqual(0, len(xListBox.getChild('1').getChildren()))
self.assertEqual(0, len(xListBox.getChild('2').getChildren()))
+1 -1
View File
@@ -35,7 +35,7 @@ class tdf137513(UITestCase):
self.assertEqual(2, len(xListBox.getChild('0').getChildren()))
self.assertEqual("Default Paragraph Style\t", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text'])
self.assertEqual("Table Contents\t", get_state_as_dict(xListBox.getChild('0').getChild('1'))['Text'])
self.assertEqual(155, len(xListBox.getChild('0').getChild('0').getChildren()))
self.assertEqual(156, len(xListBox.getChild('0').getChild('0').getChildren()))
xTableContent = xListBox.getChild('0').getChild('1')
self.assertEqual(5, len(xTableContent.getChildren()))
+2
View File
@@ -26,6 +26,7 @@
#include <comphelper/processfactory.hxx>
#include <doc.hxx>
#include <editeng/acorrcfg.hxx>
#include <editeng/autodiritem.hxx>
#include <editeng/autokernitem.hxx>
#include <editeng/blinkitem.hxx>
#include <editeng/boxitem.hxx>
@@ -376,6 +377,7 @@ std::unique_ptr<ItemInfoPackage> createItemInfoPackageSwAttributes()
{ RES_PARATR_SNAPTOGRID, new SvxParaGridItem( true, RES_PARATR_SNAPTOGRID ), SID_ATTR_PARA_SNAPTOGRID, SFX_ITEMINFOFLAG_NONE },
{ RES_PARATR_CONNECT_BORDER, new SwParaConnectBorderItem, SID_ATTR_BORDER_CONNECT, SFX_ITEMINFOFLAG_NONE },
{ RES_PARATR_OUTLINELEVEL, new SfxUInt16Item( RES_PARATR_OUTLINELEVEL, 0 ), SID_ATTR_PARA_OUTLINE_LEVEL, SFX_ITEMINFOFLAG_NONE },
{ RES_PARATR_AUTOFRAMEDIR, new SvxAutoFrameDirectionItem( false, RES_PARATR_AUTOFRAMEDIR ), SID_ATTR_PARA_AUTOFRAMEDIRECTION, SFX_ITEMINFOFLAG_NONE },
{ RES_PARATR_RSID, new SvxRsidItem( 0, RES_PARATR_RSID ), 0, SFX_ITEMINFOFLAG_NONE },
{ RES_PARATR_GRABBAG, new SfxGrabBagItem( RES_PARATR_GRABBAG ), SID_ATTR_PARA_GRABBAG, SFX_ITEMINFOFLAG_NONE },
+1
View File
@@ -159,6 +159,7 @@ static std::map<sal_uInt16,OUString> & GetItemWhichMap()
{ RES_PARATR_VERTALIGN , "PARATR_VERTALIGN" },
{ RES_PARATR_SNAPTOGRID , "PARATR_SNAPTOGRID" },
{ RES_PARATR_CONNECT_BORDER , "PARATR_CONNECT_BORDER" },
{ RES_PARATR_AUTOFRAMEDIR, "PARATR_AUTOFRAMEDIR" },
{ RES_FILL_ORDER , "FILL_ORDER" },
{ RES_FRM_SIZE , "FRM_SIZE" },
{ RES_PAPER_BIN , "PAPER_BIN" },
+3
View File
@@ -164,6 +164,9 @@ bool SwEditShell::Delete(bool const isArtificialSelection, bool goLeft)
DeleteSel(rPaM, isArtificialSelection, goLeft, &bUndo);
}
// tdf#162120: Automatically adjust paragraph directions after delete
UpdateSelectionAutoParaDirection();
// If undo container then close here
if( bUndo )
{
+64
View File
@@ -24,6 +24,9 @@
#include <comphelper/processfactory.hxx>
#include <comphelper/string.hxx>
#include <unotools/transliterationwrapper.hxx>
#include <i18nutil/guessparadirection.hxx>
#include <editeng/autodiritem.hxx>
#include <editeng/frmdiritem.hxx>
#include <fmtsrnd.hxx>
#include <fmtinfmt.hxx>
#include <txtinet.hxx>
@@ -59,6 +62,58 @@
using namespace com::sun::star;
void SwEditShell::UpdateSelectionAutoParaDirection()
{
for (SwPaM& rPaM : getShellCursor(true)->GetRingContainer())
{
auto* pNode = rPaM.GetPointNode().GetTextNode();
if (!pNode)
{
continue;
}
const SvxAutoFrameDirectionItem* pAutoItem
= pNode->GetSwAttrSet().GetItemIfSet(RES_PARATR_AUTOFRAMEDIR);
if (!pAutoItem || !pAutoItem->GetValue())
{
continue;
}
Point aPt;
std::pair<Point, bool> const tmp(aPt, false);
const SwTextFrame* pFrame
= static_cast<SwTextFrame*>(pNode->getLayoutFrame(GetLayout(), rPaM.GetPoint(), &tmp));
bool bIsAlreadyRtl = pFrame->IsRightToLeft();
bool bShouldBeRtl = bIsAlreadyRtl;
switch (i18nutil::GuessParagraphDirection(pNode->GetText()))
{
case i18nutil::ParagraphDirection::Ambiguous:
bShouldBeRtl = bIsAlreadyRtl;
break;
case i18nutil::ParagraphDirection::LeftToRight:
bShouldBeRtl = false;
break;
case i18nutil::ParagraphDirection::RightToLeft:
bShouldBeRtl = true;
break;
}
if (bShouldBeRtl == bIsAlreadyRtl)
{
continue;
}
SvxFrameDirection eNeeded = bShouldBeRtl ? SvxFrameDirection::Horizontal_RL_TB
: SvxFrameDirection::Horizontal_LR_TB;
rPaM.GetDoc().getIDocumentContentOperations().InsertPoolItem(
rPaM, SvxFrameDirectionItem{ eNeeded, RES_FRAMEDIR });
}
}
void SwEditShell::Insert( sal_Unicode c, bool bOnlyCurrCursor )
{
StartAllAction();
@@ -73,6 +128,9 @@ void SwEditShell::Insert( sal_Unicode c, bool bOnlyCurrCursor )
}
// tdf#162120: Automatically adjust paragraph direction after insert
UpdateSelectionAutoParaDirection();
EndAllAction();
}
@@ -162,6 +220,9 @@ void SwEditShell::Insert2(const OUString &rStr, const bool bForceExpandHints )
SetInFrontOfLabel( false ); // #i27615#
// tdf#162120: Automatically adjust paragraph direction after insert
UpdateSelectionAutoParaDirection();
EndAllAction();
}
@@ -978,6 +1039,9 @@ OUString SwEditShell::DeleteExtTextInput( bool bInsText )
if ( ! bInsText && IsOverwriteCursor() )
*GetCursor()->GetPoint() = aPos;
// tdf#162120: Automatically adjust paragraph direction after insert
UpdateSelectionAutoParaDirection();
EndAllAction();
}
return sRet;
+3 -1
View File
@@ -255,6 +255,7 @@
{ UNO_NAME_CHAR_SHADING_VALUE, RES_CHRATR_BACKGROUND, cppu::UnoType<sal_Int32>::get(), PROPERTY_NONE, MID_SHADING_VALUE }, \
{ UNO_NAME_PARA_INTEROP_GRAB_BAG, RES_PARATR_GRABBAG, cppu::UnoType< cppu::UnoSequenceType<css::beans::PropertyValue> >::get(), PROPERTY_NONE, 0 }, \
{ UNO_NAME_CHAR_SCRIPT_HINT, RES_CHRATR_SCRIPT_HINT, cppu::UnoType<sal_Int16>::get(), PropertyAttribute::MAYBEVOID, MID_SCRIPTHINT }, \
{ UNO_NAME_PARA_WRITING_MODE_AUTOMATIC, RES_PARATR_AUTOFRAMEDIR, cppu::UnoType<bool>::get(), PropertyAttribute::MAYBEVOID, 0 }, \
#define COMMON_CRSR_PARA_PROPERTIES_WITHOUT_FN \
COMMON_CRSR_PARA_PROPERTIES_WITHOUT_FN_01 \
@@ -547,7 +548,8 @@
{ UNO_NAME_OUTLINE_LEVEL, RES_PARATR_OUTLINELEVEL,cppu::UnoType<sal_Int16>::get(), PropertyAttribute::MAYBEVOID, 0}, \
{ UNO_NAME_HIDDEN, FN_UNO_HIDDEN, cppu::UnoType<bool>::get(), PROPERTY_NONE, 0}, \
{ UNO_NAME_STYLE_INTEROP_GRAB_BAG, FN_UNO_STYLE_INTEROP_GRAB_BAG, cppu::UnoType< cppu::UnoSequenceType<css::beans::PropertyValue> >::get(), PROPERTY_NONE, 0}, \
{ UNO_NAME_PARA_INTEROP_GRAB_BAG, RES_PARATR_GRABBAG, cppu::UnoType< cppu::UnoSequenceType<css::beans::PropertyValue> >::get(), PROPERTY_NONE, 0},
{ UNO_NAME_PARA_INTEROP_GRAB_BAG, RES_PARATR_GRABBAG, cppu::UnoType< cppu::UnoSequenceType<css::beans::PropertyValue> >::get(), PROPERTY_NONE, 0}, \
{ UNO_NAME_PARA_WRITING_MODE_AUTOMATIC, RES_PARATR_AUTOFRAMEDIR, cppu::UnoType<bool>::get(), PropertyAttribute::MAYBEVOID, 0},
#define COMMON_ACCESSIBILITY_TEXT_ATTRIBUTE \
{ UNO_NAME_CHAR_BACK_COLOR, RES_CHRATR_BACKGROUND, cppu::UnoType<sal_Int32>::get(), PROPERTY_NONE ,MID_BACK_COLOR }, \
+1
View File
@@ -3484,6 +3484,7 @@ SwAttrFnTab const aCSS1AttrFnTab = {
/* RES_PARATR_SNAPTOGRID*/ nullptr, // new
/* RES_PARATR_CONNECT_TO_BORDER */ nullptr, // new
/* RES_PARATR_OUTLINELEVEL */ nullptr, // new since cws outlinelevel
/* RES_PARATR_AUTOFRAMEDIR */ nullptr,
/* RES_PARATR_RSID */ nullptr, // new
/* RES_PARATR_GRABBAG */ nullptr,
+1
View File
@@ -3361,6 +3361,7 @@ const SwAttrFnTab aHTMLAttrFnTab = {
/* RES_PARATR_SNAPTOGRID*/ nullptr, // new
/* RES_PARATR_CONNECT_TO_BORDER */ nullptr, // new
/* RES_PARATR_OUTLINELEVEL */ nullptr,
/* RES_PARATR_AUTOFRAMEDIR */ nullptr,
/* RES_PARATR_RSID */ nullptr,
/* RES_PARATR_GRABBAG */ nullptr,
+6
View File
@@ -26,6 +26,7 @@
#include <sfx2/bindings.hxx>
#include <sfx2/request.hxx>
#include <sfx2/viewfrm.hxx>
#include <editeng/autodiritem.hxx>
#include <editeng/fhgtitem.hxx>
#include <editeng/adjustitem.hxx>
#include <editeng/lspcitem.hxx>
@@ -327,6 +328,7 @@ void SwTextShell::ExecParaAttr(SfxRequest &rReq)
// Get both attributes immediately isn't more expensive!!
SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<RES_PARATR_LINESPACING, RES_PARATR_ADJUST,
RES_PARATR_HYPHENZONE, RES_PARATR_HYPHENZONE,
RES_PARATR_AUTOFRAMEDIR, RES_PARATR_AUTOFRAMEDIR,
RES_FRAMEDIR, RES_FRAMEDIR>(GetPool()));
sal_uInt16 nSlot = rReq.GetSlot();
switch (nSlot)
@@ -406,6 +408,10 @@ SET_LINESPACE:
SvxFrameDirection::Horizontal_LR_TB : SvxFrameDirection::Horizontal_RL_TB;
aSet.Put( SvxFrameDirectionItem( eFrameDirection, RES_FRAMEDIR ) );
// tdf#162120: The paragraph direction has been manually set by the user.
// Don't automatically adjust the paragraph direction anymore.
aSet.Put(SvxAutoFrameDirectionItem(false, RES_PARATR_AUTOFRAMEDIR));
if (bChgAdjust)
{
SvxAdjust eAdjust = (SID_ATTR_PARA_LEFT_TO_RIGHT == nSlot) ?
@@ -339,6 +339,7 @@ static OUString PropertyNametoRID(const OUString& rName)
{ "UnvisitedCharStyleName", RID_UNVISITED_CHAR_STYLE_NAME },
{ "VisitedCharStyleName", RID_VISITED_CHAR_STYLE_NAME },
{ "WritingMode", RID_WRITING_MODE },
{ "WritingModeAutomatic", RID_WRITING_MODE_AUTOMATIC },
{ "BorderColor", RID_BORDER_COLOR },
{ "BorderInnerLineWidth", RID_BORDER_INNER_LINE_WIDTH },
{ "BorderLineDistance", RID_BORDER_LINE_DISTANCE },
+1
View File
@@ -691,6 +691,7 @@ inline constexpr OUString PROP_WidthType = u"WidthType"_ustr;
inline constexpr OUString PROP_WrapInfluenceOnPosition = u"WrapInfluenceOnPosition"_ustr;
inline constexpr OUString PROP_WrapTextAtFlyStart = u"WrapTextAtFlyStart"_ustr;
inline constexpr OUString PROP_WritingMode = u"WritingMode"_ustr;
inline constexpr OUString PROP_WritingModeAutomatic = u"WritingModeAutomatic"_ustr;
inline constexpr OUString PROP_XName = u"XName"_ustr;
inline constexpr OUString PROP_YName = u"YName"_ustr;
+1
View File
@@ -2227,6 +2227,7 @@ namespace xmloff::token {
TOKEN( "wrap-contour-mode", XML_WRAP_CONTOUR_MODE ),
TOKEN( "wrap-option", XML_WRAP_OPTION ),
TOKEN( "writing-mode", XML_WRITING_MODE ),
TOKEN( "writing-mode-automatic", XML_WRITING_MODE_AUTOMATIC ),
TOKEN( "www", XML_WWW ),
TOKEN( "x", XML_X ),
TOKEN( "x1", XML_X1 ),
+3
View File
@@ -465,6 +465,9 @@ XMLPropertyMapEntry constexpr aXMLParaPropMap[] =
MP_ED( PROP_WritingMode, XML_NAMESPACE_STYLE, XML_WRITING_MODE, XML_TYPE_TEXT_WRITING_MODE_WITH_DEFAULT, CTF_TEXTWRITINGMODE ),
// RES_PARATR_AUTOFRAMEDIR
MP_E( PROP_WritingModeAutomatic, XML_NAMESPACE_STYLE, XML_WRITING_MODE_AUTOMATIC, XML_TYPE_BOOL, 0 ),
MP_E( PROP_ParaIsConnectBorder, XML_NAMESPACE_STYLE, XML_JOIN_BORDER, XML_TYPE_BOOL, 0 ),
MP_E( PROP_DefaultOutlineLevel, XML_NAMESPACE_STYLE, XML_DEFAULT_OUTLINE_LEVEL, XML_TYPE_TEXT_NUMBER8_ONE_BASED|MID_FLAG_SPECIAL_ITEM_EXPORT|MID_FLAG_NO_PROPERTY_IMPORT, CTF_DEFAULT_OUTLINE_LEVEL ),
+1
View File
@@ -2127,6 +2127,7 @@ wrap-contour
wrap-contour-mode
wrap-option
writing-mode
writing-mode-automatic
www
x
x1