sw UNO Cell Style family, SwXTextCellStyle

Cell Family :: getByName
Cell Family :: getElementNames
Cell Family :: getCount

Change-Id: I37d567ee284054f847c704d9fce370d174a0c48c
Reviewed-on: https://gerrit.libreoffice.org/25896
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
diff --git a/include/rsc/rscsfx.hxx b/include/rsc/rscsfx.hxx
index cc3ab9c..dadf191 100644
--- a/include/rsc/rscsfx.hxx
+++ b/include/rsc/rscsfx.hxx
@@ -38,6 +38,7 @@ enum class SfxStyleFamily {
    Page    = 0x08,
    Pseudo  = 0x10,
    Table   = 0x20,
    Cell    = 0x40,
    All     = 0x7fff
};

diff --git a/sw/inc/SwGetPoolIdFromName.hxx b/sw/inc/SwGetPoolIdFromName.hxx
index 55f3ca6..57e28028 100644
--- a/sw/inc/SwGetPoolIdFromName.hxx
+++ b/sw/inc/SwGetPoolIdFromName.hxx
@@ -32,6 +32,7 @@ namespace nsSwGetPoolIdFromName
    const SwGetPoolIdFromName GET_POOLID_PAGEDESC = 0x08;
    const SwGetPoolIdFromName GET_POOLID_NUMRULE  = 0x10;
    const SwGetPoolIdFromName GET_POOLID_TABSTYLE = 0x20;
    const SwGetPoolIdFromName GET_POOLID_CELLSTYLE= 0x40;
}

#endif
diff --git a/sw/inc/SwStyleNameMapper.hxx b/sw/inc/SwStyleNameMapper.hxx
index 035e0c6..d4fd06e 100644
--- a/sw/inc/SwStyleNameMapper.hxx
+++ b/sw/inc/SwStyleNameMapper.hxx
@@ -94,6 +94,7 @@ protected:
                            *m_pPageDescUINameArray,
                            *m_pNumRuleUINameArray,
                            *m_pTableStyleUINameArray,
                            *m_pCellStyleUINameArray,
    // Programmatic Name tables
                            *m_pTextProgNameArray,
                            *m_pListsProgNameArray,
@@ -106,7 +107,8 @@ protected:
                            *m_pHTMLChrFormatProgNameArray,
                            *m_pPageDescProgNameArray,
                            *m_pNumRuleProgNameArray,
                            *m_pTableStyleProgNameArray;
                            *m_pTableStyleProgNameArray,
                            *m_pCellStyleProgNameArray;

    static NameToIdHash     *m_pParaUIMap,
                            *m_pCharUIMap,
@@ -114,13 +116,15 @@ protected:
                            *m_pFrameUIMap,
                            *m_pNumRuleUIMap,
                            *m_pTableStyleUIMap,
                            *m_pCellStyleUIMap,

                            *m_pParaProgMap,
                            *m_pCharProgMap,
                            *m_pPageProgMap,
                            *m_pFrameProgMap,
                            *m_pNumRuleProgMap,
                            *m_pTableStyleProgMap;
                            *m_pTableStyleProgMap,
                            *m_pCellStyleProgMap;

    static void fillNameFromId(sal_uInt16 nId, OUString &rName, bool bProgName);
    static const OUString& getNameFromId(sal_uInt16 nId, const OUString &rName,
@@ -181,6 +185,7 @@ public:
    static const ::std::vector<OUString>& GetPageDescUINameArray();
    static const ::std::vector<OUString>& GetNumRuleUINameArray();
    static const ::std::vector<OUString>& GetTableStyleUINameArray();
    static const ::std::vector<OUString>& GetCellStyleUINameArray();

    static const ::std::vector<OUString>& GetTextProgNameArray();
    static const ::std::vector<OUString>& GetListsProgNameArray();
@@ -194,6 +199,7 @@ public:
    static const ::std::vector<OUString>& GetPageDescProgNameArray();
    static const ::std::vector<OUString>& GetNumRuleProgNameArray();
    static const ::std::vector<OUString>& GetTableStyleProgNameArray();
    static const ::std::vector<OUString>& GetCellStyleProgNameArray();
};
#endif // _NAME_MAPPER_HXX

diff --git a/sw/inc/docstyle.hxx b/sw/inc/docstyle.hxx
index 89a0745..56a7568 100644
--- a/sw/inc/docstyle.hxx
+++ b/sw/inc/docstyle.hxx
@@ -37,6 +37,7 @@ class SwTextFormatColl;
class SwFrameFormat;
class SwNumRule;
class SwTableAutoFormat;
class SwBoxAutoFormat;

// Temporary StyleSheet.
class SW_DLLPUBLIC SwDocStyleSheet : public SfxStyleSheetBase
@@ -50,6 +51,7 @@ class SW_DLLPUBLIC SwDocStyleSheet : public SfxStyleSheetBase
    const SwPageDesc*   pDesc;
    const SwNumRule*    pNumRule;
    const SwTableAutoFormat* pTableFormat;
    const SwBoxAutoFormat*   pBoxFormat;
    SwDoc&              rDoc;
    SfxItemSet          aCoreSet;

