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