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