xref: /trunk/main/sw/source/filter/rtf/rtftbl.cxx (revision b264d727)
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