diff --git a/sw/inc/poolfmt.hxx b/sw/inc/poolfmt.hxx
index 6707c43..4c8958a 100644
--- a/sw/inc/poolfmt.hxx
+++ b/sw/inc/poolfmt.hxx
@@ -78,6 +78,7 @@ const sal_uInt16 POOLGRP_FRAMEFMT       = (1 << 11) + POOLGRP_NOCOLLID;
const sal_uInt16 POOLGRP_PAGEDESC       = (2 << 11) + POOLGRP_NOCOLLID;
const sal_uInt16 POOLGRP_NUMRULE        = (3 << 11) + POOLGRP_NOCOLLID;
const sal_uInt16 POOLGRP_TABSTYLE       = (4 << 11) + POOLGRP_NOCOLLID;
const sal_uInt16 POOLGRP_CELLSTYLE      = (5 << 11) + POOLGRP_NOCOLLID;

/// Recognize whether it's a user defined style or not:
const sal_uInt16 POOL_IDUSER_FMT =
@@ -222,6 +223,12 @@ RES_POOLTABLESTYLE_YELLOW,
RES_POOLTABSTYLE_END
};

enum RES_POOL_CELLSTYLE_TYPE
{
RES_POOLCELLSTYLE_BEGIN = POOLGRP_CELLSTYLE,
RES_POOLCELLSTYLE_END = RES_POOLCELLSTYLE_BEGIN
};

// IDs for paragraph styles.
enum RES_POOL_COLLFMT_TYPE
{
diff --git a/sw/inc/tblafmt.hxx b/sw/inc/tblafmt.hxx
index 5490dce..9e5f4a3 100644
--- a/sw/inc/tblafmt.hxx
+++ b/sw/inc/tblafmt.hxx
@@ -110,6 +110,8 @@ class SwBoxAutoFormat
    OUString            m_sNumFormatString;
    LanguageType        m_eSysLanguage, m_eNumFormatLanguage;

    css::uno::WeakReference<css::uno::XInterface> m_wXObject;

public:
    SwBoxAutoFormat();
    SwBoxAutoFormat( const SwBoxAutoFormat& rNew );
@@ -176,6 +178,11 @@ public:
    void SetValueFormat( const OUString& rFormat, LanguageType eLng, LanguageType eSys )
        { m_sNumFormatString = rFormat; m_eNumFormatLanguage = eLng; m_eSysLanguage = eSys; }

    css::uno::WeakReference<css::uno::XInterface> const& GetXObject() const
        { return m_wXObject; }
    void SetXObject(css::uno::Reference<css::uno::XInterface> const& xObject)
        { m_wXObject = xObject; }

    bool Load( SvStream& rStream, const SwAfVersions& rVersions, sal_uInt16 nVer );
    bool Save( SvStream& rStream, sal_uInt16 fileVersion ) const;
    bool SaveVersionNo( SvStream& rStream, sal_uInt16 fileVersion ) const;
@@ -300,6 +307,11 @@ public:
        { return m_wXObject; }
    void SetXObject(css::uno::Reference<css::uno::XInterface> const& xObject)
        { m_wXObject = xObject; }

    /// Returns the cell's name postfix. eg. ".1"
    OUString GetTableTemplateCellSubName(const SwBoxAutoFormat& rBoxFormat) const;
    /// Returns a vector of indexes in aBoxAutoFormat array. Returned indexes points to cells which are mapped to a table-template.
    static const std::vector<sal_Int32>& GetTableTemplateMap();
};

class SW_DLLPUBLIC SwTableAutoFormatTable
diff --git a/sw/inc/unocore.hrc b/sw/inc/unocore.hrc
index 9f8e8c6..ec63eb5 100644
--- a/sw/inc/unocore.hrc
+++ b/sw/inc/unocore.hrc
@@ -30,8 +30,9 @@
#define STR_STYLE_FAMILY_PAGE               (RC_UNOCORE_BEGIN + 6)
#define STR_STYLE_FAMILY_NUMBERING          (RC_UNOCORE_BEGIN + 7)
#define STR_STYLE_FAMILY_TABLE              (RC_UNOCORE_BEGIN + 8)
#define STR_STYLE_FAMILY_CELL               (RC_UNOCORE_BEGIN + 9)

#define UNOCORE_ACT_END                     STR_STYLE_FAMILY_TABLE
#define UNOCORE_ACT_END                     STR_STYLE_FAMILY_CELL

#if UNOCORE_ACT_END > RC_UNOCORE_END
#error Resource-Id Ueberlauf in #file, #line
diff --git a/sw/inc/unostyle.hxx b/sw/inc/unostyle.hxx
index 43e438d..8b7401a 100644
--- a/sw/inc/unostyle.hxx
+++ b/sw/inc/unostyle.hxx
@@ -312,12 +312,15 @@ class SwBoxAutoFormat;
class SwXTextCellStyle : public cppu::WeakImplHelper
<
    css::style::XStyle,
    css::beans::XPropertySet
    css::beans::XPropertySet,
    css::lang::XServiceInfo
