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