merge the formfield patch from ooo-build
[ooovba.git] / sw / source / filter / rtf / rtftbl.cxx
blobc3a56f64e3326a58d53b16c46c39b02b765429bb
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: rtftbl.cxx,v $
10 * $Revision: 1.40 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
35 #ifdef WTC
36 #define private public
37 #endif
38 #include <hintids.hxx>
39 #include <svx/lrspitem.hxx>
40 #include <svx/boxitem.hxx>
41 #include <svx/frmdiritem.hxx>
42 #include <svtools/rtftoken.h>
43 #include <fmtfsize.hxx>
44 #include <fmtpdsc.hxx>
45 #include <ndtxt.hxx>
46 #include <doc.hxx>
47 #include <pam.hxx>
48 #include <swparrtf.hxx>
49 #include <swtable.hxx>
50 #include <tblsel.hxx>
51 #include <swtblfmt.hxx>
52 #include <wrtswtbl.hxx>
53 #include <tblenum.hxx>
54 #include <frmatr.hxx>
55 #include <fmtrowsplt.hxx>
57 using namespace ::com::sun::star;
59 typedef SwTableBoxFmt* SwTableBoxFmtPtr;
60 SV_DECL_PTRARR( SwBoxFrmFmts, SwTableBoxFmtPtr, 25, 50 )
62 class SwShareBoxFmts;
63 extern void _DeleteBox( SwTable& rTbl, SwTableBox* pBox, SwUndo* = 0,
64 BOOL = TRUE, const BOOL = TRUE, SwShareBoxFmts* = 0 );
66 struct Row
68 bool mbUseLeftRowPad, mbUseRightRowPad, mbUseTopRowPad, mbUseBottomRowPad;
69 long mnLeftRowPad, mnRightRowPad, mnTopRowPad, mnBottomRowPad;
70 USHORT mnBrdDist;
71 Row() :
72 mbUseLeftRowPad(false), mbUseRightRowPad(false),
73 mbUseTopRowPad(false), mbUseBottomRowPad(false),
74 mnLeftRowPad(0), mnRightRowPad(0), mnTopRowPad(0), mnBottomRowPad(0),
75 mnBrdDist(MIN_BORDER_DIST)
79 static void SetRowBorder(SfxItemSet& rSet, const Row &rRow)
81 #if 1
82 SvxBoxItem aBox((const SvxBoxItem&)rSet.Get(RES_BOX, false));
83 aBox.SetDistance( static_cast< USHORT >(rRow.mbUseLeftRowPad ? rRow.mnLeftRowPad : rRow.mnBrdDist),
84 BOX_LINE_LEFT);
86 aBox.SetDistance( static_cast< USHORT >(rRow.mbUseRightRowPad ? rRow.mnRightRowPad : rRow.mnBrdDist),
87 BOX_LINE_RIGHT);
89 aBox.SetDistance( static_cast< USHORT >(rRow.mbUseTopRowPad ? rRow.mnTopRowPad : 0),
90 BOX_LINE_TOP);
92 aBox.SetDistance( static_cast< USHORT >(rRow.mbUseBottomRowPad ? rRow.mnBottomRowPad : 0),
93 BOX_LINE_BOTTOM);
95 rSet.Put(aBox);
96 #else
97 const SfxPoolItem* pItem;
98 if (SFX_ITEM_SET == rSet.GetItemState(RES_BOX, FALSE, &pItem))
100 SvxBoxItem aBox( *(SvxBoxItem*)pItem );
101 aBox.SetDistance(rRow.mbUseLeftRowPad ? rRow.mnLeftRowPad : rRow.mnBrdDist,
102 BOX_LINE_LEFT);
104 aBox.SetDistance(rRow.mbUseRightRowPad ? rRow.mnRightRowPad : rRow.mnBrdDist,
105 BOX_LINE_RIGHT);
107 aBox.SetDistance(rRow.mbUseTopRowPad ? rRow.mnTopRowPad : 0,
108 BOX_LINE_TOP);
110 aBox.SetDistance(rRow.mbUseBottomRowPad ? rRow.mnBottomRowPad : 0,
111 BOX_LINE_BOTTOM);
113 rSet.Put(aBox);
115 #endif
118 void rtfSections::PrependedInlineNode(const SwPosition &rPos,
119 const SwNode &rNode)
121 ASSERT(!mrReader.IsNewDoc() || !maSegments.empty(),
122 "should not be possible, must be at least one segment in a new document");
123 if ((!maSegments.empty()) && (maSegments.back().maStart == rPos.nNode))
124 maSegments.back().maStart = SwNodeIndex(rNode);
127 bool SwRTFParser::IsBorderToken(int nToken)
130 i30222 i28983
131 Our ability to sense border tokens is broken rtftoken.h is
132 organised in a way that ignores some border tokens. ReadBorderAttr
133 still doesn't support the more exotic borders but at least this
134 won't cause the parser to prematuerely exit the table
136 bool bResult = false;
138 bResult = (nToken >= RTF_BRDRDASHD && nToken <= RTF_BRDRTHTNMG) ||
139 (nToken >= RTF_BRDRTNTHSG && nToken <= RTF_BRDRWAVY);
141 return bResult;
144 void SwRTFParser::ReadTable( int nToken )
146 nInsTblRow = USHRT_MAX;
148 if (CantUseTables())
150 // alle Tabellen-Tokens ueberlesen
151 nToken = GetNextToken(); // RTF_TROWD ueberlesen
152 do {
153 if( RTF_TABLEDEF != (nToken & ~(0xff | RTF_SWGDEFS)) &&
154 RTF_UNKNOWNCONTROL != nToken )
156 SkipToken( -1 );
157 break;
159 nToken = GetNextToken();
160 } while( IsParserWorking() );
161 return ;
164 // verhinder Tabelle in Tabelle/Footnote
165 SwTwips nTblSz = 0;
166 int bReadNewCell = FALSE, bChkExistTbl = FALSE;
169 enum Limits {eMAXCELLS=64000};
171 SvBools aMergeBackup;
172 int nCount = aMergeBoxes.Count();
173 for (USHORT i = 0; i < nCount; ++i)
174 aMergeBackup.Insert(aMergeBoxes[i], i);
176 // kein TROWD aber ein TabellenToken -> zwischen TROWD und Tab.Token
177 // waren andere Zeichen (siehe Bug 27445.rtf)
178 if( RTF_TROWD == nToken || !pTableNode )
180 if( RTF_TROWD == nToken )
181 nToken = GetNextToken(); // RTF_TROWD ueberlesen
183 // Flags fuer die gemergten Boxen loeschen
184 aMergeBoxes.Remove( 0, aMergeBoxes.Count() );
185 aMergeBoxes.Insert( (BOOL)FALSE, USHORT(0) );
186 nAktBox = 0;
188 // wenn schon in einer Tabellen, dann splitte oder benutze
189 // die bisherigen Boxen weiter
190 bChkExistTbl = 0 != pDoc->GetNodes()[ pPam->GetPoint()->nNode ]->FindTableNode();
192 else
194 bReadNewCell = TRUE;
195 SwTableLines& rLns = pTableNode->GetTable().GetTabLines();
196 SwTableLine* pLine = rLns[ rLns.Count()-1 ];
197 // very robust to avoid crashes like bug 127425 + crash reports 118743
198 if( pLine )
200 USHORT nTmpBox = nAktBox;
201 if( nTmpBox > pLine->GetTabBoxes().Count() )
202 nTmpBox = pLine->GetTabBoxes().Count();
204 for( USHORT n = nTmpBox; n; )
206 const SwTableBox *pTmp = pLine->GetTabBoxes()[ --n ];
207 if( pTmp )
209 const SwFrmFmt* pTmpFmt = pTmp->GetFrmFmt();
210 if( pTmpFmt )
211 nTblSz += pTmpFmt->GetFrmSize().GetWidth();
218 sal_Int16 eAdjust = text::HoriOrientation::LEFT; // default fuer Tabellen
219 SwTwips nLSpace = 0;
220 Row aRow;
222 bool bUseLeftCellPad = false, bUseRightCellPad = false,
223 bUseTopCellPad = false, bUseBottomCellPad = false;
224 long nLeftCellPad = 0, nRightCellPad = 0, nTopCellPad = 0,
225 nBottomCellPad = 0;
227 sal_Int16 eVerOrient = text::VertOrientation::NONE;
228 long nLineHeight = 0;
229 USHORT nBoxCnt = aMergeBoxes.Count()-1;
230 SwBoxFrmFmts aBoxFmts;
231 SwTableBoxFmt* pBoxFmt = pDoc->MakeTableBoxFmt();
232 SvxFrameDirection eDir = FRMDIR_HORI_LEFT_TOP;
233 bool bCantSplit = false;
235 int bWeiter = TRUE;
236 do {
237 switch( nToken )
239 case RTF_TRPADDFL:
240 aRow.mbUseLeftRowPad = (nTokenValue == 3) ? true : false;
241 break;
242 case RTF_TRPADDFT:
243 aRow.mbUseTopRowPad = (nTokenValue == 3) ? true : false;
244 break;
245 case RTF_TRPADDFR:
246 aRow.mbUseRightRowPad = (nTokenValue == 3) ? true : false;
247 break;
248 case RTF_TRPADDFB:
249 aRow.mbUseBottomRowPad = (nTokenValue == 3) ? true : false;
250 break;
251 case RTF_TRPADDL:
252 aRow.mnLeftRowPad = nTokenValue;
253 break;
254 case RTF_TRPADDT:
255 aRow.mnTopRowPad = nTokenValue;
256 break;
257 case RTF_TRPADDR:
258 aRow.mnRightRowPad = nTokenValue;
259 break;
260 case RTF_TRPADDB:
261 aRow.mnBottomRowPad = nTokenValue;
262 break;
264 case RTF_CLPADFL:
265 bUseLeftCellPad = (nTokenValue == 3) ? true : false;
266 break;
267 case RTF_CLPADFT:
268 bUseTopCellPad = (nTokenValue == 3) ? true : false;
269 break;
270 case RTF_CLPADFR:
271 bUseRightCellPad = (nTokenValue == 3) ? true : false;
272 break;
273 case RTF_CLPADFB:
274 bUseBottomCellPad = (nTokenValue == 3) ? true : false;
275 break;
276 case RTF_CLPADL:
277 nLeftCellPad = nTokenValue;
278 break;
279 case RTF_CLPADT:
280 nTopCellPad = nTokenValue;
281 break;
282 case RTF_CLPADR:
283 nRightCellPad = nTokenValue;
284 break;
285 case RTF_CLPADB:
286 nBottomCellPad = nTokenValue;
287 break;
289 case RTF_TRRH:
290 nLineHeight = nTokenValue;
291 break;
293 case RTF_CLMRG:
294 aMergeBoxes[ nBoxCnt ] = TRUE;
295 break;
297 case RTF_CELLX:
298 if (!bTrowdRead) {
299 SwTableBoxFmt* pFmt = pBoxFmt;
300 SwTwips nSize = nTokenValue - nTblSz;
301 if( aMergeBoxes[ nBoxCnt ] )
303 // neue Zellen lesen und noch keine Formate vorhanden,
304 // dann benutze das der vorhergebende
305 if( bReadNewCell && !aBoxFmts.Count() )
307 SwTableLines& rLns = pTableNode->GetTable().GetTabLines();
308 SwTableLine* pLine = rLns[ rLns.Count()-1 ];
309 if(nAktBox!=0)
310 --nAktBox;
311 pFmt = (SwTableBoxFmt*)pLine->GetTabBoxes()[ nAktBox ]->GetFrmFmt();
313 else
314 pFmt = aBoxFmts[ aBoxFmts.Count()-1 ];
316 // --> OD 2007-01-25 #i73790# - method renamed
317 pBoxFmt->ResetAllFmtAttr();
318 // <--
319 nSize += pFmt->GetFrmSize().GetWidth();
321 else
324 if (nSize<=2*aRow.mnBrdDist) {
325 aRow.mnRightRowPad=0;
326 aRow.mbUseRightRowPad=TRUE;
328 SetRowBorder((SfxItemSet&)pBoxFmt->GetAttrSet(), aRow);
329 aBoxFmts.Insert( pBoxFmt, aBoxFmts.Count() );
330 pBoxFmt = pDoc->MakeTableBoxFmt();
333 if( !nSize )
334 nSize = COL_DFLT_WIDTH;
335 pFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nSize, 0 ));
336 nTblSz = nTokenValue;
337 aMergeBoxes.Insert( (BOOL)FALSE, ++nBoxCnt );
339 SvxBoxItem aBox(pFmt->GetBox());
341 if (bUseRightCellPad)
342 aBox.SetDistance( static_cast< USHORT >(nRightCellPad), BOX_LINE_RIGHT);
343 if (bUseBottomCellPad)
344 aBox.SetDistance( static_cast< USHORT >(nBottomCellPad), BOX_LINE_BOTTOM);
346 //Yes, these are the wrong way around, there appears to
347 //be a bug in word where these are swapped.
348 if (bUseLeftCellPad)
349 aBox.SetDistance( static_cast< USHORT >(nLeftCellPad), BOX_LINE_TOP);
350 if (bUseTopCellPad)
351 aBox.SetDistance( static_cast< USHORT >(nTopCellPad), BOX_LINE_LEFT);
354 /*#106415# The Cell Borders are now balanced on import to
355 improve the layout of tables.
358 if ( aBoxFmts.Count()>1)
361 SwTableBoxFmt* prevpFmt = aBoxFmts[ aBoxFmts.Count()-2 ];
362 SvxBoxItem prevaBox(prevpFmt->GetBox());
363 USHORT prevWidthRight=0;
364 USHORT currWidthLeft=0;
365 bool bDoubleLine=false;
366 const SvxBorderLine* brdrline ;
367 const Color* pPrevRightColor;
368 if(prevaBox.GetRight())
370 brdrline=prevaBox.GetRight();
371 prevWidthRight = brdrline->GetOutWidth();
372 pPrevRightColor = &brdrline->GetColor();
373 if(brdrline->GetInWidth())
374 bDoubleLine=true;
376 if(aBox.GetLeft())
378 brdrline=aBox.GetLeft();
379 currWidthLeft = brdrline->GetOutWidth();
380 if(brdrline->GetInWidth())
381 bDoubleLine=true;
384 if((currWidthLeft >0 || prevWidthRight >0) &&
385 !bDoubleLine)
387 USHORT newBorderWidth=(currWidthLeft+prevWidthRight)/2 ;
388 if(newBorderWidth /2 ==DEF_LINE_WIDTH_0 )
390 newBorderWidth =DEF_LINE_WIDTH_0;
392 else if(newBorderWidth /2 >=(DEF_LINE_WIDTH_4-DEF_LINE_WIDTH_3))
394 newBorderWidth =DEF_LINE_WIDTH_4;
396 else if(newBorderWidth /2 >=(DEF_LINE_WIDTH_3-DEF_LINE_WIDTH_2))
398 newBorderWidth =DEF_LINE_WIDTH_3;
400 else if(newBorderWidth /2>=(DEF_LINE_WIDTH_2-DEF_LINE_WIDTH_1))
402 newBorderWidth =DEF_LINE_WIDTH_2;
404 else if(newBorderWidth /2>=(DEF_LINE_WIDTH_1 - DEF_LINE_WIDTH_0) )
406 newBorderWidth =DEF_LINE_WIDTH_1;
408 else
410 newBorderWidth =DEF_LINE_WIDTH_0;
412 const SvxBorderLine newbrdrline(pPrevRightColor, newBorderWidth,0,0);
413 aBox.SetLine(&newbrdrline,BOX_LINE_LEFT);
414 prevaBox.SetLine(&newbrdrline,BOX_LINE_RIGHT);
415 prevpFmt->SetAttr(prevaBox);
421 pFmt->SetFmtAttr(aBox);
423 bUseLeftCellPad = false;
424 bUseRightCellPad = false;
425 bUseTopCellPad = false;
426 bUseBottomCellPad = false;
428 break;
430 case RTF_TRGAPH:
431 //$flr bug #117887#: RTF: wrong internal table cell margin imported (A13)
432 aRow.mnBrdDist = (nTokenValue>0?(USHORT)nTokenValue:0); // filter out negative values of \trgaph
433 break;
435 case RTF_TRQL: eAdjust = text::HoriOrientation::LEFT; break;
436 case RTF_TRQR: eAdjust = text::HoriOrientation::RIGHT; break;
437 case RTF_TRQC: eAdjust = text::HoriOrientation::CENTER; break;
439 // mit text::VertOrientation::TOP kommt der Dialog nicht klar!
440 // Bug #65126#
441 case RTF_CLVERTALT: eVerOrient = text::VertOrientation::NONE; break;
443 case RTF_CLVERTALC: eVerOrient = text::VertOrientation::CENTER; break;
444 case RTF_CLVERTALB: eVerOrient = text::VertOrientation::BOTTOM; break;
446 case RTF_TRLEFT:
447 if( text::HoriOrientation::LEFT == eAdjust )
448 eAdjust = text::HoriOrientation::LEFT_AND_WIDTH;
449 nLSpace = nTokenValue;
450 nTblSz = nTokenValue;
451 break;
453 case RTF_TRHDR:
454 nRowsToRepeat++;
455 break;
457 case RTF_CLTXLRTB:
458 case RTF_CLTXTBRL:
459 case RTF_INTBL: // das wissen wir !
460 case RTF_CLMGF:
461 case RTF_CLVMGF:
462 case RTF_CLVMRG:
463 break;
464 case RTF_LTRROW:
465 eDir = FRMDIR_HORI_LEFT_TOP;
466 break;
467 case RTF_RTLROW:
468 eDir = FRMDIR_HORI_RIGHT_TOP;
469 break;
470 case RTF_TRBRDRB:
471 case RTF_TRBRDRH:
472 case RTF_TRBRDRL:
473 case RTF_TRBRDRR:
474 case RTF_TRBRDRT:
475 case RTF_TRBRDRV:
476 break;
477 case RTF_TRKEEP:
478 bCantSplit = true;
479 break;
481 default:
482 if( ( nToken & ~(0xff | RTF_TABLEDEF)) == RTF_SHADINGDEF )
484 if( aMergeBoxes[ nBoxCnt ] )
485 break;
486 ReadBackgroundAttr( nToken,
487 (SfxItemSet&)pBoxFmt->GetAttrSet(), TRUE );
489 else if( ( nToken & ~(0xff | RTF_TABLEDEF) ) == RTF_BRDRDEF ||
490 IsBorderToken(nToken))
492 if( aMergeBoxes[ nBoxCnt ] )
493 break;
495 SfxItemSet& rSet = (SfxItemSet&)pBoxFmt->GetAttrSet();
496 if(!IsBorderToken( nToken ))
497 ReadBorderAttr( nToken, rSet, TRUE );
498 else
499 NextToken( nToken );
501 else if( RTF_TABLEDEF != (nToken & ~(0xff | RTF_SWGDEFS)) )
503 if( RTF_UNKNOWNCONTROL == nToken )
504 NextToken( nToken );
505 else
506 bWeiter = FALSE;
508 break;
511 if( text::VertOrientation::NONE != eVerOrient )
513 if( !aMergeBoxes[ nBoxCnt ] )
514 pBoxFmt->SetFmtAttr( SwFmtVertOrient( 0, eVerOrient ));
515 eVerOrient = text::VertOrientation::NONE;
517 if( bWeiter )
518 nToken = GetNextToken();
519 } while( bWeiter && IsParserWorking() );
521 // das letzte temp. BoxFmt loeschen
522 delete pBoxFmt;
524 // es wurde keine einzige Box erkannt
525 if( nAktBox == nBoxCnt || ( bReadNewCell && !pTableNode ))
527 int nC = aMergeBackup.Count();
528 for (USHORT i = 0; i < nC; ++i)
529 aMergeBoxes.Insert(aMergeBackup[i], i);
530 SkipToken( -1 ); // zum Letzen gueltigen zurueck
531 return;
534 nTblSz -= nLSpace;
536 int bNewTbl = TRUE;
537 SwTableLine* pNewLine;
538 bTrowdRead=true;
540 // lege eine neue Tabelle an oder erweiter die aktuelle um eine neue Line
541 // oder Box !
542 SwNode* pNd;
544 if( bChkExistTbl )
546 // es ist eine Tabelle vorhanden, teste mal ob die weiter benutzt
547 // werden kann oder ob sie abgesplittet und neu gefuellt werden
548 // muss.
549 pTableNode = pPam->GetNode()->FindTableNode();
551 // Cursor kann nur in der letzten Line stehen
553 // das Attribut darf nicht ueber das Modify an der
554 // Tabelle gesetzt werden, denn sonst werden alle
555 // Boxen wieder auf 0 zurueck gesetzt !!!!!
556 SwFrmFmt* pFmt = pTableNode->GetTable().GetFrmFmt();
557 const SwFmtFrmSize& rTblSz = pFmt->GetFrmSize();
558 const SwFmtHoriOrient& rHoriz = pFmt->GetHoriOrient();
560 const SwTableLines* pLns = &pTableNode->GetTable().GetTabLines();
562 if( 1 == pLns->Count() )
564 if( eAdjust != rHoriz.GetHoriOrient() )
566 ((SfxItemSet&)pFmt->GetAttrSet()).Put( SwFmtHoriOrient( 0,
567 eAdjust ) );
569 if( rTblSz.GetWidth() != nTblSz )
571 SwFmtFrmSize aSz( rTblSz );
572 aSz.SetWidth( nTblSz );
573 ((SfxItemSet&)pFmt->GetAttrSet()).Put( aSz );
576 if( text::HoriOrientation::LEFT_AND_WIDTH == eAdjust &&
577 nLSpace != pFmt->GetLRSpace().GetLeft() )
579 SvxLRSpaceItem aL( RES_LR_SPACE ); aL.SetLeft( nLSpace );
580 ((SfxItemSet&)pFmt->GetAttrSet()).Put( aL );
583 else if
585 1 < pLns->Count() &&
587 rTblSz.GetWidth() != nTblSz ||
588 rHoriz.GetHoriOrient() != eAdjust ||
590 text::HoriOrientation::LEFT_AND_WIDTH == eAdjust &&
591 nLSpace != pFmt->GetLRSpace().GetLeft()
592 ) ||
593 pTableNode->GetTable().GetTabSortBoxes().Count() >= eMAXCELLS
597 // Tabelle ab der PaM-Position splitten
598 // die vorherige Line!
599 pNewLine = (*pLns)[ pLns->Count() - 2 ];
600 SwTableBox* pBox = pNewLine->GetTabBoxes()[ 0 ];
601 while( ( pLns = &pBox->GetTabLines() )->Count() )
602 pBox = (*pLns)[ 0 ]->GetTabBoxes()[ 0 ];
604 SwNodeIndex aTmpIdx( *pBox->GetSttNd() );
605 pDoc->GetNodes().SplitTable( aTmpIdx, HEADLINE_NONE, FALSE );
606 pTableNode = pPam->GetNode()->FindTableNode();
607 pFmt = pTableNode->GetTable().GetFrmFmt();
609 SwFmtFrmSize aSz( rTblSz );
610 aSz.SetWidth( nTblSz );
611 ((SfxItemSet&)pFmt->GetAttrSet()).Put( aSz );
612 ((SfxItemSet&)pFmt->GetAttrSet()).Put( SwFmtHoriOrient( 0,
613 eAdjust ) );
614 if( text::HoriOrientation::LEFT_AND_WIDTH == eAdjust && nLSpace )
616 SvxLRSpaceItem aL( RES_LR_SPACE ); aL.SetLeft( nLSpace );
617 ((SfxItemSet&)pFmt->GetAttrSet()).Put( aL );
621 pLns = &pTableNode->GetTable().GetTabLines();
622 pNewLine = (*pLns)[ pLns->Count() - 1 ];
624 // jetzt die Boxen abgleichen
625 USHORT nBoxes = Min( pNewLine->GetTabBoxes().Count(), aBoxFmts.Count() );
626 USHORT n;
628 for( n = 0; n < nBoxes; ++n )
630 SwTableBox* pBox = pNewLine->GetTabBoxes()[ n ];
631 *pBox->GetFrmFmt() = *aBoxFmts[ n ];
632 delete aBoxFmts[ n ];
634 aBoxFmts.Remove( 0, n );
636 if( aBoxFmts.Count() ) // es muessen noch neue zugefuegt werden
637 nAktBox = n;
638 else // es mussen noch Boxen geloescht werden
640 // remove ContentIndex of other Bound
641 pPam->SetMark(); pPam->DeleteMark();
642 while( n < pNewLine->GetTabBoxes().Count() )
643 _DeleteBox( pTableNode->GetTable(),
644 pNewLine->GetTabBoxes()[ n ], 0, FALSE, FALSE );
647 pOldTblNd = pTableNode;
648 bNewTbl = FALSE;
651 // JP 13.08.98: TabellenUmrandungen optimieren - Bug 53525
652 void* p = pFmt;
653 aTblFmts.Insert( p, aTblFmts.Count() );
656 else
658 if( !bReadNewCell && ( pNd = pDoc->GetNodes()[
659 pPam->GetPoint()->nNode.GetIndex()-1 ])->IsEndNode() )
661 pTableNode = pNd->StartOfSectionNode()->GetTableNode();
662 if( pTableNode )
664 // dann test mal ob wirklich nur eine neue Line eingefuegt
665 // werden soll!
666 SwTable &rTable = pTableNode->GetTable();
667 SwFrmFmt* pFmt = rTable.GetFrmFmt();
668 const SwFmtFrmSize& rTblSz = pFmt->GetFrmSize();
669 const SwFmtHoriOrient& rHoriz = pFmt->GetHoriOrient();
670 if (
671 rTblSz.GetWidth() != nTblSz ||
672 rHoriz.GetHoriOrient() != eAdjust ||
673 rTable.GetTabSortBoxes().Count() >= eMAXCELLS
676 pTableNode = 0;
681 if( pTableNode && !bForceNewTable)
684 // das Attribut darf nicht ueber das Modify an der
685 // Tabelle gesetzt werden, denn sonst werden alle
686 // Boxen wieder auf 0 zurueck gesetzt !!!!!
687 SwFrmFmt* pFmt = pTableNode->GetTable().GetFrmFmt();
688 const SwFmtFrmSize& rTblSz = pFmt->GetFrmSize();
689 if( rTblSz.GetWidth() < nTblSz )
691 SwFmtFrmSize aSz( rTblSz );
692 aSz.SetWidth( nTblSz );
693 ((SfxItemSet&)pFmt->GetAttrSet()).Put( aSz );
696 SwTableLines& rLns = pTableNode->GetTable().GetTabLines();
698 if( bReadNewCell )
699 pNewLine = rLns[ rLns.Count()-1 ];
700 else
702 pNewLine = new SwTableLine(
703 (SwTableLineFmt*)rLns[ rLns.Count()-1 ]->GetFrmFmt(),
704 aBoxFmts.Count(), 0 );
705 pNewLine->ClaimFrmFmt();
706 pNewLine->GetFrmFmt()->ResetFmtAttr( RES_FRM_SIZE );
707 rLns.C40_INSERT( SwTableLine, pNewLine, rLns.Count() );
709 bNewTbl = FALSE;
711 else
713 bForceNewTable = false;
714 const SwTable *pTable =
715 pDoc->InsertTable(
716 SwInsertTableOptions( tabopts::HEADLINE_NO_BORDER, 0 ),
717 *pPam->GetPoint(), 1, 1, eAdjust, 0, 0, FALSE, FALSE );
718 bContainsTablePara=true; //#117881#
719 pTableNode = pTable ? pTable->GetTableNode() : 0;
721 if (pTableNode)
723 maSegments.PrependedInlineNode(*pPam->GetPoint(),
724 *pTableNode);
726 else
728 SkipToken( -1 ); // zum Letzen gueltigen zurueck
729 return;
732 SwTableLines& rLns = pTableNode->GetTable().GetTabLines();
733 pNewLine = rLns[ rLns.Count()-1 ];
735 SwFrmFmt* pFmt = pTableNode->GetTable().GetFrmFmt();
736 SwFmtFrmSize aSz( pFmt->GetFrmSize() );
737 aSz.SetWidth( nTblSz );
738 ((SfxItemSet&)pFmt->GetAttrSet()).Put( aSz );
739 ((SfxItemSet&)pFmt->GetAttrSet()).Put(SvxFrameDirectionItem(eDir, RES_FRAMEDIR));
741 if( text::HoriOrientation::LEFT_AND_WIDTH == eAdjust && nLSpace )
743 SvxLRSpaceItem aL( RES_LR_SPACE ); aL.SetLeft( nLSpace );
744 ((SfxItemSet&)pFmt->GetAttrSet()).Put( aL );
747 nAktBox = 0;
748 pOldTblNd = pTableNode;
751 // JP 13.08.98: TabellenUmrandungen optimieren - Bug 53525
752 void* p = pFmt;
753 aTblFmts.Insert( p, aTblFmts.Count() );
758 if( nLineHeight )
760 SwFrmSize eSize;
761 if( 0 > nLineHeight )
762 eSize = ATT_FIX_SIZE, nLineHeight = -nLineHeight;
763 else
764 eSize = ATT_MIN_SIZE;
765 pNewLine->ClaimFrmFmt()->SetFmtAttr(SwFmtFrmSize(eSize, 0, nLineHeight));
768 pNewLine->ClaimFrmFmt()->SetFmtAttr(SwFmtRowSplit(!bCantSplit));
770 if( aBoxFmts.Count() )
772 // setze das default Style
773 SwTxtFmtColl* pColl = aTxtCollTbl.Get( 0 );
774 if( !pColl )
775 pColl = pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false );
777 USHORT nStt = 0;
778 if( bNewTbl )
780 SwTableBox* pBox = pNewLine->GetTabBoxes()[0];
781 pBoxFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
782 pBoxFmt->Remove( pBox );
783 delete pBoxFmt;
784 aBoxFmts[0]->Add( pBox );
785 SwTxtNode* pTNd = pDoc->GetNodes()[ pBox->GetSttIdx()+1 ]
786 ->GetTxtNode();
787 ASSERT( pTNd, "wo ist der Textnode dieser Box?" );
788 pTNd->ChgFmtColl( pColl );
789 ++nStt;
790 nRowsToRepeat=0;
793 for( ; nStt < aBoxFmts.Count(); ++nStt )
795 pDoc->GetNodes().InsBoxen( pTableNode, pNewLine,
796 aBoxFmts[ nStt ],
797 // Formate fuer den TextNode der Box
798 pColl, 0,
799 nAktBox + nStt, 1 );
803 if( bChkExistTbl )
804 nAktBox = 0;
806 maInsertedTables.InsertTable(*pTableNode, *pPam);
808 SwNodeIndex aOldIdx(pPam->GetPoint()->nNode);
809 SwNodeIdx aOldPos(aOldIdx);
810 SwPaM aRg(*pPam);
812 bool bFailure = true;
813 if (pNewLine)
815 SwTableBoxes &rBoxes = pNewLine->GetTabBoxes();
816 if (SwTableBox* pBox = (nAktBox < rBoxes.Count() ? rBoxes[nAktBox] : 0))
818 if (const SwStartNode *pStart = pBox->GetSttNd())
820 if (const SwEndNode *pEnd = pStart->EndOfSectionNode())
822 pPam->GetPoint()->nNode = *pEnd;
823 pPam->Move( fnMoveBackward, fnGoCntnt );
824 bFailure = false;
830 ASSERT(!bFailure, "RTF Table failure");
831 if (bFailure)
833 SkipToken( -1 ); // zum Letzen gueltigen zurueck
834 return;
837 //It might be that there was content at this point which is not already in
838 //a table, but which is being followed by properties to place it into the
839 //table. e.g. #109199#. If this is the case then move the para/char
840 //properties inside the table, and move any content of that paragraph into
841 //the table
842 bool bInTable = aRg.GetPoint()->nNode.GetNode().FindTableNode();
843 if (!bInTable)
845 SwNodeIndex aNewIdx(pPam->GetPoint()->nNode);
846 SwNodeIdx aNewPos(aNewIdx);
848 if (aRg.GetPoint()->nContent.GetIndex())
850 //If there is content in this node then move it entirely inside the
851 //table
852 aRg.SetMark();
853 aRg.GetMark()->nContent.Assign(aRg.GetCntntNode(), 0);
854 pDoc->MoveRange(aRg, *pPam->GetPoint(),
855 IDocumentContentOperations::DOC_MOVEDEFAULT);
858 //Update the attribute stack entries to reflect that the properties
859 //which were intended to be inside the tablerow are now left outside
860 //the table after the row was placed before the current insertion point
861 SvxRTFItemStack& rAttrStk = GetAttrStack();
862 for (USHORT n = 0; n < rAttrStk.Count(); ++n)
864 SvxRTFItemStackType* pStk = rAttrStk[n];
865 pStk->MoveFullNode(aOldPos, aNewPos);
868 SkipToken( -1 ); // zum Letzen gueltigen zurueck
871 // in die naechste Box dieser Line (opt.: falls es nicht die letzte ist)
872 void SwRTFParser::GotoNextBox()
874 nInsTblRow = USHRT_MAX;
876 ASSERT( pTableNode, "Kein Tabellennode, dann auch keine Box" );
878 if (!pTableNode)
879 return;
881 SwTableLines& rLns = pTableNode->GetTable().GetTabLines();
882 SwTableLine* pLine = rLns[ rLns.Count()-1 ];
883 SwTableBoxes& rBoxes = pLine->GetTabBoxes();
884 SwTableBox* pBox = rBoxes[ rBoxes.Count()-1 ];
886 if( ++nAktBox >= aMergeBoxes.Count() )
887 nAktBox = aMergeBoxes.Count()-1;
889 if( !aMergeBoxes[ nAktBox ] )
891 int bMove = TRUE;
892 if( pBox->GetSttIdx() > pPam->GetPoint()->nNode.GetIndex() )
894 USHORT nRealBox = 0;
895 for( USHORT nTmp = 0; nTmp < nAktBox; ++nTmp )
896 if( !aMergeBoxes[ nTmp ] )
897 ++nRealBox;
899 if( nRealBox < rBoxes.Count() )
901 pPam->GetPoint()->nNode = *rBoxes[ nRealBox ]->GetSttNd()->EndOfSectionNode();
902 pPam->Move( fnMoveBackward, fnGoCntnt );
903 bMove = FALSE;
907 if( bMove && nAktBox + 1 == aMergeBoxes.Count() )
908 // dann hinter die Tabelle
909 pPam->Move( fnMoveForward, fnGoNode );
911 else if( !pDoc->GetNodes()[ pPam->GetPoint()->nNode ]->IsCntntNode() )
912 // dann in die vorherige ans Ende
913 pPam->Move( fnMoveBackward, fnGoCntnt );
917 void SwRTFParser::NewTblLine()
919 nInsTblRow = USHRT_MAX;
921 // erweiter die aktuelle um eine neue Line
922 BOOL bMakeCopy = FALSE;
923 SwNode* pNd = pDoc->GetNodes()[ pPam->GetPoint()->nNode.GetIndex()-1 ];
924 if( !pNd->IsEndNode() ||
925 !(pNd = pNd->StartOfSectionNode())->IsTableNode() )
927 if( !pOldTblNd )
928 return ;
930 bMakeCopy = TRUE;
931 pNd = pOldTblNd;
933 pTableNode = (SwTableNode*)pNd;
935 SwTableLines* pLns = &pTableNode->GetTable().GetTabLines();
936 SwTableLine* pLine = (*pLns)[ pLns->Count()-1 ];
937 SwTableBoxes& rBoxes = pLine->GetTabBoxes();
938 SwTableBox* pBox = rBoxes[ rBoxes.Count()-1 ];
940 if(nRowsToRepeat>0)
941 pTableNode->GetTable().SetRowsToRepeat( nRowsToRepeat );
943 if( !bMakeCopy &&
944 64000 < pTableNode->GetTable().GetTabSortBoxes().Count() )
946 bMakeCopy = TRUE; // spaetestens jetzt eine neue anfangen!
949 if( bMakeCopy )
951 // und die Selektion kopieren
952 SwSelBoxes aBoxes;
953 pTableNode->GetTable().SelLineFromBox( pBox, aBoxes );
954 pTableNode->GetTable().MakeCopy( pDoc, *pPam->GetPoint(),
955 aBoxes, FALSE );
956 ULONG nNd = pPam->GetPoint()->nNode.GetIndex()-1;
957 pTableNode = pDoc->GetNodes()[ nNd ]->FindTableNode();
958 pOldTblNd = pTableNode;
960 nRowsToRepeat=0;
961 pTableNode->GetTable().SetRowsToRepeat(nRowsToRepeat);
962 pLns = &pTableNode->GetTable().GetTabLines();
964 else
965 // pDoc->InsertRow( aBoxes );
966 pTableNode->GetTable().AppendRow( pDoc );
968 pBox = (*pLns)[ pLns->Count()-1 ]->GetTabBoxes()[0];
970 ULONG nOldPos = pPam->GetPoint()->nNode.GetIndex();
971 pPam->GetPoint()->nNode = *pBox->GetSttNd();
972 pPam->Move( fnMoveForward );
973 nAktBox = 0;
975 // alle Nodes in den Boxen auf die "default" Vorlage setzten
977 SwTxtFmtColl* pColl = aTxtCollTbl.Get( 0 );
978 if( !pColl )
979 pColl = pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false );
980 pPam->SetMark();
982 pLine = (*pLns)[ pLns->Count()-1 ];
983 pBox = pLine->GetTabBoxes()[ pLine->GetTabBoxes().Count() -1 ];
984 pPam->GetPoint()->nNode = *pBox->GetSttNd()->EndOfSectionNode();
985 pPam->Move( fnMoveBackward );
986 pDoc->SetTxtFmtColl( *pPam, pColl );
987 // Bug 73940 - remove ALL attributes (NumRules/Break/etc.)
989 SwNodeIndex aIdx( pPam->GetMark()->nNode );
990 SwNodeIndex& rEndIdx = pPam->GetPoint()->nNode;
991 while( aIdx <= rEndIdx )
993 SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
994 if( pCNd && pCNd->HasSwAttrSet() )
995 pCNd->ResetAllAttr();
996 aIdx++;
999 pPam->Exchange();
1000 pPam->DeleteMark();
1003 // alle Attribute, die schon auf den nachfolgen zeigen auf die neue
1004 // Box umsetzen !!
1005 SvxRTFItemStack& rAttrStk = GetAttrStack();
1006 const SvxRTFItemStackType* pStk;
1007 for( USHORT n = 0; n < rAttrStk.Count(); ++n )
1008 if( ( pStk = rAttrStk[ n ])->GetSttNodeIdx() == ULONG(nOldPos) &&
1009 !pStk->GetSttCnt() )
1010 ((SvxRTFItemStackType*)pStk)->SetStartPos( SwxPosition( pPam ) );
1013 void SwRTFParser::CheckInsNewTblLine()
1015 if( USHRT_MAX != nInsTblRow )
1017 if( nInsTblRow > GetOpenBrakets() || IsPardTokenRead() )
1018 nInsTblRow = USHRT_MAX;
1019 else if( !pTableNode ) // Tabelle nicht mehr vorhanden ?
1020 NewTblLine(); // evt. Line copieren
1024 /* vi:set tabstop=4 shiftwidth=4 expandtab: */