>
{
    SwDocShell* m_pDocShell;
    SwBoxAutoFormat& m_rBoxAutoFormat;
    OUString m_sParentStyle;
public:
    SwXTextCellStyle(SwBoxAutoFormat& rBoxAutoFormat);
    SwXTextCellStyle(SwDocShell* pDocShell, SwBoxAutoFormat& rBoxAutoFormat, const OUString& sParentStyle);

    //XStyle
    virtual sal_Bool SAL_CALL isUserDefined() throw (css::uno::RuntimeException, std::exception) override;
@@ -338,6 +341,12 @@ public:
    virtual void SAL_CALL addVetoableChangeListener(const OUString& PropertyName, const css::uno::Reference<css::beans::XVetoableChangeListener>& aListener) throw(css::beans::UnknownPropertyException, css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) override;
    virtual void SAL_CALL removeVetoableChangeListener(const OUString& PropertyName, const css::uno::Reference<css::beans::XVetoableChangeListener>& aListener) throw(css::beans::UnknownPropertyException, css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) override;

    //XServiceInfo
    virtual OUString SAL_CALL getImplementationName() throw(css::uno::RuntimeException, std::exception) override;
    virtual sal_Bool SAL_CALL supportsService(const OUString& rServiceName) throw(css::uno::RuntimeException, std::exception) override;
    virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() throw(css::uno::RuntimeException, std::exception) override;

    static css::uno::Reference<css::style::XStyle> CreateXTextCellStyle(SwDocShell* pDocShell, const OUString& sName);
};
#endif

diff --git a/sw/qa/python/check_styles.py b/sw/qa/python/check_styles.py
index 31d8b5c..c435663 100644
--- a/sw/qa/python/check_styles.py
+++ b/sw/qa/python/check_styles.py
@@ -39,11 +39,11 @@ class CheckStyle(unittest.TestCase):
        self.assertFalse(xStyleFamilies.supportsService("foobarbaz"))
        self.assertTrue(xStyleFamilies.hasElements())
        self.assertRegex(str(xStyleFamilies.ElementType), "com\.sun\.star\.container\.XNameContainer")
        self.assertEqual(len(xStyleFamilies.ElementNames), 6)
        self.assertEqual(len(xStyleFamilies.ElementNames), 7)

        for sFamilyname in xStyleFamilies.ElementNames:
            self.assertIn(sFamilyname,
                          ["CharacterStyles", "ParagraphStyles", "PageStyles", "FrameStyles", "NumberingStyles", "TableStyles"])
                          ["CharacterStyles", "ParagraphStyles", "PageStyles", "FrameStyles", "NumberingStyles", "TableStyles", "CellStyles"])

        with self.assertRaises(NoSuchElementException):
            xStyleFamilies.getByName("foobarbaz")
@@ -183,6 +183,14 @@ class CheckStyle(unittest.TestCase):
                xCellStyle.getPropertyValue("foobarbaz")
        xDoc.dispose()

    def test_CellFamily(self):
        xDoc = CheckStyle._uno.openEmptyWriterDoc()
        xCellStyles = xDoc.StyleFamilies["CellStyles"]
        vEmptyDocStyles = ['Default Style.1', 'Default Style.2', 'Default Style.3', 'Default Style.4', 'Default Style.5', 'Default Style.6', 'Default Style.7', 'Default Style.8', 'Default Style.9', 'Default Style.10']
        self.__test_StyleFamily(xCellStyles, vEmptyDocStyles, "SwXTextCellStyle")
        #possibly more depth tests could be added, to test properties of a cell style... yet to come
        xDoc.dispose()

if __name__ == '__main__':
    unittest.main()

diff --git a/sw/source/core/doc/SwStyleNameMapper.cxx b/sw/source/core/doc/SwStyleNameMapper.cxx
index f644bbf..2cdd353 100644
--- a/sw/source/core/doc/SwStyleNameMapper.cxx
+++ b/sw/source/core/doc/SwStyleNameMapper.cxx
@@ -43,6 +43,7 @@ extern ResMgr* pSwResMgr;
                *SwStyleNameMapper::m_pPageDescUINameArray = nullptr,
                *SwStyleNameMapper::m_pNumRuleUINameArray = nullptr,
                *SwStyleNameMapper::m_pTableStyleUINameArray = nullptr,
                *SwStyleNameMapper::m_pCellStyleUINameArray = nullptr,

// Initialise programmatic names to 0
                *SwStyleNameMapper::m_pTextProgNameArray = nullptr,
@@ -56,7 +57,8 @@ extern ResMgr* pSwResMgr;
                *SwStyleNameMapper::m_pHTMLChrFormatProgNameArray = nullptr,
                *SwStyleNameMapper::m_pPageDescProgNameArray = nullptr,
                *SwStyleNameMapper::m_pNumRuleProgNameArray = nullptr,
                *SwStyleNameMapper::m_pTableStyleProgNameArray = nullptr;
                *SwStyleNameMapper::m_pTableStyleProgNameArray = nullptr,
                *SwStyleNameMapper::m_pCellStyleProgNameArray = nullptr;

