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

Generated by: LCOV version 1.10