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