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

Generated by: LCOV version 1.10