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