1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ww8par2.cxx,v $
10 * $Revision: 1.145.76.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
35 #include <tools/solar.h>
36 #include <vcl/vclenum.hxx>
37 #include <vcl/font.hxx>
38 #include <hintids.hxx>
39 #include <svx/colritem.hxx>
40 #include <svx/orphitem.hxx>
41 #include <svx/widwitem.hxx>
42 #include <svx/brshitem.hxx>
43 #include <svx/boxitem.hxx>
44 #include <svx/lrspitem.hxx>
45 #include <svx/fhgtitem.hxx>
46 #include <svx/fhgtitem.hxx>
47 #include <svx/hyznitem.hxx>
48 #include <svx/frmdiritem.hxx>
49 #include <svx/langitem.hxx>
50 #include <svx/charrotateitem.hxx>
51 #include <svx/pgrditem.hxx>
52 #include <msfilter.hxx>
53 #include <pam.hxx> // fuer SwPam
56 #include <ndtxt.hxx> // class SwTxtNode
57 #include <paratr.hxx> // SwNumRuleItem
58 #include <poolfmt.hxx> // RES_POOLCOLL_STANDARD
59 #include <swtable.hxx> // class SwTableLines, ...
60 #include <tblsel.hxx> // class _SwSelBox
62 #include <fmtpdsc.hxx>
67 #include <charfmt.hxx>
68 #include <SwStyleNameMapper.hxx>
69 #include <fltshell.hxx> // fuer den Attribut Stack
70 #include <fmtanchr.hxx>
71 #include <fmtrowsplt.hxx>
72 // --> OD 2005-01-27 #i33818#
73 #include <fmtfollowtextflow.hxx>
75 #include <numrule.hxx>
76 # include "../inc/wwstyles.hxx"
77 # include "writerhelper.hxx"
78 #include "ww8struc.hxx" // struct TC
80 #include "ww8par2.hxx"
86 #define MAX_COL 64 // WW6-Beschreibung: 32, WW6-UI: 31 & WW8-UI: 63!
88 using namespace ::com::sun::star
;
91 class WW8SelBoxInfo
: public SwSelBoxes_SAR
94 WW8SelBoxInfo(const WW8SelBoxInfo
&);
95 WW8SelBoxInfo
& operator=(const WW8SelBoxInfo
&);
101 WW8SelBoxInfo(short nXCenter
, short nWidth
)
102 : nGroupXStart( nXCenter
), nGroupWidth( nWidth
), bGroupLocked(false)
106 typedef WW8SelBoxInfo
* WW8SelBoxInfoPtr
;
108 SV_DECL_PTRARR_DEL(WW8MergeGroups
, WW8SelBoxInfoPtr
, 16,16)
109 SV_IMPL_PTRARR(WW8MergeGroups
, WW8SelBoxInfoPtr
)
111 struct WW8TabBandDesc
113 WW8TabBandDesc
* pNextBand
;
117 short mnDefaultRight
;
118 short mnDefaultBottom
;
122 sal_uInt16 maDirections
[MAX_COL
+ 1];
123 short nCenter
[MAX_COL
+ 1]; // X-Rand aller Zellen dieses Bandes
124 short nWidth
[MAX_COL
+ 1]; // Laenge aller Zellen dieses Bandes
125 short nWwCols
; // BYTE wuerde reichen, alignment -> short
126 short nSwCols
; // SW: so viele Spalten fuer den Writer
127 bool bLEmptyCol
; // SW: Links eine leere Zusatz-Spalte
128 bool bREmptyCol
; // SW: dito rechts
132 BYTE nOverrideSpacing
[MAX_COL
+ 1];
133 short nOverrideValues
[MAX_COL
+ 1][4];
135 sal_uInt32
* pNewSHDs
;
139 // nur fuer WW6-7: diese Zelle hat WW-Flag bMerged (horizontal) gesetzt
140 //bool bWWMergedVer6[MAX_COL];
143 bool bExist
[MAX_COL
]; // Existiert diese Zelle ?
144 UINT8 nTransCell
[MAX_COL
+ 2]; // UEbersetzung WW-Index -> SW-Index
147 WW8TabBandDesc(WW8TabBandDesc
& rBand
); // tief kopieren
149 static void setcelldefaults(WW8_TCell
*pCells
, short nCells
);
150 void ReadDef(bool bVer67
, const BYTE
* pS
);
151 void ProcessDirection(const BYTE
* pParams
);
152 void ProcessSprmTSetBRC(bool bVer67
, const BYTE
* pParamsTSetBRC
);
153 void ProcessSprmTTableBorders(bool bVer67
, const BYTE
* pParams
);
154 void ProcessSprmTDxaCol(const BYTE
* pParamsTDxaCol
);
155 void ProcessSprmTDelete(const BYTE
* pParamsTDelete
);
156 void ProcessSprmTInsert(const BYTE
* pParamsTInsert
);
157 void ProcessSpacing(const BYTE
* pParamsTInsert
);
158 void ProcessSpecificSpacing(const BYTE
* pParamsTInsert
);
159 void ReadShd(const BYTE
* pS
);
160 void ReadNewShd(const BYTE
* pS
, bool bVer67
);
162 enum wwDIR
{wwTOP
= 0, wwLEFT
= 1, wwBOTTOM
= 2, wwRIGHT
= 3};
165 WW8TabBandDesc::WW8TabBandDesc()
167 memset(this, 0, sizeof(*this));
168 for (size_t i
= 0; i
< sizeof(maDirections
)/sizeof(sal_uInt16
); ++i
)
172 WW8TabBandDesc::~WW8TabBandDesc()
181 std::vector
<String
> aNumRuleNames
;
182 sw::util::RedlineStack
*mpOldRedlineStack
;
184 SwWW8ImplReader
* pIo
;
186 WW8TabBandDesc
* pFirstBand
;
187 WW8TabBandDesc
* pActBand
;
191 SwTableNode
* pTblNd
; // Tabellen-Node
192 const SwTableLines
* pTabLines
; // Zeilen-Array davon
193 SwTableLine
* pTabLine
; // akt. Zeile
194 SwTableBoxes
* pTabBoxes
; // Boxen-Array in akt. Zeile
195 SwTableBox
* pTabBox
; // akt. Zelle
197 WW8MergeGroups
* pMergeGroups
; // Listen aller zu verknuepfenden Zellen
199 WW8_TCell
* pAktWWCell
;
202 short nDefaultSwCols
;
205 short nConvertedLeft
;
208 short nPreferredWidth
;
215 // 2. allgemeine Verwaltungsinfo
217 short nAktBandRow
; // SW: in dieser Zeile des akt. Bandes bin ich
218 // 3. Verwaltungsinfo fuer Writer
221 USHORT nRowsToRepeat
;
225 USHORT
GetLogicalWWCol() const;
226 void SetTabBorders( SwTableBox
* pBox
, short nIdx
);
227 void SetTabShades( SwTableBox
* pBox
, short nWwIdx
);
228 void SetTabVertAlign( SwTableBox
* pBox
, short nWwIdx
);
229 void SetTabDirection( SwTableBox
* pBox
, short nWwIdx
);
231 bool SetPamInCell(short nWwCol
, bool bPam
);
232 void InsertCells( short nIns
);
233 void AdjustNewBand();
235 // durchsucht pMergeGroups, meldet Index der ersten, passenden Gruppe bzw.
236 // -1 Details siehe bei der Implementierung
237 bool FindMergeGroup(short nX1
, short nWidth
, bool bExact
, short& nMGrIdx
);
239 // einzelne Box ggfs. in eine Merge-Gruppe aufnehmen
240 // (die Merge-Gruppen werden dann spaeter auf einen Schlag abgearbeitet)
241 SwTableBox
* UpdateTableMergeGroup(WW8_TCell
& rCell
,
242 WW8SelBoxInfo
* pActGroup
, SwTableBox
* pActBox
, USHORT nCol
);
243 void StartMiserableHackForUnsupportedDirection(short nWwCol
);
244 void EndMiserableHackForUnsupportedDirection(short nWwCol
);
246 WW8TabDesc(const WW8TabDesc
&);
247 WW8TabDesc
&operator=(const WW8TabDesc
&);
249 const SwTable
* pTable
; // Tabelle
250 SwPosition
* pParentPos
;
251 SwFlyFrmFmt
* pFlyFmt
;
253 bool IsValidCell(short nCol
) const;
254 bool InFirstParaInCell() const;
256 WW8TabDesc( SwWW8ImplReader
* pIoClass
, WW8_CP nStartCp
);
257 bool Ok() const { return bOk
; }
258 void CreateSwTable();
260 void SetSizePosition(SwFrmFmt
* pFrmFmt
);
262 void MoveOutsideTable();
264 void FinishSwTable();
266 short GetMinLeft() const { return nConvertedLeft
; }
268 SwPosition
*GetPos() { return pTmpPos
; }
270 const WW8_TCell
* GetAktWWCell() const { return pAktWWCell
; }
271 short GetAktCol() const { return nAktCol
; }
272 // find name of numrule valid for current WW-COL
273 const String
& GetNumRuleName() const;
274 void SetNumRuleName( const String
& rName
);
276 sw::util::RedlineStack
* getOldRedlineStack(){ return mpOldRedlineStack
; }
279 void sw::util::RedlineStack::close( const SwPosition
& rPos
,
280 RedlineType_t eType
, WW8TabDesc
* pTabDesc
)
282 // If the redline type is not found in the redline stack, we have to check if there has been
283 // a tabledesc and to check its saved redline stack, too. (#136939, #i68139)
284 if( !close( rPos
, eType
) )
286 if( pTabDesc
&& pTabDesc
->getOldRedlineStack() )
289 ASSERT( pTabDesc
->getOldRedlineStack()->close(rPos
, eType
), "close without open!");
291 pTabDesc
->getOldRedlineStack()->close( rPos
, eType
);
298 void wwSectionManager::SetCurrentSectionHasFootnote()
300 ASSERT(!maSegments
.empty(),
301 "should not be possible, must be at least one segment");
302 if (!maSegments
.empty())
303 maSegments
.back().mbHasFootnote
= true;
306 bool wwSectionManager::CurrentSectionIsVertical() const
308 ASSERT(!maSegments
.empty(),
309 "should not be possible, must be at least one segment");
310 if (!maSegments
.empty())
311 return maSegments
.back().IsVertical();
315 bool wwSectionManager::CurrentSectionIsProtected() const
317 ASSERT(!maSegments
.empty(),
318 "should not be possible, must be at least one segment");
319 if (!maSegments
.empty())
320 return SectionIsProtected(maSegments
.back());
324 sal_uInt32
wwSectionManager::GetPageLeft() const
326 return !maSegments
.empty() ? maSegments
.back().nPgLeft
: 0;
329 sal_uInt32
wwSectionManager::GetPageRight() const
331 return !maSegments
.empty() ? maSegments
.back().nPgRight
: 0;
334 sal_uInt32
wwSectionManager::GetPageWidth() const
336 return !maSegments
.empty() ? maSegments
.back().GetPageWidth() : 0;
339 sal_uInt32
wwSectionManager::GetTextAreaWidth() const
341 return !maSegments
.empty() ? maSegments
.back().GetTextAreaWidth() : 0;
344 // --> OD 2007-07-03 #148498#
345 sal_uInt32
wwSectionManager::GetWWPageTopMargin() const
347 return !maSegments
.empty() ? maSegments
.back().maSep
.dyaTop
: 0;
351 sal_uInt16
SwWW8ImplReader::End_Ftn()
355 Ignoring Footnote outside of the normal Text. People will put footnotes
356 into field results and field commands.
359 pPaM
->GetPoint()->nNode
< rDoc
.GetNodes().GetEndOfExtras().GetIndex())
364 ASSERT(!maFtnStack
.empty(), "footnote end without start");
365 if (maFtnStack
.empty())
368 bool bFtEdOk
= false;
369 const FtnDescriptor
&rDesc
= maFtnStack
.back();
371 //Get the footnote character and remove it from the txtnode. We'll
372 //replace it with the footnote
373 SwTxtNode
* pTxt
= pPaM
->GetNode()->GetTxtNode();
374 xub_StrLen nPos
= pPaM
->GetPoint()->nContent
.GetIndex();
378 //There should have been a footnote char, we will replace this.
381 sChar
.Append(pTxt
->GetTxt().GetChar(--nPos
));
383 pPaM
->GetMark()->nContent
--;
384 rDoc
.Delete( *pPaM
);
386 SwFmtFtn
aFtn(rDesc
.meType
== MAN_EDN
);
387 pFN
= pTxt
->InsertItem(aFtn
, nPos
, nPos
);
389 ASSERT(pFN
, "Probleme beim Anlegen des Fussnoten-Textes");
393 SwPosition
aTmpPos( *pPaM
->GetPoint() ); // merke alte Cursorposition
394 WW8PLCFxSaveAll aSave
;
395 pPlcxMan
->SaveAllPLCFx( aSave
);
396 WW8PLCFMan
* pOldPlcxMan
= pPlcxMan
;
398 const SwNodeIndex
* pSttIdx
= ((SwTxtFtn
*)pFN
)->GetStartNode();
399 ASSERT(pSttIdx
, "Probleme beim Anlegen des Fussnoten-Textes");
401 ((SwTxtFtn
*)pFN
)->SetSeqNo( rDoc
.GetFtnIdxs().Count() );
406 // read content of Ft-/End-Note
407 Read_HdFtFtnText( pSttIdx
, rDesc
.mnStartCp
, rDesc
.mnLen
, rDesc
.meType
);
411 ASSERT(sChar
.Len()==1 && ((rDesc
.mbAutoNum
== (sChar
.GetChar(0) == 2))),
412 "footnote autonumbering must be 0x02, and everthing else must not be");
414 // If no automatic numbering use the following char from the main text
415 // as the footnote number
416 if (!rDesc
.mbAutoNum
)
417 ((SwTxtFtn
*)pFN
)->SetNumber(0, &sChar
);
420 Delete the footnote char from the footnote if its at the beginning
421 as usual. Might not be if the user has already deleted it, e.g.
424 SwNodeIndex
& rNIdx
= pPaM
->GetPoint()->nNode
;
425 rNIdx
= pSttIdx
->GetIndex() + 1;
426 SwTxtNode
* pTNd
= rNIdx
.GetNode().GetTxtNode();
427 if (pTNd
&& pTNd
->GetTxt().Len() && sChar
.Len())
429 if (pTNd
->GetTxt().GetChar(0) == sChar
.GetChar(0))
431 pPaM
->GetPoint()->nContent
.Assign( pTNd
, 0 );
433 // Strip out tabs we may have inserted on export #i24762#
434 if (pTNd
->GetTxt().GetChar(1) == 0x09)
435 pPaM
->GetMark()->nContent
++;
436 pPaM
->GetMark()->nContent
++;
437 pReffingStck
->Delete(*pPaM
);
438 rDoc
.Delete( *pPaM
);
443 *pPaM
->GetPoint() = aTmpPos
; // restore Cursor
445 pPlcxMan
= pOldPlcxMan
; // Restore attributes
446 pPlcxMan
->RestoreAllPLCFx( aSave
);
450 maSectionManager
.SetCurrentSectionHasFootnote();
452 maFtnStack
.pop_back();
456 long SwWW8ImplReader::Read_Ftn(WW8PLCFManResult
* pRes
)
460 Ignoring Footnote outside of the normal Text. People will put footnotes
461 into field results and field commands.
464 pPaM
->GetPoint()->nNode
< rDoc
.GetNodes().GetEndOfExtras().GetIndex())
470 aDesc
.mbAutoNum
= true;
471 if (eEDN
== pRes
->nSprmId
)
473 aDesc
.meType
= MAN_EDN
;
474 if (pPlcxMan
->GetEdn())
475 aDesc
.mbAutoNum
= 0 != *(short*)pPlcxMan
->GetEdn()->GetData();
479 aDesc
.meType
= MAN_FTN
;
480 if (pPlcxMan
->GetFtn())
481 aDesc
.mbAutoNum
= 0 != *(short*)pPlcxMan
->GetFtn()->GetData();
484 aDesc
.mnStartCp
= pRes
->nCp2OrIdx
;
485 aDesc
.mnLen
= pRes
->nMemLen
;
487 maFtnStack
.push_back(aDesc
);
492 bool SwWW8ImplReader::SearchRowEnd(WW8PLCFx_Cp_FKP
* pPap
, WW8_CP
&rStartCp
,
497 aRes
.nEndPos
= rStartCp
;
499 while (pPap
->HasFkp() && rStartCp
!= WW8_CP_MAX
)
501 if (pPap
->Where() != WW8_CP_MAX
)
503 const BYTE
* pB
= pPap
->HasSprm(TabRowSprm(nLevel
));
506 const BYTE
*pLevel
= 0;
507 if (0 != (pLevel
= pPap
->HasSprm(0x6649)))
509 if (nLevel
+ 1 == *pLevel
)
514 ASSERT(!nLevel
|| pLevel
, "sublevel without level sprm");
515 return true; // RowEnd found
520 aRes
.nStartPos
= aRes
.nEndPos
;
522 //Seek to our next block of properties
523 if (!(pPap
->SeekPos(aRes
.nStartPos
)))
525 aRes
.nEndPos
= WW8_CP_MAX
;
526 pPap
->SetDirty(true);
528 pPap
->GetSprms(&aRes
);
529 pPap
->SetDirty(false);
530 //Update our aRes to get the new starting point of the next properties
531 rStartCp
= aRes
.nEndPos
;
537 ApoTestResults
SwWW8ImplReader::TestApo(int nCellLevel
, bool bTableRowEnd
,
538 const WW8_TablePos
*pTabPos
)
540 const WW8_TablePos
*pTopLevelTable
= nCellLevel
<= 1 ? pTabPos
: 0;
542 // Frame in Style Definition (word appears to ignore them if inside an
543 // text autoshape, e.g. #94418#)
544 if (!bTxbxFlySection
)
545 aRet
.mpStyleApo
= StyleExists(nAktColl
) ? pCollA
[nAktColl
].pWWFly
: 0;
549 If I have a table and apply a style to one of its frames that should cause
550 a paragraph that its applied to it to only exist as a seperate floating
551 frame, then the behavour depends on which cell that it has been applied
552 to. If its the first cell of a row then the whole table row jumps into the
553 new frame, if its not then then the paragraph attributes are applied
554 "except" for the floating frame stuff. i.e. its ignored. So if theres a
555 table, and we're not in the first cell then we ignore the fact that the
556 paragraph style wants to be in a different frame.
558 This sort of mindbending inconsistency is surely why frames are deprecated
559 in word 97 onwards and hidden away from the user
563 If we are already a table in a frame then we must grab the para properties
564 to see if we are still in that frame.
567 aRet
.mpSprm37
= pPlcxMan
->HasParaSprm( bVer67
? 37 : 0x2423 );
568 aRet
.mpSprm29
= pPlcxMan
->HasParaSprm( bVer67
? 29 : 0x261B );
570 // Is there some frame data here
571 bool bNowApo
= aRet
.HasFrame() || pTopLevelTable
;
574 if (WW8FlyPara
*pTest
= ConstructApo(aRet
, pTabPos
))
580 bool bTestAllowed
= !bTxbxFlySection
&& !bTableRowEnd
;
583 //Test is allowed if there is no table.
584 //Otherwise only allowed if we are in the
585 //first paragraph of the first cell of a row.
586 //(And only if the row we are inside is at the
587 //same level as the previous row, think tables
589 if (nCellLevel
== nInTable
)
598 ASSERT(pTableDesc
, "What!");
599 bTestAllowed
= false;
603 // --> OD 2005-02-01 #i39468#
604 // If current cell isn't valid, the test is allowed.
605 // The cell isn't valid, if e.g. there is a new row
606 // <pTableDesc->nAktRow> >= <pTableDesc->pTabLines->Count()>
608 pTableDesc
->GetAktCol() == 0 &&
609 ( !pTableDesc
->IsValidCell( pTableDesc
->GetAktCol() ) ||
610 pTableDesc
->InFirstParaInCell() );
620 aRet
.mbStartApo
= bNowApo
&& !InAnyApo(); // APO-start
621 aRet
.mbStopApo
= InEqualOrHigherApo(nCellLevel
) && !bNowApo
; // APO-end
623 //If it happens that we are in a table, then if its not the first cell
624 //then any attributes that might otherwise cause the contents to jump
625 //into another frame don't matter, a table row sticks together as one
626 //unit no matter what else happens. So if we are not in a table at
627 //all, or if we are in the first cell then test that the last frame
628 //data is the same as the current one
629 if (bNowApo
&& InEqualApo(nCellLevel
))
631 // two bordering eachother
632 if (!TestSameApo(aRet
, pTabPos
))
633 aRet
.mbStopApo
= aRet
.mbStartApo
= true;
638 //---------------------------------------------------------------------
639 // Hilfroutinen fuer Kapitelnummerierung und Aufzaehlung / Gliederung
640 //---------------------------------------------------------------------
642 static void SetBaseAnlv(SwNumFmt
&rNum
, WW8_ANLV
&rAV
, BYTE nSwLevel
)
644 static SvxExtNumType eNumA
[8] = { SVX_NUM_ARABIC
, SVX_NUM_ROMAN_UPPER
, SVX_NUM_ROMAN_LOWER
,
645 SVX_NUM_CHARS_UPPER_LETTER_N
, SVX_NUM_CHARS_LOWER_LETTER_N
, SVX_NUM_ARABIC
,
646 SVX_NUM_ARABIC
, SVX_NUM_ARABIC
};
648 static SvxAdjust eAdjA
[4] = { SVX_ADJUST_LEFT
,
649 SVX_ADJUST_RIGHT
, SVX_ADJUST_LEFT
, SVX_ADJUST_LEFT
};
650 // eigentlich folgende 2, aber Writer-UI bietet es nicht an
651 // SVX_ADJUST_CENTER, SVX_ADJUST_BLOCKLINE };
653 rNum
.SetNumberingType( static_cast< sal_Int16
>(( SVBT8ToByte( rAV
.nfc
) < 8 ) ?
654 eNumA
[SVBT8ToByte( rAV
.nfc
) ] : SVX_NUM_NUMBER_NONE
) );
655 if ((SVBT8ToByte(rAV
.aBits1
) & 0x4) >> 2)
656 rNum
.SetIncludeUpperLevels(nSwLevel
+ 1);
657 rNum
.SetStart( SVBT16ToShort( rAV
.iStartAt
) );
658 // rNum.eNumAdjust = eAdjA[rAV.jc];
659 rNum
.SetNumAdjust( eAdjA
[SVBT8ToByte( rAV
.aBits1
) & 0x3] );
661 rNum
.SetCharTextDistance( SVBT16ToShort( rAV
.dxaSpace
) );
662 INT16 nIndent
= Abs((INT16
)SVBT16ToShort( rAV
.dxaIndent
));
663 if( SVBT8ToByte( rAV
.aBits1
) & 0x08 ) //fHang
665 rNum
.SetFirstLineOffset( -nIndent
);
666 rNum
.SetLSpace( nIndent
);
667 rNum
.SetAbsLSpace( nIndent
);
670 rNum
.SetCharTextDistance( nIndent
); // Breite der Nummer fehlt
672 if( SVBT8ToByte( rAV
.nfc
) == 5 || SVBT8ToByte( rAV
.nfc
) == 7 )
674 String
sP( rNum
.GetSuffix() );
676 rNum
.SetSuffix( sP
); // Ordinalzahlen
680 void SwWW8ImplReader::SetAnlvStrings(SwNumFmt
&rNum
, WW8_ANLV
&rAV
,
681 const BYTE
* pTxt
, bool bOutline
)
683 bool bInsert
= false; // Default
684 CharSet eCharSet
= eStructCharSet
;
686 const WW8_FFN
* pF
= pFonts
->GetFont(SVBT16ToShort(rAV
.ftc
)); // FontInfo
687 bool bListSymbol
= pF
&& ( pF
->chs
== 2 ); // Symbol/WingDings/...
692 sTxt
= String( (sal_Char
*)pTxt
, SVBT8ToByte( rAV
.cbTextBefore
)
693 + SVBT8ToByte( rAV
.cbTextAfter
), eCharSet
);
697 for(xub_StrLen i
= SVBT8ToByte(rAV
.cbTextBefore
);
698 i
< SVBT8ToByte(rAV
.cbTextAfter
); ++i
, pTxt
+= 2)
700 sTxt
.Append(SVBT16ToShort(*(SVBT16
*)pTxt
));
706 if( !rNum
.GetIncludeUpperLevels() // es sind <= 1 Nummern anzuzeigen
707 || rNum
.GetNumberingType() == SVX_NUM_NUMBER_NONE
){ // oder dieser Level hat keine
709 bInsert
= true; // -> dann uebernehme Zeichen
711 // replace by simple Bullet ?
713 //JP 14.08.96: cBulletChar benutzen, damit auf dem MAC
714 // richtig gemappt wird
715 sTxt
.Fill( SVBT8ToByte( rAV
.cbTextBefore
)
716 + SVBT8ToByte( rAV
.cbTextAfter
), cBulletChar
);
720 { // Nummerierung / Aufzaehlung
722 // if( SVBT16ToShort( rAV.ftc ) == 1
723 // || SVBT16ToShort( rAV.ftc ) == 3 ){ // Symbol / WingDings
730 if( GetFontParams( SVBT16ToShort( rAV
.ftc
), eFamily
, aName
,
731 ePitch
, eCharSet
) ){
732 // USHORT nSiz = ( SVBT16ToShort( rAV.hps ) ) ?
733 // SVBT16ToShort( rAV.hps ) : 24; // Groesse in 1/2 Pt
734 // darf nach JP nicht gesetzt werden, da immer die Size
735 // genommen wird, die am ZeilenAnfang benutzt wird
737 aFont
.SetName( aName
);
738 aFont
.SetFamily( eFamily
);
739 // aFont.SetPitch( ePitch ); // darf nach JP nicht
740 aFont
.SetCharSet( eCharSet
);
741 rNum
.SetNumberingType(SVX_NUM_CHAR_SPECIAL
);
742 // if( rAV.ico ) // geht in UI und SWG-Writer/Reader nicht
743 // aFont.SetColor( Color( GetCol( rAV.ico ) ) );
744 rNum
.SetBulletFont( &aFont
);
746 // take only the very first character
747 if( rAV
.cbTextBefore
|| rAV
.cbTextAfter
)
748 rNum
.SetBulletChar( sTxt
.GetChar( 0 ) );
750 rNum
.SetBulletChar( 0x2190 );
756 if( rAV
.cbTextBefore
)
758 String
sP( sTxt
.Copy( 0, SVBT8ToByte( rAV
.cbTextBefore
) ) );
759 rNum
.SetPrefix( sP
);
761 if( SVBT8ToByte( rAV
.cbTextAfter
) )
763 String
sP( rNum
.GetSuffix() );
764 sP
.Insert( sTxt
.Copy( SVBT8ToByte( rAV
.cbTextBefore
),
765 SVBT8ToByte( rAV
.cbTextAfter
) ) );
766 rNum
.SetSuffix( sP
);
768 // Die Zeichen vor und hinter mehreren Ziffern koennen leider nicht uebernommen
769 // werden, da sie der Writer ganz anders behandelt und das Ergebnis i.A.
770 // schlechter als ohne waere.
774 // SetAnld bekommt einen WW-ANLD-Descriptor und einen Level und modifiziert
775 // die durch pNumR anggebeben NumRules. Wird benutzt fuer alles ausser
776 // Gliederung im Text
777 void SwWW8ImplReader::SetAnld(SwNumRule
* pNumR
, WW8_ANLD
* pAD
, BYTE nSwLevel
,
782 { // Es gibt einen Anld-Sprm
783 bAktAND_fNumberAcross
= 0 != SVBT8ToByte( pAD
->fNumberAcross
);
784 WW8_ANLV
&rAV
= pAD
->eAnlv
;
785 SetBaseAnlv(aNF
, rAV
, nSwLevel
); // Setze Basis-Format
786 SetAnlvStrings(aNF
, rAV
, pAD
->rgchAnld
, bOutLine
);// und Rest
788 pNumR
->Set(nSwLevel
, aNF
);
791 //-------------------------------------------------------
792 // Kapitelnummerierung und Kapitelbullets
793 //-------------------------------------------------------
794 // Kapitelnummerierung findet in Styledefinionen statt. Sprm 13 gibt den Level
795 // an, Sprm 12 den Inhalt
797 SwNumRule
* SwWW8ImplReader::GetStyRule()
799 if( pStyles
->pStyRule
) // Bullet-Style bereits vorhanden
800 return pStyles
->pStyRule
;
802 const String
aBaseName(CREATE_CONST_ASC( "WW8StyleNum" ));
803 const String
aName( rDoc
.GetUniqueNumRuleName( &aBaseName
, false) );
805 // --> OD 2008-06-04 #i86652#
806 // USHORT nRul = rDoc.MakeNumRule( aName );
807 USHORT nRul
= rDoc
.MakeNumRule( aName
, 0, FALSE
,
808 SvxNumberFormat::LABEL_ALIGNMENT
);
810 pStyles
->pStyRule
= rDoc
.GetNumRuleTbl()[nRul
];
811 // Auto == false-> Nummerierungsvorlage
812 pStyles
->pStyRule
->SetAutoRule(false);
814 return pStyles
->pStyRule
;
818 void SwWW8ImplReader::Read_ANLevelNo( USHORT
, const BYTE
* pData
, short nLen
)
820 nSwNumLevel
= 0xff; // Default: ungueltig
828 // nur fuer SwTxtFmtColl, nicht CharFmt
829 // WW: 0 = no Numbering
830 if (pCollA
[nAktColl
].bColl
&& *pData
)
832 // Bereich WW:1..9 -> SW:0..8 keine Aufzaehlung / Nummerierung
834 if (*pData
<= MAXLEVEL
&& *pData
<= 9)
836 nSwNumLevel
= *pData
- 1;
838 //((SwTxtFmtColl*)pAktColl)->SetOutlineLevel( nSwNumLevel ); //#outline level,zhaojianwei
839 ((SwTxtFmtColl
*)pAktColl
)->AssignToListLevelOfOutlineStyle( nSwNumLevel
); //<-end,zhaojianwei
840 // Bei WW-NoNumbering koennte auch NO_NUMBERING gesetzt
841 // werden. ( Bei normaler Nummerierung muss NO_NUM gesetzt
842 // werden: NO_NUM : Nummerierungs-Pause,
843 // NO_NUMBERING : ueberhaupt keine Nummerierung )
846 else if( *pData
== 10 || *pData
== 11 )
848 // Typ merken, der Rest geschieht bei Sprm 12
849 pStyles
->nWwNumLevel
= *pData
;
857 StartAnl(pData
); // Anfang der Gliederung / Aufzaehlung
862 void SwWW8ImplReader::Read_ANLevelDesc( USHORT
, const BYTE
* pData
, short nLen
) // Sprm 12
864 if( !pAktColl
|| nLen
<= 0 // nur bei Styledef
865 || !pCollA
[nAktColl
].bColl
// CharFmt -> ignorieren
866 || ( nIniFlags
& WW8FL_NO_OUTLINE
) ){
870 if( nSwNumLevel
<= MAXLEVEL
// Bereich WW:1..9 -> SW:0..8
871 && nSwNumLevel
<= 9 ){ // keine Aufzaehlung / Nummerierung
873 // Falls bereits direkt oder durch
874 // Vererbung NumruleItems gesetzt sind,
875 // dann jetzt ausschalten #56163
876 pAktColl
->SetFmtAttr( SwNumRuleItem() );
878 String
aName(CREATE_CONST_ASC( "Outline" ));
879 // --> OD 2008-02-11 #newlistlevelattrs#
880 SwNumRule
aNR( rDoc
.GetUniqueNumRuleName( &aName
),
881 SvxNumberFormat::LABEL_WIDTH_AND_POSITION
,
884 aNR
= *rDoc
.GetOutlineNumRule();
886 SetAnld(&aNR
, (WW8_ANLD
*)pData
, nSwNumLevel
, true);
888 // fehlende Level muessen nicht aufgefuellt werden
890 rDoc
.SetOutlineNumRule( aNR
);
891 }else if( pStyles
->nWwNumLevel
== 10 || pStyles
->nWwNumLevel
== 11 ){
892 SwNumRule
* pNR
= GetStyRule();
893 SetAnld(pNR
, (WW8_ANLD
*)pData
, 0, false);
894 pAktColl
->SetFmtAttr( SwNumRuleItem( pNR
->GetName() ) );
895 pCollA
[nAktColl
].bHasStyNumRule
= true;
899 //-----------------------------------------
900 // Nummerierung / Aufzaehlung
901 //-----------------------------------------
903 // SetNumOlst() traegt die Numrules fuer diese Zeile ins SwNumFmt ein
904 // ( nur fuer Gliederungen im Text; Aufzaehlungen / Nummerierungen laufen
906 // dabei wird die Info aus dem OLST geholt und nicht aus dem ANLD ( s.u. )
907 void SwWW8ImplReader::SetNumOlst(SwNumRule
* pNumR
, WW8_OLST
* pO
, BYTE nSwLevel
)
910 WW8_ANLV
&rAV
= pO
->rganlv
[nSwLevel
];
911 SetBaseAnlv(aNF
, rAV
, nSwLevel
);
912 // ... und then the Strings
915 WW8_ANLV
* pAV1
; // search String-Positions
916 for (i
= 0, pAV1
= pO
->rganlv
; i
< nSwLevel
; ++i
, ++pAV1
)
918 nTxtOfs
+= SVBT8ToByte(pAV1
->cbTextBefore
)
919 + SVBT8ToByte(pAV1
->cbTextAfter
);
924 SetAnlvStrings(aNF
, rAV
, pO
->rgch
+ nTxtOfs
, true); // und rein
925 pNumR
->Set(nSwLevel
, aNF
);
928 // der OLST kommt am Anfang jeder Section, die Gliederungen enthaelt. Die ANLDs,
929 // die an jeder Gliederungszeile haengen, enthalten nur Stuss, also werden die
930 // OLSTs waehrend der Section gemerkt, damit die Informationen beim Auftreten
931 // von Gliederungsabsaetzen zugreifbar ist.
932 void SwWW8ImplReader::Read_OLST( USHORT
, const BYTE
* pData
, short nLen
)
936 delete pNumOlst
, pNumOlst
= 0;
940 delete pNumOlst
; // nur sicherheitshalber
941 pNumOlst
= new WW8_OLST
;
942 if( nLen
< sal::static_int_cast
< sal_Int32
>(sizeof( WW8_OLST
)) ) // auffuellen, falls zu kurz
943 memset( pNumOlst
, 0, sizeof( *pNumOlst
) );
944 *pNumOlst
= *(WW8_OLST
*)pData
;
947 WW8LvlType
GetNumType(BYTE nWwLevelNo
)
949 WW8LvlType nRet
= WW8_None
;
950 if( nWwLevelNo
== 12 )
952 else if( nWwLevelNo
== 10 )
953 nRet
= WW8_Numbering
;
954 else if( nWwLevelNo
== 11 )
956 else if( nWwLevelNo
> 0 && nWwLevelNo
<= 9 )
961 SwNumRule
*ANLDRuleMap::GetNumRule(BYTE nNumType
)
963 return (WW8_Numbering
== nNumType
? mpNumberingNumRule
: mpOutlineNumRule
);
966 void ANLDRuleMap::SetNumRule(SwNumRule
*pRule
, BYTE nNumType
)
968 if (WW8_Numbering
== nNumType
)
969 mpNumberingNumRule
= pRule
;
971 mpOutlineNumRule
= pRule
;
975 // StartAnl wird am Anfang eines Zeilenbereichs gerufen,
976 // der Gliederung / Nummerierung / Aufzaehlung enthaelt
977 void SwWW8ImplReader::StartAnl(const BYTE
* pSprm13
)
979 bAktAND_fNumberAcross
= false;
981 BYTE nT
= static_cast< BYTE
>(GetNumType(*pSprm13
));
982 if (nT
== WW8_Pause
|| nT
== WW8_None
)
986 SwNumRule
*pNumRule
= maANLDRules
.GetNumRule(nWwNumType
);
988 // check for COL numbering:
989 const BYTE
* pS12
= 0;// sprmAnld
994 sNumRule
= pTableDesc
->GetNumRuleName();
997 pNumRule
= rDoc
.FindNumRulePtr(sNumRule
);
1002 // this is ROW numbering ?
1003 pS12
= pPlcxMan
->HasParaSprm(bVer67
? 12 : 0xC63E); // sprmAnld
1004 if (pS12
&& 0 != SVBT8ToByte(((WW8_ANLD
*)pS12
)->fNumberAcross
))
1010 if (!sNumRule
.Len() && pCollA
[nAktColl
].bHasStyNumRule
)
1012 sNumRule
= pCollA
[nAktColl
].pFmt
->GetNumRule().GetValue();
1013 pNumRule
= rDoc
.FindNumRulePtr(sNumRule
);
1018 if (!sNumRule
.Len())
1022 // --> OD 2008-06-04 #i86652#
1023 // pNumRule = rDoc.GetNumRuleTbl()[rDoc.MakeNumRule(sNumRule)];
1024 pNumRule
= rDoc
.GetNumRuleTbl()[
1025 rDoc
.MakeNumRule( sNumRule
, 0, FALSE
,
1026 SvxNumberFormat::LABEL_ALIGNMENT
) ];
1032 pS12
= pPlcxMan
->HasParaSprm(bVer67
? 12 : 0xC63E); // sprmAnld
1033 if (!pS12
|| !SVBT8ToByte( ((WW8_ANLD
*)pS12
)->fNumberAcross
))
1034 pTableDesc
->SetNumRuleName(pNumRule
->GetName());
1040 // NumRules ueber Stack setzen
1041 pCtrlStck
->NewAttr(*pPaM
->GetPoint(),
1042 SfxStringItem(RES_FLTR_NUMRULE
, pNumRule
->GetName()));
1044 maANLDRules
.SetNumRule(pNumRule
, nWwNumType
);
1047 // NextAnlLine() wird fuer jede Zeile einer
1048 // Gliederung / Nummerierung / Aufzaehlung einmal gerufen
1049 void SwWW8ImplReader::NextAnlLine(const BYTE
* pSprm13
)
1054 SwNumRule
*pNumRule
= maANLDRules
.GetNumRule(nWwNumType
);
1056 // pNd->UpdateNum ohne Regelwerk gibt GPF spaetestens beim Speichern als
1059 // WW:10 = Nummerierung -> SW:0 & WW:11 = Auffzaehlung -> SW:0
1060 if (*pSprm13
== 10 || *pSprm13
== 11)
1063 if (!pNumRule
->GetNumFmt(nSwNumLevel
))
1065 // noch nicht definiert
1067 const BYTE
* pS12
= pPlcxMan
->HasParaSprm(bVer67
? 12 : 0xC63E);
1068 SetAnld(pNumRule
, (WW8_ANLD
*)pS12
, nSwNumLevel
, false);
1071 else if( *pSprm13
> 0 && *pSprm13
<= MAXLEVEL
) // Bereich WW:1..9 -> SW:0..8
1073 nSwNumLevel
= *pSprm13
- 1; // Gliederung
1074 // noch nicht definiert
1075 if (!pNumRule
->GetNumFmt(nSwNumLevel
))
1077 if (pNumOlst
) // es gab ein OLST
1079 //Assure upper levels are set, #i9556#
1080 for (BYTE nI
= 0; nI
< nSwNumLevel
; ++nI
)
1082 if (!pNumRule
->GetNumFmt(nI
))
1083 SetNumOlst(pNumRule
, pNumOlst
, nI
);
1086 SetNumOlst(pNumRule
, pNumOlst
, nSwNumLevel
);
1088 else // kein Olst, nimm Anld
1091 const BYTE
* pS12
= pPlcxMan
->HasParaSprm(bVer67
? 12 : 0xC63E);
1092 SetAnld(pNumRule
, (WW8_ANLD
*)pS12
, nSwNumLevel
, false);
1097 nSwNumLevel
= 0xff; // keine Nummer
1099 SwTxtNode
* pNd
= pPaM
->GetNode()->GetTxtNode();
1100 if (nSwNumLevel
< MAXLEVEL
)
1101 pNd
->SetAttrListLevel( nSwNumLevel
);
1104 pNd
->SetAttrListLevel(0);
1105 pNd
->SetCountedInList( false );
1109 void SwWW8ImplReader::StopAllAnl(bool bGoBack
)
1111 //Of course we're not restarting, but we'll make use of our knowledge
1112 //of the implementation to do it.
1113 StopAnlToRestart(WW8_None
, bGoBack
);
1116 void SwWW8ImplReader::StopAnlToRestart(BYTE nNewType
, bool bGoBack
)
1120 SwPosition
aTmpPos(*pPaM
->GetPoint());
1121 pPaM
->Move(fnMoveBackward
, fnGoCntnt
);
1122 pCtrlStck
->SetAttr(*pPaM
->GetPoint(), RES_FLTR_NUMRULE
);
1123 *pPaM
->GetPoint() = aTmpPos
;
1126 pCtrlStck
->SetAttr(*pPaM
->GetPoint(), RES_FLTR_NUMRULE
);
1128 maANLDRules
.mpNumberingNumRule
= 0;
1131 my take on this problem is that moving either way from an outline to a
1132 numbering doesn't halt the outline, while the numbering is always halted
1134 bool bNumberingNotStopOutline
=
1135 (((nWwNumType
== WW8_Outline
) && (nNewType
== WW8_Numbering
)) ||
1136 ((nWwNumType
== WW8_Numbering
) && (nNewType
== WW8_Outline
)));
1137 if (!bNumberingNotStopOutline
)
1138 maANLDRules
.mpOutlineNumRule
= 0;
1141 nWwNumType
= WW8_None
;
1145 WW8TabBandDesc::WW8TabBandDesc( WW8TabBandDesc
& rBand
)
1150 pTCs
= new WW8_TCell
[nWwCols
];
1151 memcpy( pTCs
, rBand
.pTCs
, nWwCols
* sizeof( WW8_TCell
) );
1155 pSHDs
= new WW8_SHD
[nWwCols
];
1156 memcpy( pSHDs
, rBand
.pSHDs
, nWwCols
* sizeof( WW8_SHD
) );
1158 if( rBand
.pNewSHDs
)
1160 pNewSHDs
= new sal_uInt32
[nWwCols
];
1161 memcpy(pNewSHDs
, rBand
.pNewSHDs
, nWwCols
* sizeof(sal_uInt32
));
1163 memcpy(aDefBrcs
, rBand
.aDefBrcs
, sizeof(aDefBrcs
));
1166 // ReadDef liest die Zellenpositionen und ggfs die Umrandungen eines Bandes ein
1167 void WW8TabBandDesc::ReadDef(bool bVer67
, const BYTE
* pS
)
1172 short nLen
= (INT16
)SVBT16ToShort( pS
- 2 ); // nicht schoen
1173 BYTE nCols
= *pS
; // Anzahl der Zellen
1174 short nOldCols
= nWwCols
;
1176 if( nCols
> MAX_COL
)
1181 const BYTE
* pT
= &pS
[1];
1184 for(i
=0; i
<=nCols
; i
++, pT
+=2 )
1185 nCenter
[i
] = (INT16
)SVBT16ToShort( pT
); // X-Raender
1186 nLen
-= 2 * ( nCols
+ 1 );
1187 if( nCols
!= nOldCols
) // andere Spaltenzahl
1189 delete[] pTCs
, pTCs
= 0;
1190 delete[] pSHDs
, pSHDs
= 0;
1191 delete[] pNewSHDs
, pNewSHDs
= 0;
1194 short nFileCols
= nLen
/ ( bVer67
? 10 : 20 ); // wirklich abgespeichert
1198 // lege leere TCs an
1199 pTCs
= new WW8_TCell
[nCols
];
1200 setcelldefaults(pTCs
,nCols
);
1208 Achtung: ab Ver8 ist ein reserve-ushort je TC eingefuegt und auch
1209 der Border-Code ist doppelt so gross, daher ist hier
1210 kein simples kopieren moeglich,
1211 d.h.: pTCs[i] = *pTc; geht leider nicht.
1213 Vorteil: Arbeitstruktur ist jetzt viel bequemer zu handhaben!
1215 WW8_TCell
* pAktTC
= pTCs
;
1218 WW8_TCellVer6
* pTc
= (WW8_TCellVer6
*)pT
;
1219 for(i
=0; i
<nFileCols
; i
++, ++pAktTC
,++pTc
)
1223 BYTE aBits1
= SVBT8ToByte( pTc
->aBits1Ver6
);
1224 pAktTC
->bFirstMerged
= ( ( aBits1
& 0x01 ) != 0 );
1225 pAktTC
->bMerged
= ( ( aBits1
& 0x02 ) != 0 );
1226 memcpy( pAktTC
->rgbrc
[ WW8_TOP
].aBits1
,
1227 pTc
->rgbrcVer6
[ WW8_TOP
].aBits1
, sizeof( SVBT16
) );
1228 memcpy( pAktTC
->rgbrc
[ WW8_LEFT
].aBits1
,
1229 pTc
->rgbrcVer6
[ WW8_LEFT
].aBits1
, sizeof( SVBT16
) );
1230 memcpy( pAktTC
->rgbrc
[ WW8_BOT
].aBits1
,
1231 pTc
->rgbrcVer6
[ WW8_BOT
].aBits1
, sizeof( SVBT16
) );
1232 memcpy( pAktTC
->rgbrc
[ WW8_RIGHT
].aBits1
,
1233 pTc
->rgbrcVer6
[ WW8_RIGHT
].aBits1
, sizeof( SVBT16
) );
1234 if( ( pAktTC
->bMerged
)
1237 // Cell gemerged -> merken
1238 //bWWMergedVer6[i] = true;
1239 memcpy( pTCs
[i
-1].rgbrc
[ WW8_RIGHT
].aBits1
,
1240 pTc
->rgbrcVer6
[ WW8_RIGHT
].aBits1
, sizeof( SVBT16
) );
1241 // right Border in vorige Zelle uebernehmen
1242 // Hier darf bExist nicht auf false gesetzt werden, da WW
1243 // in den Textboxen diese Zellen nicht mitzaehlt....
1250 WW8_TCellVer8
* pTc
= (WW8_TCellVer8
*)pT
;
1251 for (int k
= 0; k
< nFileCols
; ++k
, ++pAktTC
, ++pTc
)
1253 UINT16 aBits1
= SVBT16ToShort( pTc
->aBits1Ver8
);
1254 pAktTC
->bFirstMerged
= ( ( aBits1
& 0x0001 ) != 0 );
1255 pAktTC
->bMerged
= ( ( aBits1
& 0x0002 ) != 0 );
1256 pAktTC
->bVertical
= ( ( aBits1
& 0x0004 ) != 0 );
1257 pAktTC
->bBackward
= ( ( aBits1
& 0x0008 ) != 0 );
1258 pAktTC
->bRotateFont
= ( ( aBits1
& 0x0010 ) != 0 );
1259 pAktTC
->bVertMerge
= ( ( aBits1
& 0x0020 ) != 0 );
1260 pAktTC
->bVertRestart
= ( ( aBits1
& 0x0040 ) != 0 );
1261 pAktTC
->nVertAlign
= ( ( aBits1
& 0x0180 ) >> 7 );
1262 // am Rande: im aBits1 verstecken sich noch 7 Reserve-Bits,
1263 // anschliessend folgen noch 16 weitere Reserve-Bits
1265 // In Version 8 koennen wir alle Bordercodes auf einmal kopieren!
1266 memcpy( pAktTC
->rgbrc
, pTc
->rgbrcVer8
, 4 * sizeof( WW8_BRC
) );
1270 // #i25071 In '97 text direction appears to be only set using TC properties
1271 // not with sprmTTextFlow so we need to cycle through the maDirections and
1272 // double check any non-default directions
1273 for (int k
= 0; k
< nCols
; ++k
)
1275 if(maDirections
[k
] == 4)
1277 if(pTCs
[k
].bVertical
)
1279 if(pTCs
[k
].bBackward
)
1280 maDirections
[k
] = 3;
1282 maDirections
[k
] = 1;
1291 void WW8TabBandDesc::ProcessSprmTSetBRC(bool bVer67
, const BYTE
* pParamsTSetBRC
)
1293 if( pParamsTSetBRC
&& pTCs
) // set one or more cell border(s)
1295 BYTE nitcFirst
= pParamsTSetBRC
[0];// first col to be changed
1296 BYTE nitcLim
= pParamsTSetBRC
[1];// (last col to be changed)+1
1297 BYTE nFlag
= *(pParamsTSetBRC
+2);
1299 bool bChangeRight
= (nFlag
& 0x08) ? true : false;
1300 bool bChangeBottom
= (nFlag
& 0x04) ? true : false;
1301 bool bChangeLeft
= (nFlag
& 0x02) ? true : false;
1302 bool bChangeTop
= (nFlag
& 0x01) ? true : false;
1304 WW8_TCell
* pAktTC
= pTCs
+ nitcFirst
;
1307 WW8_BRCVer6
* pBRC
= (WW8_BRCVer6
*)(pParamsTSetBRC
+3);
1309 for( int i
= nitcFirst
; i
< nitcLim
; i
++, ++pAktTC
)
1312 memcpy( pAktTC
->rgbrc
[ WW8_TOP
].aBits1
,
1316 memcpy( pAktTC
->rgbrc
[ WW8_LEFT
].aBits1
,
1320 memcpy( pAktTC
->rgbrc
[ WW8_BOT
].aBits1
,
1324 memcpy( pAktTC
->rgbrc
[ WW8_RIGHT
].aBits1
,
1331 WW8_BRC
* pBRC
= (WW8_BRC
*)(pParamsTSetBRC
+3);
1333 for( int i
= nitcFirst
; i
< nitcLim
; i
++, ++pAktTC
)
1336 memcpy( pAktTC
->rgbrc
[ WW8_TOP
].aBits1
,
1338 sizeof( WW8_BRC
) );
1340 memcpy( pAktTC
->rgbrc
[ WW8_LEFT
].aBits1
,
1342 sizeof( WW8_BRC
) );
1344 memcpy( pAktTC
->rgbrc
[ WW8_BOT
].aBits1
,
1346 sizeof( WW8_BRC
) );
1348 memcpy( pAktTC
->rgbrc
[ WW8_RIGHT
].aBits1
,
1350 sizeof( WW8_BRC
) );
1359 void WW8TabBandDesc::ProcessSprmTTableBorders(bool bVer67
, const BYTE
* pParams
)
1361 // sprmTTableBorders
1364 for( int i
= 0; i
< 6; ++i
)
1366 aDefBrcs
[i
].aBits1
[0] = pParams
[ 2*i
];
1367 aDefBrcs
[i
].aBits1
[1] = pParams
[ 1+2*i
];
1370 else // aDefBrcs = *(BRC(*)[6])pS;
1371 memcpy( aDefBrcs
, pParams
, 24 );
1374 void WW8TabBandDesc::ProcessSprmTDxaCol(const BYTE
* pParamsTDxaCol
)
1376 // sprmTDxaCol (opcode 0x7623) changes the width of cells
1377 // whose index is within a certain range to be a certain value.
1379 if( nWwCols
&& pParamsTDxaCol
) // set one or more cell length(s)
1381 BYTE nitcFirst
= pParamsTDxaCol
[0]; // first col to be changed
1382 BYTE nitcLim
= pParamsTDxaCol
[1]; // (last col to be changed)+1
1383 short nDxaCol
= (INT16
)SVBT16ToShort( pParamsTDxaCol
+ 2 );
1387 for( int i
= nitcFirst
; (i
< nitcLim
) && (i
< nWwCols
); i
++ )
1389 nOrgWidth
= nCenter
[i
+1] - nCenter
[i
];
1390 nDelta
= nDxaCol
- nOrgWidth
;
1391 for( int j
= i
+1; j
<= nWwCols
; j
++ )
1393 nCenter
[j
] = nCenter
[j
] + nDelta
;
1399 void WW8TabBandDesc::ProcessSprmTInsert(const BYTE
* pParamsTInsert
)
1401 if( nWwCols
&& pParamsTInsert
) // set one or more cell length(s)
1403 BYTE nitcInsert
= pParamsTInsert
[0]; // position at which to insert
1404 if (nitcInsert
>= MAX_COL
) // cannot insert into cell outside max possible index
1406 BYTE nctc
= pParamsTInsert
[1]; // number of cells
1407 USHORT ndxaCol
= SVBT16ToShort( pParamsTInsert
+2 );
1410 if (nitcInsert
> nWwCols
)
1412 nNewWwCols
= nitcInsert
+nctc
;
1413 //if new count would be outside max possible count, clip it, and calc a new replacement
1415 if (nNewWwCols
> MAX_COL
)
1417 nNewWwCols
= MAX_COL
;
1418 nctc
= ::sal::static_int_cast
<BYTE
>(nNewWwCols
-nitcInsert
);
1423 nNewWwCols
= nWwCols
+nctc
;
1424 //if new count would be outside max possible count, clip it, and calc a new replacement
1426 if (nNewWwCols
> MAX_COL
)
1428 nNewWwCols
= MAX_COL
;
1429 nctc
= ::sal::static_int_cast
<BYTE
>(nNewWwCols
-nWwCols
);
1433 WW8_TCell
*pTC2s
= new WW8_TCell
[nNewWwCols
];
1434 setcelldefaults(pTC2s
, nNewWwCols
);
1438 memcpy( pTC2s
, pTCs
, nWwCols
* sizeof( WW8_TCell
) );
1443 //If we have to move some cells
1444 if (nitcInsert
<= nWwCols
)
1446 // adjust the left x-position of the dummy at the very end
1447 nCenter
[nWwCols
+ nctc
] = nCenter
[nWwCols
]+nctc
*ndxaCol
;
1448 for( int i
= nWwCols
-1; i
>= nitcInsert
; i
--)
1450 // adjust the left x-position
1451 nCenter
[i
+ nctc
] = nCenter
[i
]+nctc
*ndxaCol
;
1453 // adjust the cell's borders
1454 pTCs
[i
+ nctc
] = pTCs
[i
];
1458 //if itcMac is larger than full size, fill in missing ones first
1459 for( int i
= nWwCols
; i
> nitcInsert
+nWwCols
; i
--)
1460 nCenter
[i
] = i
? (nCenter
[i
- 1]+ndxaCol
) : 0;
1462 //now add in our new cells
1463 for( int j
= 0;j
< nctc
; j
++)
1464 nCenter
[j
+ nitcInsert
] = (j
+ nitcInsert
) ? (nCenter
[j
+ nitcInsert
-1]+ndxaCol
) : 0;
1466 nWwCols
= nNewWwCols
;
1470 void WW8TabBandDesc::ProcessDirection(const BYTE
* pParams
)
1472 sal_uInt8 nStartCell
= *pParams
++;
1473 sal_uInt8 nEndCell
= *pParams
++;
1474 sal_uInt16 nCode
= SVBT16ToShort(pParams
);
1476 ASSERT(nStartCell
< nEndCell
, "not as I thought");
1477 ASSERT(nEndCell
< MAX_COL
+ 1, "not as I thought");
1478 if (nStartCell
> MAX_COL
)
1480 if (nEndCell
> MAX_COL
+ 1)
1481 nEndCell
= MAX_COL
+ 1;
1483 for (;nStartCell
< nEndCell
; ++nStartCell
)
1484 maDirections
[nStartCell
] = nCode
;
1487 void WW8TabBandDesc::ProcessSpacing(const BYTE
* pParams
)
1489 BYTE nLen
= pParams
? *(pParams
- 1) : 0;
1490 ASSERT(nLen
== 6, "Unexpected spacing len");
1498 ASSERT(nWhichCell
== 0, "Expected cell to be 0!");
1499 *pParams
++; //unknown byte
1501 BYTE nSideBits
= *pParams
++;
1502 ASSERT(nSideBits
< 0x10, "Unexpected value for nSideBits");
1503 *pParams
++; //unknown byte
1504 USHORT nValue
= SVBT16ToShort( pParams
);
1505 for (int i
= wwTOP
; i
<= wwRIGHT
; i
++)
1507 switch (nSideBits
& (1 << i
))
1510 mnDefaultTop
= nValue
;
1513 mnDefaultLeft
= nValue
;
1516 mnDefaultBottom
= nValue
;
1519 mnDefaultRight
= nValue
;
1524 ASSERT(!this, "Impossible");
1530 void WW8TabBandDesc::ProcessSpecificSpacing(const BYTE
* pParams
)
1532 BYTE nLen
= pParams
? *(pParams
- 1) : 0;
1533 ASSERT(nLen
== 6, "Unexpected spacing len");
1536 BYTE nWhichCell
= *pParams
++;
1537 ASSERT(nWhichCell
< MAX_COL
+ 1, "Cell out of range in spacings");
1538 if (nWhichCell
>= MAX_COL
+ 1)
1541 *pParams
++; //unknown byte
1542 BYTE nSideBits
= *pParams
++;
1543 ASSERT(nSideBits
< 0x10, "Unexpected value for nSideBits");
1544 nOverrideSpacing
[nWhichCell
] |= nSideBits
;
1546 ASSERT(nOverrideSpacing
[nWhichCell
] < 0x10,
1547 "Unexpected value for nSideBits");
1552 ASSERT(nUnknown2
== 0x3, "Unexpected value for spacing2");
1553 USHORT nValue
= SVBT16ToShort( pParams
);
1555 for (int i
=0; i
< 4; i
++)
1557 if (nSideBits
& (1 << i
))
1558 nOverrideValues
[nWhichCell
][i
] = nValue
;
1562 void WW8TabBandDesc::ProcessSprmTDelete(const BYTE
* pParamsTDelete
)
1564 if( nWwCols
&& pParamsTDelete
) // set one or more cell length(s)
1566 BYTE nitcFirst
= pParamsTDelete
[0]; // first col to be deleted
1567 if (nitcFirst
>= nWwCols
) // first index to delete from doesn't exist
1569 BYTE nitcLim
= pParamsTDelete
[1]; // (last col to be deleted)+1
1570 if (nitcLim
<= nitcFirst
) // second index to delete to is not greater than first index
1574 * sprmTDelete causes any rgdxaCenter and rgtc entries whose index is
1575 * greater than or equal to itcLim to be moved
1577 int nShlCnt
= nWwCols
- nitcLim
; // count of cells to be shifted
1579 if (nShlCnt
>= 0) //There exist entries whose index is greater than or equal to itcLim
1581 WW8_TCell
* pAktTC
= pTCs
+ nitcFirst
;
1583 while( i
< nShlCnt
)
1585 // adjust the left x-position
1586 nCenter
[nitcFirst
+ i
] = nCenter
[nitcLim
+ i
];
1588 // adjust the cell's borders
1589 *pAktTC
= pTCs
[ nitcLim
+ i
];
1594 // adjust the left x-position of the dummy at the very end
1595 nCenter
[nitcFirst
+ i
] = nCenter
[nitcLim
+ i
];
1598 short nCellsDeleted
= nitcLim
- nitcFirst
;
1599 //clip delete request to available number of cells
1600 if (nCellsDeleted
> nWwCols
)
1601 nCellsDeleted
= nWwCols
;
1602 nWwCols
-= nCellsDeleted
;
1606 // ReadShd liest ggfs die Hintergrundfarben einer Zeile ein.
1607 // Es muss vorher ReadDef aufgerufen worden sein
1608 void WW8TabBandDesc::ReadShd(const BYTE
* pS
)
1610 BYTE nLen
= pS
? *(pS
- 1) : 0;
1616 pSHDs
= new WW8_SHD
[nWwCols
];
1617 memset( pSHDs
, 0, nWwCols
* sizeof( WW8_SHD
) );
1620 short nAnz
= nLen
>> 1;
1626 for(i
=0, pShd
= (SVBT16
*)pS
; i
<nAnz
; i
++, pShd
++ )
1627 pSHDs
[i
].SetWWValue( *pShd
);
1630 void WW8TabBandDesc::ReadNewShd(const BYTE
* pS
, bool bVer67
)
1632 BYTE nLen
= pS
? *(pS
- 1) : 0;
1637 pNewSHDs
= new sal_uInt32
[nWwCols
];
1639 short nAnz
= nLen
/ 10; //10 bytes each
1645 pNewSHDs
[i
++] = SwWW8ImplReader::ExtractColour(pS
, bVer67
);
1648 pNewSHDs
[i
++] = COL_AUTO
;
1651 void WW8TabBandDesc::setcelldefaults(WW8_TCell
*pCells
, short nCols
)
1653 memset( pCells
, 0, nCols
* sizeof( WW8_TCell
) );
1656 const BYTE
*HasTabCellSprm(WW8PLCFx_Cp_FKP
* pPap
, bool bVer67
)
1658 const BYTE
*pParams
;
1660 pParams
= pPap
->HasSprm(24);
1663 if (0 == (pParams
= pPap
->HasSprm(0x244B)))
1664 pParams
= pPap
->HasSprm(0x2416);
1673 sprmTTableWidth
,sprmTTextFlow
, sprmTFCantSplit
, sprmTFCantSplit90
,sprmTJc
, sprmTFBiDi
, sprmTDefTable
,
1674 sprmTDyaRowHeight
, sprmTDefTableShd
, sprmTDxaLeft
, sprmTSetBrc
,
1675 sprmTDxaCol
, sprmTInsert
, sprmTDelete
, sprmTTableHeader
,
1676 sprmTDxaGapHalf
, sprmTTableBorders
,
1678 sprmTDefTableNewShd
, sprmTSpacing
, sprmTNewSpacing
1681 wwTableSprm
GetTableSprm(sal_uInt16 nId
, ww::WordVersion eVer
)
1689 return sprmTTableWidth
;
1691 return sprmTTextFlow
;
1693 return sprmTFCantSplit
;
1695 return sprmTTableHeader
;
1697 return sprmTFCantSplit90
;
1709 return sprmTDyaRowHeight
;
1711 return sprmTDxaLeft
;
1713 return sprmTDxaGapHalf
;
1715 return sprmTTableBorders
;
1717 return sprmTDefTable
;
1719 return sprmTDefTableShd
;
1721 return sprmTDefTableNewShd
;
1725 return sprmTSpacing
;
1727 return sprmTNewSpacing
;
1737 return sprmTDxaLeft
;
1739 return sprmTDxaGapHalf
;
1741 return sprmTTableHeader
;
1743 return sprmTTableBorders
;
1745 return sprmTDyaRowHeight
;
1747 return sprmTDefTable
;
1749 return sprmTDefTableShd
;
1766 return sprmTDxaLeft
;
1768 return sprmTDxaGapHalf
;
1770 return sprmTDyaRowHeight
;
1772 return sprmTDefTable
;
1774 return sprmTDefTableShd
;
1789 WW8TabDesc::WW8TabDesc(SwWW8ImplReader
* pIoClass
, WW8_CP nStartCp
) :
1790 mpOldRedlineStack(0),
1812 bClaimLineFmt(false),
1813 eOri(text::HoriOrientation::NONE
),
1822 aItemSet(pIo
->rDoc
.GetAttrPool(),RES_FRMATR_BEGIN
,RES_FRMATR_END
-1)
1824 pIo
->bAktAND_fNumberAcross
= false;
1826 static const sal_Int16 aOriArr
[] =
1828 text::HoriOrientation::LEFT
, text::HoriOrientation::CENTER
, text::HoriOrientation::RIGHT
, text::HoriOrientation::CENTER
1831 bool bOldVer
= ww::IsSevenMinus(pIo
->GetFib().GetFIBVersion());
1832 WW8_TablePos aTabPos
;
1834 WW8PLCFxSave1 aSave
;
1835 pIo
->pPlcxMan
->GetPap()->Save( aSave
);
1837 WW8PLCFx_Cp_FKP
* pPap
= pIo
->pPlcxMan
->GetPapPLCF();
1839 eOri
= text::HoriOrientation::LEFT
;
1841 WW8TabBandDesc
* pNewBand
= new WW8TabBandDesc
;
1843 wwSprmParser
aSprmParser(pIo
->GetFib().GetFIBVersion());
1845 // process pPap until end of table found
1848 short nTabeDxaNew
= SHRT_MAX
;
1849 bool bTabRowJustRead
= false;
1850 const BYTE
* pShadeSprm
= 0;
1851 const BYTE
* pNewShadeSprm
= 0;
1852 WW8_TablePos
*pTabPos
= 0;
1854 // Suche Ende einer TabZeile
1855 if(!(pIo
->SearchRowEnd(pPap
, nStartCp
, pIo
->nInTable
)))
1861 // Get the SPRM chains:
1862 // first from PAP and then from PCD (of the Piece Table)
1864 pPap
->GetSprms( &aDesc
);
1865 WW8SprmIter
aSprmIter(aDesc
.pMemPos
, aDesc
.nSprmsLen
, aSprmParser
);
1867 const BYTE
* pParams
= aSprmIter
.GetAktParams();
1868 for (int nLoop
= 0; nLoop
< 2; ++nLoop
)
1870 bool bRepeatedSprm
= false;
1871 while (aSprmIter
.GetSprms() && 0 != (pParams
= aSprmIter
.GetAktParams()))
1873 sal_uInt16 nId
= aSprmIter
.GetAktId();
1874 wwTableSprm eSprm
= GetTableSprm(nId
, pIo
->GetFib().GetFIBVersion());
1877 case sprmTTableWidth
:
1879 const BYTE b0
= pParams
[0];
1880 const BYTE b1
= pParams
[1];
1881 const BYTE b2
= pParams
[2];
1882 if (b0
== 3) // Twips
1883 nPreferredWidth
= b2
* 0x100 + b1
;
1887 pNewBand
->ProcessDirection(pParams
);
1889 case sprmTFCantSplit
:
1890 pNewBand
->bCantSplit
= *pParams
;
1891 bClaimLineFmt
= true;
1893 case sprmTFCantSplit90
:
1894 pNewBand
->bCantSplit90
= *pParams
;
1895 bClaimLineFmt
= true;
1897 case sprmTTableBorders
:
1898 pNewBand
->ProcessSprmTTableBorders(bOldVer
, pParams
);
1900 case sprmTTableHeader
:
1904 bRepeatedSprm
= true;
1908 // sprmTJc - Justification Code
1910 eOri
= aOriArr
[*pParams
& 0x3];
1913 bIsBiDi
= SVBT16ToShort(pParams
) ? true : false;
1915 case sprmTDxaGapHalf
:
1916 pNewBand
->nGapHalf
= (INT16
)SVBT16ToShort( pParams
);
1918 case sprmTDyaRowHeight
:
1919 pNewBand
->nLineHeight
= (INT16
)SVBT16ToShort( pParams
);
1920 bClaimLineFmt
= true;
1923 pNewBand
->ReadDef(bOldVer
, pParams
);
1924 bTabRowJustRead
= true;
1926 case sprmTDefTableShd
:
1927 pShadeSprm
= pParams
;
1929 case sprmTDefTableNewShd
:
1930 pNewShadeSprm
= pParams
;
1933 // our Writer cannot shift single table lines
1934 // horizontally so we have to find the smallest
1935 // parameter (meaning the left-most position) and then
1936 // shift the whole table to that margin (see below)
1938 short nDxaNew
= (INT16
)SVBT16ToShort( pParams
);
1939 nOrgDxaLeft
= nDxaNew
;
1940 if( nDxaNew
< nTabeDxaNew
)
1941 nTabeDxaNew
= nDxaNew
;
1945 pNewBand
->ProcessSprmTSetBRC(bOldVer
, pParams
);
1948 pNewBand
->ProcessSprmTDxaCol(pParams
);
1951 pNewBand
->ProcessSprmTInsert(pParams
);
1954 pNewBand
->ProcessSprmTDelete(pParams
);
1956 case sprmTNewSpacing
:
1957 pNewBand
->ProcessSpacing(pParams
);
1960 pNewBand
->ProcessSpecificSpacing(pParams
);
1970 pPap
->GetPCDSprms( aDesc
);
1971 aSprmIter
.SetSprms( aDesc
.pMemPos
, aDesc
.nSprmsLen
);
1975 // #55171: WW-Tabellen koennen Fly-Wechsel beinhalten daher hier
1976 // Tabellen abbrechen und neu beginnen noch steht *pPap noch vor
1977 // TabRowEnd, daher kann TestApo() mit letztem Parameter false und
1978 // damit wirksam gerufen werden.
1980 if (bTabRowJustRead
)
1983 pNewBand
->ReadShd(pShadeSprm
);
1985 pNewBand
->ReadNewShd(pNewShadeSprm
, bOldVer
);
1988 if( nTabeDxaNew
< SHRT_MAX
)
1990 short* pCenter
= pNewBand
->nCenter
;
1991 short firstDxaCenter
= *pCenter
;
1992 for( int i
= 0; i
< pNewBand
->nWwCols
; i
++, ++pCenter
)
1994 // #i30298# Use sprmTDxaLeft to adjust the left indent
1995 // #i40461# Use dxaGapHalf during calculation
1997 (nTabeDxaNew
- (firstDxaCenter
+ pNewBand
->nGapHalf
));
2002 pActBand
= pFirstBand
= pNewBand
;
2005 pActBand
->pNextBand
= pNewBand
;
2006 pActBand
= pNewBand
;
2010 pNewBand
= new WW8TabBandDesc
;
2015 //Seek our pap to its next block of properties
2018 aRes
.nStartPos
= nStartCp
;
2020 if (!(pPap
->SeekPos(aRes
.nStartPos
)))
2022 aRes
.nEndPos
= WW8_CP_MAX
;
2023 pPap
->SetDirty(true);
2025 pPap
->GetSprms(&aRes
);
2026 pPap
->SetDirty(false);
2028 //Are we at the end of available properties
2030 !pPap
->HasFkp() || pPap
->Where() == WW8_CP_MAX
||
2031 aRes
.nStartPos
== WW8_CP_MAX
2038 //Are we still in a table cell
2039 pParams
= HasTabCellSprm(pPap
, bOldVer
);
2040 const BYTE
*pLevel
= pPap
->HasSprm(0x6649);
2042 if (!pParams
|| (1 != *pParams
) ||
2043 (pLevel
&& (*pLevel
<= pIo
->nInTable
)))
2048 //Get the end of row new table positioning data
2049 WW8_CP nMyStartCp
=nStartCp
;
2050 if (pIo
->SearchRowEnd(pPap
, nMyStartCp
, pIo
->nInTable
))
2051 if (SwWW8ImplReader::ParseTabPos(&aTabPos
, pPap
))
2054 //Move back to this cell
2056 aRes
.nStartPos
= nStartCp
;
2058 // #114237 PlcxMan currently points too far ahead so we need to bring
2059 // it back to where we are trying to make a table
2060 pIo
->pPlcxMan
->GetPap()->nOrigStartPos
= aRes
.nStartPos
;
2061 if (!(pPap
->SeekPos(aRes
.nStartPos
)))
2063 aRes
.nEndPos
= WW8_CP_MAX
;
2064 pPap
->SetDirty(true);
2066 pPap
->GetSprms(&aRes
);
2067 pPap
->SetDirty(false);
2069 //Does this row match up with the last row closely enough to be
2070 //considered part of the same table
2071 ApoTestResults aApo
= pIo
->TestApo(pIo
->nInTable
+ 1, false, pTabPos
);
2074 ##513##, #79474# If this is not sufficent, then we should look at
2075 sprmPD{y|x}aAbs as our indicator that the following set of rows is not
2076 part of this table, but instead is an absolutely positioned table
2081 if (aApo
.mbStartApo
)
2083 //if there really is a fly here, and not a "null" fly then break.
2084 WW8FlyPara
*pNewFly
= pIo
->ConstructApo(aApo
, pTabPos
);
2091 nStartCp
= aRes
.nEndPos
;
2097 if( pActBand
->nRows
> 1 )
2099 // Letztes Band hat mehr als 1 Zeile
2101 pNewBand
= new WW8TabBandDesc( *pActBand
); // neues machen
2102 pActBand
->nRows
--; // wegen Sonderbehandlung Raender-Defaults
2103 pNewBand
->nRows
= 1;
2104 pActBand
->pNextBand
= pNewBand
; // am Ende einschleifen
2106 pNewBand
= 0; // nicht loeschen
2112 pIo
->pPlcxMan
->GetPap()->Restore( aSave
);
2115 WW8TabDesc::~WW8TabDesc()
2117 WW8TabBandDesc
* pR
= pFirstBand
;
2120 WW8TabBandDesc
* pR2
= pR
->pNextBand
;
2126 delete pMergeGroups
;
2129 void WW8TabDesc::CalcDefaults()
2131 short nMinCols
= SHRT_MAX
;
2134 nMinLeft
= SHRT_MAX
;
2135 nMaxRight
= SHRT_MIN
;
2139 If we are an honestly inline centered table, then the normal rules of
2140 engagement for left and right margins do not apply. The multiple rows are
2141 centered regardless of the actual placement of rows, so we cannot have
2142 mismatched rows as is possible in other configurations.
2144 e.g. change the example bugdoc in word from text wrapping of none (inline)
2145 to around (in frame (bApo)) and the table splits into two very disjoint
2146 rows as the beginning point of each row are very different
2148 if ((!pIo
->InLocalApo()) && (eOri
== text::HoriOrientation::CENTER
))
2150 for (pR
= pFirstBand
; pR
; pR
= pR
->pNextBand
)
2151 for( short i
= pR
->nWwCols
; i
>= 0; --i
)
2152 pR
->nCenter
[i
] = pR
->nCenter
[i
] - pR
->nCenter
[0];
2155 // 1. Durchlauf: aeusserste L- und R-Grenzen finden
2156 for( pR
= pFirstBand
; pR
; pR
= pR
->pNextBand
)
2158 if( pR
->nCenter
[0] < nMinLeft
)
2159 nMinLeft
= pR
->nCenter
[0];
2161 for( short i
= 0; i
< pR
->nWwCols
; i
++ )
2164 #74387# If the margins are so large as to make the displayable
2165 area inside them smaller than the minimum allowed then adjust the
2166 width to fit. But only do it if the two cells are not the exact
2167 same value, if they are then the cell does not really exist and will
2168 be blended together into the same cell through the use of the
2170 #i28333# If the nGapHalf is greater than the cell width best to ignore it
2172 int nCellWidth
= pR
->nCenter
[i
+1] - pR
->nCenter
[i
];
2173 if (nCellWidth
&& ((nCellWidth
- pR
->nGapHalf
*2) < MINLAY
) && pR
->nGapHalf
< nCellWidth
)
2175 pR
->nCenter
[i
+1] = pR
->nCenter
[i
]+MINLAY
+pR
->nGapHalf
* 2;
2179 if( pR
->nCenter
[pR
->nWwCols
] > nMaxRight
)
2180 nMaxRight
= pR
->nCenter
[pR
->nWwCols
];
2182 nSwWidth
= nMaxRight
- nMinLeft
;
2184 // #109830# If the table is right aligned we need to align all rows to the
2185 // row that has the furthest right point
2187 if(eOri
== text::HoriOrientation::RIGHT
)
2189 for( pR
= pFirstBand
; pR
; pR
= pR
->pNextBand
)
2191 int adjust
= nMaxRight
- pR
->nCenter
[pR
->nWwCols
];
2192 for( short i
= 0; i
< pR
->nWwCols
+ 1; i
++ )
2194 pR
->nCenter
[i
] = static_cast< short >(pR
->nCenter
[i
] + adjust
);
2200 // 2. Durchlauf: Zahl der Writer-Spalten feststellen Die Zahl der Writer
2201 // Spalten kann um bis zu 2 hoeher sein als im WW, da der SW im Gegensatz
2202 // zu WW keine ausgefransten linken und rechten Raender kann und diese
2203 // durch leere Boxen aufgefuellt werden. Durch nichtexistente Zellen
2204 // koennen auch Zellen wegfallen
2206 // 3. Durchlauf: Wo noetig die Umrandungen durch die Defaults ersetzen
2207 nConvertedLeft
= nMinLeft
;
2209 short nLeftMaxThickness
= 0, nRightMaxThickness
=0;
2210 for( pR
= pFirstBand
; pR
; pR
= pR
->pNextBand
)
2214 pR
->pTCs
= new WW8_TCell
[ pR
->nWwCols
];
2215 memset( pR
->pTCs
, 0, pR
->nWwCols
* sizeof( WW8_TCell
) );
2217 for (int k
= 0; k
< pR
->nWwCols
; ++k
)
2219 WW8_TCell
* pT
= &pR
->pTCs
[k
];
2221 for( i
= 0; i
< 4; i
++ )
2223 if (pT
->rgbrc
[i
].IsZeroed(pIo
->bVer67
))
2225 // if shadow is set, its invalid
2230 // Aussen oben / Innen waagerecht
2231 j
= (pR
== pFirstBand
) ? 0 : 4;
2234 // Aussen links / Innen senkrecht
2238 // Aussen unten / Innen waagerecht
2239 j
= pR
->pNextBand
? 4 : 2;
2242 // Aussen rechts/ Innen senkrecht
2243 j
= (k
== pR
->nWwCols
- 1) ? 3 : 5;
2246 // mangel mit Defaults ueber
2247 pT
->rgbrc
[i
] = pR
->aDefBrcs
[j
];
2252 Similiar to graphics and other elements word does not totally
2253 factor the width of the border into its calculations of size, we
2254 do so we must adjust out widths and other dimensions to fit. It
2255 appears that what occurs is that the last cell's right margin if
2256 the margin width that is not calculated into winwords table
2257 dimensions, so in that case increase the table to include the
2258 extra width of the right margin.
2261 !(SVBT16ToShort(pR
->pTCs
[pR
->nWwCols
-1].rgbrc
[3].aBits1
) & 0x20)
2262 : !(SVBT16ToShort(pR
->pTCs
[pR
->nWwCols
-1].rgbrc
[3].aBits2
) & 0x2000))
2264 short nThickness
= pR
->pTCs
[pR
->nWwCols
-1].rgbrc
[3].
2265 DetermineBorderProperties(pIo
->bVer67
);
2266 pR
->nCenter
[pR
->nWwCols
] = pR
->nCenter
[pR
->nWwCols
] + nThickness
;
2267 if (nThickness
> nRightMaxThickness
)
2268 nRightMaxThickness
= nThickness
;
2272 The left space of the table is in nMinLeft, but again this
2273 does not consider the margin thickness to its left in the
2274 placement value, so get the thickness of the left border,
2275 half is placed to the left of the nominal left side, and
2279 !(SVBT16ToShort(pR
->pTCs
[0].rgbrc
[1].aBits1
) & 0x20)
2280 : !(SVBT16ToShort(pR
->pTCs
[0].rgbrc
[1].aBits2
) & 0x2000))
2282 short nThickness
= pR
->pTCs
[0].rgbrc
[1].
2283 DetermineBorderProperties(pIo
->bVer67
);
2284 if (nThickness
> nLeftMaxThickness
)
2285 nLeftMaxThickness
= nThickness
;
2288 nSwWidth
= nSwWidth
+ nRightMaxThickness
;
2289 nMaxRight
= nMaxRight
+ nRightMaxThickness
;
2290 nConvertedLeft
= nMinLeft
-(nLeftMaxThickness
/2);
2292 for( pR
= pFirstBand
; pR
; pR
= pR
->pNextBand
)
2294 pR
->nSwCols
= pR
->nWwCols
;
2295 pR
->bLEmptyCol
= pR
->nCenter
[0] - nMinLeft
>= MINLAY
;
2296 pR
->bREmptyCol
= (nMaxRight
- pR
->nCenter
[pR
->nWwCols
] - nRightMaxThickness
) >= MINLAY
;
2298 short nAddCols
= pR
->bLEmptyCol
+ pR
->bREmptyCol
;
2300 USHORT j
= ( pR
->bLEmptyCol
) ? 1 : 0;
2301 for (i
= 0; i
< pR
->nWwCols
; ++i
)
2303 pR
->nTransCell
[i
] = (INT8
)j
;
2304 if ( pR
->nCenter
[i
] < pR
->nCenter
[i
+1] )
2306 pR
->bExist
[i
] = true;
2311 pR
->bExist
[i
] = false;
2316 ASSERT(i
,"no columns in row ?");
2320 If the last cell was "false" then there is no valid cell following it,
2321 so the default mapping forward wont't work. So map it (and
2322 contigious invalid cells backwards to the last valid cell instead.
2324 if (i
&& pR
->bExist
[i
-1] == false)
2327 while (k
&& pR
->bExist
[k
] == false)
2329 for (USHORT n
=k
+1;n
<i
;n
++)
2330 pR
->nTransCell
[n
] = pR
->nTransCell
[k
];
2333 pR
->nTransCell
[i
++] = (INT8
)(j
++); // Wird u.a. wegen bREmptyCol um
2334 pR
->nTransCell
[i
] = (INT8
)j
; // max. 2 ueberindiziert
2336 pR
->nSwCols
= pR
->nSwCols
+ nAddCols
;
2337 if( pR
->nSwCols
< nMinCols
)
2338 nMinCols
= pR
->nSwCols
;
2343 Find the largest of the borders on cells that adjoin top bottom and remove
2344 the val from the top and put in on the bottom cell. I can't seem to make
2345 disjoint upper and lowers to see what happens there.
2348 /* #i29550# FME 2004-06-02 Removed this code because of the implementation
2349 of the collapsing table borders model. So this should not be necessary
2352 /* for (pR = pFirstBand; pR; pR = pR->pNextBand)
2354 WW8TabBandDesc *pNext = pR->pNextBand;
2358 for (int k = 0; k < pR->nWwCols; ++k)
2360 WW8_BRC &rAbove = pR->pTCs[k].rgbrc[WW8_BOT];
2361 short nAboveThick = rAbove.IsEmpty(pIo->bVer67) ?
2362 0 : rAbove.DetermineBorderProperties(pIo->bVer67);
2363 short nUpperLeft = pR->nCenter[k];
2364 short nUpperRight = pR->nCenter[k+1];
2366 for (int l = 0; l < pNext->nWwCols; ++l)
2368 short nLowerLeft = pNext->nCenter[l];
2369 short nLowerRight = pNext->nCenter[l+1];
2371 if ((nLowerLeft < nUpperLeft) || (nLowerRight > nUpperRight))
2374 WW8_BRC &rBelow = pNext->pTCs[l].rgbrc[WW8_TOP];
2375 short nBelowThick = rBelow.IsEmpty(pIo->bVer67) ?
2376 0 : rBelow.DetermineBorderProperties(pIo->bVer67);
2377 if (nAboveThick > nBelowThick)
2385 if (nMinLeft
&& ((!bIsBiDi
&& text::HoriOrientation::LEFT
== eOri
) || (bIsBiDi
&& text::HoriOrientation::RIGHT
== eOri
)))
2386 eOri
= text::HoriOrientation::LEFT_AND_WIDTH
; // absolutely positioned
2388 nDefaultSwCols
= nMinCols
; // da Zellen einfuegen billiger ist als Mergen
2389 if( nDefaultSwCols
== 0 )
2391 pActBand
= pFirstBand
;
2393 ASSERT( pActBand
, "pActBand ist 0" );
2396 void WW8TabDesc::SetSizePosition(SwFrmFmt
* pFrmFmt
)
2398 SwFrmFmt
* pApply
= pFrmFmt
;
2400 pApply
= pTable
->GetFrmFmt();
2401 ASSERT(pApply
,"No frame");
2402 pApply
->SetFmtAttr(aItemSet
);
2405 SwFmtFrmSize aSize
= pFrmFmt
->GetFrmSize();
2406 aSize
.SetHeightSizeType(ATT_MIN_SIZE
);
2407 aSize
.SetHeight(MINLAY
);
2408 pFrmFmt
->SetFmtAttr(aSize
);
2409 pTable
->GetFrmFmt()->SetFmtAttr(SwFmtHoriOrient(0,text::HoriOrientation::FULL
));
2413 void wwSectionManager::PrependedInlineNode(const SwPosition
&rPos
,
2414 const SwNode
&rNode
)
2416 ASSERT(!maSegments
.empty(),
2417 "should not be possible, must be at least one segment");
2418 if ((!maSegments
.empty()) && (maSegments
.back().maStart
== rPos
.nNode
))
2419 maSegments
.back().maStart
= SwNodeIndex(rNode
);
2422 void WW8TabDesc::CreateSwTable()
2424 ::SetProgressState(pIo
->nProgress
, pIo
->mpDocShell
); // Update
2426 // if there is already some content on the Node append new node to ensure
2427 // that this content remains ABOVE the table
2428 SwPosition
* pPoint
= pIo
->pPaM
->GetPoint();
2429 bool bInsNode
= pPoint
->nContent
.GetIndex() ? true : false;
2430 bool bSetMinHeight
= false;
2434 Set fly anchor to its anchor pos, so that if a table starts immediately
2435 at this position a new node will be inserted before inserting the table.
2437 if (!bInsNode
&& pIo
->pFmtOfJustInsertedApo
)
2439 const SwPosition
* pAPos
=
2440 pIo
->pFmtOfJustInsertedApo
->GetAnchor().GetCntntAnchor();
2441 if (pAPos
&& &pAPos
->nNode
.GetNode() == &pPoint
->nNode
.GetNode())
2444 bSetMinHeight
= true;
2446 SwFmtSurround
aSur(pIo
->pFmtOfJustInsertedApo
->GetSurround());
2447 aSur
.SetAnchorOnly(true);
2448 pIo
->pFmtOfJustInsertedApo
->SetFmtAttr(aSur
);
2452 if (bSetMinHeight
== true)
2454 // minimize Fontsize to minimize height growth of the header/footer
2455 // set font size to 1 point to minimize y-growth of Hd/Ft
2456 SvxFontHeightItem
aSz(20, 100, RES_CHRATR_FONTSIZE
);
2457 pIo
->NewAttr( aSz
);
2458 pIo
->pCtrlStck
->SetAttr(*pPoint
, RES_CHRATR_FONTSIZE
);
2462 pIo
->AppendTxtNode(*pPoint
);
2464 pTmpPos
= new SwPosition( *pIo
->pPaM
->GetPoint() );
2466 // Die Tabelle ist beim Einfuegen noch recht klein: Zahl der Spalten ist
2467 // die kleinste Spaltenanzahl des Originals, da Spalten einfuegen
2468 // schneller geht als Loeschen Zahl der Zeilen ist die Zahl der Baender,
2469 // da sich die (identischen) Zeilen eines Bandes prima duplizieren lassen
2470 pTable
= pIo
->rDoc
.InsertTable(
2471 SwInsertTableOptions( tabopts::HEADLINE_NO_BORDER
, 0 ),
2472 *pTmpPos
, nBands
, nDefaultSwCols
, eOri
, 0, 0, FALSE
, TRUE
);
2474 ASSERT(pTable
&& pTable
->GetFrmFmt(), "insert table failed");
2475 if (!pTable
|| !pTable
->GetFrmFmt())
2478 SwTableNode
* pTableNode
= pTable
->GetTableNode();
2479 ASSERT(pTableNode
, "no table node!");
2482 pIo
->maSectionManager
.PrependedInlineNode(*pIo
->pPaM
->GetPoint(),
2486 // Abfrage, ob im Node, in dem die Tabelle eingefuegt werden soll, bereits
2487 // ein Pagedesc steht. Dann wuerde der PageDesc in die naechste Zeile
2488 // hinter der Tabelle rutschen, wo er nichts zu suchen hat. -> loeschen
2489 // und spaeter an das Tabellenformat setzen
2490 if (SwTxtNode
* pNd
= pIo
->rDoc
.GetNodes()[pTmpPos
->nNode
]->GetTxtNode())
2492 if (const SfxItemSet
* pSet
= pNd
->GetpSwAttrSet())
2494 SfxPoolItem
*pSetAttr
= 0;
2495 const SfxPoolItem
* pItem
;
2496 if (SFX_ITEM_SET
== pSet
->GetItemState(RES_BREAK
, false, &pItem
))
2498 pSetAttr
= new SvxFmtBreakItem( *(SvxFmtBreakItem
*)pItem
);
2499 pNd
->ResetAttr( RES_BREAK
);
2502 // evtl den PageDesc/Break jetzt an der Tabelle setzen
2505 aItemSet
.Put(*pSetAttr
);
2511 // Gesamtbreite der Tabelle
2512 if( nMaxRight
- nMinLeft
> MINLAY
* nDefaultSwCols
)
2514 pTable
->GetFrmFmt()->SetFmtAttr(SwFmtFrmSize(ATT_FIX_SIZE
, nSwWidth
));
2515 aItemSet
.Put(SwFmtFrmSize(ATT_FIX_SIZE
, nSwWidth
));
2518 SvxFrameDirectionItem
aDirection(
2519 bIsBiDi
? FRMDIR_HORI_RIGHT_TOP
: FRMDIR_HORI_LEFT_TOP
, RES_FRAMEDIR
);
2520 pTable
->GetFrmFmt()->SetFmtAttr(aDirection
);
2522 if (text::HoriOrientation::LEFT_AND_WIDTH
== eOri
)
2524 if (!pIo
->nInTable
&& pIo
->InLocalApo() && pIo
->pSFlyPara
->pFlyFmt
&&
2527 //If we are inside a frame and we have a border, the frames
2528 //placement does not consider the tables border, which word
2529 //displays outside the frame, so adjust here.
2530 SwFmtHoriOrient
aHori(pIo
->pSFlyPara
->pFlyFmt
->GetHoriOrient());
2531 sal_Int16 eHori
= aHori
.GetHoriOrient();
2532 if ((eHori
== text::HoriOrientation::NONE
) || (eHori
== text::HoriOrientation::LEFT
) ||
2533 (eHori
== text::HoriOrientation::LEFT_AND_WIDTH
))
2535 //With multiple table, use last table settings. Perhaps
2536 //the maximum is what word does ?
2537 aHori
.SetPos(pIo
->pSFlyPara
->nXPos
+ GetMinLeft());
2538 aHori
.SetHoriOrient(text::HoriOrientation::NONE
);
2539 pIo
->pSFlyPara
->pFlyFmt
->SetFmtAttr(aHori
);
2544 //If bApo is set, then this table is being placed in a floating
2545 //frame, and the frame matches the left and right *lines* of the
2546 //table, so the space to the left of the table isn't to be used
2547 //inside the frame, in word the dialog involved greys out the
2548 //ability to set the margin.
2549 SvxLRSpaceItem
aL( RES_LR_SPACE
);
2550 // set right to original DxaLeft (i28656)
2554 nLeft
= GetMinLeft();
2556 nLeft
= pIo
->maSectionManager
.GetTextAreaWidth() - nPreferredWidth
- nOrgDxaLeft
;
2564 mpOldRedlineStack
= pIo
->mpRedlineStack
;
2565 pIo
->mpRedlineStack
= new sw::util::RedlineStack(pIo
->rDoc
);
2568 void WW8TabDesc::UseSwTable()
2570 // globale Varis initialisieren
2571 pTabLines
= &pTable
->GetTabLines();
2572 nAktRow
= nAktCol
= nAktBandRow
= 0;
2574 pTblNd
= (SwTableNode
*)(*pTabLines
)[0]->GetTabBoxes()[0]->
2575 GetSttNd()->FindTableNode();
2576 ASSERT( pTblNd
, "wo ist mein TabellenNode" );
2578 // --> mloiseleur 2007-10-10 #i69519# Restrict rows to repeat to a decent value
2579 if ( nRowsToRepeat
== static_cast<USHORT
>(nRows
) )
2583 pTblNd
->GetTable().SetRowsToRepeat( nRowsToRepeat
);
2584 // ggfs. Zusatz-Zellen einfuegen u.dgl.
2587 WW8DupProperties
aDup(pIo
->rDoc
,pIo
->pCtrlStck
);
2588 pIo
->pCtrlStck
->SetAttr(*pIo
->pPaM
->GetPoint(), 0, false);
2590 // jetzt den PaM korrekt setzen und ggfs. erste Mergegruppe vorbereiten...
2591 SetPamInCell(nAktCol
, true);
2592 aDup
.Insert(*pIo
->pPaM
->GetPoint());
2594 pIo
->bWasTabRowEnd
= false;
2595 pIo
->bWasTabCellEnd
= false;
2598 void WW8TabDesc::MergeCells()
2602 for (pActBand
=pFirstBand
, nRow
=0; pActBand
; pActBand
=pActBand
->pNextBand
)
2605 // ggfs. aktuelle Box in entsprechende Merge-Gruppe eintragen
2607 if( pActBand
->pTCs
)
2609 for( short j
= 0; j
< pActBand
->nRows
; j
++, nRow
++ )
2610 for( short i
= 0; i
< pActBand
->nWwCols
; i
++ )
2612 WW8SelBoxInfoPtr pActMGroup
= 0;
2614 // ggfs. eine neue Merge-Gruppe beginnen
2616 ASSERT(nRow
< pTabLines
->Count(),
2617 "Too few lines, table ended early");
2618 if (nRow
>= pTabLines
->Count())
2620 pTabLine
= (*pTabLines
)[ nRow
];
2621 pTabBoxes
= &pTabLine
->GetTabBoxes();
2623 USHORT nCol
= pActBand
->nTransCell
[ i
];
2624 if (!pActBand
->bExist
[i
]) //#113434#
2626 ASSERT(nCol
< pTabBoxes
->Count(),
2627 "Too few columns, table ended early");
2628 if (nCol
>= pTabBoxes
->Count())
2630 pTabBox
= (*pTabBoxes
)[nCol
];
2631 WW8_TCell
& rCell
= pActBand
->pTCs
[ i
];
2632 // ist dies die obere, linke-Zelle einer Merge-Gruppe ?
2634 bool bMerge
= false;
2635 if ( rCell
.bVertRestart
&& !rCell
.bMerged
)
2637 else if (rCell
.bFirstMerged
&& pActBand
->bExist
[i
])
2639 //#91211# Some tests to avoid merging cells
2640 //which previously were declared invalid because
2641 //of sharing the exact same dimensions as their
2644 //If theres anything underneath/above we're ok.
2645 if (rCell
.bVertMerge
|| rCell
.bVertRestart
)
2649 //If its a hori merge only, and the only things in
2650 //it are invalid cells then its already taken care
2651 //of, so don't merge.
2652 for (USHORT i2
= i
+1; i2
< pActBand
->nWwCols
; i2
++ )
2653 if (pActBand
->pTCs
[ i2
].bMerged
&&
2654 !pActBand
->pTCs
[ i2
].bFirstMerged
)
2656 if (pActBand
->bExist
[i2
])
2670 short nX1
= pActBand
->nCenter
[ i
];
2671 short nWidth
= pActBand
->nWidth
[ i
];
2673 // 0. falls noetig das Array fuer die Merge-Gruppen
2676 pMergeGroups
= new WW8MergeGroups
;
2678 // 2. aktuelle Merge-Gruppe anlegen
2679 pActMGroup
= new WW8SelBoxInfo( nX1
, nWidth
);
2681 // --> OD 2005-02-04 #118544# - determine size of new
2682 // merge group before inserted the new merge group.
2683 // Needed to correctly locked previously created merge groups.
2684 // Gesamtbreite ermitteln und zuweisen
2685 short nSizCell
= pActBand
->nWidth
[ i
];
2686 for (USHORT i2
= i
+1; i2
< pActBand
->nWwCols
; i2
++ )
2687 if (pActBand
->pTCs
[ i2
].bMerged
&&
2688 !pActBand
->pTCs
[ i2
].bFirstMerged
)
2690 nSizCell
= nSizCell
+ pActBand
->nWidth
[ i2
];
2694 pActMGroup
->nGroupWidth
= nSizCell
;
2697 // --> OD 2005-02-03 #118544# - locked previously
2698 // created merge groups, after determining the size
2699 // for the new merge group.
2700 // 1. ggfs. alte Mergegruppe(n) schliessen, die
2701 // den von unserer neuen Gruppe betroffenen
2702 // X-Bereich ueberdecken
2704 while ( FindMergeGroup( nX1
, pActMGroup
->nGroupWidth
,
2707 (*pMergeGroups
)[ nMGrIdx
]->bGroupLocked
= true;
2711 // 3. und in Gruppen-Array eintragen
2712 pMergeGroups
->Insert(pActMGroup
, pMergeGroups
->Count());
2715 // ggfs. akt. Box zu einer Merge-Gruppe hinzufuegen (dies
2716 // kann eine soeben angelegte, oder eine andere Gruppe
2718 UpdateTableMergeGroup( rCell
, pActMGroup
, pTabBox
, i
);
2724 //There is a limbo area in word at the end of the row marker
2725 //where properties can live in word, there is no location in
2726 //writer equivalent, so try and park the cursor in the best
2727 //match, see #i23022#/#i18644#
2728 void WW8TabDesc::ParkPaM()
2730 SwTableBox
*pTabBox2
= 0;
2731 short nRow
= nAktRow
+ 1;
2732 if (nRow
< pTabLines
->Count())
2734 if (SwTableLine
*pLine
= (*pTabLines
)[nRow
])
2736 SwTableBoxes
&rBoxes
= pLine
->GetTabBoxes();
2737 pTabBox2
= rBoxes
.Count() ? rBoxes
[0] : 0;
2741 if (!pTabBox2
|| !pTabBox2
->GetSttNd())
2747 if (pIo
->pPaM
->GetPoint()->nNode
!= pTabBox2
->GetSttIdx() + 1)
2749 pIo
->pPaM
->GetPoint()->nNode
= pTabBox2
->GetSttIdx() + 1;
2750 pIo
->pPaM
->GetPoint()->nContent
.Assign(pIo
->pPaM
->GetCntntNode(), 0);
2751 pIo
->rDoc
.SetTxtFmtColl(*pIo
->pPaM
, (SwTxtFmtColl
*)pIo
->pDfltTxtFmtColl
);
2755 void WW8TabDesc::MoveOutsideTable()
2757 ASSERT(pTmpPos
&& pIo
, "I've forgotten where the table is anchored");
2759 *pIo
->pPaM
->GetPoint() = *pTmpPos
;
2762 void WW8TabDesc::FinishSwTable()
2764 pIo
->mpRedlineStack
->closeall(*pIo
->pPaM
->GetPoint());
2765 delete pIo
->mpRedlineStack
;
2766 pIo
->mpRedlineStack
= mpOldRedlineStack
;
2767 mpOldRedlineStack
= 0;
2769 WW8DupProperties
aDup(pIo
->rDoc
,pIo
->pCtrlStck
);
2770 pIo
->pCtrlStck
->SetAttr( *pIo
->pPaM
->GetPoint(), 0, false);
2773 delete pTmpPos
, pTmpPos
= 0;
2775 aDup
.Insert(*pIo
->pPaM
->GetPoint());
2777 pIo
->bWasTabRowEnd
= false;
2778 pIo
->bWasTabCellEnd
= false;
2780 pIo
->maInsertedTables
.InsertTable(*pTblNd
, *pIo
->pPaM
);
2784 // falls noetig, zu mergende Zellen gruppenweise zusammenfassen
2787 // bearbeite alle Merge-Gruppen nacheinander
2788 WW8SelBoxInfo
* pActMGroup
;
2789 USHORT nActBoxCount
;
2791 for (USHORT iGr
= 0; iGr
< pMergeGroups
->Count(); ++iGr
)
2793 pActMGroup
= (*pMergeGroups
)[ iGr
];
2794 nActBoxCount
= pActMGroup
->Count();
2796 if( ( 1 < nActBoxCount
) && pActMGroup
&& (*pActMGroup
)[ 0 ] )
2798 const USHORT nRowSpan
= pActMGroup
->Count();
2799 for (USHORT n
= 0; n
< nRowSpan
; ++n
)
2801 SwTableBox
* pCurrentBox
= (*pActMGroup
)[n
];
2802 const long nRowSpanSet
= n
== 0 ?
2804 ((-1) * (nRowSpan
- n
));
2805 pCurrentBox
->setRowSpan( nRowSpanSet
);
2809 pIo
->pFmtOfJustInsertedApo
= 0;
2810 DELETEZ( pMergeGroups
);
2815 // durchsucht pMergeGroups, meldet Index der ersten, passenden Gruppe bzw. -1
2817 // Parameter: nXcenter = Mittenposition der anfragenden Box
2818 // nWidth = Breite der anfragenden Box
2819 // bExact = Flag, ob Box in dieser Gruppe passen muss,
2820 // oder diese nur zu tangieren braucht
2822 bool WW8TabDesc::FindMergeGroup(short nX1
, short nWidth
, bool bExact
,
2828 // noch als gueltig angesehener Bereich in der Naehe der Grenzen
2829 const short nToleranz
= 4;
2830 // die aktuell untersuchte Gruppe
2831 WW8SelBoxInfoPtr pActGroup
;
2833 short nX2
= nX1
+ nWidth
;
2834 // ungefaehre Gruppengrenzen
2838 // --> OD 2005-02-04 #118544# - improvement: search backwards
2839 //for ( USHORT iGr = 0; iGr < pMergeGroups->Count(); iGr++ )
2840 for ( short iGr
= pMergeGroups
->Count() - 1; iGr
>= 0; --iGr
)
2842 // die aktuell untersuchte Gruppe
2843 pActGroup
= (*pMergeGroups
)[ iGr
];
2844 if (!pActGroup
->bGroupLocked
)
2846 // ungefaehre Gruppengrenzen mit Toleranz nach *aussen* hin
2847 nGrX1
= pActGroup
->nGroupXStart
- nToleranz
;
2848 nGrX2
= pActGroup
->nGroupXStart
2849 +pActGroup
->nGroupWidth
+ nToleranz
;
2851 // Falls Box reinpasst, melde auf jeden Fall den Erfolg
2853 if( ( nX1
> nGrX1
) && ( nX2
< nGrX2
) )
2855 nMGrIdx
= iGr
; break;
2858 // hat die Box Bereiche mit der Gruppe gemeinsam?
2862 // melde Erfolg, wenn nX1 *oder* nX2 innerhalb der Gruppe liegen
2863 if( ( ( nX1
> nGrX1
)
2864 && ( nX1
< nGrX2
- 2*nToleranz
) )
2865 || ( ( nX2
> nGrX1
+ 2*nToleranz
)
2866 && ( nX2
< nGrX2
) )
2867 // oder nX1 und nX2 die Gruppe umfassen
2868 || ( ( nX1
<=nGrX1
)
2869 && ( nX2
>=nGrX2
) ) )
2871 nMGrIdx
= iGr
; break;
2877 return ( -1 < nMGrIdx
);
2880 bool WW8TabDesc::IsValidCell(short nCol
) const
2882 return pActBand
->bExist
[nCol
] && (USHORT
)nAktRow
< pTabLines
->Count();
2885 bool WW8TabDesc::InFirstParaInCell() const
2888 if (!pTabBox
|| !pTabBox
->GetSttNd())
2890 ASSERT(false, "Problem with table");
2894 if (!IsValidCell(GetAktCol()))
2897 if (pIo
->pPaM
->GetPoint()->nNode
== pTabBox
->GetSttIdx() + 1)
2903 void WW8TabDesc::StartMiserableHackForUnsupportedDirection(short nWwCol
)
2905 ASSERT(pActBand
, "Impossible");
2906 if (pActBand
&& pActBand
->maDirections
[nWwCol
] == 3)
2908 pIo
->pCtrlStck
->NewAttr(*pIo
->pPaM
->GetPoint(),
2909 SvxCharRotateItem(900, false, RES_CHRATR_ROTATE
));
2913 void WW8TabDesc::EndMiserableHackForUnsupportedDirection(short nWwCol
)
2915 ASSERT(pActBand
, "Impossible");
2916 if (pActBand
&& pActBand
->maDirections
[nWwCol
] == 3)
2917 pIo
->pCtrlStck
->SetAttr(*pIo
->pPaM
->GetPoint(), RES_CHRATR_ROTATE
);
2920 bool WW8TabDesc::SetPamInCell(short nWwCol
, bool bPam
)
2922 ASSERT( pActBand
, "pActBand ist 0" );
2924 USHORT nCol
= pActBand
->nTransCell
[nWwCol
];
2926 if ((USHORT
)nAktRow
>= pTabLines
->Count())
2928 ASSERT(!this, "Actual row bigger than expected." );
2934 pTabLine
= (*pTabLines
)[nAktRow
];
2935 pTabBoxes
= &pTabLine
->GetTabBoxes();
2937 if (nCol
>= pTabBoxes
->Count())
2941 // The first paragraph in a cell with upper autospacing has upper
2944 pIo
->bParaAutoBefore
&& pIo
->bFirstPara
&&
2945 !pIo
->pWDop
->fDontUseHTMLAutoSpacing
2948 pIo
->SetUpperSpacing(*pIo
->pPaM
, 0);
2951 // The last paragraph in a cell with lower autospacing has lower
2953 if (pIo
->bParaAutoAfter
&& !pIo
->pWDop
->fDontUseHTMLAutoSpacing
)
2954 pIo
->SetLowerSpacing(*pIo
->pPaM
, 0);
2960 pTabBox
= (*pTabBoxes
)[nCol
];
2961 if( !pTabBox
->GetSttNd() )
2963 ASSERT(pTabBox
->GetSttNd(), "Probleme beim Aufbau der Tabelle");
2970 pAktWWCell
= &pActBand
->pTCs
[ nWwCol
];
2972 // The first paragraph in a cell with upper autospacing has upper spacing set to 0
2973 if(pIo
->bParaAutoBefore
&& pIo
->bFirstPara
&& !pIo
->pWDop
->fDontUseHTMLAutoSpacing
)
2974 pIo
->SetUpperSpacing(*pIo
->pPaM
, 0);
2976 // The last paragraph in a cell with lower autospacing has lower spacing set to 0
2977 if(pIo
->bParaAutoAfter
&& !pIo
->pWDop
->fDontUseHTMLAutoSpacing
)
2978 pIo
->SetLowerSpacing(*pIo
->pPaM
, 0);
2980 //We need to set the pPaM on the first cell, invalid
2981 //or not so that we can collect paragraph proproties over
2982 //all the cells, but in that case on the valid cell we do not
2983 //want to reset the fmt properties
2984 if (pIo
->pPaM
->GetPoint()->nNode
!= pTabBox
->GetSttIdx() + 1)
2986 pIo
->pPaM
->GetPoint()->nNode
= pTabBox
->GetSttIdx() + 1;
2987 pIo
->pPaM
->GetPoint()->nContent
.Assign(pIo
->pPaM
->GetCntntNode(), 0);
2988 // Zur Sicherheit schon jetzt setzen, da bei den Zellen, die
2989 // zum Randausgleich eingefuegt werden, sonst der Style
2990 // nicht gesetzt wird.
2991 pIo
->rDoc
.SetTxtFmtColl(*pIo
->pPaM
, (SwTxtFmtColl
*)pIo
->pDfltTxtFmtColl
);
2992 // uebrigens: da diese Zellen unsichtbare Hilfskonstruktionen sind,
2993 // und nur dazu dienen, zerfranste Aussehen der WW-Tabelle
2994 // nachzuahmen, braucht NICHT SetTxtFmtCollAndListLevel()
2995 // verwendet zu werden.
2998 // Better to turn Snap to Grid off for all paragraphs in tables
2999 if(SwTxtNode
*pNd
= pIo
->pPaM
->GetNode()->GetTxtNode())
3001 const SfxPoolItem
&rItm
= pNd
->SwCntntNode::GetAttr(RES_PARATR_SNAPTOGRID
);
3002 SvxParaGridItem
&rSnapToGrid
= (SvxParaGridItem
&)(rItm
);
3004 if(rSnapToGrid
.GetValue())
3006 SvxParaGridItem
aGridItem( rSnapToGrid
);
3007 aGridItem
.SetValue(false);
3009 SwPosition
* pGridPos
= pIo
->pPaM
->GetPoint();
3011 xub_StrLen nEnd
= pGridPos
->nContent
.GetIndex();
3012 pGridPos
->nContent
.Assign(pIo
->pPaM
->GetCntntNode(), 0);
3013 pIo
->pCtrlStck
->NewAttr(*pGridPos
, aGridItem
);
3014 pGridPos
->nContent
.Assign(pIo
->pPaM
->GetCntntNode(), nEnd
);
3015 pIo
->pCtrlStck
->SetAttr(*pGridPos
, RES_PARATR_SNAPTOGRID
);
3019 StartMiserableHackForUnsupportedDirection(nWwCol
);
3024 void WW8TabDesc::InsertCells( short nIns
)
3026 pTabLine
= (*pTabLines
)[nAktRow
];
3027 pTabBoxes
= &pTabLine
->GetTabBoxes();
3028 pTabBox
= (*pTabBoxes
)[0];
3030 pIo
->rDoc
.GetNodes().InsBoxen( pTblNd
, pTabLine
, (SwTableBoxFmt
*)pTabBox
->GetFrmFmt(),
3031 (SwTxtFmtColl
*)pIo
->pDfltTxtFmtColl
, 0, pTabBoxes
->Count(), nIns
);
3032 // mit dem Dritten Parameter wird das FrmFmt der Boxen angegeben.
3033 // hier kann man auch noch optimieren, um FrmFmts zu sparen
3036 void WW8TabDesc::SetTabBorders(SwTableBox
* pBox
, short nWwIdx
)
3038 if( nWwIdx
< 0 || nWwIdx
>= pActBand
->nWwCols
)
3039 return; // kuenstlich erzeugte Zellen -> Kein Rand
3042 SvxBoxItem
aFmtBox( RES_BOX
);
3043 if (pActBand
->pTCs
) // neither Cell Border nor Default Border defined ?
3045 WW8_TCell
* pT
= &pActBand
->pTCs
[nWwIdx
];
3046 if (pIo
->IsBorder(pT
->rgbrc
))
3047 pIo
->SetBorder(aFmtBox
, pT
->rgbrc
);
3050 if (pActBand
->nOverrideSpacing
[nWwIdx
] & (1 << WW8TabBandDesc::wwTOP
))
3052 aFmtBox
.SetDistance(
3053 pActBand
->nOverrideValues
[nWwIdx
][WW8TabBandDesc::wwTOP
],
3057 aFmtBox
.SetDistance(pActBand
->mnDefaultTop
, BOX_LINE_TOP
);
3058 if (pActBand
->nOverrideSpacing
[nWwIdx
] & (1 << WW8TabBandDesc::wwBOTTOM
))
3060 aFmtBox
.SetDistance(
3061 pActBand
->nOverrideValues
[nWwIdx
][WW8TabBandDesc::wwBOTTOM
],
3065 aFmtBox
.SetDistance(pActBand
->mnDefaultBottom
,BOX_LINE_BOTTOM
);
3067 // nGapHalf bedeutet bei WW ein *horizontaler* Abstand zwischen
3068 // Tabellenzelle und -Inhalt
3070 pActBand
->mbHasSpacing
? pActBand
->mnDefaultLeft
: pActBand
->nGapHalf
;
3072 pActBand
->mbHasSpacing
? pActBand
->mnDefaultRight
: pActBand
->nGapHalf
;
3073 if (pActBand
->nOverrideSpacing
[nWwIdx
] & (1 << WW8TabBandDesc::wwLEFT
))
3075 aFmtBox
.SetDistance(
3076 pActBand
->nOverrideValues
[nWwIdx
][WW8TabBandDesc::wwLEFT
],
3080 aFmtBox
.SetDistance(nLeftDist
, BOX_LINE_LEFT
);
3081 if (pActBand
->nOverrideSpacing
[nWwIdx
] & (1 << WW8TabBandDesc::wwRIGHT
))
3083 aFmtBox
.SetDistance(
3084 pActBand
->nOverrideValues
[nWwIdx
][WW8TabBandDesc::wwRIGHT
],
3088 aFmtBox
.SetDistance(nRightDist
,BOX_LINE_RIGHT
);
3090 pBox
->GetFrmFmt()->SetFmtAttr(aFmtBox
);
3093 void WW8TabDesc::SetTabShades( SwTableBox
* pBox
, short nWwIdx
)
3095 if( nWwIdx
< 0 || nWwIdx
>= pActBand
->nWwCols
)
3096 return; // kuenstlich erzeugte Zellen -> Keine Farbe
3099 if (pActBand
->pNewSHDs
&& pActBand
->pNewSHDs
[nWwIdx
] != COL_AUTO
)
3101 Color
aColor(pActBand
->pNewSHDs
[nWwIdx
]);
3102 if (aColor
.GetColor() == 0x00333333)
3103 pIo
->maTracer
.Log(sw::log::eAutoColorBg
);
3104 pBox
->GetFrmFmt()->SetFmtAttr(SvxBrushItem(aColor
, RES_BACKGROUND
));
3108 //If there was no new shades, or no new shade setting
3109 if (pActBand
->pSHDs
&& !bFound
)
3111 WW8_SHD
& rSHD
= pActBand
->pSHDs
[nWwIdx
];
3112 if (!rSHD
.GetValue()) // auto
3115 SwWW8Shade
aSh( pIo
->bVer67
, rSHD
);
3116 pBox
->GetFrmFmt()->SetFmtAttr(SvxBrushItem(aSh
.aColor
, RES_BACKGROUND
));
3120 SvxFrameDirection
MakeDirection(sal_uInt16 nCode
, BOOL bIsBiDi
)
3122 SvxFrameDirection eDir
= FRMDIR_ENVIRONMENT
;
3123 // 1: Asian layout with rotated CJK characters
3125 // 3: Western layout rotated by 90 degrees
3126 // 4: Western layout
3130 ASSERT(eDir
== 4, "unknown direction code, maybe its a bitfield");
3132 // --> FME/Alan Yaniger: 2006-09-15 #i38158# Consider RTL tables:
3133 eDir
= bIsBiDi
? FRMDIR_HORI_RIGHT_TOP
: FRMDIR_HORI_LEFT_TOP
;
3137 eDir
= FRMDIR_VERT_TOP_RIGHT
;
3140 eDir
= FRMDIR_VERT_TOP_RIGHT
;
3143 // --> FME/Alan Yaniger: 2006-09-15 #i38158# Consider RTL tables:
3144 eDir
= bIsBiDi
? FRMDIR_HORI_RIGHT_TOP
: FRMDIR_HORI_LEFT_TOP
;
3151 void WW8TabDesc::SetTabDirection(SwTableBox
* pBox
, short nWwIdx
)
3153 if (nWwIdx
< 0 || nWwIdx
>= pActBand
->nWwCols
)
3155 SvxFrameDirectionItem
aItem(MakeDirection(pActBand
->maDirections
[nWwIdx
], bIsBiDi
), RES_FRAMEDIR
);
3156 pBox
->GetFrmFmt()->SetFmtAttr(aItem
);
3159 void WW8TabDesc::SetTabVertAlign( SwTableBox
* pBox
, short nWwIdx
)
3161 if( nWwIdx
< 0 || nWwIdx
>= pActBand
->nWwCols
)
3164 sal_Int16 eVertOri
=text::VertOrientation::TOP
;
3166 if( pActBand
->pTCs
)
3168 WW8_TCell
* pT
= &pActBand
->pTCs
[nWwIdx
];
3169 switch (pT
->nVertAlign
)
3173 eVertOri
= text::VertOrientation::TOP
;
3176 eVertOri
= text::VertOrientation::CENTER
;
3179 eVertOri
= text::VertOrientation::BOTTOM
;
3184 pBox
->GetFrmFmt()->SetFmtAttr( SwFmtVertOrient(0,eVertOri
) );
3187 void WW8TabDesc::AdjustNewBand()
3189 if( pActBand
->nSwCols
> nDefaultSwCols
) // Zellen splitten
3190 InsertCells( pActBand
->nSwCols
- nDefaultSwCols
);
3192 SetPamInCell( 0, false);
3193 ASSERT( pTabBoxes
&& pTabBoxes
->Count() == (USHORT
)pActBand
->nSwCols
,
3194 "Falsche Spaltenzahl in Tabelle" )
3198 pTabLine
->ClaimFrmFmt(); // noetig wg. Zeilenhoehe
3199 SwFmtFrmSize
aF( ATT_MIN_SIZE
, 0, 0 ); // default
3201 if (pActBand
->nLineHeight
== 0) // 0 = Auto
3202 aF
.SetHeightSizeType( ATT_VAR_SIZE
);
3205 if (pActBand
->nLineHeight
< 0) // Pos = min, Neg = exakt
3207 aF
.SetHeightSizeType(ATT_FIX_SIZE
);
3208 pActBand
->nLineHeight
= -pActBand
->nLineHeight
;
3210 if (pActBand
->nLineHeight
< MINLAY
) // nicht erlaubte Zeilenhoehe
3211 pActBand
->nLineHeight
= MINLAY
;
3213 aF
.SetHeight(pActBand
->nLineHeight
);// Min- / Exakt-Hoehe setzen
3215 pTabLine
->GetFrmFmt()->SetFmtAttr(aF
);
3218 //Word stores 1 for bCantSplit if the row cannot be split, we set true if
3219 //we can split the row
3220 // bCantSplit: Always true for rows containing merged cells (Word <= 2000 crashes otherwise)
3221 // So in case bCantSplit is true, we check for bCantSplit90, which has been introduced for
3222 // Word versions >= 2002.
3223 bool bSetCantSplit
= pActBand
->bCantSplit
;
3225 bSetCantSplit
= pActBand
->bCantSplit90
;
3227 pTabLine
->GetFrmFmt()->SetFmtAttr(SwFmtRowSplit(!bSetCantSplit
));
3229 short i
; // SW-Index
3230 short j
; // WW-Index
3232 SwFmtFrmSize
aFS( ATT_FIX_SIZE
);
3233 j
= pActBand
->bLEmptyCol
? -1 : 0;
3235 for( i
= 0; i
< pActBand
->nSwCols
; i
++ )
3237 // setze Zellenbreite
3239 nW
= pActBand
->nCenter
[0] - nMinLeft
;
3242 //Set j to first non invalid cell
3243 while ((j
< pActBand
->nWwCols
) && (!pActBand
->bExist
[j
]))
3246 if( j
< pActBand
->nWwCols
)
3247 nW
= pActBand
->nCenter
[j
+1] - pActBand
->nCenter
[j
];
3249 nW
= nMaxRight
- pActBand
->nCenter
[j
];
3250 pActBand
->nWidth
[ j
] = nW
;
3253 SwTableBox
* pBox
= (*pTabBoxes
)[i
];
3254 // liesse sich durch intelligentes Umhaengen der FrmFmts noch weiter
3256 pBox
->ClaimFrmFmt();
3258 SetTabBorders(pBox
, j
);
3260 // #i18128# word has only one line between adjoining vertical cells
3261 // we have to mimick this in the filter by picking the larger of the
3262 // sides and using that one on one side of the line (right)
3263 SvxBoxItem
aCurrentBox(sw::util::ItemGet
<SvxBoxItem
>(*(pBox
->GetFrmFmt()), RES_BOX
));
3264 const SvxBorderLine
*pLeftLine
= aCurrentBox
.GetLine(BOX_LINE_LEFT
);
3265 int nCurrentRightLineWidth
= 0;
3267 nCurrentRightLineWidth
= pLeftLine
->GetInWidth() + pLeftLine
->GetOutWidth() + pLeftLine
->GetDistance();
3271 SwTableBox
* pBox2
= (*pTabBoxes
)[i
-1];
3272 SvxBoxItem
aOldBox(sw::util::ItemGet
<SvxBoxItem
>(*(pBox2
->GetFrmFmt()), RES_BOX
));
3273 const SvxBorderLine
*pRightLine
= aOldBox
.GetLine(BOX_LINE_RIGHT
);
3274 int nOldBoxRightLineWidth
= 0;
3276 nOldBoxRightLineWidth
= pRightLine
->GetInWidth() + pRightLine
->GetOutWidth() + pRightLine
->GetDistance();
3278 if(nOldBoxRightLineWidth
>nCurrentRightLineWidth
)
3279 aCurrentBox
.SetLine(aOldBox
.GetLine(BOX_LINE_RIGHT
), BOX_LINE_LEFT
);
3281 aOldBox
.SetLine(0, BOX_LINE_RIGHT
);
3282 pBox2
->GetFrmFmt()->SetFmtAttr(aOldBox
);
3285 pBox
->GetFrmFmt()->SetFmtAttr(aCurrentBox
);
3287 SetTabVertAlign(pBox
, j
);
3288 SetTabDirection(pBox
, j
);
3289 if( pActBand
->pSHDs
|| pActBand
->pNewSHDs
)
3290 SetTabShades(pBox
, j
);
3294 pBox
->GetFrmFmt()->SetFmtAttr( aFS
);
3296 // ueberspringe nicht existente Zellen
3297 while( ( j
< pActBand
->nWwCols
) && !pActBand
->bExist
[j
] )
3299 pActBand
->nWidth
[j
] = pActBand
->nCenter
[j
+1] - pActBand
->nCenter
[j
];
3305 void WW8TabDesc::TableCellEnd()
3307 ::SetProgressState(pIo
->nProgress
, pIo
->mpDocShell
); // Update
3309 EndMiserableHackForUnsupportedDirection(nAktCol
);
3312 if( pIo
->bWasTabRowEnd
)
3314 // bWasTabRowEnd will be deactivated in
3315 // SwWW8ImplReader::ProcessSpecial()
3317 USHORT iCol
= GetLogicalWWCol();
3318 if (iCol
< aNumRuleNames
.size())
3320 aNumRuleNames
.erase(aNumRuleNames
.begin() + iCol
,
3321 aNumRuleNames
.end());
3327 ASSERT( pActBand
, "pActBand ist 0" );
3330 if( nAktRow
>= nRows
) // am Tabellenende gibt's nichts sinnvolles
3331 return; // mehr zu tun
3333 bool bNewBand
= nAktBandRow
>= pActBand
->nRows
;
3335 { // neues Band noetig ?
3336 pActBand
= pActBand
->pNextBand
; //
3338 ASSERT( pActBand
, "pActBand ist 0" );
3343 SwTableBox
* pBox
= (*pTabBoxes
)[0];
3345 pIo
->rDoc
.InsertRow( pTable
->SelLineFromBox( pBox
, aBoxes
) );
3350 { // neue Spalte ( Zelle )
3353 SetPamInCell(nAktCol
, true);
3355 // finish Annotated Level Numbering ?
3356 if (pIo
->bAnl
&& !pIo
->bAktAND_fNumberAcross
)
3357 pIo
->StopAllAnl(IsValidCell(nAktCol
));
3360 // ggfs. die Box in fuer diese Col offene Merge-Gruppe eintragen
3361 SwTableBox
* WW8TabDesc::UpdateTableMergeGroup( WW8_TCell
& rCell
,
3362 WW8SelBoxInfo
* pActGroup
,
3363 SwTableBox
* pActBox
,
3366 // Rueckgabewert defaulten
3367 SwTableBox
* pResult
= 0;
3369 // pruefen, ob die Box zu mergen ist
3370 // --> OD 2005-02-04 #118544# - If cell is the first one to be merged,
3371 // a new merge group has to be provided.
3372 // E.g., it could be that a cell is the first one to be merged, but no
3373 // new merge group is provided, because the potential other cell to be merged
3374 // doesn't exist - see method <WW8TabDesc::MergeCells>.
3375 if ( pActBand
->bExist
[ nCol
] &&
3376 ( ( rCell
.bFirstMerged
&& pActGroup
) ||
3379 rCell
.bVertRestart
) )
3382 // passende Merge-Gruppe ermitteln
3383 WW8SelBoxInfo
* pTheMergeGroup
= 0;
3385 // Gruppe uebernehmen
3386 pTheMergeGroup
= pActGroup
;
3391 if( FindMergeGroup( pActBand
->nCenter
[ nCol
],
3392 pActBand
->nWidth
[ nCol
], true, nMGrIdx
) )
3393 pTheMergeGroup
= (*pMergeGroups
)[ nMGrIdx
];
3395 if( pTheMergeGroup
)
3397 // aktuelle Box der Merge-Gruppe hinzufuegen
3398 pTheMergeGroup
->Insert( pActBox
, pTheMergeGroup
->Count() );
3400 // Target-Box zurueckmelden
3401 pResult
= (*pTheMergeGroup
)[ 0 ];
3408 USHORT
WW8TabDesc::GetLogicalWWCol() const // returns number of col as INDICATED within WW6 UI status line -1
3411 if( pActBand
&& pActBand
->pTCs
)
3413 for( USHORT iCol
= 1; iCol
<= nAktCol
; ++iCol
)
3415 if( !pActBand
->pTCs
[ iCol
-1 ].bMerged
)
3422 // find name of numrule valid for current WW-COL
3423 const String
& WW8TabDesc::GetNumRuleName() const
3425 USHORT nCol
= GetLogicalWWCol();
3426 if (nCol
< aNumRuleNames
.size())
3427 return aNumRuleNames
[nCol
];
3432 void WW8TabDesc::SetNumRuleName( const String
& rName
)
3434 USHORT nCol
= GetLogicalWWCol();
3435 for (USHORT nSize
= static_cast< USHORT
>(aNumRuleNames
.size()); nSize
<= nCol
; ++nSize
)
3436 aNumRuleNames
.push_back(aEmptyStr
);
3437 aNumRuleNames
[nCol
] = rName
;
3440 bool SwWW8ImplReader::StartTable(WW8_CP nStartCp
)
3442 // Entering a table so make sure the the FirstPara flag gets set
3444 // keine rekursiven Tabellen Nicht bei EinfuegenDatei in Tabelle oder
3450 maTableStack
.push(pTableDesc
);
3452 // --> OD 2005-01-27 #i33818# - determine absolute position object attributes,
3453 // if possible. It's needed for nested tables.
3454 WW8FlyPara
* pTableWFlyPara( 0L );
3455 WW8SwFlyPara
* pTableSFlyPara( 0L );
3456 // --> OD 2005-03-21 #i45301# - anchor nested table inside Writer fly frame
3457 // only at-character, if absolute position object attributes are available.
3458 // Thus, default anchor type is as-character anchored.
3459 RndStdIds
eAnchor( FLY_IN_CNTNT
);
3463 WW8_TablePos
* pNestedTabPos( 0L );
3464 WW8_TablePos aNestedTabPos
;
3465 WW8PLCFxSave1 aSave
;
3466 pPlcxMan
->GetPap()->Save( aSave
);
3467 WW8PLCFx_Cp_FKP
* pPap
= pPlcxMan
->GetPapPLCF();
3468 WW8_CP nMyStartCp
= nStartCp
;
3469 if ( SearchRowEnd( pPap
, nMyStartCp
, nInTable
) &&
3470 ParseTabPos( &aNestedTabPos
, pPap
) )
3472 pNestedTabPos
= &aNestedTabPos
;
3474 pPlcxMan
->GetPap()->Restore( aSave
);
3475 if ( pNestedTabPos
)
3477 ApoTestResults aApo
= TestApo( nInTable
+ 1, false, pNestedTabPos
);
3478 pTableWFlyPara
= ConstructApo( aApo
, pNestedTabPos
);
3479 if ( pTableWFlyPara
)
3481 // --> OD 2007-07-03 #148498#
3482 // <WW8SwFlyPara> constructor has changed - new 4th parameter
3483 // containing WW8 page top margin.
3484 pTableSFlyPara
= new WW8SwFlyPara(*pPaM
, *this, *pTableWFlyPara
,
3485 maSectionManager
.GetWWPageTopMargin(),
3486 maSectionManager
.GetPageLeft(), maSectionManager
.GetTextAreaWidth(),
3487 nIniFlyDx
, nIniFlyDy
);
3489 // --> OD 2005-03-21 #i45301# - anchor nested table Writer fly
3490 // frame at-character
3491 eAnchor
= FLY_AUTO_CNTNT
;
3498 pTableDesc
= new WW8TabDesc( this, nStartCp
);
3500 if( pTableDesc
->Ok() )
3502 int nNewInTable
= nInTable
+ 1;
3503 if (InEqualApo(nNewInTable
))
3505 ASSERT(pSFlyPara
->pFlyFmt
,
3506 "how could we be in a local apo and have no apo");
3509 if ( eAnchor
== FLY_AUTO_CNTNT
&& !maTableStack
.empty() && !InEqualApo(nNewInTable
) )
3511 pTableDesc
->pParentPos
= new SwPosition(*pPaM
->GetPoint());
3512 SfxItemSet
aItemSet(rDoc
.GetAttrPool(),
3513 RES_FRMATR_BEGIN
, RES_FRMATR_END
-1);
3514 // --> OD 2005-01-26 #i33818# - anchor the Writer fly frame for
3515 // the nested table at-character.
3516 // --> OD 2005-03-21 #i45301#
3517 SwFmtAnchor
aAnchor( eAnchor
);
3518 aAnchor
.SetAnchor( pTableDesc
->pParentPos
);
3519 aItemSet
.Put( aAnchor
);
3520 pTableDesc
->pFlyFmt
= rDoc
.MakeFlySection( eAnchor
,
3521 pTableDesc
->pParentPos
, &aItemSet
);
3522 ASSERT( pTableDesc
->pFlyFmt
->GetAnchor().GetAnchorId() == eAnchor
,
3523 "Not the anchor type requested!" );
3525 MoveInsideFly(pTableDesc
->pFlyFmt
);
3527 pTableDesc
->CreateSwTable();
3528 if (pTableDesc
->pFlyFmt
)
3530 pTableDesc
->SetSizePosition(pTableDesc
->pFlyFmt
);
3531 // --> OD 2005-01-26 #i33818# - Use absolute position object
3532 // attributes, if existing, and apply them to the created Writer fly
3534 if ( pTableWFlyPara
&& pTableSFlyPara
)
3536 WW8FlySet
aFlySet( *this, pTableWFlyPara
, pTableSFlyPara
, false );
3537 SwFmtAnchor
aAnchor( FLY_AUTO_CNTNT
);
3538 aAnchor
.SetAnchor( pTableDesc
->pParentPos
);
3539 aFlySet
.Put( aAnchor
);
3540 pTableDesc
->pFlyFmt
->SetFmtAttr( aFlySet
);
3544 SwFmtHoriOrient aHori
=
3545 pTableDesc
->pTable
->GetFrmFmt()->GetHoriOrient();
3546 pTableDesc
->pFlyFmt
->SetFmtAttr(aHori
);
3547 pTableDesc
->pFlyFmt
->SetFmtAttr( SwFmtSurround( SURROUND_NONE
) );
3550 // --> OD 2005-01-27 #i33818# - The nested table doesn't have to leave
3551 // the table cell. Thus, the Writer fly frame has to follow the text flow.
3552 pTableDesc
->pFlyFmt
->SetFmtAttr( SwFmtFollowTextFlow( TRUE
) );
3556 pTableDesc
->SetSizePosition(0);
3557 pTableDesc
->UseSwTable();
3562 // --> OD 2005-01-28 #i33818#
3563 delete pTableWFlyPara
;
3564 delete pTableSFlyPara
;
3567 bool bSuccess
= (0 != pTableDesc
);
3570 maTracer
.EnterEnvironment(sw::log::eTable
, rtl::OUString::valueOf(
3571 static_cast<sal_Int32
>(maTableStack
.size())));
3576 void SwWW8ImplReader::TabCellEnd()
3578 if (nInTable
&& pTableDesc
)
3580 pTableDesc
->TableCellEnd();
3583 && pWFlyPara
== NULL
3584 && mpTableEndPaM
.get() != NULL
3585 && (! SwPaM::Overlap(*pPaM
, *mpTableEndPaM
))
3586 && SwPaM::LessThan(*mpTableEndPaM
, *pPaM
))
3588 if (mpTableEndPaM
->GetPoint()->nNode
.GetNode().IsTxtNode())
3590 rDoc
.DelFullPara(*mpTableEndPaM
);
3595 bFirstPara
= true; // We have come to the end of a cell so FirstPara flag
3597 mpTableEndPaM
.reset();
3600 void SwWW8ImplReader::Read_TabCellEnd( USHORT
, const BYTE
* pData
, short nLen
)
3602 if( ( nLen
> 0 ) && ( *pData
== 1 ) )
3603 bWasTabCellEnd
= true;
3606 void SwWW8ImplReader::Read_TabRowEnd( USHORT
, const BYTE
* pData
, short nLen
) // Sprm25
3608 if( ( nLen
> 0 ) && ( *pData
== 1 ) )
3609 bWasTabRowEnd
= true;
3612 void SwWW8ImplReader::PopTableDesc()
3614 if (pTableDesc
&& pTableDesc
->pFlyFmt
)
3616 MoveOutsideFly(pTableDesc
->pFlyFmt
,*pTableDesc
->pParentPos
);
3620 if (maTableStack
.empty())
3624 pTableDesc
= maTableStack
.top();
3629 void SwWW8ImplReader::StopTable()
3631 maTracer
.LeaveEnvironment(sw::log::eTable
);
3633 ASSERT(pTableDesc
, "Panic, stop table with no table!");
3637 // We are leaving a table so make sure the next paragraph doesn't think
3638 // it's the first paragraph
3641 pTableDesc
->FinishSwTable();
3644 if (!maTableStack
.empty())
3646 maTracer
.EnterEnvironment(sw::log::eTable
, rtl::OUString::valueOf(
3647 static_cast<sal_Int32
>(maTableStack
.size())));
3651 // --> OD 2009-04-16 #i101116#
3652 // Keep PaM on table end only for nested tables
3655 mpTableEndPaM
.reset(new SwPaM(*pPaM
));
3660 // GetTableLeft() wird fuer absatzgebundene Grafikobjekte in Tabellen
3662 // WW nimmt bei eingerueckten Tabellen den Absatzrand, der ohne Tabelle
3663 // gueltig waere, als Basis; SW benutzt den linken Tabellenrand.
3664 short SwWW8ImplReader::GetTableLeft()
3666 return (pTableDesc
) ? pTableDesc
->GetMinLeft() : 0;
3669 bool SwWW8ImplReader::IsInvalidOrToBeMergedTabCell() const
3674 const WW8_TCell
* pCell
= pTableDesc
->GetAktWWCell();
3676 return !pTableDesc
->IsValidCell( pTableDesc
->GetAktCol() )
3678 && ( !pCell
->bFirstMerged
3680 || ( pCell
->bVertMerge
3681 && !pCell
->bVertRestart
3688 USHORT
SwWW8ImplReader::StyleUsingLFO( USHORT nLFOIndex
) const
3690 USHORT nRes
= USHRT_MAX
;
3693 for(USHORT nI
= 0; nI
< pStyles
->GetCount(); nI
++ )
3694 if( pCollA
[ nI
].bValid
3695 && (nLFOIndex
== pCollA
[ nI
].nLFOIndex
) )
3701 const SwFmt
* SwWW8ImplReader::GetStyleWithOrgWWName( String
& rName
) const
3706 for(USHORT nI
= 0; nI
< pStyles
->GetCount(); nI
++ )
3707 if( pCollA
[ nI
].bValid
3708 && (rName
.Equals( pCollA
[ nI
].GetOrgWWName())) )
3710 pRet
= pCollA
[ nI
].pFmt
;
3717 //-----------------------------------------
3719 //-----------------------------------------
3721 const BYTE
* WW8RStyle::HasParaSprm( USHORT nId
) const
3723 if( !pParaSprms
|| !nSprmsLen
)
3726 const BYTE
* pSprms
= pParaSprms
;
3729 for( i
=0; i
< nSprmsLen
; )
3731 USHORT nAktId
= maSprmParser
.GetSprmId(pSprms
);
3734 return pSprms
+ maSprmParser
.DistanceToData(nId
);
3736 x
= maSprmParser
.GetSprmSize(nAktId
, pSprms
);
3740 return 0; // Sprm not found
3743 void WW8RStyle::ImportSprms(BYTE
*pSprms
, short nLen
, bool bPap
)
3750 pParaSprms
= pSprms
; // fuer HasParaSprms()
3756 USHORT nL1
= pIo
->ImportSprm(pSprms
);
3765 void WW8RStyle::ImportSprms(sal_Size nPosFc
, short nLen
, bool bPap
)
3770 BYTE
*pSprms
= new BYTE
[nLen
];
3772 pStStrm
->Seek(nPosFc
);
3773 pStStrm
->Read(pSprms
, nLen
);
3775 ImportSprms(pSprms
, nLen
, bPap
);
3780 static inline short WW8SkipOdd(SvStream
* pSt
)
3782 if ( pSt
->Tell() & 0x1 )
3791 static inline short WW8SkipEven(SvStream
* pSt
)
3793 if (!(pSt
->Tell() & 0x1))
3802 short WW8RStyle::ImportUPX(short nLen
, bool bPAP
, bool bOdd
)
3806 if( 0 < nLen
) // Empty ?
3809 nLen
= nLen
- WW8SkipEven( pStStrm
);
3811 nLen
= nLen
- WW8SkipOdd( pStStrm
);
3818 cbUPX
= nLen
; // !cbUPX auf nLen verkleinert!
3820 if( (1 < cbUPX
) || ( (0 < cbUPX
) && !bPAP
) )
3833 sal_Size nPos
= pStStrm
->Tell(); // falls etwas falsch interpretiert
3834 // wird, gehts danach wieder richtig
3835 ImportSprms( nPos
, cbUPX
, bPAP
);
3837 if ( pStStrm
->Tell() != nPos
+ cbUPX
)
3838 pStStrm
->Seek( nPos
+cbUPX
);
3840 nLen
= nLen
- cbUPX
;
3847 void WW8RStyle::ImportGrupx(short nLen
, bool bPara
, bool bOdd
)
3852 nLen
= nLen
- WW8SkipEven( pStStrm
);
3854 nLen
= nLen
- WW8SkipOdd( pStStrm
);
3856 if( bPara
) // Grupx.Papx
3857 nLen
= ImportUPX(nLen
, true, bOdd
);
3858 ImportUPX(nLen
, false, bOdd
); // Grupx.Chpx
3861 WW8RStyle::WW8RStyle(WW8Fib
& _rFib
, SwWW8ImplReader
* pI
)
3862 : WW8Style(*pI
->pTableStream
, _rFib
), maSprmParser(_rFib
.GetFIBVersion()),
3863 pIo(pI
), pStStrm(pI
->pTableStream
), pStyRule(0), nWwNumLevel(0)
3865 pIo
->pCollA
= new SwWW8StyInf
[ cstd
]; // Style-UEbersetzung WW->SW
3869 void WW8RStyle::Set1StyleDefaults()
3871 if (!bCJKFontChanged
) // Style no CJK Font? set the default
3872 pIo
->SetNewFontAttr(ftcStandardChpCJKStsh
, true, RES_CHRATR_CJK_FONT
);
3875 const WW8_FFN
* pF
= pIo
->pFonts
->GetFont(3);
3878 rtl_TextEncoding eEnc
= WW8Fib::GetFIBCharset(pF
->chs
);
3879 if ((ftcStandardChpCTLStsh
== 0) && (eEnc
== RTL_TEXTENCODING_MS_1255
))
3880 ftcStandardChpCTLStsh
= 3;
3883 if (ftcStandardChpCJKStsh
== 0)
3884 ftcStandardChpCJKStsh
= 2;
3886 if (!bCTLFontChanged
) // Style no CTL Font? set the default
3887 pIo
->SetNewFontAttr(ftcStandardChpCTLStsh
, true, RES_CHRATR_CTL_FONT
);
3889 //#88976# western 2nd to make western charset conversion the default
3890 if (!bFontChanged
) // Style has no Font? set the default,
3892 pIo
->SetNewFontAttr(ftcStandardChpStsh
, true, RES_CHRATR_FONT
);
3893 /* removed by a patch from cmc for #i52786#
3895 SetStyleCharSet(pIo->pCollA[pIo->nAktColl]);
3899 if( !pIo
->bNoAttrImport
)
3901 // Style has no text color set, winword default is auto
3902 if ( !bTxtColChanged
)
3903 pIo
->pAktColl
->SetFmtAttr(SvxColorItem(Color(COL_AUTO
), RES_CHRATR_COLOR
));
3905 // Style has no FontSize ? WinWord Default is 10pt for western and asian
3906 if( !bFSizeChanged
)
3908 SvxFontHeightItem
aAttr(200, 100, RES_CHRATR_FONTSIZE
);
3909 pIo
->pAktColl
->SetFmtAttr(aAttr
);
3910 aAttr
.SetWhich(RES_CHRATR_CJK_FONTSIZE
);
3911 pIo
->pAktColl
->SetFmtAttr(aAttr
);
3914 // Style has no FontSize ? WinWord Default is 10pt for western and asian
3915 if( !bFCTLSizeChanged
)
3917 SvxFontHeightItem
aAttr(200, 100, RES_CHRATR_FONTSIZE
);
3918 aAttr
.SetWhich(RES_CHRATR_CTL_FONTSIZE
);
3919 pIo
->pAktColl
->SetFmtAttr(aAttr
);
3922 if( pIo
->pWDop
->fWidowControl
&& !bWidowsChanged
) // Widows ?
3924 pIo
->pAktColl
->SetFmtAttr( SvxWidowsItem( 2, RES_PARATR_WIDOWS
) );
3925 pIo
->pAktColl
->SetFmtAttr( SvxOrphansItem( 2, RES_PARATR_ORPHANS
) );
3930 bool WW8RStyle::PrepareStyle(SwWW8StyInf
&rSI
, ww::sti eSti
, sal_uInt16 nThisStyle
, sal_uInt16 nNextStyle
)
3937 sw::util::ParaStyleMapper::StyleResult aResult
=
3938 pIo
->maParaStyleMapper
.GetStyle(rSI
.GetOrgWWName(), eSti
);
3939 pColl
= aResult
.first
;
3940 bStyExist
= aResult
.second
;
3945 sw::util::CharStyleMapper::StyleResult aResult
=
3946 pIo
->maCharStyleMapper
.GetStyle(rSI
.GetOrgWWName(), eSti
);
3947 pColl
= aResult
.first
;
3948 bStyExist
= aResult
.second
;
3951 bool bImport
= !bStyExist
|| pIo
->mbNewDoc
; // Inhalte Importieren ?
3952 bool bOldNoImp
= pIo
->bNoAttrImport
;
3953 rSI
.bImportSkipped
= !bImport
;
3956 pIo
->bNoAttrImport
= true;
3961 // --> OD 2007-01-25 #i73790# - method renamed
3962 pColl
->ResetAllFmtAttr();
3965 pColl
->SetAuto(false); // nach Empfehlung JP
3966 } // macht die UI aber anders
3967 pIo
->pAktColl
= pColl
;
3968 rSI
.pFmt
= pColl
; // UEbersetzung WW->SW merken
3969 rSI
.bImportSkipped
= !bImport
;
3971 // Set Based on style
3972 USHORT j
= rSI
.nBase
;
3973 if (j
!= nThisStyle
&& j
< cstd
)
3975 SwWW8StyInf
* pj
= &pIo
->pCollA
[j
];
3976 if (rSI
.pFmt
&& pj
->pFmt
&& rSI
.bColl
== pj
->bColl
)
3978 rSI
.pFmt
->SetDerivedFrom( pj
->pFmt
); // ok, Based on eintragen
3979 rSI
.eLTRFontSrcCharSet
= pj
->eLTRFontSrcCharSet
;
3980 rSI
.eRTLFontSrcCharSet
= pj
->eRTLFontSrcCharSet
;
3981 rSI
.eCJKFontSrcCharSet
= pj
->eCJKFontSrcCharSet
;
3982 rSI
.n81Flags
= pj
->n81Flags
;
3983 rSI
.n81BiDiFlags
= pj
->n81BiDiFlags
;
3984 rSI
.nOutlineLevel
= pj
->nOutlineLevel
;
3985 rSI
.bParaAutoBefore
= pj
->bParaAutoBefore
;
3986 rSI
.bParaAutoAfter
= pj
->bParaAutoAfter
;
3989 rSI
.pWWFly
= new WW8FlyPara(pIo
->bVer67
, pj
->pWWFly
);
3992 else if( pIo
->mbNewDoc
&& bStyExist
)
3993 rSI
.pFmt
->SetDerivedFrom(0);
3995 rSI
.nFollow
= nNextStyle
; // Follow merken
3997 pStyRule
= 0; // falls noetig, neu anlegen
3998 bTxtColChanged
= bFontChanged
= bCJKFontChanged
= bCTLFontChanged
=
3999 bFSizeChanged
= bFCTLSizeChanged
= bWidowsChanged
= false;
4000 pIo
->SetNAktColl( nThisStyle
);
4001 pIo
->bStyNormal
= nThisStyle
== 0;
4005 void WW8RStyle::PostStyle(SwWW8StyInf
&rSI
, bool bOldNoImp
)
4007 // Alle moeglichen Attribut-Flags zuruecksetzen,
4008 // da es in Styles keine Attr-Enden gibt
4010 pIo
->bHasBorder
= pIo
->bShdTxtCol
= pIo
->bCharShdTxtCol
4011 = pIo
->bSpec
= pIo
->bObj
= pIo
->bSymbol
= false;
4014 // If Style basiert auf Nichts oder Basis ignoriert
4015 if ((rSI
.nBase
>= cstd
|| pIo
->pCollA
[rSI
.nBase
].bImportSkipped
) && rSI
.bColl
)
4017 //! Char-Styles funktionieren aus
4018 // unerfindlichen Gruenden nicht
4019 // -> dann evtl. harte WW-Defaults
4021 Set1StyleDefaults();
4024 pStyRule
= 0; // zur Sicherheit
4025 pIo
->bStyNormal
= false;
4026 pIo
->SetNAktColl( 0 );
4027 pIo
->bNoAttrImport
= bOldNoImp
;
4028 // rasch nochmal die Listen-Merk-Felder zuruecksetzen,
4029 // fuer den Fall dass sie beim einlesen des Styles verwendet wurden
4030 pIo
->nLFOPosition
= USHRT_MAX
;
4031 pIo
->nListLevel
= WW8ListManager::nMaxLevel
;
4034 void WW8RStyle::Import1Style( USHORT nNr
)
4036 SwWW8StyInf
&rSI
= pIo
->pCollA
[nNr
];
4038 if( rSI
.bImported
|| !rSI
.bValid
)
4041 rSI
.bImported
= true; // jetzt schon Flag setzen
4042 // verhindert endlose Rekursion
4044 // gueltig und nicht NIL und noch nicht Importiert
4046 if( rSI
.nBase
< cstd
&& !pIo
->pCollA
[rSI
.nBase
].bImported
)
4047 Import1Style( rSI
.nBase
);
4049 pStStrm
->Seek( rSI
.nFilePos
);
4054 WW8_STD
* pStd
= Read1Style( nSkip
, &sName
, &cbStd
);// lies Style
4057 rSI
.SetOrgWWIdent( sName
, pStd
->sti
);
4059 // either no Name or unused Slot or unknown Style
4061 if ( !pStd
|| (0 == sName
.Len()) || ((1 != pStd
->sgc
) && (2 != pStd
->sgc
)) )
4063 pStStrm
->SeekRel( nSkip
);
4067 bool bOldNoImp
= PrepareStyle(rSI
, static_cast<ww::sti
>(pStd
->sti
), nNr
, pStd
->istdNext
);
4069 // falls etwas falsch interpretiert wird, gehts danach wieder richtig
4070 long nPos
= pStStrm
->Tell();
4072 //Variable parts of the STD start at even byte offsets, but "inside
4073 //the STD", which I take to meaning even in relation to the starting
4074 //position of the STD, which matches findings in #89439#, generally it
4075 //doesn't matter as the STSHI starts off nearly always on an even
4078 //Import of the Style Contents
4079 ImportGrupx(nSkip
, pStd
->sgc
== 1, rSI
.nFilePos
& 1);
4081 PostStyle(rSI
, bOldNoImp
);
4083 pStStrm
->Seek( nPos
+nSkip
);
4087 void WW8RStyle::RecursiveReg(USHORT nNr
)
4089 SwWW8StyInf
&rSI
= pIo
->pCollA
[nNr
];
4090 if( rSI
.bImported
|| !rSI
.bValid
)
4093 rSI
.bImported
= true;
4095 if( rSI
.nBase
< cstd
&& !pIo
->pCollA
[rSI
.nBase
].bImported
)
4096 RecursiveReg(rSI
.nBase
);
4098 pIo
->RegisterNumFmtOnStyle(nNr
);
4103 After all styles are imported then we can recursively apply numbering
4104 styles to them, and change their tab stop settings if they turned out
4105 to have special first line indentation.
4107 void WW8RStyle::PostProcessStyles()
4111 Clear all imported flags so that we can recursively apply numbering
4112 formats and use it to mark handled ones
4114 for (i
=0; i
< cstd
; ++i
)
4115 pIo
->pCollA
[i
].bImported
= false;
4118 Register the num formats and tabstop changes on the styles recursively.
4122 In the same loop apply the tabstop changes required because we need to
4123 change their location if theres a special indentation for the first line,
4124 By avoiding making use of each styles margins during reading of their
4125 tabstops we don't get problems with doubly adjusting tabstops that
4128 for (i
=0; i
< cstd
; ++i
)
4130 if (pIo
->pCollA
[i
].bValid
)
4137 void WW8RStyle::ScanStyles() // untersucht Style-Abhaengigkeiten
4138 { // und ermittelt die Filepos fuer jeden Style
4140 WW8_FC nStyleStart = rFib.fcStshf;
4141 pStStrm->Seek( nStyleStart );
4143 for (USHORT i
= 0; i
< cstd
; ++i
)
4146 SwWW8StyInf
&rSI
= pIo
->pCollA
[i
];
4148 rSI
.nFilePos
= pStStrm
->Tell(); // merke FilePos
4149 WW8_STD
* pStd
= Read1Style( nSkip
, 0, 0 ); // read STD
4150 rSI
.bValid
= (0 != pStd
);
4153 rSI
.nBase
= pStd
->istdBase
; // merke Basis
4154 rSI
.bColl
= ( pStd
->sgc
== 1 ); // Para-Style
4157 rSI
= SwWW8StyInf();
4160 pStStrm
->SeekRel( nSkip
); // ueberlese Namen und Sprms
4164 std::vector
<BYTE
> ChpxToSprms(const Word2CHPX
&rChpx
)
4166 std::vector
<BYTE
> aRet
;
4169 aRet
.push_back( static_cast< BYTE
>(128 + rChpx
.fBold
) );
4172 aRet
.push_back( static_cast< BYTE
>(128 + rChpx
.fItalic
) );
4175 aRet
.push_back( static_cast< BYTE
>(128 + rChpx
.fStrike
) );
4178 aRet
.push_back( static_cast< BYTE
>(128 + rChpx
.fOutline
) );
4181 aRet
.push_back( static_cast< BYTE
>(128 + rChpx
.fSmallCaps
) );
4184 aRet
.push_back( static_cast< BYTE
>(128 + rChpx
.fCaps
) );
4187 aRet
.push_back( static_cast< BYTE
>(128 + rChpx
.fVanish
) );
4193 ShortToSVBT16(rChpx
.ftc
, a
);
4194 aRet
.push_back(a
[1]);
4195 aRet
.push_back(a
[0]);
4201 aRet
.push_back(rChpx
.kul
);
4208 ShortToSVBT16(rChpx
.lid
, a
);
4209 aRet
.push_back(a
[1]);
4210 aRet
.push_back(a
[0]);
4216 aRet
.push_back(rChpx
.ico
);
4224 ShortToSVBT16(rChpx
.hps
, a
);
4225 aRet
.push_back(a
[0]);
4226 // aRet.push_back(a[1]);
4232 aRet
.push_back(rChpx
.hpsPos
);
4236 aRet
.push_back( static_cast< BYTE
>(128 + rChpx
.fBoldBi
) );
4239 aRet
.push_back( static_cast< BYTE
>(128 + rChpx
.fItalicBi
) );
4245 ShortToSVBT16(rChpx
.fsFtcBi
, a
);
4246 aRet
.push_back(a
[1]);
4247 aRet
.push_back(a
[0]);
4254 ShortToSVBT16(rChpx
.lidBi
, a
);
4255 aRet
.push_back(a
[1]);
4256 aRet
.push_back(a
[0]);
4262 aRet
.push_back(rChpx
.icoBi
);
4269 ShortToSVBT16(rChpx
.hpsBi
, a
);
4270 aRet
.push_back(a
[1]);
4271 aRet
.push_back(a
[0]);
4277 Word2CHPX
ReadWord2Chpx(SvStream
&rSt
, sal_Size nOffset
, sal_uInt8 nSize
)
4294 aChpx
.fBold
= nFlags8
& 0x01;
4295 aChpx
.fItalic
= (nFlags8
& 0x02) >> 1;
4296 aChpx
.fRMarkDel
= (nFlags8
& 0x04) >> 2;
4297 aChpx
.fOutline
= (nFlags8
& 0x08) >> 3;
4298 aChpx
.fFldVanish
= (nFlags8
& 0x10) >> 4;
4299 aChpx
.fSmallCaps
= (nFlags8
& 0x20) >> 5;
4300 aChpx
.fCaps
= (nFlags8
& 0x40) >> 6;
4301 aChpx
.fVanish
= (nFlags8
& 0x80) >> 7;
4303 if (nCount
>= nSize
) break;
4307 aChpx
.fRMark
= nFlags8
& 0x01;
4308 aChpx
.fSpec
= (nFlags8
& 0x02) >> 1;
4309 aChpx
.fStrike
= (nFlags8
& 0x04) >> 2;
4310 aChpx
.fObj
= (nFlags8
& 0x08) >> 3;
4311 aChpx
.fBoldBi
= (nFlags8
& 0x10) >> 4;
4312 aChpx
.fItalicBi
= (nFlags8
& 0x20) >> 5;
4313 aChpx
.fBiDi
= (nFlags8
& 0x40) >> 6;
4314 aChpx
.fDiacUSico
= (nFlags8
& 0x80) >> 7;
4316 if (nCount
>= nSize
) break;
4320 aChpx
.fsIco
= nFlags8
& 0x01;
4321 aChpx
.fsFtc
= (nFlags8
& 0x02) >> 1;
4322 aChpx
.fsHps
= (nFlags8
& 0x04) >> 2;
4323 aChpx
.fsKul
= (nFlags8
& 0x08) >> 3;
4324 aChpx
.fsPos
= (nFlags8
& 0x10) >> 4;
4325 aChpx
.fsSpace
= (nFlags8
& 0x20) >> 5;
4326 aChpx
.fsLid
= (nFlags8
& 0x40) >> 6;
4327 aChpx
.fsIcoBi
= (nFlags8
& 0x80) >> 7;
4329 if (nCount
>= nSize
) break;
4333 aChpx
.fsFtcBi
= nFlags8
& 0x01;
4334 aChpx
.fsHpsBi
= (nFlags8
& 0x02) >> 1;
4335 aChpx
.fsLidBi
= (nFlags8
& 0x04) >> 2;
4337 if (nCount
>= nSize
) break;
4341 if (nCount
>= nSize
) break;
4345 if (nCount
>= nSize
) break;
4349 aChpx
.qpsSpace
= nFlags8
& 0x3F;
4350 aChpx
.fSysVanish
= (nFlags8
& 0x40) >> 6;
4351 aChpx
.fNumRun
= (nFlags8
& 0x80) >> 7;
4353 if (nCount
>= nSize
) break;
4357 aChpx
.ico
= nFlags8
& 0x1F;
4358 aChpx
.kul
= (nFlags8
& 0xE0) >> 5;
4360 if (nCount
>= nSize
) break;
4361 rSt
>> aChpx
.hpsPos
;
4364 if (nCount
>= nSize
) break;
4368 if (nCount
>= nSize
) break;
4372 if (nCount
>= nSize
) break;
4376 if (nCount
>= nSize
) break;
4380 if (nCount
>= nSize
) break;
4384 if (nCount
>= nSize
) break;
4391 rSt
.SeekRel(nSize
-nCount
);
4397 struct pxoffset
{ sal_Size mnOffset
; sal_uInt8 mnSize
; };
4400 void WW8RStyle::ImportOldFormatStyles()
4402 for (sal_uInt16 i
=0; i
< cstd
; ++i
)
4404 pIo
->pCollA
[i
].bColl
= true;
4405 //every chain must end eventually at the null style (style code 222)
4406 pIo
->pCollA
[i
].nBase
= 222;
4409 rtl_TextEncoding eStructChrSet
= WW8Fib::GetFIBCharset(
4410 pIo
->pWwFib
->chseTables
);
4417 sal_uInt16 nByteCount
= 2;
4419 while (nByteCount
< cbName
)
4425 sal_uInt8 stc
= static_cast< sal_uInt8
>((stcp
- cstcStd
) & 255);
4426 SwWW8StyInf
&rSI
= pIo
->pCollA
[stc
];
4427 if (nCount
!= 0xFF) // undefined style
4430 if (nCount
== 0) // inbuilt style
4432 ww::sti eSti
= ww::GetCanonicalStiFromStc(stc
);
4433 if (const sal_Char
*pStr
= GetEnglishNameFromSti(eSti
))
4434 sName
= String(pStr
, RTL_TEXTENCODING_ASCII_US
);
4436 sName
= String(CREATE_CONST_ASC("Unknown"));
4441 nByteCount
= static_cast< sal_uInt16
>(nByteCount
+ SafeReadString(aTmp
, nCount
, rSt
));
4442 sName
= String(aTmp
, eStructChrSet
);
4444 rSI
.SetOrgWWIdent(sName
, stc
);
4445 rSI
.bImported
= true;
4449 ww::sti eSti
= ww::GetCanonicalStiFromStc(stc
);
4450 if (const sal_Char
*pStr
= GetEnglishNameFromSti(eSti
))
4452 String sName
= String(pStr
, RTL_TEXTENCODING_ASCII_US
);
4453 rSI
.SetOrgWWIdent(sName
, stc
);
4459 USHORT nStyles
=stcp
;
4461 std::vector
<pxoffset
> aCHPXOffsets(stcp
);
4466 std::vector
< std::vector
<BYTE
> > aConvertedChpx
;
4467 while (nByteCount
< cbChpx
)
4473 aCHPXOffsets
[stcp
].mnSize
= 0;
4477 sal_uInt8 nRemainder
= cb
;
4479 aCHPXOffsets
[stcp
].mnOffset
= rSt
.Tell();
4480 aCHPXOffsets
[stcp
].mnSize
= nRemainder
;
4482 Word2CHPX aChpx
= ReadWord2Chpx(rSt
, aCHPXOffsets
[stcp
].mnOffset
,
4483 aCHPXOffsets
[stcp
].mnSize
);
4484 aConvertedChpx
.push_back( ChpxToSprms(aChpx
) );
4486 nByteCount
+= nRemainder
;
4489 aConvertedChpx
.push_back( std::vector
<BYTE
>() );
4492 if (stcp
== nStyles
)
4494 rSt
.SeekRel(cbChpx
-nByteCount
);
4495 nByteCount
+= cbChpx
-nByteCount
;
4499 std::vector
<pxoffset
> aPAPXOffsets(stcp
);
4504 while (nByteCount
< cbPapx
)
4510 aPAPXOffsets
[stcp
].mnSize
= 0;
4518 sal_uInt8 nRemainder
= cb
-7;
4520 aPAPXOffsets
[stcp
].mnOffset
= rSt
.Tell();
4521 aPAPXOffsets
[stcp
].mnSize
= nRemainder
;
4523 rSt
.SeekRel(nRemainder
);
4524 nByteCount
+= nRemainder
;
4529 if (stcp
== nStyles
)
4531 rSt
.SeekRel(cbPapx
-nByteCount
);
4532 nByteCount
+= cbPapx
-nByteCount
;
4539 if (iMac
> nStyles
) iMac
= nStyles
;
4541 for (stcp
= 0; stcp
< iMac
; ++stcp
)
4543 sal_uInt8 stcNext
, stcBase
;
4547 sal_uInt8 stc
= static_cast< sal_uInt8
>((stcp
- cstcStd
) & 255);
4550 #i64557# style based on itself
4551 every chain must end eventually at the null style (style code 222)
4556 SwWW8StyInf
&rSI
= pIo
->pCollA
[stc
];
4557 rSI
.nBase
= stcBase
;
4559 ww::sti eSti
= ww::GetCanonicalStiFromStc(stc
);
4561 if (eSti
== ww::stiNil
)
4566 if (ww::StandardStiIsCharStyle(eSti
) && !aPAPXOffsets
[stcp
].mnSize
)
4567 pIo
->pCollA
[stc
].bColl
= false;
4569 bool bOldNoImp
= PrepareStyle(rSI
, eSti
, stc
, stcNext
);
4571 ImportSprms(aPAPXOffsets
[stcp
].mnOffset
, aPAPXOffsets
[stcp
].mnSize
,
4574 if (aConvertedChpx
[stcp
].size() > 0)
4575 ImportSprms(&(aConvertedChpx
[stcp
][0]),
4576 static_cast< short >(aConvertedChpx
[stcp
].size()),
4579 PostStyle(rSI
, bOldNoImp
);
4583 void WW8RStyle::ImportNewFormatStyles()
4585 ScanStyles(); // Scanne Based On
4587 for (USHORT i
= 0; i
< cstd
; ++i
) // import Styles
4588 if (pIo
->pCollA
[i
].bValid
)
4592 void WW8RStyle::ImportStyles()
4594 if (ww::eWW2
== pIo
->pWwFib
->GetFIBVersion())
4595 ImportOldFormatStyles();
4597 ImportNewFormatStyles();
4600 void WW8RStyle::Import()
4602 pIo
->pDfltTxtFmtColl
= pIo
->rDoc
.GetDfltTxtFmtColl();
4603 pIo
->pStandardFmtColl
=
4604 pIo
->rDoc
.GetTxtCollFromPool(RES_POOLCOLL_STANDARD
, false);
4606 if( pIo
->nIniFlags
& WW8FL_NO_STYLES
)
4611 for (USHORT i
= 0; i
< cstd
; ++i
)
4614 SwWW8StyInf
* pi
= &pIo
->pCollA
[i
];
4615 USHORT j
= pi
->nFollow
;
4618 SwWW8StyInf
* pj
= &pIo
->pCollA
[j
];
4619 if ( j
!= i
// sinnvoller Index ?
4620 && pi
->pFmt
// Format ok ?
4621 && pj
->pFmt
// Derived-Format ok ?
4622 && pi
->bColl
// geht nur bei Absatz-Vorlagen (WW)
4623 && pj
->bColl
){ // beides gleicher Typ ?
4624 ( (SwTxtFmtColl
*)pi
->pFmt
)->SetNextTxtFmtColl(
4625 *(SwTxtFmtColl
*)pj
->pFmt
); // ok, eintragen
4629 // Die Sonderbehandlung zur Setzen der
4630 // Default-Zeichenvorlage "Absatz-Standardschriftart" ( Style-ID 65 ) fehlt
4631 // Sie ist aber defaultmaessig leer ( WW6 dt und US ) und von der
4632 // WW-UI nicht zu veraendern, so dass das nicht stoert.
4633 // Der Mechanismus waere folgender:
4634 // if( bNew ) rDoc.SetDefault( pDefCharFmt->GetAttrSet() );
4636 // fuer z.B. Tabellen wird ein immer gueltiger Std-Style gebraucht
4638 if( pIo
->pCollA
[0].pFmt
&& pIo
->pCollA
[0].bColl
&& pIo
->pCollA
[0].bValid
)
4639 pIo
->pDfltTxtFmtColl
= (SwTxtFmtColl
*)pIo
->pCollA
[0].pFmt
;
4641 pIo
->pDfltTxtFmtColl
= pIo
->rDoc
.GetDfltTxtFmtColl();
4644 // set Hyphenation flag on BASIC para-style
4645 if (pIo
->mbNewDoc
&& pIo
->pStandardFmtColl
)
4647 if (pIo
->pWDop
->fAutoHyphen
4648 && SFX_ITEM_SET
!= pIo
->pStandardFmtColl
->GetItemState(
4649 RES_PARATR_HYPHENZONE
, false) )
4651 SvxHyphenZoneItem
aAttr(true, RES_PARATR_HYPHENZONE
);
4652 aAttr
.GetMinLead() = 2;
4653 aAttr
.GetMinTrail() = 2;
4654 aAttr
.GetMaxHyphens() = 0;
4656 pIo
->pStandardFmtColl
->SetFmtAttr( aAttr
);
4660 Word defaults to ltr not from environment like writer. Regardless of
4661 the page/sections rtl setting the standard style lack of rtl still
4664 if (SFX_ITEM_SET
!= pIo
->pStandardFmtColl
->GetItemState(RES_FRAMEDIR
,
4667 pIo
->pStandardFmtColl
->SetFmtAttr(
4668 SvxFrameDirectionItem(FRMDIR_HORI_LEFT_TOP
, RES_FRAMEDIR
));
4672 // wir sind jetzt nicht mehr beim Style einlesen:
4676 CharSet
SwWW8StyInf::GetCharSet() const
4678 if ((pFmt
) && (pFmt
->GetFrmDir().GetValue() == FRMDIR_HORI_RIGHT_TOP
))
4679 return eRTLFontSrcCharSet
;
4680 return eLTRFontSrcCharSet
;
4683 /* vi:set tabstop=4 shiftwidth=4 expandtab: */