summaryrefslogtreecommitdiff
path: root/sw/source/filter/ww8/ww8par2.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/filter/ww8/ww8par2.cxx')
-rw-r--r--sw/source/filter/ww8/ww8par2.cxx4735
1 files changed, 4735 insertions, 0 deletions
diff --git a/sw/source/filter/ww8/ww8par2.cxx b/sw/source/filter/ww8/ww8par2.cxx
new file mode 100644
index 000000000000..7342843e6b9a
--- /dev/null
+++ b/sw/source/filter/ww8/ww8par2.cxx
@@ -0,0 +1,4735 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ww8par2.cxx,v $
+ * $Revision: 1.145.76.2 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
+
+#include <tools/solar.h>
+#include <vcl/vclenum.hxx>
+#include <vcl/font.hxx>
+#include <hintids.hxx>
+#include <svx/colritem.hxx>
+#include <svx/orphitem.hxx>
+#include <svx/widwitem.hxx>
+#include <svx/brshitem.hxx>
+#include <svx/boxitem.hxx>
+#include <svx/lrspitem.hxx>
+#include <svx/fhgtitem.hxx>
+#include <svx/fhgtitem.hxx>
+#include <svx/hyznitem.hxx>
+#include <svx/frmdiritem.hxx>
+#include <svx/langitem.hxx>
+#include <svx/charrotateitem.hxx>
+#include <svx/pgrditem.hxx>
+#include <msfilter.hxx>
+#include <pam.hxx> // fuer SwPam
+#include <doc.hxx>
+#include <docary.hxx>
+#include <ndtxt.hxx> // class SwTxtNode
+#include <paratr.hxx> // SwNumRuleItem
+#include <poolfmt.hxx> // RES_POOLCOLL_STANDARD
+#include <swtable.hxx> // class SwTableLines, ...
+#include <tblsel.hxx> // class _SwSelBox
+#include <mdiexp.hxx>
+#include <fmtpdsc.hxx>
+#include <txtftn.hxx>
+#include <frmfmt.hxx>
+#include <ftnidx.hxx>
+#include <fmtftn.hxx>
+#include <charfmt.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <fltshell.hxx> // fuer den Attribut Stack
+#include <fmtanchr.hxx>
+#include <fmtrowsplt.hxx>
+// --> OD 2005-01-27 #i33818#
+#include <fmtfollowtextflow.hxx>
+// <--
+#include <numrule.hxx>
+# include "../inc/wwstyles.hxx"
+# include "writerhelper.hxx"
+#include "ww8struc.hxx" // struct TC
+#include "ww8par.hxx"
+#include "ww8par2.hxx"
+
+#include <frmatr.hxx>
+
+#include <iostream>
+
+#define MAX_COL 64 // WW6-Beschreibung: 32, WW6-UI: 31 & WW8-UI: 63!
+
+using namespace ::com::sun::star;
+
+
+class WW8SelBoxInfo: public SwSelBoxes_SAR
+{
+private:
+ WW8SelBoxInfo(const WW8SelBoxInfo&);
+ WW8SelBoxInfo& operator=(const WW8SelBoxInfo&);
+public:
+ short nGroupXStart;
+ short nGroupWidth;
+ bool bGroupLocked;
+
+ WW8SelBoxInfo(short nXCenter, short nWidth)
+ : nGroupXStart( nXCenter ), nGroupWidth( nWidth ), bGroupLocked(false)
+ {}
+};
+
+typedef WW8SelBoxInfo* WW8SelBoxInfoPtr;
+
+SV_DECL_PTRARR_DEL(WW8MergeGroups, WW8SelBoxInfoPtr, 16,16)
+SV_IMPL_PTRARR(WW8MergeGroups, WW8SelBoxInfoPtr)
+
+struct WW8TabBandDesc
+{
+ WW8TabBandDesc* pNextBand;
+ short nGapHalf;
+ short mnDefaultLeft;
+ short mnDefaultTop;
+ short mnDefaultRight;
+ short mnDefaultBottom;
+ bool mbHasSpacing;
+ short nLineHeight;
+ short nRows;
+ sal_uInt16 maDirections[MAX_COL + 1];
+ short nCenter[MAX_COL + 1]; // X-Rand aller Zellen dieses Bandes
+ short nWidth[MAX_COL + 1]; // Laenge aller Zellen dieses Bandes
+ short nWwCols; // BYTE wuerde reichen, alignment -> short
+ short nSwCols; // SW: so viele Spalten fuer den Writer
+ bool bLEmptyCol; // SW: Links eine leere Zusatz-Spalte
+ bool bREmptyCol; // SW: dito rechts
+ bool bCantSplit;
+ bool bCantSplit90;
+ WW8_TCell* pTCs;
+ BYTE nOverrideSpacing[MAX_COL + 1];
+ short nOverrideValues[MAX_COL + 1][4];
+ WW8_SHD* pSHDs;
+ sal_uInt32* pNewSHDs;
+ WW8_BRC aDefBrcs[6];
+
+
+ // nur fuer WW6-7: diese Zelle hat WW-Flag bMerged (horizontal) gesetzt
+ //bool bWWMergedVer6[MAX_COL];
+
+
+ bool bExist[MAX_COL]; // Existiert diese Zelle ?
+ UINT8 nTransCell[MAX_COL + 2]; // UEbersetzung WW-Index -> SW-Index
+
+ WW8TabBandDesc();
+ WW8TabBandDesc(WW8TabBandDesc& rBand); // tief kopieren
+ ~WW8TabBandDesc();
+ static void setcelldefaults(WW8_TCell *pCells, short nCells);
+ void ReadDef(bool bVer67, const BYTE* pS);
+ void ProcessDirection(const BYTE* pParams);
+ void ProcessSprmTSetBRC(bool bVer67, const BYTE* pParamsTSetBRC);
+ void ProcessSprmTTableBorders(bool bVer67, const BYTE* pParams);
+ void ProcessSprmTDxaCol(const BYTE* pParamsTDxaCol);
+ void ProcessSprmTDelete(const BYTE* pParamsTDelete);
+ void ProcessSprmTInsert(const BYTE* pParamsTInsert);
+ void ProcessSpacing(const BYTE* pParamsTInsert);
+ void ProcessSpecificSpacing(const BYTE* pParamsTInsert);
+ void ReadShd(const BYTE* pS );
+ void ReadNewShd(const BYTE* pS, bool bVer67);
+
+ enum wwDIR {wwTOP = 0, wwLEFT = 1, wwBOTTOM = 2, wwRIGHT = 3};
+};
+
+WW8TabBandDesc::WW8TabBandDesc()
+{
+ memset(this, 0, sizeof(*this));
+ for (size_t i = 0; i < sizeof(maDirections)/sizeof(sal_uInt16); ++i)
+ maDirections[i] = 4;
+}
+
+WW8TabBandDesc::~WW8TabBandDesc()
+{
+ delete[] pTCs;
+ delete[] pSHDs;
+ delete[] pNewSHDs;
+}
+
+class WW8TabDesc
+{
+ std::vector<String> aNumRuleNames;
+ sw::util::RedlineStack *mpOldRedlineStack;
+
+ SwWW8ImplReader* pIo;
+
+ WW8TabBandDesc* pFirstBand;
+ WW8TabBandDesc* pActBand;
+
+ SwPosition* pTmpPos;
+
+ SwTableNode* pTblNd; // Tabellen-Node
+ const SwTableLines* pTabLines; // Zeilen-Array davon
+ SwTableLine* pTabLine; // akt. Zeile
+ SwTableBoxes* pTabBoxes; // Boxen-Array in akt. Zeile
+ SwTableBox* pTabBox; // akt. Zelle
+
+ WW8MergeGroups* pMergeGroups; // Listen aller zu verknuepfenden Zellen
+
+ WW8_TCell* pAktWWCell;
+
+ short nRows;
+ short nDefaultSwCols;
+ short nBands;
+ short nMinLeft;
+ short nConvertedLeft;
+ short nMaxRight;
+ short nSwWidth;
+ short nPreferredWidth;
+ short nOrgDxaLeft;
+
+ bool bOk;
+ bool bClaimLineFmt;
+ sal_Int16 eOri;
+ bool bIsBiDi;
+ // 2. allgemeine Verwaltungsinfo
+ short nAktRow;
+ short nAktBandRow; // SW: in dieser Zeile des akt. Bandes bin ich
+ // 3. Verwaltungsinfo fuer Writer
+ short nAktCol;
+
+ USHORT nRowsToRepeat;
+
+ // 4. Methoden
+
+ USHORT GetLogicalWWCol() const;
+ void SetTabBorders( SwTableBox* pBox, short nIdx );
+ void SetTabShades( SwTableBox* pBox, short nWwIdx );
+ void SetTabVertAlign( SwTableBox* pBox, short nWwIdx );
+ void SetTabDirection( SwTableBox* pBox, short nWwIdx );
+ void CalcDefaults();
+ bool SetPamInCell(short nWwCol, bool bPam);
+ void InsertCells( short nIns );
+ void AdjustNewBand();
+
+ // durchsucht pMergeGroups, meldet Index der ersten, passenden Gruppe bzw.
+ // -1 Details siehe bei der Implementierung
+ bool FindMergeGroup(short nX1, short nWidth, bool bExact, short& nMGrIdx);
+
+ // einzelne Box ggfs. in eine Merge-Gruppe aufnehmen
+ // (die Merge-Gruppen werden dann spaeter auf einen Schlag abgearbeitet)
+ SwTableBox* UpdateTableMergeGroup(WW8_TCell& rCell,
+ WW8SelBoxInfo* pActGroup, SwTableBox* pActBox, USHORT nCol );
+ void StartMiserableHackForUnsupportedDirection(short nWwCol);
+ void EndMiserableHackForUnsupportedDirection(short nWwCol);
+ //No copying
+ WW8TabDesc(const WW8TabDesc&);
+ WW8TabDesc &operator=(const WW8TabDesc&);
+public:
+ const SwTable* pTable; // Tabelle
+ SwPosition* pParentPos;
+ SwFlyFrmFmt* pFlyFmt;
+ SfxItemSet aItemSet;
+ bool IsValidCell(short nCol) const;
+ bool InFirstParaInCell() const;
+
+ WW8TabDesc( SwWW8ImplReader* pIoClass, WW8_CP nStartCp );
+ bool Ok() const { return bOk; }
+ void CreateSwTable();
+ void UseSwTable();
+ void SetSizePosition(SwFrmFmt* pFrmFmt);
+ void TableCellEnd();
+ void MoveOutsideTable();
+ void ParkPaM();
+ void FinishSwTable();
+ void MergeCells();
+ short GetMinLeft() const { return nConvertedLeft; }
+ ~WW8TabDesc();
+ SwPosition *GetPos() { return pTmpPos; }
+
+ const WW8_TCell* GetAktWWCell() const { return pAktWWCell; }
+ short GetAktCol() const { return nAktCol; }
+ // find name of numrule valid for current WW-COL
+ const String& GetNumRuleName() const;
+ void SetNumRuleName( const String& rName );
+
+ sw::util::RedlineStack* getOldRedlineStack(){ return mpOldRedlineStack; }
+};
+
+void sw::util::RedlineStack::close( const SwPosition& rPos,
+ RedlineType_t eType, WW8TabDesc* pTabDesc )
+{
+ // If the redline type is not found in the redline stack, we have to check if there has been
+ // a tabledesc and to check its saved redline stack, too. (#136939, #i68139)
+ if( !close( rPos, eType ) )
+ {
+ if( pTabDesc && pTabDesc->getOldRedlineStack() )
+ {
+#ifndef PRODUCT
+ ASSERT( pTabDesc->getOldRedlineStack()->close(rPos, eType), "close without open!");
+#else
+ pTabDesc->getOldRedlineStack()->close( rPos, eType );
+#endif
+ }
+ }
+}
+
+
+void wwSectionManager::SetCurrentSectionHasFootnote()
+{
+ ASSERT(!maSegments.empty(),
+ "should not be possible, must be at least one segment");
+ if (!maSegments.empty())
+ maSegments.back().mbHasFootnote = true;
+}
+
+bool wwSectionManager::CurrentSectionIsVertical() const
+{
+ ASSERT(!maSegments.empty(),
+ "should not be possible, must be at least one segment");
+ if (!maSegments.empty())
+ return maSegments.back().IsVertical();
+ return false;
+}
+
+bool wwSectionManager::CurrentSectionIsProtected() const
+{
+ ASSERT(!maSegments.empty(),
+ "should not be possible, must be at least one segment");
+ if (!maSegments.empty())
+ return SectionIsProtected(maSegments.back());
+ return false;
+}
+
+sal_uInt32 wwSectionManager::GetPageLeft() const
+{
+ return !maSegments.empty() ? maSegments.back().nPgLeft : 0;
+}
+
+sal_uInt32 wwSectionManager::GetPageRight() const
+{
+ return !maSegments.empty() ? maSegments.back().nPgRight : 0;
+}
+
+sal_uInt32 wwSectionManager::GetPageWidth() const
+{
+ return !maSegments.empty() ? maSegments.back().GetPageWidth() : 0;
+}
+
+sal_uInt32 wwSectionManager::GetTextAreaWidth() const
+{
+ return !maSegments.empty() ? maSegments.back().GetTextAreaWidth() : 0;
+}
+
+// --> OD 2007-07-03 #148498#
+sal_uInt32 wwSectionManager::GetWWPageTopMargin() const
+{
+ return !maSegments.empty() ? maSegments.back().maSep.dyaTop : 0;
+}
+// <--
+
+sal_uInt16 SwWW8ImplReader::End_Ftn()
+{
+ /*
+ #84095#
+ Ignoring Footnote outside of the normal Text. People will put footnotes
+ into field results and field commands.
+ */
+ if (bIgnoreText ||
+ pPaM->GetPoint()->nNode < rDoc.GetNodes().GetEndOfExtras().GetIndex())
+ {
+ return 0;
+ }
+
+ ASSERT(!maFtnStack.empty(), "footnote end without start");
+ if (maFtnStack.empty())
+ return 0;
+
+ bool bFtEdOk = false;
+ const FtnDescriptor &rDesc = maFtnStack.back();
+
+ //Get the footnote character and remove it from the txtnode. We'll
+ //replace it with the footnote
+ SwTxtNode* pTxt = pPaM->GetNode()->GetTxtNode();
+ xub_StrLen nPos = pPaM->GetPoint()->nContent.GetIndex();
+
+ String sChar;
+ SwTxtAttr* pFN = 0;
+ //There should have been a footnote char, we will replace this.
+ if (pTxt && nPos)
+ {
+ sChar.Append(pTxt->GetTxt().GetChar(--nPos));
+ pPaM->SetMark();
+ pPaM->GetMark()->nContent--;
+ rDoc.DeleteRange( *pPaM );
+ pPaM->DeleteMark();
+ SwFmtFtn aFtn(rDesc.meType == MAN_EDN);
+ pFN = pTxt->InsertItem(aFtn, nPos, nPos);
+ }
+ ASSERT(pFN, "Probleme beim Anlegen des Fussnoten-Textes");
+ if (pFN)
+ {
+
+ SwPosition aTmpPos( *pPaM->GetPoint() ); // merke alte Cursorposition
+ WW8PLCFxSaveAll aSave;
+ pPlcxMan->SaveAllPLCFx( aSave );
+ WW8PLCFMan* pOldPlcxMan = pPlcxMan;
+
+ const SwNodeIndex* pSttIdx = ((SwTxtFtn*)pFN)->GetStartNode();
+ ASSERT(pSttIdx, "Probleme beim Anlegen des Fussnoten-Textes");
+
+ ((SwTxtFtn*)pFN)->SetSeqNo( rDoc.GetFtnIdxs().Count() );
+
+ bool bOld = bFtnEdn;
+ bFtnEdn = true;
+
+ // read content of Ft-/End-Note
+ Read_HdFtFtnText( pSttIdx, rDesc.mnStartCp, rDesc.mnLen, rDesc.meType);
+ bFtEdOk = true;
+ bFtnEdn = bOld;
+
+ ASSERT(sChar.Len()==1 && ((rDesc.mbAutoNum == (sChar.GetChar(0) == 2))),
+ "footnote autonumbering must be 0x02, and everthing else must not be");
+
+ // If no automatic numbering use the following char from the main text
+ // as the footnote number
+ if (!rDesc.mbAutoNum)
+ ((SwTxtFtn*)pFN)->SetNumber(0, &sChar);
+
+ /*
+ Delete the footnote char from the footnote if its at the beginning
+ as usual. Might not be if the user has already deleted it, e.g.
+ #i14737#
+ */
+ SwNodeIndex& rNIdx = pPaM->GetPoint()->nNode;
+ rNIdx = pSttIdx->GetIndex() + 1;
+ SwTxtNode* pTNd = rNIdx.GetNode().GetTxtNode();
+ if (pTNd && pTNd->GetTxt().Len() && sChar.Len())
+ {
+ if (pTNd->GetTxt().GetChar(0) == sChar.GetChar(0))
+ {
+ pPaM->GetPoint()->nContent.Assign( pTNd, 0 );
+ pPaM->SetMark();
+ // Strip out tabs we may have inserted on export #i24762#
+ if (pTNd->GetTxt().GetChar(1) == 0x09)
+ pPaM->GetMark()->nContent++;
+ pPaM->GetMark()->nContent++;
+ pReffingStck->Delete(*pPaM);
+ rDoc.DeleteRange( *pPaM );
+ pPaM->DeleteMark();
+ }
+ }
+
+ *pPaM->GetPoint() = aTmpPos; // restore Cursor
+
+ pPlcxMan = pOldPlcxMan; // Restore attributes
+ pPlcxMan->RestoreAllPLCFx( aSave );
+ }
+
+ if (bFtEdOk)
+ maSectionManager.SetCurrentSectionHasFootnote();
+
+ maFtnStack.pop_back();
+ return 0;
+}
+
+long SwWW8ImplReader::Read_Ftn(WW8PLCFManResult* pRes)
+{
+ /*
+ #84095#
+ Ignoring Footnote outside of the normal Text. People will put footnotes
+ into field results and field commands.
+ */
+ if (bIgnoreText ||
+ pPaM->GetPoint()->nNode < rDoc.GetNodes().GetEndOfExtras().GetIndex())
+ {
+ return 0;
+ }
+
+ FtnDescriptor aDesc;
+ aDesc.mbAutoNum = true;
+ if (eEDN == pRes->nSprmId)
+ {
+ aDesc.meType = MAN_EDN;
+ if (pPlcxMan->GetEdn())
+ aDesc.mbAutoNum = 0 != *(short*)pPlcxMan->GetEdn()->GetData();
+ }
+ else
+ {
+ aDesc.meType = MAN_FTN;
+ if (pPlcxMan->GetFtn())
+ aDesc.mbAutoNum = 0 != *(short*)pPlcxMan->GetFtn()->GetData();
+ }
+
+ aDesc.mnStartCp = pRes->nCp2OrIdx;
+ aDesc.mnLen = pRes->nMemLen;
+
+ maFtnStack.push_back(aDesc);
+
+ return 0;
+}
+
+bool SwWW8ImplReader::SearchRowEnd(WW8PLCFx_Cp_FKP* pPap, WW8_CP &rStartCp,
+ int nLevel) const
+{
+ WW8PLCFxDesc aRes;
+ aRes.pMemPos = 0;
+ aRes.nEndPos = rStartCp;
+
+ while (pPap->HasFkp() && rStartCp != WW8_CP_MAX)
+ {
+ if (pPap->Where() != WW8_CP_MAX)
+ {
+ const BYTE* pB = pPap->HasSprm(TabRowSprm(nLevel));
+ if (pB && *pB == 1)
+ {
+ const BYTE *pLevel = 0;
+ if (0 != (pLevel = pPap->HasSprm(0x6649)))
+ {
+ if (nLevel + 1 == *pLevel)
+ return true;
+ }
+ else
+ {
+ ASSERT(!nLevel || pLevel, "sublevel without level sprm");
+ return true; // RowEnd found
+ }
+ }
+ }
+
+ aRes.nStartPos = aRes.nEndPos;
+ aRes.pMemPos = 0;
+ //Seek to our next block of properties
+ if (!(pPap->SeekPos(aRes.nStartPos)))
+ {
+ aRes.nEndPos = WW8_CP_MAX;
+ pPap->SetDirty(true);
+ }
+ pPap->GetSprms(&aRes);
+ pPap->SetDirty(false);
+ //Update our aRes to get the new starting point of the next properties
+ rStartCp = aRes.nEndPos;
+ }
+
+ return false;
+}
+
+ApoTestResults SwWW8ImplReader::TestApo(int nCellLevel, bool bTableRowEnd,
+ const WW8_TablePos *pTabPos)
+{
+ const WW8_TablePos *pTopLevelTable = nCellLevel <= 1 ? pTabPos : 0;
+ ApoTestResults aRet;
+ // Frame in Style Definition (word appears to ignore them if inside an
+ // text autoshape, e.g. #94418#)
+ if (!bTxbxFlySection)
+ aRet.mpStyleApo = StyleExists(nAktColl) ? pCollA[nAktColl].pWWFly : 0;
+
+ /*
+ #i1140#
+ If I have a table and apply a style to one of its frames that should cause
+ a paragraph that its applied to it to only exist as a seperate floating
+ frame, then the behavour depends on which cell that it has been applied
+ to. If its the first cell of a row then the whole table row jumps into the
+ new frame, if its not then then the paragraph attributes are applied
+ "except" for the floating frame stuff. i.e. its ignored. So if theres a
+ table, and we're not in the first cell then we ignore the fact that the
+ paragraph style wants to be in a different frame.
+
+ This sort of mindbending inconsistency is surely why frames are deprecated
+ in word 97 onwards and hidden away from the user
+
+
+ #i1532# & #i5379#
+ If we are already a table in a frame then we must grab the para properties
+ to see if we are still in that frame.
+ */
+
+ aRet.mpSprm37 = pPlcxMan->HasParaSprm( bVer67 ? 37 : 0x2423 );
+ aRet.mpSprm29 = pPlcxMan->HasParaSprm( bVer67 ? 29 : 0x261B );
+
+ // Is there some frame data here
+ bool bNowApo = aRet.HasFrame() || pTopLevelTable;
+ if (bNowApo)
+ {
+ if (WW8FlyPara *pTest = ConstructApo(aRet, pTabPos))
+ delete pTest;
+ else
+ bNowApo = false;
+ }
+
+ bool bTestAllowed = !bTxbxFlySection && !bTableRowEnd;
+ if (bTestAllowed)
+ {
+ //Test is allowed if there is no table.
+ //Otherwise only allowed if we are in the
+ //first paragraph of the first cell of a row.
+ //(And only if the row we are inside is at the
+ //same level as the previous row, think tables
+ //in tables)
+ if (nCellLevel == nInTable)
+ {
+
+ if (!nInTable)
+ bTestAllowed = true;
+ else
+ {
+ if (!pTableDesc)
+ {
+ ASSERT(pTableDesc, "What!");
+ bTestAllowed = false;
+ }
+ else
+ {
+ // --> OD 2005-02-01 #i39468#
+ // If current cell isn't valid, the test is allowed.
+ // The cell isn't valid, if e.g. there is a new row
+ // <pTableDesc->nAktRow> >= <pTableDesc->pTabLines->Count()>
+ bTestAllowed =
+ pTableDesc->GetAktCol() == 0 &&
+ ( !pTableDesc->IsValidCell( pTableDesc->GetAktCol() ) ||
+ pTableDesc->InFirstParaInCell() );
+ // <--
+ }
+ }
+ }
+ }
+
+ if (!bTestAllowed)
+ return aRet;
+
+ aRet.mbStartApo = bNowApo && !InAnyApo(); // APO-start
+ aRet.mbStopApo = InEqualOrHigherApo(nCellLevel) && !bNowApo; // APO-end
+
+ //If it happens that we are in a table, then if its not the first cell
+ //then any attributes that might otherwise cause the contents to jump
+ //into another frame don't matter, a table row sticks together as one
+ //unit no matter what else happens. So if we are not in a table at
+ //all, or if we are in the first cell then test that the last frame
+ //data is the same as the current one
+ if (bNowApo && InEqualApo(nCellLevel))
+ {
+ // two bordering eachother
+ if (!TestSameApo(aRet, pTabPos))
+ aRet.mbStopApo = aRet.mbStartApo = true;
+ }
+
+ return aRet;
+}
+//---------------------------------------------------------------------
+// Hilfroutinen fuer Kapitelnummerierung und Aufzaehlung / Gliederung
+//---------------------------------------------------------------------
+
+static void SetBaseAnlv(SwNumFmt &rNum, WW8_ANLV &rAV, BYTE nSwLevel )
+{
+ static SvxExtNumType eNumA[8] = { SVX_NUM_ARABIC, SVX_NUM_ROMAN_UPPER, SVX_NUM_ROMAN_LOWER,
+ SVX_NUM_CHARS_UPPER_LETTER_N, SVX_NUM_CHARS_LOWER_LETTER_N, SVX_NUM_ARABIC,
+ SVX_NUM_ARABIC, SVX_NUM_ARABIC };
+
+ static SvxAdjust eAdjA[4] = { SVX_ADJUST_LEFT,
+ SVX_ADJUST_RIGHT, SVX_ADJUST_LEFT, SVX_ADJUST_LEFT };
+// eigentlich folgende 2, aber Writer-UI bietet es nicht an
+// SVX_ADJUST_CENTER, SVX_ADJUST_BLOCKLINE };
+
+ rNum.SetNumberingType( static_cast< sal_Int16 >(( SVBT8ToByte( rAV.nfc ) < 8 ) ?
+ eNumA[SVBT8ToByte( rAV.nfc ) ] : SVX_NUM_NUMBER_NONE) );
+ if ((SVBT8ToByte(rAV.aBits1 ) & 0x4) >> 2)
+ rNum.SetIncludeUpperLevels(nSwLevel + 1);
+ rNum.SetStart( SVBT16ToShort( rAV.iStartAt ) );
+// rNum.eNumAdjust = eAdjA[rAV.jc];
+ rNum.SetNumAdjust( eAdjA[SVBT8ToByte( rAV.aBits1 ) & 0x3] );
+
+ rNum.SetCharTextDistance( SVBT16ToShort( rAV.dxaSpace ) );
+ INT16 nIndent = Abs((INT16)SVBT16ToShort( rAV.dxaIndent ));
+ if( SVBT8ToByte( rAV.aBits1 ) & 0x08 ) //fHang
+ {
+ rNum.SetFirstLineOffset( -nIndent );
+ rNum.SetLSpace( nIndent );
+ rNum.SetAbsLSpace( nIndent );
+ }
+ else
+ rNum.SetCharTextDistance( nIndent ); // Breite der Nummer fehlt
+
+ if( SVBT8ToByte( rAV.nfc ) == 5 || SVBT8ToByte( rAV.nfc ) == 7 )
+ {
+ String sP( rNum.GetSuffix() );
+ sP.Insert( '.', 0 );
+ rNum.SetSuffix( sP ); // Ordinalzahlen
+ }
+}
+
+void SwWW8ImplReader::SetAnlvStrings(SwNumFmt &rNum, WW8_ANLV &rAV,
+ const BYTE* pTxt, bool bOutline)
+{
+ bool bInsert = false; // Default
+ CharSet eCharSet = eStructCharSet;
+
+ const WW8_FFN* pF = pFonts->GetFont(SVBT16ToShort(rAV.ftc)); // FontInfo
+ bool bListSymbol = pF && ( pF->chs == 2 ); // Symbol/WingDings/...
+
+ String sTxt;
+ if (bVer67)
+ {
+ sTxt = String( (sal_Char*)pTxt, SVBT8ToByte( rAV.cbTextBefore )
+ + SVBT8ToByte( rAV.cbTextAfter ), eCharSet );
+ }
+ else
+ {
+ for(xub_StrLen i = SVBT8ToByte(rAV.cbTextBefore);
+ i < SVBT8ToByte(rAV.cbTextAfter); ++i, pTxt += 2)
+ {
+ sTxt.Append(SVBT16ToShort(*(SVBT16*)pTxt));
+ }
+ }
+
+ if( bOutline )
+ { // Gliederung
+ if( !rNum.GetIncludeUpperLevels() // es sind <= 1 Nummern anzuzeigen
+ || rNum.GetNumberingType() == SVX_NUM_NUMBER_NONE ){ // oder dieser Level hat keine
+ // eigenen Ziffern
+ bInsert = true; // -> dann uebernehme Zeichen
+
+ // replace by simple Bullet ?
+ if( bListSymbol )
+ //JP 14.08.96: cBulletChar benutzen, damit auf dem MAC
+ // richtig gemappt wird
+ sTxt.Fill( SVBT8ToByte( rAV.cbTextBefore )
+ + SVBT8ToByte( rAV.cbTextAfter ), cBulletChar );
+ }
+ }
+ else
+ { // Nummerierung / Aufzaehlung
+ bInsert = true;
+// if( SVBT16ToShort( rAV.ftc ) == 1
+// || SVBT16ToShort( rAV.ftc ) == 3 ){ // Symbol / WingDings
+ if( bListSymbol )
+ {
+ FontFamily eFamily;
+ String aName;
+ FontPitch ePitch;
+
+ if( GetFontParams( SVBT16ToShort( rAV.ftc ), eFamily, aName,
+ ePitch, eCharSet ) ){
+// USHORT nSiz = ( SVBT16ToShort( rAV.hps ) ) ?
+// SVBT16ToShort( rAV.hps ) : 24; // Groesse in 1/2 Pt
+// darf nach JP nicht gesetzt werden, da immer die Size
+// genommen wird, die am ZeilenAnfang benutzt wird
+ Font aFont;
+ aFont.SetName( aName );
+ aFont.SetFamily( eFamily );
+// aFont.SetPitch( ePitch ); // darf nach JP nicht
+ aFont.SetCharSet( eCharSet );
+ rNum.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+// if( rAV.ico ) // geht in UI und SWG-Writer/Reader nicht
+// aFont.SetColor( Color( GetCol( rAV.ico ) ) );
+ rNum.SetBulletFont( &aFont );
+
+ // take only the very first character
+ if( rAV.cbTextBefore || rAV.cbTextAfter)
+ rNum.SetBulletChar( sTxt.GetChar( 0 ) );
+ else
+ rNum.SetBulletChar( 0x2190 );
+ }
+ }
+ }
+ if( bInsert )
+ {
+ if( rAV.cbTextBefore )
+ {
+ String sP( sTxt.Copy( 0, SVBT8ToByte( rAV.cbTextBefore ) ) );
+ rNum.SetPrefix( sP );
+ }
+ if( SVBT8ToByte( rAV.cbTextAfter ) )
+ {
+ String sP( rNum.GetSuffix() );
+ sP.Insert( sTxt.Copy( SVBT8ToByte( rAV.cbTextBefore ),
+ SVBT8ToByte( rAV.cbTextAfter ) ) );
+ rNum.SetSuffix( sP );
+ }
+// Die Zeichen vor und hinter mehreren Ziffern koennen leider nicht uebernommen
+// werden, da sie der Writer ganz anders behandelt und das Ergebnis i.A.
+// schlechter als ohne waere.
+ }
+}
+
+// SetAnld bekommt einen WW-ANLD-Descriptor und einen Level und modifiziert
+// die durch pNumR anggebeben NumRules. Wird benutzt fuer alles ausser
+// Gliederung im Text
+void SwWW8ImplReader::SetAnld(SwNumRule* pNumR, WW8_ANLD* pAD, BYTE nSwLevel,
+ bool bOutLine)
+{
+ SwNumFmt aNF;
+ if (pAD)
+ { // Es gibt einen Anld-Sprm
+ bAktAND_fNumberAcross = 0 != SVBT8ToByte( pAD->fNumberAcross );
+ WW8_ANLV &rAV = pAD->eAnlv;
+ SetBaseAnlv(aNF, rAV, nSwLevel); // Setze Basis-Format
+ SetAnlvStrings(aNF, rAV, pAD->rgchAnld, bOutLine );// und Rest
+ }
+ pNumR->Set(nSwLevel, aNF);
+}
+
+//-------------------------------------------------------
+// Kapitelnummerierung und Kapitelbullets
+//-------------------------------------------------------
+// Kapitelnummerierung findet in Styledefinionen statt. Sprm 13 gibt den Level
+// an, Sprm 12 den Inhalt
+
+SwNumRule* SwWW8ImplReader::GetStyRule()
+{
+ if( pStyles->pStyRule ) // Bullet-Style bereits vorhanden
+ return pStyles->pStyRule;
+
+ const String aBaseName(CREATE_CONST_ASC( "WW8StyleNum" ));
+ const String aName( rDoc.GetUniqueNumRuleName( &aBaseName, false) );
+
+ // --> OD 2008-06-04 #i86652#
+// USHORT nRul = rDoc.MakeNumRule( aName );
+ USHORT nRul = rDoc.MakeNumRule( aName, 0, FALSE,
+ SvxNumberFormat::LABEL_ALIGNMENT );
+ // <--
+ pStyles->pStyRule = rDoc.GetNumRuleTbl()[nRul];
+ // Auto == false-> Nummerierungsvorlage
+ pStyles->pStyRule->SetAutoRule(false);
+
+ return pStyles->pStyRule;
+}
+
+// Sprm 13
+void SwWW8ImplReader::Read_ANLevelNo( USHORT, const BYTE* pData, short nLen )
+{
+ nSwNumLevel = 0xff; // Default: ungueltig
+
+ if( nLen <= 0 )
+ return;
+
+ // StyleDef ?
+ if( pAktColl )
+ {
+ // nur fuer SwTxtFmtColl, nicht CharFmt
+ // WW: 0 = no Numbering
+ if (pCollA[nAktColl].bColl && *pData)
+ {
+ // Bereich WW:1..9 -> SW:0..8 keine Aufzaehlung / Nummerierung
+
+ if (*pData <= MAXLEVEL && *pData <= 9)
+ {
+ nSwNumLevel = *pData - 1;
+ if (!bNoAttrImport)
+ //((SwTxtFmtColl*)pAktColl)->SetOutlineLevel( nSwNumLevel ); //#outline level,zhaojianwei
+ ((SwTxtFmtColl*)pAktColl)->AssignToListLevelOfOutlineStyle( nSwNumLevel ); //<-end,zhaojianwei
+ // Bei WW-NoNumbering koennte auch NO_NUMBERING gesetzt
+ // werden. ( Bei normaler Nummerierung muss NO_NUM gesetzt
+ // werden: NO_NUM : Nummerierungs-Pause,
+ // NO_NUMBERING : ueberhaupt keine Nummerierung )
+
+ }
+ else if( *pData == 10 || *pData == 11 )
+ {
+ // Typ merken, der Rest geschieht bei Sprm 12
+ pStyles->nWwNumLevel = *pData;
+ }
+ }
+ }
+ else
+ {
+ //Not StyleDef
+ if (!bAnl)
+ StartAnl(pData); // Anfang der Gliederung / Aufzaehlung
+ NextAnlLine(pData);
+ }
+}
+
+void SwWW8ImplReader::Read_ANLevelDesc( USHORT, const BYTE* pData, short nLen ) // Sprm 12
+{
+ if( !pAktColl || nLen <= 0 // nur bei Styledef
+ || !pCollA[nAktColl].bColl // CharFmt -> ignorieren
+ || ( nIniFlags & WW8FL_NO_OUTLINE ) ){
+ nSwNumLevel = 0xff;
+ return;
+ }
+ if( nSwNumLevel <= MAXLEVEL // Bereich WW:1..9 -> SW:0..8
+ && nSwNumLevel <= 9 ){ // keine Aufzaehlung / Nummerierung
+
+ // Falls bereits direkt oder durch
+ // Vererbung NumruleItems gesetzt sind,
+ // dann jetzt ausschalten #56163
+ pAktColl->SetFmtAttr( SwNumRuleItem() );
+
+ String aName(CREATE_CONST_ASC( "Outline" ));
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ SwNumRule aNR( rDoc.GetUniqueNumRuleName( &aName ),
+ SvxNumberFormat::LABEL_WIDTH_AND_POSITION,
+ OUTLINE_RULE );
+ // <--
+ aNR = *rDoc.GetOutlineNumRule();
+
+ SetAnld(&aNR, (WW8_ANLD*)pData, nSwNumLevel, true);
+
+ // fehlende Level muessen nicht aufgefuellt werden
+
+ rDoc.SetOutlineNumRule( aNR );
+ }else if( pStyles->nWwNumLevel == 10 || pStyles->nWwNumLevel == 11 ){
+ SwNumRule* pNR = GetStyRule();
+ SetAnld(pNR, (WW8_ANLD*)pData, 0, false);
+ pAktColl->SetFmtAttr( SwNumRuleItem( pNR->GetName() ) );
+ pCollA[nAktColl].bHasStyNumRule = true;
+ }
+}
+
+//-----------------------------------------
+// Nummerierung / Aufzaehlung
+//-----------------------------------------
+
+// SetNumOlst() traegt die Numrules fuer diese Zeile ins SwNumFmt ein
+// ( nur fuer Gliederungen im Text; Aufzaehlungen / Nummerierungen laufen
+// ueber ANLDs )
+// dabei wird die Info aus dem OLST geholt und nicht aus dem ANLD ( s.u. )
+void SwWW8ImplReader::SetNumOlst(SwNumRule* pNumR, WW8_OLST* pO, BYTE nSwLevel)
+{
+ SwNumFmt aNF;
+ WW8_ANLV &rAV = pO->rganlv[nSwLevel];
+ SetBaseAnlv(aNF, rAV, nSwLevel);
+ // ... und then the Strings
+ int nTxtOfs = 0;
+ BYTE i;
+ WW8_ANLV* pAV1; // search String-Positions
+ for (i = 0, pAV1 = pO->rganlv; i < nSwLevel; ++i, ++pAV1)
+ {
+ nTxtOfs += SVBT8ToByte(pAV1->cbTextBefore)
+ + SVBT8ToByte(pAV1->cbTextAfter);
+ }
+
+ if (!bVer67)
+ nTxtOfs *= 2;
+ SetAnlvStrings(aNF, rAV, pO->rgch + nTxtOfs, true); // und rein
+ pNumR->Set(nSwLevel, aNF);
+}
+
+// der OLST kommt am Anfang jeder Section, die Gliederungen enthaelt. Die ANLDs,
+// die an jeder Gliederungszeile haengen, enthalten nur Stuss, also werden die
+// OLSTs waehrend der Section gemerkt, damit die Informationen beim Auftreten
+// von Gliederungsabsaetzen zugreifbar ist.
+void SwWW8ImplReader::Read_OLST( USHORT, const BYTE* pData, short nLen )
+{
+ if (nLen <= 0)
+ {
+ delete pNumOlst, pNumOlst = 0;
+ return;
+ }
+ if (pNumOlst)
+ delete pNumOlst; // nur sicherheitshalber
+ pNumOlst = new WW8_OLST;
+ if( nLen < sal::static_int_cast< sal_Int32 >(sizeof( WW8_OLST )) ) // auffuellen, falls zu kurz
+ memset( pNumOlst, 0, sizeof( *pNumOlst ) );
+ *pNumOlst = *(WW8_OLST*)pData;
+}
+
+WW8LvlType GetNumType(BYTE nWwLevelNo)
+{
+ WW8LvlType nRet = WW8_None;
+ if( nWwLevelNo == 12 )
+ nRet = WW8_Pause;
+ else if( nWwLevelNo == 10 )
+ nRet = WW8_Numbering;
+ else if( nWwLevelNo == 11 )
+ nRet = WW8_Sequence;
+ else if( nWwLevelNo > 0 && nWwLevelNo <= 9 )
+ nRet = WW8_Outline;
+ return nRet;
+}
+
+SwNumRule *ANLDRuleMap::GetNumRule(BYTE nNumType)
+{
+ return (WW8_Numbering == nNumType ? mpNumberingNumRule : mpOutlineNumRule);
+}
+
+void ANLDRuleMap::SetNumRule(SwNumRule *pRule, BYTE nNumType)
+{
+ if (WW8_Numbering == nNumType)
+ mpNumberingNumRule = pRule;
+ else
+ mpOutlineNumRule = pRule;
+}
+
+
+// StartAnl wird am Anfang eines Zeilenbereichs gerufen,
+// der Gliederung / Nummerierung / Aufzaehlung enthaelt
+void SwWW8ImplReader::StartAnl(const BYTE* pSprm13)
+{
+ bAktAND_fNumberAcross = false;
+
+ BYTE nT = static_cast< BYTE >(GetNumType(*pSprm13));
+ if (nT == WW8_Pause || nT == WW8_None)
+ return;
+
+ nWwNumType = nT;
+ SwNumRule *pNumRule = maANLDRules.GetNumRule(nWwNumType);
+
+ // check for COL numbering:
+ const BYTE* pS12 = 0;// sprmAnld
+ String sNumRule;
+
+ if (pTableDesc)
+ {
+ sNumRule = pTableDesc->GetNumRuleName();
+ if (sNumRule.Len())
+ {
+ pNumRule = rDoc.FindNumRulePtr(sNumRule);
+ if (!pNumRule)
+ sNumRule.Erase();
+ else
+ {
+ // this is ROW numbering ?
+ pS12 = pPlcxMan->HasParaSprm(bVer67 ? 12 : 0xC63E); // sprmAnld
+ if (pS12 && 0 != SVBT8ToByte(((WW8_ANLD*)pS12)->fNumberAcross))
+ sNumRule.Erase();
+ }
+ }
+ }
+
+ if (!sNumRule.Len() && pCollA[nAktColl].bHasStyNumRule)
+ {
+ sNumRule = pCollA[nAktColl].pFmt->GetNumRule().GetValue();
+ pNumRule = rDoc.FindNumRulePtr(sNumRule);
+ if (!pNumRule)
+ sNumRule.Erase();
+ }
+
+ if (!sNumRule.Len())
+ {
+ if (!pNumRule)
+ {
+ // --> OD 2008-06-04 #i86652#
+// pNumRule = rDoc.GetNumRuleTbl()[rDoc.MakeNumRule(sNumRule)];
+ pNumRule = rDoc.GetNumRuleTbl()[
+ rDoc.MakeNumRule( sNumRule, 0, FALSE,
+ SvxNumberFormat::LABEL_ALIGNMENT ) ];
+ // <--
+ }
+ if (pTableDesc)
+ {
+ if (!pS12)
+ pS12 = pPlcxMan->HasParaSprm(bVer67 ? 12 : 0xC63E); // sprmAnld
+ if (!pS12 || !SVBT8ToByte( ((WW8_ANLD*)pS12)->fNumberAcross))
+ pTableDesc->SetNumRuleName(pNumRule->GetName());
+ }
+ }
+
+ bAnl = true;
+
+ // NumRules ueber Stack setzen
+ pCtrlStck->NewAttr(*pPaM->GetPoint(),
+ SfxStringItem(RES_FLTR_NUMRULE, pNumRule->GetName()));
+
+ maANLDRules.SetNumRule(pNumRule, nWwNumType);
+}
+
+// NextAnlLine() wird fuer jede Zeile einer
+// Gliederung / Nummerierung / Aufzaehlung einmal gerufen
+void SwWW8ImplReader::NextAnlLine(const BYTE* pSprm13)
+{
+ if (!bAnl)
+ return;
+
+ SwNumRule *pNumRule = maANLDRules.GetNumRule(nWwNumType);
+
+ // pNd->UpdateNum ohne Regelwerk gibt GPF spaetestens beim Speichern als
+ // sdw3
+
+ // WW:10 = Nummerierung -> SW:0 & WW:11 = Auffzaehlung -> SW:0
+ if (*pSprm13 == 10 || *pSprm13 == 11)
+ {
+ nSwNumLevel = 0;
+ if (!pNumRule->GetNumFmt(nSwNumLevel))
+ {
+ // noch nicht definiert
+ // sprmAnld o. 0
+ const BYTE* pS12 = pPlcxMan->HasParaSprm(bVer67 ? 12 : 0xC63E);
+ SetAnld(pNumRule, (WW8_ANLD*)pS12, nSwNumLevel, false);
+ }
+ }
+ else if( *pSprm13 > 0 && *pSprm13 <= MAXLEVEL ) // Bereich WW:1..9 -> SW:0..8
+ {
+ nSwNumLevel = *pSprm13 - 1; // Gliederung
+ // noch nicht definiert
+ if (!pNumRule->GetNumFmt(nSwNumLevel))
+ {
+ if (pNumOlst) // es gab ein OLST
+ {
+ //Assure upper levels are set, #i9556#
+ for (BYTE nI = 0; nI < nSwNumLevel; ++nI)
+ {
+ if (!pNumRule->GetNumFmt(nI))
+ SetNumOlst(pNumRule, pNumOlst, nI);
+ }
+
+ SetNumOlst(pNumRule, pNumOlst , nSwNumLevel);
+ }
+ else // kein Olst, nimm Anld
+ {
+ // sprmAnld
+ const BYTE* pS12 = pPlcxMan->HasParaSprm(bVer67 ? 12 : 0xC63E);
+ SetAnld(pNumRule, (WW8_ANLD*)pS12, nSwNumLevel, false);
+ }
+ }
+ }
+ else
+ nSwNumLevel = 0xff; // keine Nummer
+
+ SwTxtNode* pNd = pPaM->GetNode()->GetTxtNode();
+ if (nSwNumLevel < MAXLEVEL)
+ pNd->SetAttrListLevel( nSwNumLevel );
+ else
+ {
+ pNd->SetAttrListLevel(0);
+ pNd->SetCountedInList( false );
+ }
+}
+
+void SwWW8ImplReader::StopAllAnl(bool bGoBack)
+{
+ //Of course we're not restarting, but we'll make use of our knowledge
+ //of the implementation to do it.
+ StopAnlToRestart(WW8_None, bGoBack);
+}
+
+void SwWW8ImplReader::StopAnlToRestart(BYTE nNewType, bool bGoBack)
+{
+ if (bGoBack)
+ {
+ SwPosition aTmpPos(*pPaM->GetPoint());
+ pPaM->Move(fnMoveBackward, fnGoCntnt);
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_FLTR_NUMRULE);
+ *pPaM->GetPoint() = aTmpPos;
+ }
+ else
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_FLTR_NUMRULE);
+
+ maANLDRules.mpNumberingNumRule = 0;
+ /*
+ #i18816#
+ my take on this problem is that moving either way from an outline to a
+ numbering doesn't halt the outline, while the numbering is always halted
+ */
+ bool bNumberingNotStopOutline =
+ (((nWwNumType == WW8_Outline) && (nNewType == WW8_Numbering)) ||
+ ((nWwNumType == WW8_Numbering) && (nNewType == WW8_Outline)));
+ if (!bNumberingNotStopOutline)
+ maANLDRules.mpOutlineNumRule = 0;
+
+ nSwNumLevel = 0xff;
+ nWwNumType = WW8_None;
+ bAnl = false;
+}
+
+WW8TabBandDesc::WW8TabBandDesc( WW8TabBandDesc& rBand )
+{
+ *this = rBand;
+ if( rBand.pTCs )
+ {
+ pTCs = new WW8_TCell[nWwCols];
+ memcpy( pTCs, rBand.pTCs, nWwCols * sizeof( WW8_TCell ) );
+ }
+ if( rBand.pSHDs )
+ {
+ pSHDs = new WW8_SHD[nWwCols];
+ memcpy( pSHDs, rBand.pSHDs, nWwCols * sizeof( WW8_SHD ) );
+ }
+ if( rBand.pNewSHDs )
+ {
+ pNewSHDs = new sal_uInt32[nWwCols];
+ memcpy(pNewSHDs, rBand.pNewSHDs, nWwCols * sizeof(sal_uInt32));
+ }
+ memcpy(aDefBrcs, rBand.aDefBrcs, sizeof(aDefBrcs));
+}
+
+// ReadDef liest die Zellenpositionen und ggfs die Umrandungen eines Bandes ein
+void WW8TabBandDesc::ReadDef(bool bVer67, const BYTE* pS)
+{
+ if (!bVer67)
+ pS++;
+
+ short nLen = (INT16)SVBT16ToShort( pS - 2 ); // nicht schoen
+ BYTE nCols = *pS; // Anzahl der Zellen
+ short nOldCols = nWwCols;
+
+ if( nCols > MAX_COL )
+ return;
+
+ nWwCols = nCols;
+
+ const BYTE* pT = &pS[1];
+ nLen --;
+ int i;
+ for(i=0; i<=nCols; i++, pT+=2 )
+ nCenter[i] = (INT16)SVBT16ToShort( pT ); // X-Raender
+ nLen -= 2 * ( nCols + 1 );
+ if( nCols != nOldCols ) // andere Spaltenzahl
+ {
+ delete[] pTCs, pTCs = 0;
+ delete[] pSHDs, pSHDs = 0;
+ delete[] pNewSHDs, pNewSHDs = 0;
+ }
+
+ short nFileCols = nLen / ( bVer67 ? 10 : 20 ); // wirklich abgespeichert
+
+ if (!pTCs && nCols)
+ {
+ // lege leere TCs an
+ pTCs = new WW8_TCell[nCols];
+ setcelldefaults(pTCs,nCols);
+ }
+
+ if( nFileCols )
+ {
+ // lies TCs ein
+
+ /*
+ Achtung: ab Ver8 ist ein reserve-ushort je TC eingefuegt und auch
+ der Border-Code ist doppelt so gross, daher ist hier
+ kein simples kopieren moeglich,
+ d.h.: pTCs[i] = *pTc; geht leider nicht.
+ ---
+ Vorteil: Arbeitstruktur ist jetzt viel bequemer zu handhaben!
+ */
+ WW8_TCell* pAktTC = pTCs;
+ if( bVer67 )
+ {
+ WW8_TCellVer6* pTc = (WW8_TCellVer6*)pT;
+ for(i=0; i<nFileCols; i++, ++pAktTC,++pTc)
+ {
+ if( i < nFileCols )
+ { // TC aus File ?
+ BYTE aBits1 = SVBT8ToByte( pTc->aBits1Ver6 );
+ pAktTC->bFirstMerged = ( ( aBits1 & 0x01 ) != 0 );
+ pAktTC->bMerged = ( ( aBits1 & 0x02 ) != 0 );
+ memcpy( pAktTC->rgbrc[ WW8_TOP ].aBits1,
+ pTc->rgbrcVer6[ WW8_TOP ].aBits1, sizeof( SVBT16 ) );
+ memcpy( pAktTC->rgbrc[ WW8_LEFT ].aBits1,
+ pTc->rgbrcVer6[ WW8_LEFT ].aBits1, sizeof( SVBT16 ) );
+ memcpy( pAktTC->rgbrc[ WW8_BOT ].aBits1,
+ pTc->rgbrcVer6[ WW8_BOT ].aBits1, sizeof( SVBT16 ) );
+ memcpy( pAktTC->rgbrc[ WW8_RIGHT ].aBits1,
+ pTc->rgbrcVer6[ WW8_RIGHT ].aBits1, sizeof( SVBT16 ) );
+ if( ( pAktTC->bMerged )
+ && ( i > 0 ) )
+ {
+ // Cell gemerged -> merken
+ //bWWMergedVer6[i] = true;
+ memcpy( pTCs[i-1].rgbrc[ WW8_RIGHT ].aBits1,
+ pTc->rgbrcVer6[ WW8_RIGHT ].aBits1, sizeof( SVBT16 ) );
+ // right Border in vorige Zelle uebernehmen
+ // Hier darf bExist nicht auf false gesetzt werden, da WW
+ // in den Textboxen diese Zellen nicht mitzaehlt....
+ }
+ }
+ }
+ }
+ else
+ {
+ WW8_TCellVer8* pTc = (WW8_TCellVer8*)pT;
+ for (int k = 0; k < nFileCols; ++k, ++pAktTC, ++pTc )
+ {
+ UINT16 aBits1 = SVBT16ToShort( pTc->aBits1Ver8 );
+ pAktTC->bFirstMerged = ( ( aBits1 & 0x0001 ) != 0 );
+ pAktTC->bMerged = ( ( aBits1 & 0x0002 ) != 0 );
+ pAktTC->bVertical = ( ( aBits1 & 0x0004 ) != 0 );
+ pAktTC->bBackward = ( ( aBits1 & 0x0008 ) != 0 );
+ pAktTC->bRotateFont = ( ( aBits1 & 0x0010 ) != 0 );
+ pAktTC->bVertMerge = ( ( aBits1 & 0x0020 ) != 0 );
+ pAktTC->bVertRestart = ( ( aBits1 & 0x0040 ) != 0 );
+ pAktTC->nVertAlign = ( ( aBits1 & 0x0180 ) >> 7 );
+ // am Rande: im aBits1 verstecken sich noch 7 Reserve-Bits,
+ // anschliessend folgen noch 16 weitere Reserve-Bits
+
+ // In Version 8 koennen wir alle Bordercodes auf einmal kopieren!
+ memcpy( pAktTC->rgbrc, pTc->rgbrcVer8, 4 * sizeof( WW8_BRC ) );
+ }
+ }
+
+ // #i25071 In '97 text direction appears to be only set using TC properties
+ // not with sprmTTextFlow so we need to cycle through the maDirections and
+ // double check any non-default directions
+ for (int k = 0; k < nCols; ++k)
+ {
+ if(maDirections[k] == 4)
+ {
+ if(pTCs[k].bVertical)
+ {
+ if(pTCs[k].bBackward)
+ maDirections[k] = 3;
+ else
+ maDirections[k] = 1;
+ }
+ }
+ }
+
+
+ }
+}
+
+void WW8TabBandDesc::ProcessSprmTSetBRC(bool bVer67, const BYTE* pParamsTSetBRC)
+{
+ if( pParamsTSetBRC && pTCs ) // set one or more cell border(s)
+ {
+ BYTE nitcFirst= pParamsTSetBRC[0];// first col to be changed
+ BYTE nitcLim = pParamsTSetBRC[1];// (last col to be changed)+1
+ BYTE nFlag = *(pParamsTSetBRC+2);
+
+ bool bChangeRight = (nFlag & 0x08) ? true : false;
+ bool bChangeBottom = (nFlag & 0x04) ? true : false;
+ bool bChangeLeft = (nFlag & 0x02) ? true : false;
+ bool bChangeTop = (nFlag & 0x01) ? true : false;
+
+ WW8_TCell* pAktTC = pTCs + nitcFirst;
+ if( bVer67 )
+ {
+ WW8_BRCVer6* pBRC = (WW8_BRCVer6*)(pParamsTSetBRC+3);
+
+ for( int i = nitcFirst; i < nitcLim; i++, ++pAktTC )
+ {
+ if( bChangeTop )
+ memcpy( pAktTC->rgbrc[ WW8_TOP ].aBits1,
+ pBRC->aBits1,
+ sizeof( SVBT16 ) );
+ if( bChangeLeft )
+ memcpy( pAktTC->rgbrc[ WW8_LEFT ].aBits1,
+ pBRC->aBits1,
+ sizeof( SVBT16 ) );
+ if( bChangeBottom )
+ memcpy( pAktTC->rgbrc[ WW8_BOT ].aBits1,
+ pBRC->aBits1,
+ sizeof( SVBT16 ) );
+ if( bChangeRight )
+ memcpy( pAktTC->rgbrc[ WW8_RIGHT].aBits1,
+ pBRC->aBits1,
+ sizeof( SVBT16 ) );
+ }
+ }
+ else
+ {
+ WW8_BRC* pBRC = (WW8_BRC*)(pParamsTSetBRC+3);
+
+ for( int i = nitcFirst; i < nitcLim; i++, ++pAktTC )
+ {
+ if( bChangeTop )
+ memcpy( pAktTC->rgbrc[ WW8_TOP ].aBits1,
+ pBRC->aBits1,
+ sizeof( WW8_BRC ) );
+ if( bChangeLeft )
+ memcpy( pAktTC->rgbrc[ WW8_LEFT ].aBits1,
+ pBRC->aBits1,
+ sizeof( WW8_BRC ) );
+ if( bChangeBottom )
+ memcpy( pAktTC->rgbrc[ WW8_BOT ].aBits1,
+ pBRC->aBits1,
+ sizeof( WW8_BRC ) );
+ if( bChangeRight )
+ memcpy( pAktTC->rgbrc[ WW8_RIGHT].aBits1,
+ pBRC->aBits1,
+ sizeof( WW8_BRC ) );
+ }
+
+
+
+ }
+ }
+}
+
+void WW8TabBandDesc::ProcessSprmTTableBorders(bool bVer67, const BYTE* pParams)
+{
+ // sprmTTableBorders
+ if( bVer67 )
+ {
+ for( int i = 0; i < 6; ++i )
+ {
+ aDefBrcs[i].aBits1[0] = pParams[ 2*i ];
+ aDefBrcs[i].aBits1[1] = pParams[ 1+2*i ];
+ }
+ }
+ else // aDefBrcs = *(BRC(*)[6])pS;
+ memcpy( aDefBrcs, pParams, 24 );
+}
+
+void WW8TabBandDesc::ProcessSprmTDxaCol(const BYTE* pParamsTDxaCol)
+{
+ // sprmTDxaCol (opcode 0x7623) changes the width of cells
+ // whose index is within a certain range to be a certain value.
+
+ if( nWwCols && pParamsTDxaCol ) // set one or more cell length(s)
+ {
+ BYTE nitcFirst= pParamsTDxaCol[0]; // first col to be changed
+ BYTE nitcLim = pParamsTDxaCol[1]; // (last col to be changed)+1
+ short nDxaCol = (INT16)SVBT16ToShort( pParamsTDxaCol + 2 );
+ short nOrgWidth;
+ short nDelta;
+
+ for( int i = nitcFirst; (i < nitcLim) && (i < nWwCols); i++ )
+ {
+ nOrgWidth = nCenter[i+1] - nCenter[i];
+ nDelta = nDxaCol - nOrgWidth;
+ for( int j = i+1; j <= nWwCols; j++ )
+ {
+ nCenter[j] = nCenter[j] + nDelta;
+ }
+ }
+ }
+}
+
+void WW8TabBandDesc::ProcessSprmTInsert(const BYTE* pParamsTInsert)
+{
+ if( nWwCols && pParamsTInsert ) // set one or more cell length(s)
+ {
+ BYTE nitcInsert = pParamsTInsert[0]; // position at which to insert
+ if (nitcInsert >= MAX_COL) // cannot insert into cell outside max possible index
+ return;
+ BYTE nctc = pParamsTInsert[1]; // number of cells
+ USHORT ndxaCol = SVBT16ToShort( pParamsTInsert+2 );
+
+ short nNewWwCols;
+ if (nitcInsert > nWwCols)
+ {
+ nNewWwCols = nitcInsert+nctc;
+ //if new count would be outside max possible count, clip it, and calc a new replacement
+ //legal nctc
+ if (nNewWwCols > MAX_COL)
+ {
+ nNewWwCols = MAX_COL;
+ nctc = ::sal::static_int_cast<BYTE>(nNewWwCols-nitcInsert);
+ }
+ }
+ else
+ {
+ nNewWwCols = nWwCols+nctc;
+ //if new count would be outside max possible count, clip it, and calc a new replacement
+ //legal nctc
+ if (nNewWwCols > MAX_COL)
+ {
+ nNewWwCols = MAX_COL;
+ nctc = ::sal::static_int_cast<BYTE>(nNewWwCols-nWwCols);
+ }
+ }
+
+ WW8_TCell *pTC2s = new WW8_TCell[nNewWwCols];
+ setcelldefaults(pTC2s, nNewWwCols);
+
+ if (pTCs)
+ {
+ memcpy( pTC2s, pTCs, nWwCols * sizeof( WW8_TCell ) );
+ delete[] pTCs;
+ }
+ pTCs = pTC2s;
+
+ //If we have to move some cells
+ if (nitcInsert <= nWwCols)
+ {
+ // adjust the left x-position of the dummy at the very end
+ nCenter[nWwCols + nctc] = nCenter[nWwCols]+nctc*ndxaCol;
+ for( int i = nWwCols-1; i >= nitcInsert; i--)
+ {
+ // adjust the left x-position
+ nCenter[i + nctc] = nCenter[i]+nctc*ndxaCol;
+
+ // adjust the cell's borders
+ pTCs[i + nctc] = pTCs[i];
+ }
+ }
+
+ //if itcMac is larger than full size, fill in missing ones first
+ for( int i = nWwCols; i > nitcInsert+nWwCols; i--)
+ nCenter[i] = i ? (nCenter[i - 1]+ndxaCol) : 0;
+
+ //now add in our new cells
+ for( int j = 0;j < nctc; j++)
+ nCenter[j + nitcInsert] = (j + nitcInsert) ? (nCenter[j + nitcInsert -1]+ndxaCol) : 0;
+
+ nWwCols = nNewWwCols;
+ }
+}
+
+void WW8TabBandDesc::ProcessDirection(const BYTE* pParams)
+{
+ sal_uInt8 nStartCell = *pParams++;
+ sal_uInt8 nEndCell = *pParams++;
+ sal_uInt16 nCode = SVBT16ToShort(pParams);
+
+ ASSERT(nStartCell < nEndCell, "not as I thought");
+ ASSERT(nEndCell < MAX_COL + 1, "not as I thought");
+ if (nStartCell > MAX_COL)
+ return;
+ if (nEndCell > MAX_COL + 1)
+ nEndCell = MAX_COL + 1;
+
+ for (;nStartCell < nEndCell; ++nStartCell)
+ maDirections[nStartCell] = nCode;
+}
+
+void WW8TabBandDesc::ProcessSpacing(const BYTE* pParams)
+{
+ BYTE nLen = pParams ? *(pParams - 1) : 0;
+ ASSERT(nLen == 6, "Unexpected spacing len");
+ if (nLen != 6)
+ return;
+ mbHasSpacing=true;
+#ifndef PRODUCT
+ BYTE nWhichCell =
+#endif
+ *pParams++;
+ ASSERT(nWhichCell == 0, "Expected cell to be 0!");
+ *pParams++; //unknown byte
+
+ BYTE nSideBits = *pParams++;
+ ASSERT(nSideBits < 0x10, "Unexpected value for nSideBits");
+ *pParams++; //unknown byte
+ USHORT nValue = SVBT16ToShort( pParams );
+ for (int i = wwTOP; i <= wwRIGHT; i++)
+ {
+ switch (nSideBits & (1 << i))
+ {
+ case 1 << wwTOP:
+ mnDefaultTop = nValue;
+ break;
+ case 1 << wwLEFT:
+ mnDefaultLeft = nValue;
+ break;
+ case 1 << wwBOTTOM:
+ mnDefaultBottom = nValue;
+ break;
+ case 1 << wwRIGHT:
+ mnDefaultRight = nValue;
+ break;
+ case 0:
+ break;
+ default:
+ ASSERT(!this, "Impossible");
+ break;
+ }
+ }
+}
+
+void WW8TabBandDesc::ProcessSpecificSpacing(const BYTE* pParams)
+{
+ BYTE nLen = pParams ? *(pParams - 1) : 0;
+ ASSERT(nLen == 6, "Unexpected spacing len");
+ if (nLen != 6)
+ return;
+ BYTE nWhichCell = *pParams++;
+ ASSERT(nWhichCell < MAX_COL + 1, "Cell out of range in spacings");
+ if (nWhichCell >= MAX_COL + 1)
+ return;
+
+ *pParams++; //unknown byte
+ BYTE nSideBits = *pParams++;
+ ASSERT(nSideBits < 0x10, "Unexpected value for nSideBits");
+ nOverrideSpacing[nWhichCell] |= nSideBits;
+
+ ASSERT(nOverrideSpacing[nWhichCell] < 0x10,
+ "Unexpected value for nSideBits");
+#ifndef PRODUCT
+ BYTE nUnknown2 =
+#endif
+ *pParams++;
+ ASSERT(nUnknown2 == 0x3, "Unexpected value for spacing2");
+ USHORT nValue = SVBT16ToShort( pParams );
+
+ for (int i=0; i < 4; i++)
+ {
+ if (nSideBits & (1 << i))
+ nOverrideValues[nWhichCell][i] = nValue;
+ }
+}
+
+void WW8TabBandDesc::ProcessSprmTDelete(const BYTE* pParamsTDelete)
+{
+ if( nWwCols && pParamsTDelete ) // set one or more cell length(s)
+ {
+ BYTE nitcFirst= pParamsTDelete[0]; // first col to be deleted
+ if (nitcFirst >= nWwCols) // first index to delete from doesn't exist
+ return;
+ BYTE nitcLim = pParamsTDelete[1]; // (last col to be deleted)+1
+ if (nitcLim <= nitcFirst) // second index to delete to is not greater than first index
+ return;
+
+ /*
+ * sprmTDelete causes any rgdxaCenter and rgtc entries whose index is
+ * greater than or equal to itcLim to be moved
+ */
+ int nShlCnt = nWwCols - nitcLim; // count of cells to be shifted
+
+ if (nShlCnt >= 0) //There exist entries whose index is greater than or equal to itcLim
+ {
+ WW8_TCell* pAktTC = pTCs + nitcFirst;
+ int i = 0;
+ while( i < nShlCnt )
+ {
+ // adjust the left x-position
+ nCenter[nitcFirst + i] = nCenter[nitcLim + i];
+
+ // adjust the cell's borders
+ *pAktTC = pTCs[ nitcLim + i];
+
+ ++i;
+ ++pAktTC;
+ }
+ // adjust the left x-position of the dummy at the very end
+ nCenter[nitcFirst + i] = nCenter[nitcLim + i];
+ }
+
+ short nCellsDeleted = nitcLim - nitcFirst;
+ //clip delete request to available number of cells
+ if (nCellsDeleted > nWwCols)
+ nCellsDeleted = nWwCols;
+ nWwCols -= nCellsDeleted;
+ }
+}
+
+// ReadShd liest ggfs die Hintergrundfarben einer Zeile ein.
+// Es muss vorher ReadDef aufgerufen worden sein
+void WW8TabBandDesc::ReadShd(const BYTE* pS )
+{
+ BYTE nLen = pS ? *(pS - 1) : 0;
+ if( !nLen )
+ return;
+
+ if( !pSHDs )
+ {
+ pSHDs = new WW8_SHD[nWwCols];
+ memset( pSHDs, 0, nWwCols * sizeof( WW8_SHD ) );
+ }
+
+ short nAnz = nLen >> 1;
+ if (nAnz > nWwCols)
+ nAnz = nWwCols;
+
+ SVBT16* pShd;
+ int i;
+ for(i=0, pShd = (SVBT16*)pS; i<nAnz; i++, pShd++ )
+ pSHDs[i].SetWWValue( *pShd );
+}
+
+void WW8TabBandDesc::ReadNewShd(const BYTE* pS, bool bVer67)
+{
+ BYTE nLen = pS ? *(pS - 1) : 0;
+ if (!nLen)
+ return;
+
+ if (!pNewSHDs)
+ pNewSHDs = new sal_uInt32[nWwCols];
+
+ short nAnz = nLen / 10; //10 bytes each
+ if (nAnz > nWwCols)
+ nAnz = nWwCols;
+
+ int i=0;
+ while (i < nAnz)
+ pNewSHDs[i++] = SwWW8ImplReader::ExtractColour(pS, bVer67);
+
+ while (i < nWwCols)
+ pNewSHDs[i++] = COL_AUTO;
+}
+
+void WW8TabBandDesc::setcelldefaults(WW8_TCell *pCells, short nCols)
+{
+ memset( pCells, 0, nCols * sizeof( WW8_TCell ) );
+}
+
+const BYTE *HasTabCellSprm(WW8PLCFx_Cp_FKP* pPap, bool bVer67)
+{
+ const BYTE *pParams;
+ if (bVer67)
+ pParams = pPap->HasSprm(24);
+ else
+ {
+ if (0 == (pParams = pPap->HasSprm(0x244B)))
+ pParams = pPap->HasSprm(0x2416);
+ }
+ return pParams;
+}
+
+enum wwTableSprm
+{
+ sprmNil,
+
+ sprmTTableWidth,sprmTTextFlow, sprmTFCantSplit, sprmTFCantSplit90,sprmTJc, sprmTFBiDi, sprmTDefTable,
+ sprmTDyaRowHeight, sprmTDefTableShd, sprmTDxaLeft, sprmTSetBrc,
+ sprmTDxaCol, sprmTInsert, sprmTDelete, sprmTTableHeader,
+ sprmTDxaGapHalf, sprmTTableBorders,
+
+ sprmTDefTableNewShd, sprmTSpacing, sprmTNewSpacing
+};
+
+wwTableSprm GetTableSprm(sal_uInt16 nId, ww::WordVersion eVer)
+{
+ switch (eVer)
+ {
+ case ww::eWW8:
+ switch (nId)
+ {
+ case 0xF614:
+ return sprmTTableWidth;
+ case 0x7629:
+ return sprmTTextFlow;
+ case 0x3403:
+ return sprmTFCantSplit;
+ case 0x3404:
+ return sprmTTableHeader;
+ case 0x3466:
+ return sprmTFCantSplit90;
+ case 0x5400:
+ return sprmTJc;
+ case 0x560B:
+ return sprmTFBiDi;
+ case 0x5622:
+ return sprmTDelete;
+ case 0x7621:
+ return sprmTInsert;
+ case 0x7623:
+ return sprmTDxaCol;
+ case 0x9407:
+ return sprmTDyaRowHeight;
+ case 0x9601:
+ return sprmTDxaLeft;
+ case 0x9602:
+ return sprmTDxaGapHalf;
+ case 0xD605:
+ return sprmTTableBorders;
+ case 0xD608:
+ return sprmTDefTable;
+ case 0xD609:
+ return sprmTDefTableShd;
+ case 0xD612:
+ return sprmTDefTableNewShd;
+ case 0xD620:
+ return sprmTSetBrc;
+ case 0xD632:
+ return sprmTSpacing;
+ case 0xD634:
+ return sprmTNewSpacing;
+ }
+ break;
+ case ww::eWW7:
+ case ww::eWW6:
+ switch (nId)
+ {
+ case 182:
+ return sprmTJc;
+ case 183:
+ return sprmTDxaLeft;
+ case 184:
+ return sprmTDxaGapHalf;
+ case 186:
+ return sprmTTableHeader;
+ case 187:
+ return sprmTTableBorders;
+ case 189:
+ return sprmTDyaRowHeight;
+ case 190:
+ return sprmTDefTable;
+ case 191:
+ return sprmTDefTableShd;
+ case 193:
+ return sprmTSetBrc;
+ case 194:
+ return sprmTInsert;
+ case 195:
+ return sprmTDelete;
+ case 196:
+ return sprmTDxaCol;
+ }
+ break;
+ case ww::eWW2:
+ switch (nId)
+ {
+ case 146:
+ return sprmTJc;
+ case 147:
+ return sprmTDxaLeft;
+ case 148:
+ return sprmTDxaGapHalf;
+ case 153:
+ return sprmTDyaRowHeight;
+ case 154:
+ return sprmTDefTable;
+ case 155:
+ return sprmTDefTableShd;
+ case 157:
+ return sprmTSetBrc;
+ case 158:
+ return sprmTInsert;
+ case 159:
+ return sprmTDelete;
+ case 160:
+ return sprmTDxaCol;
+ }
+ break;
+ }
+ return sprmNil;
+}
+
+WW8TabDesc::WW8TabDesc(SwWW8ImplReader* pIoClass, WW8_CP nStartCp) :
+ mpOldRedlineStack(0),
+ pIo(pIoClass),
+ pFirstBand(0),
+ pActBand(0),
+ pTmpPos(0),
+ pTblNd(0),
+ pTabLines(0),
+ pTabLine(0),
+ pTabBoxes(0),
+ pTabBox(0),
+ pMergeGroups(0),
+ pAktWWCell(0),
+ nRows(0),
+ nDefaultSwCols(0),
+ nBands(0),
+ nMinLeft(0),
+ nConvertedLeft(0),
+ nMaxRight(0),
+ nSwWidth(0),
+ nPreferredWidth(0),
+ nOrgDxaLeft(0),
+ bOk(true),
+ bClaimLineFmt(false),
+ eOri(text::HoriOrientation::NONE),
+ bIsBiDi(false),
+ nAktRow(0),
+ nAktBandRow(0),
+ nAktCol(0),
+ nRowsToRepeat(0),
+ pTable(0),
+ pParentPos(0),
+ pFlyFmt(0),
+ aItemSet(pIo->rDoc.GetAttrPool(),RES_FRMATR_BEGIN,RES_FRMATR_END-1)
+{
+ pIo->bAktAND_fNumberAcross = false;
+
+ static const sal_Int16 aOriArr[] =
+ {
+ text::HoriOrientation::LEFT, text::HoriOrientation::CENTER, text::HoriOrientation::RIGHT, text::HoriOrientation::CENTER
+ };
+
+ bool bOldVer = ww::IsSevenMinus(pIo->GetFib().GetFIBVersion());
+ WW8_TablePos aTabPos;
+
+ WW8PLCFxSave1 aSave;
+ pIo->pPlcxMan->GetPap()->Save( aSave );
+
+ WW8PLCFx_Cp_FKP* pPap = pIo->pPlcxMan->GetPapPLCF();
+
+ eOri = text::HoriOrientation::LEFT;
+
+ WW8TabBandDesc* pNewBand = new WW8TabBandDesc;
+
+ wwSprmParser aSprmParser(pIo->GetFib().GetFIBVersion());
+
+ // process pPap until end of table found
+ do
+ {
+ short nTabeDxaNew = SHRT_MAX;
+ bool bTabRowJustRead = false;
+ const BYTE* pShadeSprm = 0;
+ const BYTE* pNewShadeSprm = 0;
+ WW8_TablePos *pTabPos = 0;
+
+ // Suche Ende einer TabZeile
+ if(!(pIo->SearchRowEnd(pPap, nStartCp, pIo->nInTable)))
+ {
+ bOk = false;
+ break;
+ }
+
+ // Get the SPRM chains:
+ // first from PAP and then from PCD (of the Piece Table)
+ WW8PLCFxDesc aDesc;
+ pPap->GetSprms( &aDesc );
+ WW8SprmIter aSprmIter(aDesc.pMemPos, aDesc.nSprmsLen, aSprmParser);
+
+ const BYTE* pParams = aSprmIter.GetAktParams();
+ for (int nLoop = 0; nLoop < 2; ++nLoop)
+ {
+ bool bRepeatedSprm = false;
+ while (aSprmIter.GetSprms() && 0 != (pParams = aSprmIter.GetAktParams()))
+ {
+ sal_uInt16 nId = aSprmIter.GetAktId();
+ wwTableSprm eSprm = GetTableSprm(nId, pIo->GetFib().GetFIBVersion());
+ switch (eSprm)
+ {
+ case sprmTTableWidth:
+ {
+ const BYTE b0 = pParams[0];
+ const BYTE b1 = pParams[1];
+ const BYTE b2 = pParams[2];
+ if (b0 == 3) // Twips
+ nPreferredWidth = b2 * 0x100 + b1;
+ }
+ break;
+ case sprmTTextFlow:
+ pNewBand->ProcessDirection(pParams);
+ break;
+ case sprmTFCantSplit:
+ pNewBand->bCantSplit = *pParams;
+ bClaimLineFmt = true;
+ break;
+ case sprmTFCantSplit90:
+ pNewBand->bCantSplit90 = *pParams;
+ bClaimLineFmt = true;
+ break;
+ case sprmTTableBorders:
+ pNewBand->ProcessSprmTTableBorders(bOldVer, pParams);
+ break;
+ case sprmTTableHeader:
+ if (!bRepeatedSprm)
+ {
+ nRowsToRepeat++;
+ bRepeatedSprm = true;
+ }
+ break;
+ case sprmTJc:
+ // sprmTJc - Justification Code
+ if (nRows == 0)
+ eOri = aOriArr[*pParams & 0x3];
+ break;
+ case sprmTFBiDi:
+ bIsBiDi = SVBT16ToShort(pParams) ? true : false;
+ break;
+ case sprmTDxaGapHalf:
+ pNewBand->nGapHalf = (INT16)SVBT16ToShort( pParams );
+ break;
+ case sprmTDyaRowHeight:
+ pNewBand->nLineHeight = (INT16)SVBT16ToShort( pParams );
+ bClaimLineFmt = true;
+ break;
+ case sprmTDefTable:
+ pNewBand->ReadDef(bOldVer, pParams);
+ bTabRowJustRead = true;
+ break;
+ case sprmTDefTableShd:
+ pShadeSprm = pParams;
+ break;
+ case sprmTDefTableNewShd:
+ pNewShadeSprm = pParams;
+ break;
+ case sprmTDxaLeft:
+ // our Writer cannot shift single table lines
+ // horizontally so we have to find the smallest
+ // parameter (meaning the left-most position) and then
+ // shift the whole table to that margin (see below)
+ {
+ short nDxaNew = (INT16)SVBT16ToShort( pParams );
+ nOrgDxaLeft = nDxaNew;
+ if( nDxaNew < nTabeDxaNew )
+ nTabeDxaNew = nDxaNew;
+ }
+ break;
+ case sprmTSetBrc:
+ pNewBand->ProcessSprmTSetBRC(bOldVer, pParams);
+ break;
+ case sprmTDxaCol:
+ pNewBand->ProcessSprmTDxaCol(pParams);
+ break;
+ case sprmTInsert:
+ pNewBand->ProcessSprmTInsert(pParams);
+ break;
+ case sprmTDelete:
+ pNewBand->ProcessSprmTDelete(pParams);
+ break;
+ case sprmTNewSpacing:
+ pNewBand->ProcessSpacing(pParams);
+ break;
+ case sprmTSpacing:
+ pNewBand->ProcessSpecificSpacing(pParams);
+ break;
+ default:
+ ;
+ }
+ aSprmIter++;
+ }
+
+ if( !nLoop )
+ {
+ pPap->GetPCDSprms( aDesc );
+ aSprmIter.SetSprms( aDesc.pMemPos, aDesc.nSprmsLen );
+ }
+ }
+
+ // #55171: WW-Tabellen koennen Fly-Wechsel beinhalten daher hier
+ // Tabellen abbrechen und neu beginnen noch steht *pPap noch vor
+ // TabRowEnd, daher kann TestApo() mit letztem Parameter false und
+ // damit wirksam gerufen werden.
+
+ if (bTabRowJustRead)
+ {
+ if (pShadeSprm)
+ pNewBand->ReadShd(pShadeSprm);
+ if (pNewShadeSprm)
+ pNewBand->ReadNewShd(pNewShadeSprm, bOldVer);
+ }
+
+ if( nTabeDxaNew < SHRT_MAX )
+ {
+ short* pCenter = pNewBand->nCenter;
+ short firstDxaCenter = *pCenter;
+ for( int i = 0; i < pNewBand->nWwCols; i++, ++pCenter )
+ {
+ // #i30298# Use sprmTDxaLeft to adjust the left indent
+ // #i40461# Use dxaGapHalf during calculation
+ *pCenter +=
+ (nTabeDxaNew - (firstDxaCenter + pNewBand->nGapHalf));
+ }
+ }
+
+ if (!pActBand)
+ pActBand = pFirstBand = pNewBand;
+ else
+ {
+ pActBand->pNextBand = pNewBand;
+ pActBand = pNewBand;
+ }
+ nBands++;
+
+ pNewBand = new WW8TabBandDesc;
+
+ nRows++;
+ pActBand->nRows++;
+
+ //Seek our pap to its next block of properties
+ WW8PLCFxDesc aRes;
+ aRes.pMemPos = 0;
+ aRes.nStartPos = nStartCp;
+
+ if (!(pPap->SeekPos(aRes.nStartPos)))
+ {
+ aRes.nEndPos = WW8_CP_MAX;
+ pPap->SetDirty(true);
+ }
+ pPap->GetSprms(&aRes);
+ pPap->SetDirty(false);
+
+ //Are we at the end of available properties
+ if (
+ !pPap->HasFkp() || pPap->Where() == WW8_CP_MAX ||
+ aRes.nStartPos == WW8_CP_MAX
+ )
+ {
+ bOk = false;
+ break;
+ }
+
+ //Are we still in a table cell
+ pParams = HasTabCellSprm(pPap, bOldVer);
+ const BYTE *pLevel = pPap->HasSprm(0x6649);
+ // InTable
+ if (!pParams || (1 != *pParams) ||
+ (pLevel && (*pLevel <= pIo->nInTable)))
+ {
+ break;
+ }
+
+ //Get the end of row new table positioning data
+ WW8_CP nMyStartCp=nStartCp;
+ if (pIo->SearchRowEnd(pPap, nMyStartCp, pIo->nInTable))
+ if (SwWW8ImplReader::ParseTabPos(&aTabPos, pPap))
+ pTabPos = &aTabPos;
+
+ //Move back to this cell
+ aRes.pMemPos = 0;
+ aRes.nStartPos = nStartCp;
+
+ // #114237 PlcxMan currently points too far ahead so we need to bring
+ // it back to where we are trying to make a table
+ pIo->pPlcxMan->GetPap()->nOrigStartPos = aRes.nStartPos;
+ if (!(pPap->SeekPos(aRes.nStartPos)))
+ {
+ aRes.nEndPos = WW8_CP_MAX;
+ pPap->SetDirty(true);
+ }
+ pPap->GetSprms(&aRes);
+ pPap->SetDirty(false);
+
+ //Does this row match up with the last row closely enough to be
+ //considered part of the same table
+ ApoTestResults aApo = pIo->TestApo(pIo->nInTable + 1, false, pTabPos);
+
+ /*
+ ##513##, #79474# If this is not sufficent, then we should look at
+ sprmPD{y|x}aAbs as our indicator that the following set of rows is not
+ part of this table, but instead is an absolutely positioned table
+ outside of this one
+ */
+ if (aApo.mbStopApo)
+ break;
+ if (aApo.mbStartApo)
+ {
+ //if there really is a fly here, and not a "null" fly then break.
+ WW8FlyPara *pNewFly = pIo->ConstructApo(aApo, pTabPos);
+ if (pNewFly)
+ delete pNewFly;
+ else
+ break;
+ }
+
+ nStartCp = aRes.nEndPos;
+ }
+ while( 1 );
+
+ if( bOk )
+ {
+ if( pActBand->nRows > 1 )
+ {
+ // Letztes Band hat mehr als 1 Zeile
+ delete pNewBand;
+ pNewBand = new WW8TabBandDesc( *pActBand ); // neues machen
+ pActBand->nRows--; // wegen Sonderbehandlung Raender-Defaults
+ pNewBand->nRows = 1;
+ pActBand->pNextBand = pNewBand; // am Ende einschleifen
+ nBands++;
+ pNewBand = 0; // nicht loeschen
+ }
+ CalcDefaults();
+ }
+ delete pNewBand;
+
+ pIo->pPlcxMan->GetPap()->Restore( aSave );
+}
+
+WW8TabDesc::~WW8TabDesc()
+{
+ WW8TabBandDesc* pR = pFirstBand;
+ while(pR)
+ {
+ WW8TabBandDesc* pR2 = pR->pNextBand;
+ delete pR;
+ pR = pR2;
+ }
+
+ delete pParentPos;
+ delete pMergeGroups;
+}
+
+void WW8TabDesc::CalcDefaults()
+{
+ short nMinCols = SHRT_MAX;
+ WW8TabBandDesc* pR;
+
+ nMinLeft = SHRT_MAX;
+ nMaxRight = SHRT_MIN;
+
+ /*
+ #101175#
+ If we are an honestly inline centered table, then the normal rules of
+ engagement for left and right margins do not apply. The multiple rows are
+ centered regardless of the actual placement of rows, so we cannot have
+ mismatched rows as is possible in other configurations.
+
+ e.g. change the example bugdoc in word from text wrapping of none (inline)
+ to around (in frame (bApo)) and the table splits into two very disjoint
+ rows as the beginning point of each row are very different
+ */
+ if ((!pIo->InLocalApo()) && (eOri == text::HoriOrientation::CENTER))
+ {
+ for (pR = pFirstBand; pR; pR = pR->pNextBand)
+ for( short i = pR->nWwCols; i >= 0; --i)
+ pR->nCenter[i] = pR->nCenter[i] - pR->nCenter[0];
+ }
+
+ // 1. Durchlauf: aeusserste L- und R-Grenzen finden
+ for( pR = pFirstBand; pR; pR = pR->pNextBand )
+ {
+ if( pR->nCenter[0] < nMinLeft )
+ nMinLeft = pR->nCenter[0];
+
+ for( short i = 0; i < pR->nWwCols; i++ )
+ {
+ /*
+ #74387# If the margins are so large as to make the displayable
+ area inside them smaller than the minimum allowed then adjust the
+ width to fit. But only do it if the two cells are not the exact
+ same value, if they are then the cell does not really exist and will
+ be blended together into the same cell through the use of the
+ nTrans(late) array.
+ #i28333# If the nGapHalf is greater than the cell width best to ignore it
+ */
+ int nCellWidth = pR->nCenter[i+1] - pR->nCenter[i];
+ if (nCellWidth && ((nCellWidth - pR->nGapHalf*2) < MINLAY) && pR->nGapHalf < nCellWidth)
+ {
+ pR->nCenter[i+1] = pR->nCenter[i]+MINLAY+pR->nGapHalf * 2;
+ }
+ }
+
+ if( pR->nCenter[pR->nWwCols] > nMaxRight )
+ nMaxRight = pR->nCenter[pR->nWwCols];
+ }
+ nSwWidth = nMaxRight - nMinLeft;
+
+ // #109830# If the table is right aligned we need to align all rows to the
+ // row that has the furthest right point
+
+ if(eOri == text::HoriOrientation::RIGHT)
+ {
+ for( pR = pFirstBand; pR; pR = pR->pNextBand )
+ {
+ int adjust = nMaxRight - pR->nCenter[pR->nWwCols];
+ for( short i = 0; i < pR->nWwCols + 1; i++ )
+ {
+ pR->nCenter[i] = static_cast< short >(pR->nCenter[i] + adjust);
+ }
+
+ }
+ }
+
+ // 2. Durchlauf: Zahl der Writer-Spalten feststellen Die Zahl der Writer
+ // Spalten kann um bis zu 2 hoeher sein als im WW, da der SW im Gegensatz
+ // zu WW keine ausgefransten linken und rechten Raender kann und diese
+ // durch leere Boxen aufgefuellt werden. Durch nichtexistente Zellen
+ // koennen auch Zellen wegfallen
+
+ // 3. Durchlauf: Wo noetig die Umrandungen durch die Defaults ersetzen
+ nConvertedLeft = nMinLeft;
+
+ short nLeftMaxThickness = 0, nRightMaxThickness=0;
+ for( pR = pFirstBand ; pR; pR = pR->pNextBand )
+ {
+ if( !pR->pTCs )
+ {
+ pR->pTCs = new WW8_TCell[ pR->nWwCols ];
+ memset( pR->pTCs, 0, pR->nWwCols * sizeof( WW8_TCell ) );
+ }
+ for (int k = 0; k < pR->nWwCols; ++k)
+ {
+ WW8_TCell* pT = &pR->pTCs[k];
+ int i, j;
+ for( i = 0; i < 4; i ++ )
+ {
+ if (pT->rgbrc[i].IsZeroed(pIo->bVer67))
+ {
+ // if shadow is set, its invalid
+ j = i;
+ switch( i )
+ {
+ case 0:
+ // Aussen oben / Innen waagerecht
+ j = (pR == pFirstBand) ? 0 : 4;
+ break;
+ case 1:
+ // Aussen links / Innen senkrecht
+ j = k ? 5 : 1;
+ break;
+ case 2:
+ // Aussen unten / Innen waagerecht
+ j = pR->pNextBand ? 4 : 2;
+ break;
+ case 3:
+ // Aussen rechts/ Innen senkrecht
+ j = (k == pR->nWwCols - 1) ? 3 : 5;
+ break;
+ }
+ // mangel mit Defaults ueber
+ pT->rgbrc[i] = pR->aDefBrcs[j];
+ }
+ }
+ }
+ /*
+ Similiar to graphics and other elements word does not totally
+ factor the width of the border into its calculations of size, we
+ do so we must adjust out widths and other dimensions to fit. It
+ appears that what occurs is that the last cell's right margin if
+ the margin width that is not calculated into winwords table
+ dimensions, so in that case increase the table to include the
+ extra width of the right margin.
+ */
+ if ( pIo->bVer67 ?
+ !(SVBT16ToShort(pR->pTCs[pR->nWwCols-1].rgbrc[3].aBits1) & 0x20)
+ : !(SVBT16ToShort(pR->pTCs[pR->nWwCols-1].rgbrc[3].aBits2) & 0x2000))
+ {
+ short nThickness = pR->pTCs[pR->nWwCols-1].rgbrc[3].
+ DetermineBorderProperties(pIo->bVer67);
+ pR->nCenter[pR->nWwCols] = pR->nCenter[pR->nWwCols] + nThickness;
+ if (nThickness > nRightMaxThickness)
+ nRightMaxThickness = nThickness;
+ }
+
+ /*
+ The left space of the table is in nMinLeft, but again this
+ does not consider the margin thickness to its left in the
+ placement value, so get the thickness of the left border,
+ half is placed to the left of the nominal left side, and
+ half to the right.
+ */
+ if ( pIo->bVer67 ?
+ !(SVBT16ToShort(pR->pTCs[0].rgbrc[1].aBits1) & 0x20)
+ : !(SVBT16ToShort(pR->pTCs[0].rgbrc[1].aBits2) & 0x2000))
+ {
+ short nThickness = pR->pTCs[0].rgbrc[1].
+ DetermineBorderProperties(pIo->bVer67);
+ if (nThickness > nLeftMaxThickness)
+ nLeftMaxThickness = nThickness;
+ }
+ }
+ nSwWidth = nSwWidth + nRightMaxThickness;
+ nMaxRight = nMaxRight + nRightMaxThickness;
+ nConvertedLeft = nMinLeft-(nLeftMaxThickness/2);
+
+ for( pR = pFirstBand; pR; pR = pR->pNextBand )
+ {
+ pR->nSwCols = pR->nWwCols;
+ pR->bLEmptyCol = pR->nCenter[0] - nMinLeft >= MINLAY;
+ pR->bREmptyCol = (nMaxRight - pR->nCenter[pR->nWwCols] - nRightMaxThickness) >= MINLAY;
+
+ short nAddCols = pR->bLEmptyCol + pR->bREmptyCol;
+ USHORT i;
+ USHORT j = ( pR->bLEmptyCol ) ? 1 : 0;
+ for (i = 0; i < pR->nWwCols; ++i)
+ {
+ pR->nTransCell[i] = (INT8)j;
+ if ( pR->nCenter[i] < pR->nCenter[i+1] )
+ {
+ pR->bExist[i] = true;
+ j++;
+ }
+ else
+ {
+ pR->bExist[i] = false;
+ nAddCols--;
+ }
+ }
+
+ ASSERT(i,"no columns in row ?");
+
+ /*
+ #96345#
+ If the last cell was "false" then there is no valid cell following it,
+ so the default mapping forward wont't work. So map it (and
+ contigious invalid cells backwards to the last valid cell instead.
+ */
+ if (i && pR->bExist[i-1] == false)
+ {
+ USHORT k=i-1;
+ while (k && pR->bExist[k] == false)
+ k--;
+ for (USHORT n=k+1;n<i;n++)
+ pR->nTransCell[n] = pR->nTransCell[k];
+ }
+
+ pR->nTransCell[i++] = (INT8)(j++); // Wird u.a. wegen bREmptyCol um
+ pR->nTransCell[i] = (INT8)j; // max. 2 ueberindiziert
+
+ pR->nSwCols = pR->nSwCols + nAddCols;
+ if( pR->nSwCols < nMinCols )
+ nMinCols = pR->nSwCols;
+ }
+
+ /*
+ #i9718#
+ Find the largest of the borders on cells that adjoin top bottom and remove
+ the val from the top and put in on the bottom cell. I can't seem to make
+ disjoint upper and lowers to see what happens there.
+ */
+
+ /* #i29550# FME 2004-06-02 Removed this code because of the implementation
+ of the collapsing table borders model. So this should not be necessary
+ anymore. */
+
+ /* for (pR = pFirstBand; pR; pR = pR->pNextBand)
+ {
+ WW8TabBandDesc *pNext = pR->pNextBand;
+ if (!pNext)
+ break;
+
+ for (int k = 0; k < pR->nWwCols; ++k)
+ {
+ WW8_BRC &rAbove = pR->pTCs[k].rgbrc[WW8_BOT];
+ short nAboveThick = rAbove.IsEmpty(pIo->bVer67) ?
+ 0 : rAbove.DetermineBorderProperties(pIo->bVer67);
+ short nUpperLeft = pR->nCenter[k];
+ short nUpperRight = pR->nCenter[k+1];
+
+ for (int l = 0; l < pNext->nWwCols; ++l)
+ {
+ short nLowerLeft = pNext->nCenter[l];
+ short nLowerRight = pNext->nCenter[l+1];
+
+ if ((nLowerLeft < nUpperLeft) || (nLowerRight > nUpperRight))
+ continue;
+
+ WW8_BRC &rBelow = pNext->pTCs[l].rgbrc[WW8_TOP];
+ short nBelowThick = rBelow.IsEmpty(pIo->bVer67) ?
+ 0 : rBelow.DetermineBorderProperties(pIo->bVer67);
+ if (nAboveThick > nBelowThick)
+ rBelow = rAbove;
+ }
+
+ rAbove = WW8_BRC();
+ }
+ } */
+
+ if ((nMinLeft && !bIsBiDi && text::HoriOrientation::LEFT == eOri) ||
+ (nMinLeft != -108 && bIsBiDi && text::HoriOrientation::RIGHT == eOri)) // Word sets the first nCenter value to -108 when no indent is used
+ eOri = text::HoriOrientation::LEFT_AND_WIDTH; // absolutely positioned
+
+ nDefaultSwCols = nMinCols; // da Zellen einfuegen billiger ist als Mergen
+ if( nDefaultSwCols == 0 )
+ bOk = false;
+ pActBand = pFirstBand;
+ nAktBandRow = 0;
+ ASSERT( pActBand, "pActBand ist 0" );
+}
+
+void WW8TabDesc::SetSizePosition(SwFrmFmt* pFrmFmt)
+{
+ SwFrmFmt* pApply = pFrmFmt;
+ if (!pApply )
+ pApply = pTable->GetFrmFmt();
+ ASSERT(pApply,"No frame");
+ pApply->SetFmtAttr(aItemSet);
+ if (pFrmFmt)
+ {
+ SwFmtFrmSize aSize = pFrmFmt->GetFrmSize();
+ aSize.SetHeightSizeType(ATT_MIN_SIZE);
+ aSize.SetHeight(MINLAY);
+ pFrmFmt->SetFmtAttr(aSize);
+ pTable->GetFrmFmt()->SetFmtAttr(SwFmtHoriOrient(0,text::HoriOrientation::FULL));
+ }
+}
+
+void wwSectionManager::PrependedInlineNode(const SwPosition &rPos,
+ const SwNode &rNode)
+{
+ ASSERT(!maSegments.empty(),
+ "should not be possible, must be at least one segment");
+ if ((!maSegments.empty()) && (maSegments.back().maStart == rPos.nNode))
+ maSegments.back().maStart = SwNodeIndex(rNode);
+}
+
+void WW8TabDesc::CreateSwTable()
+{
+ ::SetProgressState(pIo->nProgress, pIo->mpDocShell); // Update
+
+ // if there is already some content on the Node append new node to ensure
+ // that this content remains ABOVE the table
+ SwPosition* pPoint = pIo->pPaM->GetPoint();
+ bool bInsNode = pPoint->nContent.GetIndex() ? true : false;
+ bool bSetMinHeight = false;
+
+ /*
+ #i8062#
+ Set fly anchor to its anchor pos, so that if a table starts immediately
+ at this position a new node will be inserted before inserting the table.
+ */
+ if (!bInsNode && pIo->pFmtOfJustInsertedApo)
+ {
+ const SwPosition* pAPos =
+ pIo->pFmtOfJustInsertedApo->GetAnchor().GetCntntAnchor();
+ if (pAPos && &pAPos->nNode.GetNode() == &pPoint->nNode.GetNode())
+ {
+ bInsNode = true;
+ bSetMinHeight = true;
+
+ SwFmtSurround aSur(pIo->pFmtOfJustInsertedApo->GetSurround());
+ aSur.SetAnchorOnly(true);
+ pIo->pFmtOfJustInsertedApo->SetFmtAttr(aSur);
+ }
+ }
+
+ if (bSetMinHeight == true)
+ {
+ // minimize Fontsize to minimize height growth of the header/footer
+ // set font size to 1 point to minimize y-growth of Hd/Ft
+ SvxFontHeightItem aSz(20, 100, RES_CHRATR_FONTSIZE);
+ pIo->NewAttr( aSz );
+ pIo->pCtrlStck->SetAttr(*pPoint, RES_CHRATR_FONTSIZE);
+ }
+
+ if (bInsNode)
+ pIo->AppendTxtNode(*pPoint);
+
+ pTmpPos = new SwPosition( *pIo->pPaM->GetPoint() );
+
+ // Die Tabelle ist beim Einfuegen noch recht klein: Zahl der Spalten ist
+ // die kleinste Spaltenanzahl des Originals, da Spalten einfuegen
+ // schneller geht als Loeschen Zahl der Zeilen ist die Zahl der Baender,
+ // da sich die (identischen) Zeilen eines Bandes prima duplizieren lassen
+ pTable = pIo->rDoc.InsertTable(
+ SwInsertTableOptions( tabopts::HEADLINE_NO_BORDER, 0 ),
+ *pTmpPos, nBands, nDefaultSwCols, eOri, 0, 0, FALSE, TRUE );
+
+ ASSERT(pTable && pTable->GetFrmFmt(), "insert table failed");
+ if (!pTable || !pTable->GetFrmFmt())
+ return;
+
+ SwTableNode* pTableNode = pTable->GetTableNode();
+ ASSERT(pTableNode, "no table node!");
+ if (pTableNode)
+ {
+ pIo->maSectionManager.PrependedInlineNode(*pIo->pPaM->GetPoint(),
+ *pTableNode);
+ }
+
+ // Abfrage, ob im Node, in dem die Tabelle eingefuegt werden soll, bereits
+ // ein Pagedesc steht. Dann wuerde der PageDesc in die naechste Zeile
+ // hinter der Tabelle rutschen, wo er nichts zu suchen hat. -> loeschen
+ // und spaeter an das Tabellenformat setzen
+ if (SwTxtNode* pNd = pIo->rDoc.GetNodes()[pTmpPos->nNode]->GetTxtNode())
+ {
+ if (const SfxItemSet* pSet = pNd->GetpSwAttrSet())
+ {
+ SfxPoolItem *pSetAttr = 0;
+ const SfxPoolItem* pItem;
+ if (SFX_ITEM_SET == pSet->GetItemState(RES_BREAK, false, &pItem))
+ {
+ pSetAttr = new SvxFmtBreakItem( *(SvxFmtBreakItem*)pItem );
+ pNd->ResetAttr( RES_BREAK );
+ }
+
+ // evtl den PageDesc/Break jetzt an der Tabelle setzen
+ if (pSetAttr)
+ {
+ aItemSet.Put(*pSetAttr);
+ delete pSetAttr;
+ }
+ }
+ }
+
+ // Gesamtbreite der Tabelle
+ if( nMaxRight - nMinLeft > MINLAY * nDefaultSwCols )
+ {
+ pTable->GetFrmFmt()->SetFmtAttr(SwFmtFrmSize(ATT_FIX_SIZE, nSwWidth));
+ aItemSet.Put(SwFmtFrmSize(ATT_FIX_SIZE, nSwWidth));
+ }
+
+ SvxFrameDirectionItem aDirection(
+ bIsBiDi ? FRMDIR_HORI_RIGHT_TOP : FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR );
+ pTable->GetFrmFmt()->SetFmtAttr(aDirection);
+
+ if (text::HoriOrientation::LEFT_AND_WIDTH == eOri)
+ {
+ if (!pIo->nInTable && pIo->InLocalApo() && pIo->pSFlyPara->pFlyFmt &&
+ GetMinLeft())
+ {
+ //If we are inside a frame and we have a border, the frames
+ //placement does not consider the tables border, which word
+ //displays outside the frame, so adjust here.
+ SwFmtHoriOrient aHori(pIo->pSFlyPara->pFlyFmt->GetHoriOrient());
+ sal_Int16 eHori = aHori.GetHoriOrient();
+ if ((eHori == text::HoriOrientation::NONE) || (eHori == text::HoriOrientation::LEFT) ||
+ (eHori == text::HoriOrientation::LEFT_AND_WIDTH))
+ {
+ //With multiple table, use last table settings. Perhaps
+ //the maximum is what word does ?
+ aHori.SetPos(pIo->pSFlyPara->nXPos + GetMinLeft());
+ aHori.SetHoriOrient(text::HoriOrientation::NONE);
+ pIo->pSFlyPara->pFlyFmt->SetFmtAttr(aHori);
+ }
+ }
+ else
+ {
+ //If bApo is set, then this table is being placed in a floating
+ //frame, and the frame matches the left and right *lines* of the
+ //table, so the space to the left of the table isn't to be used
+ //inside the frame, in word the dialog involved greys out the
+ //ability to set the margin.
+ SvxLRSpaceItem aL( RES_LR_SPACE );
+ // set right to original DxaLeft (i28656)
+
+ long nLeft = 0;
+ if (!bIsBiDi)
+ nLeft = GetMinLeft();
+ else
+ {
+ if (nPreferredWidth)
+ nLeft = pIo->maSectionManager.GetTextAreaWidth() - nPreferredWidth - nOrgDxaLeft;
+ else
+ nLeft = -GetMinLeft();
+ }
+
+ aL.SetLeft(nLeft);
+
+ aItemSet.Put(aL);
+ }
+ }
+
+ mpOldRedlineStack = pIo->mpRedlineStack;
+ pIo->mpRedlineStack = new sw::util::RedlineStack(pIo->rDoc);
+}
+
+void WW8TabDesc::UseSwTable()
+{
+ // globale Varis initialisieren
+ pTabLines = &pTable->GetTabLines();
+ nAktRow = nAktCol = nAktBandRow = 0;
+
+ pTblNd = (SwTableNode*)(*pTabLines)[0]->GetTabBoxes()[0]->
+ GetSttNd()->FindTableNode();
+ ASSERT( pTblNd, "wo ist mein TabellenNode" );
+
+ // --> mloiseleur 2007-10-10 #i69519# Restrict rows to repeat to a decent value
+ if ( nRowsToRepeat == static_cast<USHORT>(nRows) )
+ nRowsToRepeat = 1;
+ // <--
+
+ pTblNd->GetTable().SetRowsToRepeat( nRowsToRepeat );
+ // ggfs. Zusatz-Zellen einfuegen u.dgl.
+ AdjustNewBand();
+
+ WW8DupProperties aDup(pIo->rDoc,pIo->pCtrlStck);
+ pIo->pCtrlStck->SetAttr(*pIo->pPaM->GetPoint(), 0, false);
+
+ // jetzt den PaM korrekt setzen und ggfs. erste Mergegruppe vorbereiten...
+ SetPamInCell(nAktCol, true);
+ aDup.Insert(*pIo->pPaM->GetPoint());
+
+ pIo->bWasTabRowEnd = false;
+ pIo->bWasTabCellEnd = false;
+}
+
+void WW8TabDesc::MergeCells()
+{
+ short nRow;
+
+ for (pActBand=pFirstBand, nRow=0; pActBand; pActBand=pActBand->pNextBand)
+ {
+ //
+ // ggfs. aktuelle Box in entsprechende Merge-Gruppe eintragen
+ //
+ if( pActBand->pTCs )
+ {
+ for( short j = 0; j < pActBand->nRows; j++, nRow++ )
+ for( short i = 0; i < pActBand->nWwCols; i++ )
+ {
+ WW8SelBoxInfoPtr pActMGroup = 0;
+ //
+ // ggfs. eine neue Merge-Gruppe beginnen
+ //
+ ASSERT(nRow < pTabLines->Count(),
+ "Too few lines, table ended early");
+ if (nRow >= pTabLines->Count())
+ return;
+ pTabLine = (*pTabLines)[ nRow ];
+ pTabBoxes = &pTabLine->GetTabBoxes();
+
+ USHORT nCol = pActBand->nTransCell[ i ];
+ if (!pActBand->bExist[i]) //#113434#
+ continue;
+ ASSERT(nCol < pTabBoxes->Count(),
+ "Too few columns, table ended early");
+ if (nCol >= pTabBoxes->Count())
+ return;
+ pTabBox = (*pTabBoxes)[nCol];
+ WW8_TCell& rCell = pActBand->pTCs[ i ];
+ // ist dies die obere, linke-Zelle einer Merge-Gruppe ?
+
+ bool bMerge = false;
+ if ( rCell.bVertRestart && !rCell.bMerged )
+ bMerge = true;
+ else if (rCell.bFirstMerged && pActBand->bExist[i])
+ {
+ //#91211# Some tests to avoid merging cells
+ //which previously were declared invalid because
+ //of sharing the exact same dimensions as their
+ //previous cell
+
+ //If theres anything underneath/above we're ok.
+ if (rCell.bVertMerge || rCell.bVertRestart)
+ bMerge = true;
+ else
+ {
+ //If its a hori merge only, and the only things in
+ //it are invalid cells then its already taken care
+ //of, so don't merge.
+ for (USHORT i2 = i+1; i2 < pActBand->nWwCols; i2++ )
+ if (pActBand->pTCs[ i2 ].bMerged &&
+ !pActBand->pTCs[ i2 ].bFirstMerged )
+ {
+ if (pActBand->bExist[i2])
+ {
+ bMerge = true;
+ break;
+ }
+ }
+ else
+ break;
+ }
+ }
+
+
+ if (bMerge)
+ {
+ short nX1 = pActBand->nCenter[ i ];
+ short nWidth = pActBand->nWidth[ i ];
+
+ // 0. falls noetig das Array fuer die Merge-Gruppen
+ // anlegen
+ if( !pMergeGroups )
+ pMergeGroups = new WW8MergeGroups;
+
+ // 2. aktuelle Merge-Gruppe anlegen
+ pActMGroup = new WW8SelBoxInfo( nX1, nWidth );
+
+ // --> OD 2005-02-04 #118544# - determine size of new
+ // merge group before inserted the new merge group.
+ // Needed to correctly locked previously created merge groups.
+ // Gesamtbreite ermitteln und zuweisen
+ short nSizCell = pActBand->nWidth[ i ];
+ for (USHORT i2 = i+1; i2 < pActBand->nWwCols; i2++ )
+ if (pActBand->pTCs[ i2 ].bMerged &&
+ !pActBand->pTCs[ i2 ].bFirstMerged )
+ {
+ nSizCell = nSizCell + pActBand->nWidth[ i2 ];
+ }
+ else
+ break;
+ pActMGroup->nGroupWidth = nSizCell;
+ // <--
+
+ // --> OD 2005-02-03 #118544# - locked previously
+ // created merge groups, after determining the size
+ // for the new merge group.
+ // 1. ggfs. alte Mergegruppe(n) schliessen, die
+ // den von unserer neuen Gruppe betroffenen
+ // X-Bereich ueberdecken
+ short nMGrIdx;
+ while ( FindMergeGroup( nX1, pActMGroup->nGroupWidth,
+ false, nMGrIdx ) )
+ {
+ (*pMergeGroups)[ nMGrIdx ]->bGroupLocked = true;
+ }
+ // <--
+
+ // 3. und in Gruppen-Array eintragen
+ pMergeGroups->Insert(pActMGroup, pMergeGroups->Count());
+ }
+
+ // ggfs. akt. Box zu einer Merge-Gruppe hinzufuegen (dies
+ // kann eine soeben angelegte, oder eine andere Gruppe
+ // sein)
+ UpdateTableMergeGroup( rCell, pActMGroup, pTabBox, i );
+ }
+ }
+ }
+}
+
+//There is a limbo area in word at the end of the row marker
+//where properties can live in word, there is no location in
+//writer equivalent, so try and park the cursor in the best
+//match, see #i23022#/#i18644#
+void WW8TabDesc::ParkPaM()
+{
+ SwTableBox *pTabBox2 = 0;
+ short nRow = nAktRow + 1;
+ if (nRow < pTabLines->Count())
+ {
+ if (SwTableLine *pLine = (*pTabLines)[nRow])
+ {
+ SwTableBoxes &rBoxes = pLine->GetTabBoxes();
+ pTabBox2 = rBoxes.Count() ? rBoxes[0] : 0;
+ }
+ }
+
+ if (!pTabBox2 || !pTabBox2->GetSttNd())
+ {
+ MoveOutsideTable();
+ return;
+ }
+
+ if (pIo->pPaM->GetPoint()->nNode != pTabBox2->GetSttIdx() + 1)
+ {
+ pIo->pPaM->GetPoint()->nNode = pTabBox2->GetSttIdx() + 1;
+ pIo->pPaM->GetPoint()->nContent.Assign(pIo->pPaM->GetCntntNode(), 0);
+ pIo->rDoc.SetTxtFmtColl(*pIo->pPaM, (SwTxtFmtColl*)pIo->pDfltTxtFmtColl);
+ }
+}
+
+void WW8TabDesc::MoveOutsideTable()
+{
+ ASSERT(pTmpPos && pIo, "I've forgotten where the table is anchored");
+ if (pTmpPos && pIo)
+ *pIo->pPaM->GetPoint() = *pTmpPos;
+}
+
+void WW8TabDesc::FinishSwTable()
+{
+ pIo->mpRedlineStack->closeall(*pIo->pPaM->GetPoint());
+ delete pIo->mpRedlineStack;
+ pIo->mpRedlineStack = mpOldRedlineStack;
+ mpOldRedlineStack = 0;
+
+ WW8DupProperties aDup(pIo->rDoc,pIo->pCtrlStck);
+ pIo->pCtrlStck->SetAttr( *pIo->pPaM->GetPoint(), 0, false);
+
+ MoveOutsideTable();
+ delete pTmpPos, pTmpPos = 0;
+
+ aDup.Insert(*pIo->pPaM->GetPoint());
+
+ pIo->bWasTabRowEnd = false;
+ pIo->bWasTabCellEnd = false;
+
+ pIo->maInsertedTables.InsertTable(*pTblNd, *pIo->pPaM);
+
+ MergeCells();
+
+ // falls noetig, zu mergende Zellen gruppenweise zusammenfassen
+ if( pMergeGroups )
+ {
+ // bearbeite alle Merge-Gruppen nacheinander
+ WW8SelBoxInfo* pActMGroup;
+ USHORT nActBoxCount;
+
+ for (USHORT iGr = 0; iGr < pMergeGroups->Count(); ++iGr)
+ {
+ pActMGroup = (*pMergeGroups)[ iGr ];
+ nActBoxCount = pActMGroup->Count();
+
+ if( ( 1 < nActBoxCount ) && pActMGroup && (*pActMGroup)[ 0 ] )
+ {
+ const USHORT nRowSpan = pActMGroup->Count();
+ for (USHORT n = 0; n < nRowSpan; ++n)
+ {
+ SwTableBox* pCurrentBox = (*pActMGroup)[n];
+ const long nRowSpanSet = n == 0 ?
+ nRowSpan :
+ ((-1) * (nRowSpan - n));
+ pCurrentBox->setRowSpan( nRowSpanSet );
+ }
+ }
+ }
+ pIo->pFmtOfJustInsertedApo = 0;
+ DELETEZ( pMergeGroups );
+ }
+}
+
+
+// durchsucht pMergeGroups, meldet Index der ersten, passenden Gruppe bzw. -1
+//
+// Parameter: nXcenter = Mittenposition der anfragenden Box
+// nWidth = Breite der anfragenden Box
+// bExact = Flag, ob Box in dieser Gruppe passen muss,
+// oder diese nur zu tangieren braucht
+//
+bool WW8TabDesc::FindMergeGroup(short nX1, short nWidth, bool bExact,
+ short& nMGrIdx)
+{
+ nMGrIdx = -1;
+ if( pMergeGroups )
+ {
+ // noch als gueltig angesehener Bereich in der Naehe der Grenzen
+ const short nToleranz = 4;
+ // die aktuell untersuchte Gruppe
+ WW8SelBoxInfoPtr pActGroup;
+ // Boxgrenzen
+ short nX2 = nX1 + nWidth;
+ // ungefaehre Gruppengrenzen
+ short nGrX1;
+ short nGrX2;
+
+ // --> OD 2005-02-04 #118544# - improvement: search backwards
+ //for ( USHORT iGr = 0; iGr < pMergeGroups->Count(); iGr++ )
+ for ( short iGr = pMergeGroups->Count() - 1; iGr >= 0; --iGr )
+ {
+ // die aktuell untersuchte Gruppe
+ pActGroup = (*pMergeGroups)[ iGr ];
+ if (!pActGroup->bGroupLocked)
+ {
+ // ungefaehre Gruppengrenzen mit Toleranz nach *aussen* hin
+ nGrX1 = pActGroup->nGroupXStart - nToleranz;
+ nGrX2 = pActGroup->nGroupXStart
+ +pActGroup->nGroupWidth + nToleranz;
+ //
+ // Falls Box reinpasst, melde auf jeden Fall den Erfolg
+ //
+ if( ( nX1 > nGrX1 ) && ( nX2 < nGrX2 ) )
+ {
+ nMGrIdx = iGr; break;
+ }
+ //
+ // hat die Box Bereiche mit der Gruppe gemeinsam?
+ //
+ if( !bExact )
+ {
+ // melde Erfolg, wenn nX1 *oder* nX2 innerhalb der Gruppe liegen
+ if( ( ( nX1 > nGrX1 )
+ && ( nX1 < nGrX2 - 2*nToleranz ) )
+ || ( ( nX2 > nGrX1 + 2*nToleranz )
+ && ( nX2 < nGrX2 ) )
+ // oder nX1 und nX2 die Gruppe umfassen
+ || ( ( nX1 <=nGrX1 )
+ && ( nX2 >=nGrX2 ) ) )
+ {
+ nMGrIdx = iGr; break;
+ }
+ }
+ }
+ }
+ }
+ return ( -1 < nMGrIdx );
+}
+
+bool WW8TabDesc::IsValidCell(short nCol) const
+{
+ return pActBand->bExist[nCol] && (USHORT)nAktRow < pTabLines->Count();
+}
+
+bool WW8TabDesc::InFirstParaInCell() const
+{
+ //e.g. #i19718#
+ if (!pTabBox || !pTabBox->GetSttNd())
+ {
+ ASSERT(false, "Problem with table");
+ return false;
+ }
+
+ if (!IsValidCell(GetAktCol()))
+ return false;
+
+ if (pIo->pPaM->GetPoint()->nNode == pTabBox->GetSttIdx() + 1)
+ return true;
+
+ return false;
+}
+
+void WW8TabDesc::StartMiserableHackForUnsupportedDirection(short nWwCol)
+{
+ ASSERT(pActBand, "Impossible");
+ if (pActBand && pActBand->maDirections[nWwCol] == 3)
+ {
+ pIo->pCtrlStck->NewAttr(*pIo->pPaM->GetPoint(),
+ SvxCharRotateItem(900, false, RES_CHRATR_ROTATE));
+ }
+}
+
+void WW8TabDesc::EndMiserableHackForUnsupportedDirection(short nWwCol)
+{
+ ASSERT(pActBand, "Impossible");
+ if (pActBand && pActBand->maDirections[nWwCol] == 3)
+ pIo->pCtrlStck->SetAttr(*pIo->pPaM->GetPoint(), RES_CHRATR_ROTATE);
+}
+
+bool WW8TabDesc::SetPamInCell(short nWwCol, bool bPam)
+{
+ ASSERT( pActBand, "pActBand ist 0" );
+
+ USHORT nCol = pActBand->nTransCell[nWwCol];
+
+ if ((USHORT)nAktRow >= pTabLines->Count())
+ {
+ ASSERT(!this, "Actual row bigger than expected." );
+ if (bPam)
+ MoveOutsideTable();
+ return false;
+ }
+
+ pTabLine = (*pTabLines)[nAktRow];
+ pTabBoxes = &pTabLine->GetTabBoxes();
+
+ if (nCol >= pTabBoxes->Count())
+ {
+ if (bPam)
+ {
+ // The first paragraph in a cell with upper autospacing has upper
+ // spacing set to 0
+ if (
+ pIo->bParaAutoBefore && pIo->bFirstPara &&
+ !pIo->pWDop->fDontUseHTMLAutoSpacing
+ )
+ {
+ pIo->SetUpperSpacing(*pIo->pPaM, 0);
+ }
+
+ // The last paragraph in a cell with lower autospacing has lower
+ // spacing set to 0
+ if (pIo->bParaAutoAfter && !pIo->pWDop->fDontUseHTMLAutoSpacing)
+ pIo->SetLowerSpacing(*pIo->pPaM, 0);
+
+ ParkPaM();
+ }
+ return false;
+ }
+ pTabBox = (*pTabBoxes)[nCol];
+ if( !pTabBox->GetSttNd() )
+ {
+ ASSERT(pTabBox->GetSttNd(), "Probleme beim Aufbau der Tabelle");
+ if (bPam)
+ MoveOutsideTable();
+ return false;
+ }
+ if (bPam)
+ {
+ pAktWWCell = &pActBand->pTCs[ nWwCol ];
+
+ // The first paragraph in a cell with upper autospacing has upper spacing set to 0
+ if(pIo->bParaAutoBefore && pIo->bFirstPara && !pIo->pWDop->fDontUseHTMLAutoSpacing)
+ pIo->SetUpperSpacing(*pIo->pPaM, 0);
+
+ // The last paragraph in a cell with lower autospacing has lower spacing set to 0
+ if(pIo->bParaAutoAfter && !pIo->pWDop->fDontUseHTMLAutoSpacing)
+ pIo->SetLowerSpacing(*pIo->pPaM, 0);
+
+ //We need to set the pPaM on the first cell, invalid
+ //or not so that we can collect paragraph proproties over
+ //all the cells, but in that case on the valid cell we do not
+ //want to reset the fmt properties
+ if (pIo->pPaM->GetPoint()->nNode != pTabBox->GetSttIdx() + 1)
+ {
+ pIo->pPaM->GetPoint()->nNode = pTabBox->GetSttIdx() + 1;
+ pIo->pPaM->GetPoint()->nContent.Assign(pIo->pPaM->GetCntntNode(), 0);
+ // Zur Sicherheit schon jetzt setzen, da bei den Zellen, die
+ // zum Randausgleich eingefuegt werden, sonst der Style
+ // nicht gesetzt wird.
+ pIo->rDoc.SetTxtFmtColl(*pIo->pPaM, (SwTxtFmtColl*)pIo->pDfltTxtFmtColl);
+ // uebrigens: da diese Zellen unsichtbare Hilfskonstruktionen sind,
+ // und nur dazu dienen, zerfranste Aussehen der WW-Tabelle
+ // nachzuahmen, braucht NICHT SetTxtFmtCollAndListLevel()
+ // verwendet zu werden.
+ }
+
+ // Better to turn Snap to Grid off for all paragraphs in tables
+ if(SwTxtNode *pNd = pIo->pPaM->GetNode()->GetTxtNode())
+ {
+ const SfxPoolItem &rItm = pNd->SwCntntNode::GetAttr(RES_PARATR_SNAPTOGRID);
+ SvxParaGridItem &rSnapToGrid = (SvxParaGridItem&)(rItm);
+
+ if(rSnapToGrid.GetValue())
+ {
+ SvxParaGridItem aGridItem( rSnapToGrid );
+ aGridItem.SetValue(false);
+
+ SwPosition* pGridPos = pIo->pPaM->GetPoint();
+
+ xub_StrLen nEnd = pGridPos->nContent.GetIndex();
+ pGridPos->nContent.Assign(pIo->pPaM->GetCntntNode(), 0);
+ pIo->pCtrlStck->NewAttr(*pGridPos, aGridItem);
+ pGridPos->nContent.Assign(pIo->pPaM->GetCntntNode(), nEnd);
+ pIo->pCtrlStck->SetAttr(*pGridPos, RES_PARATR_SNAPTOGRID);
+ }
+ }
+
+ StartMiserableHackForUnsupportedDirection(nWwCol);
+ }
+ return true;
+}
+
+void WW8TabDesc::InsertCells( short nIns )
+{
+ pTabLine = (*pTabLines)[nAktRow];
+ pTabBoxes = &pTabLine->GetTabBoxes();
+ pTabBox = (*pTabBoxes)[0];
+
+ pIo->rDoc.GetNodes().InsBoxen( pTblNd, pTabLine, (SwTableBoxFmt*)pTabBox->GetFrmFmt(),
+ (SwTxtFmtColl*)pIo->pDfltTxtFmtColl, 0, pTabBoxes->Count(), nIns );
+ // mit dem Dritten Parameter wird das FrmFmt der Boxen angegeben.
+ // hier kann man auch noch optimieren, um FrmFmts zu sparen
+}
+
+void WW8TabDesc::SetTabBorders(SwTableBox* pBox, short nWwIdx)
+{
+ if( nWwIdx < 0 || nWwIdx >= pActBand->nWwCols )
+ return; // kuenstlich erzeugte Zellen -> Kein Rand
+
+
+ SvxBoxItem aFmtBox( RES_BOX );
+ if (pActBand->pTCs) // neither Cell Border nor Default Border defined ?
+ {
+ WW8_TCell* pT = &pActBand->pTCs[nWwIdx];
+ if (pIo->IsBorder(pT->rgbrc))
+ pIo->SetBorder(aFmtBox, pT->rgbrc);
+ }
+
+ if (pActBand->nOverrideSpacing[nWwIdx] & (1 << WW8TabBandDesc::wwTOP))
+ {
+ aFmtBox.SetDistance(
+ pActBand->nOverrideValues[nWwIdx][WW8TabBandDesc::wwTOP],
+ BOX_LINE_TOP);
+ }
+ else
+ aFmtBox.SetDistance(pActBand->mnDefaultTop, BOX_LINE_TOP);
+ if (pActBand->nOverrideSpacing[nWwIdx] & (1 << WW8TabBandDesc::wwBOTTOM))
+ {
+ aFmtBox.SetDistance(
+ pActBand->nOverrideValues[nWwIdx][WW8TabBandDesc::wwBOTTOM],
+ BOX_LINE_BOTTOM);
+ }
+ else
+ aFmtBox.SetDistance(pActBand->mnDefaultBottom,BOX_LINE_BOTTOM);
+
+ // nGapHalf bedeutet bei WW ein *horizontaler* Abstand zwischen
+ // Tabellenzelle und -Inhalt
+ short nLeftDist =
+ pActBand->mbHasSpacing ? pActBand->mnDefaultLeft : pActBand->nGapHalf;
+ short nRightDist =
+ pActBand->mbHasSpacing ? pActBand->mnDefaultRight : pActBand->nGapHalf;
+ if (pActBand->nOverrideSpacing[nWwIdx] & (1 << WW8TabBandDesc::wwLEFT))
+ {
+ aFmtBox.SetDistance(
+ pActBand->nOverrideValues[nWwIdx][WW8TabBandDesc::wwLEFT],
+ BOX_LINE_LEFT);
+ }
+ else
+ aFmtBox.SetDistance(nLeftDist, BOX_LINE_LEFT);
+ if (pActBand->nOverrideSpacing[nWwIdx] & (1 << WW8TabBandDesc::wwRIGHT))
+ {
+ aFmtBox.SetDistance(
+ pActBand->nOverrideValues[nWwIdx][WW8TabBandDesc::wwRIGHT],
+ BOX_LINE_RIGHT);
+ }
+ else
+ aFmtBox.SetDistance(nRightDist,BOX_LINE_RIGHT);
+
+ pBox->GetFrmFmt()->SetFmtAttr(aFmtBox);
+}
+
+void WW8TabDesc::SetTabShades( SwTableBox* pBox, short nWwIdx )
+{
+ if( nWwIdx < 0 || nWwIdx >= pActBand->nWwCols )
+ return; // kuenstlich erzeugte Zellen -> Keine Farbe
+
+ bool bFound=false;
+ if (pActBand->pNewSHDs && pActBand->pNewSHDs[nWwIdx] != COL_AUTO)
+ {
+ Color aColor(pActBand->pNewSHDs[nWwIdx]);
+ if (aColor.GetColor() == 0x00333333)
+ pIo->maTracer.Log(sw::log::eAutoColorBg);
+ pBox->GetFrmFmt()->SetFmtAttr(SvxBrushItem(aColor, RES_BACKGROUND));
+ bFound = true;
+ }
+
+ //If there was no new shades, or no new shade setting
+ if (pActBand->pSHDs && !bFound)
+ {
+ WW8_SHD& rSHD = pActBand->pSHDs[nWwIdx];
+ if (!rSHD.GetValue()) // auto
+ return;
+
+ SwWW8Shade aSh( pIo->bVer67, rSHD );
+ pBox->GetFrmFmt()->SetFmtAttr(SvxBrushItem(aSh.aColor, RES_BACKGROUND));
+ }
+}
+
+SvxFrameDirection MakeDirection(sal_uInt16 nCode, BOOL bIsBiDi)
+{
+ SvxFrameDirection eDir = FRMDIR_ENVIRONMENT;
+ // 1: Asian layout with rotated CJK characters
+ // 5: Asian layout
+ // 3: Western layout rotated by 90 degrees
+ // 4: Western layout
+ switch (nCode)
+ {
+ default:
+ ASSERT(eDir == 4, "unknown direction code, maybe its a bitfield");
+ case 3:
+ // --> FME/Alan Yaniger: 2006-09-15 #i38158# Consider RTL tables:
+ eDir = bIsBiDi ? FRMDIR_HORI_RIGHT_TOP : FRMDIR_HORI_LEFT_TOP;
+ // <--
+ break;
+ case 5:
+ eDir = FRMDIR_VERT_TOP_RIGHT;
+ break;
+ case 1:
+ eDir = FRMDIR_VERT_TOP_RIGHT;
+ break;
+ case 4:
+ // --> FME/Alan Yaniger: 2006-09-15 #i38158# Consider RTL tables:
+ eDir = bIsBiDi ? FRMDIR_HORI_RIGHT_TOP : FRMDIR_HORI_LEFT_TOP;
+ // <--
+ break;
+ }
+ return eDir;
+}
+
+void WW8TabDesc::SetTabDirection(SwTableBox* pBox, short nWwIdx)
+{
+ if (nWwIdx < 0 || nWwIdx >= pActBand->nWwCols)
+ return;
+ SvxFrameDirectionItem aItem(MakeDirection(pActBand->maDirections[nWwIdx], bIsBiDi), RES_FRAMEDIR);
+ pBox->GetFrmFmt()->SetFmtAttr(aItem);
+}
+
+void WW8TabDesc::SetTabVertAlign( SwTableBox* pBox, short nWwIdx )
+{
+ if( nWwIdx < 0 || nWwIdx >= pActBand->nWwCols )
+ return;
+
+ sal_Int16 eVertOri=text::VertOrientation::TOP;
+
+ if( pActBand->pTCs )
+ {
+ WW8_TCell* pT = &pActBand->pTCs[nWwIdx];
+ switch (pT->nVertAlign)
+ {
+ case 0:
+ default:
+ eVertOri = text::VertOrientation::TOP;
+ break;
+ case 1:
+ eVertOri = text::VertOrientation::CENTER;
+ break;
+ case 2:
+ eVertOri = text::VertOrientation::BOTTOM;
+ break;
+ }
+ }
+
+ pBox->GetFrmFmt()->SetFmtAttr( SwFmtVertOrient(0,eVertOri) );
+}
+
+void WW8TabDesc::AdjustNewBand()
+{
+ if( pActBand->nSwCols > nDefaultSwCols ) // Zellen splitten
+ InsertCells( pActBand->nSwCols - nDefaultSwCols );
+
+ SetPamInCell( 0, false);
+ ASSERT( pTabBoxes && pTabBoxes->Count() == (USHORT)pActBand->nSwCols,
+ "Falsche Spaltenzahl in Tabelle" )
+
+ if( bClaimLineFmt )
+ {
+ pTabLine->ClaimFrmFmt(); // noetig wg. Zeilenhoehe
+ SwFmtFrmSize aF( ATT_MIN_SIZE, 0, 0 ); // default
+
+ if (pActBand->nLineHeight == 0) // 0 = Auto
+ aF.SetHeightSizeType( ATT_VAR_SIZE );
+ else
+ {
+ if (pActBand->nLineHeight < 0) // Pos = min, Neg = exakt
+ {
+ aF.SetHeightSizeType(ATT_FIX_SIZE);
+ pActBand->nLineHeight = -pActBand->nLineHeight;
+ }
+ if (pActBand->nLineHeight < MINLAY) // nicht erlaubte Zeilenhoehe
+ pActBand->nLineHeight = MINLAY;
+
+ aF.SetHeight(pActBand->nLineHeight);// Min- / Exakt-Hoehe setzen
+ }
+ pTabLine->GetFrmFmt()->SetFmtAttr(aF);
+ }
+
+ //Word stores 1 for bCantSplit if the row cannot be split, we set true if
+ //we can split the row
+ // bCantSplit: Always true for rows containing merged cells (Word <= 2000 crashes otherwise)
+ // So in case bCantSplit is true, we check for bCantSplit90, which has been introduced for
+ // Word versions >= 2002.
+ bool bSetCantSplit = pActBand->bCantSplit;
+ if(bSetCantSplit)
+ bSetCantSplit = pActBand->bCantSplit90;
+
+ pTabLine->GetFrmFmt()->SetFmtAttr(SwFmtRowSplit(!bSetCantSplit));
+
+ short i; // SW-Index
+ short j; // WW-Index
+ short nW; // Breite
+ SwFmtFrmSize aFS( ATT_FIX_SIZE );
+ j = pActBand->bLEmptyCol ? -1 : 0;
+
+ for( i = 0; i < pActBand->nSwCols; i++ )
+ {
+ // setze Zellenbreite
+ if( j < 0 )
+ nW = pActBand->nCenter[0] - nMinLeft;
+ else
+ {
+ //Set j to first non invalid cell
+ while ((j < pActBand->nWwCols) && (!pActBand->bExist[j]))
+ j++;
+
+ if( j < pActBand->nWwCols )
+ nW = pActBand->nCenter[j+1] - pActBand->nCenter[j];
+ else
+ nW = nMaxRight - pActBand->nCenter[j];
+ pActBand->nWidth[ j ] = nW;
+ }
+
+ SwTableBox* pBox = (*pTabBoxes)[i];
+ // liesse sich durch intelligentes Umhaengen der FrmFmts noch weiter
+ // verringern
+ pBox->ClaimFrmFmt();
+
+ SetTabBorders(pBox, j);
+
+ // #i18128# word has only one line between adjoining vertical cells
+ // we have to mimick this in the filter by picking the larger of the
+ // sides and using that one on one side of the line (right)
+ SvxBoxItem aCurrentBox(sw::util::ItemGet<SvxBoxItem>(*(pBox->GetFrmFmt()), RES_BOX));
+ const SvxBorderLine *pLeftLine = aCurrentBox.GetLine(BOX_LINE_LEFT);
+ int nCurrentRightLineWidth = 0;
+ if(pLeftLine)
+ nCurrentRightLineWidth = pLeftLine->GetInWidth() + pLeftLine->GetOutWidth() + pLeftLine->GetDistance();
+
+ if (i != 0)
+ {
+ SwTableBox* pBox2 = (*pTabBoxes)[i-1];
+ SvxBoxItem aOldBox(sw::util::ItemGet<SvxBoxItem>(*(pBox2->GetFrmFmt()), RES_BOX));
+ const SvxBorderLine *pRightLine = aOldBox.GetLine(BOX_LINE_RIGHT);
+ int nOldBoxRightLineWidth = 0;
+ if(pRightLine)
+ nOldBoxRightLineWidth = pRightLine->GetInWidth() + pRightLine->GetOutWidth() + pRightLine->GetDistance();
+
+ if(nOldBoxRightLineWidth>nCurrentRightLineWidth)
+ aCurrentBox.SetLine(aOldBox.GetLine(BOX_LINE_RIGHT), BOX_LINE_LEFT);
+
+ aOldBox.SetLine(0, BOX_LINE_RIGHT);
+ pBox2->GetFrmFmt()->SetFmtAttr(aOldBox);
+ }
+
+ pBox->GetFrmFmt()->SetFmtAttr(aCurrentBox);
+
+ SetTabVertAlign(pBox, j);
+ SetTabDirection(pBox, j);
+ if( pActBand->pSHDs || pActBand->pNewSHDs)
+ SetTabShades(pBox, j);
+ j++;
+
+ aFS.SetWidth( nW );
+ pBox->GetFrmFmt()->SetFmtAttr( aFS );
+
+ // ueberspringe nicht existente Zellen
+ while( ( j < pActBand->nWwCols ) && !pActBand->bExist[j] )
+ {
+ pActBand->nWidth[j] = pActBand->nCenter[j+1] - pActBand->nCenter[j];
+ j++;
+ }
+ }
+}
+
+void WW8TabDesc::TableCellEnd()
+{
+ ::SetProgressState(pIo->nProgress, pIo->mpDocShell); // Update
+
+ EndMiserableHackForUnsupportedDirection(nAktCol);
+
+ // neue Zeile
+ if( pIo->bWasTabRowEnd )
+ {
+ // bWasTabRowEnd will be deactivated in
+ // SwWW8ImplReader::ProcessSpecial()
+
+ USHORT iCol = GetLogicalWWCol();
+ if (iCol < aNumRuleNames.size())
+ {
+ aNumRuleNames.erase(aNumRuleNames.begin() + iCol,
+ aNumRuleNames.end());
+ }
+
+ nAktCol = 0;
+ nAktRow++;
+ nAktBandRow++;
+ ASSERT( pActBand , "pActBand ist 0" );
+ if( pActBand )
+ {
+ if( nAktRow >= nRows ) // am Tabellenende gibt's nichts sinnvolles
+ return; // mehr zu tun
+
+ bool bNewBand = nAktBandRow >= pActBand->nRows;
+ if( bNewBand )
+ { // neues Band noetig ?
+ pActBand = pActBand->pNextBand; //
+ nAktBandRow = 0;
+ ASSERT( pActBand, "pActBand ist 0" );
+ AdjustNewBand();
+ }
+ else
+ {
+ SwTableBox* pBox = (*pTabBoxes)[0];
+ SwSelBoxes aBoxes;
+ pIo->rDoc.InsertRow( pTable->SelLineFromBox( pBox, aBoxes ) );
+ }
+ }
+ }
+ else
+ { // neue Spalte ( Zelle )
+ nAktCol++;
+ }
+ SetPamInCell(nAktCol, true);
+
+ // finish Annotated Level Numbering ?
+ if (pIo->bAnl && !pIo->bAktAND_fNumberAcross)
+ pIo->StopAllAnl(IsValidCell(nAktCol));
+}
+
+// ggfs. die Box in fuer diese Col offene Merge-Gruppe eintragen
+SwTableBox* WW8TabDesc::UpdateTableMergeGroup( WW8_TCell& rCell,
+ WW8SelBoxInfo* pActGroup,
+ SwTableBox* pActBox,
+ USHORT nCol )
+{
+ // Rueckgabewert defaulten
+ SwTableBox* pResult = 0;
+
+ // pruefen, ob die Box zu mergen ist
+ // --> OD 2005-02-04 #118544# - If cell is the first one to be merged,
+ // a new merge group has to be provided.
+ // E.g., it could be that a cell is the first one to be merged, but no
+ // new merge group is provided, because the potential other cell to be merged
+ // doesn't exist - see method <WW8TabDesc::MergeCells>.
+ if ( pActBand->bExist[ nCol ] &&
+ ( ( rCell.bFirstMerged && pActGroup ) ||
+ rCell.bMerged ||
+ rCell.bVertMerge ||
+ rCell.bVertRestart ) )
+ // <--
+ {
+ // passende Merge-Gruppe ermitteln
+ WW8SelBoxInfo* pTheMergeGroup = 0;
+ if( pActGroup )
+ // Gruppe uebernehmen
+ pTheMergeGroup = pActGroup;
+ else
+ {
+ // Gruppe finden
+ short nMGrIdx;
+ if( FindMergeGroup( pActBand->nCenter[ nCol ],
+ pActBand->nWidth[ nCol ], true, nMGrIdx ) )
+ pTheMergeGroup = (*pMergeGroups)[ nMGrIdx ];
+ }
+ if( pTheMergeGroup )
+ {
+ // aktuelle Box der Merge-Gruppe hinzufuegen
+ pTheMergeGroup->Insert( pActBox, pTheMergeGroup->Count() );
+
+ // Target-Box zurueckmelden
+ pResult = (*pTheMergeGroup)[ 0 ];
+ }
+ }
+ return pResult;
+}
+
+
+USHORT WW8TabDesc::GetLogicalWWCol() const // returns number of col as INDICATED within WW6 UI status line -1
+{
+ USHORT nCol = 0;
+ if( pActBand && pActBand->pTCs)
+ {
+ for( USHORT iCol = 1; iCol <= nAktCol; ++iCol )
+ {
+ if( !pActBand->pTCs[ iCol-1 ].bMerged )
+ ++nCol;
+ }
+ }
+ return nCol;
+}
+
+// find name of numrule valid for current WW-COL
+const String& WW8TabDesc::GetNumRuleName() const
+{
+ USHORT nCol = GetLogicalWWCol();
+ if (nCol < aNumRuleNames.size())
+ return aNumRuleNames[nCol];
+ else
+ return aEmptyStr;
+}
+
+void WW8TabDesc::SetNumRuleName( const String& rName )
+{
+ USHORT nCol = GetLogicalWWCol();
+ for (USHORT nSize = static_cast< USHORT >(aNumRuleNames.size()); nSize <= nCol; ++nSize)
+ aNumRuleNames.push_back(aEmptyStr);
+ aNumRuleNames[nCol] = rName;
+}
+
+bool SwWW8ImplReader::StartTable(WW8_CP nStartCp)
+{
+ // Entering a table so make sure the the FirstPara flag gets set
+ bFirstPara = true;
+ // keine rekursiven Tabellen Nicht bei EinfuegenDatei in Tabelle oder
+ // Fussnote
+ if (bReadNoTbl)
+ return false;
+
+ if (pTableDesc)
+ maTableStack.push(pTableDesc);
+
+ // --> OD 2005-01-27 #i33818# - determine absolute position object attributes,
+ // if possible. It's needed for nested tables.
+ WW8FlyPara* pTableWFlyPara( 0L );
+ WW8SwFlyPara* pTableSFlyPara( 0L );
+ // --> OD 2005-03-21 #i45301# - anchor nested table inside Writer fly frame
+ // only at-character, if absolute position object attributes are available.
+ // Thus, default anchor type is as-character anchored.
+ RndStdIds eAnchor( FLY_IN_CNTNT );
+ // <--
+ if ( nInTable )
+ {
+ WW8_TablePos* pNestedTabPos( 0L );
+ WW8_TablePos aNestedTabPos;
+ WW8PLCFxSave1 aSave;
+ pPlcxMan->GetPap()->Save( aSave );
+ WW8PLCFx_Cp_FKP* pPap = pPlcxMan->GetPapPLCF();
+ WW8_CP nMyStartCp = nStartCp;
+ if ( SearchRowEnd( pPap, nMyStartCp, nInTable ) &&
+ ParseTabPos( &aNestedTabPos, pPap ) )
+ {
+ pNestedTabPos = &aNestedTabPos;
+ }
+ pPlcxMan->GetPap()->Restore( aSave );
+ if ( pNestedTabPos )
+ {
+ ApoTestResults aApo = TestApo( nInTable + 1, false, pNestedTabPos );
+ pTableWFlyPara = ConstructApo( aApo, pNestedTabPos );
+ if ( pTableWFlyPara )
+ {
+ // --> OD 2007-07-03 #148498#
+ // <WW8SwFlyPara> constructor has changed - new 4th parameter
+ // containing WW8 page top margin.
+ pTableSFlyPara = new WW8SwFlyPara(*pPaM, *this, *pTableWFlyPara,
+ maSectionManager.GetWWPageTopMargin(),
+ maSectionManager.GetPageLeft(), maSectionManager.GetTextAreaWidth(),
+ nIniFlyDx, nIniFlyDy);
+ // <--
+ // --> OD 2005-03-21 #i45301# - anchor nested table Writer fly
+ // frame at-character
+ eAnchor = FLY_AUTO_CNTNT;
+ // <--
+ }
+ }
+ }
+ // <--
+
+ pTableDesc = new WW8TabDesc( this, nStartCp );
+
+ if( pTableDesc->Ok() )
+ {
+ int nNewInTable = nInTable + 1;
+ if (InEqualApo(nNewInTable))
+ {
+ ASSERT(pSFlyPara->pFlyFmt,
+ "how could we be in a local apo and have no apo");
+ }
+
+ if ( eAnchor == FLY_AUTO_CNTNT && !maTableStack.empty() && !InEqualApo(nNewInTable) )
+ {
+ pTableDesc->pParentPos = new SwPosition(*pPaM->GetPoint());
+ SfxItemSet aItemSet(rDoc.GetAttrPool(),
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1);
+ // --> OD 2005-01-26 #i33818# - anchor the Writer fly frame for
+ // the nested table at-character.
+ // --> OD 2005-03-21 #i45301#
+ SwFmtAnchor aAnchor( eAnchor );
+ aAnchor.SetAnchor( pTableDesc->pParentPos );
+ aItemSet.Put( aAnchor );
+ pTableDesc->pFlyFmt = rDoc.MakeFlySection( eAnchor,
+ pTableDesc->pParentPos, &aItemSet);
+ ASSERT( pTableDesc->pFlyFmt->GetAnchor().GetAnchorId() == eAnchor,
+ "Not the anchor type requested!" );
+ // <--
+ MoveInsideFly(pTableDesc->pFlyFmt);
+ }
+ pTableDesc->CreateSwTable();
+ if (pTableDesc->pFlyFmt)
+ {
+ pTableDesc->SetSizePosition(pTableDesc->pFlyFmt);
+ // --> OD 2005-01-26 #i33818# - Use absolute position object
+ // attributes, if existing, and apply them to the created Writer fly
+ // frame.
+ if ( pTableWFlyPara && pTableSFlyPara )
+ {
+ WW8FlySet aFlySet( *this, pTableWFlyPara, pTableSFlyPara, false );
+ SwFmtAnchor aAnchor( FLY_AUTO_CNTNT );
+ aAnchor.SetAnchor( pTableDesc->pParentPos );
+ aFlySet.Put( aAnchor );
+ pTableDesc->pFlyFmt->SetFmtAttr( aFlySet );
+ }
+ else
+ {
+ SwFmtHoriOrient aHori =
+ pTableDesc->pTable->GetFrmFmt()->GetHoriOrient();
+ pTableDesc->pFlyFmt->SetFmtAttr(aHori);
+ pTableDesc->pFlyFmt->SetFmtAttr( SwFmtSurround( SURROUND_NONE ) );
+ }
+ // <--
+ // --> OD 2005-01-27 #i33818# - The nested table doesn't have to leave
+ // the table cell. Thus, the Writer fly frame has to follow the text flow.
+ pTableDesc->pFlyFmt->SetFmtAttr( SwFmtFollowTextFlow( TRUE ) );
+ // <--
+ }
+ else
+ pTableDesc->SetSizePosition(0);
+ pTableDesc->UseSwTable();
+ }
+ else
+ PopTableDesc();
+
+ // --> OD 2005-01-28 #i33818#
+ delete pTableWFlyPara;
+ delete pTableSFlyPara;
+ // <--
+
+ bool bSuccess = (0 != pTableDesc);
+ if (bSuccess)
+ {
+ maTracer.EnterEnvironment(sw::log::eTable, rtl::OUString::valueOf(
+ static_cast<sal_Int32>(maTableStack.size())));
+ }
+ return bSuccess;
+}
+
+bool lcl_PamContainsFly(SwPaM & rPam)
+{
+ bool bResult = false;
+ SwNodeRange aRg( rPam.Start()->nNode, rPam.End()->nNode );
+ SwDoc * pDoc = rPam.GetDoc();
+
+ sal_uInt16 n = 0;
+ SwSpzFrmFmts * pSpzFmts = pDoc->GetSpzFrmFmts();
+ sal_uInt16 nCount = pSpzFmts->Count();
+ while (!bResult && n < nCount)
+ {
+ SwFrmFmt* pFly = (*pSpzFmts)[n];
+ const SwFmtAnchor* pAnchor = &pFly->GetAnchor();
+
+ switch (pAnchor->GetAnchorId())
+ {
+ case FLY_AT_CNTNT:
+ case FLY_AUTO_CNTNT:
+ {
+ const SwPosition* pAPos = pAnchor->GetCntntAnchor();
+
+ if (pAPos != NULL &&
+ aRg.aStart <= pAPos->nNode &&
+ pAPos->nNode <= aRg.aEnd)
+ {
+ bResult = true;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ ++n;
+ }
+
+ return bResult;
+}
+
+void SwWW8ImplReader::TabCellEnd()
+{
+ if (nInTable && pTableDesc)
+ {
+ pTableDesc->TableCellEnd();
+
+ if (bReadTable
+ && pWFlyPara == NULL
+ && mpTableEndPaM.get() != NULL
+ && (! SwPaM::Overlap(*pPaM, *mpTableEndPaM))
+ && SwPaM::LessThan(*mpTableEndPaM, *pPaM)
+ && mpTableEndPaM->GetPoint()->nNode.GetNode().IsTxtNode()
+ && !lcl_PamContainsFly(*mpTableEndPaM)
+ )
+ {
+ rDoc.DelFullPara(*mpTableEndPaM);
+ }
+ }
+
+ bFirstPara = true; // We have come to the end of a cell so FirstPara flag
+ bReadTable = false;
+ mpTableEndPaM.reset();
+}
+
+void SwWW8ImplReader::Read_TabCellEnd( USHORT, const BYTE* pData, short nLen)
+{
+ if( ( nLen > 0 ) && ( *pData == 1 ) )
+ bWasTabCellEnd = true;
+}
+
+void SwWW8ImplReader::Read_TabRowEnd( USHORT, const BYTE* pData, short nLen ) // Sprm25
+{
+ if( ( nLen > 0 ) && ( *pData == 1 ) )
+ bWasTabRowEnd = true;
+}
+
+void SwWW8ImplReader::PopTableDesc()
+{
+ if (pTableDesc && pTableDesc->pFlyFmt)
+ {
+ MoveOutsideFly(pTableDesc->pFlyFmt,*pTableDesc->pParentPos);
+ }
+
+ delete pTableDesc;
+ if (maTableStack.empty())
+ pTableDesc = 0;
+ else
+ {
+ pTableDesc = maTableStack.top();
+ maTableStack.pop();
+ }
+}
+
+void SwWW8ImplReader::StopTable()
+{
+ maTracer.LeaveEnvironment(sw::log::eTable);
+
+ ASSERT(pTableDesc, "Panic, stop table with no table!");
+ if (!pTableDesc)
+ return;
+
+ // We are leaving a table so make sure the next paragraph doesn't think
+ // it's the first paragraph
+ bFirstPara = false;
+
+ pTableDesc->FinishSwTable();
+ PopTableDesc();
+
+ if (!maTableStack.empty())
+ {
+ maTracer.EnterEnvironment(sw::log::eTable, rtl::OUString::valueOf(
+ static_cast<sal_Int32>(maTableStack.size())));
+ }
+
+ bReadTable = true;
+ // --> OD 2009-04-16 #i101116#
+ // Keep PaM on table end only for nested tables
+ if ( nInTable > 1 )
+ {
+ mpTableEndPaM.reset(new SwPaM(*pPaM));
+ }
+ // <--
+}
+
+// GetTableLeft() wird fuer absatzgebundene Grafikobjekte in Tabellen
+// gebraucht.
+// WW nimmt bei eingerueckten Tabellen den Absatzrand, der ohne Tabelle
+// gueltig waere, als Basis; SW benutzt den linken Tabellenrand.
+short SwWW8ImplReader::GetTableLeft()
+{
+ return (pTableDesc) ? pTableDesc->GetMinLeft() : 0;
+}
+
+bool SwWW8ImplReader::IsInvalidOrToBeMergedTabCell() const
+{
+ if( !pTableDesc )
+ return false;
+
+ const WW8_TCell* pCell = pTableDesc->GetAktWWCell();
+
+ return !pTableDesc->IsValidCell( pTableDesc->GetAktCol() )
+ || ( pCell
+ && ( !pCell->bFirstMerged
+ && ( pCell->bMerged
+ || ( pCell->bVertMerge
+ && !pCell->bVertRestart
+ )
+ )
+ )
+ );
+}
+
+USHORT SwWW8ImplReader::StyleUsingLFO( USHORT nLFOIndex ) const
+{
+ USHORT nRes = USHRT_MAX;
+ if( pCollA )
+ {
+ for(USHORT nI = 0; nI < pStyles->GetCount(); nI++ )
+ if( pCollA[ nI ].bValid
+ && (nLFOIndex == pCollA[ nI ].nLFOIndex) )
+ nRes = nI;
+ }
+ return nRes;
+}
+
+const SwFmt* SwWW8ImplReader::GetStyleWithOrgWWName( String& rName ) const
+{
+ SwFmt* pRet = 0;
+ if( pCollA )
+ {
+ for(USHORT nI = 0; nI < pStyles->GetCount(); nI++ )
+ if( pCollA[ nI ].bValid
+ && (rName.Equals( pCollA[ nI ].GetOrgWWName())) )
+ {
+ pRet = pCollA[ nI ].pFmt;
+ break;
+ }
+ }
+ return pRet;
+}
+
+//-----------------------------------------
+// class WW8RStyle
+//-----------------------------------------
+
+const BYTE* WW8RStyle::HasParaSprm( USHORT nId ) const
+{
+ if( !pParaSprms || !nSprmsLen )
+ return 0;
+
+ const BYTE* pSprms = pParaSprms;
+ USHORT i, x;
+
+ for( i=0; i < nSprmsLen; )
+ {
+ USHORT nAktId = maSprmParser.GetSprmId(pSprms);
+ // Sprm found ?
+ if( nAktId == nId )
+ return pSprms + maSprmParser.DistanceToData(nId);
+
+ x = maSprmParser.GetSprmSize(nAktId, pSprms);
+ i = i + x;
+ pSprms += x;
+ }
+ return 0; // Sprm not found
+}
+
+void WW8RStyle::ImportSprms(BYTE *pSprms, short nLen, bool bPap)
+{
+ if (!nLen)
+ return;
+
+ if( bPap )
+ {
+ pParaSprms = pSprms; // fuer HasParaSprms()
+ nSprmsLen = nLen;
+ }
+
+ while ( nLen > 0 )
+ {
+ USHORT nL1 = pIo->ImportSprm(pSprms);
+ nLen = nLen - nL1;
+ pSprms += nL1;
+ }
+
+ pParaSprms = 0;
+ nSprmsLen = 0;
+}
+
+void WW8RStyle::ImportSprms(sal_Size nPosFc, short nLen, bool bPap)
+{
+ if (!nLen)
+ return;
+
+ BYTE *pSprms = new BYTE[nLen];
+
+ pStStrm->Seek(nPosFc);
+ pStStrm->Read(pSprms, nLen);
+
+ ImportSprms(pSprms, nLen, bPap);
+
+ delete[] pSprms;
+}
+
+static inline short WW8SkipOdd(SvStream* pSt )
+{
+ if ( pSt->Tell() & 0x1 )
+ {
+ UINT8 c;
+ pSt->Read( &c, 1 );
+ return 1;
+ }
+ return 0;
+}
+
+static inline short WW8SkipEven(SvStream* pSt )
+{
+ if (!(pSt->Tell() & 0x1))
+ {
+ UINT8 c;
+ pSt->Read( &c, 1 );
+ return 1;
+ }
+ return 0;
+}
+
+short WW8RStyle::ImportUPX(short nLen, bool bPAP, bool bOdd)
+{
+ INT16 cbUPX;
+
+ if( 0 < nLen ) // Empty ?
+ {
+ if (bOdd)
+ nLen = nLen - WW8SkipEven( pStStrm );
+ else
+ nLen = nLen - WW8SkipOdd( pStStrm );
+
+ *pStStrm >> cbUPX;
+
+ nLen-=2;
+
+ if ( cbUPX > nLen )
+ cbUPX = nLen; // !cbUPX auf nLen verkleinert!
+
+ if( (1 < cbUPX) || ( (0 < cbUPX) && !bPAP ) )
+ {
+ if( bPAP )
+ {
+ UINT16 id;
+ *pStStrm >> id;
+
+ cbUPX-= 2;
+ nLen-= 2;
+ }
+
+ if( 0 < cbUPX )
+ {
+ sal_Size nPos = pStStrm->Tell(); // falls etwas falsch interpretiert
+ // wird, gehts danach wieder richtig
+ ImportSprms( nPos, cbUPX, bPAP );
+
+ if ( pStStrm->Tell() != nPos + cbUPX )
+ pStStrm->Seek( nPos+cbUPX );
+
+ nLen = nLen - cbUPX;
+ }
+ }
+ }
+ return nLen;
+}
+
+void WW8RStyle::ImportGrupx(short nLen, bool bPara, bool bOdd)
+{
+ if( nLen <= 0 )
+ return;
+ if (bOdd)
+ nLen = nLen - WW8SkipEven( pStStrm );
+ else
+ nLen = nLen - WW8SkipOdd( pStStrm );
+
+ if( bPara ) // Grupx.Papx
+ nLen = ImportUPX(nLen, true, bOdd);
+ ImportUPX(nLen, false, bOdd); // Grupx.Chpx
+}
+
+WW8RStyle::WW8RStyle(WW8Fib& _rFib, SwWW8ImplReader* pI)
+ : WW8Style(*pI->pTableStream, _rFib), maSprmParser(_rFib.GetFIBVersion()),
+ pIo(pI), pStStrm(pI->pTableStream), pStyRule(0), nWwNumLevel(0)
+{
+ pIo->pCollA = new SwWW8StyInf[ cstd ]; // Style-UEbersetzung WW->SW
+ pIo->nColls = cstd;
+}
+
+void WW8RStyle::Set1StyleDefaults()
+{
+ if (!bCJKFontChanged) // Style no CJK Font? set the default
+ pIo->SetNewFontAttr(ftcStandardChpCJKStsh, true, RES_CHRATR_CJK_FONT);
+
+ // see i25247
+ const WW8_FFN* pF = pIo->pFonts->GetFont(3);
+ if (pF)
+ {
+ rtl_TextEncoding eEnc = WW8Fib::GetFIBCharset(pF->chs);
+ if ((ftcStandardChpCTLStsh == 0) && (eEnc == RTL_TEXTENCODING_MS_1255))
+ ftcStandardChpCTLStsh = 3;
+ }
+
+ if (ftcStandardChpCJKStsh == 0)
+ ftcStandardChpCJKStsh = 2;
+
+ if (!bCTLFontChanged) // Style no CTL Font? set the default
+ pIo->SetNewFontAttr(ftcStandardChpCTLStsh, true, RES_CHRATR_CTL_FONT);
+
+ //#88976# western 2nd to make western charset conversion the default
+ if (!bFontChanged) // Style has no Font? set the default,
+ {
+ pIo->SetNewFontAttr(ftcStandardChpStsh, true, RES_CHRATR_FONT);
+ /* removed by a patch from cmc for #i52786#
+ if (pIo->bVer67)
+ SetStyleCharSet(pIo->pCollA[pIo->nAktColl]);
+ */
+ }
+
+ if( !pIo->bNoAttrImport )
+ {
+ // Style has no text color set, winword default is auto
+ if ( !bTxtColChanged )
+ pIo->pAktColl->SetFmtAttr(SvxColorItem(Color(COL_AUTO), RES_CHRATR_COLOR));
+
+ // Style has no FontSize ? WinWord Default is 10pt for western and asian
+ if( !bFSizeChanged )
+ {
+ SvxFontHeightItem aAttr(200, 100, RES_CHRATR_FONTSIZE);
+ pIo->pAktColl->SetFmtAttr(aAttr);
+ aAttr.SetWhich(RES_CHRATR_CJK_FONTSIZE);
+ pIo->pAktColl->SetFmtAttr(aAttr);
+ }
+
+ // Style has no FontSize ? WinWord Default is 10pt for western and asian
+ if( !bFCTLSizeChanged )
+ {
+ SvxFontHeightItem aAttr(200, 100, RES_CHRATR_FONTSIZE);
+ aAttr.SetWhich(RES_CHRATR_CTL_FONTSIZE);
+ pIo->pAktColl->SetFmtAttr(aAttr);
+ }
+
+ if( pIo->pWDop->fWidowControl && !bWidowsChanged ) // Widows ?
+ {
+ pIo->pAktColl->SetFmtAttr( SvxWidowsItem( 2, RES_PARATR_WIDOWS ) );
+ pIo->pAktColl->SetFmtAttr( SvxOrphansItem( 2, RES_PARATR_ORPHANS ) );
+ }
+ }
+}
+
+bool WW8RStyle::PrepareStyle(SwWW8StyInf &rSI, ww::sti eSti, sal_uInt16 nThisStyle, sal_uInt16 nNextStyle)
+{
+ SwFmt* pColl;
+ bool bStyExist;
+ if (rSI.bColl)
+ {
+ // Para-Style
+ sw::util::ParaStyleMapper::StyleResult aResult =
+ pIo->maParaStyleMapper.GetStyle(rSI.GetOrgWWName(), eSti);
+ pColl = aResult.first;
+ bStyExist = aResult.second;
+ }
+ else
+ {
+ // Char-Style
+ sw::util::CharStyleMapper::StyleResult aResult =
+ pIo->maCharStyleMapper.GetStyle(rSI.GetOrgWWName(), eSti);
+ pColl = aResult.first;
+ bStyExist = aResult.second;
+ }
+
+ bool bImport = !bStyExist || pIo->mbNewDoc; // Inhalte Importieren ?
+ bool bOldNoImp = pIo->bNoAttrImport;
+ rSI.bImportSkipped = !bImport;
+
+ if( !bImport )
+ pIo->bNoAttrImport = true;
+ else
+ {
+ if (bStyExist)
+ {
+ // --> OD 2007-01-25 #i73790# - method renamed
+ pColl->ResetAllFmtAttr();
+ // <--
+ }
+ pColl->SetAuto(false); // nach Empfehlung JP
+ } // macht die UI aber anders
+ pIo->pAktColl = pColl;
+ rSI.pFmt = pColl; // UEbersetzung WW->SW merken
+ rSI.bImportSkipped = !bImport;
+
+ // Set Based on style
+ USHORT j = rSI.nBase;
+ if (j != nThisStyle && j < cstd )
+ {
+ SwWW8StyInf* pj = &pIo->pCollA[j];
+ if (rSI.pFmt && pj->pFmt && rSI.bColl == pj->bColl)
+ {
+ rSI.pFmt->SetDerivedFrom( pj->pFmt ); // ok, Based on eintragen
+ rSI.eLTRFontSrcCharSet = pj->eLTRFontSrcCharSet;
+ rSI.eRTLFontSrcCharSet = pj->eRTLFontSrcCharSet;
+ rSI.eCJKFontSrcCharSet = pj->eCJKFontSrcCharSet;
+ rSI.n81Flags = pj->n81Flags;
+ rSI.n81BiDiFlags = pj->n81BiDiFlags;
+ rSI.nOutlineLevel = pj->nOutlineLevel;
+ rSI.bParaAutoBefore = pj->bParaAutoBefore;
+ rSI.bParaAutoAfter = pj->bParaAutoAfter;
+
+ if (pj->pWWFly)
+ rSI.pWWFly = new WW8FlyPara(pIo->bVer67, pj->pWWFly);
+ }
+ }
+ else if( pIo->mbNewDoc && bStyExist )
+ rSI.pFmt->SetDerivedFrom(0);
+
+ rSI.nFollow = nNextStyle; // Follow merken
+
+ pStyRule = 0; // falls noetig, neu anlegen
+ bTxtColChanged = bFontChanged = bCJKFontChanged = bCTLFontChanged =
+ bFSizeChanged = bFCTLSizeChanged = bWidowsChanged = false;
+ pIo->SetNAktColl( nThisStyle );
+ pIo->bStyNormal = nThisStyle == 0;
+ return bOldNoImp;
+}
+
+void WW8RStyle::PostStyle(SwWW8StyInf &rSI, bool bOldNoImp)
+{
+ // Alle moeglichen Attribut-Flags zuruecksetzen,
+ // da es in Styles keine Attr-Enden gibt
+
+ pIo->bHasBorder = pIo->bShdTxtCol = pIo->bCharShdTxtCol
+ = pIo->bSpec = pIo->bObj = pIo->bSymbol = false;
+ pIo->nCharFmt = -1;
+
+ // If Style basiert auf Nichts oder Basis ignoriert
+ if ((rSI.nBase >= cstd || pIo->pCollA[rSI.nBase].bImportSkipped) && rSI.bColl)
+ {
+ //! Char-Styles funktionieren aus
+ // unerfindlichen Gruenden nicht
+ // -> dann evtl. harte WW-Defaults
+ // reinsetzen
+ Set1StyleDefaults();
+ }
+
+ pStyRule = 0; // zur Sicherheit
+ pIo->bStyNormal = false;
+ pIo->SetNAktColl( 0 );
+ pIo->bNoAttrImport = bOldNoImp;
+ // rasch nochmal die Listen-Merk-Felder zuruecksetzen,
+ // fuer den Fall dass sie beim einlesen des Styles verwendet wurden
+ pIo->nLFOPosition = USHRT_MAX;
+ pIo->nListLevel = WW8ListManager::nMaxLevel;
+}
+
+void WW8RStyle::Import1Style( USHORT nNr )
+{
+ SwWW8StyInf &rSI = pIo->pCollA[nNr];
+
+ if( rSI.bImported || !rSI.bValid )
+ return;
+
+ rSI.bImported = true; // jetzt schon Flag setzen
+ // verhindert endlose Rekursion
+ //
+ // gueltig und nicht NIL und noch nicht Importiert
+
+ if( rSI.nBase < cstd && !pIo->pCollA[rSI.nBase].bImported )
+ Import1Style( rSI.nBase );
+
+ pStStrm->Seek( rSI.nFilePos );
+
+ short nSkip, cbStd;
+ String sName;
+
+ WW8_STD* pStd = Read1Style( nSkip, &sName, &cbStd );// lies Style
+
+ if (pStd)
+ rSI.SetOrgWWIdent( sName, pStd->sti );
+
+ // either no Name or unused Slot or unknown Style
+
+ if ( !pStd || (0 == sName.Len()) || ((1 != pStd->sgc) && (2 != pStd->sgc)) )
+ {
+ pStStrm->SeekRel( nSkip );
+ return;
+ }
+
+ bool bOldNoImp = PrepareStyle(rSI, static_cast<ww::sti>(pStd->sti), nNr, pStd->istdNext);
+
+ // falls etwas falsch interpretiert wird, gehts danach wieder richtig
+ long nPos = pStStrm->Tell();
+
+ //Variable parts of the STD start at even byte offsets, but "inside
+ //the STD", which I take to meaning even in relation to the starting
+ //position of the STD, which matches findings in #89439#, generally it
+ //doesn't matter as the STSHI starts off nearly always on an even
+ //offset
+
+ //Import of the Style Contents
+ ImportGrupx(nSkip, pStd->sgc == 1, rSI.nFilePos & 1);
+
+ PostStyle(rSI, bOldNoImp);
+
+ pStStrm->Seek( nPos+nSkip );
+ delete pStd;
+}
+
+void WW8RStyle::RecursiveReg(USHORT nNr)
+{
+ SwWW8StyInf &rSI = pIo->pCollA[nNr];
+ if( rSI.bImported || !rSI.bValid )
+ return;
+
+ rSI.bImported = true;
+
+ if( rSI.nBase < cstd && !pIo->pCollA[rSI.nBase].bImported )
+ RecursiveReg(rSI.nBase);
+
+ pIo->RegisterNumFmtOnStyle(nNr);
+
+}
+
+/*
+ After all styles are imported then we can recursively apply numbering
+ styles to them, and change their tab stop settings if they turned out
+ to have special first line indentation.
+*/
+void WW8RStyle::PostProcessStyles()
+{
+ USHORT i;
+ /*
+ Clear all imported flags so that we can recursively apply numbering
+ formats and use it to mark handled ones
+ */
+ for (i=0; i < cstd; ++i)
+ pIo->pCollA[i].bImported = false;
+
+ /*
+ Register the num formats and tabstop changes on the styles recursively.
+ */
+
+ /*
+ In the same loop apply the tabstop changes required because we need to
+ change their location if theres a special indentation for the first line,
+ By avoiding making use of each styles margins during reading of their
+ tabstops we don't get problems with doubly adjusting tabstops that
+ are inheritied.
+ */
+ for (i=0; i < cstd; ++i)
+ {
+ if (pIo->pCollA[i].bValid)
+ {
+ RecursiveReg(i);
+ }
+ }
+}
+
+void WW8RStyle::ScanStyles() // untersucht Style-Abhaengigkeiten
+{ // und ermittelt die Filepos fuer jeden Style
+ /*
+ WW8_FC nStyleStart = rFib.fcStshf;
+ pStStrm->Seek( nStyleStart );
+ */
+ for (USHORT i = 0; i < cstd; ++i)
+ {
+ short nSkip;
+ SwWW8StyInf &rSI = pIo->pCollA[i];
+
+ rSI.nFilePos = pStStrm->Tell(); // merke FilePos
+ WW8_STD* pStd = Read1Style( nSkip, 0, 0 ); // read STD
+ rSI.bValid = (0 != pStd);
+ if (rSI.bValid)
+ {
+ rSI.nBase = pStd->istdBase; // merke Basis
+ rSI.bColl = ( pStd->sgc == 1 ); // Para-Style
+ }
+ else
+ rSI = SwWW8StyInf();
+
+ delete pStd;
+ pStStrm->SeekRel( nSkip ); // ueberlese Namen und Sprms
+ }
+}
+
+std::vector<BYTE> ChpxToSprms(const Word2CHPX &rChpx)
+{
+ std::vector<BYTE> aRet;
+
+ aRet.push_back(60);
+ aRet.push_back( static_cast< BYTE >(128 + rChpx.fBold) );
+
+ aRet.push_back(61);
+ aRet.push_back( static_cast< BYTE >(128 + rChpx.fItalic) );
+
+ aRet.push_back(62);
+ aRet.push_back( static_cast< BYTE >(128 + rChpx.fStrike) );
+
+ aRet.push_back(63);
+ aRet.push_back( static_cast< BYTE >(128 + rChpx.fOutline) );
+
+ aRet.push_back(65);
+ aRet.push_back( static_cast< BYTE >(128 + rChpx.fSmallCaps) );
+
+ aRet.push_back(66);
+ aRet.push_back( static_cast< BYTE >(128 + rChpx.fCaps) );
+
+ aRet.push_back(67);
+ aRet.push_back( static_cast< BYTE >(128 + rChpx.fVanish) );
+
+ if (rChpx.fsFtc)
+ {
+ aRet.push_back(68);
+ SVBT16 a;
+ ShortToSVBT16(rChpx.ftc, a);
+ aRet.push_back(a[1]);
+ aRet.push_back(a[0]);
+ }
+
+ if (rChpx.fsKul)
+ {
+ aRet.push_back(69);
+ aRet.push_back(rChpx.kul);
+ }
+
+ if (rChpx.fsLid)
+ {
+ aRet.push_back(72);
+ SVBT16 a;
+ ShortToSVBT16(rChpx.lid, a);
+ aRet.push_back(a[1]);
+ aRet.push_back(a[0]);
+ }
+
+ if (rChpx.fsIco)
+ {
+ aRet.push_back(73);
+ aRet.push_back(rChpx.ico);
+ }
+
+ if (rChpx.fsHps)
+ {
+ aRet.push_back(74);
+
+ SVBT16 a;
+ ShortToSVBT16(rChpx.hps, a);
+ aRet.push_back(a[0]);
+// aRet.push_back(a[1]);
+ }
+
+ if (rChpx.fsPos)
+ {
+ aRet.push_back(76);
+ aRet.push_back(rChpx.hpsPos);
+ }
+
+ aRet.push_back(80);
+ aRet.push_back( static_cast< BYTE >(128 + rChpx.fBoldBi) );
+
+ aRet.push_back(81);
+ aRet.push_back( static_cast< BYTE >(128 + rChpx.fItalicBi) );
+
+ if (rChpx.fsFtcBi)
+ {
+ aRet.push_back(82);
+ SVBT16 a;
+ ShortToSVBT16(rChpx.fsFtcBi, a);
+ aRet.push_back(a[1]);
+ aRet.push_back(a[0]);
+ }
+
+ if (rChpx.fsLidBi)
+ {
+ aRet.push_back(83);
+ SVBT16 a;
+ ShortToSVBT16(rChpx.lidBi, a);
+ aRet.push_back(a[1]);
+ aRet.push_back(a[0]);
+ }
+
+ if (rChpx.fsIcoBi)
+ {
+ aRet.push_back(84);
+ aRet.push_back(rChpx.icoBi);
+ }
+
+ if (rChpx.fsHpsBi)
+ {
+ aRet.push_back(85);
+ SVBT16 a;
+ ShortToSVBT16(rChpx.hpsBi, a);
+ aRet.push_back(a[1]);
+ aRet.push_back(a[0]);
+ }
+
+ return aRet;
+}
+
+Word2CHPX ReadWord2Chpx(SvStream &rSt, sal_Size nOffset, sal_uInt8 nSize)
+{
+ Word2CHPX aChpx;
+
+ if (!nSize)
+ return aChpx;
+
+ rSt.Seek(nOffset);
+
+ sal_uInt8 nCount=0;
+
+ while (1)
+ {
+ sal_uInt8 nFlags8;
+ rSt >> nFlags8;
+ nCount++;
+
+ aChpx.fBold = nFlags8 & 0x01;
+ aChpx.fItalic = (nFlags8 & 0x02) >> 1;
+ aChpx.fRMarkDel = (nFlags8 & 0x04) >> 2;
+ aChpx.fOutline = (nFlags8 & 0x08) >> 3;
+ aChpx.fFldVanish = (nFlags8 & 0x10) >> 4;
+ aChpx.fSmallCaps = (nFlags8 & 0x20) >> 5;
+ aChpx.fCaps = (nFlags8 & 0x40) >> 6;
+ aChpx.fVanish = (nFlags8 & 0x80) >> 7;
+
+ if (nCount >= nSize) break;
+ rSt >> nFlags8;
+ nCount++;
+
+ aChpx.fRMark = nFlags8 & 0x01;
+ aChpx.fSpec = (nFlags8 & 0x02) >> 1;
+ aChpx.fStrike = (nFlags8 & 0x04) >> 2;
+ aChpx.fObj = (nFlags8 & 0x08) >> 3;
+ aChpx.fBoldBi = (nFlags8 & 0x10) >> 4;
+ aChpx.fItalicBi = (nFlags8 & 0x20) >> 5;
+ aChpx.fBiDi = (nFlags8 & 0x40) >> 6;
+ aChpx.fDiacUSico = (nFlags8 & 0x80) >> 7;
+
+ if (nCount >= nSize) break;
+ rSt >> nFlags8;
+ nCount++;
+
+ aChpx.fsIco = nFlags8 & 0x01;
+ aChpx.fsFtc = (nFlags8 & 0x02) >> 1;
+ aChpx.fsHps = (nFlags8 & 0x04) >> 2;
+ aChpx.fsKul = (nFlags8 & 0x08) >> 3;
+ aChpx.fsPos = (nFlags8 & 0x10) >> 4;
+ aChpx.fsSpace = (nFlags8 & 0x20) >> 5;
+ aChpx.fsLid = (nFlags8 & 0x40) >> 6;
+ aChpx.fsIcoBi = (nFlags8 & 0x80) >> 7;
+
+ if (nCount >= nSize) break;
+ rSt >> nFlags8;
+ nCount++;
+
+ aChpx.fsFtcBi = nFlags8 & 0x01;
+ aChpx.fsHpsBi = (nFlags8 & 0x02) >> 1;
+ aChpx.fsLidBi = (nFlags8 & 0x04) >> 2;
+
+ if (nCount >= nSize) break;
+ rSt >> aChpx.ftc;
+ nCount+=2;
+
+ if (nCount >= nSize) break;
+ rSt >> aChpx.hps;
+ nCount+=2;
+
+ if (nCount >= nSize) break;
+ rSt >> nFlags8;
+ nCount++;
+
+ aChpx.qpsSpace = nFlags8 & 0x3F;
+ aChpx.fSysVanish = (nFlags8 & 0x40) >> 6;
+ aChpx.fNumRun = (nFlags8 & 0x80) >> 7;
+
+ if (nCount >= nSize) break;
+ rSt >> nFlags8;
+ nCount++;
+
+ aChpx.ico = nFlags8 & 0x1F;
+ aChpx.kul = (nFlags8 & 0xE0) >> 5;
+
+ if (nCount >= nSize) break;
+ rSt >> aChpx.hpsPos;
+ nCount++;
+
+ if (nCount >= nSize) break;
+ rSt >> aChpx.icoBi;
+ nCount++;
+
+ if (nCount >= nSize) break;
+ rSt >> aChpx.lid;
+ nCount+=2;
+
+ if (nCount >= nSize) break;
+ rSt >> aChpx.ftcBi;
+ nCount+=2;
+
+ if (nCount >= nSize) break;
+ rSt >> aChpx.hpsBi;
+ nCount+=2;
+
+ if (nCount >= nSize) break;
+ rSt >> aChpx.lidBi;
+ nCount+=2;
+
+ if (nCount >= nSize) break;
+ rSt >> aChpx.fcPic;
+ nCount+=4;
+
+ break;
+ }
+
+ rSt.SeekRel(nSize-nCount);
+ return aChpx;
+}
+
+namespace
+{
+ struct pxoffset { sal_Size mnOffset; sal_uInt8 mnSize; };
+}
+
+void WW8RStyle::ImportOldFormatStyles()
+{
+ for (sal_uInt16 i=0; i < cstd; ++i)
+ {
+ pIo->pCollA[i].bColl = true;
+ //every chain must end eventually at the null style (style code 222)
+ pIo->pCollA[i].nBase = 222;
+ }
+
+ rtl_TextEncoding eStructChrSet = WW8Fib::GetFIBCharset(
+ pIo->pWwFib->chseTables);
+
+ sal_uInt16 cstcStd;
+ rSt >> cstcStd;
+
+ sal_uInt16 cbName;
+ rSt >> cbName;
+ sal_uInt16 nByteCount = 2;
+ USHORT stcp=0;
+ while (nByteCount < cbName)
+ {
+ sal_uInt8 nCount;
+ rSt >> nCount;
+ nByteCount++;
+
+ sal_uInt8 stc = static_cast< sal_uInt8 >((stcp - cstcStd) & 255);
+ SwWW8StyInf &rSI = pIo->pCollA[stc];
+ if (nCount != 0xFF) // undefined style
+ {
+ String sName;
+ if (nCount == 0) // inbuilt style
+ {
+ ww::sti eSti = ww::GetCanonicalStiFromStc(stc);
+ if (const sal_Char *pStr = GetEnglishNameFromSti(eSti))
+ sName = String(pStr, RTL_TEXTENCODING_ASCII_US);
+ else
+ sName = String(CREATE_CONST_ASC("Unknown"));
+ }
+ else // user style
+ {
+ ByteString aTmp;
+ nByteCount = static_cast< sal_uInt16 >(nByteCount + SafeReadString(aTmp, nCount, rSt));
+ sName = String(aTmp, eStructChrSet);
+ }
+ rSI.SetOrgWWIdent(sName, stc);
+ rSI.bImported = true;
+ }
+ else
+ {
+ ww::sti eSti = ww::GetCanonicalStiFromStc(stc);
+ if (const sal_Char *pStr = GetEnglishNameFromSti(eSti))
+ {
+ String sName = String(pStr, RTL_TEXTENCODING_ASCII_US);
+ rSI.SetOrgWWIdent(sName, stc);
+ }
+ }
+ stcp++;
+ }
+
+ USHORT nStyles=stcp;
+
+ std::vector<pxoffset> aCHPXOffsets(stcp);
+ sal_uInt16 cbChpx;
+ rSt >> cbChpx;
+ nByteCount = 2;
+ stcp=0;
+ std::vector< std::vector<BYTE> > aConvertedChpx;
+ while (nByteCount < cbChpx)
+ {
+ sal_uInt8 cb;
+ rSt >> cb;
+ nByteCount++;
+
+ aCHPXOffsets[stcp].mnSize = 0;
+
+ if (cb != 0xFF)
+ {
+ sal_uInt8 nRemainder = cb;
+
+ aCHPXOffsets[stcp].mnOffset = rSt.Tell();
+ aCHPXOffsets[stcp].mnSize = nRemainder;
+
+ Word2CHPX aChpx = ReadWord2Chpx(rSt, aCHPXOffsets[stcp].mnOffset,
+ aCHPXOffsets[stcp].mnSize);
+ aConvertedChpx.push_back( ChpxToSprms(aChpx) );
+
+ nByteCount += nRemainder;
+ }
+ else
+ aConvertedChpx.push_back( std::vector<BYTE>() );
+
+ stcp++;
+ if (stcp == nStyles)
+ {
+ rSt.SeekRel(cbChpx-nByteCount);
+ nByteCount += cbChpx-nByteCount;
+ }
+ }
+
+ std::vector<pxoffset> aPAPXOffsets(stcp);
+ sal_uInt16 cbPapx;
+ rSt >> cbPapx;
+ nByteCount = 2;
+ stcp=0;
+ while (nByteCount < cbPapx)
+ {
+ sal_uInt8 cb;
+ rSt >> cb;
+ nByteCount++;
+
+ aPAPXOffsets[stcp].mnSize = 0;
+
+ if (cb != 0xFF)
+ {
+ sal_uInt8 stc2;
+ rSt >> stc2;
+ rSt.SeekRel(6);
+ nByteCount+=7;
+ sal_uInt8 nRemainder = cb-7;
+
+ aPAPXOffsets[stcp].mnOffset = rSt.Tell();
+ aPAPXOffsets[stcp].mnSize = nRemainder;
+
+ rSt.SeekRel(nRemainder);
+ nByteCount += nRemainder;
+ }
+
+ stcp++;
+
+ if (stcp == nStyles)
+ {
+ rSt.SeekRel(cbPapx-nByteCount);
+ nByteCount += cbPapx-nByteCount;
+ }
+ }
+
+ sal_uInt16 iMac;
+ rSt >> iMac;
+
+ if (iMac > nStyles) iMac = nStyles;
+
+ for (stcp = 0; stcp < iMac; ++stcp)
+ {
+ sal_uInt8 stcNext, stcBase;
+ rSt >> stcNext;
+ rSt >> stcBase;
+
+ sal_uInt8 stc = static_cast< sal_uInt8 >((stcp - cstcStd) & 255);
+
+ /*
+ #i64557# style based on itself
+ every chain must end eventually at the null style (style code 222)
+ */
+ if (stc == stcBase)
+ stcBase = 222;
+
+ SwWW8StyInf &rSI = pIo->pCollA[stc];
+ rSI.nBase = stcBase;
+
+ ww::sti eSti = ww::GetCanonicalStiFromStc(stc);
+
+ if (eSti == ww::stiNil)
+ continue;
+
+ rSI.bValid = true;
+
+ if (ww::StandardStiIsCharStyle(eSti) && !aPAPXOffsets[stcp].mnSize)
+ pIo->pCollA[stc].bColl = false;
+
+ bool bOldNoImp = PrepareStyle(rSI, eSti, stc, stcNext);
+
+ ImportSprms(aPAPXOffsets[stcp].mnOffset, aPAPXOffsets[stcp].mnSize,
+ true);
+
+ if (aConvertedChpx[stcp].size() > 0)
+ ImportSprms(&(aConvertedChpx[stcp][0]),
+ static_cast< short >(aConvertedChpx[stcp].size()),
+ false);
+
+ PostStyle(rSI, bOldNoImp);
+ }
+}
+
+void WW8RStyle::ImportNewFormatStyles()
+{
+ ScanStyles(); // Scanne Based On
+
+ for (USHORT i = 0; i < cstd; ++i) // import Styles
+ if (pIo->pCollA[i].bValid)
+ Import1Style( i );
+}
+
+void WW8RStyle::ImportStyles()
+{
+ if (ww::eWW2 == pIo->pWwFib->GetFIBVersion())
+ ImportOldFormatStyles();
+ else
+ ImportNewFormatStyles();
+}
+
+void WW8RStyle::Import()
+{
+ pIo->pDfltTxtFmtColl = pIo->rDoc.GetDfltTxtFmtColl();
+ pIo->pStandardFmtColl =
+ pIo->rDoc.GetTxtCollFromPool(RES_POOLCOLL_STANDARD, false);
+
+ if( pIo->nIniFlags & WW8FL_NO_STYLES )
+ return;
+
+ ImportStyles();
+
+ for (USHORT i = 0; i < cstd; ++i)
+ {
+ // Follow chain
+ SwWW8StyInf* pi = &pIo->pCollA[i];
+ USHORT j = pi->nFollow;
+ if( j < cstd )
+ {
+ SwWW8StyInf* pj = &pIo->pCollA[j];
+ if ( j != i // sinnvoller Index ?
+ && pi->pFmt // Format ok ?
+ && pj->pFmt // Derived-Format ok ?
+ && pi->bColl // geht nur bei Absatz-Vorlagen (WW)
+ && pj->bColl ){ // beides gleicher Typ ?
+ ( (SwTxtFmtColl*)pi->pFmt )->SetNextTxtFmtColl(
+ *(SwTxtFmtColl*)pj->pFmt ); // ok, eintragen
+ }
+ }
+ }
+// Die Sonderbehandlung zur Setzen der
+// Default-Zeichenvorlage "Absatz-Standardschriftart" ( Style-ID 65 ) fehlt
+// Sie ist aber defaultmaessig leer ( WW6 dt und US ) und von der
+// WW-UI nicht zu veraendern, so dass das nicht stoert.
+// Der Mechanismus waere folgender:
+// if( bNew ) rDoc.SetDefault( pDefCharFmt->GetAttrSet() );
+//
+ // fuer z.B. Tabellen wird ein immer gueltiger Std-Style gebraucht
+
+ if( pIo->pCollA[0].pFmt && pIo->pCollA[0].bColl && pIo->pCollA[0].bValid )
+ pIo->pDfltTxtFmtColl = (SwTxtFmtColl*)pIo->pCollA[0].pFmt;
+ else
+ pIo->pDfltTxtFmtColl = pIo->rDoc.GetDfltTxtFmtColl();
+
+
+ // set Hyphenation flag on BASIC para-style
+ if (pIo->mbNewDoc && pIo->pStandardFmtColl)
+ {
+ if (pIo->pWDop->fAutoHyphen
+ && SFX_ITEM_SET != pIo->pStandardFmtColl->GetItemState(
+ RES_PARATR_HYPHENZONE, false) )
+ {
+ SvxHyphenZoneItem aAttr(true, RES_PARATR_HYPHENZONE);
+ aAttr.GetMinLead() = 2;
+ aAttr.GetMinTrail() = 2;
+ aAttr.GetMaxHyphens() = 0;
+
+ pIo->pStandardFmtColl->SetFmtAttr( aAttr );
+ }
+
+ /*
+ Word defaults to ltr not from environment like writer. Regardless of
+ the page/sections rtl setting the standard style lack of rtl still
+ means ltr
+ */
+ if (SFX_ITEM_SET != pIo->pStandardFmtColl->GetItemState(RES_FRAMEDIR,
+ false))
+ {
+ pIo->pStandardFmtColl->SetFmtAttr(
+ SvxFrameDirectionItem(FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR));
+ }
+ }
+
+ // wir sind jetzt nicht mehr beim Style einlesen:
+ pIo->pAktColl = 0;
+}
+
+CharSet SwWW8StyInf::GetCharSet() const
+{
+ if ((pFmt) && (pFmt->GetFrmDir().GetValue() == FRMDIR_HORI_RIGHT_TOP))
+ return eRTLFontSrcCharSet;
+ return eLTRFontSrcCharSet;
+}
+
+CharSet SwWW8StyInf::GetCJKCharSet() const
+{
+ if ((pFmt) && (pFmt->GetFrmDir().GetValue() == FRMDIR_HORI_RIGHT_TOP))
+ return eRTLFontSrcCharSet;
+ return eCJKFontSrcCharSet;
+}
+
+/* vi:set tabstop=4 shiftwidth=4 expandtab: */