NameToIdHash    *SwStyleNameMapper::m_pParaUIMap = nullptr,
                *SwStyleNameMapper::m_pCharUIMap = nullptr,
@@ -64,13 +66,15 @@ NameToIdHash    *SwStyleNameMapper::m_pParaUIMap = nullptr,
                *SwStyleNameMapper::m_pFrameUIMap = nullptr,
                *SwStyleNameMapper::m_pNumRuleUIMap = nullptr,
                *SwStyleNameMapper::m_pTableStyleUIMap = nullptr,
                *SwStyleNameMapper::m_pCellStyleUIMap = nullptr,

                *SwStyleNameMapper::m_pParaProgMap = nullptr,
                *SwStyleNameMapper::m_pCharProgMap = nullptr,
                *SwStyleNameMapper::m_pPageProgMap = nullptr,
                *SwStyleNameMapper::m_pFrameProgMap = nullptr,
                *SwStyleNameMapper::m_pNumRuleProgMap = nullptr,
                *SwStyleNameMapper::m_pTableStyleProgMap = nullptr;
                *SwStyleNameMapper::m_pTableStyleProgMap = nullptr,
                *SwStyleNameMapper::m_pCellStyleProgMap = nullptr;

// SwTableEntry so we can pass the length to the String CTOR
struct SwTableEntry
@@ -498,6 +502,12 @@ const NameToIdHash & SwStyleNameMapper::getHashTable ( SwGetPoolIdFromName eFlag
            vIndexes.push_back( std::make_tuple(RES_POOLTABSTYLE_BEGIN, RES_POOLTABSTYLE_END, bProgName ? &GetTableStyleProgNameArray : &GetTableStyleUINameArray) );
        }
        break;
        case nsSwGetPoolIdFromName::GET_POOLID_CELLSTYLE:
        {
            pHashPointer = bProgName ? &m_pCellStyleProgMap : &m_pCellStyleUIMap;
            vIndexes.push_back( std::make_tuple(RES_POOLCELLSTYLE_BEGIN, RES_POOLCELLSTYLE_END, bProgName ? &GetCellStyleProgNameArray : &GetCellStyleUINameArray) );
        }
        break;
        default:
            assert(false && "unknown pool family");
    }
@@ -855,6 +865,14 @@ const ::std::vector<OUString>& SwStyleNameMapper::GetTableStyleUINameArray()
    return *m_pTableStyleUINameArray;
}

/// retuns an empty array because Cell Names aren't translated
const ::std::vector<OUString>& SwStyleNameMapper::GetCellStyleUINameArray()
{
    if (!m_pCellStyleUINameArray)
        m_pCellStyleUINameArray = new std::vector<OUString>();
    return *m_pCellStyleUINameArray;
}

const ::std::vector<OUString>& SwStyleNameMapper::GetTextProgNameArray()
{
    if (!m_pTextProgNameArray)
@@ -951,6 +969,14 @@ const ::std::vector<OUString>& SwStyleNameMapper::GetTableStyleProgNameArray()
    return *m_pTableStyleProgNameArray;
}

/// retuns an empty array because Cell Names aren't translated
const ::std::vector<OUString>& SwStyleNameMapper::GetCellStyleProgNameArray()
{
    if (!m_pCellStyleProgNameArray)
        m_pCellStyleProgNameArray = new std::vector<OUString>();
    return *m_pCellStyleProgNameArray;
}

const OUString
SwStyleNameMapper::GetSpecialExtraProgName(const OUString& rExtraUIName)
{
diff --git a/sw/source/core/doc/tblafmt.cxx b/sw/source/core/doc/tblafmt.cxx
index 6c368a3..95088b7 100644
--- a/sw/source/core/doc/tblafmt.cxx
+++ b/sw/source/core/doc/tblafmt.cxx
@@ -1029,6 +1029,47 @@ bool SwTableAutoFormat::Save( SvStream& rStream, sal_uInt16 fileVersion ) const
    return bRet;
}

OUString SwTableAutoFormat::GetTableTemplateCellSubName(const SwBoxAutoFormat& rBoxFormat) const
{
    sal_Int32 nIndex = 0;
    for (; nIndex < 16; ++nIndex)
        if (aBoxAutoFormat[nIndex] == &rBoxFormat) break;

    // box format doesn't belong to this table format
    if (16 <= nIndex)
        return OUString();

    const std::vector<sal_Int32> aTableTemplateMap = GetTableTemplateMap();
    for (size_t i=0; i < aTableTemplateMap.size(); ++i)
    {
        if (aTableTemplateMap[i] == nIndex)
            return "." + OUString::number(i + 1);
    }

    // box format doesn't belong to a table template
    return OUString();
}

