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