LCOV - code coverage report
Current view: top level - sw/source/filter/ww8 - ww8par2.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1638 2135 76.7 %
Date: 2015-06-13 12:38:46 Functions: 97 115 84.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <sal/config.h>
      21             : 
      22             : #include <boost/noncopyable.hpp>
      23             : #include <boost/scoped_ptr.hpp>
      24             : #include <comphelper/string.hxx>
      25             : #include <tools/solar.h>
      26             : #include <vcl/vclenum.hxx>
      27             : #include <vcl/font.hxx>
      28             : #include <hintids.hxx>
      29             : #include <editeng/colritem.hxx>
      30             : #include <editeng/orphitem.hxx>
      31             : #include <editeng/widwitem.hxx>
      32             : #include <editeng/brushitem.hxx>
      33             : #include <editeng/boxitem.hxx>
      34             : #include <editeng/lrspitem.hxx>
      35             : #include <editeng/ulspitem.hxx>
      36             : #include <editeng/fhgtitem.hxx>
      37             : #include <editeng/hyphenzoneitem.hxx>
      38             : #include <editeng/frmdiritem.hxx>
      39             : #include <editeng/langitem.hxx>
      40             : #include <editeng/charrotateitem.hxx>
      41             : #include <editeng/pgrditem.hxx>
      42             : #include <msfilter.hxx>
      43             : #include <pam.hxx>
      44             : #include <doc.hxx>
      45             : #include <IDocumentStylePoolAccess.hxx>
      46             : #include <docary.hxx>
      47             : #include <ndtxt.hxx>
      48             : #include <paratr.hxx>
      49             : #include <poolfmt.hxx>
      50             : #include <swtable.hxx>
      51             : #include <tblsel.hxx>
      52             : #include <mdiexp.hxx>
      53             : #include <fmtpdsc.hxx>
      54             : #include <txtftn.hxx>
      55             : #include <frmfmt.hxx>
      56             : #include <ftnidx.hxx>
      57             : #include <fmtftn.hxx>
      58             : #include <charfmt.hxx>
      59             : #include <SwStyleNameMapper.hxx>
      60             : #include <fltshell.hxx>
      61             : #include <fmtanchr.hxx>
      62             : #include <fmtrowsplt.hxx>
      63             : #include <fmtfollowtextflow.hxx>
      64             : #include <numrule.hxx>
      65             : #include <sprmids.hxx>
      66             : #include <wwstyles.hxx>
      67             : #include "writerhelper.hxx"
      68             : #include "ww8struc.hxx"
      69             : #include "ww8par.hxx"
      70             : #include "ww8par2.hxx"
      71             : 
      72             : #include <frmatr.hxx>
      73             : 
      74             : #include <iostream>
      75             : 
      76             : using namespace ::com::sun::star;
      77             : 
      78          12 : class WW8SelBoxInfo
      79             :     : public std::vector<SwTableBox*>, private boost::noncopyable
      80             : {
      81             : public:
      82             :     short nGroupXStart;
      83             :     short nGroupWidth;
      84             :     bool bGroupLocked;
      85             : 
      86          12 :     WW8SelBoxInfo(short nXCenter, short nWidth)
      87          12 :         : nGroupXStart( nXCenter ), nGroupWidth( nWidth ), bGroupLocked(false)
      88          12 :     {}
      89             : };
      90             : 
      91             : typedef boost::ptr_vector<WW8SelBoxInfo> WW8MergeGroups;
      92             : 
      93        2222 : WW8TabBandDesc::WW8TabBandDesc()
      94             : {
      95        2222 :     memset(this, 0, sizeof(*this));
      96      146652 :     for (size_t i = 0; i < sizeof(maDirections)/sizeof(sal_uInt16); ++i)
      97      144430 :         maDirections[i] = 4;
      98        2222 : }
      99             : 
     100        2222 : WW8TabBandDesc::~WW8TabBandDesc()
     101             : {
     102        2222 :     delete[] pTCs;
     103        2222 :     delete[] pSHDs;
     104        2222 :     delete[] pNewSHDs;
     105        2222 : }
     106             : 
     107             : class WW8TabDesc: private boost::noncopyable
     108             : {
     109             :     std::vector<OUString> aNumRuleNames;
     110             :     sw::util::RedlineStack *mpOldRedlineStack;
     111             : 
     112             :     SwWW8ImplReader* pIo;
     113             : 
     114             :     WW8TabBandDesc* pFirstBand;
     115             :     WW8TabBandDesc* pActBand;
     116             : 
     117             :     SwPosition* pTmpPos;
     118             : 
     119             :     SwTableNode* pTableNd;            // table node
     120             :     const SwTableLines* pTabLines;  // row array of node
     121             :     SwTableLine* pTabLine;          // current row
     122             :     SwTableBoxes* pTabBoxes;        // boxes array in current row
     123             :     SwTableBox* pTabBox;            // current cell
     124             : 
     125             :     WW8MergeGroups aMergeGroups;   // list of all cells to be merged
     126             : 
     127             :     WW8_TCell* pAktWWCell;
     128             : 
     129             :     short nRows;
     130             :     short nDefaultSwCols;
     131             :     short nBands;
     132             :     short nMinLeft;
     133             :     short nConvertedLeft;
     134             :     short nMaxRight;
     135             :     short nSwWidth;
     136             :     short nPreferredWidth;
     137             :     short nOrgDxaLeft;
     138             : 
     139             :     bool bOk;
     140             :     bool bClaimLineFormat;
     141             :     sal_Int16 eOri;
     142             :     bool bIsBiDi;
     143             :                                 // 2. common admin info
     144             :     short nAktRow;
     145             :     short nAktBandRow;          // SW: row of current band
     146             :                                 // 3. admin info for writer
     147             :     short nAktCol;
     148             : 
     149             :     sal_uInt16 nRowsToRepeat;
     150             : 
     151             :     // 4. methods
     152             : 
     153             :     sal_uInt16 GetLogicalWWCol() const;
     154             :     void SetTabBorders( SwTableBox* pBox, short nIdx );
     155             :     void SetTabShades( SwTableBox* pBox, short nWwIdx );
     156             :     void SetTabVertAlign( SwTableBox* pBox, short nWwIdx );
     157             :     void SetTabDirection( SwTableBox* pBox, short nWwIdx );
     158             :     void CalcDefaults();
     159             :     bool SetPamInCell(short nWwCol, bool bPam);
     160             :     void InsertCells( short nIns );
     161             :     void AdjustNewBand();
     162             : 
     163             :     WW8SelBoxInfo* FindMergeGroup(short nX1, short nWidth, bool bExact);
     164             : 
     165             :     // single box - maybe used in a merge group
     166             :     // (the merge groups are processed later at once)
     167             :     SwTableBox* UpdateTableMergeGroup(WW8_TCell& rCell,
     168             :         WW8SelBoxInfo* pActGroup, SwTableBox* pActBox, sal_uInt16 nCol  );
     169             :     void StartMiserableHackForUnsupportedDirection(short nWwCol);
     170             :     void EndMiserableHackForUnsupportedDirection(short nWwCol);
     171             : 
     172             : public:
     173             :     const SwTable* pTable;          // table
     174             :     SwPosition* pParentPos;
     175             :     SwFlyFrameFormat* pFlyFormat;
     176             :     SfxItemSet aItemSet;
     177             :     bool IsValidCell(short nCol) const;
     178             :     bool InFirstParaInCell() const;
     179             : 
     180             :     WW8TabDesc( SwWW8ImplReader* pIoClass, WW8_CP nStartCp );
     181          74 :     bool Ok() const { return bOk; }
     182             :     void CreateSwTable(SvxULSpaceItem* pULSpaceItem = 0);
     183             :     void UseSwTable();
     184             :     void SetSizePosition(SwFrameFormat* pFrameFormat);
     185             :     void TableCellEnd();
     186             :     void MoveOutsideTable();
     187             :     void ParkPaM();
     188             :     void FinishSwTable();
     189             :     void MergeCells();
     190          47 :     short GetMinLeft() const { return nConvertedLeft; }
     191             :     ~WW8TabDesc();
     192             : 
     193        1742 :     const WW8_TCell* GetAktWWCell() const { return pAktWWCell; }
     194        3923 :     short GetAktCol() const { return nAktCol; }
     195             :     // find name of numrule valid for current WW-COL
     196             :     OUString GetNumRuleName() const;
     197             :     void SetNumRuleName( const OUString& rName );
     198             : 
     199           0 :     sw::util::RedlineStack* getOldRedlineStack(){ return mpOldRedlineStack; }
     200             : };
     201             : 
     202           5 : void sw::util::RedlineStack::close( const SwPosition& rPos,
     203             :     RedlineType_t eType, WW8TabDesc* pTabDesc )
     204             : {
     205             :     // If the redline type is not found in the redline stack, we have to check if there has been
     206             :     // a tabledesc and to check its saved redline stack, too. (#136939, #i68139)
     207           5 :     if( !close( rPos, eType ) )
     208             :     {
     209           0 :         if( pTabDesc && pTabDesc->getOldRedlineStack() )
     210             :         {
     211             :             bool const bResult =
     212           0 :                 pTabDesc->getOldRedlineStack()->close(rPos, eType);
     213             :             OSL_ENSURE( bResult, "close without open!");
     214             :             (void) bResult; // unused in non-debug
     215             :         }
     216             :     }
     217           5 : }
     218             : 
     219           1 : void wwSectionManager::SetCurrentSectionHasFootnote()
     220             : {
     221             :     OSL_ENSURE(!maSegments.empty(),
     222             :         "should not be possible, must be at least one segment");
     223           1 :     if (!maSegments.empty())
     224           1 :         maSegments.back().mbHasFootnote = true;
     225           1 : }
     226             : 
     227         133 : bool wwSectionManager::CurrentSectionIsVertical() const
     228             : {
     229             :     OSL_ENSURE(!maSegments.empty(),
     230             :         "should not be possible, must be at least one segment");
     231         133 :     if (!maSegments.empty())
     232         133 :         return maSegments.back().IsVertical();
     233           0 :     return false;
     234             : }
     235             : 
     236           0 : bool wwSectionManager::CurrentSectionIsProtected() const
     237             : {
     238             :     OSL_ENSURE(!maSegments.empty(),
     239             :         "should not be possible, must be at least one segment");
     240           0 :     if (!maSegments.empty())
     241           0 :         return SectionIsProtected(maSegments.back());
     242           0 :     return false;
     243             : }
     244             : 
     245          22 : sal_uInt32 wwSectionManager::GetPageLeft() const
     246             : {
     247          22 :     return !maSegments.empty() ? maSegments.back().nPgLeft : 0;
     248             : }
     249             : 
     250          10 : sal_uInt32 wwSectionManager::GetPageRight() const
     251             : {
     252          10 :     return !maSegments.empty() ? maSegments.back().nPgRight : 0;
     253             : }
     254             : 
     255          10 : sal_uInt32 wwSectionManager::GetPageWidth() const
     256             : {
     257          10 :     return !maSegments.empty() ? maSegments.back().GetPageWidth() : 0;
     258             : }
     259             : 
     260        1865 : sal_uInt32 wwSectionManager::GetTextAreaWidth() const
     261             : {
     262        1865 :     return !maSegments.empty() ? maSegments.back().GetTextAreaWidth() : 0;
     263             : }
     264             : 
     265          12 : sal_uInt32 wwSectionManager::GetWWPageTopMargin() const
     266             : {
     267          12 :     return !maSegments.empty() ? maSegments.back().maSep.dyaTop : 0;
     268             : }
     269             : 
     270           1 : sal_uInt16 SwWW8ImplReader::End_Footnote()
     271             : {
     272             :     /*
     273             :     Ignoring Footnote outside of the normal Text. People will put footnotes
     274             :     into field results and field commands.
     275             :     */
     276           2 :     if (m_bIgnoreText ||
     277           1 :         m_pPaM->GetPoint()->nNode < m_rDoc.GetNodes().GetEndOfExtras().GetIndex())
     278             :     {
     279           0 :         return 0;
     280             :     }
     281             : 
     282             :     OSL_ENSURE(!m_aFootnoteStack.empty(), "footnote end without start");
     283           1 :     if (m_aFootnoteStack.empty())
     284           0 :         return 0;
     285             : 
     286           1 :     bool bFtEdOk = false;
     287           1 :     const FootnoteDescriptor &rDesc = m_aFootnoteStack.back();
     288             : 
     289             :     //Get the footnote character and remove it from the txtnode. We'll
     290             :     //replace it with the footnote
     291           1 :     SwTextNode* pText = m_pPaM->GetNode().GetTextNode();
     292           1 :     sal_Int32 nPos = m_pPaM->GetPoint()->nContent.GetIndex();
     293             : 
     294           1 :     OUString sChar;
     295           1 :     SwTextAttr* pFN = 0;
     296             :     //There should have been a footnote char, we will replace this.
     297           1 :     if (pText && nPos)
     298             :     {
     299           1 :         sChar += OUString(pText->GetText()[--nPos]);
     300           1 :         m_pPaM->SetMark();
     301           1 :         --m_pPaM->GetMark()->nContent;
     302           1 :         m_rDoc.getIDocumentContentOperations().DeleteRange( *m_pPaM );
     303           1 :         m_pPaM->DeleteMark();
     304           1 :         SwFormatFootnote aFootnote(rDesc.meType == MAN_EDN);
     305           1 :         pFN = pText->InsertItem(aFootnote, nPos, nPos);
     306             :     }
     307             :     OSL_ENSURE(pFN, "Probleme beim Anlegen des Fussnoten-Textes");
     308           1 :     if (pFN)
     309             :     {
     310             : 
     311           1 :         SwPosition aTmpPos( *m_pPaM->GetPoint() );    // remember old cursor position
     312           1 :         WW8PLCFxSaveAll aSave;
     313           1 :         m_pPlcxMan->SaveAllPLCFx( aSave );
     314           1 :         WW8PLCFMan* pOldPlcxMan = m_pPlcxMan;
     315             : 
     316           1 :         const SwNodeIndex* pSttIdx = static_cast<SwTextFootnote*>(pFN)->GetStartNode();
     317             :         OSL_ENSURE(pSttIdx, "Probleme beim Anlegen des Fussnoten-Textes");
     318             : 
     319           1 :         static_cast<SwTextFootnote*>(pFN)->SetSeqNo( m_rDoc.GetFootnoteIdxs().size() );
     320             : 
     321           1 :         bool bOld = m_bFootnoteEdn;
     322           1 :         m_bFootnoteEdn = true;
     323             : 
     324             :         // read content of Ft-/End-Note
     325           1 :         Read_HdFtFootnoteText( pSttIdx, rDesc.mnStartCp, rDesc.mnLen, rDesc.meType);
     326           1 :         bFtEdOk = true;
     327           1 :         m_bFootnoteEdn = bOld;
     328             : 
     329             :         OSL_ENSURE(sChar.getLength()==1 && ((rDesc.mbAutoNum == (sChar[0] == 2))),
     330             :          "footnote autonumbering must be 0x02, and everything else must not be");
     331             : 
     332             :         // If no automatic numbering use the following char from the main text
     333             :         // as the footnote number
     334           1 :         if (!rDesc.mbAutoNum)
     335           0 :             static_cast<SwTextFootnote*>(pFN)->SetNumber(0, sChar);
     336             : 
     337             :         /*
     338             :             Delete the footnote char from the footnote if its at the beginning
     339             :             as usual. Might not be if the user has already deleted it, e.g.
     340             :             #i14737#
     341             :         */
     342           1 :         SwNodeIndex& rNIdx = m_pPaM->GetPoint()->nNode;
     343           1 :         rNIdx = pSttIdx->GetIndex() + 1;
     344           1 :         SwTextNode* pTNd = rNIdx.GetNode().GetTextNode();
     345           1 :         if (pTNd && !pTNd->GetText().isEmpty() && !sChar.isEmpty())
     346             :         {
     347           1 :             const OUString &rText = pTNd->GetText();
     348           1 :             if (rText[0] == sChar[0])
     349             :             {
     350           1 :                 m_pPaM->GetPoint()->nContent.Assign( pTNd, 0 );
     351           1 :                 m_pPaM->SetMark();
     352             :                 // Strip out tabs we may have inserted on export #i24762#
     353           1 :                 if (rText.getLength() > 1 && rText[1] == 0x09)
     354           1 :                     ++m_pPaM->GetMark()->nContent;
     355           1 :                 ++m_pPaM->GetMark()->nContent;
     356           1 :                 m_pReffingStck->Delete(*m_pPaM);
     357           1 :                 m_rDoc.getIDocumentContentOperations().DeleteRange( *m_pPaM );
     358           1 :                 m_pPaM->DeleteMark();
     359             :             }
     360             :         }
     361             : 
     362           1 :         *m_pPaM->GetPoint() = aTmpPos;        // restore Cursor
     363             : 
     364           1 :         m_pPlcxMan = pOldPlcxMan;             // Restore attributes
     365           1 :         m_pPlcxMan->RestoreAllPLCFx( aSave );
     366             :     }
     367             : 
     368           1 :     if (bFtEdOk)
     369           1 :         m_aSectionManager.SetCurrentSectionHasFootnote();
     370             : 
     371           1 :     m_aFootnoteStack.pop_back();
     372           1 :     return 0;
     373             : }
     374             : 
     375           1 : long SwWW8ImplReader::Read_Footnote(WW8PLCFManResult* pRes)
     376             : {
     377             :     /*
     378             :     Ignoring Footnote outside of the normal Text. People will put footnotes
     379             :     into field results and field commands.
     380             :     */
     381           2 :     if (m_bIgnoreText ||
     382           1 :         m_pPaM->GetPoint()->nNode < m_rDoc.GetNodes().GetEndOfExtras().GetIndex())
     383             :     {
     384           0 :         return 0;
     385             :     }
     386             : 
     387             :     FootnoteDescriptor aDesc;
     388           1 :     aDesc.mbAutoNum = true;
     389           1 :     if (eEDN == pRes->nSprmId)
     390             :     {
     391           0 :         aDesc.meType = MAN_EDN;
     392           0 :         if (m_pPlcxMan->GetEdn())
     393           0 :             aDesc.mbAutoNum = 0 != *static_cast<short const *>(m_pPlcxMan->GetEdn()->GetData());
     394             :     }
     395             :     else
     396             :     {
     397           1 :         aDesc.meType = MAN_FTN;
     398           1 :         if (m_pPlcxMan->GetFootnote())
     399           1 :             aDesc.mbAutoNum = 0 != *static_cast<short const *>(m_pPlcxMan->GetFootnote()->GetData());
     400             :     }
     401             : 
     402           1 :     aDesc.mnStartCp = pRes->nCp2OrIdx;
     403           1 :     aDesc.mnLen = pRes->nMemLen;
     404             : 
     405           1 :     m_aFootnoteStack.push_back(aDesc);
     406             : 
     407           1 :     return 0;
     408             : }
     409             : 
     410        2163 : bool SwWW8ImplReader::SearchRowEnd(WW8PLCFx_Cp_FKP* pPap, WW8_CP &rStartCp,
     411             :     int nLevel) const
     412             : {
     413        2163 :     WW8PLCFxDesc aRes;
     414        2163 :     aRes.pMemPos = 0;
     415        2163 :     aRes.nEndPos = rStartCp;
     416             : 
     417       23018 :     while (pPap->HasFkp() && rStartCp != WW8_CP_MAX)
     418             :     {
     419       20854 :         if (pPap->Where() != WW8_CP_MAX)
     420             :         {
     421       20854 :             const sal_uInt8* pB = pPap->HasSprm(TabRowSprm(nLevel));
     422       20854 :             if (pB && *pB == 1)
     423             :             {
     424        2225 :                 const sal_uInt8 *pLevel = 0;
     425        2225 :                 if (0 != (pLevel = pPap->HasSprm(0x6649)))
     426             :                 {
     427        2225 :                     if (nLevel + 1 == *pLevel)
     428        2162 :                         return true;
     429             :                 }
     430             :                 else
     431             :                 {
     432             :                     OSL_ENSURE(!nLevel || pLevel, "sublevel without level sprm");
     433           0 :                     return true;    // RowEnd found
     434             :                 }
     435             :             }
     436             :         }
     437             : 
     438       18692 :         aRes.nStartPos = aRes.nEndPos;
     439       18692 :         aRes.pMemPos = 0;
     440             :         //Seek to our next block of properties
     441       18692 :         if (!(pPap->SeekPos(aRes.nStartPos)))
     442             :         {
     443           1 :             aRes.nEndPos = WW8_CP_MAX;
     444           1 :             pPap->SetDirty(true);
     445             :         }
     446       18692 :         pPap->GetSprms(&aRes);
     447       18692 :         pPap->SetDirty(false);
     448             :         //Update our aRes to get the new starting point of the next properties
     449       18692 :         rStartCp = aRes.nEndPos;
     450             :     }
     451             : 
     452           1 :     return false;
     453             : }
     454             : 
     455        4572 : ApoTestResults SwWW8ImplReader::TestApo(int nCellLevel, bool bTableRowEnd,
     456             :     const WW8_TablePos *pTabPos)
     457             : {
     458        4572 :     const WW8_TablePos *pTopLevelTable = nCellLevel <= 1 ? pTabPos : 0;
     459        4572 :     ApoTestResults aRet;
     460             :     // Frame in Style Definition (word appears to ignore them if inside an
     461             :     // text autoshape)
     462        4572 :     if (!m_bTxbxFlySection && m_nAktColl < m_vColl.size())
     463        4506 :         aRet.mpStyleApo = StyleExists(m_nAktColl) ? m_vColl[m_nAktColl].pWWFly : 0;
     464             : 
     465             :     /*
     466             :     #i1140#
     467             :     If I have a table and apply a style to one of its frames that should cause
     468             :     a paragraph that its applied to it to only exist as a separate floating
     469             :     frame, then the behaviour depends on which cell that it has been applied
     470             :     to. If its the first cell of a row then the whole table row jumps into the
     471             :     new frame, if its not then then the paragraph attributes are applied
     472             :     "except" for the floating frame stuff. i.e. its ignored. So if theres a
     473             :     table, and we're not in the first cell then we ignore the fact that the
     474             :     paragraph style wants to be in a different frame.
     475             : 
     476             :     This sort of mindbending inconsistency is surely why frames are deprecated
     477             :     in word 97 onwards and hidden away from the user
     478             : 
     479             :     #i1532# & #i5379#
     480             :     If we are already a table in a frame then we must grab the para properties
     481             :     to see if we are still in that frame.
     482             :     */
     483             : 
     484        4572 :     aRet.m_bHasSprm37 = m_pPlcxMan->HasParaSprm( m_bVer67 ? 37 : 0x2423 );
     485        4572 :     const sal_uInt8 *pSrpm29 = m_pPlcxMan->HasParaSprm( m_bVer67 ? 29 : 0x261B );
     486        4572 :     aRet.m_bHasSprm29 = pSrpm29 != NULL;
     487        4572 :     aRet.m_nSprm29 = pSrpm29 ? *pSrpm29 : 0;
     488             : 
     489             :     // Is there some frame data here
     490        4572 :     bool bNowApo = aRet.HasFrame() || pTopLevelTable;
     491        4572 :     if (bNowApo)
     492             :     {
     493         114 :         if (WW8FlyPara *pTest = ConstructApo(aRet, pTabPos))
     494         114 :             delete pTest;
     495             :         else
     496           0 :             bNowApo = false;
     497             :     }
     498             : 
     499        4572 :     bool bTestAllowed = !m_bTxbxFlySection && !bTableRowEnd;
     500        4572 :     if (bTestAllowed)
     501             :     {
     502             :         //Test is allowed if there is no table.
     503             :         //Otherwise only allowed if we are in the
     504             :         //first paragraph of the first cell of a row.
     505             :         //(And only if the row we are inside is at the
     506             :         //same level as the previous row, think tables
     507             :         //in tables)
     508        4235 :         if (nCellLevel == m_nInTable)
     509             :         {
     510             : 
     511        3877 :             if (!m_nInTable)
     512        2642 :                 bTestAllowed = true;
     513             :             else
     514             :             {
     515        1235 :                 if (!m_pTableDesc)
     516             :                 {
     517             :                     OSL_ENSURE(m_pTableDesc, "What!");
     518           0 :                     bTestAllowed = false;
     519             :                 }
     520             :                 else
     521             :                 {
     522             :                     // #i39468#
     523             :                     // If current cell isn't valid, the test is allowed.
     524             :                     // The cell isn't valid, if e.g. there is a new row
     525             :                     // <pTableDesc->nAktRow> >= <pTableDesc->pTabLines->Count()>
     526             :                     bTestAllowed =
     527        1924 :                         m_pTableDesc->GetAktCol() == 0 &&
     528         946 :                         ( !m_pTableDesc->IsValidCell( m_pTableDesc->GetAktCol() ) ||
     529        1707 :                           m_pTableDesc->InFirstParaInCell() );
     530             :                 }
     531             :             }
     532             :         }
     533             :     }
     534             : 
     535        4572 :     if (!bTestAllowed)
     536        1357 :         return aRet;
     537             : 
     538        3215 :     aRet.mbStartApo = bNowApo && !InAnyApo(); // APO-start
     539        3215 :     aRet.mbStopApo = InEqualOrHigherApo(nCellLevel) && !bNowApo;  // APO-end
     540             : 
     541             :     //If it happens that we are in a table, then if its not the first cell
     542             :     //then any attributes that might otherwise cause the contents to jump
     543             :     //into another frame don't matter, a table row sticks together as one
     544             :     //unit no matter what else happens. So if we are not in a table at
     545             :     //all, or if we are in the first cell then test that the last frame
     546             :     //data is the same as the current one
     547        3215 :     if (bNowApo && InEqualApo(nCellLevel))
     548             :     {
     549             :         // two bordering eachother
     550          16 :         if (!TestSameApo(aRet, pTabPos))
     551           0 :             aRet.mbStopApo = aRet.mbStartApo = true;
     552             :     }
     553             : 
     554        3215 :     return aRet;
     555             : }
     556             : 
     557             : // helper methods for outline, numbering and bullets
     558             : 
     559           1 : static void SetBaseAnlv(SwNumFormat &rNum, WW8_ANLV const &rAV, sal_uInt8 nSwLevel )
     560             : {
     561             :     static const SvxExtNumType eNumA[8] = { SVX_NUM_ARABIC, SVX_NUM_ROMAN_UPPER, SVX_NUM_ROMAN_LOWER,
     562             :         SVX_NUM_CHARS_UPPER_LETTER_N, SVX_NUM_CHARS_LOWER_LETTER_N, SVX_NUM_ARABIC,
     563             :         SVX_NUM_ARABIC, SVX_NUM_ARABIC };
     564             : 
     565             :     static const SvxAdjust eAdjA[4] = { SVX_ADJUST_LEFT,
     566             :         SVX_ADJUST_RIGHT, SVX_ADJUST_LEFT, SVX_ADJUST_LEFT };
     567           1 :     if (rAV.nfc < 8) {
     568           1 :         rNum.SetNumberingType( static_cast< sal_Int16 >(eNumA[ rAV.nfc ] ));
     569             :     } else {
     570           0 :         sal_Int16 nType= style::NumberingType::ARABIC;
     571           0 :         switch( rAV.nfc ) {
     572             :         case 14:
     573           0 :         case 19:nType = style::NumberingType::FULLWIDTH_ARABIC;    break;
     574           0 :         case 30:nType = style::NumberingType::TIAN_GAN_ZH;    break;
     575           0 :         case 31:nType = style::NumberingType::DI_ZI_ZH;    break;
     576             :         case 35:
     577             :         case 36:
     578             :         case 37:
     579             :         case 39:
     580           0 :             nType = style::NumberingType::NUMBER_LOWER_ZH;    break;
     581           0 :         case 34:nType = style::NumberingType::NUMBER_UPPER_ZH_TW;break;
     582           0 :         case 38:nType = style::NumberingType::NUMBER_UPPER_ZH;    break;
     583             :         case 10:
     584             :         case 11:
     585           0 :             nType = style::NumberingType::NUMBER_TRADITIONAL_JA;break;
     586           0 :         case 20:nType = style::NumberingType::AIU_FULLWIDTH_JA;break;
     587           0 :         case 12:nType = style::NumberingType::AIU_HALFWIDTH_JA;break;
     588           0 :         case 21:nType = style::NumberingType::IROHA_FULLWIDTH_JA;break;
     589           0 :         case 13:nType = style::NumberingType::IROHA_HALFWIDTH_JA;break;
     590           0 :         case 24:nType = style::NumberingType::HANGUL_SYLLABLE_KO;break;
     591           0 :         case 25:nType = style::NumberingType::HANGUL_JAMO_KO;break;
     592           0 :         case 41:nType = style::NumberingType::NUMBER_HANGUL_KO;break;
     593             :         //case 42:
     594             :         //case 43:
     595           0 :         case 44:nType = style::NumberingType::NUMBER_UPPER_KO; break;
     596             :         default:
     597           0 :             nType= style::NumberingType::ARABIC;break;
     598             :         }
     599           0 :         rNum.SetNumberingType( nType );
     600             :     }
     601             : 
     602           1 :     if ((rAV.aBits1 & 0x4) >> 2)
     603             :     {
     604           0 :         rNum.SetIncludeUpperLevels(nSwLevel + 1);
     605             :     }
     606           1 :     rNum.SetStart( SVBT16ToShort( rAV.iStartAt ) );
     607           1 :     rNum.SetNumAdjust( eAdjA[ rAV.aBits1 & 0x3] );
     608             : 
     609           1 :     rNum.SetCharTextDistance( SVBT16ToShort( rAV.dxaSpace ) );
     610           1 :     sal_Int16 nIndent = std::abs((sal_Int16)SVBT16ToShort( rAV.dxaIndent ));
     611           1 :     if( rAV.aBits1 & 0x08 )      //fHang
     612             :     {
     613           1 :         rNum.SetFirstLineOffset( -nIndent );
     614           1 :         rNum.SetAbsLSpace( nIndent );
     615             :     }
     616             :     else
     617           0 :         rNum.SetCharTextDistance( nIndent );        // width of number is missing
     618             : 
     619           1 :     if( rAV.nfc == 5 || rAV.nfc == 7 )
     620             :     {
     621           0 :         OUString sP = "." + rNum.GetSuffix();
     622           0 :         rNum.SetSuffix( sP );   // ordinal number
     623             :     }
     624           1 : }
     625             : 
     626           1 : void SwWW8ImplReader::SetAnlvStrings(SwNumFormat &rNum, WW8_ANLV const &rAV,
     627             :     const sal_uInt8* pText, bool bOutline)
     628             : {
     629           1 :     bool bInsert = false;                       // Default
     630           1 :     rtl_TextEncoding eCharSet = m_eStructCharSet;
     631             : 
     632           1 :     const WW8_FFN* pF = m_pFonts->GetFont(SVBT16ToShort(rAV.ftc)); // FontInfo
     633           1 :     bool bListSymbol = pF && ( pF->chs == 2 );      // Symbol/WingDings/...
     634             : 
     635           1 :     OUString sText;
     636           1 :     if (m_bVer67)
     637             :     {
     638           0 :         sText = OUString(reinterpret_cast<char const *>(pText), rAV.cbTextBefore + rAV.cbTextAfter, eCharSet);
     639             :     }
     640             :     else
     641             :     {
     642           2 :         for(sal_Int32 i = 0; i < rAV.cbTextBefore + rAV.cbTextAfter; ++i, pText += 2)
     643             :         {
     644           1 :             sText += OUString(SVBT16ToShort(*reinterpret_cast<SVBT16 const *>(pText)));
     645             :         }
     646             :     }
     647             : 
     648           1 :     if( bOutline )
     649             :     {                             // outline
     650           0 :         if( !rNum.GetIncludeUpperLevels()                          // there are  <= 1 number to show
     651           0 :             || rNum.GetNumberingType() == SVX_NUM_NUMBER_NONE )    // or this level has none
     652             :         {
     653             :                                                 // if self defined digits
     654           0 :             bInsert = true;                     // then apply character
     655             : 
     656             :             // replace by simple Bullet ?
     657           0 :             if( bListSymbol )
     658             :             {
     659             :                 // use cBulletChar for correct mapping on MAC
     660           0 :                 OUStringBuffer aBuf;
     661             :                 comphelper::string::padToLength(aBuf, rAV.cbTextBefore
     662           0 :                     + rAV.cbTextAfter, cBulletChar);
     663           0 :                 sText = aBuf.makeStringAndClear();
     664             :             }
     665             :         }
     666             :     }
     667             :     else
     668             :     {                                       // numbering / bullets
     669           1 :         bInsert = true;
     670           1 :         if( bListSymbol )
     671             :         {
     672             :             FontFamily eFamily;
     673           0 :             OUString aName;
     674             :             FontPitch ePitch;
     675             : 
     676           0 :             if( GetFontParams( SVBT16ToShort( rAV.ftc ), eFamily, aName,
     677           0 :                                 ePitch, eCharSet ) ){
     678             : 
     679           0 :                 vcl::Font aFont;
     680           0 :                 aFont.SetName( aName );
     681           0 :                 aFont.SetFamily( eFamily );
     682             : 
     683           0 :                 aFont.SetCharSet( eCharSet );
     684           0 :                 rNum.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
     685             : 
     686           0 :                 rNum.SetBulletFont( &aFont );
     687             : 
     688             :                 // take only the very first character
     689           0 :                 if (rAV.cbTextBefore || rAV.cbTextAfter)
     690           0 :                     rNum.SetBulletChar( sText[ 0 ] );
     691             :                 else
     692           0 :                     rNum.SetBulletChar( 0x2190 );
     693           0 :             }
     694             :         }
     695             :     }
     696           1 :     if( bInsert )
     697             :     {
     698           1 :         if (rAV.cbTextBefore)
     699             :         {
     700           0 :             OUString sP( sText.copy( 0, rAV.cbTextBefore ) );
     701           0 :             rNum.SetPrefix( sP );
     702             :         }
     703           1 :         if( rAV.cbTextAfter )
     704             :         {
     705           1 :             OUString sP( rNum.GetSuffix() );
     706           1 :             sP += sText.copy( rAV.cbTextBefore, rAV.cbTextAfter);
     707           1 :             rNum.SetSuffix( sP );
     708             :         }
     709             : // The characters before and after multipe digits do not apply because
     710             : // those are handled different by the writer and the result is in most
     711             : // cases worse than without.
     712           1 :     }
     713           1 : }
     714             : 
     715             : // SetAnld gets a WW-ANLD-Descriptor and a Level and modifies the NumRules
     716             : // which are provided by pNumR. This is used for everything beside
     717             : // outline inside the text.
     718           1 : void SwWW8ImplReader::SetAnld(SwNumRule* pNumR, WW8_ANLD const * pAD, sal_uInt8 nSwLevel,
     719             :     bool bOutLine)
     720             : {
     721           1 :     SwNumFormat aNF;
     722           1 :     if (pAD)
     723             :     {                                                       // there is a Anld-Sprm
     724           1 :         m_bAktAND_fNumberAcross = 0 != pAD->fNumberAcross;
     725           1 :         WW8_ANLV const &rAV = pAD->eAnlv;
     726           1 :         SetBaseAnlv(aNF, rAV, nSwLevel);                    // set the base format
     727           1 :         SetAnlvStrings(aNF, rAV, pAD->rgchAnld, bOutLine ); // set the rest
     728             :     }
     729           1 :     pNumR->Set(nSwLevel, aNF);
     730           1 : }
     731             : 
     732             : // chapter numbering and bullets
     733             : 
     734             : // Chapter numbering happens in the style definition.
     735             : // Sprm 13 provides the level, Sprm 12 the content.
     736             : 
     737           1 : SwNumRule* SwWW8ImplReader::GetStyRule()
     738             : {
     739           1 :     if( m_pStyles->pStyRule )         // Bullet-Style already present
     740           0 :         return m_pStyles->pStyRule;
     741             : 
     742           1 :     const OUString aBaseName("WW8StyleNum");
     743           2 :     const OUString aName( m_rDoc.GetUniqueNumRuleName( &aBaseName, false) );
     744             : 
     745             :     // #i86652#
     746             :     sal_uInt16 nRul = m_rDoc.MakeNumRule( aName, 0, false,
     747           1 :                                     SvxNumberFormat::LABEL_ALIGNMENT );
     748           1 :     m_pStyles->pStyRule = m_rDoc.GetNumRuleTable()[nRul];
     749             :     // Auto == false-> Nummerierungsvorlage
     750           1 :     m_pStyles->pStyRule->SetAutoRule(false);
     751             : 
     752           2 :     return m_pStyles->pStyRule;
     753             : }
     754             : 
     755             : // Sprm 13
     756           0 : void SwWW8ImplReader::Read_ANLevelNo( sal_uInt16, const sal_uInt8* pData, short nLen )
     757             : {
     758           0 :     m_nSwNumLevel = 0xff; // Default: invalid
     759             : 
     760           0 :     if( nLen <= 0 )
     761           0 :         return;
     762             : 
     763             :     // StyleDef ?
     764           0 :     if( m_pAktColl )
     765             :     {
     766             :         // only for SwTextFormatColl, not CharFormat
     767             :         // WW: 0 = no Numbering
     768           0 :         SwWW8StyInf * pColl = GetStyle(m_nAktColl);
     769           0 :         if (pColl != NULL && pColl->bColl && *pData)
     770             :         {
     771             :             // Range WW:1..9 -> SW:0..8 no bullets / numbering
     772             : 
     773           0 :             if (*pData <= MAXLEVEL && *pData <= 9)
     774             :             {
     775           0 :                 m_nSwNumLevel = *pData - 1;
     776           0 :                 if (!m_bNoAttrImport)
     777           0 :                     static_cast<SwTextFormatColl*>(m_pAktColl)->AssignToListLevelOfOutlineStyle( m_nSwNumLevel );
     778             :                     // For WW-NoNumbering also NO_NUMBERING could be used.
     779             :                     // ( For normal numberierung NO_NUM has to be used:
     780             :                     //   NO_NUM : pauses numbering,
     781             :                     //   NO_NUMBERING : no numbering at all )
     782             : 
     783             :             }
     784           0 :             else if( *pData == 10 || *pData == 11 )
     785             :             {
     786             :                 // remember type, the rest happens at Sprm 12
     787           0 :                 m_pStyles->nWwNumLevel = *pData;
     788             :             }
     789             :         }
     790             :     }
     791             :     else
     792             :     {
     793             :         //Not StyleDef
     794           0 :         if (!m_bAnl)
     795           0 :             StartAnl(pData);        // begin of outline / bullets
     796           0 :         NextAnlLine(pData);
     797             :     }
     798             : }
     799             : 
     800           1 : void SwWW8ImplReader::Read_ANLevelDesc( sal_uInt16, const sal_uInt8* pData, short nLen ) // Sprm 12
     801             : {
     802           1 :     SwWW8StyInf * pStyInf = GetStyle(m_nAktColl);
     803           1 :     if( !m_pAktColl || nLen <= 0                       // only for Styledef
     804           1 :         || (pStyInf && !pStyInf->bColl)              // ignore  CharFormat ->
     805           1 :         || ( m_nIniFlags & WW8FL_NO_OUTLINE ) )
     806             :     {
     807           0 :         m_nSwNumLevel = 0xff;
     808           1 :         return;
     809             :     }
     810             : 
     811           1 :     if( m_nSwNumLevel <= MAXLEVEL         // Value range mapping WW:1..9 -> SW:0..8
     812           0 :         && m_nSwNumLevel <= 9 ){          // No Bullets or Numbering
     813             : 
     814             :         // If NumRuleItems were set, either directly or through inheritance, disable them now
     815           0 :         m_pAktColl->SetFormatAttr( SwNumRuleItem() );
     816             : 
     817           0 :         const OUString aName("Outline");
     818             :         SwNumRule aNR( m_rDoc.GetUniqueNumRuleName( &aName ),
     819             :                        SvxNumberFormat::LABEL_WIDTH_AND_POSITION,
     820           0 :                        OUTLINE_RULE );
     821           0 :         aNR = *m_rDoc.GetOutlineNumRule();
     822             : 
     823           0 :         SetAnld(&aNR, reinterpret_cast<WW8_ANLD const *>(pData), m_nSwNumLevel, true);
     824             : 
     825             :         // Missing Levels need not be replenished
     826           0 :         m_rDoc.SetOutlineNumRule( aNR );
     827           1 :     }else if( m_pStyles->nWwNumLevel == 10 || m_pStyles->nWwNumLevel == 11 ){
     828           1 :         SwNumRule* pNR = GetStyRule();
     829           1 :         SetAnld(pNR, reinterpret_cast<WW8_ANLD const *>(pData), 0, false);
     830           1 :         m_pAktColl->SetFormatAttr( SwNumRuleItem( pNR->GetName() ) );
     831             : 
     832           1 :         pStyInf = GetStyle(m_nAktColl);
     833           1 :         if (pStyInf != NULL)
     834           1 :             pStyInf->bHasStyNumRule = true;
     835             :     }
     836             : }
     837             : 
     838             : // Numbering / Bullets
     839             : 
     840             : // SetNumOlst() carries the Numrules for this cell to SwNumFormat.
     841             : // For this the info is fetched from OLST and not from ANLD ( see later )
     842             : // ( only for outline inside text; Bullets / numbering use ANLDs )
     843           0 : void SwWW8ImplReader::SetNumOlst(SwNumRule* pNumR, WW8_OLST* pO, sal_uInt8 nSwLevel)
     844             : {
     845           0 :     SwNumFormat aNF;
     846           0 :     WW8_ANLV &rAV = pO->rganlv[nSwLevel];
     847           0 :     SetBaseAnlv(aNF, rAV, nSwLevel);
     848             :                                             // ... and then the Strings
     849           0 :     int nTextOfs = 0;
     850             :     sal_uInt8 i;
     851             :     WW8_ANLV* pAV1;                 // search String-Positions
     852           0 :     for (i = 0, pAV1 = pO->rganlv; i < nSwLevel; ++i, ++pAV1)
     853           0 :         nTextOfs += pAV1->cbTextBefore + pAV1->cbTextAfter;
     854             : 
     855           0 :     if (!m_bVer67)
     856           0 :         nTextOfs *= 2;
     857           0 :     SetAnlvStrings(aNF, rAV, pO->rgch + nTextOfs, true); // and apply
     858           0 :     pNumR->Set(nSwLevel, aNF);
     859           0 : }
     860             : 
     861             : // The OLST is at the beginning of each section that contains outlines.
     862             : // The ANLDs that are connected to each outline-line contain only nonsense,
     863             : // so the OLSTs are remembered for the section to have usable information
     864             : // when outline-paragraphs occur.
     865           2 : void SwWW8ImplReader::Read_OLST( sal_uInt16, const sal_uInt8* pData, short nLen )
     866             : {
     867           2 :     delete m_pNumOlst;
     868           2 :     if (nLen <= 0)
     869             :     {
     870           1 :         m_pNumOlst = 0;
     871           3 :         return;
     872             :     }
     873           1 :     m_pNumOlst = new WW8_OLST;
     874           1 :     if( nLen < sal::static_int_cast< sal_Int32 >(sizeof( WW8_OLST )) )   // fill if to short
     875           0 :         memset( m_pNumOlst, 0, sizeof( *m_pNumOlst ) );
     876           1 :     *m_pNumOlst = *reinterpret_cast<WW8_OLST const *>(pData);
     877             : }
     878             : 
     879           0 : WW8LvlType GetNumType(sal_uInt8 nWwLevelNo)
     880             : {
     881           0 :     WW8LvlType nRet = WW8_None;
     882           0 :     if( nWwLevelNo == 12 )
     883           0 :        nRet = WW8_Pause;
     884           0 :     else if( nWwLevelNo == 10 )
     885           0 :        nRet = WW8_Numbering;
     886           0 :     else if( nWwLevelNo == 11 )
     887           0 :        nRet = WW8_Sequence;
     888           0 :     else if( nWwLevelNo > 0 && nWwLevelNo <= 9 )
     889           0 :        nRet = WW8_Outline;
     890           0 :     return nRet;
     891             : }
     892             : 
     893           0 : SwNumRule *ANLDRuleMap::GetNumRule(sal_uInt8 nNumType)
     894             : {
     895           0 :     return (WW8_Numbering == nNumType ? mpNumberingNumRule : mpOutlineNumRule);
     896             : }
     897             : 
     898           0 : void ANLDRuleMap::SetNumRule(SwNumRule *pRule, sal_uInt8 nNumType)
     899             : {
     900           0 :     if (WW8_Numbering == nNumType)
     901           0 :         mpNumberingNumRule = pRule;
     902             :     else
     903           0 :         mpOutlineNumRule = pRule;
     904           0 : }
     905             : 
     906             : // StartAnl is called at the beginning of a row area that contains
     907             : // outline / numbering / bullets
     908           0 : void SwWW8ImplReader::StartAnl(const sal_uInt8* pSprm13)
     909             : {
     910           0 :     m_bAktAND_fNumberAcross = false;
     911             : 
     912           0 :     sal_uInt8 nT = static_cast< sal_uInt8 >(GetNumType(*pSprm13));
     913           0 :     if (nT == WW8_Pause || nT == WW8_None)
     914           0 :         return;
     915             : 
     916           0 :     m_nWwNumType = nT;
     917           0 :     SwNumRule *pNumRule = m_aANLDRules.GetNumRule(m_nWwNumType);
     918             : 
     919             :     // check for COL numbering:
     920           0 :     const sal_uInt8* pS12 = 0;// sprmAnld
     921           0 :     OUString sNumRule;
     922             : 
     923           0 :     if (m_pTableDesc)
     924             :     {
     925           0 :         sNumRule = m_pTableDesc->GetNumRuleName();
     926           0 :         if (!sNumRule.isEmpty())
     927             :         {
     928           0 :             pNumRule = m_rDoc.FindNumRulePtr(sNumRule);
     929           0 :             if (!pNumRule)
     930           0 :                 sNumRule.clear();
     931             :             else
     932             :             {
     933             :                 // this is ROW numbering ?
     934           0 :                 pS12 = m_pPlcxMan->HasParaSprm(m_bVer67 ? 12 : 0xC63E); // sprmAnld
     935           0 :                 if (pS12 && 0 != reinterpret_cast<WW8_ANLD const *>(pS12)->fNumberAcross)
     936           0 :                     sNumRule.clear();
     937             :             }
     938             :         }
     939             :     }
     940             : 
     941           0 :     SwWW8StyInf * pStyInf = GetStyle(m_nAktColl);
     942           0 :     if (sNumRule.isEmpty() && pStyInf != NULL &&  pStyInf->bHasStyNumRule)
     943             :     {
     944           0 :         sNumRule = pStyInf->pFormat->GetNumRule().GetValue();
     945           0 :         pNumRule = m_rDoc.FindNumRulePtr(sNumRule);
     946           0 :         if (!pNumRule)
     947           0 :             sNumRule.clear();
     948             :     }
     949             : 
     950           0 :     if (sNumRule.isEmpty())
     951             :     {
     952           0 :         if (!pNumRule)
     953             :         {
     954             :             // #i86652#
     955           0 :             pNumRule = m_rDoc.GetNumRuleTable()[
     956             :                             m_rDoc.MakeNumRule( sNumRule, 0, false,
     957           0 :                                               SvxNumberFormat::LABEL_ALIGNMENT ) ];
     958             :         }
     959           0 :         if (m_pTableDesc)
     960             :         {
     961           0 :             if (!pS12)
     962           0 :                 pS12 = m_pPlcxMan->HasParaSprm(m_bVer67 ? 12 : 0xC63E); // sprmAnld
     963           0 :             if (!pS12 || !reinterpret_cast<WW8_ANLD const *>(pS12)->fNumberAcross)
     964           0 :                 m_pTableDesc->SetNumRuleName(pNumRule->GetName());
     965             :         }
     966             :     }
     967             : 
     968           0 :     m_bAnl = true;
     969             : 
     970           0 :     sNumRule = pNumRule ? pNumRule->GetName() : OUString();
     971             :     // set NumRules via stack
     972           0 :     m_pCtrlStck->NewAttr(*m_pPaM->GetPoint(),
     973           0 :         SfxStringItem(RES_FLTR_NUMRULE, sNumRule));
     974             : 
     975           0 :     m_aANLDRules.SetNumRule(pNumRule, m_nWwNumType);
     976             : }
     977             : 
     978             : // NextAnlLine() is called once for every row of a
     979             : // outline / numbering / bullet
     980           0 : void SwWW8ImplReader::NextAnlLine(const sal_uInt8* pSprm13)
     981             : {
     982           0 :     if (!m_bAnl)
     983           0 :         return;
     984             : 
     985           0 :     SwNumRule *pNumRule = m_aANLDRules.GetNumRule(m_nWwNumType);
     986             : 
     987             :     // pNd->UpdateNum ohne Regelwerk gibt GPF spaetestens beim Speichern als
     988             :     // sdw3
     989             : 
     990             :     // WW:10 = numberierung -> SW:0 & WW:11 = bullets -> SW:0
     991           0 :     if (*pSprm13 == 10 || *pSprm13 == 11)
     992             :     {
     993           0 :         m_nSwNumLevel = 0;
     994           0 :         if (!pNumRule->GetNumFormat(m_nSwNumLevel))
     995             :         {
     996             :             // not defined yet
     997             :             // sprmAnld o. 0
     998           0 :             const sal_uInt8* pS12 = m_pPlcxMan->HasParaSprm(m_bVer67 ? 12 : 0xC63E);
     999           0 :             SetAnld(pNumRule, reinterpret_cast<WW8_ANLD const *>(pS12), m_nSwNumLevel, false);
    1000           0 :         }
    1001             :     }
    1002           0 :     else if( *pSprm13 > 0 && *pSprm13 <= MAXLEVEL )          // range WW:1..9 -> SW:0..8
    1003             :     {
    1004           0 :         m_nSwNumLevel = *pSprm13 - 1;             // outline
    1005             :         // undefined
    1006           0 :         if (!pNumRule->GetNumFormat(m_nSwNumLevel))
    1007             :         {
    1008           0 :             if (m_pNumOlst)                       // there was a OLST
    1009             :             {
    1010             :                 //Assure upper levels are set, #i9556#
    1011           0 :                 for (sal_uInt8 nI = 0; nI < m_nSwNumLevel; ++nI)
    1012             :                 {
    1013           0 :                     if (!pNumRule->GetNumFormat(nI))
    1014           0 :                         SetNumOlst(pNumRule, m_pNumOlst, nI);
    1015             :                 }
    1016             : 
    1017           0 :                 SetNumOlst(pNumRule, m_pNumOlst , m_nSwNumLevel);
    1018             :             }
    1019             :             else                                // no Olst -> use Anld
    1020             :             {
    1021             :                 // sprmAnld
    1022           0 :                 const sal_uInt8* pS12 = m_pPlcxMan->HasParaSprm(m_bVer67 ? 12 : 0xC63E);
    1023           0 :                 SetAnld(pNumRule, reinterpret_cast<WW8_ANLD const *>(pS12), m_nSwNumLevel, false);
    1024             :             }
    1025           0 :         }
    1026             :     }
    1027             :     else
    1028           0 :         m_nSwNumLevel = 0xff;                 // no number
    1029             : 
    1030           0 :     SwTextNode* pNd = m_pPaM->GetNode().GetTextNode();
    1031           0 :     if (m_nSwNumLevel < MAXLEVEL)
    1032           0 :         pNd->SetAttrListLevel( m_nSwNumLevel );
    1033             :     else
    1034             :     {
    1035           0 :         pNd->SetAttrListLevel(0);
    1036           0 :         pNd->SetCountedInList( false );
    1037             :     }
    1038             : }
    1039             : 
    1040           0 : void SwWW8ImplReader::StopAllAnl(bool bGoBack)
    1041             : {
    1042             :     //Of course we're not restarting, but we'll make use of our knowledge
    1043             :     //of the implementation to do it.
    1044           0 :     StopAnlToRestart(WW8_None, bGoBack);
    1045           0 : }
    1046             : 
    1047           0 : void SwWW8ImplReader::StopAnlToRestart(sal_uInt8 nNewType, bool bGoBack)
    1048             : {
    1049           0 :     if (bGoBack)
    1050             :     {
    1051           0 :         SwPosition aTmpPos(*m_pPaM->GetPoint());
    1052           0 :         m_pPaM->Move(fnMoveBackward, fnGoContent);
    1053           0 :         m_pCtrlStck->SetAttr(*m_pPaM->GetPoint(), RES_FLTR_NUMRULE);
    1054           0 :         *m_pPaM->GetPoint() = aTmpPos;
    1055             :     }
    1056             :     else
    1057           0 :         m_pCtrlStck->SetAttr(*m_pPaM->GetPoint(), RES_FLTR_NUMRULE);
    1058             : 
    1059           0 :     m_aANLDRules.mpNumberingNumRule = 0;
    1060             :     /*
    1061             :      #i18816#
    1062             :      my take on this problem is that moving either way from an outline to a
    1063             :      numbering doesn't halt the outline, while the numbering is always halted
    1064             :     */
    1065             :     bool bNumberingNotStopOutline =
    1066           0 :         (((m_nWwNumType == WW8_Outline) && (nNewType == WW8_Numbering)) ||
    1067           0 :         ((m_nWwNumType == WW8_Numbering) && (nNewType == WW8_Outline)));
    1068           0 :     if (!bNumberingNotStopOutline)
    1069           0 :         m_aANLDRules.mpOutlineNumRule = 0;
    1070             : 
    1071           0 :     m_nSwNumLevel = 0xff;
    1072           0 :     m_nWwNumType = WW8_None;
    1073           0 :     m_bAnl = false;
    1074           0 : }
    1075             : 
    1076           0 : WW8TabBandDesc::WW8TabBandDesc( WW8TabBandDesc& rBand )
    1077             : {
    1078           0 :     *this = rBand;
    1079           0 :     if( rBand.pTCs )
    1080             :     {
    1081           0 :         pTCs = new WW8_TCell[nWwCols];
    1082           0 :         memcpy( pTCs, rBand.pTCs, nWwCols * sizeof( WW8_TCell ) );
    1083             :     }
    1084           0 :     if( rBand.pSHDs )
    1085             :     {
    1086           0 :         pSHDs = new WW8_SHD[nWwCols];
    1087           0 :         memcpy( pSHDs, rBand.pSHDs, nWwCols * sizeof( WW8_SHD ) );
    1088             :     }
    1089           0 :     if( rBand.pNewSHDs )
    1090             :     {
    1091           0 :         pNewSHDs = new sal_uInt32[nWwCols];
    1092           0 :         memcpy(pNewSHDs, rBand.pNewSHDs, nWwCols * sizeof(sal_uInt32));
    1093             :     }
    1094           0 :     memcpy(aDefBrcs, rBand.aDefBrcs, sizeof(aDefBrcs));
    1095           0 : }
    1096             : 
    1097             : // ReadDef reads the cell position and the borders of a band
    1098        2146 : void WW8TabBandDesc::ReadDef(bool bVer67, const sal_uInt8* pS)
    1099             : {
    1100        2146 :     if (!bVer67)
    1101        2146 :         pS++;
    1102             : 
    1103        2146 :     short nLen = (sal_Int16)SVBT16ToShort( pS - 2 ); // not beautiful
    1104             : 
    1105        2146 :     sal_uInt8 nCols = *pS;                       // number of cells
    1106        2146 :     short nOldCols = nWwCols;
    1107             : 
    1108        2146 :     if( nCols > MAX_COL )
    1109        2146 :         return;
    1110             : 
    1111        2146 :     nWwCols = nCols;
    1112             : 
    1113        2146 :     const sal_uInt8* pT = &pS[1];
    1114        2146 :     nLen --;
    1115             :     int i;
    1116       13253 :     for(i=0; i<=nCols; i++, pT+=2 )
    1117       11107 :         nCenter[i] = (sal_Int16)SVBT16ToShort( pT );    // X-borders
    1118        2146 :     nLen -= 2 * ( nCols + 1 );
    1119        2146 :     if( nCols != nOldCols ) // different column count
    1120             :     {
    1121        2146 :         delete[] pTCs, pTCs = 0;
    1122        2146 :         delete[] pSHDs, pSHDs = 0;
    1123        2146 :         delete[] pNewSHDs, pNewSHDs = 0;
    1124             :     }
    1125             : 
    1126        2146 :     short nFileCols = nLen / ( bVer67 ? 10 : 20 );  // really saved
    1127             : 
    1128        2146 :     if (!pTCs && nCols)
    1129             :     {
    1130             :         // create empty TCs
    1131        2146 :         pTCs = new WW8_TCell[nCols];
    1132        2146 :         setcelldefaults(pTCs,nCols);
    1133             :     }
    1134             : 
    1135        2146 :     short nColsToRead = nFileCols;
    1136        2146 :     if (nColsToRead > nCols)
    1137           8 :         nColsToRead = nCols;
    1138             : 
    1139        2146 :     if( nColsToRead )
    1140             :     {
    1141             :         // read TCs
    1142             : 
    1143             :         /*
    1144             :             Attention: Beginning with Ver8 there is an extra ushort per TC
    1145             :                        added and the size of the border code is doubled.
    1146             :                        Because of this a simple copy (pTCs[i] = *pTc;)
    1147             :                        is not possible.
    1148             :             ---
    1149             :             Advantage: The work structure suits better.
    1150             :         */
    1151        2146 :         WW8_TCell* pAktTC  = pTCs;
    1152        2146 :         if( bVer67 )
    1153             :         {
    1154           0 :             WW8_TCellVer6 const * pTc = reinterpret_cast<WW8_TCellVer6 const *>(pT);
    1155           0 :             for(i=0; i<nColsToRead; i++, ++pAktTC,++pTc)
    1156             :             {
    1157           0 :                 if( i < nColsToRead )
    1158             :                 {               // TC from file ?
    1159           0 :                     sal_uInt8 aBits1 = pTc->aBits1Ver6;
    1160           0 :                     pAktTC->bFirstMerged = sal_uInt8( ( aBits1 & 0x01 ) != 0 );
    1161           0 :                     pAktTC->bMerged = sal_uInt8( ( aBits1 & 0x02 ) != 0 );
    1162             :                     pAktTC->rgbrc[ WW8_TOP ]
    1163           0 :                         = WW8_BRC( pTc->rgbrcVer6[ WW8_TOP ] );
    1164             :                     pAktTC->rgbrc[ WW8_LEFT ]
    1165           0 :                         = WW8_BRC( pTc->rgbrcVer6[ WW8_LEFT ] );
    1166             :                     pAktTC->rgbrc[ WW8_BOT ]
    1167           0 :                         = WW8_BRC( pTc->rgbrcVer6[ WW8_BOT ] );
    1168             :                     pAktTC->rgbrc[ WW8_RIGHT ]
    1169           0 :                         = WW8_BRC( pTc->rgbrcVer6[ WW8_RIGHT ] );
    1170           0 :                     if(    ( pAktTC->bMerged )
    1171           0 :                             && ( i > 0             ) )
    1172             :                     {
    1173             :                         // Cell merged -> remember
    1174             :                         //bWWMergedVer6[i] = true;
    1175             :                         pTCs[i-1].rgbrc[ WW8_RIGHT ]
    1176           0 :                             = WW8_BRC( pTc->rgbrcVer6[ WW8_RIGHT ] );
    1177             :                             // apply right border to previous cell
    1178             :                             // bExist must not be set to false, because WW
    1179             :                             // does not count this cells in text boxes....
    1180             :                     }
    1181             :                 }
    1182             :             }
    1183             :         }
    1184             :         else
    1185             :         {
    1186        2146 :             WW8_TCellVer8 const * pTc = reinterpret_cast<WW8_TCellVer8 const *>(pT);
    1187       10099 :             for (int k = 0; k < nColsToRead; ++k, ++pAktTC, ++pTc )
    1188             :             {
    1189        7953 :                 sal_uInt16 aBits1 = SVBT16ToShort( pTc->aBits1Ver8 );
    1190        7953 :                 pAktTC->bFirstMerged    = sal_uInt8( ( aBits1 & 0x0001 ) != 0 );
    1191        7953 :                 pAktTC->bMerged         = sal_uInt8( ( aBits1 & 0x0002 ) != 0 );
    1192        7953 :                 pAktTC->bVertical       = sal_uInt8( ( aBits1 & 0x0004 ) != 0 );
    1193        7953 :                 pAktTC->bBackward       = sal_uInt8( ( aBits1 & 0x0008 ) != 0 );
    1194        7953 :                 pAktTC->bRotateFont     = sal_uInt8( ( aBits1 & 0x0010 ) != 0 );
    1195        7953 :                 pAktTC->bVertMerge      = sal_uInt8( ( aBits1 & 0x0020 ) != 0 );
    1196        7953 :                 pAktTC->bVertRestart    = sal_uInt8( ( aBits1 & 0x0040 ) != 0 );
    1197        7953 :                 pAktTC->nVertAlign      = ( ( aBits1 & 0x0180 ) >> 7 );
    1198             :                 // note: in aBits1 there are 7 bits unused,
    1199             :                 //       followed by another 16 unused bits
    1200             : 
    1201        7953 :                 pAktTC->rgbrc[ WW8_TOP   ] = pTc->rgbrcVer8[ WW8_TOP   ];
    1202        7953 :                 pAktTC->rgbrc[ WW8_LEFT  ] = pTc->rgbrcVer8[ WW8_LEFT  ];
    1203        7953 :                 pAktTC->rgbrc[ WW8_BOT   ] = pTc->rgbrcVer8[ WW8_BOT   ];
    1204        7953 :                 pAktTC->rgbrc[ WW8_RIGHT ] = pTc->rgbrcVer8[ WW8_RIGHT ];
    1205             :             }
    1206             :         }
    1207             : 
    1208             :         // #i25071 In '97 text direction appears to be only set using TC properties
    1209             :         // not with sprmTTextFlow so we need to cycle through the maDirections and
    1210             :         // double check any non-default directions
    1211       11107 :         for (int k = 0; k < nCols; ++k)
    1212             :         {
    1213        8961 :             if(maDirections[k] == 4)
    1214             :             {
    1215        8961 :                 if(pTCs[k].bVertical)
    1216             :                 {
    1217           8 :                     if(pTCs[k].bBackward)
    1218           8 :                         maDirections[k] = 3;
    1219             :                     else
    1220           0 :                         maDirections[k] = 1;
    1221             :                 }
    1222             :             }
    1223             :         }
    1224             :     }
    1225             : }
    1226             : 
    1227         298 : void WW8TabBandDesc::ProcessSprmTSetBRC(int nBrcVer, const sal_uInt8* pParamsTSetBRC)
    1228             : {
    1229         298 :     if( pParamsTSetBRC && pTCs ) // set one or more cell border(s)
    1230             :     {
    1231         298 :         sal_uInt8 nitcFirst= pParamsTSetBRC[0];// first col to be changed
    1232         298 :         sal_uInt8 nitcLim  = pParamsTSetBRC[1];// (last col to be changed)+1
    1233         298 :         sal_uInt8 nFlag    = *(pParamsTSetBRC+2);
    1234             : 
    1235         298 :         if (nitcFirst >= nWwCols)
    1236         298 :             return;
    1237             : 
    1238         298 :         if (nitcLim > nWwCols)
    1239           1 :             nitcLim = nWwCols;
    1240             : 
    1241         298 :         bool bChangeRight  = (nFlag & 0x08) != 0;
    1242         298 :         bool bChangeBottom = (nFlag & 0x04) != 0;
    1243         298 :         bool bChangeLeft   = (nFlag & 0x02) != 0;
    1244         298 :         bool bChangeTop    = (nFlag & 0x01) != 0;
    1245             : 
    1246         298 :         WW8_TCell* pAktTC  = pTCs + nitcFirst;
    1247         298 :         WW8_BRCVer9 brcVer9;
    1248         298 :         if( nBrcVer == 6 )
    1249           0 :             brcVer9 = WW8_BRC(*reinterpret_cast<WW8_BRCVer6 const *>(pParamsTSetBRC+3));
    1250         298 :         else if( nBrcVer == 8 )
    1251           1 :             brcVer9 = *reinterpret_cast<WW8_BRC const *>(pParamsTSetBRC+3);
    1252             :         else
    1253         297 :             brcVer9 = *reinterpret_cast<WW8_BRCVer9 const *>(pParamsTSetBRC+3);
    1254             : 
    1255         695 :         for( int i = nitcFirst; i < nitcLim; ++i, ++pAktTC )
    1256             :         {
    1257         397 :             if( bChangeTop )
    1258         160 :                 pAktTC->rgbrc[ WW8_TOP   ] = brcVer9;
    1259         397 :             if( bChangeLeft )
    1260         158 :                 pAktTC->rgbrc[ WW8_LEFT  ] = brcVer9;
    1261         397 :             if( bChangeBottom )
    1262         171 :                 pAktTC->rgbrc[ WW8_BOT   ] = brcVer9;
    1263         397 :             if( bChangeRight )
    1264         111 :                 pAktTC->rgbrc[ WW8_RIGHT ] = brcVer9;
    1265             :         }
    1266             :     }
    1267             : }
    1268             : 
    1269         180 : void WW8TabBandDesc::ProcessSprmTTableBorders(int nBrcVer, const sal_uInt8* pParams)
    1270             : {
    1271             :     // sprmTTableBorders
    1272         180 :     if( nBrcVer == 6 )
    1273             :     {
    1274           0 :         WW8_BRCVer6 const *pVer6 = reinterpret_cast<WW8_BRCVer6 const *>(pParams);
    1275           0 :         for (int i = 0; i < 6; ++i)
    1276           0 :             aDefBrcs[i] = WW8_BRC(pVer6[i]);
    1277             :     }
    1278         180 :     else if ( nBrcVer == 8 )
    1279             :     {
    1280             :         static_assert(sizeof (WW8_BRC) == 4, "this has to match the msword size");
    1281          21 :         for( int i = 0; i < 6; ++i )
    1282          18 :             aDefBrcs[i] = reinterpret_cast<WW8_BRC const *>(pParams)[i];
    1283             :     }
    1284             :     else
    1285         177 :         memcpy( aDefBrcs, pParams, sizeof( aDefBrcs ) );
    1286         180 : }
    1287             : 
    1288         416 : void WW8TabBandDesc::ProcessSprmTDxaCol(const sal_uInt8* pParamsTDxaCol)
    1289             : {
    1290             :     // sprmTDxaCol (opcode 0x7623) changes the width of cells
    1291             :     // whose index is within a certain range to be a certain value.
    1292             : 
    1293         416 :     if( nWwCols && pParamsTDxaCol ) // set one or more cell length(s)
    1294             :     {
    1295           3 :         sal_uInt8 nitcFirst= pParamsTDxaCol[0]; // first col to be changed
    1296           3 :         sal_uInt8 nitcLim  = pParamsTDxaCol[1]; // (last col to be changed)+1
    1297           3 :         short nDxaCol = (sal_Int16)SVBT16ToShort( pParamsTDxaCol + 2 );
    1298             : 
    1299           8 :         for( int i = nitcFirst; (i < nitcLim) && (i < nWwCols); i++ )
    1300             :         {
    1301           5 :             const short nOrgWidth  = nCenter[i+1] - nCenter[i];
    1302           5 :             const short nDelta = nDxaCol - nOrgWidth;
    1303          25 :             for( int j = i+1; j <= nWwCols; j++ )
    1304             :             {
    1305          20 :                 nCenter[j] = nCenter[j] + nDelta;
    1306             :             }
    1307             :         }
    1308             :     }
    1309         416 : }
    1310             : 
    1311         178 : void WW8TabBandDesc::ProcessSprmTInsert(const sal_uInt8* pParamsTInsert)
    1312             : {
    1313         178 :     if( nWwCols && pParamsTInsert )        // set one or more cell length(s)
    1314             :     {
    1315           2 :         sal_uInt8 nitcInsert = pParamsTInsert[0]; // position at which to insert
    1316           2 :         if (nitcInsert >= MAX_COL)  // cannot insert into cell outside max possible index
    1317         178 :             return;
    1318           2 :         sal_uInt8 nctc  = pParamsTInsert[1];      // number of cells
    1319           2 :         sal_uInt16 ndxaCol = SVBT16ToShort( pParamsTInsert+2 );
    1320             : 
    1321             :         short nNewWwCols;
    1322           2 :         if (nitcInsert > nWwCols)
    1323             :         {
    1324           0 :             nNewWwCols = nitcInsert+nctc;
    1325             :             //if new count would be outside max possible count, clip it, and calc a new replacement
    1326             :             //legal nctc
    1327           0 :             if (nNewWwCols > MAX_COL)
    1328             :             {
    1329           0 :                 nNewWwCols = MAX_COL;
    1330           0 :                 nctc = ::sal::static_int_cast<sal_uInt8>(nNewWwCols-nitcInsert);
    1331             :             }
    1332             :         }
    1333             :         else
    1334             :         {
    1335           2 :             nNewWwCols = nWwCols+nctc;
    1336             :             //if new count would be outside max possible count, clip it, and calc a new replacement
    1337             :             //legal nctc
    1338           2 :             if (nNewWwCols > MAX_COL)
    1339             :             {
    1340           1 :                 nNewWwCols = MAX_COL;
    1341           1 :                 nctc = ::sal::static_int_cast<sal_uInt8>(nNewWwCols-nWwCols);
    1342             :             }
    1343             :         }
    1344             : 
    1345           2 :         WW8_TCell *pTC2s = new WW8_TCell[nNewWwCols];
    1346           2 :         setcelldefaults(pTC2s, nNewWwCols);
    1347             : 
    1348           2 :         if (pTCs)
    1349             :         {
    1350           2 :             memcpy( pTC2s, pTCs, nWwCols * sizeof( WW8_TCell ) );
    1351           2 :             delete[] pTCs;
    1352             :         }
    1353           2 :         pTCs = pTC2s;
    1354             : 
    1355             :         //If we have to move some cells
    1356           2 :         if (nitcInsert <= nWwCols)
    1357             :         {
    1358             :             // adjust the left x-position of the dummy at the very end
    1359           2 :             nCenter[nWwCols + nctc] = nCenter[nWwCols]+nctc*ndxaCol;
    1360           5 :             for( int i = nWwCols-1; i >= nitcInsert; i--)
    1361             :             {
    1362             :                 // adjust the left x-position
    1363           3 :                 nCenter[i + nctc] = nCenter[i]+nctc*ndxaCol;
    1364             : 
    1365             :                 // adjust the cell's borders
    1366           3 :                 pTCs[i + nctc] = pTCs[i];
    1367             :             }
    1368             :         }
    1369             : 
    1370             :         //if itcMac is larger than full size, fill in missing ones first
    1371           2 :         for( int i = nWwCols; i > nitcInsert+nWwCols; i--)
    1372           0 :             nCenter[i] = i ? (nCenter[i - 1]+ndxaCol) : 0;
    1373             : 
    1374             :         //now add in our new cells
    1375          69 :         for( int j = 0;j < nctc; j++)
    1376          67 :             nCenter[j + nitcInsert] = (j + nitcInsert) ? (nCenter[j + nitcInsert -1]+ndxaCol) : 0;
    1377             : 
    1378           2 :         nWwCols = nNewWwCols;
    1379             :     }
    1380             : }
    1381             : 
    1382           0 : void WW8TabBandDesc::ProcessDirection(const sal_uInt8* pParams)
    1383             : {
    1384           0 :     sal_uInt8 nStartCell = *pParams++;
    1385           0 :     sal_uInt8 nEndCell = *pParams++;
    1386           0 :     sal_uInt16 nCode = SVBT16ToShort(pParams);
    1387             : 
    1388             :     OSL_ENSURE(nStartCell < nEndCell, "not as I thought");
    1389             :     OSL_ENSURE(nEndCell < MAX_COL + 1, "not as I thought");
    1390           0 :     if (nStartCell > MAX_COL)
    1391           0 :         return;
    1392           0 :     if (nEndCell > MAX_COL + 1)
    1393           0 :         nEndCell = MAX_COL + 1;
    1394             : 
    1395           0 :     for (;nStartCell < nEndCell; ++nStartCell)
    1396           0 :         maDirections[nStartCell] = nCode;
    1397             : }
    1398             : 
    1399         806 : void WW8TabBandDesc::ProcessSpacing(const sal_uInt8* pParams)
    1400             : {
    1401         806 :     sal_uInt8 nLen = pParams ? *(pParams - 1) : 0;
    1402             :     OSL_ENSURE(nLen == 6, "Unexpected spacing len");
    1403         806 :     if (nLen != 6)
    1404         806 :         return;
    1405         806 :     mbHasSpacing=true;
    1406             : #if OSL_DEBUG_LEVEL > 0
    1407             :     sal_uInt8 nWhichCell = *pParams;
    1408             :     OSL_ENSURE(nWhichCell == 0, "Expected cell to be 0!");
    1409             : #endif
    1410         806 :     ++pParams; //Skip which cell
    1411         806 :     ++pParams; //unknown byte
    1412             : 
    1413         806 :     sal_uInt8 nSideBits = *pParams++;
    1414             :     OSL_ENSURE(nSideBits < 0x10, "Unexpected value for nSideBits");
    1415         806 :     ++pParams; //unknown byte
    1416         806 :     sal_uInt16 nValue =  SVBT16ToShort( pParams );
    1417        4030 :     for (int i = wwTOP; i <= wwRIGHT; i++)
    1418             :     {
    1419        3224 :         switch (nSideBits & (1 << i))
    1420             :         {
    1421             :             case 1 << wwTOP:
    1422         287 :                 mnDefaultTop = nValue;
    1423         287 :                 break;
    1424             :             case 1 << wwLEFT:
    1425         311 :                 mnDefaultLeft = nValue;
    1426         311 :                 break;
    1427             :             case 1 << wwBOTTOM:
    1428         289 :                 mnDefaultBottom = nValue;
    1429         289 :                 break;
    1430             :             case 1 << wwRIGHT:
    1431         311 :                 mnDefaultRight = nValue;
    1432         311 :                 break;
    1433             :             case 0:
    1434        2026 :                 break;
    1435             :             default:
    1436             :                 OSL_ENSURE(false, "Impossible");
    1437           0 :                 break;
    1438             :         }
    1439             :     }
    1440             : }
    1441             : 
    1442           0 : void WW8TabBandDesc::ProcessSpecificSpacing(const sal_uInt8* pParams)
    1443             : {
    1444           0 :     sal_uInt8 nLen = pParams ? *(pParams - 1) : 0;
    1445             :     OSL_ENSURE(nLen == 6, "Unexpected spacing len");
    1446           0 :     if (nLen != 6)
    1447           0 :         return;
    1448           0 :     sal_uInt8 nWhichCell = *pParams++;
    1449             :     OSL_ENSURE(nWhichCell < MAX_COL + 1, "Cell out of range in spacings");
    1450           0 :     if (nWhichCell >= MAX_COL + 1)
    1451           0 :         return;
    1452             : 
    1453           0 :     ++pParams; //unknown byte
    1454           0 :     sal_uInt8 nSideBits = *pParams++;
    1455             :     OSL_ENSURE(nSideBits < 0x10, "Unexpected value for nSideBits");
    1456           0 :     nOverrideSpacing[nWhichCell] |= nSideBits;
    1457             : 
    1458             :     OSL_ENSURE(nOverrideSpacing[nWhichCell] < 0x10,
    1459             :         "Unexpected value for nSideBits");
    1460             : #if OSL_DEBUG_LEVEL > 0
    1461             :     sal_uInt8 nUnknown2 = *pParams;
    1462             :     OSL_ENSURE(nUnknown2 == 0x3, "Unexpected value for spacing2");
    1463             : #endif
    1464           0 :     ++pParams;
    1465           0 :     sal_uInt16 nValue =  SVBT16ToShort( pParams );
    1466             : 
    1467           0 :     for (int i=0; i < 4; i++)
    1468             :     {
    1469           0 :         if (nSideBits & (1 << i))
    1470           0 :             nOverrideValues[nWhichCell][i] = nValue;
    1471             :     }
    1472             : }
    1473             : 
    1474           1 : void WW8TabBandDesc::ProcessSprmTDelete(const sal_uInt8* pParamsTDelete)
    1475             : {
    1476           1 :     if( nWwCols && pParamsTDelete )        // set one or more cell length(s)
    1477             :     {
    1478           1 :         sal_uInt8 nitcFirst= pParamsTDelete[0]; // first col to be deleted
    1479           1 :         if (nitcFirst >= nWwCols) // first index to delete from doesn't exist
    1480           0 :             return;
    1481           1 :         sal_uInt8 nitcLim  = pParamsTDelete[1]; // (last col to be deleted)+1
    1482           1 :         if (nitcLim <= nitcFirst) // second index to delete to is not greater than first index
    1483           0 :             return;
    1484             : 
    1485             :         /*
    1486             :          * sprmTDelete causes any rgdxaCenter and rgtc entries whose index is
    1487             :          * greater than or equal to itcLim to be moved
    1488             :          */
    1489           1 :         int nShlCnt  = nWwCols - nitcLim; // count of cells to be shifted
    1490             : 
    1491           1 :         if (nShlCnt >= 0) //There exist entries whose index is greater than or equal to itcLim
    1492             :         {
    1493           0 :             WW8_TCell* pAktTC  = pTCs + nitcFirst;
    1494           0 :             int i = 0;
    1495           0 :             while( i < nShlCnt )
    1496             :             {
    1497             :                 // adjust the left x-position
    1498           0 :                 nCenter[nitcFirst + i] = nCenter[nitcLim + i];
    1499             : 
    1500             :                 // adjust the cell's borders
    1501           0 :                 *pAktTC = pTCs[ nitcLim + i];
    1502             : 
    1503           0 :                 ++i;
    1504           0 :                 ++pAktTC;
    1505             :             }
    1506             :             // adjust the left x-position of the dummy at the very end
    1507           0 :             nCenter[nitcFirst + i] = nCenter[nitcLim + i];
    1508             :         }
    1509             : 
    1510           1 :         short nCellsDeleted = nitcLim - nitcFirst;
    1511             :         //clip delete request to available number of cells
    1512           1 :         if (nCellsDeleted > nWwCols)
    1513           1 :             nCellsDeleted = nWwCols;
    1514           1 :         nWwCols -= nCellsDeleted;
    1515             :     }
    1516             : }
    1517             : 
    1518             : // ReadShd reads the background color of a cell
    1519             : // ReadDef must be called before
    1520         242 : void WW8TabBandDesc::ReadShd(const sal_uInt8* pS )
    1521             : {
    1522         242 :     sal_uInt8 nLen = pS ? *(pS - 1) : 0;
    1523         242 :     if( !nLen )
    1524         242 :         return;
    1525             : 
    1526         242 :     if( !pSHDs )
    1527             :     {
    1528         242 :         pSHDs = new WW8_SHD[nWwCols];
    1529         242 :         memset( pSHDs, 0, nWwCols * sizeof( WW8_SHD ) );
    1530             :     }
    1531             : 
    1532         242 :     short nAnz = nLen >> 1;
    1533         242 :     if (nAnz > nWwCols)
    1534           0 :         nAnz = nWwCols;
    1535             : 
    1536             :     SVBT16 const * pShd;
    1537             :     int i;
    1538         816 :     for(i=0, pShd = reinterpret_cast<SVBT16 const *>(pS); i<nAnz; i++, pShd++ )
    1539         574 :         pSHDs[i].SetWWValue( *pShd );
    1540             : }
    1541             : 
    1542         242 : void WW8TabBandDesc::ReadNewShd(const sal_uInt8* pS, bool bVer67)
    1543             : {
    1544         242 :     sal_uInt8 nLen = pS ? *(pS - 1) : 0;
    1545         242 :     if (!nLen)
    1546         242 :         return;
    1547             : 
    1548         242 :     if (!pNewSHDs)
    1549         242 :         pNewSHDs = new sal_uInt32[nWwCols];
    1550             : 
    1551         242 :     short nAnz = nLen / 10; //10 bytes each
    1552         242 :     if (nAnz > nWwCols)
    1553           0 :         nAnz = nWwCols;
    1554             : 
    1555         242 :     int i=0;
    1556        1058 :     while (i < nAnz)
    1557         574 :         pNewSHDs[i++] = SwWW8ImplReader::ExtractColour(pS, bVer67);
    1558             : 
    1559         630 :     while (i < nWwCols)
    1560         146 :         pNewSHDs[i++] = COL_AUTO;
    1561             : }
    1562             : 
    1563        2148 : void WW8TabBandDesc::setcelldefaults(WW8_TCell *pCells, short nCols)
    1564             : {
    1565        2148 :     memset( pCells, 0, nCols * sizeof( WW8_TCell ) );
    1566        2148 : }
    1567             : 
    1568         297 : const sal_uInt8 *HasTabCellSprm(WW8PLCFx_Cp_FKP* pPap, bool bVer67)
    1569             : {
    1570             :     const sal_uInt8 *pParams;
    1571         297 :     if (bVer67)
    1572           0 :         pParams = pPap->HasSprm(24);
    1573             :     else
    1574             :     {
    1575         297 :         if (0 == (pParams = pPap->HasSprm(0x244B)))
    1576         282 :             pParams = pPap->HasSprm(0x2416);
    1577             :     }
    1578         297 :     return pParams;
    1579             : }
    1580             : 
    1581             : enum wwTableSprm
    1582             : {
    1583             :     sprmNil,
    1584             : 
    1585             :     sprmTTableWidth, sprmTTextFlow, sprmTFCantSplit, sprmTJc, sprmTFBiDi,
    1586             :     sprmTDefTable, sprmTDyaRowHeight, sprmTDefTableShd, sprmTDxaLeft,
    1587             :     sprmTSetBrc, sprmTSetBrc90, sprmTDxaCol, sprmTInsert, sprmTDelete,
    1588             :     sprmTTableHeader, sprmTDxaGapHalf, sprmTTableBorders, sprmTTableBorders90,
    1589             :     sprmTDefTableNewShd, sprmTCellPadding, sprmTCellPaddingDefault
    1590             : };
    1591             : 
    1592       10512 : wwTableSprm GetTableSprm(sal_uInt16 nId, ww::WordVersion eVer)
    1593             : {
    1594       10512 :     switch (eVer)
    1595             :     {
    1596             :         case ww::eWW8:
    1597       10512 :             switch (nId)
    1598             :             {
    1599             :                 case NS_sprm::LN_TTableWidth:
    1600         355 :                     return sprmTTableWidth;
    1601             :                 case NS_sprm::LN_TTextFlow:
    1602           0 :                     return sprmTTextFlow;
    1603             :                 case NS_sprm::LN_TTableHeader:
    1604           2 :                     return sprmTTableHeader;
    1605             :                 case NS_sprm::LN_TFCantSplit:
    1606         110 :                     return sprmTFCantSplit;
    1607             :                 case NS_sprm::LN_TJc90:
    1608         134 :                     return sprmTJc;
    1609             :                 case NS_sprm::LN_TFBiDi:
    1610         250 :                     return sprmTFBiDi;
    1611             :                 case NS_sprm::LN_TDelete:
    1612           1 :                     return sprmTDelete;
    1613             :                 case NS_sprm::LN_TInsert:
    1614         178 :                     return sprmTInsert;
    1615             :                 case NS_sprm::LN_TDxaCol:
    1616         416 :                     return sprmTDxaCol;
    1617             :                 case NS_sprm::LN_TDyaRowHeight:
    1618         189 :                     return sprmTDyaRowHeight;
    1619             :                 case NS_sprm::LN_TDxaLeft:
    1620         177 :                     return sprmTDxaLeft;
    1621             :                 case NS_sprm::LN_TDxaGapHalf:
    1622         366 :                     return sprmTDxaGapHalf;
    1623             :                 case NS_sprm::LN_TTableBorders80:
    1624         182 :                     return sprmTTableBorders;
    1625             :                 case NS_sprm::LN_TDefTable:
    1626         295 :                     return sprmTDefTable;
    1627             :                 case NS_sprm::LN_TDefTableShd80:
    1628         370 :                     return sprmTDefTableShd;
    1629             :                 case NS_sprm::LN_TDefTableShd:
    1630         370 :                     return sprmTDefTableNewShd;
    1631             :                 case NS_sprm::LN_TTableBorders:
    1632         326 :                     return sprmTTableBorders90;
    1633             :                 case NS_sprm::LN_TSetBrc80:
    1634           1 :                     return sprmTSetBrc;
    1635             :                 case NS_sprm::LN_TSetBrc:
    1636         297 :                     return sprmTSetBrc90;
    1637             :                 case NS_sprm::LN_TCellPadding:
    1638           0 :                     return sprmTCellPadding;
    1639             :                 case NS_sprm::LN_TCellPaddingDefault:
    1640         806 :                     return sprmTCellPaddingDefault;
    1641             :             }
    1642        5687 :             break;
    1643             :         case ww::eWW7:
    1644             :         case ww::eWW6:
    1645           0 :             switch (nId)
    1646             :             {
    1647             :                 case 182:
    1648           0 :                     return sprmTJc;
    1649             :                 case 183:
    1650           0 :                     return sprmTDxaLeft;
    1651             :                 case 184:
    1652           0 :                     return sprmTDxaGapHalf;
    1653             :                 case 186:
    1654           0 :                     return sprmTTableHeader;
    1655             :                 case 187:
    1656           0 :                     return sprmTTableBorders;
    1657             :                 case 189:
    1658           0 :                     return sprmTDyaRowHeight;
    1659             :                 case 190:
    1660           0 :                     return sprmTDefTable;
    1661             :                 case 191:
    1662           0 :                     return sprmTDefTableShd;
    1663             :                 case 193:
    1664           0 :                     return sprmTSetBrc;
    1665             :                 case 194:
    1666           0 :                     return sprmTInsert;
    1667             :                 case 195:
    1668           0 :                     return sprmTDelete;
    1669             :                 case 196:
    1670           0 :                     return sprmTDxaCol;
    1671             :             }
    1672           0 :             break;
    1673             :         case ww::eWW1:
    1674             :         case ww::eWW2:
    1675           0 :             switch (nId)
    1676             :             {
    1677             :                 case 146:
    1678           0 :                     return sprmTJc;
    1679             :                 case 147:
    1680           0 :                     return sprmTDxaLeft;
    1681             :                 case 148:
    1682           0 :                     return sprmTDxaGapHalf;
    1683             :                 case 153:
    1684           0 :                     return sprmTDyaRowHeight;
    1685             :                 case 154:
    1686           0 :                     return sprmTDefTable;
    1687             :                 case 155:
    1688           0 :                     return sprmTDefTableShd;
    1689             :                 case 157:
    1690           0 :                     return sprmTSetBrc;
    1691             :                 case 158:
    1692           0 :                     return sprmTInsert;
    1693             :                 case 159:
    1694           0 :                     return sprmTDelete;
    1695             :                 case 160:
    1696           0 :                     return sprmTDxaCol;
    1697             :             }
    1698           0 :             break;
    1699             :     }
    1700        5687 :     return sprmNil;
    1701             : }
    1702             : 
    1703          74 : WW8TabDesc::WW8TabDesc(SwWW8ImplReader* pIoClass, WW8_CP nStartCp) :
    1704             :     mpOldRedlineStack(0),
    1705             :     pIo(pIoClass),
    1706             :     pFirstBand(0),
    1707             :     pActBand(0),
    1708             :     pTmpPos(0),
    1709             :     pTableNd(0),
    1710             :     pTabLines(0),
    1711             :     pTabLine(0),
    1712             :     pTabBoxes(0),
    1713             :     pTabBox(0),
    1714             :     pAktWWCell(0),
    1715             :     nRows(0),
    1716             :     nDefaultSwCols(0),
    1717             :     nBands(0),
    1718             :     nMinLeft(0),
    1719             :     nConvertedLeft(0),
    1720             :     nMaxRight(0),
    1721             :     nSwWidth(0),
    1722             :     nPreferredWidth(0),
    1723             :     nOrgDxaLeft(0),
    1724             :     bOk(true),
    1725             :     bClaimLineFormat(false),
    1726             :     eOri(text::HoriOrientation::NONE),
    1727             :     bIsBiDi(false),
    1728             :     nAktRow(0),
    1729             :     nAktBandRow(0),
    1730             :     nAktCol(0),
    1731             :     nRowsToRepeat(0),
    1732             :     pTable(0),
    1733             :     pParentPos(0),
    1734             :     pFlyFormat(0),
    1735          74 :     aItemSet(pIo->m_rDoc.GetAttrPool(),RES_FRMATR_BEGIN,RES_FRMATR_END-1)
    1736             : {
    1737          74 :     pIo->m_bAktAND_fNumberAcross = false;
    1738             : 
    1739             :     static const sal_Int16 aOriArr[] =
    1740             :     {
    1741             :         text::HoriOrientation::LEFT, text::HoriOrientation::CENTER, text::HoriOrientation::RIGHT, text::HoriOrientation::CENTER
    1742             :     };
    1743             : 
    1744          74 :     bool bOldVer = ww::IsSevenMinus(pIo->GetFib().GetFIBVersion());
    1745             :     WW8_TablePos aTabPos;
    1746             : 
    1747             :     WW8PLCFxSave1 aSave;
    1748          74 :     pIo->m_pPlcxMan->GetPap()->Save( aSave );
    1749             : 
    1750          74 :     WW8PLCFx_Cp_FKP* pPap = pIo->m_pPlcxMan->GetPapPLCF();
    1751             : 
    1752          74 :     eOri = text::HoriOrientation::LEFT;
    1753             : 
    1754          74 :     WW8TabBandDesc* pNewBand = new WW8TabBandDesc;
    1755             : 
    1756          74 :     wwSprmParser aSprmParser(pIo->GetFib().GetFIBVersion());
    1757             : 
    1758             :     // process pPap until end of table found
    1759             :     do
    1760             :     {
    1761         297 :         short nTabeDxaNew      = SHRT_MAX;
    1762         297 :         bool bTabRowJustRead   = false;
    1763         297 :         const sal_uInt8* pShadeSprm = 0;
    1764         297 :         const sal_uInt8* pNewShadeSprm = 0;
    1765         297 :         const sal_uInt8* pTableBorders = 0;
    1766         297 :         const sal_uInt8* pTableBorders90 = 0;
    1767         520 :         std::vector<const sal_uInt8*> aTSetBrcs, aTSetBrc90s;
    1768         297 :         WW8_TablePos *pTabPos  = 0;
    1769             : 
    1770             :         // search end of a tab row
    1771         297 :         if(!(pIo->SearchRowEnd(pPap, nStartCp, pIo->m_nInTable)))
    1772             :         {
    1773           0 :             bOk = false;
    1774           0 :             break;
    1775             :         }
    1776             : 
    1777             :         // Get the SPRM chains:
    1778             :         // first from PAP and then from PCD (of the Piece Table)
    1779         297 :         WW8PLCFxDesc aDesc;
    1780         297 :         pPap->GetSprms( &aDesc );
    1781         297 :         WW8SprmIter aSprmIter(aDesc.pMemPos, aDesc.nSprmsLen, aSprmParser);
    1782             : 
    1783         891 :         for (int nLoop = 0; nLoop < 2; ++nLoop)
    1784             :         {
    1785         594 :             bool bRepeatedSprm = false;
    1786             :             const sal_uInt8* pParams;
    1787       11700 :             while (aSprmIter.GetSprms() && 0 != (pParams = aSprmIter.GetAktParams()))
    1788             :             {
    1789       10512 :                 sal_uInt16 nId = aSprmIter.GetAktId();
    1790       10512 :                 wwTableSprm eSprm = GetTableSprm(nId, pIo->GetFib().GetFIBVersion());
    1791       10512 :                 switch (eSprm)
    1792             :                 {
    1793             :                     case sprmTTableWidth:
    1794             :                         {
    1795         355 :                         const sal_uInt8 b0 = pParams[0];
    1796         355 :                         const sal_uInt8 b1 = pParams[1];
    1797         355 :                         const sal_uInt8 b2 = pParams[2];
    1798         355 :                         if (b0 == 3) // Twips
    1799          93 :                             nPreferredWidth = b2 * 0x100 + b1;
    1800             :                         }
    1801         355 :                         break;
    1802             :                     case sprmTTextFlow:
    1803           0 :                         pNewBand->ProcessDirection(pParams);
    1804           0 :                         break;
    1805             :                     case sprmTFCantSplit:
    1806         110 :                         pNewBand->bCantSplit = *pParams;
    1807         110 :                         bClaimLineFormat = true;
    1808         110 :                         break;
    1809             :                     case sprmTTableBorders:
    1810         182 :                         pTableBorders = pParams; // process at end
    1811         182 :                         break;
    1812             :                     case sprmTTableBorders90:
    1813         326 :                         pTableBorders90 = pParams; // process at end
    1814         326 :                         break;
    1815             :                     case sprmTTableHeader:
    1816           2 :                         if (!bRepeatedSprm)
    1817             :                         {
    1818           1 :                             nRowsToRepeat++;
    1819           1 :                             bRepeatedSprm = true;
    1820             :                         }
    1821           2 :                         break;
    1822             :                     case sprmTJc:
    1823             :                         // sprmTJc  -  Justification Code
    1824         134 :                         if (nRows == 0)
    1825          11 :                             eOri = aOriArr[*pParams & 0x3];
    1826         134 :                         break;
    1827             :                     case sprmTFBiDi:
    1828         250 :                         bIsBiDi = SVBT16ToShort(pParams) != 0;
    1829         250 :                         break;
    1830             :                     case sprmTDxaGapHalf:
    1831         366 :                         pNewBand->nGapHalf = (sal_Int16)SVBT16ToShort( pParams );
    1832         366 :                         break;
    1833             :                     case sprmTDyaRowHeight:
    1834         189 :                         pNewBand->nLineHeight = (sal_Int16)SVBT16ToShort( pParams );
    1835         189 :                         bClaimLineFormat = true;
    1836         189 :                         break;
    1837             :                     case sprmTDefTable:
    1838         295 :                         pNewBand->ReadDef(bOldVer, pParams);
    1839         295 :                         bTabRowJustRead = true;
    1840         295 :                         break;
    1841             :                     case sprmTDefTableShd:
    1842         370 :                         pShadeSprm = pParams;
    1843         370 :                         break;
    1844             :                     case sprmTDefTableNewShd:
    1845         370 :                         pNewShadeSprm = pParams;
    1846         370 :                         break;
    1847             :                     case sprmTDxaLeft:
    1848             :                         // our Writer cannot shift single table lines
    1849             :                         // horizontally so we have to find the smallest
    1850             :                         // parameter (meaning the left-most position) and then
    1851             :                         // shift the whole table to that margin (see below)
    1852             :                         {
    1853         177 :                             short nDxaNew = (sal_Int16)SVBT16ToShort( pParams );
    1854         177 :                             nOrgDxaLeft = nDxaNew;
    1855         177 :                             if( nDxaNew < nTabeDxaNew )
    1856         177 :                                 nTabeDxaNew = nDxaNew;
    1857             :                         }
    1858         177 :                         break;
    1859             :                     case sprmTSetBrc:
    1860           1 :                         aTSetBrcs.push_back(pParams); // process at end
    1861           1 :                         break;
    1862             :                     case sprmTSetBrc90:
    1863         297 :                         aTSetBrc90s.push_back(pParams); // process at end
    1864         297 :                         break;
    1865             :                     case sprmTDxaCol:
    1866         416 :                         pNewBand->ProcessSprmTDxaCol(pParams);
    1867         416 :                         break;
    1868             :                     case sprmTInsert:
    1869         178 :                         pNewBand->ProcessSprmTInsert(pParams);
    1870         178 :                         break;
    1871             :                     case sprmTDelete:
    1872           1 :                         pNewBand->ProcessSprmTDelete(pParams);
    1873           1 :                         break;
    1874             :                     case sprmTCellPaddingDefault:
    1875         806 :                         pNewBand->ProcessSpacing(pParams);
    1876         806 :                         break;
    1877             :                     case sprmTCellPadding:
    1878           0 :                         pNewBand->ProcessSpecificSpacing(pParams);
    1879           0 :                         break;
    1880             :                     default:
    1881             :                         ;
    1882             :                 }
    1883       10512 :                 aSprmIter.advance();
    1884             :             }
    1885             : 
    1886         594 :             if( !nLoop )
    1887             :             {
    1888         297 :                 pPap->GetPCDSprms(  aDesc );
    1889         297 :                 aSprmIter.SetSprms( aDesc.pMemPos, aDesc.nSprmsLen );
    1890             :             }
    1891             :         }
    1892             : 
    1893             :         // WW-Tables can contain Fly-changes. For this abort tables here
    1894             :         // and start again. *pPap is still before TabRowEnd, so TestApo()
    1895             :         // can be called with the last parameter set to false and therefore
    1896             :         // take effect.
    1897             : 
    1898         297 :         if (bTabRowJustRead)
    1899             :         {
    1900             :             // Some SPRMs need to be processed *after* ReadDef is called
    1901             :             // so they were saved up until here
    1902         295 :             if (pShadeSprm)
    1903         242 :                 pNewBand->ReadShd(pShadeSprm);
    1904         295 :             if (pNewShadeSprm)
    1905         242 :                 pNewBand->ReadNewShd(pNewShadeSprm, bOldVer);
    1906         295 :             if (pTableBorders90)
    1907         177 :                 pNewBand->ProcessSprmTTableBorders(9, pTableBorders90);
    1908         118 :             else if (pTableBorders)
    1909             :                 pNewBand->ProcessSprmTTableBorders(bOldVer ? 6 : 8,
    1910           3 :                     pTableBorders);
    1911         295 :             std::vector<const sal_uInt8*>::const_iterator iter;
    1912         296 :             for (iter = aTSetBrcs.begin(); iter != aTSetBrcs.end(); ++iter)
    1913           1 :                 pNewBand->ProcessSprmTSetBRC(bOldVer ? 6 : 8, *iter);
    1914         592 :             for (iter = aTSetBrc90s.begin(); iter != aTSetBrc90s.end(); ++iter)
    1915         297 :                 pNewBand->ProcessSprmTSetBRC(9, *iter);
    1916             :         }
    1917             : 
    1918         297 :         if( nTabeDxaNew < SHRT_MAX )
    1919             :         {
    1920         177 :             short* pCenter  = pNewBand->nCenter;
    1921         177 :             short firstDxaCenter = *pCenter;
    1922         761 :             for( int i = 0; i < pNewBand->nWwCols; i++, ++pCenter )
    1923             :             {
    1924             :                 // #i30298# Use sprmTDxaLeft to adjust the left indent
    1925             :                 // #i40461# Use dxaGapHalf during calculation
    1926             :                 *pCenter +=
    1927         584 :                     (nTabeDxaNew - (firstDxaCenter + pNewBand->nGapHalf));
    1928             :             }
    1929             :         }
    1930             : 
    1931         297 :         if (!pActBand)
    1932          74 :             pActBand = pFirstBand = pNewBand;
    1933             :         else
    1934             :         {
    1935         223 :             pActBand->pNextBand = pNewBand;
    1936         223 :             pActBand = pNewBand;
    1937             :         }
    1938         297 :         nBands++;
    1939             : 
    1940         297 :         pNewBand = new WW8TabBandDesc;
    1941             : 
    1942         297 :         nRows++;
    1943         297 :         pActBand->nRows++;
    1944             : 
    1945             :         //Seek our pap to its next block of properties
    1946         297 :         WW8PLCFxDesc aRes;
    1947         297 :         aRes.pMemPos = 0;
    1948         297 :         aRes.nStartPos = nStartCp;
    1949             : 
    1950         297 :         if (!(pPap->SeekPos(aRes.nStartPos)))
    1951             :         {
    1952           0 :             aRes.nEndPos = WW8_CP_MAX;
    1953           0 :             pPap->SetDirty(true);
    1954             :         }
    1955         297 :         pPap->GetSprms(&aRes);
    1956         297 :         pPap->SetDirty(false);
    1957             : 
    1958             :         //Are we at the end of available properties
    1959         297 :         if (
    1960         594 :              !pPap->HasFkp() || pPap->Where() == WW8_CP_MAX ||
    1961         297 :              aRes.nStartPos == WW8_CP_MAX
    1962             :            )
    1963             :         {
    1964           0 :             bOk = false;
    1965           0 :             break;
    1966             :         }
    1967             : 
    1968             :         //Are we still in a table cell
    1969         297 :         const sal_uInt8* pParams = HasTabCellSprm(pPap, bOldVer);
    1970         297 :         const sal_uInt8 *pLevel = pPap->HasSprm(0x6649);
    1971             :         // InTable
    1972         297 :         if (!pParams || (1 != *pParams) ||
    1973         233 :             (pLevel && (*pLevel <= pIo->m_nInTable)))
    1974             :         {
    1975             :             break;
    1976             :         }
    1977             : 
    1978             :         //Get the end of row new table positioning data
    1979         224 :         WW8_CP nMyStartCp=nStartCp;
    1980         224 :         if (pIo->SearchRowEnd(pPap, nMyStartCp, pIo->m_nInTable))
    1981         224 :             if (pIo->ParseTabPos(&aTabPos, pPap))
    1982           7 :                 pTabPos = &aTabPos;
    1983             : 
    1984             :         //Move back to this cell
    1985         224 :         aRes.pMemPos = 0;
    1986         224 :         aRes.nStartPos = nStartCp;
    1987             : 
    1988             :         // PlcxMan currently points too far ahead so we need to bring
    1989             :         // it back to where we are trying to make a table
    1990         224 :         pIo->m_pPlcxMan->GetPap()->nOrigStartPos = aRes.nStartPos;
    1991         224 :         if (!(pPap->SeekPos(aRes.nStartPos)))
    1992             :         {
    1993           0 :             aRes.nEndPos = WW8_CP_MAX;
    1994           0 :             pPap->SetDirty(true);
    1995             :         }
    1996         224 :         pPap->GetSprms(&aRes);
    1997         224 :         pPap->SetDirty(false);
    1998             : 
    1999             :         //Does this row match up with the last row closely enough to be
    2000             :         //considered part of the same table
    2001         224 :         ApoTestResults aApo = pIo->TestApo(pIo->m_nInTable + 1, false, pTabPos);
    2002             : 
    2003             :         /*
    2004             :         ##513##, #79474# If this is not sufficient, then we should look at
    2005             :         sprmPD{y|x}aAbs as our indicator that the following set of rows is not
    2006             :         part of this table, but instead is an absolutely positioned table
    2007             :         outside of this one
    2008             :         */
    2009         224 :         if (aApo.mbStopApo)
    2010           1 :             break;
    2011         223 :         if (aApo.mbStartApo)
    2012             :         {
    2013             :             //if there really is a fly here, and not a "null" fly then break.
    2014           0 :             WW8FlyPara *pNewFly = pIo->ConstructApo(aApo, pTabPos);
    2015           0 :             if (pNewFly)
    2016           0 :                 delete pNewFly;
    2017             :             else
    2018           0 :                 break;
    2019             :         }
    2020             : 
    2021         446 :         nStartCp = aRes.nEndPos;
    2022             :     }
    2023             :     while(true);
    2024             : 
    2025          74 :     if( bOk )
    2026             :     {
    2027          74 :         if( pActBand->nRows > 1 )
    2028             :         {
    2029             :             // last band has more than 1 cell
    2030           0 :             delete pNewBand;
    2031           0 :             pNewBand = new WW8TabBandDesc( *pActBand ); // create new
    2032           0 :             pActBand->nRows--;      // wegen Sonderbehandlung Raender-Defaults
    2033           0 :             pNewBand->nRows = 1;
    2034           0 :             pActBand->pNextBand = pNewBand; // am Ende einschleifen
    2035           0 :             nBands++;
    2036           0 :             pNewBand = 0;                   // do not delete
    2037             :         }
    2038          74 :         CalcDefaults();
    2039             :     }
    2040          74 :     delete pNewBand;
    2041             : 
    2042         297 :     pIo->m_pPlcxMan->GetPap()->Restore( aSave );
    2043          74 : }
    2044             : 
    2045         148 : WW8TabDesc::~WW8TabDesc()
    2046             : {
    2047          74 :     WW8TabBandDesc* pR = pFirstBand;
    2048         445 :     while(pR)
    2049             :     {
    2050         297 :         WW8TabBandDesc* pR2 = pR->pNextBand;
    2051         297 :         delete pR;
    2052         297 :         pR = pR2;
    2053             :     }
    2054             : 
    2055          74 :     delete pParentPos;
    2056          74 : }
    2057             : 
    2058          74 : void WW8TabDesc::CalcDefaults()
    2059             : {
    2060          74 :     short nMinCols = SHRT_MAX;
    2061             :     WW8TabBandDesc* pR;
    2062             : 
    2063          74 :     nMinLeft = SHRT_MAX;
    2064          74 :     nMaxRight = SHRT_MIN;
    2065             : 
    2066             :     /*
    2067             :     If we are an honestly inline centered table, then the normal rules of
    2068             :     engagement for left and right margins do not apply. The multiple rows are
    2069             :     centered regardless of the actual placement of rows, so we cannot have
    2070             :     mismatched rows as is possible in other configurations.
    2071             : 
    2072             :     e.g. change the example bugdoc in word from text wrapping of none (inline)
    2073             :     to around (in frame (bApo)) and the table splits into two very disjoint
    2074             :     rows as the beginning point of each row are very different
    2075             :     */
    2076          74 :     if ((!pIo->InLocalApo()) && (eOri == text::HoriOrientation::CENTER))
    2077             :     {
    2078           4 :         for (pR = pFirstBand; pR; pR = pR->pNextBand)
    2079          15 :             for( short i = pR->nWwCols; i >= 0; --i)
    2080          12 :                 pR->nCenter[i] = pR->nCenter[i] -  pR->nCenter[0];
    2081             :     }
    2082             : 
    2083             :     // 1. Durchlauf: aeusserste L- und R-Grenzen finden
    2084         371 :     for( pR = pFirstBand; pR; pR = pR->pNextBand )
    2085             :     {
    2086         297 :         if( pR->nCenter[0] < nMinLeft )
    2087          74 :             nMinLeft = pR->nCenter[0];
    2088             : 
    2089        1407 :         for( short i = 0; i < pR->nWwCols; i++ )
    2090             :         {
    2091             :            /*
    2092             :             If the margins are so large as to make the displayable
    2093             :             area inside them smaller than the minimum allowed then adjust the
    2094             :             width to fit. But only do it if the two cells are not the exact
    2095             :             same value, if they are then the cell does not really exist and will
    2096             :             be blended together into the same cell through the use of the
    2097             :             nTrans(late) array.
    2098             :             #i28333# If the nGapHalf is greater than the cell width best to ignore it
    2099             :             */
    2100        1110 :             int nCellWidth = pR->nCenter[i+1] - pR->nCenter[i];
    2101        1110 :             if (nCellWidth && ((nCellWidth - pR->nGapHalf*2) < MINLAY) && pR->nGapHalf < nCellWidth)
    2102             :             {
    2103          33 :                 pR->nCenter[i+1] = pR->nCenter[i]+MINLAY+pR->nGapHalf * 2;
    2104             :             }
    2105             :         }
    2106             : 
    2107         297 :         if( pR->nCenter[pR->nWwCols] > nMaxRight )
    2108          82 :             nMaxRight = pR->nCenter[pR->nWwCols];
    2109             :     }
    2110          74 :     nSwWidth = nMaxRight - nMinLeft;
    2111             : 
    2112             :     // If the table is right aligned we need to align all rows to the
    2113             :     // row that has the furthest right point
    2114             : 
    2115          74 :     if(eOri == text::HoriOrientation::RIGHT)
    2116             :     {
    2117         141 :         for( pR = pFirstBand; pR; pR = pR->pNextBand )
    2118             :         {
    2119         131 :             int adjust = nMaxRight - pR->nCenter[pR->nWwCols];
    2120         591 :             for( short i = 0; i < pR->nWwCols + 1; i++ )
    2121             :             {
    2122         460 :                 pR->nCenter[i] = static_cast< short >(pR->nCenter[i] + adjust);
    2123             :             }
    2124             : 
    2125             :         }
    2126             :     }
    2127             : 
    2128             :     // 2. pass: Detect number of writer columns. This can exceed the count
    2129             :     // of columns in WW by 2, because SW in constrast to WW does not provide
    2130             :     // fringed left and right borders and has to fill with empty boxes.
    2131             :     // Non exisitent cells can reduce the number of columns.
    2132             : 
    2133             :     // 3. pass: Replace border with defaults if needed
    2134          74 :     nConvertedLeft = nMinLeft;
    2135             : 
    2136          74 :     short nLeftMaxThickness = 0, nRightMaxThickness=0;
    2137         371 :     for( pR = pFirstBand ; pR; pR = pR->pNextBand )
    2138             :     {
    2139         297 :         if( !pR->pTCs )
    2140             :         {
    2141           2 :             pR->pTCs = new WW8_TCell[ pR->nWwCols ];
    2142           2 :             memset( pR->pTCs, 0, pR->nWwCols * sizeof( WW8_TCell ) );
    2143             :         }
    2144        1407 :         for (int k = 0; k < pR->nWwCols; ++k)
    2145             :         {
    2146        1110 :             WW8_TCell* pT = &pR->pTCs[k];
    2147             :             int i, j;
    2148        5550 :             for( i = 0; i < 4; i ++ )
    2149             :             {
    2150        4440 :                 if (pT->rgbrc[i].brcType()==0)
    2151             :                 {
    2152             :                     // if shadow is set, its invalid
    2153        3405 :                     j = i;
    2154        3405 :                     switch( i )
    2155             :                     {
    2156             :                     case 0:
    2157             :                         // outer top / horizontally inside
    2158         836 :                         j = (pR == pFirstBand) ? 0 : 4;
    2159         836 :                         break;
    2160             :                     case 1:
    2161             :                         // outer left / vertically inside
    2162         834 :                         j = k ? 5 : 1;
    2163         834 :                         break;
    2164             :                     case 2:
    2165             :                         // outer bottom  / horizontally inside
    2166         783 :                         j = pR->pNextBand ? 4 : 2;
    2167         783 :                         break;
    2168             :                     case 3:
    2169             :                         // outer right / vertically inside
    2170         952 :                         j = (k == pR->nWwCols - 1) ? 3 : 5;
    2171         952 :                         break;
    2172             :                     }
    2173             :                     // mangel mit Defaults ueber
    2174        3405 :                     pT->rgbrc[i] = pR->aDefBrcs[j];
    2175             :                 }
    2176             :             }
    2177             :         }
    2178         297 :         if (pR->nWwCols)
    2179             :         {
    2180             :             /*
    2181             :             Similar to graphics and other elements word does not totally
    2182             :             factor the width of the border into its calculations of size, we
    2183             :             do so we must adjust out widths and other dimensions to fit.  It
    2184             :             appears that what occurs is that the last cell's right margin if
    2185             :             the margin width that is not calculated into winwords table
    2186             :             dimensions, so in that case increase the table to include the
    2187             :             extra width of the right margin.
    2188             :             */
    2189         294 :             if ( ! pR->pTCs[pR->nWwCols-1].rgbrc[3].fShadow() )
    2190             :             {
    2191         293 :                 short nThickness = pR->pTCs[pR->nWwCols-1].rgbrc[3].
    2192         293 :                     DetermineBorderProperties();
    2193         293 :                 pR->nCenter[pR->nWwCols] = pR->nCenter[pR->nWwCols] + nThickness;
    2194         293 :                 if (nThickness > nRightMaxThickness)
    2195          59 :                     nRightMaxThickness = nThickness;
    2196             :             }
    2197             : 
    2198             :             /*
    2199             :             The left space of the table is in nMinLeft, but again this
    2200             :             does not consider the margin thickness to its left in the
    2201             :             placement value, so get the thickness of the left border,
    2202             :             half is placed to the left of the nominal left side, and
    2203             :             half to the right.
    2204             :             */
    2205         294 :             if ( ! pR->pTCs[0].rgbrc[1].fShadow() )
    2206             :             {
    2207         293 :                 short nThickness = pR->pTCs[0].rgbrc[1].
    2208         293 :                     DetermineBorderProperties();
    2209         293 :                 if (nThickness > nLeftMaxThickness)
    2210          60 :                     nLeftMaxThickness = nThickness;
    2211             :             }
    2212             :         }
    2213             :     }
    2214          74 :     nSwWidth = nSwWidth + nRightMaxThickness;
    2215          74 :     nMaxRight = nMaxRight + nRightMaxThickness;
    2216          74 :     nConvertedLeft = nMinLeft-(nLeftMaxThickness/2);
    2217             : 
    2218         371 :     for( pR = pFirstBand; pR; pR = pR->pNextBand )
    2219             :     {
    2220         297 :         pR->nSwCols = pR->nWwCols;
    2221         297 :         pR->bLEmptyCol = pR->nCenter[0] - nMinLeft >= MINLAY;
    2222         297 :         pR->bREmptyCol = (nMaxRight - pR->nCenter[pR->nWwCols] - nRightMaxThickness) >= MINLAY;
    2223             : 
    2224         297 :         short nAddCols = short(pR->bLEmptyCol) + short(pR->bREmptyCol);
    2225             :         sal_uInt16 i;
    2226         297 :         sal_uInt16 j = ( pR->bLEmptyCol ) ? 1 : 0;
    2227        1407 :         for (i = 0; i < pR->nWwCols; ++i)
    2228             :         {
    2229        1110 :             pR->nTransCell[i] = (sal_Int8)j;
    2230        1110 :             if ( pR->nCenter[i] < pR->nCenter[i+1] )
    2231             :             {
    2232         981 :                 pR->bExist[i] = true;
    2233         981 :                 j++;
    2234             :             }
    2235             :             else
    2236             :             {
    2237         129 :                 pR->bExist[i] = false;
    2238         129 :                 nAddCols--;
    2239             :             }
    2240             :         }
    2241             : 
    2242             :         OSL_ENSURE(i,"no columns in row ?");
    2243             : 
    2244             :         /*
    2245             :         If the last cell was "false" then there is no valid cell following it,
    2246             :         so the default mapping forward wont't work. So map it (and
    2247             :         contiguous invalid cells backwards to the last valid cell instead.
    2248             :         */
    2249         297 :         if (i && !pR->bExist[i-1])
    2250             :         {
    2251           2 :             sal_uInt16 k=i-1;
    2252           6 :             while (k && !pR->bExist[k])
    2253           2 :                 k--;
    2254           4 :             for (sal_uInt16 n=k+1;n<i;n++)
    2255           2 :                 pR->nTransCell[n] = pR->nTransCell[k];
    2256             :         }
    2257             : 
    2258         297 :         pR->nTransCell[i++] = (sal_Int8)(j++);  // Can exceed by 2 among other
    2259         297 :         pR->nTransCell[i] = (sal_Int8)j;        // things because of bREmptyCol
    2260             : 
    2261         297 :         pR->nSwCols = pR->nSwCols + nAddCols;
    2262         297 :         if( pR->nSwCols < nMinCols )
    2263          81 :             nMinCols = pR->nSwCols;
    2264             :     }
    2265             : 
    2266             :     /*
    2267             :     #i9718#
    2268             :     Find the largest of the borders on cells that adjoin top bottom and remove
    2269             :     the val from the top and put in on the bottom cell. I can't seem to make
    2270             :     disjoint upper and lowers to see what happens there.
    2271             :     */
    2272             : 
    2273         107 :     if ((nMinLeft && !bIsBiDi && text::HoriOrientation::LEFT == eOri) ||
    2274          62 :         (nMinLeft != -108 && bIsBiDi && text::HoriOrientation::RIGHT == eOri)) // Word sets the first nCenter value to -108 when no indent is used
    2275          46 :         eOri = text::HoriOrientation::LEFT_AND_WIDTH; //  absolutely positioned
    2276             : 
    2277          74 :     nDefaultSwCols = nMinCols;  // because inserting cells is cheaper than merging
    2278          74 :     if( nDefaultSwCols == 0 )
    2279           0 :         bOk = false;
    2280          74 :     pActBand = pFirstBand;
    2281          74 :     nAktBandRow = 0;
    2282             :     OSL_ENSURE( pActBand, "pActBand ist 0" );
    2283          74 : }
    2284             : 
    2285          74 : void WW8TabDesc::SetSizePosition(SwFrameFormat* pFrameFormat)
    2286             : {
    2287          74 :     SwFrameFormat* pApply = pFrameFormat;
    2288          74 :     if (!pApply )
    2289          74 :         pApply = pTable->GetFrameFormat();
    2290             :     OSL_ENSURE(pApply,"No frame");
    2291          74 :     pApply->SetFormatAttr(aItemSet);
    2292          74 :     if (pFrameFormat)
    2293             :     {
    2294           0 :         SwFormatFrmSize aSize = pFrameFormat->GetFrmSize();
    2295           0 :         aSize.SetHeightSizeType(ATT_MIN_SIZE);
    2296           0 :         aSize.SetHeight(MINLAY);
    2297           0 :         pFrameFormat->SetFormatAttr(aSize);
    2298           0 :         pTable->GetFrameFormat()->SetFormatAttr(SwFormatHoriOrient(0,text::HoriOrientation::FULL));
    2299             :     }
    2300          74 : }
    2301             : 
    2302          74 : void wwSectionManager::PrependedInlineNode(const SwPosition &rPos,
    2303             :     const SwNode &rNode)
    2304             : {
    2305             :     OSL_ENSURE(!maSegments.empty(),
    2306             :         "should not be possible, must be at least one segment");
    2307          74 :     if ((!maSegments.empty()) && (maSegments.back().maStart == rPos.nNode))
    2308          15 :         maSegments.back().maStart = SwNodeIndex(rNode);
    2309          74 : }
    2310             : 
    2311          74 : void WW8TabDesc::CreateSwTable(SvxULSpaceItem* pULSpaceItem)
    2312             : {
    2313          74 :     ::SetProgressState(pIo->m_nProgress, pIo->m_pDocShell);   // Update
    2314             : 
    2315             :     // if there is already some content on the Node append new node to ensure
    2316             :     // that this content remains ABOVE the table
    2317          74 :     SwPosition* pPoint = pIo->m_pPaM->GetPoint();
    2318          74 :     bool bInsNode = pPoint->nContent.GetIndex() != 0;
    2319          74 :     bool bSetMinHeight = false;
    2320             : 
    2321             :     /*
    2322             :      #i8062#
    2323             :      Set fly anchor to its anchor pos, so that if a table starts immediately
    2324             :      at this position a new node will be inserted before inserting the table.
    2325             :     */
    2326          74 :     if (!bInsNode && pIo->m_pFormatOfJustInsertedApo)
    2327             :     {
    2328             :         const SwPosition* pAPos =
    2329           0 :             pIo->m_pFormatOfJustInsertedApo->GetAnchor().GetContentAnchor();
    2330           0 :         if (pAPos && &pAPos->nNode.GetNode() == &pPoint->nNode.GetNode())
    2331             :         {
    2332           0 :             bInsNode = true;
    2333           0 :             bSetMinHeight = true;
    2334             : 
    2335           0 :             SwFormatSurround aSur(pIo->m_pFormatOfJustInsertedApo->GetSurround());
    2336           0 :             aSur.SetAnchorOnly(true);
    2337           0 :             pIo->m_pFormatOfJustInsertedApo->SetFormatAttr(aSur);
    2338             :         }
    2339             :     }
    2340             : 
    2341          74 :     if (bSetMinHeight)
    2342             :     {
    2343             :         // minimize Fontsize to minimize height growth of the header/footer
    2344             :         // set font size to 1 point to minimize y-growth of Hd/Ft
    2345           0 :         SvxFontHeightItem aSz(20, 100, RES_CHRATR_FONTSIZE);
    2346           0 :         pIo->NewAttr( aSz );
    2347           0 :         pIo->m_pCtrlStck->SetAttr(*pPoint, RES_CHRATR_FONTSIZE);
    2348             :     }
    2349             : 
    2350          74 :     if (bInsNode)
    2351           0 :         pIo->AppendTextNode(*pPoint);
    2352             : 
    2353          74 :     pTmpPos = new SwPosition( *pIo->m_pPaM->GetPoint() );
    2354             : 
    2355             :     // The table is small: The number of columns is the lowest count of
    2356             :     // columns of the origin, because inserting is faster than deleting.
    2357             :     // The number of rows is the count of bands because (identically)
    2358             :     // rows of a band can be duplicated easy.
    2359             :     pTable = pIo->m_rDoc.InsertTable(
    2360             :             SwInsertTableOptions( tabopts::HEADLINE_NO_BORDER, 0 ),
    2361          74 :             *pTmpPos, nBands, nDefaultSwCols, eOri, 0, 0, false, true );
    2362             : 
    2363             :     OSL_ENSURE(pTable && pTable->GetFrameFormat(), "insert table failed");
    2364          74 :     if (!pTable || !pTable->GetFrameFormat())
    2365          74 :         return;
    2366             : 
    2367          74 :     if (pULSpaceItem && pULSpaceItem->GetUpper() != 0)
    2368           4 :         aItemSet.Put(*pULSpaceItem);
    2369             : 
    2370          74 :     SwTableNode* pTableNode = pTable->GetTableNode();
    2371             :     OSL_ENSURE(pTableNode, "no table node!");
    2372          74 :     if (pTableNode)
    2373             :     {
    2374          74 :         pIo->m_aSectionManager.PrependedInlineNode(*pIo->m_pPaM->GetPoint(),
    2375         148 :             *pTableNode);
    2376             :     }
    2377             : 
    2378             :     // Check if the node into which the table should be inserted already
    2379             :     // contains a Pagedesc. If so that Pagedesc would be moved to the
    2380             :     // row after the table, whats wrong. So delete and
    2381             :     // set later to the table format.
    2382          74 :     if (SwTextNode *const pNd = pTmpPos->nNode.GetNode().GetTextNode())
    2383             :     {
    2384          74 :         if (const SfxItemSet* pSet = pNd->GetpSwAttrSet())
    2385             :         {
    2386           8 :             SfxPoolItem *pSetAttr = 0;
    2387             :             const SfxPoolItem* pItem;
    2388           8 :             if (SfxItemState::SET == pSet->GetItemState(RES_BREAK, false, &pItem))
    2389             :             {
    2390           0 :                 pSetAttr = new SvxFormatBreakItem( *static_cast<const SvxFormatBreakItem*>(pItem) );
    2391           0 :                 pNd->ResetAttr( RES_BREAK );
    2392             :             }
    2393             : 
    2394             :             // eventually set the PageDesc/Break now to the table
    2395           8 :             if (pSetAttr)
    2396             :             {
    2397           0 :                 aItemSet.Put(*pSetAttr);
    2398           0 :                 delete pSetAttr;
    2399             :             }
    2400             :         }
    2401             :     }
    2402             : 
    2403             :     // total width of table
    2404          74 :     if( nMaxRight - nMinLeft > MINLAY * nDefaultSwCols )
    2405             :     {
    2406          74 :         pTable->GetFrameFormat()->SetFormatAttr(SwFormatFrmSize(ATT_FIX_SIZE, nSwWidth));
    2407          74 :         aItemSet.Put(SwFormatFrmSize(ATT_FIX_SIZE, nSwWidth));
    2408             :     }
    2409             : 
    2410             :     SvxFrameDirectionItem aDirection(
    2411          74 :         bIsBiDi ? FRMDIR_HORI_RIGHT_TOP : FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR );
    2412          74 :     pTable->GetFrameFormat()->SetFormatAttr(aDirection);
    2413             : 
    2414          74 :     if (text::HoriOrientation::LEFT_AND_WIDTH == eOri)
    2415             :     {
    2416          49 :         if (!pIo->m_nInTable && pIo->InLocalApo() && pIo->m_pSFlyPara->pFlyFormat &&
    2417           3 :             GetMinLeft())
    2418             :         {
    2419             :             //If we are inside a frame and we have a border, the frames
    2420             :             //placement does not consider the tables border, which word
    2421             :             //displays outside the frame, so adjust here.
    2422           3 :             SwFormatHoriOrient aHori(pIo->m_pSFlyPara->pFlyFormat->GetHoriOrient());
    2423           3 :             sal_Int16 eHori = aHori.GetHoriOrient();
    2424           3 :             if ((eHori == text::HoriOrientation::NONE) || (eHori == text::HoriOrientation::LEFT) ||
    2425             :                 (eHori == text::HoriOrientation::LEFT_AND_WIDTH))
    2426             :             {
    2427             :                 //With multiple table, use last table settings. Perhaps
    2428             :                 //the maximum is what word does ?
    2429           3 :                 aHori.SetPos(pIo->m_pSFlyPara->nXPos + GetMinLeft());
    2430           3 :                 aHori.SetHoriOrient(text::HoriOrientation::NONE);
    2431           3 :                 pIo->m_pSFlyPara->pFlyFormat->SetFormatAttr(aHori);
    2432           3 :             }
    2433             :         }
    2434             :         else
    2435             :         {
    2436             :             //If bApo is set, then this table is being placed in a floating
    2437             :             //frame, and the frame matches the left and right *lines* of the
    2438             :             //table, so the space to the left of the table isn't to be used
    2439             :             //inside the frame, in word the dialog involved greys out the
    2440             :             //ability to set the margin.
    2441          43 :             SvxLRSpaceItem aL( RES_LR_SPACE );
    2442             :             // set right to original DxaLeft (i28656)
    2443             : 
    2444          43 :             long nLeft = 0;
    2445          43 :             if (!bIsBiDi)
    2446          38 :                 nLeft = GetMinLeft();
    2447             :             else
    2448             :             {
    2449           5 :                 if (nPreferredWidth)
    2450             :                 {
    2451           2 :                     nLeft = pIo->m_aSectionManager.GetTextAreaWidth();
    2452           2 :                     nLeft = nLeft - nPreferredWidth  - nOrgDxaLeft;
    2453             :                 }
    2454             :                 else
    2455           3 :                     nLeft = -GetMinLeft();
    2456             :             }
    2457             : 
    2458          43 :             aL.SetLeft(nLeft);
    2459             : 
    2460          43 :             aItemSet.Put(aL);
    2461             :         }
    2462             :     }
    2463             : 
    2464          74 :     mpOldRedlineStack = pIo->m_pRedlineStack;
    2465          74 :     pIo->m_pRedlineStack = new sw::util::RedlineStack(pIo->m_rDoc);
    2466             : }
    2467             : 
    2468          74 : void WW8TabDesc::UseSwTable()
    2469             : {
    2470             :     // init global Vars
    2471          74 :     pTabLines = &pTable->GetTabLines();
    2472          74 :     nAktRow = nAktCol = nAktBandRow = 0;
    2473             : 
    2474          74 :     pTableNd  = const_cast<SwTableNode*>((*pTabLines)[0]->GetTabBoxes()[0]->
    2475          74 :         GetSttNd()->FindTableNode());
    2476             :     OSL_ENSURE( pTableNd, "wo ist mein TabellenNode" );
    2477             : 
    2478             :     // #i69519# - Restrict rows to repeat to a decent value
    2479          74 :     if ( nRowsToRepeat == static_cast<sal_uInt16>(nRows) )
    2480           0 :         nRowsToRepeat = 1;
    2481             : 
    2482          74 :     pTableNd->GetTable().SetRowsToRepeat( nRowsToRepeat );
    2483             :     // insert extra cells if needed and something like this
    2484          74 :     AdjustNewBand();
    2485             : 
    2486          74 :     WW8DupProperties aDup(pIo->m_rDoc,pIo->m_pCtrlStck);
    2487          74 :     pIo->m_pCtrlStck->SetAttr(*pIo->m_pPaM->GetPoint(), 0, false);
    2488             : 
    2489             :     // now set the correct PaM and prepare first merger group if any
    2490          74 :     SetPamInCell(nAktCol, true);
    2491          74 :     aDup.Insert(*pIo->m_pPaM->GetPoint());
    2492             : 
    2493          74 :     pIo->m_bWasTabRowEnd = false;
    2494          74 :     pIo->m_bWasTabCellEnd = false;
    2495          74 : }
    2496             : 
    2497          74 : void WW8TabDesc::MergeCells()
    2498             : {
    2499             :     short nRow;
    2500             : 
    2501         371 :     for (pActBand=pFirstBand, nRow=0; pActBand; pActBand=pActBand->pNextBand)
    2502             :     {
    2503             :         // insert current box into merge group if appropriate
    2504         297 :         if( pActBand->pTCs )
    2505             :         {
    2506         594 :             for( short j = 0; j < pActBand->nRows; j++, nRow++ )
    2507        1407 :                 for( short i = 0; i < pActBand->nWwCols; i++ )
    2508             :                 {
    2509        1110 :                     WW8SelBoxInfo* pActMGroup = 0;
    2510             : 
    2511             :                     // start a new merge group if appropriate
    2512             : 
    2513             :                     OSL_ENSURE(nRow < (sal_uInt16)pTabLines->size(),
    2514             :                         "Too few lines, table ended early");
    2515        1110 :                     if (nRow >= (sal_uInt16)pTabLines->size())
    2516           0 :                         return;
    2517        1110 :                     pTabLine = (*pTabLines)[ nRow ];
    2518        1110 :                     pTabBoxes = &pTabLine->GetTabBoxes();
    2519             : 
    2520        1110 :                     sal_uInt16 nCol = pActBand->nTransCell[ i ];
    2521        1110 :                     if (!pActBand->bExist[i])
    2522         129 :                         continue;
    2523             :                     OSL_ENSURE(nCol < pTabBoxes->size(),
    2524             :                         "Too few columns, table ended early");
    2525         981 :                     if (nCol >= pTabBoxes->size())
    2526           0 :                         return;
    2527         981 :                     pTabBox = (*pTabBoxes)[nCol];
    2528         981 :                     WW8_TCell& rCell = pActBand->pTCs[ i ];
    2529             :                     // is this the left upper cell of a merge group ?
    2530             : 
    2531         981 :                     bool bMerge = false;
    2532         981 :                     if ( rCell.bVertRestart && !rCell.bMerged )
    2533          11 :                         bMerge = true;
    2534         970 :                     else if (rCell.bFirstMerged && pActBand->bExist[i])
    2535             :                     {
    2536             :                         // Some tests to avoid merging cells which previously were
    2537             :                         // declared invalid because of sharing the exact same dimensions
    2538             :                         // as their previous cell
    2539             : 
    2540             :                         //If theres anything underneath/above we're ok.
    2541           1 :                         if (rCell.bVertMerge || rCell.bVertRestart)
    2542           0 :                             bMerge = true;
    2543             :                         else
    2544             :                         {
    2545             :                             //If it's a hori merge only, and the only things in
    2546             :                             //it are invalid cells then it's already taken care
    2547             :                             //of, so don't merge.
    2548           1 :                             for (sal_uInt16 i2 = i+1; i2 < pActBand->nWwCols; i2++ )
    2549           2 :                                 if (pActBand->pTCs[ i2 ].bMerged &&
    2550           1 :                                     !pActBand->pTCs[ i2 ].bFirstMerged  )
    2551             :                                 {
    2552           1 :                                     if (pActBand->bExist[i2])
    2553             :                                     {
    2554           1 :                                         bMerge = true;
    2555           1 :                                         break;
    2556             :                                     }
    2557             :                                 }
    2558             :                                 else
    2559             :                                     break;
    2560             :                         }
    2561             :                     }
    2562             : 
    2563         981 :                     if (bMerge)
    2564             :                     {
    2565          12 :                         short nX1    = pActBand->nCenter[ i ];
    2566          12 :                         short nWidth = pActBand->nWidth[ i ];
    2567             : 
    2568             :                         // 2. create current merge group
    2569          12 :                         pActMGroup = new WW8SelBoxInfo( nX1, nWidth );
    2570             : 
    2571             :                         // determine size of new merge group
    2572             :                         // before inserted the new merge group.
    2573             :                         // Needed to correctly locked previously created merge groups.
    2574             :                         // Calculate total width and set
    2575          12 :                         short nSizCell = pActBand->nWidth[ i ];
    2576          13 :                         for (sal_uInt16 i2 = i+1; i2 < pActBand->nWwCols; i2++ )
    2577           9 :                             if (pActBand->pTCs[ i2 ].bMerged &&
    2578           1 :                                 !pActBand->pTCs[ i2 ].bFirstMerged  )
    2579             :                             {
    2580           1 :                                 nSizCell = nSizCell + pActBand->nWidth[ i2 ];
    2581             :                             }
    2582             :                             else
    2583             :                                 break;
    2584          12 :                         pActMGroup->nGroupWidth = nSizCell;
    2585             : 
    2586             :                         // locked previously created merge groups,
    2587             :                         // after determining the size for the new merge group.
    2588             :                         // 1. If necessary close old merge group(s) that overlap
    2589             :                         // the X-area of the new group
    2590             :                         for (;;)
    2591             :                         {
    2592             :                             WW8SelBoxInfo* p = FindMergeGroup(
    2593          15 :                                 nX1, pActMGroup->nGroupWidth, false );
    2594          15 :                             if (p == 0)
    2595             :                             {
    2596          12 :                                 break;
    2597             :                             }
    2598           3 :                             p->bGroupLocked = true;
    2599           3 :                         }
    2600             : 
    2601             :                         // 3. push to group array
    2602          12 :                         aMergeGroups.push_back(pActMGroup);
    2603             :                     }
    2604             : 
    2605             :                     // if necessary add the current box to a merge group
    2606             :                     // (that can be a newly created or another group)
    2607         981 :                     UpdateTableMergeGroup( rCell, pActMGroup, pTabBox, i );
    2608             :                 }
    2609             :             }
    2610             :     }
    2611             : }
    2612             : 
    2613             : //There is a limbo area in word at the end of the row marker
    2614             : //where properties can live in word, there is no location in
    2615             : //writer equivalent, so try and park the cursor in the best
    2616             : //match, see #i23022#/#i18644#
    2617         288 : void WW8TabDesc::ParkPaM()
    2618             : {
    2619         288 :     SwTableBox *pTabBox2 = 0;
    2620         288 :     short nRow = nAktRow + 1;
    2621         288 :     if (nRow < (sal_uInt16)pTabLines->size())
    2622             :     {
    2623         220 :         if (SwTableLine *pLine = (*pTabLines)[nRow])
    2624             :         {
    2625         220 :             SwTableBoxes &rBoxes = pLine->GetTabBoxes();
    2626         220 :             pTabBox2 = rBoxes.empty() ? 0 : rBoxes.front();
    2627             :         }
    2628             :     }
    2629             : 
    2630         288 :     if (!pTabBox2 || !pTabBox2->GetSttNd())
    2631             :     {
    2632          68 :         MoveOutsideTable();
    2633         356 :         return;
    2634             :     }
    2635             : 
    2636         220 :     sal_uLong nSttNd = pTabBox2->GetSttIdx() + 1,
    2637         220 :               nEndNd = pTabBox2->GetSttNd()->EndOfSectionIndex();
    2638             : 
    2639         220 :     if (pIo->m_pPaM->GetPoint()->nNode != nSttNd)
    2640             :     {
    2641         220 :         do
    2642             :         {
    2643         220 :             pIo->m_pPaM->GetPoint()->nNode = nSttNd;
    2644             :         }
    2645         220 :         while (pIo->m_pPaM->GetNode().GetNodeType() != ND_TEXTNODE && ++nSttNd < nEndNd);
    2646             : 
    2647         220 :         pIo->m_pPaM->GetPoint()->nContent.Assign(pIo->m_pPaM->GetContentNode(), 0);
    2648         220 :         pIo->m_rDoc.SetTextFormatColl(*pIo->m_pPaM, const_cast<SwTextFormatColl*>(pIo->m_pDfltTextFormatColl));
    2649             :     }
    2650             : }
    2651             : 
    2652         144 : void WW8TabDesc::MoveOutsideTable()
    2653             : {
    2654             :     OSL_ENSURE(pTmpPos && pIo, "I've forgotten where the table is anchored");
    2655         144 :     if (pTmpPos && pIo)
    2656         144 :         *pIo->m_pPaM->GetPoint() = *pTmpPos;
    2657         144 : }
    2658             : 
    2659          74 : void WW8TabDesc::FinishSwTable()
    2660             : {
    2661          74 :     pIo->m_pRedlineStack->closeall(*pIo->m_pPaM->GetPoint());
    2662          74 :     delete pIo->m_pRedlineStack;
    2663          74 :     pIo->m_pRedlineStack = mpOldRedlineStack;
    2664          74 :     mpOldRedlineStack = 0;
    2665             : 
    2666          74 :     WW8DupProperties aDup(pIo->m_rDoc,pIo->m_pCtrlStck);
    2667          74 :     pIo->m_pCtrlStck->SetAttr( *pIo->m_pPaM->GetPoint(), 0, false);
    2668             : 
    2669          74 :     MoveOutsideTable();
    2670          74 :     delete pTmpPos, pTmpPos = 0;
    2671             : 
    2672          74 :     aDup.Insert(*pIo->m_pPaM->GetPoint());
    2673             : 
    2674          74 :     pIo->m_bWasTabRowEnd = false;
    2675          74 :     pIo->m_bWasTabCellEnd = false;
    2676             : 
    2677          74 :     pIo->m_aInsertedTables.InsertTable(*pTableNd, *pIo->m_pPaM);
    2678             : 
    2679          74 :     MergeCells();
    2680             : 
    2681             :     // if needed group cells together that should be merged
    2682          74 :     if( !aMergeGroups.empty() )
    2683             :     {
    2684             :         // process all merge groups one by one
    2685          51 :         for (
    2686           5 :                 WW8MergeGroups::iterator groupIt = aMergeGroups.begin();
    2687          34 :                 groupIt != aMergeGroups.end();
    2688             :                 ++groupIt)
    2689             :         {
    2690          12 :             sal_uInt16 nActBoxCount = groupIt->size();
    2691             : 
    2692          12 :             if( ( 1 < nActBoxCount ) && (*groupIt)[0] )
    2693             :             {
    2694           3 :                 const sal_uInt16 nRowSpan = groupIt->size();
    2695           9 :                 for (sal_uInt16 n = 0; n < nRowSpan; ++n)
    2696             :                 {
    2697           6 :                     SwTableBox* pCurrentBox = (*groupIt)[n];
    2698             :                     const long nRowSpanSet = n == 0 ?
    2699             :                                                nRowSpan :
    2700           6 :                                              ((-1) * (nRowSpan - n));
    2701           6 :                     pCurrentBox->setRowSpan( nRowSpanSet );
    2702             :                 }
    2703             :             }
    2704             :         }
    2705           5 :         pIo->m_pFormatOfJustInsertedApo = 0;
    2706           5 :         aMergeGroups.clear();
    2707          74 :     }
    2708          74 : }
    2709             : 
    2710             : // browse aMergeGroups, detect the index of the first fitting group or -1 otherwise
    2711             : 
    2712             : // Parameter: nXcenter  = center position of asking box
    2713             : //            nWidth    = width of asking box
    2714             : //            bExact    = flag, if box has to fit into group
    2715             : //                              or only has to touch
    2716             : 
    2717          18 : WW8SelBoxInfo* WW8TabDesc::FindMergeGroup(short nX1, short nWidth, bool bExact)
    2718             : {
    2719          18 :     if( !aMergeGroups.empty() )
    2720             :     {
    2721             :         // still valid area near the boundery
    2722          13 :         const short nToleranz = 4;
    2723             :         // box boundery
    2724          13 :         short nX2 = nX1 + nWidth;
    2725             :         // approximate group boundery
    2726             :         short nGrX1;
    2727             :         short nGrX2;
    2728             : 
    2729             :         // improvement: search backwards
    2730          31 :         for ( short iGr = aMergeGroups.size() - 1; iGr >= 0; --iGr )
    2731             :         {
    2732             :             // the currently inspected group
    2733          24 :             WW8SelBoxInfo& rActGroup = aMergeGroups[ iGr ];
    2734          24 :             if (!rActGroup.bGroupLocked)
    2735             :             {
    2736             :                 // approximate group boundery with room (tolerance) to the *outside*
    2737          18 :                 nGrX1 = rActGroup.nGroupXStart - nToleranz;
    2738             :                 nGrX2 = rActGroup.nGroupXStart
    2739          18 :                              +rActGroup.nGroupWidth  + nToleranz;
    2740             : 
    2741             :                 // If box fits report success
    2742             : 
    2743          18 :                 if( ( nX1 > nGrX1 ) && ( nX2 < nGrX2 ) )
    2744             :                 {
    2745           3 :                     return &rActGroup;
    2746             :                 }
    2747             : 
    2748             :                 // does the box share areas with the group?
    2749             : 
    2750          15 :                 if( !bExact )
    2751             :                 {
    2752             :                     // successful if nX1 *or* nX2 are inside the group
    2753          14 :                     if(    (     ( nX1 > nGrX1 )
    2754           9 :                                         && ( nX1 < nGrX2 - 2*nToleranz ) )
    2755          13 :                             || (     ( nX2 > nGrX1 + 2*nToleranz )
    2756          10 :                                         && ( nX2 < nGrX2 ) )
    2757             :                             // or nX1 and nX2 surround the group
    2758          11 :                             || (     ( nX1 <=nGrX1 )
    2759           3 :                                         && ( nX2 >=nGrX2 ) ) )
    2760             :                     {
    2761           3 :                         return &rActGroup;
    2762             :                     }
    2763             :                 }
    2764             :             }
    2765             :         }
    2766             :     }
    2767          12 :     return 0;
    2768             : }
    2769             : 
    2770        2688 : bool WW8TabDesc::IsValidCell(short nCol) const
    2771             : {
    2772        5376 :     return (static_cast<size_t>(nCol) < SAL_N_ELEMENTS(pActBand->bExist)) &&
    2773        5343 :            pActBand->bExist[nCol] &&
    2774        5343 :            (sal_uInt16)nAktRow < pTabLines->size();
    2775             : }
    2776             : 
    2777         472 : bool WW8TabDesc::InFirstParaInCell() const
    2778             : {
    2779             :     //e.g. #i19718#
    2780         472 :     if (!pTabBox || !pTabBox->GetSttNd())
    2781             :     {
    2782             :         OSL_FAIL("Problem with table");
    2783           0 :         return false;
    2784             :     }
    2785             : 
    2786         472 :     if (!IsValidCell(GetAktCol()))
    2787           0 :         return false;
    2788             : 
    2789         472 :     if (pIo->m_pPaM->GetPoint()->nNode == pTabBox->GetSttIdx() + 1)
    2790         213 :         return true;
    2791             : 
    2792         259 :     return false;
    2793             : }
    2794             : 
    2795         949 : void WW8TabDesc::StartMiserableHackForUnsupportedDirection(short nWwCol)
    2796             : {
    2797             :     OSL_ENSURE(pActBand, "Impossible");
    2798         949 :     if (pActBand && pActBand->maDirections[nWwCol] == 3)
    2799             :     {
    2800           1 :         pIo->m_pCtrlStck->NewAttr(*pIo->m_pPaM->GetPoint(),
    2801           2 :             SvxCharRotateItem(900, false, RES_CHRATR_ROTATE));
    2802             :     }
    2803         949 : }
    2804             : 
    2805        1239 : void WW8TabDesc::EndMiserableHackForUnsupportedDirection(short nWwCol)
    2806             : {
    2807             :     OSL_ENSURE(pActBand, "Impossible");
    2808        1239 :     if (pActBand && pActBand->maDirections[nWwCol] == 3)
    2809           1 :         pIo->m_pCtrlStck->SetAttr(*pIo->m_pPaM->GetPoint(), RES_CHRATR_ROTATE);
    2810        1239 : }
    2811             : 
    2812        1536 : bool WW8TabDesc::SetPamInCell(short nWwCol, bool bPam)
    2813             : {
    2814             :     OSL_ENSURE( pActBand, "pActBand ist 0" );
    2815        1536 :     if (!pActBand)
    2816           0 :         return false;
    2817             : 
    2818        1536 :     sal_uInt16 nCol = pActBand->transCell(nWwCol);
    2819             : 
    2820        1536 :     if ((sal_uInt16)nAktRow >= pTabLines->size())
    2821             :     {
    2822             :         OSL_ENSURE(false, "Actual row bigger than expected." );
    2823           2 :         if (bPam)
    2824           2 :             MoveOutsideTable();
    2825           2 :         return false;
    2826             :     }
    2827             : 
    2828        1534 :     pTabLine = (*pTabLines)[nAktRow];
    2829        1534 :     pTabBoxes = &pTabLine->GetTabBoxes();
    2830             : 
    2831        1534 :     if (nCol >= pTabBoxes->size())
    2832             :     {
    2833         288 :         if (bPam)
    2834             :         {
    2835             :             // The first paragraph in a cell with upper autospacing has upper
    2836             :             // spacing set to 0
    2837         288 :             if (
    2838           0 :                  pIo->m_bParaAutoBefore && pIo->m_bFirstPara &&
    2839           0 :                  !pIo->m_pWDop->fDontUseHTMLAutoSpacing
    2840             :                )
    2841             :             {
    2842           0 :                 pIo->SetUpperSpacing(*pIo->m_pPaM, 0);
    2843             :             }
    2844             : 
    2845             :             // The last paragraph in a cell with lower autospacing has lower
    2846             :             // spacing set to 0
    2847         288 :             if (pIo->m_bParaAutoAfter && !pIo->m_pWDop->fDontUseHTMLAutoSpacing)
    2848           0 :                 pIo->SetLowerSpacing(*pIo->m_pPaM, 0);
    2849             : 
    2850         288 :             ParkPaM();
    2851             :         }
    2852         288 :         return false;
    2853             :     }
    2854        1246 :     pTabBox = (*pTabBoxes)[nCol];
    2855        1246 :     if( !pTabBox->GetSttNd() )
    2856             :     {
    2857             :         OSL_ENSURE(pTabBox->GetSttNd(), "Probleme beim Aufbau der Tabelle");
    2858           0 :         if (bPam)
    2859           0 :             MoveOutsideTable();
    2860           0 :         return false;
    2861             :     }
    2862        1246 :     if (bPam)
    2863             :     {
    2864         949 :         pAktWWCell = &pActBand->pTCs[ nWwCol ];
    2865             : 
    2866             :        // The first paragraph in a cell with upper autospacing has upper spacing set to 0
    2867         949 :         if(pIo->m_bParaAutoBefore && pIo->m_bFirstPara && !pIo->m_pWDop->fDontUseHTMLAutoSpacing)
    2868           0 :             pIo->SetUpperSpacing(*pIo->m_pPaM, 0);
    2869             : 
    2870             :         // The last paragraph in a cell with lower autospacing has lower spacing set to 0
    2871         949 :         if(pIo->m_bParaAutoAfter && !pIo->m_pWDop->fDontUseHTMLAutoSpacing)
    2872           0 :             pIo->SetLowerSpacing(*pIo->m_pPaM, 0);
    2873             : 
    2874             :         //We need to set the pPaM on the first cell, invalid
    2875             :         //or not so that we can collect paragraph proproties over
    2876             :         //all the cells, but in that case on the valid cell we do not
    2877             :         //want to reset the fmt properties
    2878         949 :         sal_uLong nSttNd = pTabBox->GetSttIdx() + 1,
    2879         949 :                   nEndNd = pTabBox->GetSttNd()->EndOfSectionIndex();
    2880         949 :         if (pIo->m_pPaM->GetPoint()->nNode != nSttNd)
    2881             :         {
    2882         727 :             do
    2883             :             {
    2884         727 :                 pIo->m_pPaM->GetPoint()->nNode = nSttNd;
    2885             :             }
    2886         727 :             while (pIo->m_pPaM->GetNode().GetNodeType() != ND_TEXTNODE && ++nSttNd < nEndNd);
    2887         727 :             pIo->m_pPaM->GetPoint()->nContent.Assign(pIo->m_pPaM->GetContentNode(), 0);
    2888             :             // Precautionally set now, otherwise the style is not set for cells
    2889             :             // that are inserted for margin balancing.
    2890         727 :             pIo->m_rDoc.SetTextFormatColl(*pIo->m_pPaM, const_cast<SwTextFormatColl*>(pIo->m_pDfltTextFormatColl));
    2891             :             // because this cells are invisible helper constructions only to simulate
    2892             :             // the frayed view of WW-tables we do NOT need SetTextFormatCollAndListLevel()
    2893             :         }
    2894             : 
    2895             :         // Better to turn Snap to Grid off for all paragraphs in tables
    2896         949 :         if(SwTextNode *pNd = pIo->m_pPaM->GetNode().GetTextNode())
    2897             :         {
    2898         949 :             const SfxPoolItem &rItm = pNd->SwContentNode::GetAttr(RES_PARATR_SNAPTOGRID);
    2899         949 :             const SvxParaGridItem &rSnapToGrid = static_cast<const SvxParaGridItem&>(rItm);
    2900             : 
    2901         949 :             if(rSnapToGrid.GetValue())
    2902             :             {
    2903         949 :                 SvxParaGridItem aGridItem( rSnapToGrid );
    2904         949 :                 aGridItem.SetValue(false);
    2905             : 
    2906         949 :                 SwPosition* pGridPos = pIo->m_pPaM->GetPoint();
    2907             : 
    2908         949 :                 const sal_Int32 nEnd = pGridPos->nContent.GetIndex();
    2909         949 :                 pGridPos->nContent.Assign(pIo->m_pPaM->GetContentNode(), 0);
    2910         949 :                 pIo->m_pCtrlStck->NewAttr(*pGridPos, aGridItem);
    2911         949 :                 pGridPos->nContent.Assign(pIo->m_pPaM->GetContentNode(), nEnd);
    2912         949 :                 pIo->m_pCtrlStck->SetAttr(*pGridPos, RES_PARATR_SNAPTOGRID);
    2913             :             }
    2914             :         }
    2915             : 
    2916         949 :         StartMiserableHackForUnsupportedDirection(nWwCol);
    2917             :     }
    2918        1246 :     return true;
    2919             : }
    2920             : 
    2921          52 : void WW8TabDesc::InsertCells( short nIns )
    2922             : {
    2923          52 :     pTabLine = (*pTabLines)[nAktRow];
    2924          52 :     pTabBoxes = &pTabLine->GetTabBoxes();
    2925          52 :     pTabBox = (*pTabBoxes)[0];
    2926             : 
    2927         104 :     pIo->m_rDoc.GetNodes().InsBoxen( pTableNd, pTabLine, static_cast<SwTableBoxFormat*>(pTabBox->GetFrameFormat()),
    2928         156 :                             const_cast<SwTextFormatColl*>(pIo->m_pDfltTextFormatColl), 0, pTabBoxes->size(), nIns );
    2929             :     // The third parameter contains the FrameFormat of the boxes.
    2930             :     // Here it is possible to optimize to save (reduce) FrameFormats.
    2931          52 : }
    2932             : 
    2933         988 : void WW8TabDesc::SetTabBorders(SwTableBox* pBox, short nWwIdx)
    2934             : {
    2935         988 :     if( nWwIdx < 0 || nWwIdx >= pActBand->nWwCols )
    2936         995 :         return;                 // faked cells -> no border
    2937             : 
    2938         981 :     SvxBoxItem aFormatBox( RES_BOX );
    2939         981 :     if (pActBand->pTCs)     // neither Cell Border nor Default Border defined ?
    2940             :     {
    2941         981 :         WW8_TCell* pT = &pActBand->pTCs[nWwIdx];
    2942         981 :         if (SwWW8ImplReader::IsBorder(pT->rgbrc))
    2943         819 :             SwWW8ImplReader::SetBorder(aFormatBox, pT->rgbrc);
    2944             :     }
    2945             : 
    2946         981 :     if (pActBand->nOverrideSpacing[nWwIdx] & (1 << WW8TabBandDesc::wwTOP))
    2947             :     {
    2948             :         aFormatBox.SetDistance(
    2949           0 :             pActBand->nOverrideValues[nWwIdx][WW8TabBandDesc::wwTOP],
    2950           0 :             SvxBoxItemLine::TOP);
    2951             :     }
    2952             :     else
    2953         981 :         aFormatBox.SetDistance(pActBand->mnDefaultTop, SvxBoxItemLine::TOP);
    2954         981 :     if (pActBand->nOverrideSpacing[nWwIdx] & (1 << WW8TabBandDesc::wwBOTTOM))
    2955             :     {
    2956             :         aFormatBox.SetDistance(
    2957           0 :             pActBand->nOverrideValues[nWwIdx][WW8TabBandDesc::wwBOTTOM],
    2958           0 :             SvxBoxItemLine::BOTTOM);
    2959             :     }
    2960             :     else
    2961         981 :         aFormatBox.SetDistance(pActBand->mnDefaultBottom,SvxBoxItemLine::BOTTOM);
    2962             : 
    2963             :     // nGapHalf for WW is a *horizontal* gap between table cell and content.
    2964             :     short nLeftDist =
    2965         981 :         pActBand->mbHasSpacing ? pActBand->mnDefaultLeft : pActBand->nGapHalf;
    2966             :     short nRightDist =
    2967         981 :         pActBand->mbHasSpacing ? pActBand->mnDefaultRight : pActBand->nGapHalf;
    2968         981 :     if (pActBand->nOverrideSpacing[nWwIdx] & (1 << WW8TabBandDesc::wwLEFT))
    2969             :     {
    2970             :         aFormatBox.SetDistance(
    2971           0 :             pActBand->nOverrideValues[nWwIdx][WW8TabBandDesc::wwLEFT],
    2972           0 :             SvxBoxItemLine::LEFT);
    2973             :     }
    2974             :     else
    2975         981 :         aFormatBox.SetDistance(nLeftDist, SvxBoxItemLine::LEFT);
    2976         981 :     if (pActBand->nOverrideSpacing[nWwIdx] & (1 << WW8TabBandDesc::wwRIGHT))
    2977             :     {
    2978             :         aFormatBox.SetDistance(
    2979           0 :             pActBand->nOverrideValues[nWwIdx][WW8TabBandDesc::wwRIGHT],
    2980           0 :             SvxBoxItemLine::RIGHT);
    2981             :     }
    2982             :     else
    2983         981 :         aFormatBox.SetDistance(nRightDist,SvxBoxItemLine::RIGHT);
    2984             : 
    2985         981 :     pBox->GetFrameFormat()->SetFormatAttr(aFormatBox);
    2986             : }
    2987             : 
    2988         721 : void WW8TabDesc::SetTabShades( SwTableBox* pBox, short nWwIdx )
    2989             : {
    2990         721 :     if( nWwIdx < 0 || nWwIdx >= pActBand->nWwCols )
    2991           1 :         return;                 // faked cells -> no color
    2992             : 
    2993         720 :     bool bFound=false;
    2994         720 :     if (pActBand->pNewSHDs && pActBand->pNewSHDs[nWwIdx] != COL_AUTO)
    2995             :     {
    2996         222 :         Color aColor(pActBand->pNewSHDs[nWwIdx]);
    2997         222 :         pBox->GetFrameFormat()->SetFormatAttr(SvxBrushItem(aColor, RES_BACKGROUND));
    2998         222 :         bFound = true;
    2999             :     }
    3000             : 
    3001             :     //If there was no new shades, or no new shade setting
    3002         720 :     if (pActBand->pSHDs && !bFound)
    3003             :     {
    3004         498 :         WW8_SHD& rSHD = pActBand->pSHDs[nWwIdx];
    3005         498 :         if (!rSHD.GetValue())       // auto
    3006         498 :             return;
    3007             : 
    3008           0 :         SwWW8Shade aSh( pIo->m_bVer67, rSHD );
    3009           0 :         pBox->GetFrameFormat()->SetFormatAttr(SvxBrushItem(aSh.aColor, RES_BACKGROUND));
    3010             :     }
    3011             : }
    3012             : 
    3013         981 : SvxFrameDirection MakeDirection(sal_uInt16 nCode, bool bIsBiDi)
    3014             : {
    3015         981 :     SvxFrameDirection eDir = FRMDIR_ENVIRONMENT;
    3016             :     // 1: Asian layout with rotated CJK characters
    3017             :     // 5: Asian layout
    3018             :     // 3: Western layout rotated by 90 degrees
    3019             :     // 4: Western layout
    3020         981 :     switch (nCode)
    3021             :     {
    3022             :         default:
    3023             :             OSL_ENSURE(eDir == 4, "unknown direction code, maybe it's a bitfield");
    3024             :             //fall-through
    3025             :         case 3:
    3026           1 :             eDir = bIsBiDi ? FRMDIR_HORI_RIGHT_TOP : FRMDIR_HORI_LEFT_TOP; // #i38158# - Consider RTL tables
    3027           1 :             break;
    3028             :         case 5:
    3029           0 :             eDir = FRMDIR_VERT_TOP_RIGHT;
    3030           0 :             break;
    3031             :         case 1:
    3032           0 :             eDir = FRMDIR_VERT_TOP_RIGHT;
    3033           0 :             break;
    3034             :         case 4:
    3035         980 :             eDir = bIsBiDi ? FRMDIR_HORI_RIGHT_TOP : FRMDIR_HORI_LEFT_TOP; // #i38158# - Consider RTL tables
    3036         980 :             break;
    3037             :     }
    3038         981 :     return eDir;
    3039             : }
    3040             : 
    3041         988 : void WW8TabDesc::SetTabDirection(SwTableBox* pBox, short nWwIdx)
    3042             : {
    3043         988 :     if (nWwIdx < 0 || nWwIdx >= pActBand->nWwCols)
    3044         995 :         return;
    3045         981 :     SvxFrameDirectionItem aItem(MakeDirection(pActBand->maDirections[nWwIdx], bIsBiDi), RES_FRAMEDIR);
    3046         981 :     pBox->GetFrameFormat()->SetFormatAttr(aItem);
    3047             : }
    3048             : 
    3049         988 : void WW8TabDesc::SetTabVertAlign( SwTableBox* pBox, short nWwIdx )
    3050             : {
    3051         988 :     if( nWwIdx < 0 || nWwIdx >= pActBand->nWwCols )
    3052         995 :         return;
    3053             : 
    3054         981 :     sal_Int16 eVertOri=text::VertOrientation::TOP;
    3055             : 
    3056         981 :     if( pActBand->pTCs )
    3057             :     {
    3058         981 :         WW8_TCell* pT = &pActBand->pTCs[nWwIdx];
    3059         981 :         switch (pT->nVertAlign)
    3060             :         {
    3061             :             case 0:
    3062             :             default:
    3063         902 :                 eVertOri = text::VertOrientation::TOP;
    3064         902 :                 break;
    3065             :             case 1:
    3066          79 :                 eVertOri = text::VertOrientation::CENTER;
    3067          79 :                 break;
    3068             :             case 2:
    3069           0 :                 eVertOri = text::VertOrientation::BOTTOM;
    3070           0 :                 break;
    3071             :         }
    3072             :     }
    3073             : 
    3074         981 :     pBox->GetFrameFormat()->SetFormatAttr( SwFormatVertOrient(0,eVertOri) );
    3075             : }
    3076             : 
    3077         297 : void WW8TabDesc::AdjustNewBand()
    3078             : {
    3079         297 :     if( pActBand->nSwCols > nDefaultSwCols )        // split cells
    3080          52 :         InsertCells( pActBand->nSwCols - nDefaultSwCols );
    3081             : 
    3082         297 :     SetPamInCell( 0, false);
    3083             :     OSL_ENSURE( pTabBoxes && pTabBoxes->size() == (sal_uInt16)pActBand->nSwCols,
    3084             :         "Falsche Spaltenzahl in Tabelle" );
    3085             : 
    3086         297 :     if( bClaimLineFormat )
    3087             :     {
    3088         203 :         pTabLine->ClaimFrameFormat();            // necessary because of cell height
    3089         203 :         SwFormatFrmSize aF( ATT_MIN_SIZE, 0, 0 );  // default
    3090             : 
    3091         203 :         if (pActBand->nLineHeight == 0)    // 0 = Auto
    3092          62 :             aF.SetHeightSizeType( ATT_VAR_SIZE );
    3093             :         else
    3094             :         {
    3095         141 :             if (pActBand->nLineHeight < 0) // positive = min, negative = exact
    3096             :             {
    3097          66 :                 aF.SetHeightSizeType(ATT_FIX_SIZE);
    3098          66 :                 pActBand->nLineHeight = -pActBand->nLineHeight;
    3099             :             }
    3100         141 :             if (pActBand->nLineHeight < MINLAY) // invalid cell height
    3101           0 :                 pActBand->nLineHeight = MINLAY;
    3102             : 
    3103         141 :             aF.SetHeight(pActBand->nLineHeight);// set min/exact height
    3104             :         }
    3105         203 :         pTabLine->GetFrameFormat()->SetFormatAttr(aF);
    3106             :     }
    3107             : 
    3108             :     //Word stores 1 for bCantSplit if the row cannot be split, we set true if
    3109             :     //we can split the row
    3110         297 :     bool bSetCantSplit = pActBand->bCantSplit;
    3111         297 :     pTabLine->GetFrameFormat()->SetFormatAttr(SwFormatRowSplit(!bSetCantSplit));
    3112             : 
    3113             :     short i;    // SW-Index
    3114             :     short j;    // WW-Index
    3115             :     short nW;   // Width
    3116         297 :     SwFormatFrmSize aFS( ATT_FIX_SIZE );
    3117         297 :     j = pActBand->bLEmptyCol ? -1 : 0;
    3118             : 
    3119        1285 :     for( i = 0; i < pActBand->nSwCols; i++ )
    3120             :     {
    3121             :         // set cell width
    3122         988 :         if( j < 0 )
    3123           0 :             nW = pActBand->nCenter[0] - nMinLeft;
    3124             :         else
    3125             :         {
    3126             :             //Set j to first non invalid cell
    3127        1976 :             while ((j < pActBand->nWwCols) && (!pActBand->bExist[j]))
    3128           0 :                 j++;
    3129             : 
    3130         988 :             if( j < pActBand->nWwCols )
    3131         981 :                 nW = pActBand->nCenter[j+1] - pActBand->nCenter[j];
    3132             :             else
    3133           7 :                 nW = nMaxRight - pActBand->nCenter[j];
    3134         988 :             pActBand->nWidth[ j ] = nW;
    3135             :         }
    3136             : 
    3137         988 :         SwTableBox* pBox = (*pTabBoxes)[i];
    3138             :         // could be reduced further by intelligent moving of FrameFormats
    3139         988 :         pBox->ClaimFrameFormat();
    3140             : 
    3141         988 :         SetTabBorders(pBox, j);
    3142             : 
    3143             :         // #i18128# word has only one line between adjoining vertical cells
    3144             :         // we have to mimick this in the filter by picking the larger of the
    3145             :         // sides and using that one on one side of the line (right)
    3146         988 :         SvxBoxItem aCurrentBox(sw::util::ItemGet<SvxBoxItem>(*(pBox->GetFrameFormat()), RES_BOX));
    3147         988 :         const ::editeng::SvxBorderLine *pLeftLine = aCurrentBox.GetLine(SvxBoxItemLine::LEFT);
    3148         988 :         int nCurrentRightLineWidth = 0;
    3149         988 :         if(pLeftLine)
    3150         667 :             nCurrentRightLineWidth = pLeftLine->GetScaledWidth();
    3151             : 
    3152         988 :         if (i != 0)
    3153             :         {
    3154         691 :             SwTableBox* pBox2 = (*pTabBoxes)[i-1];
    3155         691 :             SvxBoxItem aOldBox(sw::util::ItemGet<SvxBoxItem>(*(pBox2->GetFrameFormat()), RES_BOX));
    3156         691 :             const ::editeng::SvxBorderLine *pRightLine = aOldBox.GetLine(SvxBoxItemLine::RIGHT);
    3157         691 :             int nOldBoxRightLineWidth = 0;
    3158         691 :             if(pRightLine)
    3159         302 :                 nOldBoxRightLineWidth = pRightLine->GetScaledWidth();
    3160             : 
    3161         691 :             if(nOldBoxRightLineWidth>nCurrentRightLineWidth)
    3162           6 :                 aCurrentBox.SetLine(aOldBox.GetLine(SvxBoxItemLine::RIGHT), SvxBoxItemLine::LEFT);
    3163             : 
    3164         691 :             aOldBox.SetLine(0, SvxBoxItemLine::RIGHT);
    3165         691 :             pBox2->GetFrameFormat()->SetFormatAttr(aOldBox);
    3166             :         }
    3167             : 
    3168         988 :         pBox->GetFrameFormat()->SetFormatAttr(aCurrentBox);
    3169             : 
    3170         988 :         SetTabVertAlign(pBox, j);
    3171         988 :         SetTabDirection(pBox, j);
    3172         988 :         if( pActBand->pSHDs || pActBand->pNewSHDs)
    3173         721 :             SetTabShades(pBox, j);
    3174         988 :         j++;
    3175             : 
    3176         988 :         aFS.SetWidth( nW );
    3177         988 :         pBox->GetFrameFormat()->SetFormatAttr( aFS );
    3178             : 
    3179             :         // skip non existing cells
    3180        2105 :         while( ( j < pActBand->nWwCols ) && !pActBand->bExist[j] )
    3181             :         {
    3182         129 :             pActBand->nWidth[j] = pActBand->nCenter[j+1] - pActBand->nCenter[j];
    3183         129 :             j++;
    3184             :         }
    3185        1285 :     }
    3186         297 : }
    3187             : 
    3188        1239 : void WW8TabDesc::TableCellEnd()
    3189             : {
    3190        1239 :     ::SetProgressState(pIo->m_nProgress, pIo->m_pDocShell);   // Update
    3191             : 
    3192        1239 :     EndMiserableHackForUnsupportedDirection(nAktCol);
    3193             : 
    3194             :     // new line/row
    3195        1239 :     if( pIo->m_bWasTabRowEnd )
    3196             :     {
    3197             :         // bWasTabRowEnd will be deactivated in
    3198             :         // SwWW8ImplReader::ProcessSpecial()
    3199             : 
    3200         297 :         sal_uInt16 iCol = GetLogicalWWCol();
    3201         297 :         if (iCol < aNumRuleNames.size())
    3202             :         {
    3203           0 :             aNumRuleNames.erase(aNumRuleNames.begin() + iCol,
    3204           0 :                 aNumRuleNames.end());
    3205             :         }
    3206             : 
    3207         297 :         nAktCol = 0;
    3208         297 :         nAktRow++;
    3209         297 :         nAktBandRow++;
    3210             :         OSL_ENSURE( pActBand , "pActBand ist 0" );
    3211         297 :         if( pActBand )
    3212             :         {
    3213         297 :             if( nAktRow >= nRows )  // nothing to at end of table
    3214        1313 :                 return;
    3215             : 
    3216         223 :             bool bNewBand = nAktBandRow >= pActBand->nRows;
    3217         223 :             if( bNewBand )
    3218             :             {                       // new band needed ?
    3219         223 :                 pActBand = pActBand->pNextBand;
    3220         223 :                 nAktBandRow = 0;
    3221             :                 OSL_ENSURE( pActBand, "pActBand ist 0" );
    3222         223 :                 AdjustNewBand();
    3223             :             }
    3224             :             else
    3225             :             {
    3226           0 :                 SwTableBox* pBox = (*pTabBoxes)[0];
    3227           0 :                 SwSelBoxes aBoxes;
    3228           0 :                 pIo->m_rDoc.InsertRow( SwTable::SelLineFromBox( pBox, aBoxes ) );
    3229             :             }
    3230             :         }
    3231             :     }
    3232             :     else
    3233             :     {                       // new column ( cell )
    3234         942 :         nAktCol++;
    3235             :     }
    3236        1165 :     SetPamInCell(nAktCol, true);
    3237             : 
    3238             :     // finish Annotated Level Numbering ?
    3239        1165 :     if (pIo->m_bAnl && !pIo->m_bAktAND_fNumberAcross && pActBand)
    3240           0 :         pIo->StopAllAnl(IsValidCell(nAktCol));
    3241             : }
    3242             : 
    3243             : // if necessary register the box for the merge group for this column
    3244         981 : SwTableBox* WW8TabDesc::UpdateTableMergeGroup(  WW8_TCell&     rCell,
    3245             :                                                 WW8SelBoxInfo* pActGroup,
    3246             :                                                 SwTableBox*    pActBox,
    3247             :                                                 sal_uInt16         nCol )
    3248             : {
    3249             :     // set default for return
    3250         981 :     SwTableBox* pResult = 0;
    3251             : 
    3252             :     // check if the box has to be merged
    3253             :     // If cell is the first one to be merged, a new merge group has to be provided.
    3254             :     // E.g., it could be that a cell is the first one to be merged, but no
    3255             :     // new merge group is provided, because the potential other cell to be merged
    3256             :     // doesn't exist - see method <WW8TabDesc::MergeCells>.
    3257         981 :     if ( pActBand->bExist[ nCol ] &&
    3258           3 :          ( ( rCell.bFirstMerged && pActGroup ) ||
    3259         977 :            rCell.bMerged ||
    3260         966 :            rCell.bVertMerge ||
    3261             :            rCell.bVertRestart ) )
    3262             :     {
    3263             :         // detect appropriate merge group
    3264          15 :         WW8SelBoxInfo* pTheMergeGroup = 0;
    3265          15 :         if( pActGroup )
    3266             :             // assign group
    3267          12 :             pTheMergeGroup = pActGroup;
    3268             :         else
    3269             :         {
    3270             :             // find group
    3271             :             pTheMergeGroup = FindMergeGroup(
    3272           3 :                 pActBand->nCenter[ nCol ], pActBand->nWidth[  nCol ], true );
    3273             :         }
    3274          15 :         if( pTheMergeGroup )
    3275             :         {
    3276             :             // add current box to merge group
    3277          15 :             pTheMergeGroup->push_back(pActBox);
    3278             :             // return target box
    3279          15 :             pResult = (*pTheMergeGroup)[ 0 ];
    3280             :         }
    3281             :     }
    3282         981 :     return pResult;
    3283             : }
    3284             : 
    3285         297 : sal_uInt16 WW8TabDesc::GetLogicalWWCol() const // returns number of col as INDICATED within WW6 UI status line -1
    3286             : {
    3287         297 :     sal_uInt16 nCol = 0;
    3288         297 :     if( pActBand && pActBand->pTCs)
    3289             :     {
    3290        1225 :         for( sal_uInt16 iCol = 1; iCol <= nAktCol && iCol <= pActBand->nWwCols; ++iCol )
    3291             :         {
    3292         928 :             if( !pActBand->pTCs[ iCol-1 ].bMerged )
    3293         927 :                 ++nCol;
    3294             :         }
    3295             :     }
    3296         297 :     return nCol;
    3297             : }
    3298             : 
    3299             : // find name of numrule valid for current WW-COL
    3300           0 : OUString WW8TabDesc::GetNumRuleName() const
    3301             : {
    3302           0 :     sal_uInt16 nCol = GetLogicalWWCol();
    3303           0 :     if (nCol < aNumRuleNames.size())
    3304           0 :         return aNumRuleNames[nCol];
    3305           0 :     return OUString();
    3306             : }
    3307             : 
    3308           0 : void WW8TabDesc::SetNumRuleName( const OUString& rName )
    3309             : {
    3310           0 :     sal_uInt16 nCol = GetLogicalWWCol();
    3311           0 :     for (sal_uInt16 nSize = static_cast< sal_uInt16 >(aNumRuleNames.size()); nSize <= nCol; ++nSize)
    3312           0 :         aNumRuleNames.push_back(OUString());
    3313           0 :     aNumRuleNames[nCol] = rName;
    3314           0 : }
    3315             : 
    3316          74 : bool SwWW8ImplReader::StartTable(WW8_CP nStartCp, SvxULSpaceItem* pULSpaceItem)
    3317             : {
    3318             :     // Entering a table so make sure the FirstPara flag gets set
    3319          74 :     m_bFirstPara = true;
    3320             :     // keine rekursiven Tabellen Nicht bei EinfuegenDatei in Tabelle oder
    3321             :     // Fussnote
    3322          74 :     if (m_bReadNoTable)
    3323           0 :         return false;
    3324             : 
    3325          74 :     if (m_pTableDesc)
    3326           9 :         m_aTableStack.push(m_pTableDesc);
    3327             : 
    3328             :     // #i33818# - determine absolute position object attributes,
    3329             :     // if possible. It's needed for nested tables.
    3330          74 :     WW8FlyPara* pTableWFlyPara( 0L );
    3331          74 :     WW8SwFlyPara* pTableSFlyPara( 0L );
    3332             :     // #i45301# - anchor nested table inside Writer fly frame
    3333             :     // only at-character, if absolute position object attributes are available.
    3334             :     // Thus, default anchor type is as-character anchored.
    3335          74 :     RndStdIds eAnchor( FLY_AS_CHAR );
    3336          74 :     if ( m_nInTable )
    3337             :     {
    3338           9 :         WW8_TablePos* pNestedTabPos( 0L );
    3339             :         WW8_TablePos aNestedTabPos;
    3340             :         WW8PLCFxSave1 aSave;
    3341           9 :         m_pPlcxMan->GetPap()->Save( aSave );
    3342           9 :         WW8PLCFx_Cp_FKP* pPap = m_pPlcxMan->GetPapPLCF();
    3343           9 :         WW8_CP nMyStartCp = nStartCp;
    3344          18 :         if ( SearchRowEnd( pPap, nMyStartCp, m_nInTable ) &&
    3345           9 :              ParseTabPos( &aNestedTabPos, pPap ) )
    3346             :         {
    3347           0 :             pNestedTabPos = &aNestedTabPos;
    3348             :         }
    3349           9 :         m_pPlcxMan->GetPap()->Restore( aSave );
    3350           9 :         if ( pNestedTabPos )
    3351             :         {
    3352           0 :             ApoTestResults aApo = TestApo( m_nInTable + 1, false, pNestedTabPos );
    3353           0 :             pTableWFlyPara = ConstructApo( aApo, pNestedTabPos );
    3354           0 :             if ( pTableWFlyPara )
    3355             :             {
    3356             :                 // <WW8SwFlyPara> constructor has changed - new 4th parameter
    3357             :                 // containing WW8 page top margin.
    3358             :                 pTableSFlyPara = new WW8SwFlyPara(*m_pPaM, *this, *pTableWFlyPara,
    3359           0 :                     m_aSectionManager.GetWWPageTopMargin(),
    3360           0 :                     m_aSectionManager.GetPageLeft(), m_aSectionManager.GetTextAreaWidth(),
    3361           0 :                     m_nIniFlyDx, m_nIniFlyDy);
    3362             : 
    3363             :                 // #i45301# - anchor nested table Writer fly frame at-character
    3364           0 :                 eAnchor = FLY_AT_CHAR;
    3365             :             }
    3366             :         }
    3367             :     }
    3368             : 
    3369          74 :     m_pTableDesc = new WW8TabDesc( this, nStartCp );
    3370             : 
    3371          74 :     if( m_pTableDesc->Ok() )
    3372             :     {
    3373          74 :         int nNewInTable = m_nInTable + 1;
    3374             : 
    3375          74 :         if ((eAnchor == FLY_AT_CHAR)
    3376          74 :             && !m_aTableStack.empty() && !InEqualApo(nNewInTable) )
    3377             :         {
    3378           0 :             m_pTableDesc->pParentPos = new SwPosition(*m_pPaM->GetPoint());
    3379           0 :             SfxItemSet aItemSet(m_rDoc.GetAttrPool(),
    3380           0 :                                 RES_FRMATR_BEGIN, RES_FRMATR_END-1);
    3381             :             // #i33818# - anchor the Writer fly frame for the nested table at-character.
    3382             :             // #i45301#
    3383           0 :             SwFormatAnchor aAnchor( eAnchor );
    3384           0 :             aAnchor.SetAnchor( m_pTableDesc->pParentPos );
    3385           0 :             aItemSet.Put( aAnchor );
    3386             :             m_pTableDesc->pFlyFormat = m_rDoc.MakeFlySection( eAnchor,
    3387           0 :                                                       m_pTableDesc->pParentPos, &aItemSet);
    3388             :             OSL_ENSURE( m_pTableDesc->pFlyFormat->GetAnchor().GetAnchorId() == eAnchor,
    3389             :                    "Not the anchor type requested!" );
    3390           0 :             MoveInsideFly(m_pTableDesc->pFlyFormat);
    3391             :         }
    3392          74 :         m_pTableDesc->CreateSwTable(pULSpaceItem);
    3393          74 :         if (m_pTableDesc->pFlyFormat)
    3394             :         {
    3395           0 :             m_pTableDesc->SetSizePosition(m_pTableDesc->pFlyFormat);
    3396             :             // #i33818# - Use absolute position object attributes,
    3397             :             // if existing, and apply them to the created Writer fly frame.
    3398           0 :             if ( pTableWFlyPara && pTableSFlyPara )
    3399             :             {
    3400           0 :                 WW8FlySet aFlySet( *this, pTableWFlyPara, pTableSFlyPara, false );
    3401           0 :                 SwFormatAnchor aAnchor( FLY_AT_CHAR );
    3402           0 :                 aAnchor.SetAnchor( m_pTableDesc->pParentPos );
    3403           0 :                 aFlySet.Put( aAnchor );
    3404           0 :                 m_pTableDesc->pFlyFormat->SetFormatAttr( aFlySet );
    3405             :             }
    3406             :             else
    3407             :             {
    3408             :                 SwFormatHoriOrient aHori =
    3409           0 :                             m_pTableDesc->pTable->GetFrameFormat()->GetHoriOrient();
    3410           0 :                 m_pTableDesc->pFlyFormat->SetFormatAttr(aHori);
    3411           0 :                 m_pTableDesc->pFlyFormat->SetFormatAttr( SwFormatSurround( SURROUND_NONE ) );
    3412             :             }
    3413             :             // #i33818# - The nested table doesn't have to leave
    3414             :             // the table cell. Thus, the Writer fly frame has to follow the text flow.
    3415           0 :             m_pTableDesc->pFlyFormat->SetFormatAttr( SwFormatFollowTextFlow( true ) );
    3416             :         }
    3417             :         else
    3418          74 :             m_pTableDesc->SetSizePosition(0);
    3419          74 :         m_pTableDesc->UseSwTable();
    3420             :     }
    3421             :     else
    3422           0 :         PopTableDesc();
    3423             : 
    3424             :     // #i33818#
    3425          74 :     delete pTableWFlyPara;
    3426          74 :     delete pTableSFlyPara;
    3427             : 
    3428          74 :     return 0 != m_pTableDesc;
    3429             : }
    3430             : 
    3431        1239 : void SwWW8ImplReader::TabCellEnd()
    3432             : {
    3433        1239 :     if (m_nInTable && m_pTableDesc)
    3434        1239 :         m_pTableDesc->TableCellEnd();
    3435             : 
    3436        1239 :     m_bFirstPara = true;    // We have come to the end of a cell so FirstPara flag
    3437        1239 :     m_bReadTable = false;
    3438        1239 :     m_pTableEndPaM.reset();
    3439        1239 : }
    3440             : 
    3441         252 : void SwWW8ImplReader::Read_TabCellEnd( sal_uInt16, const sal_uInt8* pData, short nLen)
    3442             : {
    3443         252 :     if( ( nLen > 0 ) && ( *pData == 1 ) )
    3444         126 :         m_bWasTabCellEnd = true;
    3445         252 : }
    3446             : 
    3447         950 : void SwWW8ImplReader::Read_TabRowEnd( sal_uInt16, const sal_uInt8* pData, short nLen )   // Sprm25
    3448             : {
    3449         950 :     if( ( nLen > 0 ) && ( *pData == 1 ) )
    3450         475 :         m_bWasTabRowEnd = true;
    3451         950 : }
    3452             : 
    3453          74 : void SwWW8ImplReader::PopTableDesc()
    3454             : {
    3455          74 :     if (m_pTableDesc && m_pTableDesc->pFlyFormat)
    3456             :     {
    3457           0 :         MoveOutsideFly(m_pTableDesc->pFlyFormat,*m_pTableDesc->pParentPos);
    3458             :     }
    3459             : 
    3460          74 :     delete m_pTableDesc;
    3461          74 :     if (m_aTableStack.empty())
    3462          65 :         m_pTableDesc = 0;
    3463             :     else
    3464             :     {
    3465           9 :        m_pTableDesc = m_aTableStack.top();
    3466           9 :        m_aTableStack.pop();
    3467             :     }
    3468          74 : }
    3469             : 
    3470          74 : void SwWW8ImplReader::StopTable()
    3471             : {
    3472             :     OSL_ENSURE(m_pTableDesc, "Panic, stop table with no table!");
    3473          74 :     if (!m_pTableDesc)
    3474          74 :         return;
    3475             : 
    3476             :     // We are leaving a table so make sure the next paragraph doesn't think
    3477             :     // it's the first paragraph
    3478          74 :     m_bFirstPara = false;
    3479             : 
    3480          74 :     m_pTableDesc->FinishSwTable();
    3481          74 :     PopTableDesc();
    3482             : 
    3483          74 :     m_bReadTable = true;
    3484             :     // #i101116# - Keep PaM on table end only for nested tables
    3485          74 :     if ( m_nInTable > 1 )
    3486             :     {
    3487           9 :         m_pTableEndPaM.reset(new SwPaM(*m_pPaM, m_pPaM));
    3488             :     }
    3489             : }
    3490             : 
    3491        6949 : bool SwWW8ImplReader::IsInvalidOrToBeMergedTabCell() const
    3492             : {
    3493        6949 :     if( !m_pTableDesc )
    3494        5207 :         return false;
    3495             : 
    3496        1742 :     const WW8_TCell* pCell = m_pTableDesc->GetAktWWCell();
    3497             : 
    3498        1742 :     return     !m_pTableDesc->IsValidCell( m_pTableDesc->GetAktCol() )
    3499        1780 :             || (    pCell
    3500        1707 :                  && (    !pCell->bFirstMerged
    3501        1704 :                       && (    pCell->bMerged
    3502        1703 :                            || (    pCell->bVertMerge
    3503           9 :                                 && !pCell->bVertRestart
    3504             :                               )
    3505             :                          )
    3506             :                     )
    3507        1742 :                 );
    3508             : }
    3509             : 
    3510          15 : sal_uInt16 SwWW8ImplReader::StyleUsingLFO( sal_uInt16 nLFOIndex ) const
    3511             : {
    3512          15 :     sal_uInt16 nRes = USHRT_MAX;
    3513          15 :     if( !m_vColl.empty() )
    3514             :     {
    3515           0 :         for(sal_uInt16 nI = 0; nI < m_pStyles->GetCount(); nI++ )
    3516           0 :             if(    m_vColl[ nI ].bValid
    3517           0 :                 && (nLFOIndex == m_vColl[ nI ].nLFOIndex) )
    3518           0 :                 nRes = nI;
    3519             :     }
    3520          15 :     return nRes;
    3521             : }
    3522             : 
    3523           0 : const SwFormat* SwWW8ImplReader::GetStyleWithOrgWWName( OUString& rName ) const
    3524             : {
    3525           0 :     SwFormat* pRet = 0;
    3526           0 :     if( !m_vColl.empty() )
    3527             :     {
    3528           0 :         for(sal_uInt16 nI = 0; nI < m_pStyles->GetCount(); nI++ )
    3529           0 :             if(    m_vColl[ nI ].bValid
    3530           0 :                 && (rName.equals( m_vColl[ nI ].GetOrgWWName())) )
    3531             :             {
    3532           0 :                 pRet = m_vColl[ nI ].pFormat;
    3533           0 :                 break;
    3534             :             }
    3535             :     }
    3536           0 :     return pRet;
    3537             : }
    3538             : 
    3539             : //          class WW8RStyle
    3540             : 
    3541         436 : const sal_uInt8* WW8RStyle::HasParaSprm( sal_uInt16 nId ) const
    3542             : {
    3543         436 :     if( !pParaSprms || !nSprmsLen )
    3544           0 :         return 0;
    3545             : 
    3546         436 :     return maSprmParser.findSprmData(nId, pParaSprms, nSprmsLen);
    3547             : }
    3548             : 
    3549        1940 : void WW8RStyle::ImportSprms(sal_uInt8 *pSprms, short nLen, bool bPap)
    3550             : {
    3551        1940 :     if (!nLen)
    3552        1940 :         return;
    3553             : 
    3554        1940 :     if( bPap )
    3555             :     {
    3556         876 :         pParaSprms = pSprms;   // for HasParaSprms()
    3557         876 :         nSprmsLen = nLen;
    3558             :     }
    3559             : 
    3560        1940 :     WW8SprmIter aSprmIter(pSprms, nLen, maSprmParser);
    3561        9750 :     while (const sal_uInt8* pSprm = aSprmIter.GetSprms())
    3562             :     {
    3563        7810 :         pIo->ImportSprm(pSprm);
    3564        7810 :         aSprmIter.advance();
    3565             :     }
    3566             : 
    3567        1940 :     pParaSprms = 0;
    3568        9750 :     nSprmsLen = 0;
    3569             : }
    3570             : 
    3571        1954 : void WW8RStyle::ImportSprms(sal_Size nPosFc, short nLen, bool bPap)
    3572             : {
    3573        1954 :     if (!nLen)
    3574        1970 :         return;
    3575             : 
    3576        1938 :     if (checkSeek(*pStStrm, nPosFc))
    3577             :     {
    3578        1938 :         sal_uInt8 *pSprms = new sal_uInt8[nLen];
    3579        1938 :         nLen = pStStrm->Read(pSprms, nLen);
    3580        1938 :         ImportSprms(pSprms, nLen, bPap);
    3581        1938 :         delete[] pSprms;
    3582             :     }
    3583             : }
    3584             : 
    3585        4342 : static inline short WW8SkipOdd(SvStream* pSt )
    3586             : {
    3587        4342 :     if ( pSt->Tell() & 0x1 )
    3588             :     {
    3589             :         sal_uInt8 c;
    3590         407 :         return pSt->Read( &c, 1 );
    3591             :     }
    3592        3935 :     return 0;
    3593             : }
    3594             : 
    3595           0 : static inline short WW8SkipEven(SvStream* pSt )
    3596             : {
    3597           0 :     if (!(pSt->Tell() & 0x1))
    3598             :     {
    3599             :         sal_uInt8 c;
    3600           0 :         return pSt->Read( &c, 1 );
    3601             :     }
    3602           0 :     return 0;
    3603             : }
    3604             : 
    3605        2689 : short WW8RStyle::ImportUPX(short nLen, bool bPAP, bool bOdd)
    3606             : {
    3607        2689 :     if( 0 < nLen ) // Empty ?
    3608             :     {
    3609        2689 :         if (bOdd)
    3610           0 :             nLen = nLen - WW8SkipEven( pStStrm );
    3611             :         else
    3612        2689 :             nLen = nLen - WW8SkipOdd( pStStrm );
    3613             : 
    3614        2689 :         sal_Int16 cbUPX(0);
    3615        2689 :         pStStrm->ReadInt16( cbUPX );
    3616             : 
    3617        2689 :         nLen-=2;
    3618             : 
    3619        2689 :         if ( cbUPX > nLen )
    3620           0 :             cbUPX = nLen;       // shrink cbUPX to nLen
    3621             : 
    3622        2689 :         if( (1 < cbUPX) || ( (0 < cbUPX) && !bPAP ) )
    3623             :         {
    3624        2098 :             if( bPAP )
    3625             :             {
    3626             :                 sal_uInt16 id;
    3627        1036 :                 pStStrm->ReadUInt16( id );
    3628             : 
    3629        1036 :                 cbUPX-=  2;
    3630        1036 :                 nLen-=  2;
    3631             :             }
    3632             : 
    3633        2098 :             if( 0 < cbUPX )
    3634             :             {
    3635        1937 :                 sal_Size nPos = pStStrm->Tell(); // if something is interpreted wrong,
    3636             :                                                  // this should make it work again
    3637        1937 :                 ImportSprms( nPos, cbUPX, bPAP );
    3638             : 
    3639        1937 :                 if ( pStStrm->Tell() != nPos + cbUPX )
    3640           0 :                     pStStrm->Seek( nPos+cbUPX );
    3641             : 
    3642        1937 :                 nLen = nLen - cbUPX;
    3643             :             }
    3644             :         }
    3645             :     }
    3646        2689 :     return nLen;
    3647             : }
    3648             : 
    3649        1653 : void WW8RStyle::ImportGrupx(short nLen, bool bPara, bool bOdd)
    3650             : {
    3651        1653 :     if( nLen <= 0 )
    3652        1653 :         return;
    3653        1653 :     if (bOdd)
    3654           0 :         nLen = nLen - WW8SkipEven( pStStrm );
    3655             :     else
    3656        1653 :         nLen = nLen - WW8SkipOdd( pStStrm );
    3657             : 
    3658        1653 :     if( bPara ) // Grupx.Papx
    3659        1036 :         nLen = ImportUPX(nLen, true, bOdd);
    3660        1653 :     ImportUPX(nLen, false, bOdd);                   // Grupx.Chpx
    3661             : }
    3662             : 
    3663         125 : WW8RStyle::WW8RStyle(WW8Fib& _rFib, SwWW8ImplReader* pI)
    3664             :     : WW8Style(*pI->m_pTableStream, _rFib)
    3665             :     , maSprmParser(_rFib.GetFIBVersion())
    3666             :     , pIo(pI)
    3667             :     , pStStrm(pI->m_pTableStream)
    3668             :     , pStyRule(0)
    3669             :     , pParaSprms(0)
    3670             :     , nSprmsLen(0)
    3671             :     , nWwNumLevel(0)
    3672             :     , bTextColChanged(false)
    3673             :     , bFontChanged(false)
    3674             :     , bCJKFontChanged(false)
    3675             :     , bCTLFontChanged(false)
    3676             :     , bFSizeChanged(false)
    3677             :     , bFCTLSizeChanged(false)
    3678         125 :     , bWidowsChanged(false)
    3679             : {
    3680         125 :     pIo->m_vColl.resize(cstd);
    3681         125 : }
    3682             : 
    3683         155 : void WW8RStyle::Set1StyleDefaults()
    3684             : {
    3685             :     // see #i25247#, #i25561#, #i48064#, #i92341# for default font
    3686         155 :     if (!bCJKFontChanged)   // Style no CJK Font? set the default
    3687          93 :         pIo->SetNewFontAttr(ftcFE, true, RES_CHRATR_CJK_FONT);
    3688             : 
    3689         155 :     if (!bCTLFontChanged)   // Style no CTL Font? set the default
    3690          79 :         pIo->SetNewFontAttr(ftcBi, true, RES_CHRATR_CTL_FONT);
    3691             : 
    3692             :     // western 2nd to make western charset conversion the default
    3693         155 :     if (!bFontChanged)      // Style has no Font? set the default,
    3694          79 :         pIo->SetNewFontAttr(ftcAsci, true, RES_CHRATR_FONT);
    3695             : 
    3696         155 :     if( !pIo->m_bNoAttrImport )
    3697             :     {
    3698             :         // Style has no text color set, winword default is auto
    3699         155 :         if ( !bTextColChanged )
    3700          94 :             pIo->m_pAktColl->SetFormatAttr(SvxColorItem(Color(COL_AUTO), RES_CHRATR_COLOR));
    3701             : 
    3702             :         // Style has no FontSize ? WinWord Default is 10pt for western and asian
    3703         155 :         if( !bFSizeChanged )
    3704             :         {
    3705          11 :             SvxFontHeightItem aAttr(200, 100, RES_CHRATR_FONTSIZE);
    3706          11 :             pIo->m_pAktColl->SetFormatAttr(aAttr);
    3707          11 :             aAttr.SetWhich(RES_CHRATR_CJK_FONTSIZE);
    3708          11 :             pIo->m_pAktColl->SetFormatAttr(aAttr);
    3709             :         }
    3710             : 
    3711             :         // Style has no FontSize ? WinWord Default is 10pt for western and asian
    3712         155 :         if( !bFCTLSizeChanged )
    3713             :         {
    3714          29 :             SvxFontHeightItem aAttr(200, 100, RES_CHRATR_FONTSIZE);
    3715          29 :             aAttr.SetWhich(RES_CHRATR_CTL_FONTSIZE);
    3716          29 :             pIo->m_pAktColl->SetFormatAttr(aAttr);
    3717             :         }
    3718             : 
    3719         155 :         if( !bWidowsChanged )  // Widows ?
    3720             :         {
    3721          84 :             pIo->m_pAktColl->SetFormatAttr( SvxWidowsItem( 2, RES_PARATR_WIDOWS ) );
    3722          84 :             pIo->m_pAktColl->SetFormatAttr( SvxOrphansItem( 2, RES_PARATR_ORPHANS ) );
    3723             :         }
    3724             :     }
    3725         155 : }
    3726             : 
    3727        1670 : bool WW8RStyle::PrepareStyle(SwWW8StyInf &rSI, ww::sti eSti, sal_uInt16 nThisStyle, sal_uInt16 nNextStyle)
    3728             : {
    3729             :     SwFormat* pColl;
    3730             :     bool bStyExist;
    3731             : 
    3732        1670 :     if (rSI.bColl)
    3733             :     {
    3734             :         // Para-Style
    3735             :         sw::util::ParaStyleMapper::StyleResult aResult =
    3736        1052 :             pIo->m_aParaStyleMapper.GetStyle(rSI.GetOrgWWName(), eSti);
    3737        1052 :         pColl = aResult.first;
    3738        1052 :         bStyExist = aResult.second;
    3739             :     }
    3740             :     else
    3741             :     {
    3742             :         // Char-Style
    3743             :         sw::util::CharStyleMapper::StyleResult aResult =
    3744         618 :             pIo->m_aCharStyleMapper.GetStyle(rSI.GetOrgWWName(), eSti);
    3745         618 :         pColl = aResult.first;
    3746         618 :         bStyExist = aResult.second;
    3747             :     }
    3748             : 
    3749        1670 :     bool bImport = !bStyExist || pIo->m_bNewDoc; // import content ?
    3750             : 
    3751             :     // Do not override character styles the list import code created earlier.
    3752        1670 :     if (bImport && bStyExist && rSI.GetOrgWWName().startsWith("WW8Num"))
    3753         139 :         bImport = false;
    3754             : 
    3755        1670 :     bool bOldNoImp = pIo->m_bNoAttrImport;
    3756        1670 :     rSI.bImportSkipped = !bImport;
    3757             : 
    3758        1670 :     if( !bImport )
    3759         139 :         pIo->m_bNoAttrImport = true;
    3760             :     else
    3761             :     {
    3762        1531 :         if (bStyExist)
    3763             :         {
    3764         794 :             pColl->ResetAllFormatAttr(); // #i73790# - method renamed
    3765             :         }
    3766        1531 :         pColl->SetAuto(false);          // suggested by JP
    3767             :     }                                   // but changes the UI
    3768        1670 :     pIo->m_pAktColl = pColl;
    3769        1670 :     rSI.pFormat = pColl;                  // remember translation WW->SW
    3770        1670 :     rSI.bImportSkipped = !bImport;
    3771             : 
    3772             :     // Set Based on style
    3773        1670 :     sal_uInt16 j = rSI.nBase;
    3774        1670 :     if (j != nThisStyle && j < cstd )
    3775             :     {
    3776         978 :         SwWW8StyInf* pj = &pIo->m_vColl[j];
    3777         978 :         if (rSI.pFormat && pj->pFormat && rSI.bColl == pj->bColl)
    3778             :         {
    3779         961 :             rSI.pFormat->SetDerivedFrom( pj->pFormat );  // ok, set Based on
    3780         961 :             rSI.eLTRFontSrcCharSet = pj->eLTRFontSrcCharSet;
    3781         961 :             rSI.eRTLFontSrcCharSet = pj->eRTLFontSrcCharSet;
    3782         961 :             rSI.eCJKFontSrcCharSet = pj->eCJKFontSrcCharSet;
    3783         961 :             rSI.n81Flags = pj->n81Flags;
    3784         961 :             rSI.n81BiDiFlags = pj->n81BiDiFlags;
    3785         961 :             if (!rSI.IsWW8BuiltInHeadingStyle())
    3786             :             {
    3787         852 :                 rSI.mnWW8OutlineLevel = pj->mnWW8OutlineLevel;
    3788             :             }
    3789         961 :             rSI.bParaAutoBefore = pj->bParaAutoBefore;
    3790         961 :             rSI.bParaAutoAfter = pj->bParaAutoAfter;
    3791             : 
    3792         961 :             if (pj->pWWFly)
    3793           0 :                 rSI.pWWFly = new WW8FlyPara(pIo->m_bVer67, pj->pWWFly);
    3794         978 :         }
    3795             :     }
    3796         692 :     else if( pIo->m_bNewDoc && bStyExist )
    3797         305 :         rSI.pFormat->SetDerivedFrom(0);
    3798             : 
    3799        1670 :     rSI.nFollow = nNextStyle;       // remember Follow
    3800             : 
    3801        1670 :     pStyRule = 0;                   // recreate if necessary
    3802             :     bTextColChanged = bFontChanged = bCJKFontChanged = bCTLFontChanged =
    3803        1670 :         bFSizeChanged = bFCTLSizeChanged = bWidowsChanged = false;
    3804        1670 :     pIo->SetNAktColl( nThisStyle );
    3805        1670 :     pIo->m_bStyNormal = nThisStyle == 0;
    3806        1670 :     return bOldNoImp;
    3807             : }
    3808             : 
    3809        1670 : void WW8RStyle::PostStyle(SwWW8StyInf &rSI, bool bOldNoImp)
    3810             : {
    3811             :     // Reset attribute flags, because there are no style-ends.
    3812             : 
    3813        1670 :     pIo->m_bHasBorder = pIo->m_bSpec = pIo->m_bObj = pIo->m_bSymbol = false;
    3814        1670 :     pIo->m_nCharFormat = -1;
    3815             : 
    3816             :     // If Style basiert auf Nichts oder Basis ignoriert
    3817        1670 :     if ((rSI.nBase >= cstd || pIo->m_vColl[rSI.nBase].bImportSkipped) && rSI.bColl)
    3818             :     {
    3819             :         // If Char-Styles does not work
    3820             :         // -> set hard WW-Defaults
    3821         155 :         Set1StyleDefaults();
    3822             :     }
    3823             : 
    3824        1670 :     pStyRule = 0;                   // to be on the safe side
    3825        1670 :     pIo->m_bStyNormal = false;
    3826        1670 :     pIo->SetNAktColl( 0 );
    3827        1670 :     pIo->m_bNoAttrImport = bOldNoImp;
    3828             :     // reset the list-remember-fields, if used when reading styles
    3829        1670 :     pIo->m_nLFOPosition = USHRT_MAX;
    3830        1670 :     pIo->m_nListLevel = WW8ListManager::nMaxLevel;
    3831        1670 : }
    3832             : 
    3833        1802 : void WW8RStyle::Import1Style( sal_uInt16 nNr )
    3834             : {
    3835        1802 :     if (nNr >= pIo->m_vColl.size())
    3836         149 :         return;
    3837             : 
    3838        1802 :     SwWW8StyInf &rSI = pIo->m_vColl[nNr];
    3839             : 
    3840        1802 :     if( rSI.bImported || !rSI.bValid )
    3841          13 :         return;
    3842             : 
    3843        1789 :     rSI.bImported = true;                      // set flag now to avoid endless loops
    3844             : 
    3845             :     // valid and not NUL and not yet imported
    3846             : 
    3847        1789 :     if( rSI.nBase < cstd && !pIo->m_vColl[rSI.nBase].bImported )
    3848          13 :         Import1Style( rSI.nBase );
    3849             : 
    3850        1789 :     pStStrm->Seek( rSI.nFilePos );
    3851             : 
    3852             :     short nSkip, cbStd;
    3853        1789 :     OUString sName;
    3854             : 
    3855        3442 :     boost::scoped_ptr<WW8_STD> xStd(Read1Style(nSkip, &sName, &cbStd));// read Style
    3856             : 
    3857        1789 :     if (xStd)
    3858        1789 :         rSI.SetOrgWWIdent( sName, xStd->sti );
    3859             : 
    3860             :     // either no Name or unused Slot or unknown Style
    3861             : 
    3862        1789 :     if ( !xStd || sName.isEmpty() || ((1 != xStd->sgc) && (2 != xStd->sgc)) )
    3863             :     {
    3864         136 :         pStStrm->SeekRel( nSkip );
    3865         136 :         return;
    3866             :     }
    3867             : 
    3868        1653 :     bool bOldNoImp = PrepareStyle(rSI, static_cast<ww::sti>(xStd->sti), nNr, xStd->istdNext);
    3869             : 
    3870             :     // if something is interpreted wrong, this should make it work again
    3871        1653 :     long nPos = pStStrm->Tell();
    3872             : 
    3873             :     //Variable parts of the STD start at even byte offsets, but "inside
    3874             :     //the STD", which I take to meaning even in relation to the starting
    3875             :     //position of the STD, which matches findings in #89439#, generally it
    3876             :     //doesn't matter as the STSHI starts off nearly always on an even
    3877             :     //offset
    3878             : 
    3879             :     //Import of the Style Contents
    3880        1653 :     ImportGrupx(nSkip, xStd->sgc == 1, rSI.nFilePos & 1);
    3881             : 
    3882        1653 :     PostStyle(rSI, bOldNoImp);
    3883             : 
    3884        3306 :     pStStrm->Seek( nPos+nSkip );
    3885             : }
    3886             : 
    3887        1822 : void WW8RStyle::RecursiveReg(sal_uInt16 nNr)
    3888             : {
    3889        1822 :     if (nNr >= pIo->m_vColl.size())
    3890           0 :         return;
    3891             : 
    3892        1822 :     SwWW8StyInf &rSI = pIo->m_vColl[nNr];
    3893        1822 :     if( rSI.bImported || !rSI.bValid )
    3894          16 :         return;
    3895             : 
    3896        1806 :     rSI.bImported = true;
    3897             : 
    3898        1806 :     if( rSI.nBase < cstd && !pIo->m_vColl[rSI.nBase].bImported )
    3899          16 :         RecursiveReg(rSI.nBase);
    3900             : 
    3901        1806 :     pIo->RegisterNumFormatOnStyle(nNr);
    3902             : 
    3903             : }
    3904             : 
    3905             : /*
    3906             :  After all styles are imported then we can recursively apply numbering
    3907             :  styles to them, and change their tab stop settings if they turned out
    3908             :  to have special first line indentation.
    3909             : */
    3910         125 : void WW8RStyle::PostProcessStyles()
    3911             : {
    3912             :     sal_uInt16 i;
    3913             :     /*
    3914             :      Clear all imported flags so that we can recursively apply numbering
    3915             :      formats and use it to mark handled ones
    3916             :     */
    3917        3825 :     for (i=0; i < cstd; ++i)
    3918        3700 :         pIo->m_vColl[i].bImported = false;
    3919             : 
    3920             :     /*
    3921             :      Register the num formats and tabstop changes on the styles recursively.
    3922             :     */
    3923             : 
    3924             :     /*
    3925             :      In the same loop apply the tabstop changes required because we need to
    3926             :      change their location if theres a special indentation for the first line,
    3927             :      By avoiding making use of each styles margins during reading of their
    3928             :      tabstops we don't get problems with doubly adjusting tabstops that
    3929             :      are inheritied.
    3930             :     */
    3931        3825 :     for (i=0; i < cstd; ++i)
    3932             :     {
    3933        3700 :         if (pIo->m_vColl[i].bValid)
    3934             :         {
    3935        1806 :             RecursiveReg(i);
    3936             :         }
    3937             :     }
    3938         125 : }
    3939             : 
    3940         123 : void WW8RStyle::ScanStyles()        // investigate style dependencies
    3941             : {                                   // and detect Filepos for each Style
    3942        3311 :     for (sal_uInt16 i = 0; i < cstd; ++i)
    3943             :     {
    3944             :         short nSkip;
    3945        3188 :         SwWW8StyInf &rSI = pIo->m_vColl[i];
    3946             : 
    3947        3188 :         rSI.nFilePos = pStStrm->Tell();        // remember FilePos
    3948        3188 :         WW8_STD* pStd = Read1Style( nSkip, 0, 0 );  // read STD
    3949        3188 :         rSI.bValid = (0 != pStd);
    3950        3188 :         if (rSI.bValid)
    3951             :         {
    3952        1789 :             rSI.nBase = pStd->istdBase;        // remember Basis
    3953        1789 :             rSI.bColl = ( pStd->sgc == 1 );    // Para-Style
    3954             :         }
    3955             :         else
    3956        1399 :             rSI = SwWW8StyInf();
    3957             : 
    3958        3188 :         delete pStd;
    3959        3188 :         pStStrm->SeekRel( nSkip );              // skip Names and Sprms
    3960             :     }
    3961         123 : }
    3962             : 
    3963          93 : std::vector<sal_uInt8> ChpxToSprms(const Word2CHPX &rChpx)
    3964             : {
    3965          93 :     std::vector<sal_uInt8> aRet;
    3966             : 
    3967          93 :     aRet.push_back(60);
    3968          93 :     aRet.push_back( static_cast< sal_uInt8 >(128 + rChpx.fBold) );
    3969             : 
    3970          93 :     aRet.push_back(61);
    3971          93 :     aRet.push_back( static_cast< sal_uInt8 >(128 + rChpx.fItalic) );
    3972             : 
    3973          93 :     aRet.push_back(62);
    3974          93 :     aRet.push_back( static_cast< sal_uInt8 >(128 + rChpx.fStrike) );
    3975             : 
    3976          93 :     aRet.push_back(63);
    3977          93 :     aRet.push_back( static_cast< sal_uInt8 >(128 + rChpx.fOutline) );
    3978             : 
    3979          93 :     aRet.push_back(65);
    3980          93 :     aRet.push_back( static_cast< sal_uInt8 >(128 + rChpx.fSmallCaps) );
    3981             : 
    3982          93 :     aRet.push_back(66);
    3983          93 :     aRet.push_back( static_cast< sal_uInt8 >(128 + rChpx.fCaps) );
    3984             : 
    3985          93 :     aRet.push_back(67);
    3986          93 :     aRet.push_back( static_cast< sal_uInt8 >(128 + rChpx.fVanish) );
    3987             : 
    3988          93 :     if (rChpx.fsFtc)
    3989             :     {
    3990          86 :         aRet.push_back(68);
    3991             :         SVBT16 a;
    3992          86 :         ShortToSVBT16(rChpx.ftc, a);
    3993          86 :         aRet.push_back(a[1]);
    3994          86 :         aRet.push_back(a[0]);
    3995             :     }
    3996             : 
    3997          93 :     if (rChpx.fsKul)
    3998             :     {
    3999           6 :         aRet.push_back(69);
    4000           6 :         aRet.push_back(rChpx.kul);
    4001             :     }
    4002             : 
    4003          93 :     if (rChpx.fsLid)
    4004             :     {
    4005           1 :         aRet.push_back(72);
    4006             :         SVBT16 a;
    4007           1 :         ShortToSVBT16(rChpx.lid, a);
    4008           1 :         aRet.push_back(a[1]);
    4009           1 :         aRet.push_back(a[0]);
    4010             :     }
    4011             : 
    4012          93 :     if (rChpx.fsIco)
    4013             :     {
    4014           6 :         aRet.push_back(73);
    4015           6 :         aRet.push_back(rChpx.ico);
    4016             :     }
    4017             : 
    4018          93 :     if (rChpx.fsHps)
    4019             :     {
    4020          86 :         aRet.push_back(74);
    4021             : 
    4022             :         SVBT16 a;
    4023          86 :         ShortToSVBT16(rChpx.hps, a);
    4024          86 :         aRet.push_back(a[0]);
    4025             :     }
    4026             : 
    4027          93 :     if (rChpx.fsPos)
    4028             :     {
    4029           0 :         aRet.push_back(76);
    4030           0 :         aRet.push_back(rChpx.hpsPos);
    4031             :     }
    4032             : 
    4033          93 :     aRet.push_back(80);
    4034          93 :     aRet.push_back( static_cast< sal_uInt8 >(128 + rChpx.fBoldBi) );
    4035             : 
    4036          93 :     aRet.push_back(81);
    4037          93 :     aRet.push_back( static_cast< sal_uInt8 >(128 + rChpx.fItalicBi) );
    4038             : 
    4039          93 :     if (rChpx.fsFtcBi)
    4040             :     {
    4041           0 :         aRet.push_back(82);
    4042             :         SVBT16 a;
    4043           0 :         ShortToSVBT16(rChpx.fsFtcBi, a);
    4044           0 :         aRet.push_back(a[1]);
    4045           0 :         aRet.push_back(a[0]);
    4046             :     }
    4047             : 
    4048          93 :     if (rChpx.fsLidBi)
    4049             :     {
    4050           0 :         aRet.push_back(83);
    4051             :         SVBT16 a;
    4052           0 :         ShortToSVBT16(rChpx.lidBi, a);
    4053           0 :         aRet.push_back(a[1]);
    4054           0 :         aRet.push_back(a[0]);
    4055             :     }
    4056             : 
    4057          93 :     if (rChpx.fsIcoBi)
    4058             :     {
    4059           0 :         aRet.push_back(84);
    4060           0 :         aRet.push_back(rChpx.icoBi);
    4061             :     }
    4062             : 
    4063          93 :     if (rChpx.fsHpsBi)
    4064             :     {
    4065           0 :         aRet.push_back(85);
    4066             :         SVBT16 a;
    4067           0 :         ShortToSVBT16(rChpx.hpsBi, a);
    4068           0 :         aRet.push_back(a[1]);
    4069           0 :         aRet.push_back(a[0]);
    4070             :     }
    4071             : 
    4072          93 :     return aRet;
    4073             : }
    4074             : 
    4075          93 : Word2CHPX ReadWord2Chpx(SvStream &rSt, sal_Size nOffset, sal_uInt8 nSize)
    4076             : {
    4077          93 :     Word2CHPX aChpx;
    4078             : 
    4079          93 :     if (!nSize)
    4080           1 :         return aChpx;
    4081             : 
    4082          92 :     rSt.Seek(nOffset);
    4083             : 
    4084          92 :     sal_uInt8 nCount=0;
    4085             : 
    4086             :     while (true)
    4087             :     {
    4088             :         sal_uInt8 nFlags8;
    4089          92 :         rSt.ReadUChar( nFlags8 );
    4090          92 :         nCount++;
    4091             : 
    4092          92 :         aChpx.fBold = nFlags8 & 0x01;
    4093          92 :         aChpx.fItalic = (nFlags8 & 0x02) >> 1;
    4094          92 :         aChpx.fRMarkDel = (nFlags8 & 0x04) >> 2;
    4095          92 :         aChpx.fOutline = (nFlags8 & 0x08) >> 3;
    4096          92 :         aChpx.fFieldVanish = (nFlags8 & 0x10) >> 4;
    4097          92 :         aChpx.fSmallCaps = (nFlags8 & 0x20) >> 5;
    4098          92 :         aChpx.fCaps = (nFlags8 & 0x40) >> 6;
    4099          92 :         aChpx.fVanish = (nFlags8 & 0x80) >> 7;
    4100             : 
    4101          92 :         if (nCount >= nSize) break;
    4102          92 :         rSt.ReadUChar( nFlags8 );
    4103          92 :         nCount++;
    4104             : 
    4105          92 :         aChpx.fRMark = nFlags8 & 0x01;
    4106          92 :         aChpx.fSpec = (nFlags8 & 0x02) >> 1;
    4107          92 :         aChpx.fStrike = (nFlags8 & 0x04) >> 2;
    4108          92 :         aChpx.fObj = (nFlags8 & 0x08) >> 3;
    4109          92 :         aChpx.fBoldBi = (nFlags8 & 0x10) >> 4;
    4110          92 :         aChpx.fItalicBi = (nFlags8 & 0x20) >> 5;
    4111          92 :         aChpx.fBiDi = (nFlags8 & 0x40) >> 6;
    4112          92 :         aChpx.fDiacUSico = (nFlags8 & 0x80) >> 7;
    4113             : 
    4114          92 :         if (nCount >= nSize) break;
    4115          92 :         rSt.ReadUChar( nFlags8 );
    4116          92 :         nCount++;
    4117             : 
    4118          92 :         aChpx.fsIco = nFlags8 & 0x01;
    4119          92 :         aChpx.fsFtc = (nFlags8 & 0x02) >> 1;
    4120          92 :         aChpx.fsHps = (nFlags8 & 0x04) >> 2;
    4121          92 :         aChpx.fsKul = (nFlags8 & 0x08) >> 3;
    4122          92 :         aChpx.fsPos = (nFlags8 & 0x10) >> 4;
    4123          92 :         aChpx.fsSpace = (nFlags8 & 0x20) >> 5;
    4124          92 :         aChpx.fsLid = (nFlags8 & 0x40) >> 6;
    4125          92 :         aChpx.fsIcoBi = (nFlags8 & 0x80) >> 7;
    4126             : 
    4127          92 :         if (nCount >= nSize) break;
    4128          92 :         rSt.ReadUChar( nFlags8 );
    4129          92 :         nCount++;
    4130             : 
    4131          92 :         aChpx.fsFtcBi = nFlags8 & 0x01;
    4132          92 :         aChpx.fsHpsBi = (nFlags8 & 0x02) >> 1;
    4133          92 :         aChpx.fsLidBi = (nFlags8 & 0x04) >> 2;
    4134             : 
    4135          92 :         if (nCount >= nSize) break;
    4136          92 :         rSt.ReadUInt16( aChpx.ftc );
    4137          92 :         nCount+=2;
    4138             : 
    4139          92 :         if (nCount >= nSize) break;
    4140          88 :         rSt.ReadUInt16( aChpx.hps );
    4141          88 :         nCount+=2;
    4142             : 
    4143          88 :         if (nCount >= nSize) break;
    4144           9 :         rSt.ReadUChar( nFlags8 );
    4145           9 :         nCount++;
    4146             : 
    4147           9 :         aChpx.qpsSpace = nFlags8 & 0x3F;
    4148           9 :         aChpx.fSysVanish = (nFlags8 & 0x40) >> 6;
    4149           9 :         aChpx.fNumRun = (nFlags8 & 0x80) >> 7;
    4150             : 
    4151           9 :         if (nCount >= nSize) break;
    4152           9 :         rSt.ReadUChar( nFlags8 );
    4153           9 :         nCount++;
    4154             : 
    4155           9 :         aChpx.ico = nFlags8 & 0x1F;
    4156           9 :         aChpx.kul = (nFlags8 & 0xE0) >> 5;
    4157             : 
    4158           9 :         if (nCount >= nSize) break;
    4159           3 :         rSt.ReadUChar( aChpx.hpsPos );
    4160           3 :         nCount++;
    4161             : 
    4162           3 :         if (nCount >= nSize) break;
    4163           3 :         rSt.ReadUChar( aChpx.icoBi );
    4164           3 :         nCount++;
    4165             : 
    4166           3 :         if (nCount >= nSize) break;
    4167           3 :         rSt.ReadUInt16( aChpx.lid );
    4168           3 :         nCount+=2;
    4169             : 
    4170           3 :         if (nCount >= nSize) break;
    4171           1 :         rSt.ReadUInt16( aChpx.ftcBi );
    4172           1 :         nCount+=2;
    4173             : 
    4174           1 :         if (nCount >= nSize) break;
    4175           1 :         rSt.ReadUInt16( aChpx.hpsBi );
    4176           1 :         nCount+=2;
    4177             : 
    4178           1 :         if (nCount >= nSize) break;
    4179           0 :         rSt.ReadUInt16( aChpx.lidBi );
    4180           0 :         nCount+=2;
    4181             : 
    4182           0 :         if (nCount >= nSize) break;
    4183           0 :         rSt.ReadUInt32( aChpx.fcPic );
    4184           0 :         nCount+=4;
    4185             : 
    4186           0 :         break;
    4187             :     }
    4188             : 
    4189          92 :     rSt.SeekRel(nSize-nCount);
    4190          92 :     return aChpx;
    4191             : }
    4192             : 
    4193             : namespace
    4194             : {
    4195             :     struct pxoffset { sal_Size mnOffset; sal_uInt8 mnSize; };
    4196             : }
    4197             : 
    4198           2 : void WW8RStyle::ImportOldFormatStyles()
    4199             : {
    4200         514 :     for (sal_uInt16 i=0; i < cstd; ++i)
    4201             :     {
    4202         512 :         pIo->m_vColl[i].bColl = true;
    4203             :         //every chain must end eventually at the null style (style code 222)
    4204         512 :         pIo->m_vColl[i].nBase = 222;
    4205             :     }
    4206             : 
    4207             :     rtl_TextEncoding eStructChrSet = WW8Fib::GetFIBCharset(
    4208           2 :         pIo->m_pWwFib->chseTables, pIo->m_pWwFib->lid);
    4209             : 
    4210           2 :     sal_uInt16 cstcStd(0);
    4211           2 :     rSt.ReadUInt16( cstcStd );
    4212             : 
    4213           2 :     size_t nMaxByteCount = rSt.remainingSize();
    4214           2 :     sal_uInt16 cbName(0);
    4215           2 :     rSt.ReadUInt16(cbName);
    4216           2 :     if (cbName > nMaxByteCount)
    4217             :     {
    4218             :         SAL_WARN("sw.ww8", "WW8RStyle::ImportOldFormatStyles: truncating out of range "
    4219             :             << cbName << " to " << nMaxByteCount);
    4220           0 :         cbName = nMaxByteCount;
    4221             :     }
    4222           2 :     sal_uInt16 nByteCount = 2;
    4223           2 :     sal_uInt16 stcp=0;
    4224          21 :     while (nByteCount < cbName)
    4225             :     {
    4226          17 :         sal_uInt8 nCount(0);
    4227          17 :         rSt.ReadUChar( nCount );
    4228          17 :         nByteCount++;
    4229             : 
    4230          17 :         sal_uInt8 stc = static_cast< sal_uInt8 >((stcp - cstcStd) & 255);
    4231          17 :         if (stc >=pIo->m_vColl.size())
    4232           0 :             continue;
    4233             : 
    4234          17 :         SwWW8StyInf &rSI = pIo->m_vColl[stc];
    4235          17 :         OUString sName;
    4236             : 
    4237          17 :         if (nCount != 0xFF)    // undefined style
    4238             :         {
    4239           4 :             if (nCount != 0)   // user style
    4240             :             {
    4241           0 :                 OString aTmp = read_uInt8s_ToOString(rSt, nCount);
    4242           0 :                 nByteCount += aTmp.getLength();
    4243           0 :                 sName = OStringToOUString(aTmp, eStructChrSet);
    4244             :             }
    4245           4 :             rSI.bImported = true;
    4246             :         }
    4247             : 
    4248          17 :         if (sName.isEmpty())
    4249             :         {
    4250          17 :             ww::sti eSti = ww::GetCanonicalStiFromStc(stc);
    4251          17 :             if (const sal_Char *pStr = GetEnglishNameFromSti(eSti))
    4252          16 :                 sName = OUString(pStr, strlen(pStr), RTL_TEXTENCODING_ASCII_US);
    4253             :         }
    4254             : 
    4255          17 :         if (sName.isEmpty())
    4256           1 :             sName = "Unknown Style: " + OUString::number(stc);
    4257             : 
    4258          17 :         rSI.SetOrgWWIdent(sName, stc);
    4259          17 :         stcp++;
    4260          17 :     }
    4261             : 
    4262           2 :     sal_uInt16 nStyles=stcp;
    4263             : 
    4264           2 :     std::vector<pxoffset> aCHPXOffsets(stcp);
    4265           2 :     nMaxByteCount = rSt.remainingSize();
    4266           2 :     sal_uInt16 cbChpx(0);
    4267           2 :     rSt.ReadUInt16(cbChpx);
    4268           2 :     if (cbChpx > nMaxByteCount)
    4269             :     {
    4270             :         SAL_WARN("sw.ww8", "WW8RStyle::ImportOldFormatStyles: truncating out of range "
    4271             :             << cbChpx << " to " << nMaxByteCount);
    4272           0 :         cbChpx = nMaxByteCount;
    4273             :     }
    4274           2 :     nByteCount = 2;
    4275           2 :     stcp=0;
    4276           4 :     std::vector< std::vector<sal_uInt8> > aConvertedChpx;
    4277          21 :     while (nByteCount < cbChpx)
    4278             :     {
    4279          17 :         sal_uInt8 cb(0);
    4280          17 :         rSt.ReadUChar( cb );
    4281          17 :         nByteCount++;
    4282             : 
    4283          17 :         aCHPXOffsets[stcp].mnSize = 0;
    4284             : 
    4285          17 :         if (cb != 0xFF)
    4286             :         {
    4287           2 :             sal_uInt8 nRemainder = cb;
    4288             : 
    4289           2 :             aCHPXOffsets[stcp].mnOffset = rSt.Tell();
    4290           2 :             aCHPXOffsets[stcp].mnSize = nRemainder;
    4291             : 
    4292           2 :             Word2CHPX aChpx = ReadWord2Chpx(rSt, aCHPXOffsets[stcp].mnOffset,
    4293           4 :                 aCHPXOffsets[stcp].mnSize);
    4294           2 :             aConvertedChpx.push_back( ChpxToSprms(aChpx) );
    4295             : 
    4296           2 :             nByteCount += nRemainder;
    4297             :         }
    4298             :         else
    4299          15 :             aConvertedChpx.push_back( std::vector<sal_uInt8>() );
    4300             : 
    4301          17 :         stcp++;
    4302          17 :         if (stcp == nStyles)
    4303             :         {
    4304           2 :             rSt.SeekRel(cbChpx-nByteCount);
    4305           2 :             nByteCount += cbChpx-nByteCount;
    4306             :         }
    4307             :     }
    4308             : 
    4309           4 :     std::vector<pxoffset> aPAPXOffsets(stcp);
    4310           2 :     nMaxByteCount = rSt.remainingSize();
    4311           2 :     sal_uInt16 cbPapx(0);
    4312           2 :     rSt.ReadUInt16(cbPapx);
    4313           2 :     if (cbPapx > nMaxByteCount)
    4314             :     {
    4315             :         SAL_WARN("sw.ww8", "WW8RStyle::ImportOldFormatStyles: truncating out of range "
    4316             :             << cbPapx << " to " << nMaxByteCount);
    4317           0 :         cbPapx = nMaxByteCount;
    4318             :     }
    4319           2 :     nByteCount = 2;
    4320           2 :     stcp=0;
    4321          21 :     while (nByteCount < cbPapx)
    4322             :     {
    4323          17 :         sal_uInt8 cb(0);
    4324          17 :         rSt.ReadUChar( cb );
    4325          17 :         nByteCount++;
    4326             : 
    4327          17 :         aPAPXOffsets[stcp].mnSize = 0;
    4328             : 
    4329          17 :         if (cb != 0xFF)
    4330             :         {
    4331           2 :             sal_uInt8 stc2(0);
    4332           2 :             rSt.ReadUChar( stc2 );
    4333           2 :             rSt.SeekRel(6);
    4334           2 :             nByteCount+=7;
    4335           2 :             sal_uInt8 nRemainder = cb-7;
    4336             : 
    4337           2 :             aPAPXOffsets[stcp].mnOffset = rSt.Tell();
    4338           2 :             aPAPXOffsets[stcp].mnSize = nRemainder;
    4339             : 
    4340           2 :             rSt.SeekRel(nRemainder);
    4341           2 :             nByteCount += nRemainder;
    4342             :         }
    4343             : 
    4344          17 :         stcp++;
    4345             : 
    4346          17 :         if (stcp == nStyles)
    4347             :         {
    4348           2 :             rSt.SeekRel(cbPapx-nByteCount);
    4349           2 :             nByteCount += cbPapx-nByteCount;
    4350             :         }
    4351             :     }
    4352             : 
    4353           2 :     sal_uInt16 iMac(0);
    4354           2 :     rSt.ReadUInt16( iMac );
    4355             : 
    4356           2 :     if (iMac > nStyles) iMac = nStyles;
    4357             : 
    4358          19 :     for (stcp = 0; stcp < iMac; ++stcp)
    4359             :     {
    4360          17 :         sal_uInt8 stcNext(0), stcBase(0);
    4361          17 :         rSt.ReadUChar( stcNext );
    4362          17 :         rSt.ReadUChar( stcBase );
    4363             : 
    4364          17 :         sal_uInt8 stc = static_cast< sal_uInt8 >((stcp - cstcStd) & 255);
    4365             : 
    4366             :         /*
    4367             :           #i64557# style based on itself
    4368             :           every chain must end eventually at the null style (style code 222)
    4369             :         */
    4370          17 :         if (stc == stcBase)
    4371           1 :             stcBase = 222;
    4372             : 
    4373          17 :         SwWW8StyInf &rSI = pIo->m_vColl[stc];
    4374          17 :         rSI.nBase = stcBase;
    4375             : 
    4376          17 :         ww::sti eSti = ww::GetCanonicalStiFromStc(stc);
    4377             : 
    4378          17 :         if (eSti == ww::stiNil)
    4379           0 :             continue;
    4380             : 
    4381          17 :         rSI.bValid = true;
    4382             : 
    4383          17 :         if (ww::StandardStiIsCharStyle(eSti) && !aPAPXOffsets[stcp].mnSize)
    4384           1 :             pIo->m_vColl[stc].bColl = false;
    4385             : 
    4386          17 :         bool bOldNoImp = PrepareStyle(rSI, eSti, stc, stcNext);
    4387             : 
    4388          34 :         ImportSprms(aPAPXOffsets[stcp].mnOffset, aPAPXOffsets[stcp].mnSize,
    4389          34 :             true);
    4390             : 
    4391          17 :         if (aConvertedChpx[stcp].size() > 0)
    4392           2 :             ImportSprms(&(aConvertedChpx[stcp][0]),
    4393           2 :                         static_cast< short >(aConvertedChpx[stcp].size()),
    4394           4 :                         false);
    4395             : 
    4396          17 :         PostStyle(rSI, bOldNoImp);
    4397           2 :     }
    4398           2 : }
    4399             : 
    4400         123 : void WW8RStyle::ImportNewFormatStyles()
    4401             : {
    4402         123 :     ScanStyles();                       // Scan Based On
    4403             : 
    4404        3311 :     for (sal_uInt16 i = 0; i < cstd; ++i) // import Styles
    4405        3188 :         if (pIo->m_vColl[i].bValid)
    4406        1789 :             Import1Style( i );
    4407         123 : }
    4408             : 
    4409         125 : void WW8RStyle::ImportStyles()
    4410             : {
    4411         125 :     if (pIo->m_pWwFib->GetFIBVersion() <= ww::eWW2)
    4412           2 :         ImportOldFormatStyles();
    4413             :     else
    4414         123 :         ImportNewFormatStyles();
    4415         125 : }
    4416             : 
    4417         125 : void WW8RStyle::Import()
    4418             : {
    4419         125 :     pIo->m_pDfltTextFormatColl  = pIo->m_rDoc.GetDfltTextFormatColl();
    4420             :     pIo->m_pStandardFormatColl =
    4421         125 :         pIo->m_rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool(RES_POOLCOLL_STANDARD, false);
    4422             : 
    4423         125 :     if( pIo->m_nIniFlags & WW8FL_NO_STYLES )
    4424         125 :         return;
    4425             : 
    4426         125 :     ImportStyles();
    4427             : 
    4428        3825 :     for (sal_uInt16 i = 0; i < cstd; ++i)
    4429             :     {
    4430             :         // Follow chain
    4431        3700 :         SwWW8StyInf* pi = &pIo->m_vColl[i];
    4432        3700 :         sal_uInt16 j = pi->nFollow;
    4433        3700 :         if( j < cstd )
    4434             :         {
    4435        3700 :             SwWW8StyInf* pj = &pIo->m_vColl[j];
    4436        3700 :             if ( j != i                             // rational Index ?
    4437        2269 :                  && pi->pFormat                        // Format ok ?
    4438         239 :                  && pj->pFormat                        // Derived-Format ok ?
    4439         238 :                  && pi->bColl                       // only possible for paragraph templates (WW)
    4440         237 :                  && pj->bColl ){                    // identical Typ ?
    4441             :                     static_cast<SwTextFormatColl*>(pi->pFormat)->SetNextTextFormatColl(
    4442         237 :                      *static_cast<SwTextFormatColl*>(pj->pFormat) );    // ok, register
    4443             :             }
    4444             :         }
    4445             :     }
    4446             : 
    4447             :     // Missing special handling for default character template
    4448             :     // "Absatz-Standardschriftart" ( Style-ID 65 ).
    4449             :     // That is empty by default ( WW6 dt and US ) and not changeable
    4450             :     // via WW-UI so this does not matter.
    4451             :     // This could be done by:
    4452             :     //  if( bNew ) rDoc.SetDefault( pDefCharFormat->GetAttrSet() );
    4453             : 
    4454             :     // for e.g. tables an always valid Std-Style is necessary
    4455             : 
    4456         500 :     if( pIo->StyleExists(0) && !pIo->m_vColl.empty() &&
    4457         375 :         pIo->m_vColl[0].pFormat && pIo->m_vColl[0].bColl && pIo->m_vColl[0].bValid )
    4458         125 :         pIo->m_pDfltTextFormatColl = static_cast<SwTextFormatColl*>(pIo->m_vColl[0].pFormat);
    4459             :     else
    4460           0 :         pIo->m_pDfltTextFormatColl = pIo->m_rDoc.GetDfltTextFormatColl();
    4461             : 
    4462             :     // set Hyphenation flag on BASIC para-style
    4463         125 :     if (pIo->m_bNewDoc && pIo->m_pStandardFormatColl)
    4464             :     {
    4465         125 :         if (pIo->m_pWDop->fAutoHyphen
    4466         125 :             && SfxItemState::SET != pIo->m_pStandardFormatColl->GetItemState(
    4467           0 :                                             RES_PARATR_HYPHENZONE, false) )
    4468             :         {
    4469           0 :             SvxHyphenZoneItem aAttr(true, RES_PARATR_HYPHENZONE);
    4470           0 :             aAttr.GetMinLead()    = 2;
    4471           0 :             aAttr.GetMinTrail()   = 2;
    4472           0 :             aAttr.GetMaxHyphens() = 0;
    4473             : 
    4474           0 :             pIo->m_pStandardFormatColl->SetFormatAttr( aAttr );
    4475             :         }
    4476             : 
    4477             :         /*
    4478             :         Word defaults to ltr not from environment like writer. Regardless of
    4479             :         the page/sections rtl setting the standard style lack of rtl still
    4480             :         means ltr
    4481             :         */
    4482         125 :         if (SfxItemState::SET != pIo->m_pStandardFormatColl->GetItemState(RES_FRAMEDIR,
    4483         125 :             false))
    4484             :         {
    4485             :            pIo->m_pStandardFormatColl->SetFormatAttr(
    4486          82 :                 SvxFrameDirectionItem(FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR));
    4487             :         }
    4488             :     }
    4489             : 
    4490             :     // we do not read styles anymore:
    4491         125 :     pIo->m_pAktColl = 0;
    4492             : }
    4493             : 
    4494         351 : rtl_TextEncoding SwWW8StyInf::GetCharSet() const
    4495             : {
    4496         351 :     if ((pFormat) && (pFormat->GetFrmDir().GetValue() == FRMDIR_HORI_RIGHT_TOP))
    4497           0 :         return eRTLFontSrcCharSet;
    4498         351 :     return eLTRFontSrcCharSet;
    4499             : }
    4500             : 
    4501         311 : rtl_TextEncoding SwWW8StyInf::GetCJKCharSet() const
    4502             : {
    4503         311 :     if ((pFormat) && (pFormat->GetFrmDir().GetValue() == FRMDIR_HORI_RIGHT_TOP))
    4504           0 :         return eRTLFontSrcCharSet;
    4505         311 :     return eCJKFontSrcCharSet;
    4506          60 : }
    4507             : 
    4508             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11