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