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