include/xmloff/xmltoken.hxx                                 |    1 
 offapi/com/sun/star/text/TextTableRow.idl                   |    2 
 schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng |    9 +
 sw/inc/unoprnms.hxx                                         |    2 
 sw/qa/extras/uiwriter/uiwriter2.cxx                         |   63 +++++++++++-
 sw/source/core/bastyp/init.cxx                              |    2 
 sw/source/core/doc/DocumentRedlineManager.cxx               |    6 -
 sw/source/core/unocore/unomap.cxx                           |    2 
 sw/source/filter/xml/xmlexpit.cxx                           |   12 ++
 sw/source/filter/xml/xmlimpit.cxx                           |   17 +++
 sw/source/filter/xml/xmliteme.cxx                           |   29 +++++
 sw/source/filter/xml/xmlitemm.cxx                           |    3 
 sw/source/filter/xml/xmltble.cxx                            |   25 ++++
 xmloff/source/core/xmltoken.cxx                             |    1 
 xmloff/source/token/tokens.txt                              |    1 
 15 files changed, 163 insertions(+), 12 deletions(-)

New commits:
commit 0ac551ff9a1c9f4e3aef9345d2c0525da92d40e8
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Wed May 26 16:31:15 2021 +0200
Commit:     Gabor Kelemen <kelemen.gab...@nisz.hu>
CommitDate: Thu Aug 19 19:56:38 2021 +0200

    tdf#60382 sw xmloff: import/export tracked table/row deletion
    
    to OpenDocument format using
    
    <style:table-row-properties loext:text-changes-only="false"/>
    
    Rename also com::sun::star::text::TextTableRow::IsNotTracked
    to com::sun::star::text::TextTableRow::HasTextChangesOnly.
    
    Follow-up to commit 05366b8e6683363688de8708a3d88cf144c7a2bf
    "tdf#60382 sw offapi: add change tracking of table/row deletion".
    
    Change-Id: Iefb0d4095af0983fdd15697d5b80073d18d21bd7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/116212
    Tested-by: Jenkins
    Reviewed-by: László Németh <nem...@numbertext.org>
    (cherry picked from commit 48898a72066ff9982feafebb26708c4e779fd460)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120719
    Tested-by: Gabor Kelemen <kelemen.gab...@nisz.hu>
    Reviewed-by: Gabor Kelemen <kelemen.gab...@nisz.hu>

diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx
index 7c7dc8ef95bb..b4a054c5add3 100644
--- a/include/xmloff/xmltoken.hxx
+++ b/include/xmloff/xmltoken.hxx
@@ -1910,6 +1910,7 @@ namespace xmloff::token {
         XML_TEXT_BACKGROUND_COLOR,
         XML_TEXT_BLINKING,
         XML_TEXT_BOX,
+        XML_TEXT_CHANGES_ONLY,
         XML_TEXT_COMBINE,
         XML_TEXT_COMBINE_END_CHAR,
         XML_TEXT_COMBINE_START_CHAR,
diff --git a/offapi/com/sun/star/text/TextTableRow.idl 
b/offapi/com/sun/star/text/TextTableRow.idl
index e418fbbf9366..dcecda3f25c7 100644
--- a/offapi/com/sun/star/text/TextTableRow.idl
+++ b/offapi/com/sun/star/text/TextTableRow.idl
@@ -111,7 +111,7 @@ published service TextTableRow
         @since LibreOffice 7.2
      */
 
-        [optional, property] boolean IsNotTracked;
+        [optional, property] boolean HasTextChangesOnly;
 
 };
 
diff --git a/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng 
b/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng
index 0c0b41ef4ca9..cea33a32c7bf 100644
--- a/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng
+++ b/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng
@@ -2483,4 +2483,13 @@ 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.
     </rng:optional>
   </rng:define>
 
+  <!-- TODO no proposal -->
+  <rng:define name="style-table-row-properties-attlist" combine="interleave">
+    <rng:optional>
+      <rng:attribute name="loext:text-changes-only">
+        <rng:ref name="boolean"/>
+      </rng:attribute>
+    </rng:optional>
+  </rng:define>
+
 </rng:grammar>
diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx
index 61cee34745ac..fc2c34d687cd 100644
--- a/sw/inc/unoprnms.hxx
+++ b/sw/inc/unoprnms.hxx
@@ -735,7 +735,7 @@
 #define UNO_NAME_ITEMS "Items"
 #define UNO_NAME_SELITEM "SelectedItem"
 #define UNO_NAME_IS_SPLIT_ALLOWED "IsSplitAllowed"