const std::vector<sal_Int32>& SwTableAutoFormat::GetTableTemplateMap()
{
    static std::vector<sal_Int32>* pTableTemplateMap;
    if (!pTableTemplateMap)
    {
        pTableTemplateMap = new std::vector<sal_Int32>;
        pTableTemplateMap->push_back(0); // FIRST_ROW
        pTableTemplateMap->push_back(1); // LAST_ROW
        pTableTemplateMap->push_back(2); // FIRST_COLUMN
        pTableTemplateMap->push_back(3); // LAST_COLUMN
        pTableTemplateMap->push_back(4); // EVEN_ROWS
        pTableTemplateMap->push_back(5); // ODD_ROWS
        pTableTemplateMap->push_back(6); // EVEN_COLUMNS
        pTableTemplateMap->push_back(7); // ODD_COLUMNS
        pTableTemplateMap->push_back(8); // BODY
        pTableTemplateMap->push_back(9); // BACKGROUND
    }
    return *pTableTemplateMap;
}

struct SwTableAutoFormatTable::Impl
{
    std::vector<std::unique_ptr<SwTableAutoFormat>> m_AutoFormats;
diff --git a/sw/source/core/unocore/unocore.src b/sw/source/core/unocore/unocore.src
index e9f3d61..adb0cd8 100644
--- a/sw/source/core/unocore/unocore.src
+++ b/sw/source/core/unocore/unocore.src
@@ -59,4 +59,9 @@ String STR_STYLE_FAMILY_TABLE
    Text [ en-US ] = "Table" ;
};

String STR_STYLE_FAMILY_CELL
{
    Text [ en-US ] = "Cell" ;
};

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/unocore/unostyle.cxx b/sw/source/core/unocore/unostyle.cxx
index 8ee3615..7f73a61 100644
--- a/sw/source/core/unocore/unostyle.cxx
+++ b/sw/source/core/unocore/unostyle.cxx
@@ -711,6 +711,14 @@ sal_Int32 lcl_GetCountOrName<SfxStyleFamily::Table>(const SwDoc& rDoc, OUString*
    return nCount;
}

template<>
sal_Int32 lcl_GetCountOrName<SfxStyleFamily::Cell>(const SwDoc& rDoc, OUString* /*pString*/, sal_Int32 /*nIndex*/)
{
    const auto pAutoFormats = &rDoc.GetTableStyles();
    const sal_Int32 nCount = pAutoFormats->size() * SwTableAutoFormat::GetTableTemplateMap().size();
    return nCount;
}

template<SfxStyleFamily eFamily>
static uno::Reference< css::style::XStyle> lcl_CreateStyle(SfxStyleSheetBasePool* pBasePool, SwDocShell* pDocShell, const OUString& sStyleName)
    { return pBasePool ? new SwXStyle(pBasePool, eFamily, pDocShell->GetDoc(), sStyleName) : new SwXStyle(pDocShell->GetDoc(), eFamily, false); };
@@ -730,6 +738,10 @@ template<>
uno::Reference< css::style::XStyle> lcl_CreateStyle<SfxStyleFamily::Table>(SfxStyleSheetBasePool* /*pBasePool*/, SwDocShell* pDocShell, const OUString& sStyleName)
    { return SwXTextTableStyle::CreateXTextTableStyle(pDocShell, sStyleName); };

template<>
uno::Reference< css::style::XStyle> lcl_CreateStyle<SfxStyleFamily::Cell>(SfxStyleSheetBasePool* /*pBasePool*/, SwDocShell* pDocShell, const OUString& sStyleName)
    { return SwXTextCellStyle::CreateXTextCellStyle(pDocShell, sStyleName); };

uno::Reference<css::style::XStyle> SwXStyleFamilies::CreateStyle(SfxStyleFamily eFamily, SwDoc& rDoc)
{
    auto pEntries(lcl_GetStyleFamilyEntries());
@@ -781,6 +793,12 @@ sal_uInt16 lcl_TranslateIndex<SfxStyleFamily::Table>(const sal_uInt16 nIndex)
    return nIndex;
}

template<>
sal_uInt16 lcl_TranslateIndex<SfxStyleFamily::Cell>(const sal_uInt16 nIndex)
{
    return nIndex;
}

