xref: /aoo4110/main/sw/source/core/table/swnewtable.cxx (revision b1cdbd2c)
1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_sw.hxx"
26*b1cdbd2cSJim Jagielski 
27*b1cdbd2cSJim Jagielski #include <swtable.hxx>
28*b1cdbd2cSJim Jagielski #include <tblsel.hxx>
29*b1cdbd2cSJim Jagielski #include <tblrwcl.hxx>
30*b1cdbd2cSJim Jagielski #include <node.hxx>
31*b1cdbd2cSJim Jagielski #include <UndoTable.hxx>
32*b1cdbd2cSJim Jagielski #include <pam.hxx>
33*b1cdbd2cSJim Jagielski #include <frmfmt.hxx>
34*b1cdbd2cSJim Jagielski #include <frmatr.hxx>
35*b1cdbd2cSJim Jagielski #include <cellfrm.hxx>
36*b1cdbd2cSJim Jagielski #include <fmtfsize.hxx>
37*b1cdbd2cSJim Jagielski #include <doc.hxx>
38*b1cdbd2cSJim Jagielski #include <IDocumentUndoRedo.hxx>
39*b1cdbd2cSJim Jagielski #include <vector>
40*b1cdbd2cSJim Jagielski #include <set>
41*b1cdbd2cSJim Jagielski #include <list>
42*b1cdbd2cSJim Jagielski #include <memory>
43*b1cdbd2cSJim Jagielski #include <editeng/boxitem.hxx>
44*b1cdbd2cSJim Jagielski #include <editeng/protitem.hxx>
45*b1cdbd2cSJim Jagielski #include <swtblfmt.hxx>
46*b1cdbd2cSJim Jagielski #include <switerator.hxx>
47*b1cdbd2cSJim Jagielski 
48*b1cdbd2cSJim Jagielski #ifndef DBG_UTIL
49*b1cdbd2cSJim Jagielski #define CHECK_TABLE(t)
50*b1cdbd2cSJim Jagielski #else
51*b1cdbd2cSJim Jagielski #ifdef DEBUG
52*b1cdbd2cSJim Jagielski #define CHECK_TABLE(t) (t).CheckConsistency();
53*b1cdbd2cSJim Jagielski #else
54*b1cdbd2cSJim Jagielski #define CHECK_TABLE(t)
55*b1cdbd2cSJim Jagielski #endif
56*b1cdbd2cSJim Jagielski #endif
57*b1cdbd2cSJim Jagielski 
58*b1cdbd2cSJim Jagielski // ---------------------------------------------------------------
59*b1cdbd2cSJim Jagielski 
60*b1cdbd2cSJim Jagielski /** SwBoxSelection is a small helperclass (structure) to handle selections
61*b1cdbd2cSJim Jagielski     of cells (boxes) between table functions
62*b1cdbd2cSJim Jagielski 
63*b1cdbd2cSJim Jagielski     It contains an "array" of table boxes, a rectangulare selection of table boxes.
64*b1cdbd2cSJim Jagielski     To be more specific, it contains a vector of box selections,
65*b1cdbd2cSJim Jagielski     every box selection (SwSelBoxes) contains the selected boxes inside one row.
66*b1cdbd2cSJim Jagielski     The member mnMergeWidth contains the width of the selected boxes
67*b1cdbd2cSJim Jagielski */
68*b1cdbd2cSJim Jagielski 
69*b1cdbd2cSJim Jagielski class SwBoxSelection
70*b1cdbd2cSJim Jagielski {
71*b1cdbd2cSJim Jagielski public:
72*b1cdbd2cSJim Jagielski     std::vector<const SwSelBoxes*> aBoxes;
73*b1cdbd2cSJim Jagielski     long mnMergeWidth;
SwBoxSelection()74*b1cdbd2cSJim Jagielski     SwBoxSelection() : mnMergeWidth(0) {}
isEmpty() const75*b1cdbd2cSJim Jagielski     bool isEmpty() const { return aBoxes.size() == 0; }
insertBoxes(const SwSelBoxes * pNew)76*b1cdbd2cSJim Jagielski     void insertBoxes( const SwSelBoxes* pNew ){ aBoxes.insert( aBoxes.end(), pNew ); }
77*b1cdbd2cSJim Jagielski };
78*b1cdbd2cSJim Jagielski 
79*b1cdbd2cSJim Jagielski /** NewMerge(..) removes the superfluous cells after cell merge
80*b1cdbd2cSJim Jagielski 
81*b1cdbd2cSJim Jagielski SwTable::NewMerge(..) does some cleaning up,
82*b1cdbd2cSJim Jagielski it simply deletes the superfluous cells ("cell span")
83*b1cdbd2cSJim Jagielski and notifies the Undo about it.
84*b1cdbd2cSJim Jagielski The main work has been done by SwTable::PrepareMerge(..) already.
85*b1cdbd2cSJim Jagielski 
86*b1cdbd2cSJim Jagielski @param rBoxes
87*b1cdbd2cSJim Jagielski the boxes to remove
88*b1cdbd2cSJim Jagielski 
89*b1cdbd2cSJim Jagielski @param pUndo
90*b1cdbd2cSJim Jagielski the undo object to notify, maybe empty
91*b1cdbd2cSJim Jagielski 
92*b1cdbd2cSJim Jagielski @return sal_True for compatibility reasons with OldMerge(..)
93*b1cdbd2cSJim Jagielski */
94*b1cdbd2cSJim Jagielski 
NewMerge(SwDoc * pDoc,const SwSelBoxes & rBoxes,const SwSelBoxes & rMerged,SwTableBox *,SwUndoTblMerge * pUndo)95*b1cdbd2cSJim Jagielski sal_Bool SwTable::NewMerge( SwDoc* pDoc, const SwSelBoxes& rBoxes,
96*b1cdbd2cSJim Jagielski      const SwSelBoxes& rMerged, SwTableBox*, SwUndoTblMerge* pUndo )
97*b1cdbd2cSJim Jagielski {
98*b1cdbd2cSJim Jagielski     if( pUndo )
99*b1cdbd2cSJim Jagielski 		pUndo->SetSelBoxes( rBoxes );
100*b1cdbd2cSJim Jagielski 	DeleteSel( pDoc, rBoxes, &rMerged, 0, sal_True, sal_True );
101*b1cdbd2cSJim Jagielski 
102*b1cdbd2cSJim Jagielski     CHECK_TABLE( *this )
103*b1cdbd2cSJim Jagielski     return sal_True;
104*b1cdbd2cSJim Jagielski }
105*b1cdbd2cSJim Jagielski 
106*b1cdbd2cSJim Jagielski /** lcl_CheckMinMax helps evaluating (horizontal) min/max of boxes
107*b1cdbd2cSJim Jagielski 
108*b1cdbd2cSJim Jagielski lcl_CheckMinMax(..) compares the left border and the right border
109*b1cdbd2cSJim Jagielski of a given cell with the given range and sets it accordingly.
110*b1cdbd2cSJim Jagielski 
111*b1cdbd2cSJim Jagielski @param rMin
112*b1cdbd2cSJim Jagielski will be decremented if necessary to the left border of the cell
113*b1cdbd2cSJim Jagielski 
114*b1cdbd2cSJim Jagielski @param rMax
115*b1cdbd2cSJim Jagielski will be incremented if necessary to the right border of the cell
116*b1cdbd2cSJim Jagielski 
117*b1cdbd2cSJim Jagielski @param rLine
118*b1cdbd2cSJim Jagielski the row (table line) of the interesting box
119*b1cdbd2cSJim Jagielski 
120*b1cdbd2cSJim Jagielski @param nCheck
121*b1cdbd2cSJim Jagielski the index of the box in the table box array of the given row
122*b1cdbd2cSJim Jagielski 
123*b1cdbd2cSJim Jagielski @param bSet
124*b1cdbd2cSJim Jagielski if bSet is false, rMin and rMax will be manipulated if necessary
125*b1cdbd2cSJim Jagielski if bSet is true, rMin and rMax will be set to the left and right border of the box
126*b1cdbd2cSJim Jagielski 
127*b1cdbd2cSJim Jagielski */
128*b1cdbd2cSJim Jagielski 
lcl_CheckMinMax(long & rMin,long & rMax,const SwTableLine & rLine,sal_uInt16 nCheck,bool bSet)129*b1cdbd2cSJim Jagielski void lcl_CheckMinMax( long& rMin, long& rMax, const SwTableLine& rLine, sal_uInt16 nCheck, bool bSet )
130*b1cdbd2cSJim Jagielski {
131*b1cdbd2cSJim Jagielski     ++nCheck;
132*b1cdbd2cSJim Jagielski     if( rLine.GetTabBoxes().Count() < nCheck )
133*b1cdbd2cSJim Jagielski     {   // robust
134*b1cdbd2cSJim Jagielski         ASSERT( false, "Box out of table line" );
135*b1cdbd2cSJim Jagielski         nCheck = rLine.GetTabBoxes().Count();
136*b1cdbd2cSJim Jagielski     }
137*b1cdbd2cSJim Jagielski 
138*b1cdbd2cSJim Jagielski     long nNew = 0; // will be the right border of the current box
139*b1cdbd2cSJim Jagielski     long nWidth = 0; // the width of the current box
140*b1cdbd2cSJim Jagielski     for( sal_uInt16 nCurrBox = 0; nCurrBox < nCheck; ++nCurrBox )
141*b1cdbd2cSJim Jagielski     {
142*b1cdbd2cSJim Jagielski         SwTableBox* pBox = rLine.GetTabBoxes()[nCurrBox];
143*b1cdbd2cSJim Jagielski         ASSERT( pBox, "Missing table box" );
144*b1cdbd2cSJim Jagielski         nWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
145*b1cdbd2cSJim Jagielski         nNew += nWidth;
146*b1cdbd2cSJim Jagielski     }
147*b1cdbd2cSJim Jagielski     // nNew is the right border of the wished box
148*b1cdbd2cSJim Jagielski     if( bSet || nNew > rMax )
149*b1cdbd2cSJim Jagielski         rMax = nNew;
150*b1cdbd2cSJim Jagielski     nNew -= nWidth; // nNew becomes the left border of the wished box
151*b1cdbd2cSJim Jagielski     if( bSet || nNew < rMin )
152*b1cdbd2cSJim Jagielski         rMin = nNew;
153*b1cdbd2cSJim Jagielski }
154*b1cdbd2cSJim Jagielski 
155*b1cdbd2cSJim Jagielski /** lcl_Box2LeftBorder(..) delivers the left (logical) border of a table box
156*b1cdbd2cSJim Jagielski 
157*b1cdbd2cSJim Jagielski The left logical border of a table box is the sum of the cell width before this
158*b1cdbd2cSJim Jagielski box.
159*b1cdbd2cSJim Jagielski 
160*b1cdbd2cSJim Jagielski @param rBox
161*b1cdbd2cSJim Jagielski is the requested table box
162*b1cdbd2cSJim Jagielski 
163*b1cdbd2cSJim Jagielski @return is the left logical border (long, even it cannot be negative)
164*b1cdbd2cSJim Jagielski 
165*b1cdbd2cSJim Jagielski */
166*b1cdbd2cSJim Jagielski 
lcl_Box2LeftBorder(const SwTableBox & rBox)167*b1cdbd2cSJim Jagielski long lcl_Box2LeftBorder( const SwTableBox& rBox )
168*b1cdbd2cSJim Jagielski {
169*b1cdbd2cSJim Jagielski     if( !rBox.GetUpper() )
170*b1cdbd2cSJim Jagielski         return 0;
171*b1cdbd2cSJim Jagielski     long nLeft = 0;
172*b1cdbd2cSJim Jagielski     const SwTableLine &rLine = *rBox.GetUpper();
173*b1cdbd2cSJim Jagielski     sal_uInt16 nCount = rLine.GetTabBoxes().Count();
174*b1cdbd2cSJim Jagielski     for( sal_uInt16 nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
175*b1cdbd2cSJim Jagielski     {
176*b1cdbd2cSJim Jagielski         SwTableBox* pBox = rLine.GetTabBoxes()[nCurrBox];
177*b1cdbd2cSJim Jagielski         ASSERT( pBox, "Missing table box" );
178*b1cdbd2cSJim Jagielski         if( pBox == &rBox )
179*b1cdbd2cSJim Jagielski             return nLeft;
180*b1cdbd2cSJim Jagielski         nLeft += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
181*b1cdbd2cSJim Jagielski     }
182*b1cdbd2cSJim Jagielski     ASSERT( false, "Box not found in own upper?" );
183*b1cdbd2cSJim Jagielski     return nLeft;
184*b1cdbd2cSJim Jagielski }
185*b1cdbd2cSJim Jagielski 
186*b1cdbd2cSJim Jagielski /** lcl_LeftBorder2Box delivers the box to a given left border
187*b1cdbd2cSJim Jagielski 
188*b1cdbd2cSJim Jagielski It's used to find the master/follow table boxes in previous/next rows.
189*b1cdbd2cSJim Jagielski Don't call this function to check if there is such a box,
190*b1cdbd2cSJim Jagielski call it if you know there has to be such box.
191*b1cdbd2cSJim Jagielski 
192*b1cdbd2cSJim Jagielski @param nLeft
193*b1cdbd2cSJim Jagielski the left border (logical x-value) of the demanded box
194*b1cdbd2cSJim Jagielski 
195*b1cdbd2cSJim Jagielski @param rLine
196*b1cdbd2cSJim Jagielski the row (table line) to be scanned
197*b1cdbd2cSJim Jagielski 
198*b1cdbd2cSJim Jagielski @return a pointer to the table box inside the given row with the wished left border
199*b1cdbd2cSJim Jagielski 
200*b1cdbd2cSJim Jagielski */
201*b1cdbd2cSJim Jagielski 
lcl_LeftBorder2Box(long nLeft,const SwTableLine * pLine)202*b1cdbd2cSJim Jagielski SwTableBox* lcl_LeftBorder2Box( long nLeft, const SwTableLine* pLine )
203*b1cdbd2cSJim Jagielski {
204*b1cdbd2cSJim Jagielski     if( !pLine )
205*b1cdbd2cSJim Jagielski         return 0;
206*b1cdbd2cSJim Jagielski     long nCurrLeft = 0;
207*b1cdbd2cSJim Jagielski     sal_uInt16 nCount = pLine->GetTabBoxes().Count();
208*b1cdbd2cSJim Jagielski     for( sal_uInt16 nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
209*b1cdbd2cSJim Jagielski     {
210*b1cdbd2cSJim Jagielski         SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
211*b1cdbd2cSJim Jagielski         ASSERT( pBox, "Missing table box" );
212*b1cdbd2cSJim Jagielski         if( nCurrLeft >= nLeft && pBox->GetFrmFmt()->GetFrmSize().GetWidth() )
213*b1cdbd2cSJim Jagielski         {
214*b1cdbd2cSJim Jagielski             ASSERT( nCurrLeft == nLeft, "Wrong box found" );
215*b1cdbd2cSJim Jagielski             return pBox;
216*b1cdbd2cSJim Jagielski         }
217*b1cdbd2cSJim Jagielski         nCurrLeft += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
218*b1cdbd2cSJim Jagielski     }
219*b1cdbd2cSJim Jagielski     ASSERT( false, "Didn't found wished box" );
220*b1cdbd2cSJim Jagielski     return 0;
221*b1cdbd2cSJim Jagielski }
222*b1cdbd2cSJim Jagielski 
223*b1cdbd2cSJim Jagielski /** lcl_ChangeRowSpan corrects row span after insertion/deletion of rows
224*b1cdbd2cSJim Jagielski 
225*b1cdbd2cSJim Jagielski lcl_ChangeRowSpan(..) has to be called after an insertion or deletion of rows
226*b1cdbd2cSJim Jagielski to adjust the row spans of previous rows accordingly.
227*b1cdbd2cSJim Jagielski If rows are deleted, the previous rows with row spans into the deleted area
228*b1cdbd2cSJim Jagielski have to be decremented by the number of _overlapped_ inserted rows.
229*b1cdbd2cSJim Jagielski If rows are inserted, the previous rows with row span into the inserted area
230*b1cdbd2cSJim Jagielski have to be incremented by the number of inserted rows.
231*b1cdbd2cSJim Jagielski For those row spans which ends exactly above the inserted area it has to be
232*b1cdbd2cSJim Jagielski decided by the parameter bSingle if they have to be expanded or not.
233*b1cdbd2cSJim Jagielski 
234*b1cdbd2cSJim Jagielski @param rTable
235*b1cdbd2cSJim Jagielski the table to manipulate (has to be a new model table)
236*b1cdbd2cSJim Jagielski 
237*b1cdbd2cSJim Jagielski @param nDiff
238*b1cdbd2cSJim Jagielski the number of rows which has been inserted (nDiff > 0) or deleted (nDiff < 0)
239*b1cdbd2cSJim Jagielski 
240*b1cdbd2cSJim Jagielski @param nRowIdx
241*b1cdbd2cSJim Jagielski the index of the first row which has to be checked
242*b1cdbd2cSJim Jagielski 
243*b1cdbd2cSJim Jagielski @param bSingle
244*b1cdbd2cSJim Jagielski true if the new inserted row should not extend row spans which ends in the row above
245*b1cdbd2cSJim Jagielski this is for rows inserted by UI "insert row"
246*b1cdbd2cSJim Jagielski false if all cells of an inserted row has to be overlapped by the previous row
247*b1cdbd2cSJim Jagielski this is for rows inserted by "split row"
248*b1cdbd2cSJim Jagielski false is also needed for deleted rows
249*b1cdbd2cSJim Jagielski 
250*b1cdbd2cSJim Jagielski */
251*b1cdbd2cSJim Jagielski 
lcl_ChangeRowSpan(const SwTable & rTable,const long nDiff,sal_uInt16 nRowIdx,const bool bSingle)252*b1cdbd2cSJim Jagielski void lcl_ChangeRowSpan( const SwTable& rTable, const long nDiff,
253*b1cdbd2cSJim Jagielski                         sal_uInt16 nRowIdx, const bool bSingle )
254*b1cdbd2cSJim Jagielski {
255*b1cdbd2cSJim Jagielski     if( !nDiff || nRowIdx >= rTable.GetTabLines().Count() )
256*b1cdbd2cSJim Jagielski         return;
257*b1cdbd2cSJim Jagielski     ASSERT( !bSingle || nDiff > 0, "Don't set bSingle when deleting lines!" );
258*b1cdbd2cSJim Jagielski     bool bGoOn;
259*b1cdbd2cSJim Jagielski     // nDistance is the distance between the current row and the critical row,
260*b1cdbd2cSJim Jagielski     // e.g. the deleted rows or the inserted rows.
261*b1cdbd2cSJim Jagielski     // If the row span is lower than the distance there is nothing to do
262*b1cdbd2cSJim Jagielski     // because the row span ends before the critical area.
263*b1cdbd2cSJim Jagielski     // When the inserted rows should not be overlapped by row spans which ends
264*b1cdbd2cSJim Jagielski     // exactly in the row above, the trick is to start with a distance of 1.
265*b1cdbd2cSJim Jagielski     long nDistance = bSingle ? 1 : 0;
266*b1cdbd2cSJim Jagielski     do
267*b1cdbd2cSJim Jagielski     {
268*b1cdbd2cSJim Jagielski         bGoOn = false; // will be set to true if we found a non-master cell
269*b1cdbd2cSJim Jagielski         // which has to be manipulated => we have to chekc the previous row, too.
270*b1cdbd2cSJim Jagielski         const SwTableLine* pLine = rTable.GetTabLines()[ nRowIdx ];
271*b1cdbd2cSJim Jagielski         sal_uInt16 nBoxCount = pLine->GetTabBoxes().Count();
272*b1cdbd2cSJim Jagielski         for( sal_uInt16 nCurrBox = 0; nCurrBox < nBoxCount; ++nCurrBox )
273*b1cdbd2cSJim Jagielski         {
274*b1cdbd2cSJim Jagielski             long nRowSpan = pLine->GetTabBoxes()[nCurrBox]->getRowSpan();
275*b1cdbd2cSJim Jagielski             long nAbsSpan = nRowSpan > 0 ? nRowSpan : -nRowSpan;
276*b1cdbd2cSJim Jagielski             // Check if the last overlapped cell is above or below
277*b1cdbd2cSJim Jagielski             // the critical area
278*b1cdbd2cSJim Jagielski             if( nAbsSpan > nDistance )
279*b1cdbd2cSJim Jagielski             {
280*b1cdbd2cSJim Jagielski                 if( nDiff > 0 )
281*b1cdbd2cSJim Jagielski                 {
282*b1cdbd2cSJim Jagielski                     if( nRowSpan > 0 )
283*b1cdbd2cSJim Jagielski                         nRowSpan += nDiff; // increment row span of master cell
284*b1cdbd2cSJim Jagielski                     else
285*b1cdbd2cSJim Jagielski                     {
286*b1cdbd2cSJim Jagielski                         nRowSpan -= nDiff; // increment row span of non-master cell
287*b1cdbd2cSJim Jagielski                         bGoOn = true;
288*b1cdbd2cSJim Jagielski                     }
289*b1cdbd2cSJim Jagielski                 }
290*b1cdbd2cSJim Jagielski                 else
291*b1cdbd2cSJim Jagielski                 {
292*b1cdbd2cSJim Jagielski                     if( nRowSpan > 0 )
293*b1cdbd2cSJim Jagielski                     {   // A master cell
294*b1cdbd2cSJim Jagielski                          // end of row span behind the deleted area ..
295*b1cdbd2cSJim Jagielski                         if( nRowSpan - nDistance > -nDiff )
296*b1cdbd2cSJim Jagielski                             nRowSpan += nDiff;
297*b1cdbd2cSJim Jagielski                         else // .. or inside the deleted area
298*b1cdbd2cSJim Jagielski                             nRowSpan = nDistance + 1;
299*b1cdbd2cSJim Jagielski                     }
300*b1cdbd2cSJim Jagielski                     else
301*b1cdbd2cSJim Jagielski                     {   // Same for a non-master cell
302*b1cdbd2cSJim Jagielski                         if( nRowSpan + nDistance < nDiff )
303*b1cdbd2cSJim Jagielski                             nRowSpan -= nDiff;
304*b1cdbd2cSJim Jagielski                         else
305*b1cdbd2cSJim Jagielski                             nRowSpan = -nDistance - 1;
306*b1cdbd2cSJim Jagielski                         bGoOn = true; // We have to continue
307*b1cdbd2cSJim Jagielski                     }
308*b1cdbd2cSJim Jagielski                 }
309*b1cdbd2cSJim Jagielski                 pLine->GetTabBoxes()[ nCurrBox ]->setRowSpan( nRowSpan );
310*b1cdbd2cSJim Jagielski             }
311*b1cdbd2cSJim Jagielski         }
312*b1cdbd2cSJim Jagielski         ++nDistance;
313*b1cdbd2cSJim Jagielski         if( nRowIdx )
314*b1cdbd2cSJim Jagielski             --nRowIdx;
315*b1cdbd2cSJim Jagielski         else
316*b1cdbd2cSJim Jagielski             bGoOn = false; //robust
317*b1cdbd2cSJim Jagielski     } while( bGoOn );
318*b1cdbd2cSJim Jagielski }
319*b1cdbd2cSJim Jagielski 
320*b1cdbd2cSJim Jagielski /** CollectBoxSelection(..) create a rectangulare selection based on the given SwPaM
321*b1cdbd2cSJim Jagielski     and prepares the selected cells for merging
322*b1cdbd2cSJim Jagielski */
323*b1cdbd2cSJim Jagielski 
CollectBoxSelection(const SwPaM & rPam) const324*b1cdbd2cSJim Jagielski SwBoxSelection* SwTable::CollectBoxSelection( const SwPaM& rPam ) const
325*b1cdbd2cSJim Jagielski {
326*b1cdbd2cSJim Jagielski     ASSERT( bNewModel, "Don't call me for old tables" );
327*b1cdbd2cSJim Jagielski     if( !aLines.Count() )
328*b1cdbd2cSJim Jagielski         return 0;
329*b1cdbd2cSJim Jagielski     const SwNode* pStartNd = rPam.Start()->nNode.GetNode().FindTableBoxStartNode();
330*b1cdbd2cSJim Jagielski     const SwNode* pEndNd = rPam.End()->nNode.GetNode().FindTableBoxStartNode();
331*b1cdbd2cSJim Jagielski     if( !pStartNd || !pEndNd || pStartNd == pEndNd )
332*b1cdbd2cSJim Jagielski         return 0;
333*b1cdbd2cSJim Jagielski 
334*b1cdbd2cSJim Jagielski     sal_uInt16 nLines = aLines.Count();
335*b1cdbd2cSJim Jagielski     sal_uInt16 nTop = 0, nBottom = 0;
336*b1cdbd2cSJim Jagielski     long nMin = 0, nMax = 0;
337*b1cdbd2cSJim Jagielski     int nFound = 0;
338*b1cdbd2cSJim Jagielski     for( sal_uInt16 nRow = 0; nFound < 2 && nRow < nLines; ++nRow )
339*b1cdbd2cSJim Jagielski     {
340*b1cdbd2cSJim Jagielski         SwTableLine* pLine = aLines[nRow];
341*b1cdbd2cSJim Jagielski         ASSERT( pLine, "Missing table line" );
342*b1cdbd2cSJim Jagielski         sal_uInt16 nCols = pLine->GetTabBoxes().Count();
343*b1cdbd2cSJim Jagielski         for( sal_uInt16 nCol = 0; nCol < nCols; ++nCol )
344*b1cdbd2cSJim Jagielski         {
345*b1cdbd2cSJim Jagielski             SwTableBox* pBox = pLine->GetTabBoxes()[nCol];
346*b1cdbd2cSJim Jagielski             ASSERT( pBox, "Missing table box" );
347*b1cdbd2cSJim Jagielski             if( nFound )
348*b1cdbd2cSJim Jagielski             {
349*b1cdbd2cSJim Jagielski                 if( pBox->GetSttNd() == pEndNd )
350*b1cdbd2cSJim Jagielski                 {
351*b1cdbd2cSJim Jagielski                     nBottom = nRow;
352*b1cdbd2cSJim Jagielski                     lcl_CheckMinMax( nMin, nMax, *pLine, nCol, false );
353*b1cdbd2cSJim Jagielski                     ++nFound;
354*b1cdbd2cSJim Jagielski                     break;
355*b1cdbd2cSJim Jagielski                 }
356*b1cdbd2cSJim Jagielski             }
357*b1cdbd2cSJim Jagielski             else if( pBox->GetSttNd() == pStartNd )
358*b1cdbd2cSJim Jagielski             {
359*b1cdbd2cSJim Jagielski                 nTop = nRow;
360*b1cdbd2cSJim Jagielski                 lcl_CheckMinMax( nMin, nMax, *pLine, nCol, true );
361*b1cdbd2cSJim Jagielski                 ++nFound;
362*b1cdbd2cSJim Jagielski             }
363*b1cdbd2cSJim Jagielski         }
364*b1cdbd2cSJim Jagielski     }
365*b1cdbd2cSJim Jagielski     if( nFound < 2 )
366*b1cdbd2cSJim Jagielski         return 0;
367*b1cdbd2cSJim Jagielski 
368*b1cdbd2cSJim Jagielski     bool bOkay = true;
369*b1cdbd2cSJim Jagielski     long nMid = ( nMin + nMax ) / 2;
370*b1cdbd2cSJim Jagielski 
371*b1cdbd2cSJim Jagielski     SwBoxSelection* pRet = new SwBoxSelection();
372*b1cdbd2cSJim Jagielski     std::list< std::pair< SwTableBox*, long > > aNewWidthList;
373*b1cdbd2cSJim Jagielski     sal_uInt16 nCheckBottom = nBottom;
374*b1cdbd2cSJim Jagielski     long nLeftSpan = 0;
375*b1cdbd2cSJim Jagielski     long nRightSpan = 0;
376*b1cdbd2cSJim Jagielski     long nLeftSpanCnt = 0;
377*b1cdbd2cSJim Jagielski     long nRightSpanCnt = 0;
378*b1cdbd2cSJim Jagielski     for( sal_uInt16 nRow = nTop; nRow <= nBottom && bOkay; ++nRow )
379*b1cdbd2cSJim Jagielski     {
380*b1cdbd2cSJim Jagielski         SwTableLine* pLine = aLines[nRow];
381*b1cdbd2cSJim Jagielski         ASSERT( pLine, "Missing table line" );
382*b1cdbd2cSJim Jagielski         SwSelBoxes *pBoxes = new SwSelBoxes();
383*b1cdbd2cSJim Jagielski         long nLeft = 0;
384*b1cdbd2cSJim Jagielski         long nRight = 0;
385*b1cdbd2cSJim Jagielski         long nRowSpan = 1;
386*b1cdbd2cSJim Jagielski         sal_uInt16 nCount = pLine->GetTabBoxes().Count();
387*b1cdbd2cSJim Jagielski         for( sal_uInt16 nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
388*b1cdbd2cSJim Jagielski         {
389*b1cdbd2cSJim Jagielski             SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
390*b1cdbd2cSJim Jagielski             ASSERT( pBox, "Missing table box" );
391*b1cdbd2cSJim Jagielski             nLeft = nRight;
392*b1cdbd2cSJim Jagielski             nRight += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
393*b1cdbd2cSJim Jagielski             nRowSpan = pBox->getRowSpan();
394*b1cdbd2cSJim Jagielski             if( nRight <= nMin )
395*b1cdbd2cSJim Jagielski             {
396*b1cdbd2cSJim Jagielski                 if( nRight == nMin && nLeftSpanCnt )
397*b1cdbd2cSJim Jagielski                     bOkay = false;
398*b1cdbd2cSJim Jagielski                 continue;
399*b1cdbd2cSJim Jagielski             }
400*b1cdbd2cSJim Jagielski             SwTableBox* pInnerBox = 0;
401*b1cdbd2cSJim Jagielski             SwTableBox* pLeftBox = 0;
402*b1cdbd2cSJim Jagielski             SwTableBox* pRightBox = 0;
403*b1cdbd2cSJim Jagielski             long nDiff = 0;
404*b1cdbd2cSJim Jagielski             long nDiff2 = 0;
405*b1cdbd2cSJim Jagielski             if( nLeft < nMin )
406*b1cdbd2cSJim Jagielski             {
407*b1cdbd2cSJim Jagielski                 if( nRight >= nMid || nRight + nLeft >= nMin + nMin )
408*b1cdbd2cSJim Jagielski                 {
409*b1cdbd2cSJim Jagielski                     if( nCurrBox )
410*b1cdbd2cSJim Jagielski                     {
411*b1cdbd2cSJim Jagielski                         pBoxes->Insert( pBox );
412*b1cdbd2cSJim Jagielski                         pInnerBox = pBox;
413*b1cdbd2cSJim Jagielski                         pLeftBox = pLine->GetTabBoxes()[nCurrBox-1];
414*b1cdbd2cSJim Jagielski                         nDiff = nMin - nLeft;
415*b1cdbd2cSJim Jagielski                         if( nRight > nMax )
416*b1cdbd2cSJim Jagielski                         {
417*b1cdbd2cSJim Jagielski                             if( nCurrBox+1 < nCount )
418*b1cdbd2cSJim Jagielski                             {
419*b1cdbd2cSJim Jagielski                                 pRightBox = pLine->GetTabBoxes()[nCurrBox+1];
420*b1cdbd2cSJim Jagielski                                 nDiff2 = nRight - nMax;
421*b1cdbd2cSJim Jagielski                             }
422*b1cdbd2cSJim Jagielski                             else
423*b1cdbd2cSJim Jagielski                                 bOkay = false;
424*b1cdbd2cSJim Jagielski                         }
425*b1cdbd2cSJim Jagielski                         else if( nRightSpanCnt && nRight == nMax )
426*b1cdbd2cSJim Jagielski                             bOkay = false;
427*b1cdbd2cSJim Jagielski                     }
428*b1cdbd2cSJim Jagielski                     else
429*b1cdbd2cSJim Jagielski                         bOkay = false;
430*b1cdbd2cSJim Jagielski                 }
431*b1cdbd2cSJim Jagielski                 else if( nCurrBox+1 < nCount )
432*b1cdbd2cSJim Jagielski                 {
433*b1cdbd2cSJim Jagielski                     pLeftBox = pBox;
434*b1cdbd2cSJim Jagielski                     pInnerBox = pLine->GetTabBoxes()[nCurrBox+1];
435*b1cdbd2cSJim Jagielski                     nDiff = nMin - nRight;
436*b1cdbd2cSJim Jagielski                 }
437*b1cdbd2cSJim Jagielski                 else
438*b1cdbd2cSJim Jagielski                     bOkay = false;
439*b1cdbd2cSJim Jagielski             }
440*b1cdbd2cSJim Jagielski             else if( nRight <= nMax )
441*b1cdbd2cSJim Jagielski             {
442*b1cdbd2cSJim Jagielski                 pBoxes->Insert( pBox );
443*b1cdbd2cSJim Jagielski                 if( nRow == nTop && nRowSpan < 0 )
444*b1cdbd2cSJim Jagielski                 {
445*b1cdbd2cSJim Jagielski                     bOkay = false;
446*b1cdbd2cSJim Jagielski                     break;
447*b1cdbd2cSJim Jagielski                 }
448*b1cdbd2cSJim Jagielski                 if( nRowSpan > 1 && nRow + nRowSpan - 1 > nBottom )
449*b1cdbd2cSJim Jagielski                     nBottom = nRow + (sal_uInt16)nRowSpan - 1;
450*b1cdbd2cSJim Jagielski                 if( nRowSpan < -1 && nRow - nRowSpan - 1 > nBottom )
451*b1cdbd2cSJim Jagielski                     nBottom = (sal_uInt16)(nRow - nRowSpan - 1);
452*b1cdbd2cSJim Jagielski                 if( nRightSpanCnt && nRight == nMax )
453*b1cdbd2cSJim Jagielski                     bOkay = false;
454*b1cdbd2cSJim Jagielski             }
455*b1cdbd2cSJim Jagielski             else if( nLeft < nMax )
456*b1cdbd2cSJim Jagielski             {
457*b1cdbd2cSJim Jagielski                 if( nLeft <= nMid || nRight + nLeft <= nMax )
458*b1cdbd2cSJim Jagielski                 {
459*b1cdbd2cSJim Jagielski                     if( nCurrBox+1 < nCount )
460*b1cdbd2cSJim Jagielski                     {
461*b1cdbd2cSJim Jagielski                         pBoxes->Insert( pBox );
462*b1cdbd2cSJim Jagielski                         pInnerBox = pBox;
463*b1cdbd2cSJim Jagielski                         pRightBox = pLine->GetTabBoxes()[nCurrBox+1];
464*b1cdbd2cSJim Jagielski                         nDiff = nRight - nMax;
465*b1cdbd2cSJim Jagielski                     }
466*b1cdbd2cSJim Jagielski                     else
467*b1cdbd2cSJim Jagielski                         bOkay = false;
468*b1cdbd2cSJim Jagielski                 }
469*b1cdbd2cSJim Jagielski                 else if( nCurrBox )
470*b1cdbd2cSJim Jagielski                 {
471*b1cdbd2cSJim Jagielski                     pRightBox = pBox;
472*b1cdbd2cSJim Jagielski                     pInnerBox = pLine->GetTabBoxes()[nCurrBox-1];
473*b1cdbd2cSJim Jagielski                     nDiff = nLeft - nMax;
474*b1cdbd2cSJim Jagielski                 }
475*b1cdbd2cSJim Jagielski                 else
476*b1cdbd2cSJim Jagielski                     bOkay = false;
477*b1cdbd2cSJim Jagielski             }
478*b1cdbd2cSJim Jagielski             else
479*b1cdbd2cSJim Jagielski                 break;
480*b1cdbd2cSJim Jagielski             if( pInnerBox )
481*b1cdbd2cSJim Jagielski             {
482*b1cdbd2cSJim Jagielski                 if( nRow == nBottom )
483*b1cdbd2cSJim Jagielski                 {
484*b1cdbd2cSJim Jagielski                     long nTmpSpan = pInnerBox->getRowSpan();
485*b1cdbd2cSJim Jagielski                     if( nTmpSpan > 1 )
486*b1cdbd2cSJim Jagielski                         nBottom += (sal_uInt16)nTmpSpan - 1;
487*b1cdbd2cSJim Jagielski                     else if( nTmpSpan < -1 )
488*b1cdbd2cSJim Jagielski                         nBottom = (sal_uInt16)( nBottom - nTmpSpan - 1 );
489*b1cdbd2cSJim Jagielski                 }
490*b1cdbd2cSJim Jagielski                 SwTableBox* pOuterBox = pLeftBox;
491*b1cdbd2cSJim Jagielski                 do
492*b1cdbd2cSJim Jagielski                 {
493*b1cdbd2cSJim Jagielski                     if( pOuterBox )
494*b1cdbd2cSJim Jagielski                     {
495*b1cdbd2cSJim Jagielski                         long nOutSpan = pOuterBox->getRowSpan();
496*b1cdbd2cSJim Jagielski                         if( nOutSpan != 1 )
497*b1cdbd2cSJim Jagielski                         {
498*b1cdbd2cSJim Jagielski                             sal_uInt16 nCheck = nRow;
499*b1cdbd2cSJim Jagielski                             if( nOutSpan < 0 )
500*b1cdbd2cSJim Jagielski                             {
501*b1cdbd2cSJim Jagielski                                 const SwTableBox& rBox =
502*b1cdbd2cSJim Jagielski                                     pOuterBox->FindStartOfRowSpan( *this, USHRT_MAX );
503*b1cdbd2cSJim Jagielski                                 nOutSpan = rBox.getRowSpan();
504*b1cdbd2cSJim Jagielski                                 const SwTableLine* pTmpL = rBox.GetUpper();
505*b1cdbd2cSJim Jagielski                                 nCheck = GetTabLines().C40_GETPOS( SwTableLine, pTmpL );
506*b1cdbd2cSJim Jagielski                                 if( nCheck < nTop )
507*b1cdbd2cSJim Jagielski                                     bOkay = false;
508*b1cdbd2cSJim Jagielski                                 if( pOuterBox == pLeftBox )
509*b1cdbd2cSJim Jagielski                                 {
510*b1cdbd2cSJim Jagielski                                     if( !nLeftSpanCnt || nMin - nDiff != nLeftSpan )
511*b1cdbd2cSJim Jagielski                                         bOkay = false;
512*b1cdbd2cSJim Jagielski                                 }
513*b1cdbd2cSJim Jagielski                                 else
514*b1cdbd2cSJim Jagielski                                 {
515*b1cdbd2cSJim Jagielski                                     if( !nRightSpanCnt || nMax + nDiff != nRightSpan )
516*b1cdbd2cSJim Jagielski                                         bOkay = false;
517*b1cdbd2cSJim Jagielski                                 }
518*b1cdbd2cSJim Jagielski                             }
519*b1cdbd2cSJim Jagielski                             else
520*b1cdbd2cSJim Jagielski                             {
521*b1cdbd2cSJim Jagielski                                 if( pOuterBox == pLeftBox )
522*b1cdbd2cSJim Jagielski                                 {
523*b1cdbd2cSJim Jagielski                                     if( nLeftSpanCnt )
524*b1cdbd2cSJim Jagielski                                         bOkay = false;
525*b1cdbd2cSJim Jagielski                                     nLeftSpan = nMin - nDiff;
526*b1cdbd2cSJim Jagielski                                     nLeftSpanCnt = nOutSpan;
527*b1cdbd2cSJim Jagielski                                 }
528*b1cdbd2cSJim Jagielski                                 else
529*b1cdbd2cSJim Jagielski                                 {
530*b1cdbd2cSJim Jagielski                                     if( nRightSpanCnt )
531*b1cdbd2cSJim Jagielski                                         bOkay = false;
532*b1cdbd2cSJim Jagielski                                     nRightSpan = nMax + nDiff;
533*b1cdbd2cSJim Jagielski                                     nRightSpanCnt = nOutSpan;
534*b1cdbd2cSJim Jagielski                                 }
535*b1cdbd2cSJim Jagielski                             }
536*b1cdbd2cSJim Jagielski                             nCheck += (sal_uInt16)nOutSpan - 1;
537*b1cdbd2cSJim Jagielski                             if( nCheck > nCheckBottom )
538*b1cdbd2cSJim Jagielski                                 nCheckBottom = nCheck;
539*b1cdbd2cSJim Jagielski                         }
540*b1cdbd2cSJim Jagielski                         else if( ( nLeftSpanCnt && pLeftBox == pOuterBox ) ||
541*b1cdbd2cSJim Jagielski                             ( nRightSpanCnt && pRightBox == pOuterBox ) )
542*b1cdbd2cSJim Jagielski                             bOkay = false;
543*b1cdbd2cSJim Jagielski                         std::pair< SwTableBox*, long > aTmp;
544*b1cdbd2cSJim Jagielski                         aTmp.first = pInnerBox;
545*b1cdbd2cSJim Jagielski                         aTmp.second = -nDiff;
546*b1cdbd2cSJim Jagielski                         aNewWidthList.push_back( aTmp );
547*b1cdbd2cSJim Jagielski                         aTmp.first = pOuterBox;
548*b1cdbd2cSJim Jagielski                         aTmp.second = nDiff;
549*b1cdbd2cSJim Jagielski                         aNewWidthList.push_back( aTmp );
550*b1cdbd2cSJim Jagielski                     }
551*b1cdbd2cSJim Jagielski 					pOuterBox = pOuterBox == pRightBox ? 0 : pRightBox;
552*b1cdbd2cSJim Jagielski                     if( nDiff2 )
553*b1cdbd2cSJim Jagielski                         nDiff = nDiff2;
554*b1cdbd2cSJim Jagielski                 } while( pOuterBox );
555*b1cdbd2cSJim Jagielski             }
556*b1cdbd2cSJim Jagielski         }
557*b1cdbd2cSJim Jagielski         if( nLeftSpanCnt )
558*b1cdbd2cSJim Jagielski             --nLeftSpanCnt;
559*b1cdbd2cSJim Jagielski         if( nRightSpanCnt )
560*b1cdbd2cSJim Jagielski             --nRightSpanCnt;
561*b1cdbd2cSJim Jagielski         pRet->insertBoxes( pBoxes );
562*b1cdbd2cSJim Jagielski     }
563*b1cdbd2cSJim Jagielski     pRet->mnMergeWidth = nMax - nMin;
564*b1cdbd2cSJim Jagielski     if( nCheckBottom > nBottom )
565*b1cdbd2cSJim Jagielski         bOkay = false;
566*b1cdbd2cSJim Jagielski     if( bOkay )
567*b1cdbd2cSJim Jagielski     {
568*b1cdbd2cSJim Jagielski         std::list< std::pair< SwTableBox*, long > >::iterator
569*b1cdbd2cSJim Jagielski             pCurr = aNewWidthList.begin();
570*b1cdbd2cSJim Jagielski         while( pCurr != aNewWidthList.end() )
571*b1cdbd2cSJim Jagielski         {
572*b1cdbd2cSJim Jagielski             SwFrmFmt* pFmt = pCurr->first->ClaimFrmFmt();
573*b1cdbd2cSJim Jagielski             long nNewWidth = pFmt->GetFrmSize().GetWidth() + pCurr->second;
574*b1cdbd2cSJim Jagielski             pFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nNewWidth, 0 ) );
575*b1cdbd2cSJim Jagielski             ++pCurr;
576*b1cdbd2cSJim Jagielski         }
577*b1cdbd2cSJim Jagielski     }
578*b1cdbd2cSJim Jagielski     else
579*b1cdbd2cSJim Jagielski     {
580*b1cdbd2cSJim Jagielski         delete pRet;
581*b1cdbd2cSJim Jagielski         pRet = 0;
582*b1cdbd2cSJim Jagielski     }
583*b1cdbd2cSJim Jagielski     return pRet;
584*b1cdbd2cSJim Jagielski }
585*b1cdbd2cSJim Jagielski 
586*b1cdbd2cSJim Jagielski /** lcl_InvalidateCellFrm(..) invalidates all layout representations of a given cell
587*b1cdbd2cSJim Jagielski     to initiate a reformatting
588*b1cdbd2cSJim Jagielski */
589*b1cdbd2cSJim Jagielski 
lcl_InvalidateCellFrm(const SwTableBox & rBox)590*b1cdbd2cSJim Jagielski void lcl_InvalidateCellFrm( const SwTableBox& rBox )
591*b1cdbd2cSJim Jagielski {
592*b1cdbd2cSJim Jagielski 	SwIterator<SwCellFrm,SwFmt> aIter( *rBox.GetFrmFmt() );
593*b1cdbd2cSJim Jagielski 	for( SwCellFrm* pCell = aIter.First(); pCell; pCell = aIter.Next() )
594*b1cdbd2cSJim Jagielski 	{
595*b1cdbd2cSJim Jagielski 		if( pCell->GetTabBox() == &rBox )
596*b1cdbd2cSJim Jagielski         {
597*b1cdbd2cSJim Jagielski 			pCell->InvalidateSize();
598*b1cdbd2cSJim Jagielski             SwFrm* pLower = pCell->GetLower();
599*b1cdbd2cSJim Jagielski             if( pLower )
600*b1cdbd2cSJim Jagielski                 pLower->_InvalidateSize();
601*b1cdbd2cSJim Jagielski         }
602*b1cdbd2cSJim Jagielski     }
603*b1cdbd2cSJim Jagielski }
604*b1cdbd2cSJim Jagielski 
605*b1cdbd2cSJim Jagielski /** lcl_InsertPosition(..) evaluates the insert positions in every table line,
606*b1cdbd2cSJim Jagielski     when a selection of cells is given and returns the average cell widths
607*b1cdbd2cSJim Jagielski */
608*b1cdbd2cSJim Jagielski 
lcl_InsertPosition(SwTable & rTable,std::vector<sal_uInt16> & rInsPos,const SwSelBoxes & rBoxes,sal_Bool bBehind)609*b1cdbd2cSJim Jagielski long lcl_InsertPosition( SwTable &rTable, std::vector<sal_uInt16>& rInsPos,
610*b1cdbd2cSJim Jagielski     const SwSelBoxes& rBoxes, sal_Bool bBehind )
611*b1cdbd2cSJim Jagielski {
612*b1cdbd2cSJim Jagielski     sal_Int32 nAddWidth = 0;
613*b1cdbd2cSJim Jagielski     long nCount = 0;
614*b1cdbd2cSJim Jagielski     for( sal_uInt16 j = 0; j < rBoxes.Count(); ++j )
615*b1cdbd2cSJim Jagielski     {
616*b1cdbd2cSJim Jagielski         SwTableBox *pBox = rBoxes[j];
617*b1cdbd2cSJim Jagielski         SwTableLine* pLine = pBox->GetUpper();
618*b1cdbd2cSJim Jagielski         long nWidth = rBoxes[j]->GetFrmFmt()->GetFrmSize().GetWidth();
619*b1cdbd2cSJim Jagielski         nAddWidth += nWidth;
620*b1cdbd2cSJim Jagielski         sal_uInt16 nCurrBox = pLine->GetTabBoxes().C40_GETPOS(SwTableBox, pBox );
621*b1cdbd2cSJim Jagielski         sal_uInt16 nCurrLine = rTable.GetTabLines().C40_GETPOS(SwTableLine, pLine );
622*b1cdbd2cSJim Jagielski         ASSERT( nCurrLine != USHRT_MAX, "Time to say Good-Bye.." );
623*b1cdbd2cSJim Jagielski         if( rInsPos[ nCurrLine ] == USHRT_MAX )
624*b1cdbd2cSJim Jagielski         {
625*b1cdbd2cSJim Jagielski             rInsPos[ nCurrLine ] = nCurrBox;
626*b1cdbd2cSJim Jagielski             ++nCount;
627*b1cdbd2cSJim Jagielski         }
628*b1cdbd2cSJim Jagielski         else if( ( rInsPos[ nCurrLine ] > nCurrBox ) == !bBehind )
629*b1cdbd2cSJim Jagielski             rInsPos[ nCurrLine ] = nCurrBox;
630*b1cdbd2cSJim Jagielski     }
631*b1cdbd2cSJim Jagielski     if( nCount )
632*b1cdbd2cSJim Jagielski         nAddWidth /= nCount;
633*b1cdbd2cSJim Jagielski     return nAddWidth;
634*b1cdbd2cSJim Jagielski }
635*b1cdbd2cSJim Jagielski 
636*b1cdbd2cSJim Jagielski /** SwTable::NewInsertCol(..) insert new column(s) into a table
637*b1cdbd2cSJim Jagielski 
638*b1cdbd2cSJim Jagielski 
639*b1cdbd2cSJim Jagielski @param pDoc
640*b1cdbd2cSJim Jagielski the document
641*b1cdbd2cSJim Jagielski 
642*b1cdbd2cSJim Jagielski @param rBoxes
643*b1cdbd2cSJim Jagielski the selected boxes
644*b1cdbd2cSJim Jagielski 
645*b1cdbd2cSJim Jagielski @param nCnt
646*b1cdbd2cSJim Jagielski the number of columns to insert
647*b1cdbd2cSJim Jagielski 
648*b1cdbd2cSJim Jagielski @param bBehind
649*b1cdbd2cSJim Jagielski insertion behind (true) or before (false) the selected boxes
650*b1cdbd2cSJim Jagielski 
651*b1cdbd2cSJim Jagielski @return true, if any insertion has been done successfully
652*b1cdbd2cSJim Jagielski 
653*b1cdbd2cSJim Jagielski */
654*b1cdbd2cSJim Jagielski 
NewInsertCol(SwDoc * pDoc,const SwSelBoxes & rBoxes,sal_uInt16 nCnt,sal_Bool bBehind)655*b1cdbd2cSJim Jagielski sal_Bool SwTable::NewInsertCol( SwDoc* pDoc, const SwSelBoxes& rBoxes,
656*b1cdbd2cSJim Jagielski     sal_uInt16 nCnt, sal_Bool bBehind )
657*b1cdbd2cSJim Jagielski {
658*b1cdbd2cSJim Jagielski     if( !aLines.Count() || !nCnt )
659*b1cdbd2cSJim Jagielski         return sal_False;
660*b1cdbd2cSJim Jagielski 
661*b1cdbd2cSJim Jagielski     CHECK_TABLE( *this )
662*b1cdbd2cSJim Jagielski     long nNewBoxWidth = 0;
663*b1cdbd2cSJim Jagielski     std::vector< sal_uInt16 > aInsPos( aLines.Count(), USHRT_MAX );
664*b1cdbd2cSJim Jagielski     { // Calculation of the insert positions and the width of the new boxes
665*b1cdbd2cSJim Jagielski         sal_uInt64 nTableWidth = 0;
666*b1cdbd2cSJim Jagielski         for( sal_uInt16 i = 0; i < aLines[0]->GetTabBoxes().Count(); ++i )
667*b1cdbd2cSJim Jagielski             nTableWidth += aLines[0]->GetTabBoxes()[i]->GetFrmFmt()->GetFrmSize().GetWidth();
668*b1cdbd2cSJim Jagielski 
669*b1cdbd2cSJim Jagielski         // Fill the vector of insert positions and the (average) width to insert
670*b1cdbd2cSJim Jagielski         sal_uInt64 nAddWidth = lcl_InsertPosition( *this, aInsPos, rBoxes, bBehind );
671*b1cdbd2cSJim Jagielski 
672*b1cdbd2cSJim Jagielski         // Given is the (average) width of the selected boxes, if we would
673*b1cdbd2cSJim Jagielski         // insert nCnt of columns the table would grow
674*b1cdbd2cSJim Jagielski         // So we will shrink the table first, then insert the new boxes and
675*b1cdbd2cSJim Jagielski         // get a table with the same width than before.
676*b1cdbd2cSJim Jagielski         // But we will not shrink the table by the full already calculated value,
677*b1cdbd2cSJim Jagielski         // we will reduce this value proportional to the old table width
678*b1cdbd2cSJim Jagielski         nAddWidth *= nCnt; // we have to insert nCnt boxes per line
679*b1cdbd2cSJim Jagielski         sal_uInt64 nResultingWidth = nAddWidth + nTableWidth;
680*b1cdbd2cSJim Jagielski         if( !nResultingWidth )
681*b1cdbd2cSJim Jagielski             return sal_False;
682*b1cdbd2cSJim Jagielski         nAddWidth = (nAddWidth * nTableWidth) / nResultingWidth;
683*b1cdbd2cSJim Jagielski         nNewBoxWidth = long( nAddWidth / nCnt ); // Rounding
684*b1cdbd2cSJim Jagielski         nAddWidth = nNewBoxWidth * nCnt; // Rounding
685*b1cdbd2cSJim Jagielski         if( !nAddWidth || nAddWidth >= nTableWidth )
686*b1cdbd2cSJim Jagielski             return sal_False;
687*b1cdbd2cSJim Jagielski         AdjustWidths( static_cast< long >(nTableWidth), static_cast< long >(nTableWidth - nAddWidth) );
688*b1cdbd2cSJim Jagielski     }
689*b1cdbd2cSJim Jagielski 
690*b1cdbd2cSJim Jagielski 	_FndBox aFndBox( 0, 0 );
691*b1cdbd2cSJim Jagielski 	aFndBox.SetTableLines( rBoxes, *this );
692*b1cdbd2cSJim Jagielski 	aFndBox.DelFrms( *this );
693*b1cdbd2cSJim Jagielski // 	aFndBox.SaveChartData( *this );
694*b1cdbd2cSJim Jagielski 
695*b1cdbd2cSJim Jagielski     SwTableNode* pTblNd = GetTableNode();
696*b1cdbd2cSJim Jagielski     std::vector<SwTableBoxFmt*> aInsFormat( nCnt, 0 );
697*b1cdbd2cSJim Jagielski     sal_uInt16 nLastLine = USHRT_MAX;
698*b1cdbd2cSJim Jagielski     long nLastRowSpan = 1;
699*b1cdbd2cSJim Jagielski 
700*b1cdbd2cSJim Jagielski     for( sal_uInt16 i = 0; i < aLines.Count(); ++i )
701*b1cdbd2cSJim Jagielski     {
702*b1cdbd2cSJim Jagielski         SwTableLine* pLine = aLines[ i ];
703*b1cdbd2cSJim Jagielski         sal_uInt16 nInsPos = aInsPos[i];
704*b1cdbd2cSJim Jagielski         ASSERT( nInsPos != USHRT_MAX, "Didn't found insert position" );
705*b1cdbd2cSJim Jagielski         SwTableBox* pBox = pLine->GetTabBoxes()[ nInsPos ];
706*b1cdbd2cSJim Jagielski         if( bBehind )
707*b1cdbd2cSJim Jagielski             ++nInsPos;
708*b1cdbd2cSJim Jagielski         SwTableBoxFmt* pBoxFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
709*b1cdbd2cSJim Jagielski         ::_InsTblBox( pDoc, pTblNd, pLine, pBoxFrmFmt, pBox, nInsPos, nCnt );
710*b1cdbd2cSJim Jagielski         long nRowSpan = pBox->getRowSpan();
711*b1cdbd2cSJim Jagielski         long nDiff = i - nLastLine;
712*b1cdbd2cSJim Jagielski         bool bNewSpan = false;
713*b1cdbd2cSJim Jagielski         if( nLastLine != USHRT_MAX && nDiff <= nLastRowSpan &&
714*b1cdbd2cSJim Jagielski             nRowSpan != nDiff - nLastRowSpan )
715*b1cdbd2cSJim Jagielski         {
716*b1cdbd2cSJim Jagielski             bNewSpan = true;
717*b1cdbd2cSJim Jagielski             while( nLastLine < i )
718*b1cdbd2cSJim Jagielski             {
719*b1cdbd2cSJim Jagielski                 SwTableLine* pTmpLine = aLines[ nLastLine ];
720*b1cdbd2cSJim Jagielski                 sal_uInt16 nTmpPos = aInsPos[nLastLine];
721*b1cdbd2cSJim Jagielski                 if( bBehind )
722*b1cdbd2cSJim Jagielski                     ++nTmpPos;
723*b1cdbd2cSJim Jagielski                 for( sal_uInt16 j = 0; j < nCnt; ++j )
724*b1cdbd2cSJim Jagielski                     pTmpLine->GetTabBoxes()[nTmpPos+j]->setRowSpan( nDiff );
725*b1cdbd2cSJim Jagielski                 if( nDiff > 0 )
726*b1cdbd2cSJim Jagielski                     nDiff = -nDiff;
727*b1cdbd2cSJim Jagielski                 ++nDiff;
728*b1cdbd2cSJim Jagielski                 ++nLastLine;
729*b1cdbd2cSJim Jagielski             }
730*b1cdbd2cSJim Jagielski         }
731*b1cdbd2cSJim Jagielski         if( nRowSpan > 0 )
732*b1cdbd2cSJim Jagielski             bNewSpan = true;
733*b1cdbd2cSJim Jagielski         if( bNewSpan )
734*b1cdbd2cSJim Jagielski         {
735*b1cdbd2cSJim Jagielski             nLastLine = i;
736*b1cdbd2cSJim Jagielski             if( nRowSpan < 0 )
737*b1cdbd2cSJim Jagielski                 nLastRowSpan = -nRowSpan;
738*b1cdbd2cSJim Jagielski             else
739*b1cdbd2cSJim Jagielski                 nLastRowSpan = nRowSpan;
740*b1cdbd2cSJim Jagielski         }
741*b1cdbd2cSJim Jagielski 		const SvxBoxItem& aSelBoxItem = pBoxFrmFmt->GetBox();
742*b1cdbd2cSJim Jagielski 		SvxBoxItem* pNoRightBorder = 0;
743*b1cdbd2cSJim Jagielski         if( aSelBoxItem.GetRight() )
744*b1cdbd2cSJim Jagielski         {
745*b1cdbd2cSJim Jagielski             pNoRightBorder = new SvxBoxItem( aSelBoxItem );
746*b1cdbd2cSJim Jagielski 			pNoRightBorder->SetLine( 0, BOX_LINE_RIGHT );
747*b1cdbd2cSJim Jagielski         }
748*b1cdbd2cSJim Jagielski         for( sal_uInt16 j = 0; j < nCnt; ++j )
749*b1cdbd2cSJim Jagielski         {
750*b1cdbd2cSJim Jagielski             SwTableBox *pCurrBox = pLine->GetTabBoxes()[nInsPos+j];
751*b1cdbd2cSJim Jagielski             if( bNewSpan )
752*b1cdbd2cSJim Jagielski             {
753*b1cdbd2cSJim Jagielski                 pCurrBox->setRowSpan( nLastRowSpan );
754*b1cdbd2cSJim Jagielski                 SwFrmFmt* pFrmFmt = pCurrBox->ClaimFrmFmt();
755*b1cdbd2cSJim Jagielski                 SwFmtFrmSize aFrmSz( pFrmFmt->GetFrmSize() );
756*b1cdbd2cSJim Jagielski                 aFrmSz.SetWidth( nNewBoxWidth );
757*b1cdbd2cSJim Jagielski                 pFrmFmt->SetFmtAttr( aFrmSz );
758*b1cdbd2cSJim Jagielski                 if( pNoRightBorder && ( !bBehind || j+1 < nCnt ) )
759*b1cdbd2cSJim Jagielski                     pFrmFmt->SetFmtAttr( *pNoRightBorder );
760*b1cdbd2cSJim Jagielski                 aInsFormat[j] = (SwTableBoxFmt*)pFrmFmt;
761*b1cdbd2cSJim Jagielski             }
762*b1cdbd2cSJim Jagielski             else
763*b1cdbd2cSJim Jagielski                 pCurrBox->ChgFrmFmt( aInsFormat[j] );
764*b1cdbd2cSJim Jagielski         }
765*b1cdbd2cSJim Jagielski         if( bBehind && pNoRightBorder )
766*b1cdbd2cSJim Jagielski         {
767*b1cdbd2cSJim Jagielski             SwFrmFmt* pFrmFmt = pBox->ClaimFrmFmt();
768*b1cdbd2cSJim Jagielski             pFrmFmt->SetFmtAttr( *pNoRightBorder );
769*b1cdbd2cSJim Jagielski         }
770*b1cdbd2cSJim Jagielski         delete pNoRightBorder;
771*b1cdbd2cSJim Jagielski     }
772*b1cdbd2cSJim Jagielski 
773*b1cdbd2cSJim Jagielski 	aFndBox.MakeFrms( *this );
774*b1cdbd2cSJim Jagielski // 	aFndBox.RestoreChartData( *this );
775*b1cdbd2cSJim Jagielski #ifdef DBG_UTIL
776*b1cdbd2cSJim Jagielski     {
777*b1cdbd2cSJim Jagielski         const SwTableBoxes &rTabBoxes = aLines[0]->GetTabBoxes();
778*b1cdbd2cSJim Jagielski         long nNewWidth = 0;
779*b1cdbd2cSJim Jagielski         for( sal_uInt16 i = 0; i < rTabBoxes.Count(); ++i )
780*b1cdbd2cSJim Jagielski             nNewWidth += rTabBoxes[i]->GetFrmFmt()->GetFrmSize().GetWidth();
781*b1cdbd2cSJim Jagielski         ASSERT( nNewWidth > 0, "Very small" );
782*b1cdbd2cSJim Jagielski     }
783*b1cdbd2cSJim Jagielski #endif
784*b1cdbd2cSJim Jagielski     CHECK_TABLE( *this )
785*b1cdbd2cSJim Jagielski 
786*b1cdbd2cSJim Jagielski     return sal_True;
787*b1cdbd2cSJim Jagielski }
788*b1cdbd2cSJim Jagielski 
789*b1cdbd2cSJim Jagielski /** SwTable::PrepareMerge(..) some preparation for the coming Merge(..)
790*b1cdbd2cSJim Jagielski 
791*b1cdbd2cSJim Jagielski For the old table model, ::GetMergeSel(..) is called only,
792*b1cdbd2cSJim Jagielski for the new table model, PrepareMerge does the main work.
793*b1cdbd2cSJim Jagielski It modifices all cells to merge (width, border, rowspan etc.) and collects
794*b1cdbd2cSJim Jagielski the cells which have to be deleted by Merge(..) afterwards.
795*b1cdbd2cSJim Jagielski If there are superfluous rows, these cells are put into the deletion list as well.
796*b1cdbd2cSJim Jagielski 
797*b1cdbd2cSJim Jagielski @param rPam
798*b1cdbd2cSJim Jagielski the selection to merge
799*b1cdbd2cSJim Jagielski 
800*b1cdbd2cSJim Jagielski @param rBoxes
801*b1cdbd2cSJim Jagielski should be empty at the beginning, at the end it is filled with boxes to delete.
802*b1cdbd2cSJim Jagielski 
803*b1cdbd2cSJim Jagielski @param ppMergeBox
804*b1cdbd2cSJim Jagielski will be set to the master cell box
805*b1cdbd2cSJim Jagielski 
806*b1cdbd2cSJim Jagielski @param pUndo
807*b1cdbd2cSJim Jagielski the undo object to record all changes
808*b1cdbd2cSJim Jagielski can be Null, e.g. when called by Redo(..)
809*b1cdbd2cSJim Jagielski 
810*b1cdbd2cSJim Jagielski @return
811*b1cdbd2cSJim Jagielski 
812*b1cdbd2cSJim Jagielski */
813*b1cdbd2cSJim Jagielski 
PrepareMerge(const SwPaM & rPam,SwSelBoxes & rBoxes,SwSelBoxes & rMerged,SwTableBox ** ppMergeBox,SwUndoTblMerge * pUndo)814*b1cdbd2cSJim Jagielski bool SwTable::PrepareMerge( const SwPaM& rPam, SwSelBoxes& rBoxes,
815*b1cdbd2cSJim Jagielski    SwSelBoxes& rMerged, SwTableBox** ppMergeBox, SwUndoTblMerge* pUndo )
816*b1cdbd2cSJim Jagielski {
817*b1cdbd2cSJim Jagielski     if( !bNewModel )
818*b1cdbd2cSJim Jagielski     {
819*b1cdbd2cSJim Jagielski         ::GetMergeSel( rPam, rBoxes, ppMergeBox, pUndo );
820*b1cdbd2cSJim Jagielski         return rBoxes.Count() > 1;
821*b1cdbd2cSJim Jagielski     }
822*b1cdbd2cSJim Jagielski     CHECK_TABLE( *this )
823*b1cdbd2cSJim Jagielski     // We have to assert a "rectangular" box selection before we start to merge
824*b1cdbd2cSJim Jagielski     std::auto_ptr< SwBoxSelection > pSel( CollectBoxSelection( rPam ) );
825*b1cdbd2cSJim Jagielski     if( !pSel.get() || pSel->isEmpty() )
826*b1cdbd2cSJim Jagielski         return false;
827*b1cdbd2cSJim Jagielski     // Now we should have a rectangle of boxes,
828*b1cdbd2cSJim Jagielski     // i.e. contiguous cells in contiguous rows
829*b1cdbd2cSJim Jagielski     bool bMerge = false; // will be set if any content is transferred from
830*b1cdbd2cSJim Jagielski     // a "not already overlapped" cell into the new master cell.
831*b1cdbd2cSJim Jagielski     SwTableBox *pMergeBox = (*pSel->aBoxes[0])[0]; // the master cell box
832*b1cdbd2cSJim Jagielski     if( !pMergeBox )
833*b1cdbd2cSJim Jagielski         return false;
834*b1cdbd2cSJim Jagielski     (*ppMergeBox) = pMergeBox;
835*b1cdbd2cSJim Jagielski     // The new master box will get the left and the top border of the top-left
836*b1cdbd2cSJim Jagielski     // box of the selection and because the new master cell _is_ the top-left
837*b1cdbd2cSJim Jagielski     // box, the left and right border does not need to be changed.
838*b1cdbd2cSJim Jagielski     // The right and bottom border instead has to be derived from the right-
839*b1cdbd2cSJim Jagielski     // bottom box of the selection. If this is a overlapped cell,
840*b1cdbd2cSJim Jagielski     // the appropiate master box.
841*b1cdbd2cSJim Jagielski     SwTableBox* pLastBox = 0; // the right-bottom (master) cell
842*b1cdbd2cSJim Jagielski     SwDoc* pDoc = GetFrmFmt()->GetDoc();
843*b1cdbd2cSJim Jagielski     SwPosition aInsPos( *pMergeBox->GetSttNd()->EndOfSectionNode() );
844*b1cdbd2cSJim Jagielski     SwPaM aChkPam( aInsPos );
845*b1cdbd2cSJim Jagielski     // The number of lines in the selection rectangle: nLineCount
846*b1cdbd2cSJim Jagielski     const sal_uInt16 nLineCount = sal_uInt16(pSel->aBoxes.size());
847*b1cdbd2cSJim Jagielski     // BTW: nLineCount is the rowspan of the new master cell
848*b1cdbd2cSJim Jagielski     long nRowSpan = nLineCount;
849*b1cdbd2cSJim Jagielski     // We will need the first and last line of the selection
850*b1cdbd2cSJim Jagielski     // to check if there any superfluous row after merging
851*b1cdbd2cSJim Jagielski     SwTableLine* pFirstLn = 0;
852*b1cdbd2cSJim Jagielski     SwTableLine* pLastLn = 0;
853*b1cdbd2cSJim Jagielski     // Iteration over the lines of the selection...
854*b1cdbd2cSJim Jagielski     for( sal_uInt16 nCurrLine = 0; nCurrLine < nLineCount; ++nCurrLine )
855*b1cdbd2cSJim Jagielski     {
856*b1cdbd2cSJim Jagielski         // The selected boxes in the current line
857*b1cdbd2cSJim Jagielski         const SwSelBoxes* pBoxes = pSel->aBoxes[ nCurrLine ];
858*b1cdbd2cSJim Jagielski         sal_uInt16 nColCount = pBoxes->Count();
859*b1cdbd2cSJim Jagielski         // Iteration over the selected cell in the current row
860*b1cdbd2cSJim Jagielski         for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol )
861*b1cdbd2cSJim Jagielski         {
862*b1cdbd2cSJim Jagielski             SwTableBox* pBox = (*pBoxes)[nCurrCol];
863*b1cdbd2cSJim Jagielski             rMerged.Insert( pBox );
864*b1cdbd2cSJim Jagielski             // Only the first selected cell in every row will be alive,
865*b1cdbd2cSJim Jagielski             // the other will be deleted => put into rBoxes
866*b1cdbd2cSJim Jagielski             if( nCurrCol )
867*b1cdbd2cSJim Jagielski                 rBoxes.Insert( pBox );
868*b1cdbd2cSJim Jagielski             else
869*b1cdbd2cSJim Jagielski             {
870*b1cdbd2cSJim Jagielski                 if( nCurrLine == 1 )
871*b1cdbd2cSJim Jagielski                     pFirstLn = pBox->GetUpper(); // we need this line later on
872*b1cdbd2cSJim Jagielski                 if( nCurrLine + 1 == nLineCount )
873*b1cdbd2cSJim Jagielski                     pLastLn = pBox->GetUpper(); // and this one, too.
874*b1cdbd2cSJim Jagielski             }
875*b1cdbd2cSJim Jagielski             // A box has to be merged if it's not the master box itself,
876*b1cdbd2cSJim Jagielski             // but an already overlapped cell must not be merged as well.
877*b1cdbd2cSJim Jagielski             bool bDoMerge = pBox != pMergeBox && pBox->getRowSpan() > 0;
878*b1cdbd2cSJim Jagielski             // The last box has to be in the last "column" of the selection
879*b1cdbd2cSJim Jagielski             // and it has to be a master cell
880*b1cdbd2cSJim Jagielski             if( nCurrCol+1 == nColCount && pBox->getRowSpan() > 0 )
881*b1cdbd2cSJim Jagielski                 pLastBox = pBox;
882*b1cdbd2cSJim Jagielski             if( bDoMerge )
883*b1cdbd2cSJim Jagielski             {
884*b1cdbd2cSJim Jagielski                 bMerge = true;
885*b1cdbd2cSJim Jagielski                 // If the cell to merge contains only one empty paragraph,
886*b1cdbd2cSJim Jagielski                 // we do not transfer this paragraph.
887*b1cdbd2cSJim Jagielski                 if( !IsEmptyBox( *pBox, aChkPam ) )
888*b1cdbd2cSJim Jagielski                 {
889*b1cdbd2cSJim Jagielski                     SwNodeIndex& rInsPosNd = aInsPos.nNode;
890*b1cdbd2cSJim Jagielski                     SwPaM aPam( aInsPos );
891*b1cdbd2cSJim Jagielski                     aPam.GetPoint()->nNode.Assign( *pBox->GetSttNd()->EndOfSectionNode(), -1 );
892*b1cdbd2cSJim Jagielski                     SwCntntNode* pCNd = aPam.GetCntntNode();
893*b1cdbd2cSJim Jagielski                     sal_uInt16 nL = pCNd ? pCNd->Len() : 0;
894*b1cdbd2cSJim Jagielski                     aPam.GetPoint()->nContent.Assign( pCNd, nL );
895*b1cdbd2cSJim Jagielski                     SwNodeIndex aSttNdIdx( *pBox->GetSttNd(), 1 );
896*b1cdbd2cSJim Jagielski                     bool const bUndo = pDoc->GetIDocumentUndoRedo().DoesUndo();
897*b1cdbd2cSJim Jagielski                     if( pUndo )
898*b1cdbd2cSJim Jagielski                     {
899*b1cdbd2cSJim Jagielski                         pDoc->GetIDocumentUndoRedo().DoUndo(false);
900*b1cdbd2cSJim Jagielski                     }
901*b1cdbd2cSJim Jagielski                     pDoc->AppendTxtNode( *aPam.GetPoint() );
902*b1cdbd2cSJim Jagielski                     if( pUndo )
903*b1cdbd2cSJim Jagielski                     {
904*b1cdbd2cSJim Jagielski                         pDoc->GetIDocumentUndoRedo().DoUndo(bUndo);
905*b1cdbd2cSJim Jagielski                     }
906*b1cdbd2cSJim Jagielski                     SwNodeRange aRg( aSttNdIdx, aPam.GetPoint()->nNode );
907*b1cdbd2cSJim Jagielski                     if( pUndo )
908*b1cdbd2cSJim Jagielski                         pUndo->MoveBoxCntnt( pDoc, aRg, rInsPosNd );
909*b1cdbd2cSJim Jagielski                     else
910*b1cdbd2cSJim Jagielski                     {
911*b1cdbd2cSJim Jagielski                         pDoc->MoveNodeRange( aRg, rInsPosNd,
912*b1cdbd2cSJim Jagielski                             IDocumentContentOperations::DOC_NO_DELFRMS );
913*b1cdbd2cSJim Jagielski                     }
914*b1cdbd2cSJim Jagielski                 }
915*b1cdbd2cSJim Jagielski             }
916*b1cdbd2cSJim Jagielski             // Only the cell of the first selected column will stay alive
917*b1cdbd2cSJim Jagielski             // and got a new row span
918*b1cdbd2cSJim Jagielski             if( !nCurrCol )
919*b1cdbd2cSJim Jagielski                 pBox->setRowSpan( nRowSpan );
920*b1cdbd2cSJim Jagielski         }
921*b1cdbd2cSJim Jagielski         if( nRowSpan > 0 ) // the master cell is done, from now on we set
922*b1cdbd2cSJim Jagielski             nRowSpan = -nRowSpan; // negative row spans
923*b1cdbd2cSJim Jagielski         ++nRowSpan; // ... -3, -2, -1
924*b1cdbd2cSJim Jagielski     }
925*b1cdbd2cSJim Jagielski     if( bMerge )
926*b1cdbd2cSJim Jagielski     {
927*b1cdbd2cSJim Jagielski         // A row containing overlapped cells is superfluous,
928*b1cdbd2cSJim Jagielski         // these cells can be put into rBoxes for deletion
929*b1cdbd2cSJim Jagielski         _FindSuperfluousRows( rBoxes, pFirstLn, pLastLn );
930*b1cdbd2cSJim Jagielski         // pNewFmt will be set to the new master box and the overlapped cells
931*b1cdbd2cSJim Jagielski         SwFrmFmt* pNewFmt = pMergeBox->ClaimFrmFmt();
932*b1cdbd2cSJim Jagielski         pNewFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, pSel->mnMergeWidth, 0 ) );
933*b1cdbd2cSJim Jagielski         for( sal_uInt16 nCurrLine = 0; nCurrLine < nLineCount; ++nCurrLine )
934*b1cdbd2cSJim Jagielski         {
935*b1cdbd2cSJim Jagielski             const SwSelBoxes* pBoxes = pSel->aBoxes[ nCurrLine ];
936*b1cdbd2cSJim Jagielski             sal_uInt16 nColCount = pBoxes->Count();
937*b1cdbd2cSJim Jagielski             for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol )
938*b1cdbd2cSJim Jagielski             {
939*b1cdbd2cSJim Jagielski                 SwTableBox* pBox = (*pBoxes)[nCurrCol];
940*b1cdbd2cSJim Jagielski                 if( nCurrCol )
941*b1cdbd2cSJim Jagielski                 {
942*b1cdbd2cSJim Jagielski                     // Even this box will be deleted soon,
943*b1cdbd2cSJim Jagielski                     // we have to correct the width to avoid side effects
944*b1cdbd2cSJim Jagielski                     SwFrmFmt* pFmt = pBox->ClaimFrmFmt();
945*b1cdbd2cSJim Jagielski                     pFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, 0, 0 ) );
946*b1cdbd2cSJim Jagielski                 }
947*b1cdbd2cSJim Jagielski                 else
948*b1cdbd2cSJim Jagielski                     pBox->ChgFrmFmt( (SwTableBoxFmt*)pNewFmt );
949*b1cdbd2cSJim Jagielski             }
950*b1cdbd2cSJim Jagielski         }
951*b1cdbd2cSJim Jagielski         if( pLastBox ) // Robust
952*b1cdbd2cSJim Jagielski         {
953*b1cdbd2cSJim Jagielski             // The new borders of the master cell...
954*b1cdbd2cSJim Jagielski             SvxBoxItem aBox( pMergeBox->GetFrmFmt()->GetBox() );
955*b1cdbd2cSJim Jagielski             bool bOld = aBox.GetRight() || aBox.GetBottom();
956*b1cdbd2cSJim Jagielski             const SvxBoxItem& rBox = pLastBox->GetFrmFmt()->GetBox();
957*b1cdbd2cSJim Jagielski             aBox.SetLine( rBox.GetRight(), BOX_LINE_RIGHT );
958*b1cdbd2cSJim Jagielski             aBox.SetLine( rBox.GetBottom(), BOX_LINE_BOTTOM );
959*b1cdbd2cSJim Jagielski             if( bOld || aBox.GetLeft() || aBox.GetTop() || aBox.GetRight() || aBox.GetBottom() )
960*b1cdbd2cSJim Jagielski                 (*ppMergeBox)->GetFrmFmt()->SetFmtAttr( aBox );
961*b1cdbd2cSJim Jagielski         }
962*b1cdbd2cSJim Jagielski 
963*b1cdbd2cSJim Jagielski         if( pUndo )
964*b1cdbd2cSJim Jagielski             pUndo->AddNewBox( pMergeBox->GetSttIdx() );
965*b1cdbd2cSJim Jagielski     }
966*b1cdbd2cSJim Jagielski     return bMerge;
967*b1cdbd2cSJim Jagielski }
968*b1cdbd2cSJim Jagielski 
969*b1cdbd2cSJim Jagielski /** SwTable::_FindSuperfluousRows(..) is looking for superfluous rows, i.e. rows
970*b1cdbd2cSJim Jagielski     containing overlapped cells only.
971*b1cdbd2cSJim Jagielski */
972*b1cdbd2cSJim Jagielski 
_FindSuperfluousRows(SwSelBoxes & rBoxes,SwTableLine * pFirstLn,SwTableLine * pLastLn)973*b1cdbd2cSJim Jagielski void SwTable::_FindSuperfluousRows( SwSelBoxes& rBoxes,
974*b1cdbd2cSJim Jagielski     SwTableLine* pFirstLn, SwTableLine* pLastLn )
975*b1cdbd2cSJim Jagielski {
976*b1cdbd2cSJim Jagielski     if( !pFirstLn || !pLastLn )
977*b1cdbd2cSJim Jagielski     {
978*b1cdbd2cSJim Jagielski         if( !rBoxes.Count() )
979*b1cdbd2cSJim Jagielski             return;
980*b1cdbd2cSJim Jagielski         pFirstLn = rBoxes[0]->GetUpper();
981*b1cdbd2cSJim Jagielski         pLastLn = rBoxes[ rBoxes.Count() - 1 ]->GetUpper();
982*b1cdbd2cSJim Jagielski     }
983*b1cdbd2cSJim Jagielski     sal_uInt16 nFirstLn = GetTabLines().C40_GETPOS(SwTableLine, pFirstLn );
984*b1cdbd2cSJim Jagielski     sal_uInt16 nLastLn = GetTabLines().C40_GETPOS(SwTableLine, pLastLn );
985*b1cdbd2cSJim Jagielski     for( sal_uInt16 nRow = nFirstLn; nRow <= nLastLn; ++nRow )
986*b1cdbd2cSJim Jagielski     {
987*b1cdbd2cSJim Jagielski         SwTableLine* pLine = aLines[nRow];
988*b1cdbd2cSJim Jagielski         ASSERT( pLine, "Missing table line" );
989*b1cdbd2cSJim Jagielski         sal_uInt16 nCols = pLine->GetTabBoxes().Count();
990*b1cdbd2cSJim Jagielski         bool bSuperfl = true;
991*b1cdbd2cSJim Jagielski         for( sal_uInt16 nCol = 0; nCol < nCols; ++nCol )
992*b1cdbd2cSJim Jagielski         {
993*b1cdbd2cSJim Jagielski             SwTableBox *pBox = pLine->GetTabBoxes()[nCol];
994*b1cdbd2cSJim Jagielski             if( pBox->getRowSpan() > 0 &&
995*b1cdbd2cSJim Jagielski                 USHRT_MAX == rBoxes.GetPos( pBox ) )
996*b1cdbd2cSJim Jagielski             {
997*b1cdbd2cSJim Jagielski                 bSuperfl = false;
998*b1cdbd2cSJim Jagielski                 break;
999*b1cdbd2cSJim Jagielski             }
1000*b1cdbd2cSJim Jagielski         }
1001*b1cdbd2cSJim Jagielski         if( bSuperfl )
1002*b1cdbd2cSJim Jagielski         {
1003*b1cdbd2cSJim Jagielski             for( sal_uInt16 nCol = 0; nCol < nCols; ++nCol )
1004*b1cdbd2cSJim Jagielski             {
1005*b1cdbd2cSJim Jagielski                 SwTableBox* pBox = pLine->GetTabBoxes()[nCol];
1006*b1cdbd2cSJim Jagielski                 rBoxes.Insert( pBox );
1007*b1cdbd2cSJim Jagielski             }
1008*b1cdbd2cSJim Jagielski         }
1009*b1cdbd2cSJim Jagielski     }
1010*b1cdbd2cSJim Jagielski }
1011*b1cdbd2cSJim Jagielski 
1012*b1cdbd2cSJim Jagielski /** SwTableBox::FindStartOfRowSpan(..) retruns the "master" cell, the cell which
1013*b1cdbd2cSJim Jagielski     overlaps the given cell, it maybe the cell itself.
1014*b1cdbd2cSJim Jagielski */
1015*b1cdbd2cSJim Jagielski 
FindStartOfRowSpan(const SwTable & rTable,sal_uInt16 nMaxStep)1016*b1cdbd2cSJim Jagielski SwTableBox& SwTableBox::FindStartOfRowSpan( const SwTable& rTable, sal_uInt16 nMaxStep )
1017*b1cdbd2cSJim Jagielski {
1018*b1cdbd2cSJim Jagielski     if( getRowSpan() > 0 || !nMaxStep )
1019*b1cdbd2cSJim Jagielski         return *this;
1020*b1cdbd2cSJim Jagielski 
1021*b1cdbd2cSJim Jagielski     long nLeftBorder = lcl_Box2LeftBorder( *this );
1022*b1cdbd2cSJim Jagielski     SwTableBox* pBox = this;
1023*b1cdbd2cSJim Jagielski     const SwTableLine* pMyUpper = GetUpper();
1024*b1cdbd2cSJim Jagielski     sal_uInt16 nLine = rTable.GetTabLines().C40_GETPOS(SwTableLine, pMyUpper );
1025*b1cdbd2cSJim Jagielski     if( nLine && nLine < rTable.GetTabLines().Count() )
1026*b1cdbd2cSJim Jagielski     {
1027*b1cdbd2cSJim Jagielski         SwTableBox* pNext;
1028*b1cdbd2cSJim Jagielski         do
1029*b1cdbd2cSJim Jagielski         {
1030*b1cdbd2cSJim Jagielski             pNext = lcl_LeftBorder2Box( nLeftBorder, rTable.GetTabLines()[--nLine] );
1031*b1cdbd2cSJim Jagielski             if( pNext )
1032*b1cdbd2cSJim Jagielski                 pBox = pNext;
1033*b1cdbd2cSJim Jagielski         } while( nLine && --nMaxStep && pNext && pBox->getRowSpan() < 1 );
1034*b1cdbd2cSJim Jagielski     }
1035*b1cdbd2cSJim Jagielski 
1036*b1cdbd2cSJim Jagielski     return *pBox;
1037*b1cdbd2cSJim Jagielski }
1038*b1cdbd2cSJim Jagielski 
1039*b1cdbd2cSJim Jagielski /** SwTableBox::FindEndOfRowSpan(..) returns the last overlapped cell if there is
1040*b1cdbd2cSJim Jagielski     any. Otherwise the cell itself will returned.
1041*b1cdbd2cSJim Jagielski */
1042*b1cdbd2cSJim Jagielski 
FindEndOfRowSpan(const SwTable & rTable,sal_uInt16 nMaxStep)1043*b1cdbd2cSJim Jagielski SwTableBox& SwTableBox::FindEndOfRowSpan( const SwTable& rTable, sal_uInt16 nMaxStep )
1044*b1cdbd2cSJim Jagielski {
1045*b1cdbd2cSJim Jagielski     long nAbsSpan = getRowSpan();
1046*b1cdbd2cSJim Jagielski     if( nAbsSpan < 0 )
1047*b1cdbd2cSJim Jagielski         nAbsSpan = -nAbsSpan;
1048*b1cdbd2cSJim Jagielski     if( nAbsSpan == 1 || !nMaxStep )
1049*b1cdbd2cSJim Jagielski         return *this;
1050*b1cdbd2cSJim Jagielski 
1051*b1cdbd2cSJim Jagielski     if( nMaxStep > --nAbsSpan )
1052*b1cdbd2cSJim Jagielski         nMaxStep = (sal_uInt16)nAbsSpan;
1053*b1cdbd2cSJim Jagielski     const SwTableLine* pMyUpper = GetUpper();
1054*b1cdbd2cSJim Jagielski     sal_uInt16 nLine = rTable.GetTabLines().C40_GETPOS(SwTableLine, pMyUpper );
1055*b1cdbd2cSJim Jagielski     nMaxStep = nLine + nMaxStep;
1056*b1cdbd2cSJim Jagielski     if( nMaxStep >= rTable.GetTabLines().Count() )
1057*b1cdbd2cSJim Jagielski         nMaxStep = rTable.GetTabLines().Count() - 1;
1058*b1cdbd2cSJim Jagielski     long nLeftBorder = lcl_Box2LeftBorder( *this );
1059*b1cdbd2cSJim Jagielski     SwTableBox* pBox =
1060*b1cdbd2cSJim Jagielski         lcl_LeftBorder2Box( nLeftBorder, rTable.GetTabLines()[ nMaxStep ] );
1061*b1cdbd2cSJim Jagielski     if ( !pBox )
1062*b1cdbd2cSJim Jagielski         pBox = this;
1063*b1cdbd2cSJim Jagielski 
1064*b1cdbd2cSJim Jagielski     return *pBox;
1065*b1cdbd2cSJim Jagielski }
1066*b1cdbd2cSJim Jagielski 
1067*b1cdbd2cSJim Jagielski /** lcl_getAllMergedBoxes(..) collects all overlapped boxes to a given (master) box
1068*b1cdbd2cSJim Jagielski */
1069*b1cdbd2cSJim Jagielski 
lcl_getAllMergedBoxes(const SwTable & rTable,SwSelBoxes & rBoxes,SwTableBox & rBox)1070*b1cdbd2cSJim Jagielski void lcl_getAllMergedBoxes( const SwTable& rTable, SwSelBoxes& rBoxes, SwTableBox& rBox )
1071*b1cdbd2cSJim Jagielski {
1072*b1cdbd2cSJim Jagielski     SwTableBox* pBox = &rBox;
1073*b1cdbd2cSJim Jagielski     ASSERT( pBox == &rBox.FindStartOfRowSpan( rTable, USHRT_MAX ), "Not a master box" );
1074*b1cdbd2cSJim Jagielski     rBoxes.Insert( pBox );
1075*b1cdbd2cSJim Jagielski     if( pBox->getRowSpan() == 1 )
1076*b1cdbd2cSJim Jagielski         return;
1077*b1cdbd2cSJim Jagielski     const SwTableLine* pMyUpper = pBox->GetUpper();
1078*b1cdbd2cSJim Jagielski     sal_uInt16 nLine = rTable.GetTabLines().C40_GETPOS(SwTableLine, pMyUpper );
1079*b1cdbd2cSJim Jagielski     long nLeftBorder = lcl_Box2LeftBorder( *pBox );
1080*b1cdbd2cSJim Jagielski     sal_uInt16 nCount = rTable.GetTabLines().Count();
1081*b1cdbd2cSJim Jagielski     while( ++nLine < nCount && pBox && pBox->getRowSpan() != -1 )
1082*b1cdbd2cSJim Jagielski     {
1083*b1cdbd2cSJim Jagielski         pBox = lcl_LeftBorder2Box( nLeftBorder, rTable.GetTabLines()[nLine] );
1084*b1cdbd2cSJim Jagielski         if( pBox )
1085*b1cdbd2cSJim Jagielski             rBoxes.Insert( pBox );
1086*b1cdbd2cSJim Jagielski     };
1087*b1cdbd2cSJim Jagielski }
1088*b1cdbd2cSJim Jagielski 
1089*b1cdbd2cSJim Jagielski /** lcl_UnMerge(..) manipulates the row span attribute of a given master cell
1090*b1cdbd2cSJim Jagielski     and its overlapped cells to split them into several pieces.
1091*b1cdbd2cSJim Jagielski */
1092*b1cdbd2cSJim Jagielski 
lcl_UnMerge(const SwTable & rTable,SwTableBox & rBox,sal_uInt16 nCnt,sal_Bool bSameHeight)1093*b1cdbd2cSJim Jagielski void lcl_UnMerge( const SwTable& rTable, SwTableBox& rBox, sal_uInt16 nCnt,
1094*b1cdbd2cSJim Jagielski     sal_Bool bSameHeight )
1095*b1cdbd2cSJim Jagielski {
1096*b1cdbd2cSJim Jagielski     SwSelBoxes aBoxes;
1097*b1cdbd2cSJim Jagielski     lcl_getAllMergedBoxes( rTable, aBoxes, rBox );
1098*b1cdbd2cSJim Jagielski     sal_uInt16 nCount = aBoxes.Count();
1099*b1cdbd2cSJim Jagielski     if( nCount < 2 )
1100*b1cdbd2cSJim Jagielski         return;
1101*b1cdbd2cSJim Jagielski     if( nCnt > nCount )
1102*b1cdbd2cSJim Jagielski         nCnt = nCount;
1103*b1cdbd2cSJim Jagielski     sal_uInt16 *pSplitIdx = new sal_uInt16[ nCnt ];
1104*b1cdbd2cSJim Jagielski     if( bSameHeight )
1105*b1cdbd2cSJim Jagielski     {
1106*b1cdbd2cSJim Jagielski         SwTwips *pHeights = new SwTwips[ nCount ];
1107*b1cdbd2cSJim Jagielski         SwTwips nHeight = 0;
1108*b1cdbd2cSJim Jagielski         for( sal_uInt16 i = 0; i < nCount; ++i )
1109*b1cdbd2cSJim Jagielski         {
1110*b1cdbd2cSJim Jagielski             SwTableLine* pLine = aBoxes[ i ]->GetUpper();
1111*b1cdbd2cSJim Jagielski             SwFrmFmt *pRowFmt = pLine->GetFrmFmt();
1112*b1cdbd2cSJim Jagielski             pHeights[ i ] = pRowFmt->GetFrmSize().GetHeight();
1113*b1cdbd2cSJim Jagielski             nHeight += pHeights[ i ];
1114*b1cdbd2cSJim Jagielski         }
1115*b1cdbd2cSJim Jagielski         SwTwips nSumH = 0;
1116*b1cdbd2cSJim Jagielski         sal_uInt16 nIdx = 0;
1117*b1cdbd2cSJim Jagielski         for( sal_uInt16 i = 1; i <= nCnt; ++i )
1118*b1cdbd2cSJim Jagielski         {
1119*b1cdbd2cSJim Jagielski             SwTwips nSplit = ( i * nHeight ) / nCnt;
1120*b1cdbd2cSJim Jagielski             while( nSumH < nSplit && nIdx < nCount )
1121*b1cdbd2cSJim Jagielski                 nSumH += pHeights[ nIdx++ ];
1122*b1cdbd2cSJim Jagielski             pSplitIdx[ i - 1 ] = nIdx;
1123*b1cdbd2cSJim Jagielski         }
1124*b1cdbd2cSJim Jagielski         delete[] pHeights;
1125*b1cdbd2cSJim Jagielski     }
1126*b1cdbd2cSJim Jagielski     else
1127*b1cdbd2cSJim Jagielski     {
1128*b1cdbd2cSJim Jagielski         for( long i = 1; i <= nCnt; ++i )
1129*b1cdbd2cSJim Jagielski             pSplitIdx[ i - 1 ] = (sal_uInt16)( ( i * nCount ) / nCnt );
1130*b1cdbd2cSJim Jagielski     }
1131*b1cdbd2cSJim Jagielski     sal_uInt16 nIdx = 0;
1132*b1cdbd2cSJim Jagielski     for( long i = 0; i < nCnt; ++i )
1133*b1cdbd2cSJim Jagielski     {
1134*b1cdbd2cSJim Jagielski         sal_uInt16 nNextIdx = pSplitIdx[ i ];
1135*b1cdbd2cSJim Jagielski         aBoxes[ nIdx ]->setRowSpan( nNextIdx - nIdx );
1136*b1cdbd2cSJim Jagielski         lcl_InvalidateCellFrm( *aBoxes[ nIdx ] );
1137*b1cdbd2cSJim Jagielski         while( ++nIdx < nNextIdx )
1138*b1cdbd2cSJim Jagielski             aBoxes[ nIdx ]->setRowSpan( nIdx - nNextIdx );
1139*b1cdbd2cSJim Jagielski     }
1140*b1cdbd2cSJim Jagielski     delete[] pSplitIdx;
1141*b1cdbd2cSJim Jagielski }
1142*b1cdbd2cSJim Jagielski 
1143*b1cdbd2cSJim Jagielski /** lcl_FillSelBoxes(..) puts all boxes of a given line into the selection structure
1144*b1cdbd2cSJim Jagielski */
1145*b1cdbd2cSJim Jagielski 
lcl_FillSelBoxes(SwSelBoxes & rBoxes,SwTableLine & rLine)1146*b1cdbd2cSJim Jagielski void lcl_FillSelBoxes( SwSelBoxes &rBoxes, SwTableLine &rLine )
1147*b1cdbd2cSJim Jagielski {
1148*b1cdbd2cSJim Jagielski     sal_uInt16 nBoxCount = rLine.GetTabBoxes().Count();
1149*b1cdbd2cSJim Jagielski     sal_uInt16 nCurrBox;
1150*b1cdbd2cSJim Jagielski     for( nCurrBox = 0; nCurrBox < nBoxCount; ++nCurrBox )
1151*b1cdbd2cSJim Jagielski         rBoxes.Insert( rLine.GetTabBoxes()[nCurrBox] );
1152*b1cdbd2cSJim Jagielski }
1153*b1cdbd2cSJim Jagielski 
1154*b1cdbd2cSJim Jagielski /** SwTable::InsertSpannedRow(..) inserts "superfluous" rows, i.e. rows containig
1155*b1cdbd2cSJim Jagielski     overlapped cells only. This is a preparation for an upcoming split.
1156*b1cdbd2cSJim Jagielski */
1157*b1cdbd2cSJim Jagielski 
InsertSpannedRow(SwDoc * pDoc,sal_uInt16 nRowIdx,sal_uInt16 nCnt)1158*b1cdbd2cSJim Jagielski void SwTable::InsertSpannedRow( SwDoc* pDoc, sal_uInt16 nRowIdx, sal_uInt16 nCnt )
1159*b1cdbd2cSJim Jagielski {
1160*b1cdbd2cSJim Jagielski     CHECK_TABLE( *this )
1161*b1cdbd2cSJim Jagielski     ASSERT( nCnt && nRowIdx < GetTabLines().Count(), "Wrong call of InsertSpannedRow" );
1162*b1cdbd2cSJim Jagielski     SwSelBoxes aBoxes;
1163*b1cdbd2cSJim Jagielski     SwTableLine& rLine = *GetTabLines()[ nRowIdx ];
1164*b1cdbd2cSJim Jagielski     lcl_FillSelBoxes( aBoxes, rLine );
1165*b1cdbd2cSJim Jagielski     SwFmtFrmSize aFSz( rLine.GetFrmFmt()->GetFrmSize() );
1166*b1cdbd2cSJim Jagielski     if( ATT_VAR_SIZE != aFSz.GetHeightSizeType() )
1167*b1cdbd2cSJim Jagielski     {
1168*b1cdbd2cSJim Jagielski         SwFrmFmt* pFrmFmt = rLine.ClaimFrmFmt();
1169*b1cdbd2cSJim Jagielski         long nNewHeight = aFSz.GetHeight() / ( nCnt + 1 );
1170*b1cdbd2cSJim Jagielski         if( !nNewHeight )
1171*b1cdbd2cSJim Jagielski             ++nNewHeight;
1172*b1cdbd2cSJim Jagielski         aFSz.SetHeight( nNewHeight );
1173*b1cdbd2cSJim Jagielski         pFrmFmt->SetFmtAttr( aFSz );
1174*b1cdbd2cSJim Jagielski     }
1175*b1cdbd2cSJim Jagielski     _InsertRow( pDoc, aBoxes, nCnt, sal_True );
1176*b1cdbd2cSJim Jagielski     sal_uInt16 nBoxCount = rLine.GetTabBoxes().Count();
1177*b1cdbd2cSJim Jagielski     for( sal_uInt16 n = 0; n < nCnt; ++n )
1178*b1cdbd2cSJim Jagielski     {
1179*b1cdbd2cSJim Jagielski         SwTableLine *pNewLine = GetTabLines()[ nRowIdx + nCnt - n ];
1180*b1cdbd2cSJim Jagielski         for( sal_uInt16 nCurrBox = 0; nCurrBox < nBoxCount; ++nCurrBox )
1181*b1cdbd2cSJim Jagielski         {
1182*b1cdbd2cSJim Jagielski             long nRowSpan = rLine.GetTabBoxes()[nCurrBox]->getRowSpan();
1183*b1cdbd2cSJim Jagielski             if( nRowSpan > 0 )
1184*b1cdbd2cSJim Jagielski                 nRowSpan = - nRowSpan;
1185*b1cdbd2cSJim Jagielski             pNewLine->GetTabBoxes()[ nCurrBox ]->setRowSpan( nRowSpan - n );
1186*b1cdbd2cSJim Jagielski         }
1187*b1cdbd2cSJim Jagielski     }
1188*b1cdbd2cSJim Jagielski     lcl_ChangeRowSpan( *this, nCnt, nRowIdx, false );
1189*b1cdbd2cSJim Jagielski     CHECK_TABLE( *this )
1190*b1cdbd2cSJim Jagielski }
1191*b1cdbd2cSJim Jagielski 
1192*b1cdbd2cSJim Jagielski typedef std::pair< sal_uInt16, sal_uInt16 > SwLineOffset;
1193*b1cdbd2cSJim Jagielski typedef std::list< SwLineOffset > SwLineOffsetArray;
1194*b1cdbd2cSJim Jagielski 
1195*b1cdbd2cSJim Jagielski /******************************************************************************
1196*b1cdbd2cSJim Jagielski When a couple of table boxes has to be split,
1197*b1cdbd2cSJim Jagielski lcl_SophisticatedFillLineIndices delivers the information where and how many
1198*b1cdbd2cSJim Jagielski rows have to be inserted.
1199*b1cdbd2cSJim Jagielski Input
1200*b1cdbd2cSJim Jagielski     rTable: the table to manipulate
1201*b1cdbd2cSJim Jagielski     rBoxes: an array of boxes to split
1202*b1cdbd2cSJim Jagielski     nCnt:   how many parts are wanted
1203*b1cdbd2cSJim Jagielski Output
1204*b1cdbd2cSJim Jagielski     rArr:   a list of pairs ( line index, number of lines to insert )
1205*b1cdbd2cSJim Jagielski 
1206*b1cdbd2cSJim Jagielski ******************************************************************************/
1207*b1cdbd2cSJim Jagielski 
lcl_SophisticatedFillLineIndices(SwLineOffsetArray & rArr,const SwTable & rTable,const SwSelBoxes & rBoxes,sal_uInt16 nCnt)1208*b1cdbd2cSJim Jagielski void lcl_SophisticatedFillLineIndices( SwLineOffsetArray &rArr,
1209*b1cdbd2cSJim Jagielski     const SwTable& rTable, const SwSelBoxes& rBoxes, sal_uInt16 nCnt )
1210*b1cdbd2cSJim Jagielski {
1211*b1cdbd2cSJim Jagielski     std::list< SwLineOffset > aBoxes;
1212*b1cdbd2cSJim Jagielski     SwLineOffset aLnOfs( USHRT_MAX, USHRT_MAX );
1213*b1cdbd2cSJim Jagielski     for( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
1214*b1cdbd2cSJim Jagielski     {   // Collect all end line indices and the row spans
1215*b1cdbd2cSJim Jagielski         const SwTableBox &rBox = rBoxes[ i ]->FindStartOfRowSpan( rTable );
1216*b1cdbd2cSJim Jagielski         ASSERT( rBox.getRowSpan() > 0, "Didn't I say 'StartOfRowSpan' ??" )
1217*b1cdbd2cSJim Jagielski         if( nCnt > rBox.getRowSpan() )
1218*b1cdbd2cSJim Jagielski         {
1219*b1cdbd2cSJim Jagielski             const SwTableLine *pLine = rBox.GetUpper();
1220*b1cdbd2cSJim Jagielski             const sal_uInt16 nEnd = sal_uInt16( rBox.getRowSpan() +
1221*b1cdbd2cSJim Jagielski                 rTable.GetTabLines().C40_GETPOS( SwTableLine, pLine ) );
1222*b1cdbd2cSJim Jagielski             // The next if statement is a small optimization
1223*b1cdbd2cSJim Jagielski             if( aLnOfs.first != nEnd || aLnOfs.second != rBox.getRowSpan() )
1224*b1cdbd2cSJim Jagielski             {
1225*b1cdbd2cSJim Jagielski                 aLnOfs.first = nEnd; // ok, this is the line behind the box
1226*b1cdbd2cSJim Jagielski                 aLnOfs.second = sal_uInt16( rBox.getRowSpan() ); // the row span
1227*b1cdbd2cSJim Jagielski                 aBoxes.insert( aBoxes.end(), aLnOfs );
1228*b1cdbd2cSJim Jagielski             }
1229*b1cdbd2cSJim Jagielski         }
1230*b1cdbd2cSJim Jagielski     }
1231*b1cdbd2cSJim Jagielski     // As I said, I noted the line index _behind_ the last line of the boxes
1232*b1cdbd2cSJim Jagielski     // in the resulting array the index has to be _on_ the line
1233*b1cdbd2cSJim Jagielski     // nSum is to evaluate the wished value
1234*b1cdbd2cSJim Jagielski     sal_uInt16 nSum = 1;
1235*b1cdbd2cSJim Jagielski     while( aBoxes.size() )
1236*b1cdbd2cSJim Jagielski     {
1237*b1cdbd2cSJim Jagielski         // I. step:
1238*b1cdbd2cSJim Jagielski         // Looking for the "smallest" line end with the smallest row span
1239*b1cdbd2cSJim Jagielski         std::list< SwLineOffset >::iterator pCurr = aBoxes.begin();
1240*b1cdbd2cSJim Jagielski         aLnOfs = *pCurr; // the line end and row span of the first box
1241*b1cdbd2cSJim Jagielski         while( ++pCurr != aBoxes.end() )
1242*b1cdbd2cSJim Jagielski         {
1243*b1cdbd2cSJim Jagielski             if( aLnOfs.first > pCurr->first )
1244*b1cdbd2cSJim Jagielski             {   // Found a smaller line end
1245*b1cdbd2cSJim Jagielski                 aLnOfs.first = pCurr->first;
1246*b1cdbd2cSJim Jagielski                 aLnOfs.second = pCurr->second; // row span
1247*b1cdbd2cSJim Jagielski             }
1248*b1cdbd2cSJim Jagielski             else if( aLnOfs.first == pCurr->first &&
1249*b1cdbd2cSJim Jagielski                      aLnOfs.second < pCurr->second )
1250*b1cdbd2cSJim Jagielski                 aLnOfs.second = pCurr->second; // Found a smaller row span
1251*b1cdbd2cSJim Jagielski         }
1252*b1cdbd2cSJim Jagielski         ASSERT( aLnOfs.second < nCnt, "Clean-up failed" )
1253*b1cdbd2cSJim Jagielski         aLnOfs.second = nCnt - aLnOfs.second; // the number of rows to insert
1254*b1cdbd2cSJim Jagielski         rArr.insert( rArr.end(),
1255*b1cdbd2cSJim Jagielski             SwLineOffset( aLnOfs.first - nSum, aLnOfs.second ) );
1256*b1cdbd2cSJim Jagielski         // the correction has to be incremented because in the following
1257*b1cdbd2cSJim Jagielski         // loops the line ends were manipulated
1258*b1cdbd2cSJim Jagielski         nSum = nSum + aLnOfs.second;
1259*b1cdbd2cSJim Jagielski 
1260*b1cdbd2cSJim Jagielski         pCurr = aBoxes.begin();
1261*b1cdbd2cSJim Jagielski         while( pCurr != aBoxes.end() )
1262*b1cdbd2cSJim Jagielski         {
1263*b1cdbd2cSJim Jagielski             if( pCurr->first == aLnOfs.first )
1264*b1cdbd2cSJim Jagielski             {   // These boxes can be removed because the last insertion
1265*b1cdbd2cSJim Jagielski                 // of rows will expand their row span above the needed value
1266*b1cdbd2cSJim Jagielski                 std::list< SwLineOffset >::iterator pDel = pCurr;
1267*b1cdbd2cSJim Jagielski                 ++pCurr;
1268*b1cdbd2cSJim Jagielski                 aBoxes.erase( pDel );
1269*b1cdbd2cSJim Jagielski             }
1270*b1cdbd2cSJim Jagielski             else
1271*b1cdbd2cSJim Jagielski             {
1272*b1cdbd2cSJim Jagielski                 bool bBefore = ( pCurr->first - pCurr->second < aLnOfs.first );
1273*b1cdbd2cSJim Jagielski                 // Manipulation of the end line indices as if the rows are
1274*b1cdbd2cSJim Jagielski                 // already inserted
1275*b1cdbd2cSJim Jagielski                 pCurr->first = pCurr->first + aLnOfs.second;
1276*b1cdbd2cSJim Jagielski                 if( bBefore )
1277*b1cdbd2cSJim Jagielski                 {   // If the insertion is inside the box,
1278*b1cdbd2cSJim Jagielski                     // its row span has to be incremented
1279*b1cdbd2cSJim Jagielski                     pCurr->second = pCurr->second + aLnOfs.second;
1280*b1cdbd2cSJim Jagielski                     if( pCurr->second >= nCnt )
1281*b1cdbd2cSJim Jagielski                     {   // if the row span is bigger than the split factor
1282*b1cdbd2cSJim Jagielski                         // this box is done
1283*b1cdbd2cSJim Jagielski                         std::list< SwLineOffset >::iterator pDel = pCurr;
1284*b1cdbd2cSJim Jagielski                         ++pCurr;
1285*b1cdbd2cSJim Jagielski                         aBoxes.erase( pDel );
1286*b1cdbd2cSJim Jagielski                     }
1287*b1cdbd2cSJim Jagielski                     else
1288*b1cdbd2cSJim Jagielski                         ++pCurr;
1289*b1cdbd2cSJim Jagielski                 }
1290*b1cdbd2cSJim Jagielski                 else
1291*b1cdbd2cSJim Jagielski                     ++pCurr;
1292*b1cdbd2cSJim Jagielski             }
1293*b1cdbd2cSJim Jagielski         }
1294*b1cdbd2cSJim Jagielski     }
1295*b1cdbd2cSJim Jagielski }
1296*b1cdbd2cSJim Jagielski 
1297*b1cdbd2cSJim Jagielski typedef std::set< SwTwips > SwSplitLines;
1298*b1cdbd2cSJim Jagielski 
1299*b1cdbd2cSJim Jagielski /** lcl_CalculateSplitLineHeights(..) delivers all y-positions where table rows have
1300*b1cdbd2cSJim Jagielski     to be splitted to fulfill the requested "split same height"
1301*b1cdbd2cSJim Jagielski */
1302*b1cdbd2cSJim Jagielski 
lcl_CalculateSplitLineHeights(SwSplitLines & rCurr,SwSplitLines & rNew,const SwTable & rTable,const SwSelBoxes & rBoxes,sal_uInt16 nCnt)1303*b1cdbd2cSJim Jagielski sal_uInt16 lcl_CalculateSplitLineHeights( SwSplitLines &rCurr, SwSplitLines &rNew,
1304*b1cdbd2cSJim Jagielski     const SwTable& rTable, const SwSelBoxes& rBoxes, sal_uInt16 nCnt )
1305*b1cdbd2cSJim Jagielski {
1306*b1cdbd2cSJim Jagielski     if( nCnt < 2 )
1307*b1cdbd2cSJim Jagielski         return 0;
1308*b1cdbd2cSJim Jagielski     std::list< SwLineOffset > aBoxes;
1309*b1cdbd2cSJim Jagielski     SwLineOffset aLnOfs( USHRT_MAX, USHRT_MAX );
1310*b1cdbd2cSJim Jagielski     sal_uInt16 nFirst = USHRT_MAX; // becomes the index of the first line
1311*b1cdbd2cSJim Jagielski     sal_uInt16 nLast = 0; // becomes the index of the last line of the splitting
1312*b1cdbd2cSJim Jagielski     for( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
1313*b1cdbd2cSJim Jagielski     {   // Collect all pairs (start+end) of line indices to split
1314*b1cdbd2cSJim Jagielski         const SwTableBox &rBox = rBoxes[ i ]->FindStartOfRowSpan( rTable );
1315*b1cdbd2cSJim Jagielski         ASSERT( rBox.getRowSpan() > 0, "Didn't I say 'StartOfRowSpan' ??" )
1316*b1cdbd2cSJim Jagielski         const SwTableLine *pLine = rBox.GetUpper();
1317*b1cdbd2cSJim Jagielski         const sal_uInt16 nStart = rTable.GetTabLines().C40_GETPOS( SwTableLine, pLine );
1318*b1cdbd2cSJim Jagielski         const sal_uInt16 nEnd = sal_uInt16( rBox.getRowSpan() + nStart - 1 );
1319*b1cdbd2cSJim Jagielski         // The next if statement is a small optimization
1320*b1cdbd2cSJim Jagielski         if( aLnOfs.first != nStart || aLnOfs.second != nEnd )
1321*b1cdbd2cSJim Jagielski         {
1322*b1cdbd2cSJim Jagielski             aLnOfs.first = nStart;
1323*b1cdbd2cSJim Jagielski             aLnOfs.second = nEnd;
1324*b1cdbd2cSJim Jagielski             aBoxes.insert( aBoxes.end(), aLnOfs );
1325*b1cdbd2cSJim Jagielski             if( nStart < nFirst )
1326*b1cdbd2cSJim Jagielski                 nFirst = nStart;
1327*b1cdbd2cSJim Jagielski             if( nEnd > nLast )
1328*b1cdbd2cSJim Jagielski                 nLast = nEnd;
1329*b1cdbd2cSJim Jagielski         }
1330*b1cdbd2cSJim Jagielski     }
1331*b1cdbd2cSJim Jagielski 
1332*b1cdbd2cSJim Jagielski     if( aBoxes.empty() )
1333*b1cdbd2cSJim Jagielski         return 0;
1334*b1cdbd2cSJim Jagielski     SwTwips nHeight = 0;
1335*b1cdbd2cSJim Jagielski     SwTwips* pLines = new SwTwips[ nLast + 1 - nFirst ];
1336*b1cdbd2cSJim Jagielski     for( sal_uInt16 i = nFirst; i <= nLast; ++i )
1337*b1cdbd2cSJim Jagielski     {
1338*b1cdbd2cSJim Jagielski         bool bLayoutAvailable = false;
1339*b1cdbd2cSJim Jagielski         nHeight += rTable.GetTabLines()[ i ]->GetTableLineHeight( bLayoutAvailable );
1340*b1cdbd2cSJim Jagielski         rCurr.insert( rCurr.end(), nHeight );
1341*b1cdbd2cSJim Jagielski         pLines[ i - nFirst ] = nHeight;
1342*b1cdbd2cSJim Jagielski     }
1343*b1cdbd2cSJim Jagielski     std::list< SwLineOffset >::iterator pSplit = aBoxes.begin();
1344*b1cdbd2cSJim Jagielski     while( pSplit != aBoxes.end() )
1345*b1cdbd2cSJim Jagielski     {
1346*b1cdbd2cSJim Jagielski         SwTwips nBase = pSplit->first <= nFirst ? 0 :
1347*b1cdbd2cSJim Jagielski                         pLines[ pSplit->first - nFirst - 1 ];
1348*b1cdbd2cSJim Jagielski         SwTwips nDiff = pLines[ pSplit->second - nFirst ] - nBase;
1349*b1cdbd2cSJim Jagielski         for( sal_uInt16 i = 1; i < nCnt; ++i )
1350*b1cdbd2cSJim Jagielski         {
1351*b1cdbd2cSJim Jagielski             SwTwips nSplit = nBase + ( i * nDiff ) / nCnt;
1352*b1cdbd2cSJim Jagielski             rNew.insert( nSplit );
1353*b1cdbd2cSJim Jagielski         }
1354*b1cdbd2cSJim Jagielski         ++pSplit;
1355*b1cdbd2cSJim Jagielski     }
1356*b1cdbd2cSJim Jagielski     delete[] pLines;
1357*b1cdbd2cSJim Jagielski     return nFirst;
1358*b1cdbd2cSJim Jagielski }
1359*b1cdbd2cSJim Jagielski 
1360*b1cdbd2cSJim Jagielski /** lcl_LineIndex(..) delivers the line index of the line behind or above
1361*b1cdbd2cSJim Jagielski     the box selection.
1362*b1cdbd2cSJim Jagielski */
1363*b1cdbd2cSJim Jagielski 
lcl_LineIndex(const SwTable & rTable,const SwSelBoxes & rBoxes,bool bBehind)1364*b1cdbd2cSJim Jagielski sal_uInt16 lcl_LineIndex( const SwTable& rTable, const SwSelBoxes& rBoxes,
1365*b1cdbd2cSJim Jagielski                       bool bBehind )
1366*b1cdbd2cSJim Jagielski {
1367*b1cdbd2cSJim Jagielski     sal_uInt16 nDirect = USHRT_MAX;
1368*b1cdbd2cSJim Jagielski     sal_uInt16 nSpan = USHRT_MAX;
1369*b1cdbd2cSJim Jagielski     for( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
1370*b1cdbd2cSJim Jagielski     {
1371*b1cdbd2cSJim Jagielski         SwTableBox *pBox = rBoxes[i];
1372*b1cdbd2cSJim Jagielski         const SwTableLine* pLine = rBoxes[i]->GetUpper();
1373*b1cdbd2cSJim Jagielski         sal_uInt16 nPos = rTable.GetTabLines().C40_GETPOS( SwTableLine, pLine );
1374*b1cdbd2cSJim Jagielski         if( USHRT_MAX != nPos )
1375*b1cdbd2cSJim Jagielski         {
1376*b1cdbd2cSJim Jagielski             if( bBehind )
1377*b1cdbd2cSJim Jagielski             {
1378*b1cdbd2cSJim Jagielski                 if( nPos > nDirect || nDirect == USHRT_MAX )
1379*b1cdbd2cSJim Jagielski                     nDirect = nPos;
1380*b1cdbd2cSJim Jagielski                 long nRowSpan = pBox->getRowSpan();
1381*b1cdbd2cSJim Jagielski                 if( nRowSpan < 2 )
1382*b1cdbd2cSJim Jagielski                     nSpan = 0;
1383*b1cdbd2cSJim Jagielski                 else if( nSpan )
1384*b1cdbd2cSJim Jagielski                 {
1385*b1cdbd2cSJim Jagielski                     sal_uInt16 nEndOfRowSpan = (sal_uInt16)(nPos + nRowSpan - 1);
1386*b1cdbd2cSJim Jagielski                     if( nEndOfRowSpan > nSpan || nSpan == USHRT_MAX )
1387*b1cdbd2cSJim Jagielski                         nSpan = nEndOfRowSpan;
1388*b1cdbd2cSJim Jagielski                 }
1389*b1cdbd2cSJim Jagielski             }
1390*b1cdbd2cSJim Jagielski             else if( nPos < nDirect )
1391*b1cdbd2cSJim Jagielski                 nDirect = nPos;
1392*b1cdbd2cSJim Jagielski         }
1393*b1cdbd2cSJim Jagielski     }
1394*b1cdbd2cSJim Jagielski     if( nSpan && nSpan < USHRT_MAX )
1395*b1cdbd2cSJim Jagielski         return nSpan;
1396*b1cdbd2cSJim Jagielski     return nDirect;
1397*b1cdbd2cSJim Jagielski }
1398*b1cdbd2cSJim Jagielski 
1399*b1cdbd2cSJim Jagielski /** SwTable::NewSplitRow(..) splits all selected boxes horizontally.
1400*b1cdbd2cSJim Jagielski */
1401*b1cdbd2cSJim Jagielski 
NewSplitRow(SwDoc * pDoc,const SwSelBoxes & rBoxes,sal_uInt16 nCnt,sal_Bool bSameHeight)1402*b1cdbd2cSJim Jagielski sal_Bool SwTable::NewSplitRow( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt,
1403*b1cdbd2cSJim Jagielski     sal_Bool bSameHeight )
1404*b1cdbd2cSJim Jagielski {
1405*b1cdbd2cSJim Jagielski     CHECK_TABLE( *this )
1406*b1cdbd2cSJim Jagielski     ++nCnt;
1407*b1cdbd2cSJim Jagielski 	_FndBox aFndBox( 0, 0 );
1408*b1cdbd2cSJim Jagielski 	aFndBox.SetTableLines( rBoxes, *this );
1409*b1cdbd2cSJim Jagielski 
1410*b1cdbd2cSJim Jagielski     if( bSameHeight && pDoc->GetCurrentViewShell() )	//swmod 071108//swmod 071225
1411*b1cdbd2cSJim Jagielski     {
1412*b1cdbd2cSJim Jagielski         SwSplitLines aRowLines;
1413*b1cdbd2cSJim Jagielski         SwSplitLines aSplitLines;
1414*b1cdbd2cSJim Jagielski         sal_uInt16 nFirst = lcl_CalculateSplitLineHeights( aRowLines, aSplitLines,
1415*b1cdbd2cSJim Jagielski             *this, rBoxes, nCnt );
1416*b1cdbd2cSJim Jagielski         aFndBox.DelFrms( *this );
1417*b1cdbd2cSJim Jagielski         SwTwips nLast = 0;
1418*b1cdbd2cSJim Jagielski         SwSplitLines::iterator pSplit = aSplitLines.begin();
1419*b1cdbd2cSJim Jagielski         SwSplitLines::iterator pCurr = aRowLines.begin();
1420*b1cdbd2cSJim Jagielski         while( pCurr != aRowLines.end() )
1421*b1cdbd2cSJim Jagielski         {
1422*b1cdbd2cSJim Jagielski             while( pSplit != aSplitLines.end() && *pSplit < *pCurr )
1423*b1cdbd2cSJim Jagielski             {
1424*b1cdbd2cSJim Jagielski                 InsertSpannedRow( pDoc, nFirst, 1 );
1425*b1cdbd2cSJim Jagielski                 SwTableLine* pRow = GetTabLines()[ nFirst ];
1426*b1cdbd2cSJim Jagielski                 SwFrmFmt* pRowFmt = pRow->ClaimFrmFmt();
1427*b1cdbd2cSJim Jagielski                 SwFmtFrmSize aFSz( pRowFmt->GetFrmSize() );
1428*b1cdbd2cSJim Jagielski                 aFSz.SetHeightSizeType( ATT_MIN_SIZE );
1429*b1cdbd2cSJim Jagielski                 aFSz.SetHeight( *pSplit - nLast );
1430*b1cdbd2cSJim Jagielski                 pRowFmt->SetFmtAttr( aFSz );
1431*b1cdbd2cSJim Jagielski                 nLast = *pSplit;
1432*b1cdbd2cSJim Jagielski                 ++pSplit;
1433*b1cdbd2cSJim Jagielski                 ++nFirst;
1434*b1cdbd2cSJim Jagielski             }
1435*b1cdbd2cSJim Jagielski             if( pSplit != aSplitLines.end() && *pCurr == *pSplit )
1436*b1cdbd2cSJim Jagielski                 ++pSplit;
1437*b1cdbd2cSJim Jagielski             SwTableLine* pRow = GetTabLines()[ nFirst ];
1438*b1cdbd2cSJim Jagielski             SwFrmFmt* pRowFmt = pRow->ClaimFrmFmt();
1439*b1cdbd2cSJim Jagielski             SwFmtFrmSize aFSz( pRowFmt->GetFrmSize() );
1440*b1cdbd2cSJim Jagielski             aFSz.SetHeightSizeType( ATT_MIN_SIZE );
1441*b1cdbd2cSJim Jagielski             aFSz.SetHeight( *pCurr - nLast );
1442*b1cdbd2cSJim Jagielski             pRowFmt->SetFmtAttr( aFSz );
1443*b1cdbd2cSJim Jagielski             nLast = *pCurr;
1444*b1cdbd2cSJim Jagielski             ++pCurr;
1445*b1cdbd2cSJim Jagielski             ++nFirst;
1446*b1cdbd2cSJim Jagielski         }
1447*b1cdbd2cSJim Jagielski     }
1448*b1cdbd2cSJim Jagielski     else
1449*b1cdbd2cSJim Jagielski     {
1450*b1cdbd2cSJim Jagielski         aFndBox.DelFrms( *this );
1451*b1cdbd2cSJim Jagielski         bSameHeight = sal_False;
1452*b1cdbd2cSJim Jagielski     }
1453*b1cdbd2cSJim Jagielski     if( !bSameHeight )
1454*b1cdbd2cSJim Jagielski     {
1455*b1cdbd2cSJim Jagielski         SwLineOffsetArray aLineOffs;
1456*b1cdbd2cSJim Jagielski         lcl_SophisticatedFillLineIndices( aLineOffs, *this, rBoxes, nCnt );
1457*b1cdbd2cSJim Jagielski         SwLineOffsetArray::reverse_iterator pCurr( aLineOffs.rbegin() );
1458*b1cdbd2cSJim Jagielski         while( pCurr != aLineOffs.rend() )
1459*b1cdbd2cSJim Jagielski         {
1460*b1cdbd2cSJim Jagielski             InsertSpannedRow( pDoc, pCurr->first, pCurr->second );
1461*b1cdbd2cSJim Jagielski             ++pCurr;
1462*b1cdbd2cSJim Jagielski         }
1463*b1cdbd2cSJim Jagielski     }
1464*b1cdbd2cSJim Jagielski 
1465*b1cdbd2cSJim Jagielski     std::set< sal_uInt16> aIndices;
1466*b1cdbd2cSJim Jagielski     for( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
1467*b1cdbd2cSJim Jagielski     {
1468*b1cdbd2cSJim Jagielski         ASSERT( rBoxes[i]->getRowSpan() != 1, "Forgot to split?" )
1469*b1cdbd2cSJim Jagielski         if( rBoxes[i]->getRowSpan() > 1 )
1470*b1cdbd2cSJim Jagielski             aIndices.insert( i );
1471*b1cdbd2cSJim Jagielski     }
1472*b1cdbd2cSJim Jagielski 
1473*b1cdbd2cSJim Jagielski     std::set< sal_uInt16 >::iterator pCurrBox = aIndices.begin();
1474*b1cdbd2cSJim Jagielski     while( pCurrBox != aIndices.end() )
1475*b1cdbd2cSJim Jagielski         lcl_UnMerge( *this, *rBoxes[*pCurrBox++], nCnt, bSameHeight );
1476*b1cdbd2cSJim Jagielski 
1477*b1cdbd2cSJim Jagielski     CHECK_TABLE( *this )
1478*b1cdbd2cSJim Jagielski 	//Layout updaten
1479*b1cdbd2cSJim Jagielski 	aFndBox.MakeFrms( *this );
1480*b1cdbd2cSJim Jagielski 
1481*b1cdbd2cSJim Jagielski     return sal_True;
1482*b1cdbd2cSJim Jagielski }
1483*b1cdbd2cSJim Jagielski 
1484*b1cdbd2cSJim Jagielski /** SwTable::InsertRow(..) inserts one or more rows before or behind the selected
1485*b1cdbd2cSJim Jagielski     boxes.
1486*b1cdbd2cSJim Jagielski */
1487*b1cdbd2cSJim Jagielski 
InsertRow(SwDoc * pDoc,const SwSelBoxes & rBoxes,sal_uInt16 nCnt,sal_Bool bBehind)1488*b1cdbd2cSJim Jagielski sal_Bool SwTable::InsertRow( SwDoc* pDoc, const SwSelBoxes& rBoxes,
1489*b1cdbd2cSJim Jagielski 						sal_uInt16 nCnt, sal_Bool bBehind )
1490*b1cdbd2cSJim Jagielski {
1491*b1cdbd2cSJim Jagielski     bool bRet = false;
1492*b1cdbd2cSJim Jagielski     if( IsNewModel() )
1493*b1cdbd2cSJim Jagielski     {
1494*b1cdbd2cSJim Jagielski         CHECK_TABLE( *this )
1495*b1cdbd2cSJim Jagielski         sal_uInt16 nRowIdx = lcl_LineIndex( *this, rBoxes, bBehind );
1496*b1cdbd2cSJim Jagielski         if( nRowIdx < USHRT_MAX )
1497*b1cdbd2cSJim Jagielski         {
1498*b1cdbd2cSJim Jagielski             _FndBox aFndBox( 0, 0 );
1499*b1cdbd2cSJim Jagielski             aFndBox.SetTableLines( rBoxes, *this );
1500*b1cdbd2cSJim Jagielski             aFndBox.DelFrms( *this );
1501*b1cdbd2cSJim Jagielski //             aFndBox.SaveChartData( *this );
1502*b1cdbd2cSJim Jagielski 
1503*b1cdbd2cSJim Jagielski             bRet = true;
1504*b1cdbd2cSJim Jagielski             SwTableLine *pLine = GetTabLines()[ nRowIdx ];
1505*b1cdbd2cSJim Jagielski             SwSelBoxes aLineBoxes;
1506*b1cdbd2cSJim Jagielski             lcl_FillSelBoxes( aLineBoxes, *pLine );
1507*b1cdbd2cSJim Jagielski             _InsertRow( pDoc, aLineBoxes, nCnt, bBehind );
1508*b1cdbd2cSJim Jagielski             sal_uInt16 nBoxCount = pLine->GetTabBoxes().Count();
1509*b1cdbd2cSJim Jagielski             sal_uInt16 nOfs = bBehind ? 0 : 1;
1510*b1cdbd2cSJim Jagielski             for( sal_uInt16 n = 0; n < nCnt; ++n )
1511*b1cdbd2cSJim Jagielski             {
1512*b1cdbd2cSJim Jagielski                 SwTableLine *pNewLine = GetTabLines()[ nRowIdx+nCnt-n-nOfs];
1513*b1cdbd2cSJim Jagielski                 for( sal_uInt16 nCurrBox = 0; nCurrBox < nBoxCount; ++nCurrBox )
1514*b1cdbd2cSJim Jagielski                 {
1515*b1cdbd2cSJim Jagielski                     long nRowSpan = pLine->GetTabBoxes()[nCurrBox]->getRowSpan();
1516*b1cdbd2cSJim Jagielski                     if( bBehind )
1517*b1cdbd2cSJim Jagielski                     {
1518*b1cdbd2cSJim Jagielski                         if( nRowSpan == 1 || nRowSpan == -1 )
1519*b1cdbd2cSJim Jagielski                             nRowSpan = n + 1;
1520*b1cdbd2cSJim Jagielski                         else if( nRowSpan > 1 )
1521*b1cdbd2cSJim Jagielski                             nRowSpan = - nRowSpan;
1522*b1cdbd2cSJim Jagielski                     }
1523*b1cdbd2cSJim Jagielski                     else
1524*b1cdbd2cSJim Jagielski                     {
1525*b1cdbd2cSJim Jagielski                         if( nRowSpan > 0 )
1526*b1cdbd2cSJim Jagielski                             nRowSpan = n + 1;
1527*b1cdbd2cSJim Jagielski                         else
1528*b1cdbd2cSJim Jagielski                             --nRowSpan;
1529*b1cdbd2cSJim Jagielski                     }
1530*b1cdbd2cSJim Jagielski                     pNewLine->GetTabBoxes()[ nCurrBox ]->setRowSpan( nRowSpan - n );
1531*b1cdbd2cSJim Jagielski                 }
1532*b1cdbd2cSJim Jagielski             }
1533*b1cdbd2cSJim Jagielski             if( bBehind )
1534*b1cdbd2cSJim Jagielski                 ++nRowIdx;
1535*b1cdbd2cSJim Jagielski             if( nRowIdx )
1536*b1cdbd2cSJim Jagielski                 lcl_ChangeRowSpan( *this, nCnt, --nRowIdx, true );
1537*b1cdbd2cSJim Jagielski             //Layout update
1538*b1cdbd2cSJim Jagielski             aFndBox.MakeFrms( *this );
1539*b1cdbd2cSJim Jagielski //             aFndBox.RestoreChartData( *this );
1540*b1cdbd2cSJim Jagielski         }
1541*b1cdbd2cSJim Jagielski         CHECK_TABLE( *this )
1542*b1cdbd2cSJim Jagielski     }
1543*b1cdbd2cSJim Jagielski     else
1544*b1cdbd2cSJim Jagielski         bRet = _InsertRow( pDoc, rBoxes, nCnt, bBehind );
1545*b1cdbd2cSJim Jagielski     return bRet;
1546*b1cdbd2cSJim Jagielski }
1547*b1cdbd2cSJim Jagielski 
1548*b1cdbd2cSJim Jagielski /** SwTable::PrepareDelBoxes(..) adjusts the row span attributes for an upcoming
1549*b1cdbd2cSJim Jagielski     deletion of table cells and invalidates the layout of these cells.
1550*b1cdbd2cSJim Jagielski */
1551*b1cdbd2cSJim Jagielski 
PrepareDelBoxes(const SwSelBoxes & rBoxes)1552*b1cdbd2cSJim Jagielski void SwTable::PrepareDelBoxes( const SwSelBoxes& rBoxes )
1553*b1cdbd2cSJim Jagielski {
1554*b1cdbd2cSJim Jagielski     if( IsNewModel() )
1555*b1cdbd2cSJim Jagielski     {
1556*b1cdbd2cSJim Jagielski         for( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
1557*b1cdbd2cSJim Jagielski         {
1558*b1cdbd2cSJim Jagielski             SwTableBox* pBox = rBoxes[i];
1559*b1cdbd2cSJim Jagielski             long nRowSpan = pBox->getRowSpan();
1560*b1cdbd2cSJim Jagielski             if( nRowSpan != 1 && pBox->GetFrmFmt()->GetFrmSize().GetWidth() )
1561*b1cdbd2cSJim Jagielski             {
1562*b1cdbd2cSJim Jagielski                 long nLeft = lcl_Box2LeftBorder( *pBox );
1563*b1cdbd2cSJim Jagielski                 SwTableLine *pLine = pBox->GetUpper();
1564*b1cdbd2cSJim Jagielski                 sal_uInt16 nLinePos = GetTabLines().C40_GETPOS(SwTableLine, pLine);
1565*b1cdbd2cSJim Jagielski                 ASSERT( nLinePos < USHRT_MAX, "Box/table mismatch" )
1566*b1cdbd2cSJim Jagielski                 if( nRowSpan > 1 )
1567*b1cdbd2cSJim Jagielski                 {
1568*b1cdbd2cSJim Jagielski                     if( ++nLinePos < GetTabLines().Count() )
1569*b1cdbd2cSJim Jagielski                     {
1570*b1cdbd2cSJim Jagielski                         pLine = GetTabLines()[ nLinePos ];
1571*b1cdbd2cSJim Jagielski                         pBox = lcl_LeftBorder2Box( nLeft, pLine );
1572*b1cdbd2cSJim Jagielski                         ASSERT( pBox, "RowSpan irritation I" )
1573*b1cdbd2cSJim Jagielski                         if( pBox )
1574*b1cdbd2cSJim Jagielski                             pBox->setRowSpan( --nRowSpan );
1575*b1cdbd2cSJim Jagielski                     }
1576*b1cdbd2cSJim Jagielski                 }
1577*b1cdbd2cSJim Jagielski                 else if( nLinePos > 0 )
1578*b1cdbd2cSJim Jagielski                 {
1579*b1cdbd2cSJim Jagielski                     do
1580*b1cdbd2cSJim Jagielski                     {
1581*b1cdbd2cSJim Jagielski                         pLine = GetTabLines()[ --nLinePos ];
1582*b1cdbd2cSJim Jagielski                         pBox = lcl_LeftBorder2Box( nLeft, pLine );
1583*b1cdbd2cSJim Jagielski                         ASSERT( pBox, "RowSpan irritation II" )
1584*b1cdbd2cSJim Jagielski                         if( pBox )
1585*b1cdbd2cSJim Jagielski                         {
1586*b1cdbd2cSJim Jagielski                             nRowSpan = pBox->getRowSpan();
1587*b1cdbd2cSJim Jagielski                             if( nRowSpan > 1 )
1588*b1cdbd2cSJim Jagielski                             {
1589*b1cdbd2cSJim Jagielski                                 lcl_InvalidateCellFrm( *pBox );
1590*b1cdbd2cSJim Jagielski                                 --nRowSpan;
1591*b1cdbd2cSJim Jagielski                             }
1592*b1cdbd2cSJim Jagielski                             else
1593*b1cdbd2cSJim Jagielski                                 ++nRowSpan;
1594*b1cdbd2cSJim Jagielski                             pBox->setRowSpan( nRowSpan );
1595*b1cdbd2cSJim Jagielski                         }
1596*b1cdbd2cSJim Jagielski                         else
1597*b1cdbd2cSJim Jagielski                             nRowSpan = 1;
1598*b1cdbd2cSJim Jagielski                     }
1599*b1cdbd2cSJim Jagielski                     while( nRowSpan < 0 && nLinePos > 0 );
1600*b1cdbd2cSJim Jagielski                 }
1601*b1cdbd2cSJim Jagielski             }
1602*b1cdbd2cSJim Jagielski         }
1603*b1cdbd2cSJim Jagielski     }
1604*b1cdbd2cSJim Jagielski }
1605*b1cdbd2cSJim Jagielski 
1606*b1cdbd2cSJim Jagielski /** lcl_SearchSelBox(..) adds cells of a given table row to the selection structure
1607*b1cdbd2cSJim Jagielski     if it overlaps with the given x-position range
1608*b1cdbd2cSJim Jagielski */
1609*b1cdbd2cSJim Jagielski 
lcl_SearchSelBox(const SwTable & rTable,SwSelBoxes & rBoxes,long nMin,long nMax,SwTableLine & rLine,bool bChkProtected,bool bColumn)1610*b1cdbd2cSJim Jagielski void lcl_SearchSelBox( const SwTable &rTable, SwSelBoxes& rBoxes, long nMin, long nMax,
1611*b1cdbd2cSJim Jagielski                        SwTableLine& rLine, bool bChkProtected, bool bColumn )
1612*b1cdbd2cSJim Jagielski {
1613*b1cdbd2cSJim Jagielski     long nLeft = 0;
1614*b1cdbd2cSJim Jagielski     long nRight = 0;
1615*b1cdbd2cSJim Jagielski     long nMid = ( nMax + nMin )/ 2;
1616*b1cdbd2cSJim Jagielski     sal_uInt16 nCount = rLine.GetTabBoxes().Count();
1617*b1cdbd2cSJim Jagielski     for( sal_uInt16 nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
1618*b1cdbd2cSJim Jagielski     {
1619*b1cdbd2cSJim Jagielski         SwTableBox* pBox = rLine.GetTabBoxes()[nCurrBox];
1620*b1cdbd2cSJim Jagielski         ASSERT( pBox, "Missing table box" );
1621*b1cdbd2cSJim Jagielski         long nWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
1622*b1cdbd2cSJim Jagielski         nRight += nWidth;
1623*b1cdbd2cSJim Jagielski         if( nRight > nMin )
1624*b1cdbd2cSJim Jagielski         {
1625*b1cdbd2cSJim Jagielski             bool bAdd = false;
1626*b1cdbd2cSJim Jagielski             if( nRight <= nMax )
1627*b1cdbd2cSJim Jagielski                 bAdd = nLeft >= nMin || nRight >= nMid ||
1628*b1cdbd2cSJim Jagielski                        nRight - nMin > nMin - nLeft;
1629*b1cdbd2cSJim Jagielski             else
1630*b1cdbd2cSJim Jagielski                 bAdd = nLeft <= nMid || nRight - nMax < nMax - nLeft;
1631*b1cdbd2cSJim Jagielski             long nRowSpan = pBox->getRowSpan();
1632*b1cdbd2cSJim Jagielski             if( bAdd &&
1633*b1cdbd2cSJim Jagielski                 //( bColumn || nRowSpan > 0 ) &&
1634*b1cdbd2cSJim Jagielski                 ( !bChkProtected ||
1635*b1cdbd2cSJim Jagielski                 !pBox->GetFrmFmt()->GetProtect().IsCntntProtected() ) )
1636*b1cdbd2cSJim Jagielski             {
1637*b1cdbd2cSJim Jagielski                 sal_uInt16 nOldCnt = rBoxes.Count();
1638*b1cdbd2cSJim Jagielski                 rBoxes.Insert( pBox );
1639*b1cdbd2cSJim Jagielski                 if( bColumn && nRowSpan != 1 && nOldCnt < rBoxes.Count() )
1640*b1cdbd2cSJim Jagielski                 {
1641*b1cdbd2cSJim Jagielski                     SwTableBox *pMasterBox = pBox->getRowSpan() > 0 ? pBox
1642*b1cdbd2cSJim Jagielski                         : &pBox->FindStartOfRowSpan( rTable, USHRT_MAX );
1643*b1cdbd2cSJim Jagielski                     lcl_getAllMergedBoxes( rTable, rBoxes, *pMasterBox );
1644*b1cdbd2cSJim Jagielski                 }
1645*b1cdbd2cSJim Jagielski             }
1646*b1cdbd2cSJim Jagielski         }
1647*b1cdbd2cSJim Jagielski         if( nRight >= nMax )
1648*b1cdbd2cSJim Jagielski             break;
1649*b1cdbd2cSJim Jagielski         nLeft = nRight;
1650*b1cdbd2cSJim Jagielski     }
1651*b1cdbd2cSJim Jagielski }
1652*b1cdbd2cSJim Jagielski 
1653*b1cdbd2cSJim Jagielski /** void SwTable::CreateSelection(..) fills the selection structure with table cells
1654*b1cdbd2cSJim Jagielski     for a given SwPaM, ie. start and end position inside a table
1655*b1cdbd2cSJim Jagielski */
1656*b1cdbd2cSJim Jagielski 
CreateSelection(const SwPaM & rPam,SwSelBoxes & rBoxes,const SearchType eSearch,bool bChkProtected) const1657*b1cdbd2cSJim Jagielski void SwTable::CreateSelection(  const SwPaM& rPam, SwSelBoxes& rBoxes,
1658*b1cdbd2cSJim Jagielski     const SearchType eSearch, bool bChkProtected ) const
1659*b1cdbd2cSJim Jagielski {
1660*b1cdbd2cSJim Jagielski     ASSERT( bNewModel, "Don't call me for old tables" );
1661*b1cdbd2cSJim Jagielski     if( !aLines.Count() )
1662*b1cdbd2cSJim Jagielski         return;
1663*b1cdbd2cSJim Jagielski     const SwNode* pStartNd = rPam.GetPoint()->nNode.GetNode().FindTableBoxStartNode();
1664*b1cdbd2cSJim Jagielski     const SwNode* pEndNd = rPam.GetMark()->nNode.GetNode().FindTableBoxStartNode();
1665*b1cdbd2cSJim Jagielski     if( !pStartNd || !pEndNd )
1666*b1cdbd2cSJim Jagielski         return;
1667*b1cdbd2cSJim Jagielski     CreateSelection( pStartNd, pEndNd, rBoxes, eSearch, bChkProtected );
1668*b1cdbd2cSJim Jagielski }
1669*b1cdbd2cSJim Jagielski 
1670*b1cdbd2cSJim Jagielski /** void SwTable::CreateSelection(..) fills the selection structure with table cells
1671*b1cdbd2cSJim Jagielski     for given start and end nodes inside a table
1672*b1cdbd2cSJim Jagielski */
CreateSelection(const SwNode * pStartNd,const SwNode * pEndNd,SwSelBoxes & rBoxes,const SearchType eSearch,bool bChkProtected) const1673*b1cdbd2cSJim Jagielski void SwTable::CreateSelection( const SwNode* pStartNd, const SwNode* pEndNd,
1674*b1cdbd2cSJim Jagielski     SwSelBoxes& rBoxes, const SearchType eSearch, bool bChkProtected ) const
1675*b1cdbd2cSJim Jagielski {
1676*b1cdbd2cSJim Jagielski     // SwSelBoxes aKeepBoxes;
1677*b1cdbd2cSJim Jagielski     if( rBoxes.Count() )
1678*b1cdbd2cSJim Jagielski     {
1679*b1cdbd2cSJim Jagielski         // aKeepBoxes.Insert( &rBoxes );
1680*b1cdbd2cSJim Jagielski 		rBoxes.Remove( sal_uInt16(0), rBoxes.Count() );
1681*b1cdbd2cSJim Jagielski     }
1682*b1cdbd2cSJim Jagielski     // Looking for start and end of the selection given by SwNode-pointer
1683*b1cdbd2cSJim Jagielski     sal_uInt16 nLines = aLines.Count();
1684*b1cdbd2cSJim Jagielski     // nTop becomes the line number of the upper box
1685*b1cdbd2cSJim Jagielski     // nBottom becomes the line number of the lower box
1686*b1cdbd2cSJim Jagielski     sal_uInt16 nTop = 0, nBottom = 0;
1687*b1cdbd2cSJim Jagielski     // nUpperMin becomes the left border value of the upper box
1688*b1cdbd2cSJim Jagielski     // nUpperMax becomes the right border of the upper box
1689*b1cdbd2cSJim Jagielski     // nLowerMin and nLowerMax the borders of the lower box
1690*b1cdbd2cSJim Jagielski     long nUpperMin = 0, nUpperMax = 0;
1691*b1cdbd2cSJim Jagielski     long nLowerMin = 0, nLowerMax = 0;
1692*b1cdbd2cSJim Jagielski     // nFound will incremented if a box is found
1693*b1cdbd2cSJim Jagielski     // 0 => no box found; 1 => the upper box has been found; 2 => both found
1694*b1cdbd2cSJim Jagielski     int nFound = 0;
1695*b1cdbd2cSJim Jagielski     for( sal_uInt16 nRow = 0; nFound < 2 && nRow < nLines; ++nRow )
1696*b1cdbd2cSJim Jagielski     {
1697*b1cdbd2cSJim Jagielski         SwTableLine* pLine = aLines[nRow];
1698*b1cdbd2cSJim Jagielski         ASSERT( pLine, "Missing table line" );
1699*b1cdbd2cSJim Jagielski         sal_uInt16 nCols = pLine->GetTabBoxes().Count();
1700*b1cdbd2cSJim Jagielski         for( sal_uInt16 nCol = 0; nCol < nCols; ++nCol )
1701*b1cdbd2cSJim Jagielski         {
1702*b1cdbd2cSJim Jagielski             SwTableBox* pBox = pLine->GetTabBoxes()[nCol];
1703*b1cdbd2cSJim Jagielski             ASSERT( pBox, "Missing table box" );
1704*b1cdbd2cSJim Jagielski             if( pBox->GetSttNd() == pEndNd || pBox->GetSttNd() == pStartNd )
1705*b1cdbd2cSJim Jagielski             {
1706*b1cdbd2cSJim Jagielski                 if( !bChkProtected ||
1707*b1cdbd2cSJim Jagielski                     !pBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
1708*b1cdbd2cSJim Jagielski                     rBoxes.Insert( pBox );
1709*b1cdbd2cSJim Jagielski                 if( nFound )
1710*b1cdbd2cSJim Jagielski                 {
1711*b1cdbd2cSJim Jagielski                     nBottom = nRow;
1712*b1cdbd2cSJim Jagielski                     lcl_CheckMinMax( nLowerMin, nLowerMax, *pLine, nCol, true );
1713*b1cdbd2cSJim Jagielski                     ++nFound;
1714*b1cdbd2cSJim Jagielski                     break;
1715*b1cdbd2cSJim Jagielski                 }
1716*b1cdbd2cSJim Jagielski                 else
1717*b1cdbd2cSJim Jagielski                 {
1718*b1cdbd2cSJim Jagielski                     nTop = nRow;
1719*b1cdbd2cSJim Jagielski                     lcl_CheckMinMax( nUpperMin, nUpperMax, *pLine, nCol, true );
1720*b1cdbd2cSJim Jagielski                     ++nFound;
1721*b1cdbd2cSJim Jagielski                      // If start and end node are identical, we're nearly done..
1722*b1cdbd2cSJim Jagielski                     if( pEndNd == pStartNd )
1723*b1cdbd2cSJim Jagielski                     {
1724*b1cdbd2cSJim Jagielski                         nBottom = nTop;
1725*b1cdbd2cSJim Jagielski                         nLowerMin = nUpperMin;
1726*b1cdbd2cSJim Jagielski                         nLowerMax = nUpperMax;
1727*b1cdbd2cSJim Jagielski                         ++nFound;
1728*b1cdbd2cSJim Jagielski                     }
1729*b1cdbd2cSJim Jagielski                 }
1730*b1cdbd2cSJim Jagielski             }
1731*b1cdbd2cSJim Jagielski         }
1732*b1cdbd2cSJim Jagielski     }
1733*b1cdbd2cSJim Jagielski     if( nFound < 2 )
1734*b1cdbd2cSJim Jagielski         return; // At least one node was not a part of the given table
1735*b1cdbd2cSJim Jagielski     if( eSearch == SEARCH_ROW )
1736*b1cdbd2cSJim Jagielski     {
1737*b1cdbd2cSJim Jagielski         // Selection of a row is quiet easy:
1738*b1cdbd2cSJim Jagielski         // every (unprotected) box between start and end line
1739*b1cdbd2cSJim Jagielski         // with a positive row span will be collected
1740*b1cdbd2cSJim Jagielski         for( sal_uInt16 nRow = nTop; nRow <= nBottom; ++nRow )
1741*b1cdbd2cSJim Jagielski         {
1742*b1cdbd2cSJim Jagielski             SwTableLine* pLine = aLines[nRow];
1743*b1cdbd2cSJim Jagielski             ASSERT( pLine, "Missing table line" );
1744*b1cdbd2cSJim Jagielski             sal_uInt16 nCount = pLine->GetTabBoxes().Count();
1745*b1cdbd2cSJim Jagielski             for( sal_uInt16 nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
1746*b1cdbd2cSJim Jagielski             {
1747*b1cdbd2cSJim Jagielski                 SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
1748*b1cdbd2cSJim Jagielski                 ASSERT( pBox, "Missing table box" );
1749*b1cdbd2cSJim Jagielski 				if( pBox->getRowSpan() > 0 && ( !bChkProtected ||
1750*b1cdbd2cSJim Jagielski                     !pBox->GetFrmFmt()->GetProtect().IsCntntProtected() ) )
1751*b1cdbd2cSJim Jagielski                     rBoxes.Insert( pBox );
1752*b1cdbd2cSJim Jagielski             }
1753*b1cdbd2cSJim Jagielski         }
1754*b1cdbd2cSJim Jagielski         return;
1755*b1cdbd2cSJim Jagielski     }
1756*b1cdbd2cSJim Jagielski     bool bCombine = nTop == nBottom;
1757*b1cdbd2cSJim Jagielski     if( !bCombine )
1758*b1cdbd2cSJim Jagielski     {
1759*b1cdbd2cSJim Jagielski         long nMinWidth = nUpperMax - nUpperMin;
1760*b1cdbd2cSJim Jagielski         long nTmp = nLowerMax - nLowerMin;
1761*b1cdbd2cSJim Jagielski         if( nMinWidth > nTmp )
1762*b1cdbd2cSJim Jagielski             nMinWidth = nTmp;
1763*b1cdbd2cSJim Jagielski         nTmp = nLowerMax < nUpperMax ? nLowerMax : nUpperMax;
1764*b1cdbd2cSJim Jagielski         nTmp -= ( nLowerMin < nUpperMin ) ? nUpperMin : nLowerMin;
1765*b1cdbd2cSJim Jagielski         // If the overlapping between upper and lower box is less than half
1766*b1cdbd2cSJim Jagielski         // of the width (of the smaller cell), bCombine is set,
1767*b1cdbd2cSJim Jagielski         // e.g. if upper and lower cell are in different columns
1768*b1cdbd2cSJim Jagielski         bCombine = ( nTmp + nTmp < nMinWidth );
1769*b1cdbd2cSJim Jagielski     }
1770*b1cdbd2cSJim Jagielski     if( bCombine )
1771*b1cdbd2cSJim Jagielski     {
1772*b1cdbd2cSJim Jagielski         if( nUpperMin < nLowerMin )
1773*b1cdbd2cSJim Jagielski             nLowerMin = nUpperMin;
1774*b1cdbd2cSJim Jagielski         else
1775*b1cdbd2cSJim Jagielski             nUpperMin = nLowerMin;
1776*b1cdbd2cSJim Jagielski         if( nUpperMax > nLowerMax )
1777*b1cdbd2cSJim Jagielski             nLowerMax = nUpperMax;
1778*b1cdbd2cSJim Jagielski         else
1779*b1cdbd2cSJim Jagielski             nUpperMax = nLowerMax;
1780*b1cdbd2cSJim Jagielski     }
1781*b1cdbd2cSJim Jagielski     const bool bColumn = eSearch == SEARCH_COL;
1782*b1cdbd2cSJim Jagielski     if( bColumn )
1783*b1cdbd2cSJim Jagielski     {
1784*b1cdbd2cSJim Jagielski         for( sal_uInt16 i = 0; i < nTop; ++i )
1785*b1cdbd2cSJim Jagielski             lcl_SearchSelBox( *this, rBoxes, nUpperMin, nUpperMax,
1786*b1cdbd2cSJim Jagielski                               *aLines[i], bChkProtected, bColumn );
1787*b1cdbd2cSJim Jagielski     }
1788*b1cdbd2cSJim Jagielski 
1789*b1cdbd2cSJim Jagielski     {
1790*b1cdbd2cSJim Jagielski         long nMin = nUpperMin < nLowerMin ? nUpperMin : nLowerMin;
1791*b1cdbd2cSJim Jagielski         long nMax = nUpperMax < nLowerMax ? nLowerMax : nUpperMax;
1792*b1cdbd2cSJim Jagielski         for( sal_uInt16 i = nTop; i <= nBottom; ++i )
1793*b1cdbd2cSJim Jagielski             lcl_SearchSelBox( *this, rBoxes, nMin, nMax, *aLines[i],
1794*b1cdbd2cSJim Jagielski                               bChkProtected, bColumn );
1795*b1cdbd2cSJim Jagielski     }
1796*b1cdbd2cSJim Jagielski     /* if( nTop + 1 < nBottom )
1797*b1cdbd2cSJim Jagielski     {
1798*b1cdbd2cSJim Jagielski         long nInnerMin = nUpperMin < nLowerMin ? nLowerMin : nUpperMin;
1799*b1cdbd2cSJim Jagielski         long nInnerMax = nUpperMax < nLowerMax ? nUpperMax : nLowerMax;
1800*b1cdbd2cSJim Jagielski         for( sal_uInt16 i = nTop + 1; i < nBottom; ++i )
1801*b1cdbd2cSJim Jagielski             lcl_SearchSelBox( *this, rBoxes, nInnerMin, nInnerMax, *aLines[i],
1802*b1cdbd2cSJim Jagielski                               bChkProtected, bColumn );
1803*b1cdbd2cSJim Jagielski     }
1804*b1cdbd2cSJim Jagielski     if( bCombine ) // => nUpperMin == nLowerMin, nUpperMax == nLowerMax
1805*b1cdbd2cSJim Jagielski     {
1806*b1cdbd2cSJim Jagielski         if( nBottom > nTop )
1807*b1cdbd2cSJim Jagielski             lcl_SearchSelBox( *this, rBoxes, nUpperMin, nUpperMax, *aLines[nTop],
1808*b1cdbd2cSJim Jagielski                               bChkProtected, bColumn );
1809*b1cdbd2cSJim Jagielski         lcl_SearchSelBox( *this, rBoxes, nLowerMin, nLowerMax, *aLines[nBottom],
1810*b1cdbd2cSJim Jagielski                           bChkProtected, bColumn );
1811*b1cdbd2cSJim Jagielski     }
1812*b1cdbd2cSJim Jagielski     else if( aKeepBoxes.Count() )
1813*b1cdbd2cSJim Jagielski     {
1814*b1cdbd2cSJim Jagielski         long nMin = nUpperMin < nLowerMin ? nUpperMin : nLowerMin;
1815*b1cdbd2cSJim Jagielski         long nMax = nUpperMax < nLowerMax ? nLowerMax : nUpperMax;
1816*b1cdbd2cSJim Jagielski         SwSelBoxes aCandidates;
1817*b1cdbd2cSJim Jagielski         for( sal_uInt16 i = nTop; i <= nBottom; ++i )
1818*b1cdbd2cSJim Jagielski             lcl_SearchSelBox( *this, aCandidates, nMin, nMax, *aLines[i],
1819*b1cdbd2cSJim Jagielski                               bChkProtected, bColumn );
1820*b1cdbd2cSJim Jagielski         sal_uInt16 nOld = 0, nNew = 0;
1821*b1cdbd2cSJim Jagielski         while ( nOld < aKeepBoxes.Count() && nNew < aCandidates.Count() )
1822*b1cdbd2cSJim Jagielski         {
1823*b1cdbd2cSJim Jagielski             const SwTableBox* pPOld = *( aKeepBoxes.GetData() + nOld );
1824*b1cdbd2cSJim Jagielski             SwTableBox* pPNew = *( aCandidates.GetData() + nNew );
1825*b1cdbd2cSJim Jagielski             if( pPOld == pPNew )
1826*b1cdbd2cSJim Jagielski             {   // this box will stay
1827*b1cdbd2cSJim Jagielski                 rBoxes.Insert( pPNew );
1828*b1cdbd2cSJim Jagielski                 ++nOld;
1829*b1cdbd2cSJim Jagielski                 ++nNew;
1830*b1cdbd2cSJim Jagielski             }
1831*b1cdbd2cSJim Jagielski             else if( pPOld->GetSttIdx() < pPNew->GetSttIdx() )
1832*b1cdbd2cSJim Jagielski                 ++nOld;
1833*b1cdbd2cSJim Jagielski             else
1834*b1cdbd2cSJim Jagielski                 ++nNew;
1835*b1cdbd2cSJim Jagielski         }
1836*b1cdbd2cSJim Jagielski     } */
1837*b1cdbd2cSJim Jagielski     if( bColumn )
1838*b1cdbd2cSJim Jagielski     {
1839*b1cdbd2cSJim Jagielski         for( sal_uInt16 i = nBottom + 1; i < nLines; ++i )
1840*b1cdbd2cSJim Jagielski             lcl_SearchSelBox( *this, rBoxes, nLowerMin, nLowerMax, *aLines[i],
1841*b1cdbd2cSJim Jagielski                               bChkProtected, true );
1842*b1cdbd2cSJim Jagielski     }
1843*b1cdbd2cSJim Jagielski }
1844*b1cdbd2cSJim Jagielski 
1845*b1cdbd2cSJim Jagielski /** void SwTable::ExpandColumnSelection(..) adds cell to the give selection to
1846*b1cdbd2cSJim Jagielski     assure that at least one cell of every row is part of the selection.
1847*b1cdbd2cSJim Jagielski */
1848*b1cdbd2cSJim Jagielski 
ExpandColumnSelection(SwSelBoxes & rBoxes,long & rMin,long & rMax) const1849*b1cdbd2cSJim Jagielski void SwTable::ExpandColumnSelection( SwSelBoxes& rBoxes, long &rMin, long &rMax ) const
1850*b1cdbd2cSJim Jagielski {
1851*b1cdbd2cSJim Jagielski     ASSERT( bNewModel, "Don't call me for old tables" );
1852*b1cdbd2cSJim Jagielski     rMin = 0;
1853*b1cdbd2cSJim Jagielski     rMax = 0;
1854*b1cdbd2cSJim Jagielski     if( !aLines.Count() || !rBoxes.Count() )
1855*b1cdbd2cSJim Jagielski         return;
1856*b1cdbd2cSJim Jagielski 
1857*b1cdbd2cSJim Jagielski     sal_uInt16 nLineCnt = aLines.Count();
1858*b1cdbd2cSJim Jagielski     sal_uInt16 nBoxCnt = rBoxes.Count();
1859*b1cdbd2cSJim Jagielski     sal_uInt16 nBox = 0;
1860*b1cdbd2cSJim Jagielski     for( sal_uInt16 nRow = 0; nRow < nLineCnt && nBox < nBoxCnt; ++nRow )
1861*b1cdbd2cSJim Jagielski     {
1862*b1cdbd2cSJim Jagielski         SwTableLine* pLine = aLines[nRow];
1863*b1cdbd2cSJim Jagielski         ASSERT( pLine, "Missing table line" );
1864*b1cdbd2cSJim Jagielski         sal_uInt16 nCols = pLine->GetTabBoxes().Count();
1865*b1cdbd2cSJim Jagielski         for( sal_uInt16 nCol = 0; nCol < nCols; ++nCol )
1866*b1cdbd2cSJim Jagielski         {
1867*b1cdbd2cSJim Jagielski             SwTableBox* pBox = pLine->GetTabBoxes()[nCol];
1868*b1cdbd2cSJim Jagielski             ASSERT( pBox, "Missing table box" );
1869*b1cdbd2cSJim Jagielski             if( pBox == rBoxes[nBox] )
1870*b1cdbd2cSJim Jagielski             {
1871*b1cdbd2cSJim Jagielski                 lcl_CheckMinMax( rMin, rMax, *pLine, nCol, nBox == 0 );
1872*b1cdbd2cSJim Jagielski                 if( ++nBox >= nBoxCnt )
1873*b1cdbd2cSJim Jagielski                     break;
1874*b1cdbd2cSJim Jagielski             }
1875*b1cdbd2cSJim Jagielski         }
1876*b1cdbd2cSJim Jagielski     }
1877*b1cdbd2cSJim Jagielski     nBox = 0;
1878*b1cdbd2cSJim Jagielski     for( sal_uInt16 nRow = 0; nRow < nLineCnt; ++nRow )
1879*b1cdbd2cSJim Jagielski     {
1880*b1cdbd2cSJim Jagielski         SwTableLine* pLine = aLines[nRow];
1881*b1cdbd2cSJim Jagielski         sal_uInt16 nCols = pLine->GetTabBoxes().Count();
1882*b1cdbd2cSJim Jagielski         long nLeft = 0;
1883*b1cdbd2cSJim Jagielski         long nRight = 0;
1884*b1cdbd2cSJim Jagielski         for( sal_uInt16 nCurrBox = 0; nCurrBox < nCols; ++nCurrBox )
1885*b1cdbd2cSJim Jagielski         {
1886*b1cdbd2cSJim Jagielski             nLeft = nRight;
1887*b1cdbd2cSJim Jagielski             SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
1888*b1cdbd2cSJim Jagielski             nRight += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
1889*b1cdbd2cSJim Jagielski             if( nLeft >= rMin && nRight <= rMax )
1890*b1cdbd2cSJim Jagielski                 rBoxes.Insert( pBox );
1891*b1cdbd2cSJim Jagielski         }
1892*b1cdbd2cSJim Jagielski     }
1893*b1cdbd2cSJim Jagielski }
1894*b1cdbd2cSJim Jagielski 
1895*b1cdbd2cSJim Jagielski /** SwTable::PrepareDeleteCol(..) adjusts the widths of the neighbour cells of
1896*b1cdbd2cSJim Jagielski     a cell selection for an upcoming (column) deletion
1897*b1cdbd2cSJim Jagielski */
PrepareDeleteCol(long nMin,long nMax)1898*b1cdbd2cSJim Jagielski void SwTable::PrepareDeleteCol( long nMin, long nMax )
1899*b1cdbd2cSJim Jagielski {
1900*b1cdbd2cSJim Jagielski     ASSERT( bNewModel, "Don't call me for old tables" );
1901*b1cdbd2cSJim Jagielski     if( !aLines.Count() || nMax < nMin )
1902*b1cdbd2cSJim Jagielski         return;
1903*b1cdbd2cSJim Jagielski     long nMid = nMin ? ( nMin + nMax ) / 2 : 0;
1904*b1cdbd2cSJim Jagielski 	const SwTwips nTabSize = GetFrmFmt()->GetFrmSize().GetWidth();
1905*b1cdbd2cSJim Jagielski     if( nTabSize == nMax )
1906*b1cdbd2cSJim Jagielski         nMid = nMax;
1907*b1cdbd2cSJim Jagielski     sal_uInt16 nLineCnt = aLines.Count();
1908*b1cdbd2cSJim Jagielski     for( sal_uInt16 nRow = 0; nRow < nLineCnt; ++nRow )
1909*b1cdbd2cSJim Jagielski     {
1910*b1cdbd2cSJim Jagielski         SwTableLine* pLine = aLines[nRow];
1911*b1cdbd2cSJim Jagielski         sal_uInt16 nCols = pLine->GetTabBoxes().Count();
1912*b1cdbd2cSJim Jagielski         long nLeft = 0;
1913*b1cdbd2cSJim Jagielski         long nRight = 0;
1914*b1cdbd2cSJim Jagielski         for( sal_uInt16 nCurrBox = 0; nCurrBox < nCols; ++nCurrBox )
1915*b1cdbd2cSJim Jagielski         {
1916*b1cdbd2cSJim Jagielski             nLeft = nRight;
1917*b1cdbd2cSJim Jagielski             SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
1918*b1cdbd2cSJim Jagielski             nRight += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
1919*b1cdbd2cSJim Jagielski             if( nRight < nMin )
1920*b1cdbd2cSJim Jagielski                 continue;
1921*b1cdbd2cSJim Jagielski             if( nLeft > nMax )
1922*b1cdbd2cSJim Jagielski                 break;
1923*b1cdbd2cSJim Jagielski             long nNewWidth = -1;
1924*b1cdbd2cSJim Jagielski             if( nLeft < nMin )
1925*b1cdbd2cSJim Jagielski             {
1926*b1cdbd2cSJim Jagielski                 if( nRight <= nMax )
1927*b1cdbd2cSJim Jagielski                     nNewWidth = nMid - nLeft;
1928*b1cdbd2cSJim Jagielski             }
1929*b1cdbd2cSJim Jagielski             else if( nRight > nMax )
1930*b1cdbd2cSJim Jagielski                 nNewWidth = nRight - nMid;
1931*b1cdbd2cSJim Jagielski             else
1932*b1cdbd2cSJim Jagielski                 nNewWidth = 0;
1933*b1cdbd2cSJim Jagielski             if( nNewWidth >= 0 )
1934*b1cdbd2cSJim Jagielski             {
1935*b1cdbd2cSJim Jagielski                 SwFrmFmt* pFrmFmt = pBox->ClaimFrmFmt();
1936*b1cdbd2cSJim Jagielski                 SwFmtFrmSize aFrmSz( pFrmFmt->GetFrmSize() );
1937*b1cdbd2cSJim Jagielski                 aFrmSz.SetWidth( nNewWidth );
1938*b1cdbd2cSJim Jagielski                 pFrmFmt->SetFmtAttr( aFrmSz );
1939*b1cdbd2cSJim Jagielski             }
1940*b1cdbd2cSJim Jagielski         }
1941*b1cdbd2cSJim Jagielski     }
1942*b1cdbd2cSJim Jagielski }
1943*b1cdbd2cSJim Jagielski 
1944*b1cdbd2cSJim Jagielski 
1945*b1cdbd2cSJim Jagielski 
1946*b1cdbd2cSJim Jagielski /** SwTable::ExpandSelection(..) adds all boxes to the box selections which are
1947*b1cdbd2cSJim Jagielski     overlapped by it.
1948*b1cdbd2cSJim Jagielski */
1949*b1cdbd2cSJim Jagielski 
ExpandSelection(SwSelBoxes & rBoxes) const1950*b1cdbd2cSJim Jagielski void SwTable::ExpandSelection( SwSelBoxes& rBoxes ) const
1951*b1cdbd2cSJim Jagielski {
1952*b1cdbd2cSJim Jagielski     for( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
1953*b1cdbd2cSJim Jagielski     {
1954*b1cdbd2cSJim Jagielski         SwTableBox *pBox = rBoxes[i];
1955*b1cdbd2cSJim Jagielski         long nRowSpan = pBox->getRowSpan();
1956*b1cdbd2cSJim Jagielski         if( nRowSpan != 1 )
1957*b1cdbd2cSJim Jagielski         {
1958*b1cdbd2cSJim Jagielski             SwTableBox *pMasterBox = nRowSpan > 0 ? pBox
1959*b1cdbd2cSJim Jagielski                     : &pBox->FindStartOfRowSpan( *this, USHRT_MAX );
1960*b1cdbd2cSJim Jagielski             lcl_getAllMergedBoxes( *this, rBoxes, *pMasterBox );
1961*b1cdbd2cSJim Jagielski         }
1962*b1cdbd2cSJim Jagielski     }
1963*b1cdbd2cSJim Jagielski }
1964*b1cdbd2cSJim Jagielski 
1965*b1cdbd2cSJim Jagielski /** SwTable::CheckRowSpan(..) looks for the next line without an overlapping to
1966*b1cdbd2cSJim Jagielski     the previous line.
1967*b1cdbd2cSJim Jagielski */
1968*b1cdbd2cSJim Jagielski 
CheckRowSpan(SwTableLinePtr & rpLine,bool bUp) const1969*b1cdbd2cSJim Jagielski void SwTable::CheckRowSpan( SwTableLinePtr &rpLine, bool bUp ) const
1970*b1cdbd2cSJim Jagielski {
1971*b1cdbd2cSJim Jagielski     ASSERT( IsNewModel(), "Don't call me for old tables" );
1972*b1cdbd2cSJim Jagielski     sal_uInt16 nLineIdx = GetTabLines().C40_GETPOS( SwTableLine, rpLine );
1973*b1cdbd2cSJim Jagielski     ASSERT( nLineIdx < GetTabLines().Count(), "Start line out of range" );
1974*b1cdbd2cSJim Jagielski     bool bChange = true;
1975*b1cdbd2cSJim Jagielski     if( bUp )
1976*b1cdbd2cSJim Jagielski     {
1977*b1cdbd2cSJim Jagielski         while( bChange )
1978*b1cdbd2cSJim Jagielski         {
1979*b1cdbd2cSJim Jagielski             bChange = false;
1980*b1cdbd2cSJim Jagielski             rpLine = GetTabLines()[ nLineIdx ];
1981*b1cdbd2cSJim Jagielski             sal_uInt16 nCols = rpLine->GetTabBoxes().Count();
1982*b1cdbd2cSJim Jagielski             for( sal_uInt16 nCol = 0; !bChange && nCol < nCols; ++nCol )
1983*b1cdbd2cSJim Jagielski             {
1984*b1cdbd2cSJim Jagielski                 SwTableBox* pBox = rpLine->GetTabBoxes()[nCol];
1985*b1cdbd2cSJim Jagielski                 if( pBox->getRowSpan() > 1 || pBox->getRowSpan() < -1 )
1986*b1cdbd2cSJim Jagielski                     bChange = true;
1987*b1cdbd2cSJim Jagielski             }
1988*b1cdbd2cSJim Jagielski             if( bChange )
1989*b1cdbd2cSJim Jagielski             {
1990*b1cdbd2cSJim Jagielski                 if( nLineIdx )
1991*b1cdbd2cSJim Jagielski                     --nLineIdx;
1992*b1cdbd2cSJim Jagielski                 else
1993*b1cdbd2cSJim Jagielski                 {
1994*b1cdbd2cSJim Jagielski                     bChange = false;
1995*b1cdbd2cSJim Jagielski                     rpLine = 0;
1996*b1cdbd2cSJim Jagielski                 }
1997*b1cdbd2cSJim Jagielski             }
1998*b1cdbd2cSJim Jagielski         }
1999*b1cdbd2cSJim Jagielski     }
2000*b1cdbd2cSJim Jagielski     else
2001*b1cdbd2cSJim Jagielski     {
2002*b1cdbd2cSJim Jagielski         sal_uInt16 nMaxLine = GetTabLines().Count();
2003*b1cdbd2cSJim Jagielski         while( bChange )
2004*b1cdbd2cSJim Jagielski         {
2005*b1cdbd2cSJim Jagielski             bChange = false;
2006*b1cdbd2cSJim Jagielski             rpLine = GetTabLines()[ nLineIdx ];
2007*b1cdbd2cSJim Jagielski             sal_uInt16 nCols = rpLine->GetTabBoxes().Count();
2008*b1cdbd2cSJim Jagielski             for( sal_uInt16 nCol = 0; !bChange && nCol < nCols; ++nCol )
2009*b1cdbd2cSJim Jagielski             {
2010*b1cdbd2cSJim Jagielski                 SwTableBox* pBox = rpLine->GetTabBoxes()[nCol];
2011*b1cdbd2cSJim Jagielski                 if( pBox->getRowSpan() < 0 )
2012*b1cdbd2cSJim Jagielski                     bChange = true;
2013*b1cdbd2cSJim Jagielski             }
2014*b1cdbd2cSJim Jagielski             if( bChange )
2015*b1cdbd2cSJim Jagielski             {
2016*b1cdbd2cSJim Jagielski                 ++nLineIdx;
2017*b1cdbd2cSJim Jagielski                 if( nLineIdx >= nMaxLine )
2018*b1cdbd2cSJim Jagielski                 {
2019*b1cdbd2cSJim Jagielski                     bChange = false;
2020*b1cdbd2cSJim Jagielski                     rpLine = 0;
2021*b1cdbd2cSJim Jagielski                 }
2022*b1cdbd2cSJim Jagielski             }
2023*b1cdbd2cSJim Jagielski         }
2024*b1cdbd2cSJim Jagielski     }
2025*b1cdbd2cSJim Jagielski }
2026*b1cdbd2cSJim Jagielski 
2027*b1cdbd2cSJim Jagielski // This structure corrects the row span attributes for a top line of a table
2028*b1cdbd2cSJim Jagielski // In a top line no negative row span is allowed, so these have to be corrected.
2029*b1cdbd2cSJim Jagielski // If there has been at least one correction, all values are stored
2030*b1cdbd2cSJim Jagielski // and can be used by undo of table split
SwSaveRowSpan(SwTableBoxes & rBoxes,sal_uInt16 nSplitLn)2031*b1cdbd2cSJim Jagielski SwSaveRowSpan::SwSaveRowSpan( SwTableBoxes& rBoxes, sal_uInt16 nSplitLn )
2032*b1cdbd2cSJim Jagielski     : mnSplitLine( nSplitLn )
2033*b1cdbd2cSJim Jagielski {
2034*b1cdbd2cSJim Jagielski     bool bDontSave = true; // nothing changed, nothing to save
2035*b1cdbd2cSJim Jagielski     sal_uInt16 nColCount = rBoxes.Count();
2036*b1cdbd2cSJim Jagielski     ASSERT( nColCount, "Empty Table Line" )
2037*b1cdbd2cSJim Jagielski     mnRowSpans.resize( nColCount );
2038*b1cdbd2cSJim Jagielski     for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol )
2039*b1cdbd2cSJim Jagielski     {
2040*b1cdbd2cSJim Jagielski         SwTableBox* pBox = rBoxes[nCurrCol];
2041*b1cdbd2cSJim Jagielski         ASSERT( pBox, "Missing Table Box" );
2042*b1cdbd2cSJim Jagielski         long nRowSp = pBox->getRowSpan();
2043*b1cdbd2cSJim Jagielski         mnRowSpans[ nCurrCol ] = nRowSp;
2044*b1cdbd2cSJim Jagielski         if( nRowSp < 0 )
2045*b1cdbd2cSJim Jagielski         {
2046*b1cdbd2cSJim Jagielski             bDontSave = false;
2047*b1cdbd2cSJim Jagielski             nRowSp = -nRowSp;
2048*b1cdbd2cSJim Jagielski             pBox->setRowSpan( nRowSp ); // correction needed
2049*b1cdbd2cSJim Jagielski         }
2050*b1cdbd2cSJim Jagielski     }
2051*b1cdbd2cSJim Jagielski     if( bDontSave )
2052*b1cdbd2cSJim Jagielski         mnRowSpans.clear();
2053*b1cdbd2cSJim Jagielski }
2054*b1cdbd2cSJim Jagielski 
2055*b1cdbd2cSJim Jagielski // This function is called by undo of table split to restore the old row span
2056*b1cdbd2cSJim Jagielski // values at the split line
RestoreRowSpan(const SwSaveRowSpan & rSave)2057*b1cdbd2cSJim Jagielski void SwTable::RestoreRowSpan( const SwSaveRowSpan& rSave )
2058*b1cdbd2cSJim Jagielski {
2059*b1cdbd2cSJim Jagielski     if( !IsNewModel() ) // for new model only
2060*b1cdbd2cSJim Jagielski         return;
2061*b1cdbd2cSJim Jagielski     sal_uInt16 nLineCount = GetTabLines().Count();
2062*b1cdbd2cSJim Jagielski     ASSERT( rSave.mnSplitLine < nLineCount, "Restore behind last line?" )
2063*b1cdbd2cSJim Jagielski     if( rSave.mnSplitLine < nLineCount )
2064*b1cdbd2cSJim Jagielski     {
2065*b1cdbd2cSJim Jagielski         SwTableLine* pLine = GetTabLines()[rSave.mnSplitLine];
2066*b1cdbd2cSJim Jagielski         sal_uInt16 nColCount = pLine->GetTabBoxes().Count();
2067*b1cdbd2cSJim Jagielski         ASSERT( nColCount, "Empty Table Line" )
2068*b1cdbd2cSJim Jagielski         ASSERT( nColCount == rSave.mnRowSpans.size(), "Wrong row span store" )
2069*b1cdbd2cSJim Jagielski         if( nColCount == rSave.mnRowSpans.size() )
2070*b1cdbd2cSJim Jagielski         {
2071*b1cdbd2cSJim Jagielski             for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol )
2072*b1cdbd2cSJim Jagielski             {
2073*b1cdbd2cSJim Jagielski                 SwTableBox* pBox = pLine->GetTabBoxes()[nCurrCol];
2074*b1cdbd2cSJim Jagielski                 ASSERT( pBox, "Missing Table Box" );
2075*b1cdbd2cSJim Jagielski                 long nRowSp = pBox->getRowSpan();
2076*b1cdbd2cSJim Jagielski                 if( nRowSp != rSave.mnRowSpans[ nCurrCol ] )
2077*b1cdbd2cSJim Jagielski                 {
2078*b1cdbd2cSJim Jagielski                     ASSERT( -nRowSp == rSave.mnRowSpans[ nCurrCol ], "Pardon me?!" )
2079*b1cdbd2cSJim Jagielski                     ASSERT( rSave.mnRowSpans[ nCurrCol ] < 0, "Pardon me?!" )
2080*b1cdbd2cSJim Jagielski                     pBox->setRowSpan( -nRowSp );
2081*b1cdbd2cSJim Jagielski 
2082*b1cdbd2cSJim Jagielski                     sal_uInt16 nLine = rSave.mnSplitLine;
2083*b1cdbd2cSJim Jagielski                     if( nLine )
2084*b1cdbd2cSJim Jagielski                     {
2085*b1cdbd2cSJim Jagielski                         long nLeftBorder = lcl_Box2LeftBorder( *pBox );
2086*b1cdbd2cSJim Jagielski                         SwTableBox* pNext;
2087*b1cdbd2cSJim Jagielski                         do
2088*b1cdbd2cSJim Jagielski                         {
2089*b1cdbd2cSJim Jagielski                             pNext = lcl_LeftBorder2Box( nLeftBorder, GetTabLines()[--nLine] );
2090*b1cdbd2cSJim Jagielski                             if( pNext )
2091*b1cdbd2cSJim Jagielski                             {
2092*b1cdbd2cSJim Jagielski                                 pBox = pNext;
2093*b1cdbd2cSJim Jagielski                                 long nNewSpan = pBox->getRowSpan();
2094*b1cdbd2cSJim Jagielski                                 if( pBox->getRowSpan() < 1 )
2095*b1cdbd2cSJim Jagielski                                     nNewSpan -= nRowSp;
2096*b1cdbd2cSJim Jagielski                                 else
2097*b1cdbd2cSJim Jagielski                                 {
2098*b1cdbd2cSJim Jagielski                                     nNewSpan += nRowSp;
2099*b1cdbd2cSJim Jagielski                                     pNext = 0;
2100*b1cdbd2cSJim Jagielski                                 }
2101*b1cdbd2cSJim Jagielski                                 pBox->setRowSpan( nNewSpan );
2102*b1cdbd2cSJim Jagielski                             }
2103*b1cdbd2cSJim Jagielski                         } while( nLine && pNext );
2104*b1cdbd2cSJim Jagielski                     }
2105*b1cdbd2cSJim Jagielski                 }
2106*b1cdbd2cSJim Jagielski             }
2107*b1cdbd2cSJim Jagielski         }
2108*b1cdbd2cSJim Jagielski     }
2109*b1cdbd2cSJim Jagielski }
2110*b1cdbd2cSJim Jagielski 
CleanUpTopRowSpan(sal_uInt16 nSplitLine)2111*b1cdbd2cSJim Jagielski SwSaveRowSpan* SwTable::CleanUpTopRowSpan( sal_uInt16 nSplitLine )
2112*b1cdbd2cSJim Jagielski {
2113*b1cdbd2cSJim Jagielski     SwSaveRowSpan* pRet = 0;
2114*b1cdbd2cSJim Jagielski     if( !IsNewModel() )
2115*b1cdbd2cSJim Jagielski         return pRet;
2116*b1cdbd2cSJim Jagielski     pRet = new SwSaveRowSpan( GetTabLines()[0]->GetTabBoxes(), nSplitLine );
2117*b1cdbd2cSJim Jagielski     if( pRet->mnRowSpans.size() == 0 )
2118*b1cdbd2cSJim Jagielski     {
2119*b1cdbd2cSJim Jagielski         delete pRet;
2120*b1cdbd2cSJim Jagielski         pRet = 0;
2121*b1cdbd2cSJim Jagielski     }
2122*b1cdbd2cSJim Jagielski     return pRet;
2123*b1cdbd2cSJim Jagielski }
2124*b1cdbd2cSJim Jagielski 
CleanUpBottomRowSpan(sal_uInt16 nDelLines)2125*b1cdbd2cSJim Jagielski void SwTable::CleanUpBottomRowSpan( sal_uInt16 nDelLines )
2126*b1cdbd2cSJim Jagielski {
2127*b1cdbd2cSJim Jagielski     if( !IsNewModel() )
2128*b1cdbd2cSJim Jagielski         return;
2129*b1cdbd2cSJim Jagielski     sal_uInt16 nLastLine = GetTabLines().Count()-1;
2130*b1cdbd2cSJim Jagielski     SwTableLine* pLine = GetTabLines()[nLastLine];
2131*b1cdbd2cSJim Jagielski     sal_uInt16 nColCount = pLine->GetTabBoxes().Count();
2132*b1cdbd2cSJim Jagielski     ASSERT( nColCount, "Empty Table Line" )
2133*b1cdbd2cSJim Jagielski     for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol )
2134*b1cdbd2cSJim Jagielski     {
2135*b1cdbd2cSJim Jagielski         SwTableBox* pBox = pLine->GetTabBoxes()[nCurrCol];
2136*b1cdbd2cSJim Jagielski         ASSERT( pBox, "Missing Table Box" );
2137*b1cdbd2cSJim Jagielski         long nRowSp = pBox->getRowSpan();
2138*b1cdbd2cSJim Jagielski         if( nRowSp < 0 )
2139*b1cdbd2cSJim Jagielski             nRowSp = -nRowSp;
2140*b1cdbd2cSJim Jagielski         if( nRowSp > 1 )
2141*b1cdbd2cSJim Jagielski         {
2142*b1cdbd2cSJim Jagielski             lcl_ChangeRowSpan( *this, -static_cast<long>(nDelLines), nLastLine, false );
2143*b1cdbd2cSJim Jagielski             break;
2144*b1cdbd2cSJim Jagielski         }
2145*b1cdbd2cSJim Jagielski     }
2146*b1cdbd2cSJim Jagielski }
2147*b1cdbd2cSJim Jagielski 
2148*b1cdbd2cSJim Jagielski #ifdef DBG_UTIL
2149*b1cdbd2cSJim Jagielski 
2150*b1cdbd2cSJim Jagielski struct RowSpanCheck
2151*b1cdbd2cSJim Jagielski {
2152*b1cdbd2cSJim Jagielski     long nRowSpan;
2153*b1cdbd2cSJim Jagielski     SwTwips nLeft;
2154*b1cdbd2cSJim Jagielski     SwTwips nRight;
2155*b1cdbd2cSJim Jagielski };
2156*b1cdbd2cSJim Jagielski 
CheckConsistency() const2157*b1cdbd2cSJim Jagielski void SwTable::CheckConsistency() const
2158*b1cdbd2cSJim Jagielski {
2159*b1cdbd2cSJim Jagielski     if( !IsNewModel() )
2160*b1cdbd2cSJim Jagielski         return;
2161*b1cdbd2cSJim Jagielski     sal_uInt16 nLineCount = GetTabLines().Count();
2162*b1cdbd2cSJim Jagielski 	const SwTwips nTabSize = GetFrmFmt()->GetFrmSize().GetWidth();
2163*b1cdbd2cSJim Jagielski     SwTwips nLineWidth = 0;
2164*b1cdbd2cSJim Jagielski     std::list< RowSpanCheck > aRowSpanCells;
2165*b1cdbd2cSJim Jagielski     std::list< RowSpanCheck >::iterator aIter = aRowSpanCells.end();
2166*b1cdbd2cSJim Jagielski     for( sal_uInt16 nCurrLine = 0; nCurrLine < nLineCount; ++nCurrLine )
2167*b1cdbd2cSJim Jagielski     {
2168*b1cdbd2cSJim Jagielski         SwTwips nWidth = 0;
2169*b1cdbd2cSJim Jagielski         SwTableLine* pLine = GetTabLines()[nCurrLine];
2170*b1cdbd2cSJim Jagielski         ASSERT( pLine, "Missing Table Line" )
2171*b1cdbd2cSJim Jagielski         sal_uInt16 nColCount = pLine->GetTabBoxes().Count();
2172*b1cdbd2cSJim Jagielski         ASSERT( nColCount, "Empty Table Line" )
2173*b1cdbd2cSJim Jagielski         for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol )
2174*b1cdbd2cSJim Jagielski         {
2175*b1cdbd2cSJim Jagielski             SwTableBox* pBox = pLine->GetTabBoxes()[nCurrCol];
2176*b1cdbd2cSJim Jagielski             ASSERT( pBox, "Missing Table Box" );
2177*b1cdbd2cSJim Jagielski             SwTwips nNewWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth() + nWidth;
2178*b1cdbd2cSJim Jagielski             long nRowSp = pBox->getRowSpan();
2179*b1cdbd2cSJim Jagielski             if( nRowSp < 0 )
2180*b1cdbd2cSJim Jagielski             {
2181*b1cdbd2cSJim Jagielski                 ASSERT( aIter != aRowSpanCells.end(), "Missing master box" )
2182*b1cdbd2cSJim Jagielski #ifdef DBG_UTIL
2183*b1cdbd2cSJim Jagielski                 //RowSpanCheck &rCheck = *aIter;
2184*b1cdbd2cSJim Jagielski #endif
2185*b1cdbd2cSJim Jagielski                 ASSERT( aIter->nLeft == nWidth && aIter->nRight == nNewWidth,
2186*b1cdbd2cSJim Jagielski                     "Wrong position/size of overlapped table box" );
2187*b1cdbd2cSJim Jagielski                 --(aIter->nRowSpan);
2188*b1cdbd2cSJim Jagielski                 ASSERT( aIter->nRowSpan == -nRowSp, "Wrong row span value" );
2189*b1cdbd2cSJim Jagielski                 if( nRowSp == -1 )
2190*b1cdbd2cSJim Jagielski                 {
2191*b1cdbd2cSJim Jagielski                     std::list< RowSpanCheck >::iterator aEraseIter = aIter;
2192*b1cdbd2cSJim Jagielski                     ++aIter;
2193*b1cdbd2cSJim Jagielski                     aRowSpanCells.erase( aEraseIter );
2194*b1cdbd2cSJim Jagielski                 }
2195*b1cdbd2cSJim Jagielski                 else
2196*b1cdbd2cSJim Jagielski                     ++aIter;
2197*b1cdbd2cSJim Jagielski             }
2198*b1cdbd2cSJim Jagielski             else if( nRowSp != 1 )
2199*b1cdbd2cSJim Jagielski             {
2200*b1cdbd2cSJim Jagielski                 ASSERT( nRowSp, "Zero row span?!" );
2201*b1cdbd2cSJim Jagielski                 RowSpanCheck aEntry;
2202*b1cdbd2cSJim Jagielski                 aEntry.nLeft = nWidth;
2203*b1cdbd2cSJim Jagielski                 aEntry.nRight = nNewWidth;
2204*b1cdbd2cSJim Jagielski                 aEntry.nRowSpan = nRowSp;
2205*b1cdbd2cSJim Jagielski                 aRowSpanCells.insert( aIter, aEntry );
2206*b1cdbd2cSJim Jagielski             }
2207*b1cdbd2cSJim Jagielski             nWidth = nNewWidth;
2208*b1cdbd2cSJim Jagielski         }
2209*b1cdbd2cSJim Jagielski         if( !nCurrLine )
2210*b1cdbd2cSJim Jagielski             nLineWidth = nWidth;
2211*b1cdbd2cSJim Jagielski         ASSERT( nWidth == nLineWidth, "Different Line Widths" )
2212*b1cdbd2cSJim Jagielski         ASSERT( nWidth == nTabSize, "Boxen der Line zu klein/gross" )
2213*b1cdbd2cSJim Jagielski         ASSERT( nWidth >= 0 && nWidth <= USHRT_MAX, "Width out of range" )
2214*b1cdbd2cSJim Jagielski         ASSERT( aIter == aRowSpanCells.end(), "Missing overlapped box" )
2215*b1cdbd2cSJim Jagielski         aIter = aRowSpanCells.begin();
2216*b1cdbd2cSJim Jagielski     }
2217*b1cdbd2cSJim Jagielski     bool bEmpty = aRowSpanCells.empty();
2218*b1cdbd2cSJim Jagielski     ASSERT( bEmpty, "Open row span detected" )
2219*b1cdbd2cSJim Jagielski }
2220*b1cdbd2cSJim Jagielski 
2221*b1cdbd2cSJim Jagielski #endif
2222*b1cdbd2cSJim Jagielski 
2223*b1cdbd2cSJim Jagielski 
2224*b1cdbd2cSJim Jagielski #ifdef FINDSTARTENDOFROWSPANCACHE
2225*b1cdbd2cSJim Jagielski /*
2226*b1cdbd2cSJim Jagielski  * A small optimization for FindStartEndOfRowSpan START
2227*b1cdbd2cSJim Jagielski  *
2228*b1cdbd2cSJim Jagielski  * NOTE: Results of some measurement revealed that this cache
2229*b1cdbd2cSJim Jagielski  * does not improve performance!
2230*b1cdbd2cSJim Jagielski  */
2231*b1cdbd2cSJim Jagielski 
2232*b1cdbd2cSJim Jagielski class SwFindRowSpanCache
2233*b1cdbd2cSJim Jagielski {
2234*b1cdbd2cSJim Jagielski private:
2235*b1cdbd2cSJim Jagielski 
2236*b1cdbd2cSJim Jagielski     struct SwFindRowSpanCacheObj
2237*b1cdbd2cSJim Jagielski     {
2238*b1cdbd2cSJim Jagielski         const SwTableBox* mpKeyBox;
2239*b1cdbd2cSJim Jagielski         const SwTableBox* mpCacheBox;
2240*b1cdbd2cSJim Jagielski         sal_uInt16 mnSteps;
2241*b1cdbd2cSJim Jagielski         bool mbStart;
2242*b1cdbd2cSJim Jagielski 
SwFindRowSpanCacheObjSwFindRowSpanCache::SwFindRowSpanCacheObj2243*b1cdbd2cSJim Jagielski         SwFindRowSpanCacheObj( const SwTableBox& rKeyBox, const SwTableBox& rCacheBox, sal_uInt16 nSteps, bool bStart ) :
2244*b1cdbd2cSJim Jagielski             mpKeyBox( &rKeyBox ), mpCacheBox( &rCacheBox ), mnSteps( nSteps ), mbStart( bStart ) {}
2245*b1cdbd2cSJim Jagielski     };
2246*b1cdbd2cSJim Jagielski 
2247*b1cdbd2cSJim Jagielski     std::list< SwFindRowSpanCacheObj > aCache;
2248*b1cdbd2cSJim Jagielski     bool mbUseCache;
2249*b1cdbd2cSJim Jagielski     static SwFindRowSpanCache* mpFindRowSpanCache;
2250*b1cdbd2cSJim Jagielski     SwFindRowSpanCache();
2251*b1cdbd2cSJim Jagielski 
2252*b1cdbd2cSJim Jagielski public:
2253*b1cdbd2cSJim Jagielski 
2254*b1cdbd2cSJim Jagielski     static SwFindRowSpanCache& getSwFindRowSpanCache();
2255*b1cdbd2cSJim Jagielski     const SwTableBox* FindCachedStartEndOfRowSpan( const SwTableBox& rKeyBox, sal_uInt16 nSteps, bool bStart );
2256*b1cdbd2cSJim Jagielski     void SetCachedStartEndOfRowSpan( const SwTableBox& rKeyBox, const SwTableBox& rCacheBox, sal_uInt16 nSteps, bool bStart );
2257*b1cdbd2cSJim Jagielski     void SetUseCache( bool bNew );
2258*b1cdbd2cSJim Jagielski };
2259*b1cdbd2cSJim Jagielski 
2260*b1cdbd2cSJim Jagielski SwFindRowSpanCache* SwFindRowSpanCache::mpFindRowSpanCache = 0;
getSwFindRowSpanCache()2261*b1cdbd2cSJim Jagielski SwFindRowSpanCache& SwFindRowSpanCache::getSwFindRowSpanCache()
2262*b1cdbd2cSJim Jagielski {
2263*b1cdbd2cSJim Jagielski     if ( !mpFindRowSpanCache ) mpFindRowSpanCache = new SwFindRowSpanCache;
2264*b1cdbd2cSJim Jagielski     return *mpFindRowSpanCache;
2265*b1cdbd2cSJim Jagielski }
2266*b1cdbd2cSJim Jagielski 
SwFindRowSpanCache()2267*b1cdbd2cSJim Jagielski SwFindRowSpanCache::SwFindRowSpanCache() : mbUseCache( false )
2268*b1cdbd2cSJim Jagielski {
2269*b1cdbd2cSJim Jagielski }
2270*b1cdbd2cSJim Jagielski 
SetUseCache(bool bNew)2271*b1cdbd2cSJim Jagielski void SwFindRowSpanCache::SetUseCache( bool bNew )
2272*b1cdbd2cSJim Jagielski {
2273*b1cdbd2cSJim Jagielski     mbUseCache = bNew; aCache.clear();
2274*b1cdbd2cSJim Jagielski }
2275*b1cdbd2cSJim Jagielski 
FindCachedStartEndOfRowSpan(const SwTableBox & rKeyBox,sal_uInt16 nSteps,bool bStart)2276*b1cdbd2cSJim Jagielski const SwTableBox* SwFindRowSpanCache::FindCachedStartEndOfRowSpan( const SwTableBox& rKeyBox,
2277*b1cdbd2cSJim Jagielski                                                                    sal_uInt16 nSteps,
2278*b1cdbd2cSJim Jagielski                                                                    bool bStart )
2279*b1cdbd2cSJim Jagielski {
2280*b1cdbd2cSJim Jagielski     static nCallCount = 0;
2281*b1cdbd2cSJim Jagielski     static nSuccessCount = 0;
2282*b1cdbd2cSJim Jagielski     ++nCallCount;
2283*b1cdbd2cSJim Jagielski 
2284*b1cdbd2cSJim Jagielski     if ( !mbUseCache ) return 0;
2285*b1cdbd2cSJim Jagielski 
2286*b1cdbd2cSJim Jagielski     const SwTableBox* pRet = 0;
2287*b1cdbd2cSJim Jagielski 
2288*b1cdbd2cSJim Jagielski     std::list< SwFindRowSpanCacheObj >::const_iterator aIter;
2289*b1cdbd2cSJim Jagielski     for ( aIter = aCache.begin(); aIter != aCache.end(); ++aIter )
2290*b1cdbd2cSJim Jagielski     {
2291*b1cdbd2cSJim Jagielski         if ( aIter->mpKeyBox == &rKeyBox &&
2292*b1cdbd2cSJim Jagielski              aIter->mnSteps == nSteps &&
2293*b1cdbd2cSJim Jagielski              aIter->mbStart == bStart )
2294*b1cdbd2cSJim Jagielski         {
2295*b1cdbd2cSJim Jagielski             pRet = aIter->mpCacheBox;
2296*b1cdbd2cSJim Jagielski             ++nSuccessCount;
2297*b1cdbd2cSJim Jagielski             break;
2298*b1cdbd2cSJim Jagielski         }
2299*b1cdbd2cSJim Jagielski     }
2300*b1cdbd2cSJim Jagielski 
2301*b1cdbd2cSJim Jagielski     return pRet;
2302*b1cdbd2cSJim Jagielski }
2303*b1cdbd2cSJim Jagielski 
2304*b1cdbd2cSJim Jagielski const int FindBoxCacheSize = 2;
2305*b1cdbd2cSJim Jagielski 
SetCachedStartEndOfRowSpan(const SwTableBox & rKeyBox,const SwTableBox & rCacheBox,sal_uInt16 nSteps,bool bStart)2306*b1cdbd2cSJim Jagielski void SwFindRowSpanCache::SetCachedStartEndOfRowSpan( const SwTableBox& rKeyBox,
2307*b1cdbd2cSJim Jagielski                                                      const SwTableBox& rCacheBox,
2308*b1cdbd2cSJim Jagielski                                                      sal_uInt16 nSteps,
2309*b1cdbd2cSJim Jagielski                                                      bool bStart )
2310*b1cdbd2cSJim Jagielski {
2311*b1cdbd2cSJim Jagielski     if ( !mbUseCache ) return;
2312*b1cdbd2cSJim Jagielski 
2313*b1cdbd2cSJim Jagielski     const SwFindRowSpanCacheObj aNew( rKeyBox, rCacheBox, nSteps, bStart );
2314*b1cdbd2cSJim Jagielski     aCache.push_front( aNew );
2315*b1cdbd2cSJim Jagielski     if ( aCache.size() > FindBoxCacheSize )
2316*b1cdbd2cSJim Jagielski         aCache.pop_back();
2317*b1cdbd2cSJim Jagielski }
2318*b1cdbd2cSJim Jagielski 
2319*b1cdbd2cSJim Jagielski /*
2320*b1cdbd2cSJim Jagielski  * A small optimization for FindStartEndOfRowSpan END
2321*b1cdbd2cSJim Jagielski  */
2322*b1cdbd2cSJim Jagielski 
2323*b1cdbd2cSJim Jagielski #endif
2324*b1cdbd2cSJim Jagielski 
2325