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

Generated by: LCOV version 1.10