-#define UNO_NAME_IS_NOT_TRACKED "IsNotTracked"
+#define UNO_NAME_HAS_TEXT_CHANGES_ONLY "HasTextChangesOnly"
 #define UNO_NAME_CHAR_HIDDEN "CharHidden"
 #define UNO_NAME_IS_FOLLOWING_TEXT_FLOW "IsFollowingTextFlow"
 #define UNO_NAME_WIDTH_TYPE "WidthType"
diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx 
b/sw/qa/extras/uiwriter/uiwriter2.cxx
index e643df300576..37820608d74f 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -3394,7 +3394,7 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, 
testRedlineTableRowDeletion)
     assertXPath(pXmlDoc, "//page[1]//body/tab");
 
     // delete table row with enabled change tracking
-    // (IsNotTracked property of the row will be false)
+    // (HasTextChangesOnly property of the row will be false)
     dispatchCommand(mxComponent, ".uno:DeleteRows", {});
 
     // This was deleted without change tracking
@@ -3421,7 +3421,7 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, 
testRedlineTableRowDeletion)
     assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
 
     // Undo, and repeat the previous test, but only with deletion of the text 
content of the cells
-    // (IsNotTracked property will be removed by Undo)
+    // (HasTextChangesOnly property will be removed by Undo)
 
     dispatchCommand(mxComponent, ".uno:Undo", {});
     dispatchCommand(mxComponent, ".uno:Undo", {});
@@ -3454,7 +3454,7 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, 
testRedlineTableRowDeletion)
     pEditShell->AcceptRedline(0);
 
     // table row (and the 1-row table) still exists
-    // (IsNotTracked property wasn't set for table row deletion)
+    // (HasTextChangesOnly property wasn't set for table row deletion)
     discardDumpedLayout();
     pXmlDoc = parseLayoutDump();
     assertXPath(pXmlDoc, "//page[1]//body/tab");
@@ -3486,6 +3486,63 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, 
testRedlineTableRowDeletion)
     assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testRedlineTableRowDeletionWithExport)