template<sal_uInt16 nRangeBegin, sal_uInt16 nRangeSize>
static sal_uInt16 lcl_TranslateIndexRange(const sal_uInt16 nIndex)
{
@@ -976,7 +994,8 @@ static const std::vector<StyleFamilyEntry>* lcl_GetStyleFamilyEntries()
            { SfxStyleFamily::Page,   PROPERTY_MAP_PAGE_STYLE,  nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC, "PageStyles",      STR_STYLE_FAMILY_PAGE,      &lcl_GetCountOrName<SfxStyleFamily::Page>,   &lcl_CreateStyle<SfxStyleFamily::Page>,   &lcl_TranslateIndexRange<RES_POOLPAGE_BEGIN,    nPoolPageRange>  },
            { SfxStyleFamily::Frame,  PROPERTY_MAP_FRAME_STYLE, nsSwGetPoolIdFromName::GET_POOLID_FRMFMT,   "FrameStyles",     STR_STYLE_FAMILY_FRAME,     &lcl_GetCountOrName<SfxStyleFamily::Frame>,  &lcl_CreateStyle<SfxStyleFamily::Frame>,  &lcl_TranslateIndexRange<RES_POOLFRM_BEGIN,     nPoolFrameRange> },
            { SfxStyleFamily::Pseudo, PROPERTY_MAP_NUM_STYLE,   nsSwGetPoolIdFromName::GET_POOLID_NUMRULE,  "NumberingStyles", STR_STYLE_FAMILY_NUMBERING, &lcl_GetCountOrName<SfxStyleFamily::Pseudo>, &lcl_CreateStyle<SfxStyleFamily::Pseudo>, &lcl_TranslateIndexRange<RES_POOLNUMRULE_BEGIN, nPoolNumRange>   },
            { SfxStyleFamily::Table,  PROPERTY_MAP_TABLE_STYLE, nsSwGetPoolIdFromName::GET_POOLID_TABSTYLE, "TableStyles",     STR_STYLE_FAMILY_TABLE,     &lcl_GetCountOrName<SfxStyleFamily::Table>,  &lcl_CreateStyle<SfxStyleFamily::Table>,  &lcl_TranslateIndex<SfxStyleFamily::Table>                       }
            { SfxStyleFamily::Table,  PROPERTY_MAP_TABLE_STYLE, nsSwGetPoolIdFromName::GET_POOLID_TABSTYLE, "TableStyles",     STR_STYLE_FAMILY_TABLE,     &lcl_GetCountOrName<SfxStyleFamily::Table>,  &lcl_CreateStyle<SfxStyleFamily::Table>,  &lcl_TranslateIndex<SfxStyleFamily::Table>                       },
            { SfxStyleFamily::Cell,   PROPERTY_MAP_CELL_STYLE,  nsSwGetPoolIdFromName::GET_POOLID_CELLSTYLE,"CellStyles",      STR_STYLE_FAMILY_CELL,      &lcl_GetCountOrName<SfxStyleFamily::Cell>,   &lcl_CreateStyle<SfxStyleFamily::Cell>,   &lcl_TranslateIndex<SfxStyleFamily::Cell>                        }
       };
    }
    return our_pStyleFamilyEntries;
@@ -4245,17 +4264,19 @@ SwXTextTableStyle::SwXTextTableStyle(SwDocShell* pDocShell, const OUString& rTab

    if (pAutoFormat)
    {
        // TODO fix styles mapping
        m_aCellStyles[ FIRST_ROW_STYLE    ] = new SwXTextCellStyle(pAutoFormat->GetBoxFormat( 0 ));  // 0
        m_aCellStyles[ LAST_ROW_STYLE     ] = new SwXTextCellStyle(pAutoFormat->GetBoxFormat( 12 )); // 1
        m_aCellStyles[ FIRST_COLUMN_STYLE ] = new SwXTextCellStyle(pAutoFormat->GetBoxFormat( 4 ));  // 2
        m_aCellStyles[ LAST_COLUMN_STYLE  ] = new SwXTextCellStyle(pAutoFormat->GetBoxFormat( 7 ));  // 3
        m_aCellStyles[ EVEN_ROWS_STYLE    ] = new SwXTextCellStyle(pAutoFormat->GetBoxFormat( 13 )); // 4
        m_aCellStyles[ ODD_ROWS_STYLE     ] = new SwXTextCellStyle(pAutoFormat->GetBoxFormat( 13 )); // 5
        m_aCellStyles[ EVEN_COLUMNS_STYLE ] = new SwXTextCellStyle(pAutoFormat->GetBoxFormat( 13 )); // 6
        m_aCellStyles[ ODD_COLUMNS_STYLE  ] = new SwXTextCellStyle(pAutoFormat->GetBoxFormat( 13 )); // 7
        m_aCellStyles[ BODY_STYLE         ] = new SwXTextCellStyle(pAutoFormat->GetBoxFormat( 13 )); // 8
        m_aCellStyles[ BACKGROUND_STYLE   ] = new SwXTextCellStyle(pAutoFormat->GetBoxFormat( 13 )); // 9
        const std::vector<sal_Int32> aTableTemplateMap = SwTableAutoFormat::GetTableTemplateMap();
        assert(aTableTemplateMap.size() == STYLE_COUNT && "can not map SwTableAutoFormat to a SwXTextTableStyle");
        for (sal_Int32 i=0; i<STYLE_COUNT; ++i)
        {
            SwBoxAutoFormat& rBoxFormat = pAutoFormat->GetBoxFormat(aTableTemplateMap[i]);
            uno::Reference<style::XStyle> xCellStyle(rBoxFormat.GetXObject(), uno::UNO_QUERY);
            if (!xCellStyle.is())
            {
                xCellStyle.set(new SwXTextCellStyle(m_pDocShell, rBoxFormat, m_sTableAutoFormatName));
                rBoxFormat.SetXObject(xCellStyle);
            }
            m_aCellStyles[i] = xCellStyle;
        }
    }
}

@@ -4425,10 +4446,56 @@ css::uno::Sequence<OUString> SAL_CALL SwXTextTableStyle::getSupportedServiceName
}

// SwXTextCellStyle
SwXTextCellStyle::SwXTextCellStyle(SwBoxAutoFormat& rBoxAutoFormat) :
    m_rBoxAutoFormat(rBoxAutoFormat)
