/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * The Contents of this file are made available subject to the terms of * either of the following licenses * * - GNU Lesser General Public License Version 2.1 * - Sun Industry Standards Source License Version 1.1 * * Sun Microsystems Inc., October, 2000 * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2000 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * * Sun Industry Standards Source License Version 1.1 * ================================================= * The contents of this file are subject to the Sun Industry Standards * Source License Version 1.1 (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.openoffice.org/license.html. * * Software provided under this License is provided on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. * See the License for the specific provisions governing your rights and * obligations concerning the Software. * * The Initial Developer of the Original Code is: IBM Corporation * * Copyright: 2008 by IBM Corporation * * All Rights Reserved. * * Contributor(s): _______________________________________ * * ************************************************************************/ /************************************************************************* * @file * LwpStory: 1. Word Pro object for paragraph list; 2. the content of layout object ************************************************************************/ #include #include "lwpstory.hxx" #include #include #include "lwppara.hxx" #include #include "lwppagelayout.hxx" #include #include #include LwpStory::LwpStory(LwpObjectHeader const &objHdr, LwpSvStream* pStrm) : LwpContent(objHdr, pStrm) , m_bPMModified(false) , m_pCurrentLayout(nullptr) , m_pTabLayout(nullptr) , m_bDropcap(false) , m_pHyperlinkMgr(new LwpHyperlinkMgr) { } LwpStory::~LwpStory() { } void LwpStory::Read() { LwpContent::Read(); m_ParaList.Read(m_pObjStrm.get()); m_FirstParaStyle.ReadIndexed(m_pObjStrm.get()); m_pObjStrm->SkipExtra(); } /************************************************************************** * @descr: Convert all the contents in current story **************************************************************************/ void LwpStory::XFConvert(XFContentContainer* pCont) { //process frame which anchor frame XFConvertFrameInFrame(pCont); //process para list XFContentContainer* pParaCont = pCont; rtl::Reference xPara(dynamic_cast(GetFirstPara().obj().get())); o3tl::sorted_vector aSeen; while (xPara.is()) { bool bAlreadySeen = !aSeen.insert(xPara.get()).second; if (bAlreadySeen) throw std::runtime_error("loop in conversion"); xPara->SetFoundry(m_pFoundry); xPara->XFConvert(pParaCont); //Get the xfcontainer for the next para pParaCont = xPara->GetXFContainer(); xPara.set(dynamic_cast(xPara->GetNext().obj().get())); } //process frame which anchor is to cell after converter all the para XFConvertFrameInCell(pCont); XFConvertFrameInHeaderFooter(pCont); //Release Lwp Objects rtl::Reference xCur(dynamic_cast(GetFirstPara().obj().get())); rtl::Reference xNext; while (xCur.is()) { xNext.set(dynamic_cast(xCur->GetNext().obj().get())); LwpGlobalMgr* pGlobal = LwpGlobalMgr::GetInstance(); LwpObjectFactory* pObjMgr = pGlobal->GetLwpObjFactory(); pObjMgr->ReleaseObject(xCur->GetObjectID()); xCur = xNext; } } void LwpStory::RegisterStyle() { rtl::Reference xPara(dynamic_cast(GetFirstPara().obj().get())); o3tl::sorted_vector aSeen; while (xPara.is()) { bool bAlreadySeen = !aSeen.insert(xPara.get()).second; if (bAlreadySeen) throw std::runtime_error("loop in register style"); xPara->SetFoundry(m_pFoundry); xPara->DoRegisterStyle(); xPara.set(dynamic_cast(xPara->GetNext().obj().get())); } } void LwpStory::Parse(IXFStream* pOutputStream) { m_xXFContainer.set(new XFContentContainer); XFConvert(m_xXFContainer.get()); m_xXFContainer->ToXml(pOutputStream); m_xXFContainer.clear(); } /************************************************************************** * @descr: Set current page layout. If pPageLayout is a mirror page layout, use odd child page layout as current page layout. **************************************************************************/ void LwpStory::SetCurrentLayout(LwpPageLayout *pPageLayout) { LwpPageLayout* pLayout = pPageLayout->GetOddChildLayout(); if(pLayout) { m_pCurrentLayout = pLayout; m_pTabLayout = pLayout; } else { m_pCurrentLayout = pPageLayout; m_pTabLayout = pPageLayout; } m_bPMModified = true; } /************************************************************************** * @descr: Get the next page layout relative to m_pCurrentLayout **************************************************************************/ LwpPageLayout* LwpStory::GetNextPageLayout() { std::vector::iterator it = std::find(m_LayoutList.begin(), m_LayoutList.end(), m_pCurrentLayout); if (it != m_LayoutList.end() && (it+1) != m_LayoutList.end()) return *(it+1); return nullptr; } /************************************************************************** * @descr: Sort the pagelayout according to their position **************************************************************************/ void LwpStory::SortPageLayout() { //Get all the pagelayout and store in list std::vector aLayoutList; rtl::Reference xLayout(GetLayout(nullptr)); while (xLayout) { LwpPageLayout *pLayout = xLayout->IsPage() ? dynamic_cast(xLayout.get()) : nullptr; if (pLayout) { LwpLayout::UseWhenType eSectionType = pLayout->GetUseWhenType(); //for mirror page, the child is pagelayout rtl::Reference xParent = xLayout->GetParentLayout(); if(eSectionType != LwpLayout::StartWithinColume && xParent.is() && !xParent->IsPage()) { aLayoutList.push_back(pLayout); } } xLayout = GetLayout(xLayout.get()); } // sort the pagelayout according to their position if (!aLayoutList.empty()) { for( std::vector::iterator aIt = aLayoutList.begin(); aIt != aLayoutList.end() -1; ++aIt) { for( std::vector::iterator bIt = aIt +1; bIt != aLayoutList.end(); ++bIt ) { if(!(**aIt < **bIt)) { std::swap(*aIt, *bIt); } } } } //put all the sorted layouts into list m_LayoutList.clear(); for (auto const& layout : aLayoutList) { m_LayoutList.push_back(layout); } } /************************************************************************** * @descr: whether need create a new section and reset column in current page layout **************************************************************************/ bool LwpStory::IsNeedSection() { bool bNewSection = false; if(m_pCurrentLayout) { if(m_pCurrentLayout->HasColumns()) { //get the following pagelayout and its type bool bColumns = true; LwpPageLayout* pNextLayout = GetNextPageLayout(); if(pNextLayout) { //get layout type LwpLayout::UseWhenType eWhenType = pNextLayout->GetUseWhenType(); switch(eWhenType) { case LwpLayout::StartWithinColume://not support now case LwpLayout::StartWithinPage: { bColumns =false; bNewSection = true; break; } case LwpLayout::StartOnNextPage: case LwpLayout::StartOnOddPage://not support now case LwpLayout::StartOnEvenPage://not support now { bColumns =true; bNewSection = false; break; } default: break; } } //if bColumns is true, the page layout doesn't need columns, set the xfcolumns to NULL in page master if(!bColumns) { m_pCurrentLayout->ResetXFColumns(); } } SetPMModified(false); } return bNewSection; } /************************************************************************** * @descr: process frame which anchor type is to cell **************************************************************************/ void LwpStory::XFConvertFrameInCell(XFContentContainer* pCont) { rtl::Reference xLayout(GetLayout(nullptr)); while (xLayout.is()) { rtl::Reference xFrameLayout(dynamic_cast(xLayout->GetChildHead().obj().get())); while (xFrameLayout.is()) { if (xFrameLayout->IsAnchorCell() && xFrameLayout->HasContent()) { //get the first xfpara rtl::Reference first( pCont->FindFirstContent(enumXFContentPara)); XFContentContainer* pXFFirtPara = static_cast(first.get()); if(pXFFirtPara) xFrameLayout->DoXFConvert(pXFFirtPara); } xFrameLayout.set(dynamic_cast(xFrameLayout->GetNext().obj().get())); } xLayout = GetLayout(xLayout.get()); } } /************************************************************************** * @descr: process frame which anchor type is to page **************************************************************************/ void LwpStory::XFConvertFrameInPage(XFContentContainer* pCont) { rtl::Reference xLayout(GetLayout(nullptr)); while (xLayout.is()) { rtl::Reference xFrameLayout(dynamic_cast(xLayout->GetChildHead().obj().get())); o3tl::sorted_vector aSeen; while (xFrameLayout.is()) { bool bAlreadySeen = !aSeen.insert(xFrameLayout.get()).second; if (bAlreadySeen) throw std::runtime_error("loop in conversion"); if( xFrameLayout->IsAnchorPage() && (xFrameLayout->IsFrame() || xFrameLayout->IsSuperTable() || xFrameLayout->IsGroupHead()) ) { xFrameLayout->DoXFConvert(pCont); } xFrameLayout.set(dynamic_cast(xFrameLayout->GetNext().obj().get())); } xLayout = GetLayout(xLayout.get()); } } /************************************************************************** * @descr: process frame which anchor type is to frame **************************************************************************/ void LwpStory::XFConvertFrameInFrame(XFContentContainer* pCont) { rtl::Reference xLayout(GetLayout(nullptr)); while (xLayout) { rtl::Reference xFrameLayout(dynamic_cast(xLayout->GetChildHead().obj().get())); o3tl::sorted_vector aSeen; while (xFrameLayout.is()) { bool bAlreadySeen = !aSeen.insert(xFrameLayout.get()).second; if (bAlreadySeen) throw std::runtime_error("loop in register style"); if (xFrameLayout->IsAnchorFrame()) { xFrameLayout->DoXFConvert(pCont); } xFrameLayout.set(dynamic_cast(xFrameLayout->GetNext().obj().get())); } xLayout = GetLayout(xLayout.get()); } } /************************************************************************** * @descr: process frame which anchor type is to page and the frame is contained by header or footer **************************************************************************/ void LwpStory::XFConvertFrameInHeaderFooter(XFContentContainer* pCont) { rtl::Reference xLayout(GetLayout(nullptr)); while (xLayout.is()) { rtl::Reference xFrameLayout(dynamic_cast(xLayout->GetChildHead().obj().get())); while (xFrameLayout.is()) { if (xFrameLayout->IsAnchorPage() && (xLayout->IsHeader() || xLayout->IsFooter())) { //The frame must be included by rtl::Reference first( pCont->FindFirstContent(enumXFContentPara)); XFContentContainer* pXFFirtPara = static_cast(first.get()); if(pXFFirtPara) xFrameLayout->DoXFConvert(pXFFirtPara); } xFrameLayout.set(dynamic_cast(xFrameLayout->GetNext().obj().get())); } xLayout = GetLayout(xLayout.get()); } } void LwpStory::AddXFContent(XFContent* pContent) { if (m_xXFContainer) m_xXFContainer->Add(pContent); } XFContentContainer* LwpStory::GetXFContent() { return m_xXFContainer.get(); } LwpPara* LwpStory::GetLastParaOfPreviousStory() { rtl::Reference xVLayout(GetLayout(nullptr)); if (xVLayout.is()) { return xVLayout->GetLastParaOfPreviousStory(); } return nullptr; } /************************************************************************** * @descr: get text from story **************************************************************************/ OUString LwpStory::GetContentText(bool bAllText) { if (bAllText)//convert all text fribs { OUStringBuffer sText; //process para list LwpPara* pPara = dynamic_cast(GetFirstPara().obj().get()); while (pPara) { pPara->SetFoundry(m_pFoundry); sText.append(pPara->GetContentText(true)); pPara = dynamic_cast(pPara->GetNext().obj().get()); } return sText.makeStringAndClear(); } else //only the first text frib { rtl::Reference pObj = GetFirstPara().obj(); if(pObj.is()) { LwpPara* pPara = dynamic_cast(pObj.get()); if (!pPara || pPara->GetNext().obj() != nullptr) return OUString(); pPara->SetFoundry(m_pFoundry); return pPara->GetContentText(); } return OUString(); } } OUString LwpStory::RegisterFirstFribStyle() { LwpPara* pPara = dynamic_cast(GetFirstPara().obj().get()); if (!pPara) return OUString(); pPara->SetFoundry(m_pFoundry); LwpFribPtr& rFribs = pPara->GetFribs(); LwpFrib* pFirstFrib = rFribs.GetFribs(); pFirstFrib->RegisterStyle(m_pFoundry); XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager(); XFTextStyle* pBaseStyle = pXFStyleManager->FindTextStyle(pFirstFrib->GetStyleName()); if (pBaseStyle == nullptr) return OUString(); std::unique_ptr pStyle(new XFTextStyle); *pStyle = *pBaseStyle; OUString sName = "Ruby" + pFirstFrib->GetStyleName(); pStyle->SetStyleName(sName); pXFStyleManager->AddStyle(std::move(pStyle)); return sName; } bool LwpStory::IsBullStyleUsedBefore(const OUString& rStyleName, sal_uInt8 nPos) { return std::any_of(m_vBulletStyleNameList.rbegin(), m_vBulletStyleNameList.rend(), [&rStyleName, &nPos](const NamePosPair& rPair) { return rPair.first == rStyleName && rPair.second == nPos; }); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */