cmcfixes76: #i113073# redundant dereferences
[LibreOffice.git] / sw / source / filter / rtf / rtftbl.cxx
blob2c182532079df8fda230760e6ebabba1395e5122
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
32 #ifdef WTC
33 #define private public
34 #endif
35 #include <hintids.hxx>
36 #include <editeng/lrspitem.hxx>
37 #include <editeng/boxitem.hxx>
38 #include <editeng/frmdiritem.hxx>
39 #include <svtools/rtftoken.h>
40 #include <fmtfsize.hxx>
41 #include <fmtpdsc.hxx>
42 #include <ndtxt.hxx>
43 #include <doc.hxx>
44 #include <pam.hxx>
45 #include <swparrtf.hxx>
46 #include <swtable.hxx>
47 #include <tblsel.hxx>
48 #include <swtblfmt.hxx>
49 #include <wrtswtbl.hxx>
50 #include <tblenum.hxx>
51 #include <frmatr.hxx>
52 #include <fmtrowsplt.hxx>
54 using namespace ::com::sun::star;
56 typedef SwTableBoxFmt* SwTableBoxFmtPtr;
57 SV_DECL_PTRARR( SwBoxFrmFmts, SwTableBoxFmtPtr, 25, 50 )
59 class SwShareBoxFmts;
60 extern void _DeleteBox( SwTable& rTbl, SwTableBox* pBox, SwUndo* = 0,
61 BOOL = TRUE, const BOOL = TRUE, SwShareBoxFmts* = 0 );
63 struct Row
65 bool mbUseLeftRowPad, mbUseRightRowPad, mbUseTopRowPad, mbUseBottomRowPad;
66 long mnLeftRowPad, mnRightRowPad, mnTopRowPad, mnBottomRowPad;
67 USHORT mnBrdDist;
68 Row() :
69 mbUseLeftRowPad(false), mbUseRightRowPad(false),
70 mbUseTopRowPad(false), mbUseBottomRowPad(false),
71 mnLeftRowPad(0), mnRightRowPad(0), mnTopRowPad(0), mnBottomRowPad(0),
72 mnBrdDist(MIN_BORDER_DIST)
76 static void SetRowBorder(SfxItemSet& rSet, const Row &rRow)
78 #if 1
79 SvxBoxItem aBox((const SvxBoxItem&)rSet.Get(RES_BOX, false));
80 aBox.SetDistance( static_cast< USHORT >(rRow.mbUseLeftRowPad ? rRow.mnLeftRowPad : rRow.mnBrdDist),
81 BOX_LINE_LEFT);
83 aBox.SetDistance( static_cast< USHORT >(rRow.mbUseRightRowPad ? rRow.mnRightRowPad : rRow.mnBrdDist),
84 BOX_LINE_RIGHT);
86 aBox.SetDistance( static_cast< USHORT >(rRow.mbUseTopRowPad ? rRow.mnTopRowPad : 0),
87 BOX_LINE_TOP);
89 aBox.SetDistance( static_cast< USHORT >(rRow.mbUseBottomRowPad ? rRow.mnBottomRowPad : 0),
90 BOX_LINE_BOTTOM);
92 rSet.Put(aBox);
93 #else
94 const SfxPoolItem* pItem;
95 if (SFX_ITEM_SET == rSet.GetItemState(RES_BOX, FALSE, &pItem))
97 SvxBoxItem aBox( *(SvxBoxItem*)pItem );
98 aBox.SetDistance(rRow.mbUseLeftRowPad ? rRow.mnLeftRowPad : rRow.mnBrdDist,
99 BOX_LINE_LEFT);
101 aBox.SetDistance(rRow.mbUseRightRowPad ? rRow.mnRightRowPad : rRow.mnBrdDist,
102 BOX_LINE_RIGHT);
104 aBox.SetDistance(rRow.mbUseTopRowPad ? rRow.mnTopRowPad : 0,
105 BOX_LINE_TOP);
107 aBox.SetDistance(rRow.mbUseBottomRowPad ? rRow.mnBottomRowPad : 0,
108 BOX_LINE_BOTTOM);
110 rSet.Put(aBox);
112 #endif
115 void rtfSections::PrependedInlineNode(const SwPosition &rPos,
116 const SwNode &rNode)
118 ASSERT(!mrReader.IsNewDoc() || !maSegments.empty(),
119 "should not be possible, must be at least one segment in a new document");
120 if ((!maSegments.empty()) && (maSegments.back().maStart == rPos.nNode))
121 maSegments.back().maStart = SwNodeIndex(rNode);
124 bool SwRTFParser::IsBorderToken(int nToken)
127 i30222 i28983
128 Our ability to sense border tokens is broken rtftoken.h is
129 organised in a way that ignores some border tokens. ReadBorderAttr
130 still doesn't support the more exotic borders but at least this
131 won't cause the parser to prematuerely exit the table
133 bool bResult = false;
135 bResult = (nToken >= RTF_BRDRDASHD && nToken <= RTF_BRDRTHTNMG) ||
136 (nToken >= RTF_BRDRTNTHSG && nToken <= RTF_BRDRWAVY);
138 return bResult;
141 void SwRTFParser::ReadTable( int nToken )
143 nInsTblRow = USHRT_MAX;
145 if (CantUseTables())
147 // alle Tabellen-Tokens ueberlesen
148 nToken = GetNextToken(); // RTF_TROWD ueberlesen
149 do {
150 if( RTF_TABLEDEF != (nToken & ~(0xff | RTF_SWGDEFS)) &&
151 RTF_UNKNOWNCONTROL != nToken )
153 SkipToken( -1 );
154 break;
156 nToken = GetNextToken();
157 } while( IsParserWorking() );
158 return ;
161 // verhinder Tabelle in Tabelle/Footnote
162 SwTwips nTblSz = 0;
163 int bReadNewCell = FALSE, bChkExistTbl = FALSE;
166 enum Limits {eMAXCELLS=64000};
168 SvBools aMergeBackup;
169 int nCount = aMergeBoxes.Count();
170 for (USHORT i = 0; i < nCount; ++i)
171 aMergeBackup.Insert(aMergeBoxes[i], i);
173 // kein TROWD aber ein TabellenToken -> zwischen TROWD und Tab.Token
174 // waren andere Zeichen (siehe Bug 27445.rtf)
175 if( RTF_TROWD == nToken || !pTableNode )
177 if( RTF_TROWD == nToken )
178 nToken = GetNextToken(); // RTF_TROWD ueberlesen
180 // Flags fuer die gemergten Boxen loeschen
181 aMergeBoxes.Remove( 0, aMergeBoxes.Count() );
182 aMergeBoxes.Insert( (BOOL)FALSE, USHORT(0) );
183 nAktBox = 0;
185 // wenn schon in einer Tabellen, dann splitte oder benutze
186 // die bisherigen Boxen weiter
187 bChkExistTbl = 0 != pDoc->GetNodes()[ pPam->GetPoint()->nNode ]->FindTableNode();
189 else
191 bReadNewCell = TRUE;
192 SwTableLines& rLns = pTableNode->GetTable().GetTabLines();
193 SwTableLine* pLine = rLns[ rLns.Count()-1 ];
194 // very robust to avoid crashes like bug 127425 + crash reports 118743
195 if( pLine )
197 USHORT nTmpBox = nAktBox;
198 if( nTmpBox > pLine->GetTabBoxes().Count() )
199 nTmpBox = pLine->GetTabBoxes().Count();
201 for( USHORT n = nTmpBox; n; )
203 const SwTableBox *pTmp = pLine->GetTabBoxes()[ --n ];
204 if( pTmp )
206 const SwFrmFmt* pTmpFmt = pTmp->GetFrmFmt();
207 if( pTmpFmt )
208 nTblSz += pTmpFmt->GetFrmSize().GetWidth();
215 sal_Int16 eAdjust = text::HoriOrientation::LEFT; // default fuer Tabellen
216 SwTwips nLSpace = 0;
217 Row aRow;
219 bool bUseLeftCellPad = false, bUseRightCellPad = false,
220 bUseTopCellPad = false, bUseBottomCellPad = false;
221 long nLeftCellPad = 0, nRightCellPad = 0, nTopCellPad = 0,
222 nBottomCellPad = 0;
224 sal_Int16 eVerOrient = text::VertOrientation::NONE;
225 long nLineHeight = 0;
226 USHORT nBoxCnt = aMergeBoxes.Count()-1;
227 SwBoxFrmFmts aBoxFmts;
228 SwTableBoxFmt* pBoxFmt = pDoc->MakeTableBoxFmt();
229 SvxFrameDirection eDir = FRMDIR_HORI_LEFT_TOP;
230 bool bCantSplit = false;
232 int bWeiter = TRUE;
233 do {
234 switch( nToken )
236 case RTF_TRPADDFL:
237 aRow.mbUseLeftRowPad = (nTokenValue == 3) ? true : false;
238 break;
239 case RTF_TRPADDFT:
240 aRow.mbUseTopRowPad = (nTokenValue == 3) ? true : false;
241 break;
242 case RTF_TRPADDFR:
243 aRow.mbUseRightRowPad = (nTokenValue == 3) ? true : false;
244 break;
245 case RTF_TRPADDFB:
246 aRow.mbUseBottomRowPad = (nTokenValue == 3) ? true : false;
247 break;
248 case RTF_TRPADDL:
249 aRow.mnLeftRowPad = nTokenValue;
250 break;
251 case RTF_TRPADDT:
252 aRow.mnTopRowPad = nTokenValue;
253 break;
254 case RTF_TRPADDR:
255 aRow.mnRightRowPad = nTokenValue;
256 break;
257 case RTF_TRPADDB:
258 aRow.mnBottomRowPad = nTokenValue;
259 break;
261 case RTF_CLPADFL:
262 bUseLeftCellPad = (nTokenValue == 3) ? true : false;
263 break;
264 case RTF_CLPADFT:
265 bUseTopCellPad = (nTokenValue == 3) ? true : false;
266 break;
267 case RTF_CLPADFR:
268 bUseRightCellPad = (nTokenValue == 3) ? true : false;
269 break;
270 case RTF_CLPADFB:
271 bUseBottomCellPad = (nTokenValue == 3) ? true : false;
272 break;
273 case RTF_CLPADL:
274 nLeftCellPad = nTokenValue;
275 break;
276 case RTF_CLPADT:
277 nTopCellPad = nTokenValue;
278 break;
279 case RTF_CLPADR:
280 nRightCellPad = nTokenValue;
281 break;
282 case RTF_CLPADB:
283 nBottomCellPad = nTokenValue;
284 break;
286 case RTF_TRRH:
287 nLineHeight = nTokenValue;
288 break;
290 case RTF_CLMRG:
291 // would crash later on reading \cellx (#i112657#):
292 // the first cell cannot be merged with earlier ones.
293 if (nBoxCnt != 0)
295 aMergeBoxes[ nBoxCnt ] = TRUE;
297 break;
299 case RTF_CELLX:
300 if (!bTrowdRead) {
301 SwTableBoxFmt* pFmt = pBoxFmt;
302 SwTwips nSize = nTokenValue - nTblSz;
303 if( aMergeBoxes[ nBoxCnt ] )
305 // neue Zellen lesen und noch keine Formate vorhanden,
306 // dann benutze das der vorhergebende
307 if( bReadNewCell && !aBoxFmts.Count() )
309 SwTableLines& rLns = pTableNode->GetTable().GetTabLines();
310 SwTableLine* pLine = rLns[ rLns.Count()-1 ];
311 if(nAktBox!=0)
312 --nAktBox;
313 pFmt = (SwTableBoxFmt*)pLine->GetTabBoxes()[ nAktBox ]->GetFrmFmt();
315 else
316 pFmt = aBoxFmts[ aBoxFmts.Count()-1 ];
318 // --> OD 2007-01-25 #i73790# - method renamed
319 pBoxFmt->ResetAllFmtAttr();
320 // <--
321 nSize += pFmt->GetFrmSize().GetWidth();
323 else
326 if (nSize<=2*aRow.mnBrdDist) {
327 aRow.mnRightRowPad=0;
328 aRow.mbUseRightRowPad=TRUE;
330 SetRowBorder((SfxItemSet&)pBoxFmt->GetAttrSet(), aRow);
331 aBoxFmts.Insert( pBoxFmt, aBoxFmts.Count() );
332 pBoxFmt = pDoc->MakeTableBoxFmt();
335 if( !nSize )
336 nSize = COL_DFLT_WIDTH;
337 pFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nSize, 0 ));
338 nTblSz = nTokenValue;
339 aMergeBoxes.Insert( (BOOL)FALSE, ++nBoxCnt );
341 SvxBoxItem aBox(pFmt->GetBox());
343 if (bUseRightCellPad)
344 aBox.SetDistance( static_cast< USHORT >(nRightCellPad), BOX_LINE_RIGHT);
345 if (bUseBottomCellPad)
346 aBox.SetDistance( static_cast< USHORT >(nBottomCellPad), BOX_LINE_BOTTOM);
348 //Yes, these are the wrong way around, there appears to
349 //be a bug in word where these are swapped.
350 if (bUseLeftCellPad)
351 aBox.SetDistance( static_cast< USHORT >(nLeftCellPad), BOX_LINE_TOP);
352 if (bUseTopCellPad)
353 aBox.SetDistance( static_cast< USHORT >(nTopCellPad), BOX_LINE_LEFT);
356 /*#106415# The Cell Borders are now balanced on import to
357 improve the layout of tables.
360 if ( aBoxFmts.Count()>1)
363 SwTableBoxFmt* prevpFmt = aBoxFmts[ aBoxFmts.Count()-2 ];
364 SvxBoxItem prevaBox(prevpFmt->GetBox());
365 USHORT prevWidthRight=0;
366 USHORT currWidthLeft=0;
367 bool bDoubleLine=false;
368 const SvxBorderLine* brdrline ;
369 const Color* pPrevRightColor;
370 if(prevaBox.GetRight())
372 brdrline=prevaBox.GetRight();
373 prevWidthRight = brdrline->GetOutWidth();
374 pPrevRightColor = &brdrline->GetColor();
375 if(brdrline->GetInWidth())
376 bDoubleLine=true;
378 if(aBox.GetLeft())
380 brdrline=aBox.GetLeft();
381 currWidthLeft = brdrline->GetOutWidth();
382 if(brdrline->GetInWidth())
383 bDoubleLine=true;
386 if((currWidthLeft >0 || prevWidthRight >0) &&
387 !bDoubleLine)
389 USHORT newBorderWidth=(currWidthLeft+prevWidthRight)/2 ;
390 if(newBorderWidth /2 ==DEF_LINE_WIDTH_0 )
392 newBorderWidth =DEF_LINE_WIDTH_0;
394 else if(newBorderWidth /2 >=(DEF_LINE_WIDTH_4-DEF_LINE_WIDTH_3))
396 newBorderWidth =DEF_LINE_WIDTH_4;
398 else if(newBorderWidth /2 >=(DEF_LINE_WIDTH_3-DEF_LINE_WIDTH_2))
400 newBorderWidth =DEF_LINE_WIDTH_3;
402 else if(newBorderWidth /2>=(DEF_LINE_WIDTH_2-DEF_LINE_WIDTH_1))
404 newBorderWidth =DEF_LINE_WIDTH_2;
406 else if(newBorderWidth /2>=(DEF_LINE_WIDTH_1 - DEF_LINE_WIDTH_0) )
408 newBorderWidth =DEF_LINE_WIDTH_1;
410 else
412 newBorderWidth =DEF_LINE_WIDTH_0;
414 const SvxBorderLine newbrdrline(pPrevRightColor, newBorderWidth,0,0);
415 aBox.SetLine(&newbrdrline,BOX_LINE_LEFT);
416 prevaBox.SetLine(&newbrdrline,BOX_LINE_RIGHT);
417 prevpFmt->SetAttr(prevaBox);
423 pFmt->SetFmtAttr(aBox);
425 bUseLeftCellPad = false;
426 bUseRightCellPad = false;
427 bUseTopCellPad = false;
428 bUseBottomCellPad = false;
430 break;
432 case RTF_TRGAPH:
433 //$flr bug #117887#: RTF: wrong internal table cell margin imported (A13)
434 aRow.mnBrdDist = (nTokenValue>0?(USHORT)nTokenValue:0); // filter out negative values of \trgaph
435 break;
437 case RTF_TRQL: eAdjust = text::HoriOrientation::LEFT; break;
438 case RTF_TRQR: eAdjust = text::HoriOrientation::RIGHT; break;
439 case RTF_TRQC: eAdjust = text::HoriOrientation::CENTER; break;
441 // mit text::VertOrientation::TOP kommt der Dialog nicht klar!
442 // Bug #65126#
443 case RTF_CLVERTALT: eVerOrient = text::VertOrientation::NONE; break;
445 case RTF_CLVERTALC: eVerOrient = text::VertOrientation::CENTER; break;
446 case RTF_CLVERTALB: eVerOrient = text::VertOrientation::BOTTOM; break;
448 case RTF_TRLEFT:
449 if( text::HoriOrientation::LEFT == eAdjust )
450 eAdjust = text::HoriOrientation::LEFT_AND_WIDTH;
451 nLSpace = nTokenValue;
452 nTblSz = nTokenValue;
453 break;
455 case RTF_TRHDR:
456 nRowsToRepeat++;
457 break;
459 case RTF_CLTXLRTB:
460 case RTF_CLTXTBRL:
461 case RTF_INTBL: // das wissen wir !
462 case RTF_CLMGF:
463 case RTF_CLVMGF:
464 case RTF_CLVMRG:
465 break;
466 case RTF_LTRROW:
467 eDir = FRMDIR_HORI_LEFT_TOP;
468 break;
469 case RTF_RTLROW:
470 eDir = FRMDIR_HORI_RIGHT_TOP;
471 break;
472 case RTF_TRBRDRB:
473 case RTF_TRBRDRH:
474 case RTF_TRBRDRL:
475 case RTF_TRBRDRR:
476 case RTF_TRBRDRT:
477 case RTF_TRBRDRV:
478 break;
479 case RTF_TRKEEP:
480 bCantSplit = true;
481 break;
483 default:
484 if( ( nToken & ~(0xff | RTF_TABLEDEF)) == RTF_SHADINGDEF )
486 if( aMergeBoxes[ nBoxCnt ] )
487 break;
488 ReadBackgroundAttr( nToken,
489 (SfxItemSet&)pBoxFmt->GetAttrSet(), TRUE );
491 else if( ( nToken & ~(0xff | RTF_TABLEDEF) ) == RTF_BRDRDEF ||
492 IsBorderToken(nToken))
494 if( aMergeBoxes[ nBoxCnt ] )
495 break;
497 SfxItemSet& rSet = (SfxItemSet&)pBoxFmt->GetAttrSet();
498 if(!IsBorderToken( nToken ))
499 ReadBorderAttr( nToken, rSet, TRUE );
500 else
501 NextToken( nToken );
503 else if( RTF_TABLEDEF != (nToken & ~(0xff | RTF_SWGDEFS)) )
505 if( RTF_UNKNOWNCONTROL == nToken )
506 NextToken( nToken );
507 else
508 bWeiter = FALSE;
510 break;
513 if( text::VertOrientation::NONE != eVerOrient )
515 if( !aMergeBoxes[ nBoxCnt ] )
516 pBoxFmt->SetFmtAttr( SwFmtVertOrient( 0, eVerOrient ));
517 eVerOrient = text::VertOrientation::NONE;
519 if( bWeiter )
520 nToken = GetNextToken();
521 } while( bWeiter && IsParserWorking() );
523 // das letzte temp. BoxFmt loeschen
524 delete pBoxFmt;
526 // es wurde keine einzige Box erkannt
527 if( nAktBox == nBoxCnt || ( bReadNewCell && !pTableNode ))
529 int nC = aMergeBackup.Count();
530 for (USHORT i = 0; i < nC; ++i)
531 aMergeBoxes.Insert(aMergeBackup[i], i);
532 SkipToken( -1 ); // zum Letzen gueltigen zurueck
533 return;
536 nTblSz -= nLSpace;
538 int bNewTbl = TRUE;
539 SwTableLine* pNewLine;
540 bTrowdRead=true;
542 // lege eine neue Tabelle an oder erweiter die aktuelle um eine neue Line
543 // oder Box !
544 SwNode* pNd;
546 if( bChkExistTbl )
548 // es ist eine Tabelle vorhanden, teste mal ob die weiter benutzt
549 // werden kann oder ob sie abgesplittet und neu gefuellt werden
550 // muss.
551 pTableNode = pPam->GetNode()->FindTableNode();
553 // Cursor kann nur in der letzten Line stehen
555 // das Attribut darf nicht ueber das Modify an der
556 // Tabelle gesetzt werden, denn sonst werden alle
557 // Boxen wieder auf 0 zurueck gesetzt !!!!!
558 SwFrmFmt* pFmt = pTableNode->GetTable().GetFrmFmt();
559 const SwFmtFrmSize& rTblSz = pFmt->GetFrmSize();
560 const SwFmtHoriOrient& rHoriz = pFmt->GetHoriOrient();
562 const SwTableLines* pLns = &pTableNode->GetTable().GetTabLines();
564 if( 1 == pLns->Count() )
566 if( eAdjust != rHoriz.GetHoriOrient() )
568 ((SfxItemSet&)pFmt->GetAttrSet()).Put( SwFmtHoriOrient( 0,
569 eAdjust ) );
571 if( rTblSz.GetWidth() != nTblSz )
573 SwFmtFrmSize aSz( rTblSz );
574 aSz.SetWidth( nTblSz );
575 ((SfxItemSet&)pFmt->GetAttrSet()).Put( aSz );
578 if( text::HoriOrientation::LEFT_AND_WIDTH == eAdjust &&
579 nLSpace != pFmt->GetLRSpace().GetLeft() )
581 SvxLRSpaceItem aL( RES_LR_SPACE ); aL.SetLeft( nLSpace );
582 ((SfxItemSet&)pFmt->GetAttrSet()).Put( aL );
585 else if
587 1 < pLns->Count() &&
589 rTblSz.GetWidth() != nTblSz ||
590 rHoriz.GetHoriOrient() != eAdjust ||
592 text::HoriOrientation::LEFT_AND_WIDTH == eAdjust &&
593 nLSpace != pFmt->GetLRSpace().GetLeft()
594 ) ||
595 pTableNode->GetTable().GetTabSortBoxes().Count() >= eMAXCELLS
599 // Tabelle ab der PaM-Position splitten
600 // die vorherige Line!
601 pNewLine = (*pLns)[ pLns->Count() - 2 ];
602 SwTableBox* pBox = pNewLine->GetTabBoxes()[ 0 ];
603 while( ( pLns = &pBox->GetTabLines() )->Count() )
604 pBox = (*pLns)[ 0 ]->GetTabBoxes()[ 0 ];
606 SwNodeIndex aTmpIdx( *pBox->GetSttNd() );
607 pDoc->GetNodes().SplitTable( aTmpIdx, HEADLINE_NONE, FALSE );
608 pTableNode = pPam->GetNode()->FindTableNode();
609 pFmt = pTableNode->GetTable().GetFrmFmt();
611 SwFmtFrmSize aSz( rTblSz );
612 aSz.SetWidth( nTblSz );
613 ((SfxItemSet&)pFmt->GetAttrSet()).Put( aSz );
614 ((SfxItemSet&)pFmt->GetAttrSet()).Put( SwFmtHoriOrient( 0,
615 eAdjust ) );
616 if( text::HoriOrientation::LEFT_AND_WIDTH == eAdjust && nLSpace )
618 SvxLRSpaceItem aL( RES_LR_SPACE ); aL.SetLeft( nLSpace );
619 ((SfxItemSet&)pFmt->GetAttrSet()).Put( aL );
623 pLns = &pTableNode->GetTable().GetTabLines();
624 pNewLine = (*pLns)[ pLns->Count() - 1 ];
626 // jetzt die Boxen abgleichen
627 USHORT nBoxes = Min( pNewLine->GetTabBoxes().Count(), aBoxFmts.Count() );
628 USHORT n;
630 for( n = 0; n < nBoxes; ++n )
632 SwTableBox* pBox = pNewLine->GetTabBoxes()[ n ];
633 *pBox->GetFrmFmt() = *aBoxFmts[ n ];
634 delete aBoxFmts[ n ];
636 aBoxFmts.Remove( 0, n );
638 if( aBoxFmts.Count() ) // es muessen noch neue zugefuegt werden
639 nAktBox = n;
640 else // es mussen noch Boxen geloescht werden
642 // remove ContentIndex of other Bound
643 pPam->SetMark(); pPam->DeleteMark();
644 while( n < pNewLine->GetTabBoxes().Count() )
645 _DeleteBox( pTableNode->GetTable(),
646 pNewLine->GetTabBoxes()[ n ], 0, FALSE, FALSE );
649 pOldTblNd = pTableNode;
650 bNewTbl = FALSE;
653 // JP 13.08.98: TabellenUmrandungen optimieren - Bug 53525
654 void* p = pFmt;
655 aTblFmts.Insert( p, aTblFmts.Count() );
658 else
660 if( !bReadNewCell && ( pNd = pDoc->GetNodes()[
661 pPam->GetPoint()->nNode.GetIndex()-1 ])->IsEndNode() )
663 pTableNode = pNd->StartOfSectionNode()->GetTableNode();
664 if( pTableNode )
666 // dann test mal ob wirklich nur eine neue Line eingefuegt
667 // werden soll!
668 SwTable &rTable = pTableNode->GetTable();
669 SwFrmFmt* pFmt = rTable.GetFrmFmt();
670 const SwFmtFrmSize& rTblSz = pFmt->GetFrmSize();
671 const SwFmtHoriOrient& rHoriz = pFmt->GetHoriOrient();
672 if (
673 rTblSz.GetWidth() != nTblSz ||
674 rHoriz.GetHoriOrient() != eAdjust ||
675 rTable.GetTabSortBoxes().Count() >= eMAXCELLS
678 pTableNode = 0;
683 if( pTableNode && !bForceNewTable)
686 // das Attribut darf nicht ueber das Modify an der
687 // Tabelle gesetzt werden, denn sonst werden alle
688 // Boxen wieder auf 0 zurueck gesetzt !!!!!
689 SwFrmFmt* pFmt = pTableNode->GetTable().GetFrmFmt();
690 const SwFmtFrmSize& rTblSz = pFmt->GetFrmSize();
691 if( rTblSz.GetWidth() < nTblSz )
693 SwFmtFrmSize aSz( rTblSz );
694 aSz.SetWidth( nTblSz );
695 ((SfxItemSet&)pFmt->GetAttrSet()).Put( aSz );
698 SwTableLines& rLns = pTableNode->GetTable().GetTabLines();
700 if( bReadNewCell )
701 pNewLine = rLns[ rLns.Count()-1 ];
702 else
704 pNewLine = new SwTableLine(
705 (SwTableLineFmt*)rLns[ rLns.Count()-1 ]->GetFrmFmt(),
706 aBoxFmts.Count(), 0 );
707 pNewLine->ClaimFrmFmt();
708 pNewLine->GetFrmFmt()->ResetFmtAttr( RES_FRM_SIZE );
709 rLns.C40_INSERT( SwTableLine, pNewLine, rLns.Count() );
711 bNewTbl = FALSE;
713 else
715 bForceNewTable = false;
716 const SwTable *pTable =
717 pDoc->InsertTable(
718 SwInsertTableOptions( tabopts::HEADLINE_NO_BORDER, 0 ),
719 *pPam->GetPoint(), 1, 1, eAdjust, 0, 0, FALSE, FALSE );
720 bContainsTablePara=true; //#117881#
721 pTableNode = pTable ? pTable->GetTableNode() : 0;
723 if (pTableNode)
725 maSegments.PrependedInlineNode(*pPam->GetPoint(),
726 *pTableNode);
728 else
730 SkipToken( -1 ); // zum Letzen gueltigen zurueck
731 return;
734 SwTableLines& rLns = pTableNode->GetTable().GetTabLines();
735 pNewLine = rLns[ rLns.Count()-1 ];
737 SwFrmFmt* pFmt = pTableNode->GetTable().GetFrmFmt();
738 SwFmtFrmSize aSz( pFmt->GetFrmSize() );
739 aSz.SetWidth( nTblSz );
740 ((SfxItemSet&)pFmt->GetAttrSet()).Put( aSz );
741 ((SfxItemSet&)pFmt->GetAttrSet()).Put(SvxFrameDirectionItem(eDir, RES_FRAMEDIR));
743 if( text::HoriOrientation::LEFT_AND_WIDTH == eAdjust && nLSpace )
745 SvxLRSpaceItem aL( RES_LR_SPACE ); aL.SetLeft( nLSpace );
746 ((SfxItemSet&)pFmt->GetAttrSet()).Put( aL );
749 nAktBox = 0;
750 pOldTblNd = pTableNode;
753 // JP 13.08.98: TabellenUmrandungen optimieren - Bug 53525
754 void* p = pFmt;
755 aTblFmts.Insert( p, aTblFmts.Count() );
760 if( nLineHeight )
762 SwFrmSize eSize;
763 if( 0 > nLineHeight )
764 eSize = ATT_FIX_SIZE, nLineHeight = -nLineHeight;
765 else
766 eSize = ATT_MIN_SIZE;
767 pNewLine->ClaimFrmFmt()->SetFmtAttr(SwFmtFrmSize(eSize, 0, nLineHeight));
770 pNewLine->ClaimFrmFmt()->SetFmtAttr(SwFmtRowSplit(!bCantSplit));
772 if( aBoxFmts.Count() )
774 // setze das default Style
775 SwTxtFmtColl* pColl = aTxtCollTbl.Get( 0 );
776 if( !pColl )
777 pColl = pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false );
779 USHORT nStt = 0;
780 if( bNewTbl )
782 SwTableBox* pBox = pNewLine->GetTabBoxes()[0];
783 pBoxFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
784 pBoxFmt->Remove( pBox );
785 delete pBoxFmt;
786 aBoxFmts[0]->Add( pBox );
787 SwTxtNode* pTNd = pDoc->GetNodes()[ pBox->GetSttIdx()+1 ]
788 ->GetTxtNode();
789 ASSERT( pTNd, "wo ist der Textnode dieser Box?" );
790 pTNd->ChgFmtColl( pColl );
791 ++nStt;
792 nRowsToRepeat=0;
795 for( ; nStt < aBoxFmts.Count(); ++nStt )
797 pDoc->GetNodes().InsBoxen( pTableNode, pNewLine,
798 aBoxFmts[ nStt ],
799 // Formate fuer den TextNode der Box
800 pColl, 0,
801 nAktBox + nStt, 1 );
805 if( bChkExistTbl )
806 nAktBox = 0;
808 maInsertedTables.InsertTable(*pTableNode, *pPam);
810 SwNodeIndex aOldIdx(pPam->GetPoint()->nNode);
811 SwNodeIdx aOldPos(aOldIdx);
812 SwPaM aRg(*pPam);
814 bool bFailure = true;
815 if (pNewLine)
817 SwTableBoxes &rBoxes = pNewLine->GetTabBoxes();
818 if (SwTableBox* pBox = (nAktBox < rBoxes.Count() ? rBoxes[nAktBox] : 0))
820 if (const SwStartNode *pStart = pBox->GetSttNd())
822 if (const SwEndNode *pEnd = pStart->EndOfSectionNode())
824 pPam->GetPoint()->nNode = *pEnd;
825 pPam->Move( fnMoveBackward, fnGoCntnt );
826 bFailure = false;
832 ASSERT(!bFailure, "RTF Table failure");
833 if (bFailure)
835 SkipToken( -1 ); // zum Letzen gueltigen zurueck
836 return;
839 //It might be that there was content at this point which is not already in
840 //a table, but which is being followed by properties to place it into the
841 //table. e.g. #109199#. If this is the case then move the para/char
842 //properties inside the table, and move any content of that paragraph into
843 //the table
844 bool bInTable = aRg.GetPoint()->nNode.GetNode().FindTableNode();
845 if (!bInTable)
847 SwNodeIndex aNewIdx(pPam->GetPoint()->nNode);
848 SwNodeIdx aNewPos(aNewIdx);
850 if (aRg.GetPoint()->nContent.GetIndex())
852 //If there is content in this node then move it entirely inside the
853 //table
854 aRg.SetMark();
855 aRg.GetMark()->nContent.Assign(aRg.GetCntntNode(), 0);
856 pDoc->MoveRange(aRg, *pPam->GetPoint(),
857 IDocumentContentOperations::DOC_MOVEDEFAULT);
860 //Update the attribute stack entries to reflect that the properties
861 //which were intended to be inside the tablerow are now left outside
862 //the table after the row was placed before the current insertion point
863 SvxRTFItemStack& rAttrStk = GetAttrStack();
864 for (USHORT n = 0; n < rAttrStk.Count(); ++n)
866 SvxRTFItemStackType* pStk = rAttrStk[n];
867 pStk->MoveFullNode(aOldPos, aNewPos);
870 SkipToken( -1 ); // zum Letzen gueltigen zurueck
873 // in die naechste Box dieser Line (opt.: falls es nicht die letzte ist)
874 void SwRTFParser::GotoNextBox()
876 nInsTblRow = USHRT_MAX;
878 ASSERT( pTableNode, "Kein Tabellennode, dann auch keine Box" );
880 if (!pTableNode)
881 return;
883 SwTableLines& rLns = pTableNode->GetTable().GetTabLines();
884 SwTableLine* pLine = rLns[ rLns.Count()-1 ];
885 SwTableBoxes& rBoxes = pLine->GetTabBoxes();
886 SwTableBox* pBox = rBoxes[ rBoxes.Count()-1 ];
888 if( ++nAktBox >= aMergeBoxes.Count() )
889 nAktBox = aMergeBoxes.Count()-1;
891 if( !aMergeBoxes[ nAktBox ] )
893 int bMove = TRUE;
894 if( pBox->GetSttIdx() > pPam->GetPoint()->nNode.GetIndex() )
896 USHORT nRealBox = 0;
897 for( USHORT nTmp = 0; nTmp < nAktBox; ++nTmp )
898 if( !aMergeBoxes[ nTmp ] )
899 ++nRealBox;
901 if( nRealBox < rBoxes.Count() )
903 pPam->GetPoint()->nNode = *rBoxes[ nRealBox ]->GetSttNd()->EndOfSectionNode();
904 pPam->Move( fnMoveBackward, fnGoCntnt );
905 bMove = FALSE;
909 if( bMove && nAktBox + 1 == aMergeBoxes.Count() )
910 // dann hinter die Tabelle
911 pPam->Move( fnMoveForward, fnGoNode );
913 else if( !pDoc->GetNodes()[ pPam->GetPoint()->nNode ]->IsCntntNode() )
914 // dann in die vorherige ans Ende
915 pPam->Move( fnMoveBackward, fnGoCntnt );
919 void SwRTFParser::NewTblLine()
921 nInsTblRow = USHRT_MAX;
923 // erweiter die aktuelle um eine neue Line
924 BOOL bMakeCopy = FALSE;
925 SwNode* pNd = pDoc->GetNodes()[ pPam->GetPoint()->nNode.GetIndex()-1 ];
926 if( !pNd->IsEndNode() ||
927 !(pNd = pNd->StartOfSectionNode())->IsTableNode() )
929 if( !pOldTblNd )
930 return ;
932 bMakeCopy = TRUE;
933 pNd = pOldTblNd;
935 pTableNode = (SwTableNode*)pNd;
937 SwTableLines* pLns = &pTableNode->GetTable().GetTabLines();
938 SwTableLine* pLine = (*pLns)[ pLns->Count()-1 ];
939 SwTableBoxes& rBoxes = pLine->GetTabBoxes();
940 SwTableBox* pBox = rBoxes[ rBoxes.Count()-1 ];
942 if(nRowsToRepeat>0)
943 pTableNode->GetTable().SetRowsToRepeat( nRowsToRepeat );
945 if( !bMakeCopy &&
946 64000 < pTableNode->GetTable().GetTabSortBoxes().Count() )
948 bMakeCopy = TRUE; // spaetestens jetzt eine neue anfangen!
951 if( bMakeCopy )
953 // und die Selektion kopieren
954 SwSelBoxes aBoxes;
955 pTableNode->GetTable().SelLineFromBox( pBox, aBoxes );
956 pTableNode->GetTable().MakeCopy( pDoc, *pPam->GetPoint(),
957 aBoxes, FALSE );
958 ULONG nNd = pPam->GetPoint()->nNode.GetIndex()-1;
959 pTableNode = pDoc->GetNodes()[ nNd ]->FindTableNode();
960 pOldTblNd = pTableNode;
962 nRowsToRepeat=0;
963 pTableNode->GetTable().SetRowsToRepeat(nRowsToRepeat);
964 pLns = &pTableNode->GetTable().GetTabLines();
966 else
967 // pDoc->InsertRow( aBoxes );
968 pTableNode->GetTable().AppendRow( pDoc );
970 pBox = (*pLns)[ pLns->Count()-1 ]->GetTabBoxes()[0];
972 ULONG nOldPos = pPam->GetPoint()->nNode.GetIndex();
973 pPam->GetPoint()->nNode = *pBox->GetSttNd();
974 pPam->Move( fnMoveForward );
975 nAktBox = 0;
977 // alle Nodes in den Boxen auf die "default" Vorlage setzten
979 SwTxtFmtColl* pColl = aTxtCollTbl.Get( 0 );
980 if( !pColl )
981 pColl = pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false );
982 pPam->SetMark();
984 pLine = (*pLns)[ pLns->Count()-1 ];
985 pBox = pLine->GetTabBoxes()[ pLine->GetTabBoxes().Count() -1 ];
986 pPam->GetPoint()->nNode = *pBox->GetSttNd()->EndOfSectionNode();
987 pPam->Move( fnMoveBackward );
988 pDoc->SetTxtFmtColl( *pPam, pColl );
989 // Bug 73940 - remove ALL attributes (NumRules/Break/etc.)
991 SwNodeIndex aIdx( pPam->GetMark()->nNode );
992 SwNodeIndex& rEndIdx = pPam->GetPoint()->nNode;
993 while( aIdx <= rEndIdx )
995 SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
996 if( pCNd && pCNd->HasSwAttrSet() )
997 pCNd->ResetAllAttr();
998 aIdx++;
1001 pPam->Exchange();
1002 pPam->DeleteMark();
1005 // alle Attribute, die schon auf den nachfolgen zeigen auf die neue
1006 // Box umsetzen !!
1007 SvxRTFItemStack& rAttrStk = GetAttrStack();
1008 const SvxRTFItemStackType* pStk;
1009 for( USHORT n = 0; n < rAttrStk.Count(); ++n )
1010 if( ( pStk = rAttrStk[ n ])->GetSttNodeIdx() == ULONG(nOldPos) &&
1011 !pStk->GetSttCnt() )
1012 ((SvxRTFItemStackType*)pStk)->SetStartPos( SwxPosition( pPam ) );
1015 void SwRTFParser::CheckInsNewTblLine()
1017 if( USHRT_MAX != nInsTblRow )
1019 if( nInsTblRow > GetOpenBrakets() || IsPardTokenRead() )
1020 nInsTblRow = USHRT_MAX;
1021 else if( !pTableNode ) // Tabelle nicht mehr vorhanden ?
1022 NewTblLine(); // evt. Line copieren
1026 /* vi:set tabstop=4 shiftwidth=4 expandtab: */