SwXTextCellStyle::SwXTextCellStyle(SwDocShell* pDocShell, SwBoxAutoFormat& rBoxAutoFormat, const OUString& sParentStyle) :
    m_pDocShell(pDocShell), m_rBoxAutoFormat(rBoxAutoFormat), m_sParentStyle(sParentStyle)
{ }

css::uno::Reference<css::style::XStyle> SwXTextCellStyle::CreateXTextCellStyle(SwDocShell* pDocShell, const OUString& sName)
{
    SwBoxAutoFormat* pBoxFormat = nullptr;
    sal_Int32 nSeparatorIndex;
    sal_uInt32 nTemplateIndex;
    OUString sParentName, sCellSubName;

    try {
        nSeparatorIndex = sName.lastIndexOf('.');
        sParentName = sName.copy(0, nSeparatorIndex);
        sCellSubName = sName.copy(nSeparatorIndex+1);
        nTemplateIndex = sCellSubName.toInt32()-1;      // -1 because cell styles names start from 1

        auto rTableTemplateMap = SwTableAutoFormat::GetTableTemplateMap();
        if (nTemplateIndex >= rTableTemplateMap.size())
            throw;

        SwTableAutoFormat* pFormat = pDocShell->GetDoc()->GetTableStyles().FindAutoFormat(sParentName);
        sal_uInt32 nBoxIndex = rTableTemplateMap[nTemplateIndex];
        pBoxFormat = &pFormat->GetBoxFormat(nBoxIndex);
    }
    catch (...)
    {
        SAL_WARN("sw.uno", "could not get a BoxFormat to create XTextCellStyle for, unexpected error");
    }

    if (!pBoxFormat)
    {
        // return a default-dummy style to prevent crash
        static SwBoxAutoFormat* pDefaultBoxFormat;
        if (!pDefaultBoxFormat)
            pDefaultBoxFormat = new SwBoxAutoFormat();
        pBoxFormat = pDefaultBoxFormat;
    }

    uno::Reference<style::XStyle> xTextCellStyle;
    xTextCellStyle.set(pBoxFormat->GetXObject(), uno::UNO_QUERY);
    if (!xTextCellStyle.is())
    {
        xTextCellStyle.set(new SwXTextCellStyle(pDocShell, *pBoxFormat, sParentName));
        pBoxFormat->SetXObject(xTextCellStyle);
    }

    return xTextCellStyle;
}