+{
+    // load a 1-row table, and delete the row with enabled change tracking:
+    // now the row is not deleted silently, but keeps the deleted cell 
contents,
+    // and only accepting all of them will result the deletion of the table 
row.
+    SwDoc* pDoc = createDoc("tdf118311.fodt");
+
+    SwXTextDocument* pTextDoc = 
dynamic_cast<SwXTextDocument*>(mxComponent.get());
+    CPPUNIT_ASSERT(pTextDoc);
+
+    // turn on red-lining and show changes
+    pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | 
RedlineFlags::ShowDelete
+                                                      | 
RedlineFlags::ShowInsert);
+    CPPUNIT_ASSERT_MESSAGE("redlining should be on",
+                           pDoc->getIDocumentRedlineAccess().IsRedlineOn());
+    CPPUNIT_ASSERT_MESSAGE(
+        "redlines should be visible",
+        
IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
+
+    // check table
+    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+    assertXPath(pXmlDoc, "//page[1]//body/tab");
+
+    // delete table row with enabled change tracking
+    // (HasTextChangesOnly property of the row will be false)
+    dispatchCommand(mxComponent, ".uno:DeleteRows", {});
+
+    // Deleted text content with change tracking,
+    // but not table deletion
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+    assertXPath(pXmlDoc, "//page[1]//body/tab");
+
+    // Save it and load it back.
+    reload("writer8", "tdf60382_tracked_table_deletion.odt");
+    pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+    pDoc = pTextDoc->GetDocShell()->GetWrtShell()->GetDoc();
+
+    // accept the deletion of the content of the first cell
+    SwEditShell* const pEditShell(pDoc->GetEditShell());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), 
pEditShell->GetRedlineCount());
+    pEditShell->AcceptRedline(0);
+
+    // table row was still not deleted
+    pXmlDoc = parseLayoutDump();
+    assertXPath(pXmlDoc, "//page[1]//body/tab");
+
+    // accept last redline
+    pEditShell->AcceptRedline(0);
+
+    // table row (and the 1-row table) was deleted finally
+    // (working export/import of HasTextChangesOnly)
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+    assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf128335)
 {
     // Load the bugdoc, which has 3 textboxes.
diff --git a/sw/source/core/bastyp/init.cxx b/sw/source/core/bastyp/init.cxx
index e6775a11666c..8f5342fb2573 100644
--- a/sw/source/core/bastyp/init.cxx
+++ b/sw/source/core/bastyp/init.cxx
@@ -206,7 +206,7 @@ sal_uInt16 const aTableSetRange[] = {
 
 sal_uInt16 const aTableLineSetRange[] = {
     RES_FILL_ORDER,     RES_FRM_SIZE,
-    // IsNotTracked
+    // HasTextChangesOnly
     RES_PRINT,          RES_PRINT,
     RES_LR_SPACE,       RES_UL_SPACE,
     RES_BACKGROUND,     RES_SHADOW,
diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx 
b/sw/source/core/doc/DocumentRedlineManager.cxx
index d7c3e1e1e545..26ad2204d786 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -433,10 +433,10 @@ namespace
         if ( const SwTableBox* pBox = pPos->nNode.GetNode().GetTableBox() )
         {
             const SwTableLine* pLine = pBox->GetUpper();
-            const SvxPrintItem *pIsNoTrackedProp =
+            const SvxPrintItem *pHasTextChangesOnlyProp =
                     
pLine->GetFrameFormat()->GetAttrSet().GetItem<SvxPrintItem>(RES_PRINT);
-            // table row property "IsNotTracked" is set and its value is false
-            if ( pIsNoTrackedProp && !pIsNoTrackedProp->GetValue() )
+            // table row property "HasTextChangesOnly" is set and its value is 
false
+            if ( pHasTextChangesOnlyProp && 
!pHasTextChangesOnlyProp->GetValue() )
             {
                 bool bEmptyLine = true;
                 const SwTableBoxes & rBoxes = pLine->GetTabBoxes();
diff --git a/sw/source/core/unocore/unomap.cxx 
b/sw/source/core/unocore/unomap.cxx
index a1282519d47e..f62f38192aa7 100644
--- a/sw/source/core/unocore/unomap.cxx
+++ b/sw/source/core/unocore/unomap.cxx
@@ -543,7 +543,7 @@ const SfxItemPropertyMapEntry* 
SwUnoPropertyMapProvider::GetPropertyMapEntries(s
                     { u"" UNO_NAME_SIZE_TYPE, RES_FRM_SIZE,           
cppu::UnoType<sal_Int16>::get()  ,         PROPERTY_NONE,   
MID_FRMSIZE_SIZE_TYPE  },
                     { u"" UNO_NAME_WIDTH_TYPE, RES_FRM_SIZE,          
cppu::UnoType<sal_Int16>::get()  ,         PROPERTY_NONE,   
MID_FRMSIZE_WIDTH_TYPE },
                     { u"" UNO_NAME_IS_SPLIT_ALLOWED, RES_ROW_SPLIT,       
cppu::UnoType<bool>::get()  , PropertyAttribute::MAYBEVOID, 0},
-                    { u"" UNO_NAME_IS_NOT_TRACKED, RES_PRINT, 
cppu::UnoType<bool>::get()  , PropertyAttribute::MAYBEVOID, 0},
+                    { u"" UNO_NAME_HAS_TEXT_CHANGES_ONLY, RES_PRINT, 
cppu::UnoType<bool>::get()  , PropertyAttribute::MAYBEVOID, 0},
                     { u"" UNO_NAME_ROW_INTEROP_GRAB_BAG, RES_FRMATR_GRABBAG, 
cppu::UnoType< cppu::UnoSequenceType<css::beans::PropertyValue> >::get(), 
PROPERTY_NONE, 0 },
                     { u"", 0, css::uno::Type(), 0, 0 }
                 };
diff --git a/sw/source/filter/xml/xmlexpit.cxx 
b/sw/source/filter/xml/xmlexpit.cxx
index d458936a0116..0796835dcc07 100644
--- a/sw/source/filter/xml/xmlexpit.cxx
+++ b/sw/source/filter/xml/xmlexpit.cxx
@@ -46,6 +46,7 @@
 #include <editeng/keepitem.hxx>
 #include <editeng/brushitem.hxx>
 #include <editeng/frmdiritem.hxx>
+#include <editeng/prntitem.hxx>
 #include <fmtpdsc.hxx>
 #include <fmtornt.hxx>
 #include <fmtfsize.hxx>
@@ -871,6 +872,17 @@ bool SvXMLExportItemMapper::QueryXMLValue(
         }
         break;
 
+        case RES_PRINT:
+        {
+            const SvxPrintItem* pHasTextChangesOnly = dynamic_cast<const 
SvxPrintItem*>( &rItem );
+            if (pHasTextChangesOnly && !pHasTextChangesOnly->GetValue())
+            {
+                aOut.append( "false" );
+                bOk = true;
+            }
+        }
+        break;
+
         case RES_BACKGROUND:
         {
             const SvxBrushItem& rBrush = dynamic_cast<const 
SvxBrushItem&>(rItem);
diff --git a/sw/source/filter/xml/xmlimpit.cxx 
b/sw/source/filter/xml/xmlimpit.cxx
index 1a0978bc9bbd..6a792eaa2ef0 100644
--- a/sw/source/filter/xml/xmlimpit.cxx
+++ b/sw/source/filter/xml/xmlimpit.cxx
@@ -857,6 +857,23 @@ bool SvXMLImportItemMapper::PutXMLValue(
         }
         break;
 
+        case RES_PRINT:
+        {
+            SfxBoolItem& rHasTextChangesOnly = 
dynamic_cast<SfxBoolItem&>(rItem);
+
+            if( IsXMLToken( rValue, XML_TRUE ) )
+            {
+                rHasTextChangesOnly.SetValue( true );
+                bOk = true;
+            }
+            else if( IsXMLToken( rValue, XML_FALSE ) )
+            {
+                rHasTextChangesOnly.SetValue( false );
+                bOk = true;
+            }
+        }
+        break;
+
         case RES_HORI_ORIENT:
         {
             SwFormatHoriOrient& rHoriOrient = 
dynamic_cast<SwFormatHoriOrient&>(rItem);
diff --git a/sw/source/filter/xml/xmliteme.cxx 
b/sw/source/filter/xml/xmliteme.cxx
index eb5f74ced41d..0251083100a8 100644
--- a/sw/source/filter/xml/xmliteme.cxx
+++ b/sw/source/filter/xml/xmliteme.cxx
@@ -33,6 +33,8 @@
 #include <frmfmt.hxx>
 #include "xmlexp.hxx"
 #include <editeng/memberids.h>
+#include <editeng/prntitem.hxx>
+#include <xmloff/xmlnamespace.hxx>
 
 using namespace ::com::sun::star;
 using namespace ::com::sun::star::uno;
@@ -105,6 +107,33 @@ void SwXMLTableItemMapper_Impl::handleSpecialItem(
 {
     switch( rEntry.nWhichId )
     {
+
+    case RES_PRINT:
+        {
+            const SfxPoolItem *pItem;
+            if( pSet &&
+                SfxItemState::SET == pSet->GetItemState( RES_PRINT, true,
+                                                    &pItem ) )
+            {
+                bool bHasTextChangesOnly =
+                    static_cast<const SvxPrintItem *>(pItem)->GetValue();
+                if ( !bHasTextChangesOnly )
+                {
+                    OUString sValue;
+                    sal_uInt16 nMemberId =
+                        static_cast<sal_uInt16>( rEntry.nMemberId & 
MID_SW_FLAG_MASK );
+
+                    if( SvXMLExportItemMapper::QueryXMLValue(
+                        rItem, sValue, nMemberId, rUnitConverter ) )
+                    {
+                        AddAttribute( rEntry.nNameSpace, rEntry.eLocalName,
+                                      sValue, rNamespaceMap, rAttrList );
+                    }
+               }
+           }
+        }
+        break;
+
     case RES_LR_SPACE:
         {
             const SfxPoolItem *pItem;
diff --git a/sw/source/filter/xml/xmlitemm.cxx 
b/sw/source/filter/xml/xmlitemm.cxx
index 5513e925ccbf..afbf0a4e2f72 100644
--- a/sw/source/filter/xml/xmlitemm.cxx
+++ b/sw/source/filter/xml/xmlitemm.cxx
@@ -151,7 +151,8 @@ SvXMLItemMapEntry const aXMLTableRowItemMap[] =
     // RES_FOOTER
     // not required
     // RES_PRINT
-    // not required
+    // M_E_SE( STYLE, TEXT_CHANGES_ONLY, RES_PRINT, 0 ),
+    M_E_SE( LO_EXT, TEXT_CHANGES_ONLY, RES_PRINT, 0 ),
     // RES_OPAQUE
     // not required
     // RES_PROTECT
diff --git a/sw/source/filter/xml/xmltble.cxx b/sw/source/filter/xml/xmltble.cxx
index 605845088fa1..f27647ae7e4c 100644
--- a/sw/source/filter/xml/xmltble.cxx
+++ b/sw/source/filter/xml/xmltble.cxx
@@ -28,6 +28,7 @@
 #include <xmloff/numehelp.hxx>
 #include <editeng/brushitem.hxx>
 #include <editeng/boxitem.hxx>
+#include <editeng/prntitem.hxx>
 #include <editeng/xmlcnitm.hxx>
 #include <fmtrowsplt.hxx>
 #include <editeng/frmdiritem.hxx>
@@ -193,6 +194,7 @@ bool SwXMLTableFrameFormatsSort_Impl::AddRow( 
SwFrameFormat& rFrameFormat,
     const SwFormatFrameSize *pFrameSize = nullptr;
     const SwFormatRowSplit* pRowSplit = nullptr;
     const SvxBrushItem *pBrush = nullptr;
+    const SvxPrintItem *pHasTextChangesOnly = nullptr;
 
     const SfxItemSet& rItemSet = rFrameFormat.GetAttrSet();
     const SfxPoolItem *pItem;
@@ -205,8 +207,11 @@ bool SwXMLTableFrameFormatsSort_Impl::AddRow( 
SwFrameFormat& rFrameFormat,
     if( SfxItemState::SET == rItemSet.GetItemState( RES_BACKGROUND, false, 
&pItem ) )
         pBrush = static_cast<const SvxBrushItem *>(pItem);
 
+    if( SfxItemState::SET == rItemSet.GetItemState( RES_PRINT, false, &pItem ) 
)
+        pHasTextChangesOnly = static_cast<const SvxPrintItem *>(pItem);
+
     // empty styles have not to be exported
-    if( !pFrameSize && !pBrush && !pRowSplit )
+    if( !pFrameSize && !pBrush && !pRowSplit && !pHasTextChangesOnly )
         return false;
 
     // order is: -/brush, size/-, size/brush
@@ -217,6 +222,7 @@ bool SwXMLTableFrameFormatsSort_Impl::AddRow( 
SwFrameFormat& rFrameFormat,
         const SwFormatFrameSize *pTestFrameSize = nullptr;
         const SwFormatRowSplit* pTestRowSplit = nullptr;
         const SvxBrushItem *pTestBrush = nullptr;
+        const SvxPrintItem *pTestHasTextChangesOnly = nullptr;
         const SwFrameFormat *pTestFormat = *i;
         const SfxItemSet& rTestSet = pTestFormat->GetAttrSet();
         if( SfxItemState::SET == rTestSet.GetItemState( RES_FRM_SIZE, false,
@@ -261,6 +267,20 @@ bool SwXMLTableFrameFormatsSort_Impl::AddRow( 
SwFrameFormat& rFrameFormat,
                 continue;
         }
 
+        if( SfxItemState::SET == rTestSet.GetItemState( RES_PRINT, false,
+                                                  &pItem ) )
+        {
+            if( !pHasTextChangesOnly )
+                break;
+
+            pTestHasTextChangesOnly = static_cast<const SvxPrintItem *>(pItem);
+        }
+        else
+        {
+            if( pHasTextChangesOnly )
+                continue;
+        }
+
         if( pFrameSize &&
             ( pFrameSize->GetHeightSizeType() != 
pTestFrameSize->GetHeightSizeType() ||
               pFrameSize->GetHeight() != pTestFrameSize->GetHeight() ) )
@@ -272,6 +292,9 @@ bool SwXMLTableFrameFormatsSort_Impl::AddRow( 
SwFrameFormat& rFrameFormat,
         if( pRowSplit && (!pRowSplit->GetValue() != 
!pTestRowSplit->GetValue()) )
             continue;
 
+        if( pHasTextChangesOnly && (!pHasTextChangesOnly->GetValue() != 
!pTestHasTextChangesOnly->GetValue()) )
+            continue;
+
         // found!
         rFrameFormat.SetName( pTestFormat->GetName() );
         bInsert = false;
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index 12fd1a1e9aa8..e5dd46cd914e 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -1916,6 +1916,7 @@ namespace xmloff::token {
         TOKEN( "text-background-color",           XML_TEXT_BACKGROUND_COLOR ),
         TOKEN( "text-blinking",                   XML_TEXT_BLINKING ),
         TOKEN( "text-box",                        XML_TEXT_BOX ),
+        TOKEN( "text-changes-only",               XML_TEXT_CHANGES_ONLY ),
         TOKEN( "text-combine",                    XML_TEXT_COMBINE ),
         TOKEN( "text-combine-end-char",           XML_TEXT_COMBINE_END_CHAR ),
         TOKEN( "text-combine-start-char",         XML_TEXT_COMBINE_START_CHAR 
),
diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt
index da31bdf2ff97..65d77b9f4143 100644
--- a/xmloff/source/token/tokens.txt
+++ b/xmloff/source/token/tokens.txt
@@ -1823,6 +1823,7 @@ text-autospace
 text-background-color
 text-blinking
 text-box
+text-changes-only
 text-combine
 text-combine-end-char
 text-combine-start-char

Reply via email to