1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
27
28 #ifdef WTC
29 #define private public
30 #endif
31 #include <hintids.hxx>
32 #include <editeng/lrspitem.hxx>
33 #include <editeng/boxitem.hxx>
34 #include <editeng/frmdiritem.hxx>
35 #include <svtools/rtftoken.h>
36 #include <fmtfsize.hxx>
37 #include <fmtpdsc.hxx>
38 #include <ndtxt.hxx>
39 #include <doc.hxx>
40 #include <pam.hxx>
41 #include <swparrtf.hxx>
42 #include <swtable.hxx>
43 #include <tblsel.hxx>
44 #include <swtblfmt.hxx>
45 #include <wrtswtbl.hxx>
46 #include <tblenum.hxx>
47 #include <frmatr.hxx>
48 #include <fmtrowsplt.hxx>
49
50 using namespace ::com::sun::star;
51
52 typedef SwTableBoxFmt* SwTableBoxFmtPtr;
53 SV_DECL_PTRARR( SwBoxFrmFmts, SwTableBoxFmtPtr, 25, 50 )
54
55 class SwShareBoxFmts;
56 extern void _DeleteBox( SwTable& rTbl, SwTableBox* pBox, SwUndo* = 0,
57 sal_Bool = sal_True, const sal_Bool = sal_True, SwShareBoxFmts* = 0 );
58
59 struct Row
60 {
61 bool mbUseLeftRowPad, mbUseRightRowPad, mbUseTopRowPad, mbUseBottomRowPad;
62 long mnLeftRowPad, mnRightRowPad, mnTopRowPad, mnBottomRowPad;
63 sal_uInt16 mnBrdDist;
RowRow64 Row() :
65 mbUseLeftRowPad(false), mbUseRightRowPad(false),
66 mbUseTopRowPad(false), mbUseBottomRowPad(false),
67 mnLeftRowPad(0), mnRightRowPad(0), mnTopRowPad(0), mnBottomRowPad(0),
68 mnBrdDist(MIN_BORDER_DIST)
69 {}
70 };
71
SetRowBorder(SfxItemSet & rSet,const Row & rRow)72 static void SetRowBorder(SfxItemSet& rSet, const Row &rRow)
73 {
74 #if 1
75 SvxBoxItem aBox((const SvxBoxItem&)rSet.Get(RES_BOX, false));
76 aBox.SetDistance( static_cast< sal_uInt16 >(rRow.mbUseLeftRowPad ? rRow.mnLeftRowPad : rRow.mnBrdDist),
77 BOX_LINE_LEFT);
78
79 aBox.SetDistance( static_cast< sal_uInt16 >(rRow.mbUseRightRowPad ? rRow.mnRightRowPad : rRow.mnBrdDist),
80 BOX_LINE_RIGHT);
81
82 aBox.SetDistance( static_cast< sal_uInt16 >(rRow.mbUseTopRowPad ? rRow.mnTopRowPad : 0),
83 BOX_LINE_TOP);
84
85 aBox.SetDistance( static_cast< sal_uInt16 >(rRow.mbUseBottomRowPad ? rRow.mnBottomRowPad : 0),
86 BOX_LINE_BOTTOM);
87
88 rSet.Put(aBox);
89 #else
90 const SfxPoolItem* pItem;
91 if (SFX_ITEM_SET == rSet.GetItemState(RES_BOX, sal_False, &pItem))
92 {
93 SvxBoxItem aBox( *(SvxBoxItem*)pItem );
94 aBox.SetDistance(rRow.mbUseLeftRowPad ? rRow.mnLeftRowPad : rRow.mnBrdDist,
95 BOX_LINE_LEFT);
96
97 aBox.SetDistance(rRow.mbUseRightRowPad ? rRow.mnRightRowPad : rRow.mnBrdDist,
98 BOX_LINE_RIGHT);
99
100 aBox.SetDistance(rRow.mbUseTopRowPad ? rRow.mnTopRowPad : 0,
101 BOX_LINE_TOP);
102
103 aBox.SetDistance(rRow.mbUseBottomRowPad ? rRow.mnBottomRowPad : 0,
104 BOX_LINE_BOTTOM);
105
106 rSet.Put(aBox);
107 }
108 #endif
109 }
110
PrependedInlineNode(const SwPosition & rPos,const SwNode & rNode)111 void rtfSections::PrependedInlineNode(const SwPosition &rPos,
112 const SwNode &rNode)
113 {
114 ASSERT(!mrReader.IsNewDoc() || !maSegments.empty(),
115 "should not be possible, must be at least one segment in a new document");
116 if ((!maSegments.empty()) && (maSegments.back().maStart == rPos.nNode))
117 maSegments.back().maStart = SwNodeIndex(rNode);
118 }
119
IsBorderToken(int nToken)120 bool SwRTFParser::IsBorderToken(int nToken)
121 {
122 /*
123 i30222 i28983
124 Our ability to sense border tokens is broken rtftoken.h is
125 organised in a way that ignores some border tokens. ReadBorderAttr
126 still doesn't support the more exotic borders but at least this
127 won't cause the parser to prematuerely exit the table
128 */
129 bool bResult = false;
130
131 bResult = (nToken >= RTF_BRDRDASHD && nToken <= RTF_BRDRTHTNMG) ||
132 (nToken >= RTF_BRDRTNTHSG && nToken <= RTF_BRDRWAVY);
133
134 return bResult;
135 }
136
ReadTable(int nToken)137 void SwRTFParser::ReadTable( int nToken )
138 {
139 nInsTblRow = USHRT_MAX;
140
141 if (CantUseTables())
142 {
143 // alle Tabellen-Tokens ueberlesen
144 nToken = GetNextToken(); // RTF_TROWD ueberlesen
145 do {
146 if( RTF_TABLEDEF != (nToken & ~(0xff | RTF_SWGDEFS)) &&
147 RTF_UNKNOWNCONTROL != nToken )
148 {
149 SkipToken( -1 );
150 break;
151 }
152 nToken = GetNextToken();
153 } while( IsParserWorking() );
154 return ;
155 }
156
157 // verhinder Tabelle in Tabelle/Footnote
158 SwTwips nTblSz = 0;
159 int bReadNewCell = sal_False, bChkExistTbl = sal_False;
160
161
162 enum Limits {eMAXCELLS=64000};
163
164 SvBools aMergeBackup(aMergeBoxes);
165
166 // kein TROWD aber ein TabellenToken -> zwischen TROWD und Tab.Token
167 // waren andere Zeichen (siehe Bug 27445.rtf)
168 if( RTF_TROWD == nToken || !pTableNode )
169 {
170 if( RTF_TROWD == nToken )
171 nToken = GetNextToken(); // RTF_TROWD ueberlesen
172
173 // Flag for delete merged boxes
174 aMergeBoxes.clear();
175 aMergeBoxes.push_back( (sal_Bool)sal_False );
176 m_nCurrentBox = 0;
177
178 // wenn schon in einer Tabellen, dann splitte oder benutze
179 // die bisherigen Boxen weiter
180 bChkExistTbl = 0 != pPam->GetPoint()->nNode.GetNode().FindTableNode();
181 }
182 else
183 {
184 bReadNewCell = sal_True;
185 SwTableLines& rLns = pTableNode->GetTable().GetTabLines();
186 SwTableLine* pLine = rLns[ rLns.Count()-1 ];
187 // very robust to avoid crashes like bug 127425 + crash reports 118743
188 if( pLine )
189 {
190 sal_uInt16 nTmpBox = m_nCurrentBox;
191 if( nTmpBox > pLine->GetTabBoxes().Count() )
192 nTmpBox = pLine->GetTabBoxes().Count();
193
194 for (sal_uInt16 n = nTmpBox; n; )
195 {
196 const SwTableBox *pTmp = pLine->GetTabBoxes()[ --n ];
197 if( pTmp )
198 {
199 const SwFrmFmt* pTmpFmt = pTmp->GetFrmFmt();
200 if( pTmpFmt )
201 nTblSz += pTmpFmt->GetFrmSize().GetWidth();
202 }
203 }
204 }
205 }
206
207
208 sal_Int16 eAdjust = text::HoriOrientation::LEFT; // default fuer Tabellen
209 SwTwips nLSpace = 0;
210 Row aRow;
211
212 bool bUseLeftCellPad = false, bUseRightCellPad = false,
213 bUseTopCellPad = false, bUseBottomCellPad = false;
214 long nLeftCellPad = 0, nRightCellPad = 0, nTopCellPad = 0,
215 nBottomCellPad = 0;
216
217 sal_Int16 eVerOrient = text::VertOrientation::NONE;
218 long nLineHeight = 0;
219 if (aMergeBoxes.empty()) // can this actually happen?
220 {
221 OSL_ASSERT(false);
222 aMergeBoxes.push_back(sal_False);
223 }
224 size_t nBoxCnt = aMergeBoxes.size()-1;
225 SwBoxFrmFmts aBoxFmts;
226 SwTableBoxFmt* pBoxFmt = pDoc->MakeTableBoxFmt();
227 SvxFrameDirection eDir = FRMDIR_HORI_LEFT_TOP;
228 bool bCantSplit = false;
229
230 int bWeiter = sal_True;
231 do {
232 switch( nToken )
233 {
234 case RTF_TRPADDFL:
235 aRow.mbUseLeftRowPad = (nTokenValue == 3) ? true : false;
236 break;
237 case RTF_TRPADDFT:
238 aRow.mbUseTopRowPad = (nTokenValue == 3) ? true : false;
239 break;
240 case RTF_TRPADDFR:
241 aRow.mbUseRightRowPad = (nTokenValue == 3) ? true : false;
242 break;
243 case RTF_TRPADDFB:
244 aRow.mbUseBottomRowPad = (nTokenValue == 3) ? true : false;
245 break;
246 case RTF_TRPADDL:
247 aRow.mnLeftRowPad = nTokenValue;
248 break;
249 case RTF_TRPADDT:
250 aRow.mnTopRowPad = nTokenValue;
251 break;
252 case RTF_TRPADDR:
253 aRow.mnRightRowPad = nTokenValue;
254 break;
255 case RTF_TRPADDB:
256 aRow.mnBottomRowPad = nTokenValue;
257 break;
258
259 case RTF_CLPADFL:
260 bUseLeftCellPad = (nTokenValue == 3) ? true : false;
261 break;
262 case RTF_CLPADFT:
263 bUseTopCellPad = (nTokenValue == 3) ? true : false;
264 break;
265 case RTF_CLPADFR:
266 bUseRightCellPad = (nTokenValue == 3) ? true : false;
267 break;
268 case RTF_CLPADFB:
269 bUseBottomCellPad = (nTokenValue == 3) ? true : false;
270 break;
271 case RTF_CLPADL:
272 nLeftCellPad = nTokenValue;
273 break;
274 case RTF_CLPADT:
275 nTopCellPad = nTokenValue;
276 break;
277 case RTF_CLPADR:
278 nRightCellPad = nTokenValue;
279 break;
280 case RTF_CLPADB:
281 nBottomCellPad = nTokenValue;
282 break;
283
284 case RTF_TRRH:
285 nLineHeight = nTokenValue;
286 break;
287
288 case RTF_CLMRG:
289 // would crash later on reading \cellx (#i112657#):
290 // the first cell cannot be merged with earlier ones.
291 if (nBoxCnt != 0)
292 {
293 aMergeBoxes.back() = sal_True;
294 }
295 break;
296
297 case RTF_CELLX:
298 if (!bTrowdRead && (aMergeBoxes.size() < (SAL_MAX_UINT16 - 1)))
299 {
300 SwTableBoxFmt* pFmt = pBoxFmt;
301 SwTwips nSize = nTokenValue - nTblSz;
302 if( aMergeBoxes.back() )
303 {
304 // neue Zellen lesen und noch keine Formate vorhanden,
305 // dann benutze das der vorhergebende
306 if( bReadNewCell && !aBoxFmts.Count() )
307 {
308 SwTableLines& rLns = pTableNode->GetTable().GetTabLines();
309 SwTableLine* pLine = rLns[ rLns.Count()-1 ];
310 if (m_nCurrentBox != 0)
311 {
312 --m_nCurrentBox;
313 }
314 if (m_nCurrentBox < pLine->GetTabBoxes().Count())
315 {
316 pFmt = static_cast<SwTableBoxFmt*>(
317 pLine->GetTabBoxes()[m_nCurrentBox]->GetFrmFmt());
318 }
319 }
320 else
321 pFmt = aBoxFmts[ aBoxFmts.Count()-1 ];
322
323 // --> OD 2007-01-25 #i73790# - method renamed
324 pBoxFmt->ResetAllFmtAttr();
325 // <--
326 nSize += pFmt->GetFrmSize().GetWidth();
327 }
328 else
329 {
330 //
331 if (nSize<=2*aRow.mnBrdDist) {
332 aRow.mnRightRowPad=0;
333 aRow.mbUseRightRowPad=sal_True;
334 }
335 SetRowBorder((SfxItemSet&)pBoxFmt->GetAttrSet(), aRow);
336 aBoxFmts.Insert( pBoxFmt, aBoxFmts.Count() );
337 pBoxFmt = pDoc->MakeTableBoxFmt();
338 }
339
340 if( !nSize )
341 nSize = COL_DFLT_WIDTH;
342 pFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nSize, 0 ));
343 nTblSz = nTokenValue;
344 aMergeBoxes.push_back( (sal_Bool)sal_False );
345 ++nBoxCnt;
346
347 SvxBoxItem aBox(pFmt->GetBox());
348
349 if (bUseRightCellPad)
350 aBox.SetDistance( static_cast< sal_uInt16 >(nRightCellPad), BOX_LINE_RIGHT);
351 if (bUseBottomCellPad)
352 aBox.SetDistance( static_cast< sal_uInt16 >(nBottomCellPad), BOX_LINE_BOTTOM);
353
354 //Yes, these are the wrong way around, there appears to
355 //be a bug in word where these are swapped.
356 if (bUseLeftCellPad)
357 aBox.SetDistance( static_cast< sal_uInt16 >(nLeftCellPad), BOX_LINE_TOP);
358 if (bUseTopCellPad)
359 aBox.SetDistance( static_cast< sal_uInt16 >(nTopCellPad), BOX_LINE_LEFT);
360
361
362 /*#106415# The Cell Borders are now balanced on import to
363 improve the layout of tables.
364 */
365 /*
366 if ( aBoxFmts.Count()>1)
367 {
368
369 SwTableBoxFmt* prevpFmt = aBoxFmts[ aBoxFmts.Count()-2 ];
370 SvxBoxItem prevaBox(prevpFmt->GetBox());
371 sal_uInt16 prevWidthRight=0;
372 sal_uInt16 currWidthLeft=0;
373 bool bDoubleLine=false;
374 const SvxBorderLine* brdrline ;
375 const Color* pPrevRightColor;
376 if(prevaBox.GetRight())
377 {
378 brdrline=prevaBox.GetRight();
379 prevWidthRight = brdrline->GetOutWidth();
380 pPrevRightColor = &brdrline->GetColor();
381 if(brdrline->GetInWidth())
382 bDoubleLine=true;
383 }
384 if(aBox.GetLeft())
385 {
386 brdrline=aBox.GetLeft();
387 currWidthLeft = brdrline->GetOutWidth();
388 if(brdrline->GetInWidth())
389 bDoubleLine=true;
390 }
391
392 if((currWidthLeft >0 || prevWidthRight >0) &&
393 !bDoubleLine)
394 {
395 sal_uInt16 newBorderWidth=(currWidthLeft+prevWidthRight)/2 ;
396 if(newBorderWidth /2 ==DEF_LINE_WIDTH_0 )
397 {
398 newBorderWidth =DEF_LINE_WIDTH_0;
399 }
400 else if(newBorderWidth /2 >=(DEF_LINE_WIDTH_4-DEF_LINE_WIDTH_3))
401 {
402 newBorderWidth =DEF_LINE_WIDTH_4;
403 }
404 else if(newBorderWidth /2 >=(DEF_LINE_WIDTH_3-DEF_LINE_WIDTH_2))
405 {
406 newBorderWidth =DEF_LINE_WIDTH_3;
407 }
408 else if(newBorderWidth /2>=(DEF_LINE_WIDTH_2-DEF_LINE_WIDTH_1))
409 {
410 newBorderWidth =DEF_LINE_WIDTH_2;
411 }
412 else if(newBorderWidth /2>=(DEF_LINE_WIDTH_1 - DEF_LINE_WIDTH_0) )
413 {
414 newBorderWidth =DEF_LINE_WIDTH_1;
415 }
416 else
417 {
418 newBorderWidth =DEF_LINE_WIDTH_0;
419 }
420 const SvxBorderLine newbrdrline(pPrevRightColor, newBorderWidth,0,0);
421 aBox.SetLine(&newbrdrline,BOX_LINE_LEFT);
422 prevaBox.SetLine(&newbrdrline,BOX_LINE_RIGHT);
423 prevpFmt->SetAttr(prevaBox);
424 }
425
426 }
427 */
428
429 pFmt->SetFmtAttr(aBox);
430
431 bUseLeftCellPad = false;
432 bUseRightCellPad = false;
433 bUseTopCellPad = false;
434 bUseBottomCellPad = false;
435 }
436 break;
437
438 case RTF_TRGAPH:
439 //$flr bug #117887#: RTF: wrong internal table cell margin imported (A13)
440 aRow.mnBrdDist = (nTokenValue>0?(sal_uInt16)nTokenValue:0); // filter out negative values of \trgaph
441 break;
442
443 case RTF_TRQL: eAdjust = text::HoriOrientation::LEFT; break;
444 case RTF_TRQR: eAdjust = text::HoriOrientation::RIGHT; break;
445 case RTF_TRQC: eAdjust = text::HoriOrientation::CENTER; break;
446
447 // mit text::VertOrientation::TOP kommt der Dialog nicht klar!
448 // Bug #65126#
449 case RTF_CLVERTALT: eVerOrient = text::VertOrientation::NONE; break;
450
451 case RTF_CLVERTALC: eVerOrient = text::VertOrientation::CENTER; break;
452 case RTF_CLVERTALB: eVerOrient = text::VertOrientation::BOTTOM; break;
453
454 case RTF_TRLEFT:
455 if( text::HoriOrientation::LEFT == eAdjust )
456 eAdjust = text::HoriOrientation::LEFT_AND_WIDTH;
457 nLSpace = nTokenValue;
458 nTblSz = nTokenValue;
459 break;
460
461 case RTF_TRHDR:
462 nRowsToRepeat++;
463 break;
464
465 case RTF_CLTXLRTB:
466 case RTF_CLTXTBRL:
467 case RTF_INTBL: // das wissen wir !
468 case RTF_CLMGF:
469 case RTF_CLVMGF:
470 case RTF_CLVMRG:
471 break;
472 case RTF_LTRROW:
473 eDir = FRMDIR_HORI_LEFT_TOP;
474 break;
475 case RTF_RTLROW:
476 eDir = FRMDIR_HORI_RIGHT_TOP;
477 break;
478 case RTF_TRBRDRB:
479 case RTF_TRBRDRH:
480 case RTF_TRBRDRL:
481 case RTF_TRBRDRR:
482 case RTF_TRBRDRT:
483 case RTF_TRBRDRV:
484 break;
485 case RTF_TRKEEP:
486 bCantSplit = true;
487 break;
488
489 default:
490 if( ( nToken & ~(0xff | RTF_TABLEDEF)) == RTF_SHADINGDEF )
491 {
492 if( aMergeBoxes.back() )
493 break;
494 ReadBackgroundAttr( nToken,
495 (SfxItemSet&)pBoxFmt->GetAttrSet(), sal_True );
496 }
497 else if( ( nToken & ~(0xff | RTF_TABLEDEF) ) == RTF_BRDRDEF ||
498 IsBorderToken(nToken))
499 {
500 if( aMergeBoxes.back() )
501 break;
502
503 SfxItemSet& rSet = (SfxItemSet&)pBoxFmt->GetAttrSet();
504 if(!IsBorderToken( nToken ))
505 ReadBorderAttr( nToken, rSet, sal_True );
506 else
507 NextToken( nToken );
508 }
509 else if( RTF_TABLEDEF != (nToken & ~(0xff | RTF_SWGDEFS)) )
510 {
511 if( RTF_UNKNOWNCONTROL == nToken )
512 NextToken( nToken );
513 else
514 bWeiter = sal_False;
515 }
516 break;
517 }
518
519 if( text::VertOrientation::NONE != eVerOrient )
520 {
521 if( !aMergeBoxes.back() )
522 pBoxFmt->SetFmtAttr( SwFmtVertOrient( 0, eVerOrient ));
523 eVerOrient = text::VertOrientation::NONE;
524 }
525 if( bWeiter )
526 nToken = GetNextToken();
527 } while( bWeiter && IsParserWorking() );
528
529 // das letzte temp. BoxFmt loeschen
530 delete pBoxFmt;
531
532 // It has been recognized as not single box
533 if ((m_nCurrentBox == nBoxCnt) || ( bReadNewCell && !pTableNode ))
534 {
535 aMergeBoxes = aMergeBackup;
536 SkipToken( -1 ); // go back to the last valid
537 return;
538 }
539
540 nTblSz -= nLSpace;
541
542 int bNewTbl = sal_True;
543 SwTableLine* pNewLine;
544 bTrowdRead=true;
545
546 // lege eine neue Tabelle an oder erweiter die aktuelle um eine neue Line
547 // oder Box !
548 SwNode* pNd;
549
550 if( bChkExistTbl )
551 {
552 // es ist eine Tabelle vorhanden, teste mal ob die weiter benutzt
553 // werden kann oder ob sie abgesplittet und neu gefuellt werden
554 // muss.
555 pTableNode = pPam->GetNode()->FindTableNode();
556
557 // Cursor kann nur in der letzten Line stehen
558
559 // das Attribut darf nicht ueber das Modify an der
560 // Tabelle gesetzt werden, denn sonst werden alle
561 // Boxen wieder auf 0 zurueck gesetzt !!!!!
562 SwFrmFmt* pFmt = pTableNode->GetTable().GetFrmFmt();
563 const SwFmtFrmSize& rTblSz = pFmt->GetFrmSize();
564 const SwFmtHoriOrient& rHoriz = pFmt->GetHoriOrient();
565
566 const SwTableLines* pLns = &pTableNode->GetTable().GetTabLines();
567
568 if( 1 == pLns->Count() )
569 {
570 if( eAdjust != rHoriz.GetHoriOrient() )
571 {
572 ((SfxItemSet&)pFmt->GetAttrSet()).Put( SwFmtHoriOrient( 0,
573 eAdjust ) );
574 }
575 if( rTblSz.GetWidth() != nTblSz )
576 {
577 SwFmtFrmSize aSz( rTblSz );
578 aSz.SetWidth( nTblSz );
579 ((SfxItemSet&)pFmt->GetAttrSet()).Put( aSz );
580 }
581
582 if( text::HoriOrientation::LEFT_AND_WIDTH == eAdjust &&
583 nLSpace != pFmt->GetLRSpace().GetLeft() )
584 {
585 SvxLRSpaceItem aL( RES_LR_SPACE ); aL.SetLeft( nLSpace );
586 ((SfxItemSet&)pFmt->GetAttrSet()).Put( aL );
587 }
588 }
589 else if
590 (
591 1 < pLns->Count() &&
592 (
593 rTblSz.GetWidth() != nTblSz ||
594 rHoriz.GetHoriOrient() != eAdjust ||
595 (
596 text::HoriOrientation::LEFT_AND_WIDTH == eAdjust &&
597 nLSpace != pFmt->GetLRSpace().GetLeft()
598 ) ||
599 pTableNode->GetTable().GetTabSortBoxes().Count() >= eMAXCELLS
600 )
601 )
602 {
603 // Tabelle ab der PaM-Position splitten
604 // die vorherige Line!
605 pNewLine = (*pLns)[ pLns->Count() - 2 ];
606 SwTableBox* pBox = pNewLine->GetTabBoxes()[ 0 ];
607 while( ( pLns = &pBox->GetTabLines() )->Count() )
608 pBox = (*pLns)[ 0 ]->GetTabBoxes()[ 0 ];
609
610 SwNodeIndex aTmpIdx( *pBox->GetSttNd() );
611 pDoc->GetNodes().SplitTable( aTmpIdx, HEADLINE_NONE, sal_False );
612 pTableNode = pPam->GetNode()->FindTableNode();
613 pFmt = pTableNode->GetTable().GetFrmFmt();
614
615 SwFmtFrmSize aSz( rTblSz );
616 aSz.SetWidth( nTblSz );
617 ((SfxItemSet&)pFmt->GetAttrSet()).Put( aSz );
618 ((SfxItemSet&)pFmt->GetAttrSet()).Put( SwFmtHoriOrient( 0,
619 eAdjust ) );
620 if( text::HoriOrientation::LEFT_AND_WIDTH == eAdjust && nLSpace )
621 {
622 SvxLRSpaceItem aL( RES_LR_SPACE ); aL.SetLeft( nLSpace );
623 ((SfxItemSet&)pFmt->GetAttrSet()).Put( aL );
624 }
625 }
626
627 pLns = &pTableNode->GetTable().GetTabLines();
628 pNewLine = (*pLns)[ pLns->Count() - 1 ];
629
630 // jetzt die Boxen abgleichen
631 sal_uInt16 nBoxes = Min( pNewLine->GetTabBoxes().Count(), aBoxFmts.Count() );
632 sal_uInt16 n;
633
634 for( n = 0; n < nBoxes; ++n )
635 {
636 SwTableBox* pBox = pNewLine->GetTabBoxes()[ n ];
637 *pBox->GetFrmFmt() = *aBoxFmts[ n ];
638 delete aBoxFmts[ n ];
639 }
640 aBoxFmts.Remove( 0, n );
641
642 if( aBoxFmts.Count() ) // es muessen noch neue zugefuegt werden
643 {
644 m_nCurrentBox = n;
645 }
646 else // es mussen noch Boxen geloescht werden
647 {
648 // remove ContentIndex of other Bound
649 pPam->SetMark(); pPam->DeleteMark();
650 while( n < pNewLine->GetTabBoxes().Count() )
651 _DeleteBox( pTableNode->GetTable(),
652 pNewLine->GetTabBoxes()[ n ], 0, sal_False, sal_False );
653 }
654
655 pOldTblNd = pTableNode;
656 bNewTbl = sal_False;
657 }
658 else
659 {
660 if( !bReadNewCell && ( pNd = pDoc->GetNodes()[
661 pPam->GetPoint()->nNode.GetIndex()-1 ])->IsEndNode() )
662 {
663 pTableNode = pNd->StartOfSectionNode()->GetTableNode();
664 if( pTableNode )
665 {
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
676 )
677 {
678 pTableNode = 0;
679 }
680 }
681 }
682
683 if( pTableNode && !bForceNewTable)
684 {
685
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 )
692 {
693 SwFmtFrmSize aSz( rTblSz );
694 aSz.SetWidth( nTblSz );
695 ((SfxItemSet&)pFmt->GetAttrSet()).Put( aSz );
696 }
697
698 SwTableLines& rLns = pTableNode->GetTable().GetTabLines();
699
700 if( bReadNewCell )
701 pNewLine = rLns[ rLns.Count()-1 ];
702 else
703 {
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() );
710 }
711 bNewTbl = sal_False;
712 }
713 else
714 {
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, sal_False, sal_False );
720 bContainsTablePara=true; //#117881#
721 pTableNode = pTable ? pTable->GetTableNode() : 0;
722
723 if (pTableNode)
724 {
725 maSegments.PrependedInlineNode(*pPam->GetPoint(),
726 *pTableNode);
727 }
728 else
729 {
730 SkipToken( -1 ); // zum Letzen gueltigen zurueck
731 return;
732 }
733
734 SwTableLines& rLns = pTableNode->GetTable().GetTabLines();
735 pNewLine = rLns[ rLns.Count()-1 ];
736
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));
742
743 if( text::HoriOrientation::LEFT_AND_WIDTH == eAdjust && nLSpace )
744 {
745 SvxLRSpaceItem aL( RES_LR_SPACE ); aL.SetLeft( nLSpace );
746 ((SfxItemSet&)pFmt->GetAttrSet()).Put( aL );
747 }
748
749 m_nCurrentBox = 0;
750 pOldTblNd = pTableNode;
751 }
752 }
753
754 if( nLineHeight )
755 {
756 SwFrmSize eSize;
757 if( 0 > nLineHeight )
758 eSize = ATT_FIX_SIZE, nLineHeight = -nLineHeight;
759 else
760 eSize = ATT_MIN_SIZE;
761 pNewLine->ClaimFrmFmt()->SetFmtAttr(SwFmtFrmSize(eSize, 0, nLineHeight));
762 }
763
764 pNewLine->ClaimFrmFmt()->SetFmtAttr(SwFmtRowSplit(!bCantSplit));
765
766 if( aBoxFmts.Count() )
767 {
768 // setze das default Style
769 SwTxtFmtColl* pColl = aTxtCollTbl.Get( 0 );
770 if( !pColl )
771 pColl = pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false );
772
773 sal_uInt16 nStt = 0;
774 if( bNewTbl )
775 {
776 SwTableBox* pBox = pNewLine->GetTabBoxes()[0];
777 pBoxFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
778 pBox->ForgetFrmFmt();
779 delete pBoxFmt;
780 pBox->RegisterToFormat( *aBoxFmts[0] );
781 SwTxtNode* pTNd = pDoc->GetNodes()[ pBox->GetSttIdx()+1 ]
782 ->GetTxtNode();
783 ASSERT( pTNd, "wo ist der Textnode dieser Box?" );
784 pTNd->ChgFmtColl( pColl );
785 ++nStt;
786 nRowsToRepeat=0;
787 }
788
789 for( ; nStt < aBoxFmts.Count(); ++nStt )
790 {
791 pDoc->GetNodes().InsBoxen( pTableNode, pNewLine,
792 aBoxFmts[ nStt ],
793 // Formate fuer den TextNode der Box
794 pColl, 0,
795 m_nCurrentBox + nStt, 1 );
796 }
797 }
798
799 if( bChkExistTbl )
800 {
801 m_nCurrentBox = 0;
802 }
803
804 maInsertedTables.InsertTable(*pTableNode, *pPam);
805
806 SwNodeIndex aOldIdx(pPam->GetPoint()->nNode);
807 SwNodeIdx aOldPos(aOldIdx);
808 SwPaM aRg(*pPam);
809
810 bool bFailure = true;
811 if (pNewLine)
812 {
813 SwTableBoxes &rBoxes = pNewLine->GetTabBoxes();
814 if (SwTableBox* pBox = ((m_nCurrentBox < rBoxes.Count())
815 ? rBoxes[m_nCurrentBox] : 0))
816 {
817 if (const SwStartNode *pStart = pBox->GetSttNd())
818 {
819 if (const SwEndNode *pEnd = pStart->EndOfSectionNode())
820 {
821 pPam->GetPoint()->nNode = *pEnd;
822 pPam->Move( fnMoveBackward, fnGoCntnt );
823 bFailure = false;
824 }
825 }
826 }
827 }
828
829 ASSERT(!bFailure, "RTF Table failure");
830 if (bFailure)
831 {
832 SkipToken( -1 ); // zum Letzen gueltigen zurueck
833 return;
834 }
835
836 //It might be that there was content at this point which is not already in
837 //a table, but which is being followed by properties to place it into the
838 //table. e.g. #109199#. If this is the case then move the para/char
839 //properties inside the table, and move any content of that paragraph into
840 //the table
841 bool bInTable = aRg.GetPoint()->nNode.GetNode().FindTableNode();
842 if (!bInTable)
843 {
844 SwNodeIndex aNewIdx(pPam->GetPoint()->nNode);
845 SwNodeIdx aNewPos(aNewIdx);
846
847 if (aRg.GetPoint()->nContent.GetIndex())
848 {
849 //If there is content in this node then move it entirely inside the
850 //table
851 aRg.SetMark();
852 aRg.GetMark()->nContent.Assign(aRg.GetCntntNode(), 0);
853 pDoc->MoveRange(aRg, *pPam->GetPoint(),
854 IDocumentContentOperations::DOC_MOVEDEFAULT);
855 }
856
857 //Update the attribute stack entries to reflect that the properties
858 //which were intended to be inside the tablerow are now left outside
859 //the table after the row was placed before the current insertion point
860 SvxRTFItemStack& rAttrStk = GetAttrStack();
861 for (size_t n = 0; n < rAttrStk.size(); ++n)
862 {
863 SvxRTFItemStackType* pStk = rAttrStk[n];
864 pStk->MoveFullNode(aOldPos, aNewPos);
865 }
866 }
867 SkipToken( -1 ); // zum Letzen gueltigen zurueck
868 }
869
870 // in die naechste Box dieser Line (opt.: falls es nicht die letzte ist)
GotoNextBox()871 void SwRTFParser::GotoNextBox()
872 {
873 nInsTblRow = USHRT_MAX;
874
875 ASSERT( pTableNode, "Kein Tabellennode, dann auch keine Box" );
876
877 if (!pTableNode)
878 return;
879
880 SwTableLines& rLns = pTableNode->GetTable().GetTabLines();
881 SwTableLine* pLine = rLns[ rLns.Count()-1 ];
882 SwTableBoxes& rBoxes = pLine->GetTabBoxes();
883 SwTableBox* pBox = rBoxes[ rBoxes.Count()-1 ];
884
885 if (++m_nCurrentBox >= aMergeBoxes.size())
886 {
887 OSL_ENSURE(aMergeBoxes.size() < SAL_MAX_UINT16, "too many boxes?");
888 m_nCurrentBox = static_cast<sal_uInt16>(aMergeBoxes.size()-1);
889 }
890
891 if (!aMergeBoxes[ m_nCurrentBox ])
892 {
893 int bMove = sal_True;
894 if( pBox->GetSttIdx() > pPam->GetPoint()->nNode.GetIndex() )
895 {
896 sal_uInt16 nRealBox = 0;
897 for (sal_uInt16 nTmp = 0; nTmp < m_nCurrentBox; ++nTmp)
898 if( !aMergeBoxes[ nTmp ] )
899 ++nRealBox;
900
901 if( nRealBox < rBoxes.Count() )
902 {
903 pPam->GetPoint()->nNode = *rBoxes[ nRealBox ]->GetSttNd()->EndOfSectionNode();
904 pPam->Move( fnMoveBackward, fnGoCntnt );
905 bMove = sal_False;
906 }
907 }
908
909 if (bMove &&
910 ((static_cast<size_t>(m_nCurrentBox) + 1) == aMergeBoxes.size()))
911 // dann hinter die Tabelle
912 pPam->Move( fnMoveForward, fnGoNode );
913 }
914 else if (pPam->GetPoint()->nNode.GetNode().IsCntntNode())
915 // dann in die vorherige ans Ende
916 pPam->Move( fnMoveBackward, fnGoCntnt );
917 }
918
919
NewTblLine()920 void SwRTFParser::NewTblLine()
921 {
922 nInsTblRow = USHRT_MAX;
923
924 // erweiter die aktuelle um eine neue Line
925 sal_Bool bMakeCopy = sal_False;
926 SwNode* pNd = pDoc->GetNodes()[ pPam->GetPoint()->nNode.GetIndex()-1 ];
927 if( !pNd->IsEndNode() ||
928 !(pNd = pNd->StartOfSectionNode())->IsTableNode() )
929 {
930 if( !pOldTblNd )
931 return ;
932
933 bMakeCopy = sal_True;
934 pNd = pOldTblNd;
935 }
936 pTableNode = (SwTableNode*)pNd;
937
938 SwTableLines* pLns = &pTableNode->GetTable().GetTabLines();
939 SwTableLine* pLine = (*pLns)[ pLns->Count()-1 ];
940 SwTableBoxes& rBoxes = pLine->GetTabBoxes();
941 SwTableBox* pBox = rBoxes[ rBoxes.Count()-1 ];
942
943 if(nRowsToRepeat>0)
944 pTableNode->GetTable().SetRowsToRepeat( nRowsToRepeat );
945
946 if( !bMakeCopy &&
947 64000 < pTableNode->GetTable().GetTabSortBoxes().Count() )
948 {
949 bMakeCopy = sal_True; // spaetestens jetzt eine neue anfangen!
950 }
951
952 if( bMakeCopy )
953 {
954 // und die Selektion kopieren
955 SwSelBoxes aBoxes;
956 pTableNode->GetTable().SelLineFromBox( pBox, aBoxes );
957 pTableNode->GetTable().MakeCopy( pDoc, *pPam->GetPoint(),
958 aBoxes, sal_False );
959 sal_uLong nNd = pPam->GetPoint()->nNode.GetIndex()-1;
960 pTableNode = pDoc->GetNodes()[ nNd ]->FindTableNode();
961 pOldTblNd = pTableNode;
962
963 nRowsToRepeat=0;
964 pTableNode->GetTable().SetRowsToRepeat(nRowsToRepeat);
965 pLns = &pTableNode->GetTable().GetTabLines();
966 }
967 else
968 // pDoc->InsertRow( aBoxes );
969 pTableNode->GetTable().AppendRow( pDoc );
970
971 pBox = (*pLns)[ pLns->Count()-1 ]->GetTabBoxes()[0];
972
973 sal_uLong nOldPos = pPam->GetPoint()->nNode.GetIndex();
974 pPam->GetPoint()->nNode = *pBox->GetSttNd();
975 pPam->Move( fnMoveForward );
976 m_nCurrentBox = 0;
977
978 // alle Nodes in den Boxen auf die "default" Vorlage setzten
979 {
980 SwTxtFmtColl* pColl = aTxtCollTbl.Get( 0 );
981 if( !pColl )
982 pColl = pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false );
983 pPam->SetMark();
984
985 pLine = (*pLns)[ pLns->Count()-1 ];
986 pBox = pLine->GetTabBoxes()[ pLine->GetTabBoxes().Count() -1 ];
987 pPam->GetPoint()->nNode = *pBox->GetSttNd()->EndOfSectionNode();
988 pPam->Move( fnMoveBackward );
989 pDoc->SetTxtFmtColl( *pPam, pColl );
990 // Bug 73940 - remove ALL attributes (NumRules/Break/etc.)
991 {
992 SwNodeIndex aIdx( pPam->GetMark()->nNode );
993 SwNodeIndex& rEndIdx = pPam->GetPoint()->nNode;
994 while( aIdx <= rEndIdx )
995 {
996 SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
997 if( pCNd && pCNd->HasSwAttrSet() )
998 pCNd->ResetAllAttr();
999 aIdx++;
1000 }
1001 }
1002 pPam->Exchange();
1003 pPam->DeleteMark();
1004 }
1005
1006 // all attributes which will be displayed in new Box
1007 SvxRTFItemStack& rAttrStk = GetAttrStack();
1008 const SvxRTFItemStackType* pStk;
1009 for( size_t n = 0; n < rAttrStk.size(); ++n )
1010 if( ( pStk = rAttrStk[ n ])->GetSttNodeIdx() == sal_uLong(nOldPos) &&
1011 !pStk->GetSttCnt() )
1012 ((SvxRTFItemStackType*)pStk)->SetStartPos( SwxPosition( pPam ) );
1013 }
1014
CheckInsNewTblLine()1015 void SwRTFParser::CheckInsNewTblLine()
1016 {
1017 if( USHRT_MAX != nInsTblRow )
1018 {
1019 if( nInsTblRow > GetOpenBrakets() || IsPardTokenRead() )
1020 nInsTblRow = USHRT_MAX;
1021 else if( !pTableNode ) // Tabelle nicht mehr vorhanden ?
1022 NewTblLine(); // evt. Line copieren
1023 }
1024 }
1025
1026 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
1027