// XStyle
sal_Bool SAL_CALL SwXTextCellStyle::isUserDefined() throw (css::uno::RuntimeException, std::exception)
{
@@ -4442,16 +4509,26 @@ sal_Bool SAL_CALL SwXTextCellStyle::isInUse() throw (css::uno::RuntimeException,

OUString SAL_CALL SwXTextCellStyle::getParentStyle() throw (css::uno::RuntimeException, std::exception)
{
    return OUString();
    return m_sParentStyle;
}

void SAL_CALL SwXTextCellStyle::setParentStyle( const OUString& /*aParentStyle*/ ) throw (css::container::NoSuchElementException, css::uno::RuntimeException, std::exception)
{ }
void SAL_CALL SwXTextCellStyle::setParentStyle(const OUString& sParentStyle) throw (css::container::NoSuchElementException, css::uno::RuntimeException, std::exception)
{
    // Changing parent to one which is unaware of it will lead to a something unexcpected. getName() rely on a parent.
    SAL_INFO("sw.uno", "Changing SwXTextCellStyle parent");
    m_sParentStyle = sParentStyle;
}

//XNamed
OUString SAL_CALL SwXTextCellStyle::getName() throw(css::uno::RuntimeException, std::exception)
{
    return OUString();
    OUString sParentStyle;
    SwStyleNameMapper::FillUIName(m_sParentStyle, sParentStyle, nsSwGetPoolIdFromName::GET_POOLID_TABSTYLE, true);
    SwTableAutoFormat* pTableFormat = m_pDocShell->GetDoc()->GetTableStyles().FindAutoFormat(sParentStyle);
    if (!pTableFormat)
        return OUString();

    return sParentStyle + pTableFormat->GetTableTemplateCellSubName(m_rBoxAutoFormat);
}

void SAL_CALL SwXTextCellStyle::setName(const OUString& /*rName*/) throw(css::uno::RuntimeException, std::exception)
@@ -4532,4 +4609,20 @@ void SAL_CALL SwXTextCellStyle::removeVetoableChangeListener( const OUString& /*
    SAL_WARN("sw.uno", "not implemented");
}

//XServiceInfo
OUString SAL_CALL SwXTextCellStyle::getImplementationName() throw(css::uno::RuntimeException, std::exception)
{
    return {"SwXTextCellStyle"};
}

sal_Bool SAL_CALL SwXTextCellStyle::supportsService(const OUString& rServiceName) throw(css::uno::RuntimeException, std::exception)
{
    return cppu::supportsService(this, rServiceName);
}

css::uno::Sequence<OUString> SAL_CALL SwXTextCellStyle::getSupportedServiceNames() throw(css::uno::RuntimeException, std::exception)
{
    return {"com.sun.star.style.Style"};
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/app/docstyle.cxx b/sw/source/uibase/app/docstyle.cxx
index 82ecf65..277c222 100644
--- a/sw/source/uibase/app/docstyle.cxx
+++ b/sw/source/uibase/app/docstyle.cxx
@@ -77,6 +77,7 @@
#define cPAGE       (sal_Unicode)'g'
#define cNUMRULE    (sal_Unicode)'n'
#define cTABSTYLE   (sal_Unicode)'t'
#define cCELLSTYLE  (sal_Unicode)'b'

using namespace com::sun::star;

@@ -320,6 +321,40 @@ static const SwTableAutoFormat* lcl_FindTableStyle(SwDoc& rDoc, const OUString& 
    return pFormat;
}

static const SwBoxAutoFormat* lcl_FindCellStyle(SwDoc& rDoc, const OUString& rName, SwDocStyleSheet *pStyle = nullptr)
{
    const SwBoxAutoFormat* pFormat = nullptr;

    auto aTableTemplateMap = SwTableAutoFormat::GetTableTemplateMap();
    SwTableAutoFormatTable& rTableStyles = rDoc.GetTableStyles();
    for (size_t i=0; i < rTableStyles.size() && !pFormat; ++i)
    {
        const SwTableAutoFormat& rTableStyle = rTableStyles[i];
        for (size_t nBoxFormat=0; nBoxFormat < aTableTemplateMap.size() && !pFormat; ++nBoxFormat)
        {
                const sal_uInt32 nBoxIndex = aTableTemplateMap[nBoxFormat];
                const SwBoxAutoFormat& rBoxFormat = rTableStyle.GetBoxFormat(nBoxIndex);
                OUString sBoxFormatName;
                SwStyleNameMapper::FillProgName(rTableStyle.GetName(), sBoxFormatName, nsSwGetPoolIdFromName::GET_POOLID_CELLSTYLE, true);
                sBoxFormatName += rTableStyle.GetTableTemplateCellSubName(rBoxFormat);
                if (rName == sBoxFormatName)
                    pFormat = &rBoxFormat;
        }
    }

    if(pStyle)
    {
        if(pFormat)
        {
            pStyle->SetPhysical(true);
            pStyle->PresetParent(OUString());
        }
        else
            pStyle->SetPhysical(false);
    }
    return pFormat;
}

sal_uInt32 SwStyleSheetIterator::SwPoolFormatList::FindName(SfxStyleFamily eFam,
                                                         const OUString &rName)
{
@@ -346,6 +381,9 @@ sal_uInt32 SwStyleSheetIterator::SwPoolFormatList::FindName(SfxStyleFamily eFam,
        case SfxStyleFamily::Table:
            cStyle = cTABSTYLE;
            break;
        case SfxStyleFamily::Cell:
            cStyle = cCELLSTYLE;
            break;
        default:
            cStyle = ' ';
            break;
@@ -1945,6 +1983,11 @@ bool SwDocStyleSheet::FillStyleSheet(
        pTableFormat = lcl_FindTableStyle(rDoc, aName, this);
        bRet = bPhysical = (nullptr != pTableFormat);
        break;

    case SfxStyleFamily::Cell:
        pBoxFormat = lcl_FindCellStyle(rDoc, aName, this);
        bRet = bPhysical = (nullptr != pBoxFormat);
        break;
        default:; //prevent warning
    }

@@ -2529,6 +2572,9 @@ SfxStyleSheetBase* SwDocStyleSheetPool::Find( const OUString& rName,
            }
            break;

        case SfxStyleFamily::Table:
        case SfxStyleFamily::Cell:
            break;
        default:
            OSL_ENSURE(false, "unknown style family");
        }
@@ -2941,6 +2987,26 @@ SfxStyleSheetBase*  SwStyleSheetIterator::First()
        }
    }

    if( nSearchFamily == SfxStyleFamily::Cell ||
        nSearchFamily == SfxStyleFamily::All )
    {
        const std::vector<sal_Int32> aTableTemplateMap = SwTableAutoFormat::GetTableTemplateMap();
        const SwTableAutoFormatTable& rTableStyles = rDoc.GetTableStyles();
        for(size_t i = 0; i < rTableStyles.size(); ++i)
        {
            const SwTableAutoFormat& rTableStyle = rTableStyles[i];
            for(size_t nBoxFormat = 0; nBoxFormat < aTableTemplateMap.size(); ++nBoxFormat)
            {
                const sal_uInt32 nBoxIndex = aTableTemplateMap[nBoxFormat];
                const SwBoxAutoFormat& rBoxFormat = rTableStyle.GetBoxFormat(nBoxIndex);
                OUString sBoxFormatName;
                SwStyleNameMapper::FillProgName(rTableStyle.GetName(), sBoxFormatName, nsSwGetPoolIdFromName::GET_POOLID_CELLSTYLE, true);
                sBoxFormatName += rTableStyle.GetTableTemplateCellSubName(rBoxFormat);
                aLst.Append( cCELLSTYLE, sBoxFormatName );
            }
        }
    }

    if(!aLst.empty())
    {
        nLastPos = SAL_MAX_UINT32;