Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <hintids.hxx>
21 :
22 : #include <tools/errinf.hxx>
23 : #include <vcl/svapp.hxx>
24 : #include <basegfx/vector/b2dvector.hxx>
25 : #include <svx/svxids.hrc>
26 : #include <editeng/protitem.hxx>
27 : #include <editeng/brushitem.hxx>
28 : #include <editeng/frmdiritem.hxx>
29 : #include <svtools/ruler.hxx>
30 : #include <swwait.hxx>
31 : #include <fmtfsize.hxx>
32 : #include <fmtornt.hxx>
33 : #include <frmatr.hxx>
34 : #include <docary.hxx>
35 : #include <fesh.hxx>
36 : #include <doc.hxx>
37 : #include <cntfrm.hxx>
38 : #include <rootfrm.hxx>
39 : #include <pagefrm.hxx>
40 : #include <tabfrm.hxx>
41 : #include <rowfrm.hxx>
42 : #include <cellfrm.hxx>
43 : #include <flyfrm.hxx>
44 : #include <dflyobj.hxx>
45 : #include <swtable.hxx>
46 : #include <swddetbl.hxx>
47 : #include <ndtxt.hxx>
48 : #include <calc.hxx>
49 : #include <tabcol.hxx>
50 : #include <cellatr.hxx>
51 : #include <pam.hxx>
52 : #include <viscrs.hxx>
53 : #include <tblsel.hxx>
54 : #include <swtblfmt.hxx>
55 : #include <swerror.h>
56 : #include <swundo.hxx>
57 : #include <frmtool.hxx>
58 :
59 : #include <node.hxx>
60 : // OD 2004-05-24 #i28701#
61 : #include <sortedobjs.hxx>
62 :
63 : using namespace ::com::sun::star;
64 :
65 : // also see swtable.cxx
66 : #define COLFUZZY 20L
67 :
68 0 : inline bool IsSame( long nA, long nB ) { return std::abs(nA-nB) <= COLFUZZY; }
69 :
70 : // table column cache
71 : SwTabCols *pLastCols = 0;
72 : const SwTable *pColumnCacheLastTable = 0;
73 : const SwTabFrm *pColumnCacheLastTabFrm = 0;
74 : const SwFrm *pColumnCacheLastCellFrm = 0;
75 :
76 : // table row cache
77 : SwTabCols *pLastRows = 0;
78 : const SwTable *pRowCacheLastTable = 0;
79 : const SwTabFrm *pRowCacheLastTabFrm = 0;
80 : const SwFrm *pRowCacheLastCellFrm = 0;
81 :
82 : class TblWait
83 : {
84 : SwWait *pWait;
85 : public:
86 : TblWait(size_t nCnt, SwFrm *pFrm, SwDocShell &rDocShell, size_t nCnt2 = 0);
87 0 : ~TblWait() { delete pWait; }
88 : };
89 :
90 0 : TblWait::TblWait(size_t const nCnt, SwFrm *pFrm, SwDocShell &rDocShell, size_t const nCnt2):
91 0 : pWait( 0 )
92 : {
93 0 : bool bWait = 20 < nCnt || 20 < nCnt2 || (pFrm &&
94 0 : 20 < pFrm->ImplFindTabFrm()->GetTable()->GetTabLines().size());
95 0 : if( bWait )
96 0 : pWait = new SwWait( rDocShell, true );
97 0 : }
98 :
99 0 : void SwFEShell::ParkCursorInTab()
100 : {
101 0 : SwCursor * pSwCrsr = GetSwCrsr();
102 :
103 : OSL_ENSURE(pSwCrsr, "no SwCursor");
104 :
105 0 : SwPosition aStartPos = *pSwCrsr->GetPoint(), aEndPos = aStartPos;
106 :
107 0 : SwCursor * pTmpCrsr = (SwCursor *) pSwCrsr;
108 :
109 : /* Search least and greatest position in current cursor ring.
110 : */
111 0 : do
112 : {
113 0 : const SwPosition * pPt = pTmpCrsr->GetPoint(),
114 0 : * pMk = pTmpCrsr->GetMark();
115 :
116 0 : if (*pPt < aStartPos)
117 0 : aStartPos = *pPt;
118 :
119 0 : if (*pPt > aEndPos)
120 0 : aEndPos = *pPt;
121 :
122 0 : if (*pMk < aStartPos)
123 0 : aStartPos = *pMk;
124 :
125 0 : if (*pMk > aEndPos)
126 0 : aEndPos = *pMk;
127 :
128 0 : pTmpCrsr = (SwCursor *) pTmpCrsr->GetNext();
129 : }
130 : while (pTmpCrsr != pSwCrsr);
131 :
132 0 : KillPams();
133 :
134 : /* @@@ semantic: SwCursor::operator=() is not implemented @@@ */
135 :
136 : /* Set cursor to end of selection to ensure IsLastCellInRow works
137 : properly. */
138 : {
139 0 : SwCursor aTmpCrsr( aEndPos, 0, false );
140 0 : *pSwCrsr = aTmpCrsr;
141 : }
142 :
143 : /* Move the cursor out of the columns to delete and stay in the
144 : same row. If the table has only one column the cursor will
145 : stay in the row and the shell will take care of it. */
146 0 : if (IsLastCellInRow())
147 : {
148 : /* If the cursor is in the last row of the table, first
149 : try to move it to the previous cell. If that fails move
150 : it to the next cell. */
151 :
152 : {
153 0 : SwCursor aTmpCrsr( aStartPos, 0, false );
154 0 : *pSwCrsr = aTmpCrsr;
155 : }
156 :
157 0 : if (! pSwCrsr->GoPrevCell())
158 : {
159 0 : SwCursor aTmpCrsr( aEndPos, 0, false );
160 0 : *pSwCrsr = aTmpCrsr;
161 0 : pSwCrsr->GoNextCell();
162 : }
163 : }
164 : else
165 : {
166 : /* If the cursor is not in the last row of the table, first
167 : try to move it to the next cell. If that fails move it
168 : to the previous cell. */
169 :
170 : {
171 0 : SwCursor aTmpCrsr( aEndPos, 0, false );
172 0 : *pSwCrsr = aTmpCrsr;
173 : }
174 :
175 0 : if (! pSwCrsr->GoNextCell())
176 : {
177 0 : SwCursor aTmpCrsr( aStartPos, 0, false );
178 0 : *pSwCrsr = aTmpCrsr;
179 0 : pSwCrsr->GoPrevCell();
180 : }
181 0 : }
182 0 : }
183 :
184 : /***********************************************************************
185 : #* Class : SwFEShell
186 : #* Methods : InsertRow(), InsertCol
187 : #***********************************************************************/
188 0 : bool SwFEShell::InsertRow( sal_uInt16 nCnt, bool bBehind )
189 : {
190 : // check if Point/Mark of current cursor are in a table
191 0 : SwFrm *pFrm = GetCurrFrm();
192 0 : if( !pFrm || !pFrm->IsInTab() )
193 0 : return false;
194 :
195 0 : if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
196 : {
197 : ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
198 0 : ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
199 0 : return false;
200 : }
201 :
202 0 : SET_CURR_SHELL( this );
203 0 : StartAllAction();
204 :
205 : // search boxes via the layout
206 0 : SwSelBoxes aBoxes;
207 0 : bool bSelectAll = StartsWithTable() && ExtendedSelectedAll(/*bFootnotes=*/false);
208 0 : if (bSelectAll)
209 : {
210 : // Set the end of the selection to the last paragraph of the last cell of the table.
211 0 : SwPaM* pPaM = getShellCrsr(false);
212 0 : SwNode* pNode = pPaM->Start()->nNode.GetNode().FindTableNode()->EndOfSectionNode();
213 : // pNode is the end node of the table, we want the last node before the end node of the last cell.
214 0 : pPaM->End()->nNode = pNode->GetIndex() - 2;
215 0 : pPaM->End()->nContent.Assign(pPaM->End()->nNode.GetNode().GetCntntNode(), 0);
216 : }
217 0 : GetTblSel( *this, aBoxes, nsSwTblSearchType::TBLSEARCH_ROW );
218 :
219 0 : TblWait( nCnt, pFrm, *GetDoc()->GetDocShell(), aBoxes.size() );
220 :
221 0 : bool bRet = false;
222 0 : if ( aBoxes.size() )
223 0 : bRet = GetDoc()->InsertRow( aBoxes, nCnt, bBehind );
224 :
225 0 : EndAllActionAndCall();
226 0 : return bRet;
227 : }
228 :
229 0 : bool SwFEShell::InsertCol( sal_uInt16 nCnt, bool bBehind )
230 : {
231 : // check if Point/Mark of current cursor are in a table
232 0 : SwFrm *pFrm = GetCurrFrm();
233 0 : if( !pFrm || !pFrm->IsInTab() )
234 0 : return false;
235 :
236 0 : if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
237 : {
238 : ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
239 0 : ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
240 0 : return false;
241 : }
242 :
243 0 : SET_CURR_SHELL( this );
244 :
245 0 : if( !CheckSplitCells( *this, nCnt + 1, nsSwTblSearchType::TBLSEARCH_COL ) )
246 : {
247 : ErrorHandler::HandleError( ERR_TBLINSCOL_ERROR,
248 0 : ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
249 0 : return false;
250 : }
251 :
252 0 : StartAllAction();
253 : // search boxes via the layout
254 0 : SwSelBoxes aBoxes;
255 0 : GetTblSel( *this, aBoxes, nsSwTblSearchType::TBLSEARCH_COL );
256 :
257 0 : TblWait( nCnt, pFrm, *GetDoc()->GetDocShell(), aBoxes.size() );
258 :
259 0 : bool bRet = false;
260 0 : if( !aBoxes.empty() )
261 0 : bRet = GetDoc()->InsertCol( aBoxes, nCnt, bBehind );
262 :
263 0 : EndAllActionAndCall();
264 0 : return bRet;
265 : }
266 :
267 : /***********************************************************************
268 : #* Class : SwFEShell
269 : #* Methoden : DeleteRow(), DeleteCol()
270 : #***********************************************************************/
271 :
272 : /**
273 : Determines if the current cursor is in the last row of the table.
274 : */
275 0 : sal_Bool SwFEShell::IsLastCellInRow() const
276 : {
277 0 : SwTabCols aTabCols;
278 0 : GetTabCols( aTabCols );
279 0 : sal_Bool bResult = sal_False;
280 :
281 0 : if (IsTableRightToLeft())
282 : /* If the table is right-to-left the last row is the most left one. */
283 0 : bResult = 0 == GetCurTabColNum();
284 : else
285 : /* If the table is left-to-right the last row is the most right one. */
286 0 : bResult = aTabCols.Count() == GetCurTabColNum();
287 :
288 0 : return bResult;
289 : }
290 :
291 0 : sal_Bool SwFEShell::DeleteCol()
292 : {
293 : // check if Point/Mark of current cursor are in a table
294 0 : SwFrm *pFrm = GetCurrFrm();
295 0 : if( !pFrm || !pFrm->IsInTab() )
296 0 : return sal_False;
297 :
298 0 : if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
299 : {
300 : ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
301 0 : ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
302 0 : return sal_False;
303 : }
304 :
305 0 : SET_CURR_SHELL( this );
306 0 : StartAllAction();
307 :
308 : // search boxes via the layout
309 : sal_Bool bRet;
310 0 : SwSelBoxes aBoxes;
311 0 : GetTblSel( *this, aBoxes, nsSwTblSearchType::TBLSEARCH_COL );
312 0 : if ( !aBoxes.empty() )
313 : {
314 0 : TblWait( aBoxes.size(), pFrm, *GetDoc()->GetDocShell() );
315 :
316 : // remove crsr from the deletion area.
317 : // Put them behind/on the table; via the
318 : // document position they will be put to the old position
319 0 : while( !pFrm->IsCellFrm() )
320 0 : pFrm = pFrm->GetUpper();
321 :
322 0 : ParkCursorInTab();
323 :
324 : // then delete the column
325 0 : StartUndo(UNDO_COL_DELETE);
326 0 : bRet = GetDoc()->DeleteRowCol( aBoxes, true );
327 0 : EndUndo(UNDO_COL_DELETE);
328 :
329 : }
330 : else
331 0 : bRet = sal_False;
332 :
333 0 : EndAllActionAndCall();
334 0 : return bRet;
335 : }
336 :
337 0 : sal_Bool SwFEShell::DeleteTable()
338 : {
339 0 : return DeleteRow(true);
340 : }
341 :
342 0 : sal_Bool SwFEShell::DeleteRow(bool bCompleteTable)
343 : {
344 : // check if Point/Mark of current cursor are in a table
345 0 : SwFrm *pFrm = GetCurrFrm();
346 0 : if( !pFrm || !pFrm->IsInTab() )
347 0 : return sal_False;
348 :
349 0 : if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
350 : {
351 : ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
352 0 : ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
353 0 : return sal_False;
354 : }
355 :
356 0 : SET_CURR_SHELL( this );
357 0 : StartAllAction();
358 :
359 : // search for boxes via the layout
360 : sal_Bool bRet;
361 0 : SwSelBoxes aBoxes;
362 0 : GetTblSel( *this, aBoxes, nsSwTblSearchType::TBLSEARCH_ROW );
363 :
364 0 : if( !aBoxes.empty() )
365 : {
366 0 : TblWait( aBoxes.size(), pFrm, *GetDoc()->GetDocShell() );
367 :
368 : // Delete cursors from the deletion area.
369 : // Then the cursor is:
370 : // 1. the following row, if there is another row after this
371 : // 2. the preceding row, if there is another row before this
372 : // 3. otherwise below the table
373 : {
374 0 : SwTableNode* pTblNd = ((SwCntntFrm*)pFrm)->GetNode()->FindTableNode();
375 :
376 : // search all boxes / lines
377 0 : _FndBox aFndBox( 0, 0 );
378 : {
379 0 : _FndPara aPara( aBoxes, &aFndBox );
380 0 : ForEach_FndLineCopyCol( pTblNd->GetTable().GetTabLines(), &aPara );
381 : }
382 :
383 0 : if( aFndBox.GetLines().empty() )
384 : {
385 0 : EndAllActionAndCall();
386 0 : return sal_False;
387 : }
388 :
389 0 : KillPams();
390 :
391 0 : _FndBox* pFndBox = &aFndBox;
392 0 : while( 1 == pFndBox->GetLines().size() &&
393 0 : 1 == pFndBox->GetLines().front().GetBoxes().size() )
394 : {
395 0 : _FndBox* pTmp = &pFndBox->GetLines().front().GetBoxes()[0];
396 0 : if( pTmp->GetBox()->GetSttNd() )
397 0 : break; // otherwise too far
398 0 : pFndBox = pTmp;
399 : }
400 :
401 0 : SwTableLine* pDelLine = pFndBox->GetLines().back().GetLine();
402 0 : SwTableBox* pDelBox = pDelLine->GetTabBoxes().back();
403 0 : while( !pDelBox->GetSttNd() )
404 : {
405 0 : SwTableLine* pLn = pDelBox->GetTabLines().back();
406 0 : pDelBox = pLn->GetTabBoxes().back();
407 : }
408 0 : SwTableBox* pNextBox = pDelLine->FindNextBox( pTblNd->GetTable(),
409 0 : pDelBox, true );
410 0 : while( pNextBox &&
411 0 : pNextBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
412 0 : pNextBox = pNextBox->FindNextBox( pTblNd->GetTable(), pNextBox );
413 :
414 0 : if( !pNextBox ) // no next? then the previous
415 : {
416 0 : pDelLine = pFndBox->GetLines().front().GetLine();
417 0 : pDelBox = pDelLine->GetTabBoxes()[ 0 ];
418 0 : while( !pDelBox->GetSttNd() )
419 0 : pDelBox = pDelBox->GetTabLines()[0]->GetTabBoxes()[0];
420 0 : pNextBox = pDelLine->FindPreviousBox( pTblNd->GetTable(),
421 0 : pDelBox, true );
422 0 : while( pNextBox &&
423 0 : pNextBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
424 0 : pNextBox = pNextBox->FindPreviousBox( pTblNd->GetTable(), pNextBox );
425 : }
426 :
427 : sal_uLong nIdx;
428 0 : if( pNextBox ) // put cursor here
429 0 : nIdx = pNextBox->GetSttIdx() + 1;
430 : else // otherwise below the table
431 0 : nIdx = pTblNd->EndOfSectionIndex() + 1;
432 :
433 0 : SwNodeIndex aIdx( GetDoc()->GetNodes(), nIdx );
434 0 : SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
435 0 : if( !pCNd )
436 0 : pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
437 :
438 0 : if( pCNd )
439 : {
440 0 : SwPaM* pPam = GetCrsr();
441 0 : pPam->GetPoint()->nNode = aIdx;
442 0 : pPam->GetPoint()->nContent.Assign( pCNd, 0 );
443 0 : pPam->SetMark(); // both want something
444 0 : pPam->DeleteMark();
445 0 : }
446 : }
447 :
448 : // now delete the lines
449 0 : StartUndo(bCompleteTable ? UNDO_UI_TABLE_DELETE : UNDO_ROW_DELETE);
450 0 : bRet = GetDoc()->DeleteRowCol( aBoxes );
451 0 : EndUndo(bCompleteTable ? UNDO_UI_TABLE_DELETE : UNDO_ROW_DELETE);
452 : }
453 : else
454 0 : bRet = sal_False;
455 :
456 0 : EndAllActionAndCall();
457 0 : return bRet;
458 : }
459 :
460 : /***********************************************************************
461 : #* Class : SwFEShell
462 : #* Methods : MergeTab(), SplitTab()
463 : #***********************************************************************/
464 :
465 0 : sal_uInt16 SwFEShell::MergeTab()
466 : {
467 : // check if Point/Mark of current cursor are in a table
468 0 : sal_uInt16 nRet = TBLMERGE_NOSELECTION;
469 0 : if( IsTableMode() )
470 : {
471 0 : SwShellTableCrsr* pTableCrsr = GetTableCrsr();
472 0 : const SwTableNode* pTblNd = pTableCrsr->GetNode()->FindTableNode();
473 0 : if( pTblNd->GetTable().ISA( SwDDETable ))
474 : {
475 : ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
476 0 : ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
477 : }
478 : else
479 : {
480 0 : SET_CURR_SHELL( this );
481 0 : StartAllAction();
482 :
483 : TblWait(pTableCrsr->GetSelectedBoxesCount(), 0,
484 0 : *GetDoc()->GetDocShell(),
485 0 : pTblNd->GetTable().GetTabLines().size() );
486 :
487 0 : nRet = GetDoc()->MergeTbl( *pTableCrsr );
488 :
489 0 : KillPams();
490 :
491 0 : EndAllActionAndCall();
492 : }
493 : }
494 0 : return nRet;
495 : }
496 :
497 0 : sal_Bool SwFEShell::SplitTab( sal_Bool bVert, sal_uInt16 nCnt, sal_Bool bSameHeight )
498 : {
499 : // check if Point/Mark of current cursor are in a table
500 0 : SwFrm *pFrm = GetCurrFrm();
501 0 : if( !pFrm || !pFrm->IsInTab() )
502 0 : return sal_False;
503 :
504 0 : if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
505 : {
506 : ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
507 0 : ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
508 0 : return sal_False;
509 : }
510 :
511 0 : SET_CURR_SHELL( this );
512 :
513 0 : if( bVert && !CheckSplitCells( *this, nCnt + 1 ) )
514 : {
515 : ErrorHandler::HandleError( ERR_TBLSPLIT_ERROR,
516 0 : ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
517 0 : return sal_False;
518 : }
519 0 : StartAllAction();
520 : // search boxes via the layout
521 : sal_Bool bRet;
522 0 : SwSelBoxes aBoxes;
523 0 : GetTblSel( *this, aBoxes );
524 0 : if( !aBoxes.empty() )
525 : {
526 0 : TblWait( nCnt, pFrm, *GetDoc()->GetDocShell(), aBoxes.size() );
527 :
528 : // now delete the columns
529 0 : bRet = GetDoc()->SplitTbl( aBoxes, bVert, nCnt, bSameHeight );
530 :
531 0 : DELETEZ( pLastCols );
532 0 : DELETEZ( pLastRows );
533 : }
534 : else
535 0 : bRet = sal_False;
536 0 : EndAllActionAndCall();
537 0 : return bRet;
538 : }
539 :
540 : /***********************************************************************
541 : #* Class : SwFEShell
542 : #* Methods : _GetTabCols
543 : #***********************************************************************/
544 0 : void SwFEShell::_GetTabCols( SwTabCols &rToFill, const SwFrm *pBox ) const
545 : {
546 0 : const SwTabFrm *pTab = pBox->FindTabFrm();
547 0 : if ( pLastCols )
548 : {
549 0 : bool bDel = true;
550 0 : if ( pColumnCacheLastTable == pTab->GetTable() )
551 : {
552 0 : bDel = false;
553 0 : SWRECTFN( pTab )
554 :
555 0 : const SwPageFrm* pPage = pTab->FindPageFrm();
556 0 : const sal_uLong nLeftMin = (pTab->Frm().*fnRect->fnGetLeft)() -
557 0 : (pPage->Frm().*fnRect->fnGetLeft)();
558 0 : const sal_uLong nRightMax = (pTab->Frm().*fnRect->fnGetRight)() -
559 0 : (pPage->Frm().*fnRect->fnGetLeft)();
560 :
561 0 : if ( pColumnCacheLastTabFrm != pTab )
562 : {
563 : // if TabFrm was changed, we only shift a little bit
564 : // as the width is the same
565 0 : SWRECTFNX( pColumnCacheLastTabFrm )
566 0 : if( (pColumnCacheLastTabFrm->Frm().*fnRectX->fnGetWidth)() ==
567 0 : (pTab->Frm().*fnRect->fnGetWidth)() )
568 : {
569 0 : pLastCols->SetLeftMin( nLeftMin );
570 :
571 0 : pColumnCacheLastTabFrm = pTab;
572 : }
573 : else
574 0 : bDel = true;
575 : }
576 :
577 0 : if ( !bDel &&
578 0 : pLastCols->GetLeftMin () == (sal_uInt16)nLeftMin &&
579 0 : pLastCols->GetLeft () == (sal_uInt16)(pTab->Prt().*fnRect->fnGetLeft)() &&
580 0 : pLastCols->GetRight () == (sal_uInt16)(pTab->Prt().*fnRect->fnGetRight)()&&
581 0 : pLastCols->GetRightMax() == (sal_uInt16)nRightMax - pLastCols->GetLeftMin() )
582 : {
583 0 : if ( pColumnCacheLastCellFrm != pBox )
584 : {
585 : pTab->GetTable()->GetTabCols( *pLastCols,
586 0 : ((SwCellFrm*)pBox)->GetTabBox(), sal_True);
587 0 : pColumnCacheLastCellFrm = pBox;
588 : }
589 0 : rToFill = *pLastCols;
590 : }
591 : else
592 0 : bDel = true;
593 : }
594 0 : if ( bDel )
595 0 : DELETEZ(pLastCols);
596 : }
597 0 : if ( !pLastCols )
598 : {
599 0 : GetDoc()->GetTabCols( rToFill, 0, (SwCellFrm*)pBox );
600 :
601 0 : pLastCols = new SwTabCols( rToFill );
602 0 : pColumnCacheLastTable = pTab->GetTable();
603 0 : pColumnCacheLastTabFrm = pTab;
604 0 : pColumnCacheLastCellFrm= pBox;
605 : }
606 :
607 : #if OSL_DEBUG_LEVEL > 1
608 : SwTabColsEntry aEntry;
609 : for ( sal_uInt16 i = 0; i < rToFill.Count(); ++i )
610 : {
611 : aEntry = rToFill.GetEntry( i );
612 : (void)aEntry;
613 : }
614 : #endif
615 0 : }
616 :
617 : /***********************************************************************
618 : #* Class : SwFEShell
619 : #* Methods : _GetTabRows
620 : #***********************************************************************/
621 0 : void SwFEShell::_GetTabRows( SwTabCols &rToFill, const SwFrm *pBox ) const
622 : {
623 0 : const SwTabFrm *pTab = pBox->FindTabFrm();
624 0 : if ( pLastRows )
625 : {
626 0 : bool bDel = true;
627 0 : if ( pRowCacheLastTable == pTab->GetTable() )
628 : {
629 0 : bDel = false;
630 0 : SWRECTFN( pTab )
631 0 : const SwPageFrm* pPage = pTab->FindPageFrm();
632 : const long nLeftMin = ( bVert ?
633 0 : pTab->GetPrtLeft() - pPage->Frm().Left() :
634 0 : pTab->GetPrtTop() - pPage->Frm().Top() );
635 0 : const long nLeft = bVert ? LONG_MAX : 0;
636 0 : const long nRight = (pTab->Prt().*fnRect->fnGetHeight)();
637 0 : const long nRightMax = bVert ? nRight : LONG_MAX;
638 :
639 0 : if ( pRowCacheLastTabFrm != pTab ||
640 0 : pRowCacheLastCellFrm != pBox )
641 0 : bDel = true;
642 :
643 0 : if ( !bDel &&
644 0 : pLastRows->GetLeftMin () == nLeftMin &&
645 0 : pLastRows->GetLeft () == nLeft &&
646 0 : pLastRows->GetRight () == nRight &&
647 0 : pLastRows->GetRightMax() == nRightMax )
648 : {
649 0 : rToFill = *pLastRows;
650 : }
651 : else
652 0 : bDel = true;
653 : }
654 0 : if ( bDel )
655 0 : DELETEZ(pLastRows);
656 : }
657 0 : if ( !pLastRows )
658 : {
659 0 : GetDoc()->GetTabRows( rToFill, 0, (SwCellFrm*)pBox );
660 :
661 0 : pLastRows = new SwTabCols( rToFill );
662 0 : pRowCacheLastTable = pTab->GetTable();
663 0 : pRowCacheLastTabFrm = pTab;
664 0 : pRowCacheLastCellFrm= pBox;
665 : }
666 0 : }
667 :
668 : /***********************************************************************
669 : #* Class : SwFEShell
670 : #* Methods : SetTabCols(), GetTabCols()
671 : #***********************************************************************/
672 0 : void SwFEShell::SetTabCols( const SwTabCols &rNew, sal_Bool bCurRowOnly )
673 : {
674 0 : SwFrm *pBox = GetCurrFrm();
675 0 : if( !pBox || !pBox->IsInTab() )
676 0 : return;
677 :
678 0 : SET_CURR_SHELL( this );
679 0 : StartAllAction();
680 :
681 0 : do {
682 0 : pBox = pBox->GetUpper();
683 0 : } while ( !pBox->IsCellFrm() );
684 :
685 0 : GetDoc()->SetTabCols( rNew, bCurRowOnly, 0, (SwCellFrm*)pBox );
686 0 : EndAllActionAndCall();
687 : }
688 :
689 0 : void SwFEShell::GetTabCols( SwTabCols &rToFill ) const
690 : {
691 0 : const SwFrm *pFrm = GetCurrFrm();
692 0 : if( !pFrm || !pFrm->IsInTab() )
693 0 : return;
694 0 : do
695 0 : { pFrm = pFrm->GetUpper();
696 0 : } while ( !pFrm->IsCellFrm() );
697 :
698 0 : _GetTabCols( rToFill, pFrm );
699 : }
700 :
701 0 : void SwFEShell::GetTabRows( SwTabCols &rToFill ) const
702 : {
703 0 : const SwFrm *pFrm = GetCurrFrm();
704 0 : if( !pFrm || !pFrm->IsInTab() )
705 0 : return;
706 0 : do
707 0 : { pFrm = pFrm->GetUpper();
708 0 : } while ( !pFrm->IsCellFrm() );
709 :
710 0 : _GetTabRows( rToFill, pFrm );
711 : }
712 :
713 0 : void SwFEShell::SetTabRows( const SwTabCols &rNew, sal_Bool bCurColOnly )
714 : {
715 0 : SwFrm *pBox = GetCurrFrm();
716 0 : if( !pBox || !pBox->IsInTab() )
717 0 : return;
718 :
719 0 : SET_CURR_SHELL( this );
720 0 : StartAllAction();
721 :
722 0 : do {
723 0 : pBox = pBox->GetUpper();
724 0 : } while ( !pBox->IsCellFrm() );
725 :
726 0 : GetDoc()->SetTabRows( rNew, bCurColOnly, 0, (SwCellFrm*)pBox );
727 0 : EndAllActionAndCall();
728 : }
729 :
730 0 : void SwFEShell::GetMouseTabRows( SwTabCols &rToFill, const Point &rPt ) const
731 : {
732 0 : const SwFrm *pBox = GetBox( rPt );
733 0 : if ( pBox )
734 0 : _GetTabRows( rToFill, pBox );
735 0 : }
736 :
737 0 : void SwFEShell::SetMouseTabRows( const SwTabCols &rNew, sal_Bool bCurColOnly, const Point &rPt )
738 : {
739 0 : const SwFrm *pBox = GetBox( rPt );
740 0 : if( pBox )
741 : {
742 0 : SET_CURR_SHELL( this );
743 0 : StartAllAction();
744 0 : GetDoc()->SetTabRows( rNew, bCurColOnly, 0, (SwCellFrm*)pBox );
745 0 : EndAllActionAndCall();
746 : }
747 0 : }
748 :
749 : /***********************************************************************
750 : * Class : SwFEShell
751 : * Methods : SetRowSplit(), GetRowSplit()
752 : ***********************************************************************/
753 :
754 0 : void SwFEShell::SetRowSplit( const SwFmtRowSplit& rNew )
755 : {
756 0 : SET_CURR_SHELL( this );
757 0 : StartAllAction();
758 0 : GetDoc()->SetRowSplit( *getShellCrsr( false ), rNew );
759 0 : EndAllActionAndCall();
760 0 : }
761 :
762 0 : void SwFEShell::GetRowSplit( SwFmtRowSplit*& rpSz ) const
763 : {
764 0 : GetDoc()->GetRowSplit( *getShellCrsr( false ), rpSz );
765 0 : }
766 :
767 : /***********************************************************************
768 : * Class : SwFEShell
769 : * Methods : SetRowHeight(), GetRowHeight()
770 : ***********************************************************************/
771 0 : void SwFEShell::SetRowHeight( const SwFmtFrmSize &rNew )
772 : {
773 0 : SET_CURR_SHELL( this );
774 0 : StartAllAction();
775 0 : GetDoc()->SetRowHeight( *getShellCrsr( false ), rNew );
776 0 : EndAllActionAndCall();
777 0 : }
778 :
779 : /******************************************************************************
780 : * SwTwips SwFEShell::GetRowHeight() const
781 : ******************************************************************************/
782 0 : void SwFEShell::GetRowHeight( SwFmtFrmSize *& rpSz ) const
783 : {
784 0 : GetDoc()->GetRowHeight( *getShellCrsr( false ), rpSz );
785 0 : }
786 :
787 0 : sal_Bool SwFEShell::BalanceRowHeight( sal_Bool bTstOnly )
788 : {
789 0 : SET_CURR_SHELL( this );
790 0 : if( !bTstOnly )
791 0 : StartAllAction();
792 0 : sal_Bool bRet = GetDoc()->BalanceRowHeight( *getShellCrsr( false ), bTstOnly );
793 0 : if( !bTstOnly )
794 0 : EndAllActionAndCall();
795 0 : return bRet;
796 : }
797 :
798 : /******************************************************************************
799 : * void SwFEShell::SetRowBackground()
800 : ******************************************************************************/
801 0 : void SwFEShell::SetRowBackground( const SvxBrushItem &rNew )
802 : {
803 0 : SET_CURR_SHELL( this );
804 0 : StartAllAction();
805 0 : GetDoc()->SetRowBackground( *getShellCrsr( false ), rNew );
806 0 : EndAllActionAndCall();
807 0 : }
808 :
809 : /******************************************************************************
810 : * SwTwips SwFEShell::GetRowBackground() const
811 : ******************************************************************************/
812 0 : sal_Bool SwFEShell::GetRowBackground( SvxBrushItem &rToFill ) const
813 : {
814 0 : return GetDoc()->GetRowBackground( *getShellCrsr( false ), rToFill );
815 : }
816 :
817 : /***********************************************************************
818 : #* Class : SwFEShell
819 : #* Methods : SetTabBorders(), GetTabBorders()
820 : #***********************************************************************/
821 :
822 0 : void SwFEShell::SetTabBorders( const SfxItemSet& rSet )
823 : {
824 0 : SET_CURR_SHELL( this );
825 0 : StartAllAction();
826 0 : GetDoc()->SetTabBorders( *getShellCrsr( false ), rSet );
827 0 : EndAllActionAndCall();
828 0 : }
829 :
830 0 : void SwFEShell::SetTabLineStyle( const Color* pColor, sal_Bool bSetLine,
831 : const editeng::SvxBorderLine* pBorderLine )
832 : {
833 0 : SET_CURR_SHELL( this );
834 0 : StartAllAction();
835 0 : GetDoc()->SetTabLineStyle( *getShellCrsr( false ),
836 0 : pColor, bSetLine, pBorderLine );
837 0 : EndAllActionAndCall();
838 0 : }
839 :
840 0 : void SwFEShell::GetTabBorders( SfxItemSet& rSet ) const
841 : {
842 0 : GetDoc()->GetTabBorders( *getShellCrsr( false ), rSet );
843 0 : }
844 :
845 : /***********************************************************************
846 : #* Class : SwFEShell
847 : #* Methods : SetBoxBackground(), GetBoxBackground()
848 : #***********************************************************************/
849 0 : void SwFEShell::SetBoxBackground( const SvxBrushItem &rNew )
850 : {
851 0 : SET_CURR_SHELL( this );
852 0 : StartAllAction();
853 0 : GetDoc()->SetBoxAttr( *getShellCrsr( false ), rNew );
854 0 : EndAllActionAndCall();
855 0 : }
856 :
857 0 : sal_Bool SwFEShell::GetBoxBackground( SvxBrushItem &rToFill ) const
858 : {
859 0 : return GetDoc()->GetBoxAttr( *getShellCrsr( false ), rToFill );
860 : }
861 :
862 : /***********************************************************************
863 : #* Class : SwFEShell
864 : #* Methods : SetBoxDirection(), GetBoxDirection()
865 : #***********************************************************************/
866 0 : void SwFEShell::SetBoxDirection( const SvxFrameDirectionItem& rNew )
867 : {
868 0 : SET_CURR_SHELL( this );
869 0 : StartAllAction();
870 0 : GetDoc()->SetBoxAttr( *getShellCrsr( false ), rNew );
871 0 : EndAllActionAndCall();
872 0 : }
873 :
874 0 : sal_Bool SwFEShell::GetBoxDirection( SvxFrameDirectionItem& rToFill ) const
875 : {
876 0 : return GetDoc()->GetBoxAttr( *getShellCrsr( false ), rToFill );
877 : }
878 :
879 : /***********************************************************************
880 : #* Class : SwFEShell
881 : #* Methods : SetBoxAlign, SetBoxAlign
882 : #***********************************************************************/
883 0 : void SwFEShell::SetBoxAlign( sal_uInt16 nAlign )
884 : {
885 0 : SET_CURR_SHELL( this );
886 0 : StartAllAction();
887 0 : GetDoc()->SetBoxAlign( *getShellCrsr( false ), nAlign );
888 0 : EndAllActionAndCall();
889 0 : }
890 :
891 0 : sal_uInt16 SwFEShell::GetBoxAlign() const
892 : {
893 0 : return GetDoc()->GetBoxAlign( *getShellCrsr( false ) );
894 : }
895 :
896 : /***********************************************************************
897 : #* Class : SwFEShell
898 : #* Methods : SetTabBackground(), GetTabBackground()
899 : #***********************************************************************/
900 0 : void SwFEShell::SetTabBackground( const SvxBrushItem &rNew )
901 : {
902 0 : SwFrm *pFrm = GetCurrFrm();
903 0 : if( !pFrm || !pFrm->IsInTab() )
904 0 : return;
905 :
906 0 : SET_CURR_SHELL( this );
907 0 : StartAllAction();
908 0 : GetDoc()->SetAttr( rNew, *pFrm->ImplFindTabFrm()->GetFmt() );
909 0 : EndAllAction(); // no call, nothing changes!
910 0 : GetDoc()->SetModified();
911 : }
912 :
913 0 : void SwFEShell::GetTabBackground( SvxBrushItem &rToFill ) const
914 : {
915 0 : SwFrm *pFrm = GetCurrFrm();
916 0 : if( pFrm && pFrm->IsInTab() )
917 0 : rToFill = pFrm->ImplFindTabFrm()->GetFmt()->GetBackground();
918 0 : }
919 :
920 : /***********************************************************************
921 : #* Class : SwFEShell
922 : #* Methods : HasWholeTabSelection()
923 : #***********************************************************************/
924 0 : sal_Bool SwFEShell::HasWholeTabSelection() const
925 : {
926 : // whole table selected?
927 0 : if ( IsTableMode() )
928 : {
929 0 : SwSelBoxes aBoxes;
930 0 : ::GetTblSelCrs( *this, aBoxes );
931 0 : if( !aBoxes.empty() )
932 : {
933 0 : const SwTableNode *pTblNd = IsCrsrInTbl();
934 0 : return pTblNd &&
935 0 : aBoxes[0]->GetSttIdx() - 1 == pTblNd->EndOfSectionNode()->StartOfSectionIndex() &&
936 0 : aBoxes.back()->GetSttNd()->EndOfSectionIndex() + 1 == pTblNd->EndOfSectionIndex();
937 0 : }
938 : }
939 0 : return sal_False;
940 : }
941 :
942 0 : sal_Bool SwFEShell::HasBoxSelection() const
943 : {
944 0 : if(!IsCrsrInTbl())
945 0 : return sal_False;
946 : // whole table selected?
947 0 : if( IsTableMode() )
948 0 : return sal_True;
949 0 : SwPaM* pPam = GetCrsr();
950 : // empty boxes are also selected as the absence of selection
951 0 : bool bChg = false;
952 0 : if( pPam->GetPoint() == pPam->End())
953 : {
954 0 : bChg = true;
955 0 : pPam->Exchange();
956 : }
957 : SwNode* pNd;
958 0 : if( pPam->GetPoint()->nNode.GetIndex() -1 ==
959 0 : ( pNd = pPam->GetNode())->StartOfSectionIndex() &&
960 0 : !pPam->GetPoint()->nContent.GetIndex() &&
961 0 : pPam->GetMark()->nNode.GetIndex() + 1 ==
962 0 : pNd->EndOfSectionIndex())
963 : {
964 0 : SwNodeIndex aIdx( *pNd->EndOfSectionNode(), -1 );
965 0 : SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
966 0 : if( !pCNd )
967 : {
968 0 : pCNd = GetDoc()->GetNodes().GoPrevious( &aIdx );
969 : OSL_ENSURE( pCNd, "no ContentNode in box ??" );
970 : }
971 0 : if( pPam->GetMark()->nContent == pCNd->Len() )
972 : {
973 0 : if( bChg )
974 0 : pPam->Exchange();
975 0 : return sal_True;
976 0 : }
977 : }
978 0 : if( bChg )
979 0 : pPam->Exchange();
980 0 : return sal_False;
981 : }
982 :
983 : /***********************************************************************
984 : #* Class : SwFEShell
985 : #* Methods : ProtectCells(), UnProtectCells()
986 : #***********************************************************************/
987 0 : void SwFEShell::ProtectCells()
988 : {
989 0 : SvxProtectItem aProt( RES_PROTECT );
990 0 : aProt.SetCntntProtect( true );
991 :
992 0 : SET_CURR_SHELL( this );
993 0 : StartAllAction();
994 :
995 0 : GetDoc()->SetBoxAttr( *getShellCrsr( false ), aProt );
996 :
997 0 : if( !IsCrsrReadonly() )
998 : {
999 0 : if( IsTableMode() )
1000 0 : ClearMark();
1001 0 : ParkCursorInTab();
1002 : }
1003 0 : EndAllActionAndCall();
1004 0 : }
1005 :
1006 : // cancel table selection
1007 0 : void SwFEShell::UnProtectCells()
1008 : {
1009 0 : SET_CURR_SHELL( this );
1010 0 : StartAllAction();
1011 :
1012 0 : SwSelBoxes aBoxes;
1013 0 : if( IsTableMode() )
1014 0 : ::GetTblSelCrs( *this, aBoxes );
1015 : else
1016 : {
1017 0 : SwFrm *pFrm = GetCurrFrm();
1018 0 : do {
1019 0 : pFrm = pFrm->GetUpper();
1020 0 : } while ( pFrm && !pFrm->IsCellFrm() );
1021 0 : if( pFrm )
1022 : {
1023 0 : SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
1024 0 : aBoxes.insert( pBox );
1025 : }
1026 : }
1027 :
1028 0 : if( !aBoxes.empty() )
1029 0 : GetDoc()->UnProtectCells( aBoxes );
1030 :
1031 0 : EndAllActionAndCall();
1032 0 : }
1033 :
1034 0 : void SwFEShell::UnProtectTbls()
1035 : {
1036 0 : SET_CURR_SHELL( this );
1037 0 : StartAllAction();
1038 0 : GetDoc()->UnProtectTbls( *GetCrsr() );
1039 0 : EndAllActionAndCall();
1040 0 : }
1041 :
1042 0 : sal_Bool SwFEShell::HasTblAnyProtection( const OUString* pTblName,
1043 : sal_Bool* pFullTblProtection )
1044 : {
1045 0 : return GetDoc()->HasTblAnyProtection( GetCrsr()->GetPoint(), pTblName,
1046 0 : pFullTblProtection );
1047 : }
1048 :
1049 0 : sal_Bool SwFEShell::CanUnProtectCells() const
1050 : {
1051 0 : sal_Bool bUnProtectAvailable = sal_False;
1052 0 : const SwTableNode *pTblNd = IsCrsrInTbl();
1053 0 : if( pTblNd && !pTblNd->IsProtect() )
1054 : {
1055 0 : SwSelBoxes aBoxes;
1056 0 : if( IsTableMode() )
1057 0 : ::GetTblSelCrs( *this, aBoxes );
1058 : else
1059 : {
1060 0 : SwFrm *pFrm = GetCurrFrm();
1061 0 : do {
1062 0 : pFrm = pFrm->GetUpper();
1063 0 : } while ( pFrm && !pFrm->IsCellFrm() );
1064 0 : if( pFrm )
1065 : {
1066 0 : SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
1067 0 : aBoxes.insert( pBox );
1068 : }
1069 : }
1070 0 : if( !aBoxes.empty() )
1071 0 : bUnProtectAvailable = ::HasProtectedCells( aBoxes );
1072 : }
1073 0 : return bUnProtectAvailable;
1074 : }
1075 :
1076 : /***********************************************************************
1077 : #* Class : SwFEShell
1078 : #* Methods : GetRowsToRepeat(), SetRowsToRepeat()
1079 : #***********************************************************************/
1080 0 : sal_uInt16 SwFEShell::GetRowsToRepeat() const
1081 : {
1082 0 : const SwFrm *pFrm = GetCurrFrm();
1083 0 : const SwTabFrm *pTab = pFrm ? pFrm->FindTabFrm() : 0;
1084 0 : if( pTab )
1085 0 : return pTab->GetTable()->GetRowsToRepeat();
1086 0 : return 0;
1087 : }
1088 :
1089 0 : void SwFEShell::SetRowsToRepeat( sal_uInt16 nSet )
1090 : {
1091 0 : SwFrm *pFrm = GetCurrFrm();
1092 0 : SwTabFrm *pTab = pFrm ? pFrm->FindTabFrm() : 0;
1093 0 : if( pTab && pTab->GetTable()->GetRowsToRepeat() != nSet )
1094 : {
1095 0 : SwWait aWait( *GetDoc()->GetDocShell(), true );
1096 0 : SET_CURR_SHELL( this );
1097 0 : StartAllAction();
1098 0 : GetDoc()->SetRowsToRepeat( *pTab->GetTable(), nSet );
1099 0 : EndAllActionAndCall();
1100 : }
1101 0 : }
1102 :
1103 : /*-------------------------------------------------------------------------
1104 : returns the number of rows consecutively selected from top
1105 : -----------------------------------------------------------------------*/
1106 0 : static sal_uInt16 lcl_GetRowNumber( const SwPosition& rPos )
1107 : {
1108 0 : sal_uInt16 nRet = USHRT_MAX;
1109 0 : Point aTmpPt;
1110 : const SwCntntNode *pNd;
1111 : const SwCntntFrm *pFrm;
1112 :
1113 0 : if( 0 != ( pNd = rPos.nNode.GetNode().GetCntntNode() ))
1114 0 : pFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout(), &aTmpPt, &rPos, false );
1115 : else
1116 0 : pFrm = 0;
1117 :
1118 0 : if ( pFrm && pFrm->IsInTab() )
1119 : {
1120 0 : const SwFrm* pRow = pFrm->GetUpper();
1121 0 : while ( !pRow->GetUpper()->IsTabFrm() )
1122 0 : pRow = pRow->GetUpper();
1123 :
1124 0 : const SwTabFrm* pTabFrm = (const SwTabFrm*)pRow->GetUpper();
1125 0 : const SwTableLine* pTabLine = static_cast<const SwRowFrm*>(pRow)->GetTabLine();
1126 :
1127 0 : sal_uInt16 nI = 0;
1128 0 : while ( nI < pTabFrm->GetTable()->GetTabLines().size() )
1129 : {
1130 0 : if ( pTabFrm->GetTable()->GetTabLines()[ nI ] == pTabLine )
1131 : {
1132 0 : nRet = nI;
1133 0 : break;
1134 : }
1135 0 : ++nI;
1136 : }
1137 : }
1138 :
1139 0 : return nRet;
1140 : }
1141 0 : sal_uInt16 SwFEShell::GetRowSelectionFromTop() const
1142 : {
1143 0 : sal_uInt16 nRet = 0;
1144 0 : const SwPaM* pPaM = IsTableMode() ? GetTableCrsr() : _GetCrsr();
1145 0 : const sal_uInt16 nPtLine = lcl_GetRowNumber( *pPaM->GetPoint() );
1146 :
1147 0 : if ( !IsTableMode() )
1148 : {
1149 0 : nRet = 0 == nPtLine ? 1 : 0;
1150 : }
1151 : else
1152 : {
1153 0 : const sal_uInt16 nMkLine = lcl_GetRowNumber( *pPaM->GetMark() );
1154 :
1155 0 : if ( ( nPtLine == 0 && nMkLine != USHRT_MAX ) ||
1156 0 : ( nMkLine == 0 && nPtLine != USHRT_MAX ) )
1157 : {
1158 0 : nRet = std::max( nPtLine, nMkLine ) + 1;
1159 : }
1160 : }
1161 :
1162 0 : return nRet;
1163 : }
1164 :
1165 : /*
1166 : * 1. case: bRepeat = true
1167 : * returns true if the current frame is located inside a table headline in
1168 : * a follow frame
1169 : *
1170 : * 2. case: bRepeat = false
1171 : * returns true if the current frame is localed inside a table headline OR
1172 : * inside the first line of a table!!!
1173 : */
1174 0 : sal_Bool SwFEShell::CheckHeadline( bool bRepeat ) const
1175 : {
1176 0 : sal_Bool bRet = sal_False;
1177 0 : if ( !IsTableMode() )
1178 : {
1179 0 : SwFrm *pFrm = GetCurrFrm(); // DONE MULTIIHEADER
1180 0 : if ( pFrm && pFrm->IsInTab() )
1181 : {
1182 0 : SwTabFrm* pTab = pFrm->FindTabFrm();
1183 0 : if ( bRepeat )
1184 : {
1185 0 : bRet = pTab->IsFollow() && pTab->IsInHeadline( *pFrm );
1186 : }
1187 : else
1188 : {
1189 0 : bRet = ((SwLayoutFrm*)pTab->Lower())->IsAnLower( pFrm ) ||
1190 0 : pTab->IsInHeadline( *pFrm );
1191 : }
1192 : }
1193 : }
1194 0 : return bRet;
1195 : }
1196 :
1197 : /***********************************************************************
1198 : #* Class : SwFEShell
1199 : #* Methoden : AdjustCellWidth()
1200 : #***********************************************************************/
1201 :
1202 0 : void SwFEShell::AdjustCellWidth( sal_Bool bBalance )
1203 : {
1204 0 : SET_CURR_SHELL( this );
1205 0 : StartAllAction();
1206 :
1207 : // switch on wait-cursor, as we do not know how
1208 : // much content is affected
1209 : TblWait aWait(::std::numeric_limits<size_t>::max(), 0,
1210 0 : *GetDoc()->GetDocShell());
1211 :
1212 0 : GetDoc()->AdjustCellWidth( *getShellCrsr( false ), bBalance );
1213 0 : EndAllActionAndCall();
1214 0 : }
1215 :
1216 0 : sal_Bool SwFEShell::IsAdjustCellWidthAllowed( sal_Bool bBalance ) const
1217 : {
1218 : // at least one row with content should be contained in the selection
1219 :
1220 0 : SwFrm *pFrm = GetCurrFrm();
1221 0 : if( !pFrm || !pFrm->IsInTab() )
1222 0 : return sal_False;
1223 :
1224 0 : SwSelBoxes aBoxes;
1225 0 : ::GetTblSelCrs( *this, aBoxes );
1226 :
1227 0 : if ( bBalance )
1228 0 : return aBoxes.size() > 1;
1229 :
1230 0 : if ( aBoxes.empty() )
1231 : {
1232 0 : do
1233 0 : { pFrm = pFrm->GetUpper();
1234 0 : } while ( !pFrm->IsCellFrm() );
1235 0 : SwTableBox *pBox = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
1236 0 : aBoxes.insert( pBox );
1237 : }
1238 :
1239 0 : for (size_t i = 0; i < aBoxes.size(); ++i)
1240 : {
1241 0 : SwTableBox *pBox = aBoxes[i];
1242 0 : if ( pBox->GetSttNd() )
1243 : {
1244 0 : SwNodeIndex aIdx( *pBox->GetSttNd(), 1 );
1245 0 : SwTxtNode* pCNd = aIdx.GetNode().GetTxtNode();
1246 0 : if( !pCNd )
1247 0 : pCNd = (SwTxtNode*)GetDoc()->GetNodes().GoNext( &aIdx );
1248 :
1249 0 : while ( pCNd )
1250 : {
1251 0 : if (!pCNd->GetTxt().isEmpty())
1252 0 : return sal_True;
1253 0 : ++aIdx;
1254 0 : pCNd = aIdx.GetNode().GetTxtNode();
1255 0 : }
1256 : }
1257 : }
1258 0 : return sal_False;
1259 : }
1260 :
1261 : // AutoFormat for the table/table selection
1262 0 : sal_Bool SwFEShell::SetTableAutoFmt( const SwTableAutoFmt& rNew )
1263 : {
1264 0 : SwTableNode *pTblNd = (SwTableNode*)IsCrsrInTbl();
1265 0 : if( !pTblNd || pTblNd->GetTable().IsTblComplex() )
1266 0 : return sal_False;
1267 :
1268 0 : SwSelBoxes aBoxes;
1269 :
1270 0 : if ( !IsTableMode() ) // if cursors are not current
1271 0 : GetCrsr();
1272 :
1273 : // whole table or only current selection
1274 0 : if( IsTableMode() )
1275 0 : ::GetTblSelCrs( *this, aBoxes );
1276 : else
1277 : {
1278 0 : const SwTableSortBoxes& rTBoxes = pTblNd->GetTable().GetTabSortBoxes();
1279 0 : for (size_t n = 0; n < rTBoxes.size(); ++n)
1280 : {
1281 0 : SwTableBox* pBox = rTBoxes[ n ];
1282 0 : aBoxes.insert( pBox );
1283 : }
1284 : }
1285 :
1286 : sal_Bool bRet;
1287 0 : if( !aBoxes.empty() )
1288 : {
1289 0 : SET_CURR_SHELL( this );
1290 0 : StartAllAction();
1291 0 : bRet = GetDoc()->SetTableAutoFmt( aBoxes, rNew );
1292 0 : DELETEZ( pLastCols );
1293 0 : DELETEZ( pLastRows );
1294 0 : EndAllActionAndCall();
1295 : }
1296 : else
1297 0 : bRet = sal_False;
1298 0 : return bRet;
1299 : }
1300 :
1301 0 : sal_Bool SwFEShell::GetTableAutoFmt( SwTableAutoFmt& rGet )
1302 : {
1303 0 : const SwTableNode *pTblNd = IsCrsrInTbl();
1304 0 : if( !pTblNd || pTblNd->GetTable().IsTblComplex() )
1305 0 : return sal_False;
1306 :
1307 0 : SwSelBoxes aBoxes;
1308 :
1309 0 : if ( !IsTableMode() ) // if cursor are not current
1310 0 : GetCrsr();
1311 :
1312 : // whole table or only current selection
1313 0 : if( IsTableMode() )
1314 0 : ::GetTblSelCrs( *this, aBoxes );
1315 : else
1316 : {
1317 0 : const SwTableSortBoxes& rTBoxes = pTblNd->GetTable().GetTabSortBoxes();
1318 0 : for (size_t n = 0; n < rTBoxes.size(); ++n)
1319 : {
1320 0 : SwTableBox* pBox = rTBoxes[ n ];
1321 0 : aBoxes.insert( pBox );
1322 : }
1323 : }
1324 :
1325 0 : return GetDoc()->GetTableAutoFmt( aBoxes, rGet );
1326 : }
1327 :
1328 : /***********************************************************************
1329 : #* Class : SwFEShell
1330 : #* Methoden : DeleteTblSel()
1331 : #***********************************************************************/
1332 0 : sal_Bool SwFEShell::DeleteTblSel()
1333 : {
1334 : // check if SPoint/Mark of current cursor are in a table
1335 0 : SwFrm *pFrm = GetCurrFrm();
1336 0 : if( !pFrm || !pFrm->IsInTab() )
1337 0 : return sal_False;
1338 :
1339 0 : if( pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
1340 : {
1341 : ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
1342 0 : ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
1343 0 : return sal_False;
1344 : }
1345 :
1346 0 : SET_CURR_SHELL( this );
1347 0 : StartAllAction();
1348 :
1349 : // search boxes via the layout
1350 : sal_Bool bRet;
1351 0 : SwSelBoxes aBoxes;
1352 0 : GetTblSelCrs( *this, aBoxes );
1353 0 : if( !aBoxes.empty() )
1354 : {
1355 0 : TblWait( aBoxes.size(), pFrm, *GetDoc()->GetDocShell() );
1356 :
1357 : // cursor should be removed from deletion area.
1358 : // Put them behind/on the table; via the document
1359 : // position they'll be set to the old position
1360 0 : while( !pFrm->IsCellFrm() )
1361 0 : pFrm = pFrm->GetUpper();
1362 0 : ParkCrsr( SwNodeIndex( *((SwCellFrm*)pFrm)->GetTabBox()->GetSttNd() ));
1363 :
1364 0 : bRet = GetDoc()->DeleteRowCol( aBoxes );
1365 :
1366 0 : DELETEZ( pLastCols );
1367 0 : DELETEZ( pLastRows );
1368 : }
1369 : else
1370 0 : bRet = sal_False;
1371 0 : EndAllActionAndCall();
1372 0 : return bRet;
1373 : }
1374 :
1375 : /*************************************************************************
1376 : |*
1377 : |* SwFEShell::GetCurTabColNum()
1378 : |*
1379 : |*************************************************************************/
1380 0 : size_t SwFEShell::GetCurTabColNum() const
1381 : {
1382 : //!!!GetCurMouseTabColNum() mitpflegen!!!!
1383 0 : size_t nRet = 0;
1384 :
1385 0 : SwFrm *pFrm = GetCurrFrm();
1386 : OSL_ENSURE( pFrm, "Crsr parked?" );
1387 :
1388 : // check if SPoint/Mark of current cursor are in a table
1389 0 : if( pFrm && pFrm->IsInTab() )
1390 : {
1391 0 : do { // JP 26.09.95: why compare with CntntFrame
1392 : // and not with CellFrame ????
1393 0 : pFrm = pFrm->GetUpper();
1394 0 : } while ( !pFrm->IsCellFrm() );
1395 0 : SWRECTFN( pFrm )
1396 :
1397 0 : const SwPageFrm* pPage = pFrm->FindPageFrm();
1398 :
1399 : // get TabCols, as only via these we get to the position
1400 0 : SwTabCols aTabCols;
1401 0 : GetTabCols( aTabCols );
1402 :
1403 0 : if( pFrm->FindTabFrm()->IsRightToLeft() )
1404 : {
1405 0 : long nX = (pFrm->Frm().*fnRect->fnGetRight)() - (pPage->Frm().*fnRect->fnGetLeft)();
1406 :
1407 0 : const long nRight = aTabCols.GetLeftMin() + aTabCols.GetRight();;
1408 :
1409 0 : if ( !::IsSame( nX, nRight ) )
1410 : {
1411 0 : nX = nRight - nX + aTabCols.GetLeft();
1412 0 : for ( size_t i = 0; i < aTabCols.Count(); ++i )
1413 0 : if ( ::IsSame( nX, aTabCols[i] ) )
1414 : {
1415 0 : nRet = i + 1;
1416 0 : break;
1417 : }
1418 : }
1419 : }
1420 : else
1421 : {
1422 0 : const long nX = (pFrm->Frm().*fnRect->fnGetLeft)() -
1423 0 : (pPage->Frm().*fnRect->fnGetLeft)();
1424 :
1425 0 : const long nLeft = aTabCols.GetLeftMin();
1426 :
1427 0 : if ( !::IsSame( nX, nLeft + aTabCols.GetLeft() ) )
1428 : {
1429 0 : for ( size_t i = 0; i < aTabCols.Count(); ++i )
1430 0 : if ( ::IsSame( nX, nLeft + aTabCols[i] ) )
1431 : {
1432 0 : nRet = i + 1;
1433 0 : break;
1434 : }
1435 : }
1436 0 : }
1437 : }
1438 0 : return nRet;
1439 : }
1440 :
1441 : /*************************************************************************
1442 : |*
1443 : |* SwFEShell::GetBox()
1444 : |*
1445 : |*************************************************************************/
1446 :
1447 0 : static const SwFrm *lcl_FindFrmInTab( const SwLayoutFrm *pLay, const Point &rPt, SwTwips nFuzzy )
1448 : {
1449 0 : const SwFrm *pFrm = pLay->Lower();
1450 :
1451 0 : while( pFrm && pLay->IsAnLower( pFrm ) )
1452 : {
1453 0 : if ( pFrm->Frm().IsNear( rPt, nFuzzy ) )
1454 : {
1455 0 : if ( pFrm->IsLayoutFrm() )
1456 : {
1457 0 : const SwFrm *pTmp = ::lcl_FindFrmInTab( (SwLayoutFrm*)pFrm, rPt, nFuzzy );
1458 0 : if ( pTmp )
1459 0 : return pTmp;
1460 : }
1461 :
1462 0 : return pFrm;
1463 : }
1464 :
1465 0 : pFrm = pFrm->FindNext();
1466 : }
1467 :
1468 0 : return 0;
1469 : }
1470 :
1471 0 : static const SwCellFrm *lcl_FindFrm( const SwLayoutFrm *pLay, const Point &rPt,
1472 : SwTwips nFuzzy, bool* pbRow, bool* pbCol )
1473 : {
1474 : // bMouseMoveRowCols :
1475 : // Method is called for
1476 : // - Moving columns/rows with the mouse or
1477 : // - Enhanced table selection
1478 0 : const bool bMouseMoveRowCols = 0 == pbCol;
1479 :
1480 0 : bool bCloseToRow = false;
1481 0 : bool bCloseToCol = false;
1482 :
1483 0 : const SwFrm *pFrm = pLay->ContainsCntnt();
1484 0 : const SwFrm* pRet = 0;
1485 :
1486 0 : if ( pFrm )
1487 : {
1488 0 : do
1489 : {
1490 0 : if ( pFrm->IsInTab() )
1491 0 : pFrm = ((SwFrm*)pFrm)->ImplFindTabFrm();
1492 :
1493 0 : if ( pFrm->IsTabFrm() )
1494 : {
1495 0 : Point aPt( rPt );
1496 0 : bool bSearchForFrmInTab = true;
1497 0 : SwTwips nTmpFuzzy = nFuzzy;
1498 :
1499 0 : if ( !bMouseMoveRowCols )
1500 : {
1501 : // We ignore nested tables for the enhanced table selection:
1502 0 : while ( pFrm->GetUpper()->IsInTab() )
1503 0 : pFrm = pFrm->GetUpper()->FindTabFrm();
1504 :
1505 : // We first check if the given point is 'close' to the left or top
1506 : // border of the table frame:
1507 : OSL_ENSURE( pFrm, "Nested table frame without outer table" );
1508 0 : SWRECTFN( pFrm )
1509 0 : const bool bRTL = pFrm->IsRightToLeft();
1510 :
1511 0 : SwRect aTabRect = pFrm->Prt();
1512 0 : aTabRect.Pos() += pFrm->Frm().Pos();
1513 :
1514 : const SwTwips nLeft = bRTL ?
1515 0 : (aTabRect.*fnRect->fnGetRight)() :
1516 0 : (aTabRect.*fnRect->fnGetLeft)();
1517 0 : const SwTwips nTop = (aTabRect.*fnRect->fnGetTop)();
1518 :
1519 0 : SwTwips& rPointX = bVert ? aPt.Y() : aPt.X();
1520 0 : SwTwips& rPointY = bVert ? aPt.X() : aPt.Y();
1521 :
1522 0 : const SwTwips nXDiff = (*fnRect->fnXDiff)( nLeft, rPointX ) * ( bRTL ? (-1) : 1 );
1523 0 : const SwTwips nYDiff = (*fnRect->fnYDiff)( nTop, rPointY );
1524 :
1525 0 : bCloseToRow = nXDiff >= 0 && nXDiff < nFuzzy;
1526 0 : bCloseToCol = nYDiff >= 0 && nYDiff < nFuzzy;
1527 :
1528 0 : if ( bCloseToCol && 2 * nYDiff > nFuzzy )
1529 : {
1530 0 : const SwFrm* pPrev = pFrm->GetPrev();
1531 0 : if ( pPrev )
1532 : {
1533 0 : SwRect aPrevRect = pPrev->Prt();
1534 0 : aPrevRect.Pos() += pPrev->Frm().Pos();
1535 :
1536 0 : if( aPrevRect.IsInside( rPt ) )
1537 : {
1538 0 : bCloseToCol = false;
1539 : }
1540 : }
1541 :
1542 : }
1543 :
1544 : // If we found the point to be 'close' to the left or top border
1545 : // of the table frame, we adjust the point to be on that border:
1546 0 : if ( bCloseToRow && bCloseToCol )
1547 0 : aPt = bRTL ? aTabRect.TopRight() : (aTabRect.*fnRect->fnGetPos)();
1548 0 : else if ( bCloseToRow )
1549 0 : rPointX = nLeft;
1550 0 : else if ( bCloseToCol )
1551 0 : rPointY = nTop;
1552 :
1553 0 : if ( !bCloseToRow && !bCloseToCol )
1554 0 : bSearchForFrmInTab = false;
1555 :
1556 : // Since the point has been adjusted, we call lcl_FindFrmInTab()
1557 : // with a fuzzy value of 1:
1558 0 : nTmpFuzzy = 1;
1559 : }
1560 :
1561 : const SwFrm* pTmp = bSearchForFrmInTab ?
1562 : ::lcl_FindFrmInTab( (SwLayoutFrm*)pFrm, aPt, nTmpFuzzy ) :
1563 0 : 0;
1564 :
1565 0 : if ( pTmp )
1566 : {
1567 0 : pFrm = pTmp;
1568 0 : break;
1569 : }
1570 : }
1571 0 : pFrm = pFrm->FindNextCnt();
1572 :
1573 0 : } while ( pFrm && pLay->IsAnLower( pFrm ) );
1574 : }
1575 :
1576 0 : if ( pFrm && pFrm->IsInTab() && pLay->IsAnLower( pFrm ) )
1577 : {
1578 0 : do
1579 : {
1580 : // We allow mouse drag of table borders within nested tables,
1581 : // but disallow hotspot selection of nested tables.
1582 0 : if ( bMouseMoveRowCols )
1583 : {
1584 : // find the next cell frame
1585 0 : while ( pFrm && !pFrm->IsCellFrm() )
1586 0 : pFrm = pFrm->GetUpper();
1587 : }
1588 : else
1589 : {
1590 : // find the most upper cell frame:
1591 0 : while ( pFrm &&
1592 0 : ( !pFrm->IsCellFrm() ||
1593 0 : !pFrm->GetUpper()->GetUpper()->IsTabFrm() ||
1594 0 : pFrm->GetUpper()->GetUpper()->GetUpper()->IsInTab() ) )
1595 0 : pFrm = pFrm->GetUpper();
1596 : }
1597 :
1598 0 : if ( pFrm ) // Note: this condition should be the same like the while condition!!!
1599 : {
1600 : // #i32329# Enhanced table selection
1601 : // used for hotspot selection of tab/cols/rows
1602 0 : if ( !bMouseMoveRowCols )
1603 : {
1604 :
1605 : OSL_ENSURE( pbCol && pbRow, "pbCol or pbRow missing" );
1606 :
1607 0 : if ( bCloseToRow || bCloseToCol )
1608 : {
1609 0 : *pbRow = bCloseToRow;
1610 0 : *pbCol = bCloseToCol;
1611 0 : pRet = pFrm;
1612 0 : break;
1613 : }
1614 : }
1615 : else
1616 : {
1617 : // used for mouse move of columns/rows
1618 0 : const SwTabFrm* pTabFrm = pFrm->FindTabFrm();
1619 0 : SwRect aTabRect = pTabFrm->Prt();
1620 0 : aTabRect.Pos() += pTabFrm->Frm().Pos();
1621 :
1622 0 : SWRECTFN( pTabFrm )
1623 :
1624 0 : const SwTwips nTabTop = (aTabRect.*fnRect->fnGetTop)();
1625 0 : const SwTwips nMouseTop = bVert ? rPt.X() : rPt.Y();
1626 :
1627 : // Do not allow to drag upper table border:
1628 0 : if ( !::IsSame( nTabTop, nMouseTop ) )
1629 : {
1630 0 : if ( ::IsSame( pFrm->Frm().Left(), rPt.X() ) ||
1631 0 : ::IsSame( pFrm->Frm().Right(),rPt.X() ) )
1632 : {
1633 0 : if ( pbRow ) *pbRow = false;
1634 0 : pRet = pFrm;
1635 0 : break;
1636 : }
1637 0 : if ( ::IsSame( pFrm->Frm().Top(), rPt.Y() ) ||
1638 0 : ::IsSame( pFrm->Frm().Bottom(),rPt.Y() ) )
1639 : {
1640 0 : if ( pbRow ) *pbRow = true;
1641 0 : pRet = pFrm;
1642 0 : break;
1643 : }
1644 : }
1645 : }
1646 :
1647 0 : pFrm = pFrm->GetUpper();
1648 : }
1649 : } while ( pFrm );
1650 : }
1651 :
1652 : // robust:
1653 : OSL_ENSURE( !pRet || pRet->IsCellFrm(), "lcl_FindFrm() is supposed to find a cell frame!" );
1654 0 : return pRet && pRet->IsCellFrm() ? static_cast<const SwCellFrm*>(pRet) : 0;
1655 : }
1656 :
1657 : // pbCol = 0 => Used for moving table rows/cols with mouse
1658 : // pbCol != 0 => Used for selecting table/rows/cols
1659 :
1660 : #define ENHANCED_TABLE_SELECTION_FUZZY 10
1661 :
1662 0 : const SwFrm* SwFEShell::GetBox( const Point &rPt, bool* pbRow, bool* pbCol ) const
1663 : {
1664 0 : const SwPageFrm *pPage = (SwPageFrm*)GetLayout()->Lower();
1665 0 : Window* pOutWin = GetWin();
1666 0 : SwTwips nFuzzy = COLFUZZY;
1667 0 : if( pOutWin )
1668 : {
1669 : // #i32329# Enhanced table selection
1670 0 : SwTwips nSize = pbCol ? ENHANCED_TABLE_SELECTION_FUZZY : RULER_MOUSE_MARGINWIDTH;
1671 0 : Size aTmp( nSize, nSize );
1672 0 : aTmp = pOutWin->PixelToLogic( aTmp );
1673 0 : nFuzzy = aTmp.Width();
1674 : }
1675 :
1676 0 : while ( pPage && !pPage->Frm().IsNear( rPt, nFuzzy ) )
1677 0 : pPage = (SwPageFrm*)pPage->GetNext();
1678 :
1679 0 : const SwCellFrm *pFrm = 0;
1680 0 : if ( pPage )
1681 : {
1682 : // We cannot search the box by GetCrsrOfst or GetCntntPos.
1683 : // This would lead to a performance collapse for documents
1684 : // with a lot of paragraphs/tables on one page
1685 : //(BrowseMode!)
1686 :
1687 : // check flys first
1688 0 : if ( pPage->GetSortedObjs() )
1689 : {
1690 0 : for ( sal_uInt16 i = 0; !pFrm && i < pPage->GetSortedObjs()->Count(); ++i )
1691 : {
1692 0 : SwAnchoredObject* pObj = (*pPage->GetSortedObjs())[i];
1693 0 : if ( pObj->ISA(SwFlyFrm) )
1694 : {
1695 : pFrm = lcl_FindFrm( static_cast<SwFlyFrm*>(pObj),
1696 0 : rPt, nFuzzy, pbRow, pbCol );
1697 : }
1698 : }
1699 : }
1700 0 : const SwLayoutFrm *pLay = (SwLayoutFrm*)pPage->Lower();
1701 0 : while ( pLay && !pFrm )
1702 : {
1703 0 : pFrm = lcl_FindFrm( pLay, rPt, nFuzzy, pbRow, pbCol );
1704 0 : pLay = (SwLayoutFrm*)pLay->GetNext();
1705 : }
1706 : }
1707 0 : return pFrm;
1708 : }
1709 :
1710 : /* Helper function*/
1711 : /* calculated the distance between Point rC and Line Segment (rA, rB) */
1712 0 : static double lcl_DistancePoint2Segment( const Point& rA, const Point& rB, const Point& rC )
1713 : {
1714 0 : double nRet = 0;
1715 :
1716 0 : const basegfx::B2DVector aBC( rC.X() - rB.X(), rC.Y() - rB.Y() );
1717 0 : const basegfx::B2DVector aAB( rB.X() - rA.X(), rB.Y() - rA.Y() );
1718 0 : const double nDot1 = aBC.scalar( aAB );
1719 :
1720 0 : if ( nDot1 > 0 ) // check outside case 1
1721 0 : nRet = aBC.getLength();
1722 : else
1723 : {
1724 0 : const basegfx::B2DVector aAC( rC.X() - rA.X(), rC.Y() - rA.Y() );
1725 0 : const basegfx::B2DVector aBA( rA.X() - rB.X(), rA.Y() - rB.Y() );
1726 0 : const double nDot2 = aAC.scalar( aBA );
1727 :
1728 0 : if ( nDot2 > 0 ) // check outside case 2
1729 0 : nRet = aAC.getLength();
1730 : else
1731 : {
1732 0 : const double nDiv = aAB.getLength();
1733 0 : nRet = nDiv ? aAB.cross( aAC ) / nDiv : 0;
1734 0 : }
1735 : }
1736 :
1737 0 : return std::abs(nRet);
1738 : }
1739 :
1740 : /* Helper function*/
1741 0 : static Point lcl_ProjectOntoClosestTableFrm( const SwTabFrm& rTab, const Point& rPoint, bool bRowDrag )
1742 : {
1743 0 : Point aRet( rPoint );
1744 0 : const SwTabFrm* pCurrentTab = &rTab;
1745 0 : const bool bVert = pCurrentTab->IsVertical();
1746 0 : const bool bRTL = pCurrentTab->IsRightToLeft();
1747 :
1748 : // Western Layout:
1749 : // bRowDrag = true => compare to left border of table
1750 : // bRowDrag = false => compare to top border of table
1751 :
1752 : // Asian Layout:
1753 : // bRowDrag = true => compare to right border of table
1754 : // bRowDrag = false => compare to top border of table
1755 :
1756 : // RTL Layout:
1757 : // bRowDrag = true => compare to right border of table
1758 : // bRowDrag = false => compare to top border of table
1759 0 : bool bLeft = false;
1760 0 : bool bRight = false;
1761 :
1762 0 : if ( bRowDrag )
1763 : {
1764 0 : if ( bVert || bRTL )
1765 0 : bRight = true;
1766 : else
1767 0 : bLeft = true;
1768 : }
1769 :
1770 : // used to find the minimal distance
1771 0 : double nMin = -1;
1772 0 : Point aMin1;
1773 0 : Point aMin2;
1774 :
1775 0 : Point aS1;
1776 0 : Point aS2;
1777 :
1778 0 : while ( pCurrentTab )
1779 : {
1780 0 : SwRect aTabRect( pCurrentTab->Prt() );
1781 0 : aTabRect += pCurrentTab->Frm().Pos();
1782 :
1783 0 : if ( bLeft )
1784 : {
1785 : // distance to left table border
1786 0 : aS1 = aTabRect.TopLeft();
1787 0 : aS2 = aTabRect.BottomLeft();
1788 : }
1789 0 : else if ( bRight )
1790 : {
1791 : // distance to right table border
1792 0 : aS1 = aTabRect.TopRight();
1793 0 : aS2 = aTabRect.BottomRight();
1794 : }
1795 : else //if ( bTop )
1796 : {
1797 : // distance to top table border
1798 0 : aS1 = aTabRect.TopLeft();
1799 0 : aS2 = aTabRect.TopRight();
1800 : }
1801 :
1802 0 : const double nDist = lcl_DistancePoint2Segment( aS1, aS2, rPoint );
1803 :
1804 0 : if ( nDist < nMin || -1 == nMin )
1805 : {
1806 0 : aMin1 = aS1;
1807 0 : aMin2 = aS2;
1808 0 : nMin = nDist;
1809 : }
1810 :
1811 0 : pCurrentTab = pCurrentTab->GetFollow();
1812 : }
1813 :
1814 : // project onto closest line:
1815 0 : if ( bLeft || bRight )
1816 : {
1817 0 : aRet.setX(aMin1.getX());
1818 0 : if ( aRet.getY() > aMin2.getY() )
1819 0 : aRet.setY(aMin2.getY());
1820 0 : else if ( aRet.getY() < aMin1.getY() )
1821 0 : aRet.setY(aMin1.getY());
1822 : }
1823 : else
1824 : {
1825 0 : aRet.setY(aMin1.getY());
1826 0 : if ( aRet.getX() > aMin2.getX() )
1827 0 : aRet.setX(aMin2.getX());
1828 0 : else if ( aRet.getX() < aMin1.getX() )
1829 0 : aRet.setX(aMin1.getX());
1830 : }
1831 :
1832 0 : return aRet;
1833 : }
1834 :
1835 : // #i32329# Enhanced table selection
1836 0 : bool SwFEShell::SelTblRowCol( const Point& rPt, const Point* pEnd, bool bRowDrag )
1837 : {
1838 0 : bool bRet = false;
1839 0 : Point aEndPt;
1840 0 : if ( pEnd )
1841 0 : aEndPt = *pEnd;
1842 :
1843 0 : SwPosition* ppPos[2] = { 0, 0 };
1844 0 : Point paPt [2] = { rPt, aEndPt };
1845 0 : bool pbRow[2] = { false, false };
1846 0 : bool pbCol[2] = { false, false };
1847 :
1848 : // pEnd is set during dragging.
1849 0 : for ( sal_uInt16 i = 0; i < ( pEnd ? 2 : 1 ); ++i )
1850 : {
1851 : const SwCellFrm* pFrm =
1852 0 : static_cast<const SwCellFrm*>(GetBox( paPt[i], &pbRow[i], &pbCol[i] ) );
1853 :
1854 0 : if( pFrm )
1855 : {
1856 0 : while( pFrm && pFrm->Lower() && pFrm->Lower()->IsRowFrm() )
1857 0 : pFrm = static_cast<const SwCellFrm*>( static_cast<const SwLayoutFrm*>( pFrm->Lower() )->Lower() );
1858 0 : if( pFrm && pFrm->GetTabBox()->GetSttNd() &&
1859 0 : pFrm->GetTabBox()->GetSttNd()->IsInProtectSect() )
1860 0 : pFrm = 0;
1861 : }
1862 :
1863 0 : if ( pFrm )
1864 : {
1865 0 : const SwCntntFrm* pCntnt = ::GetCellCntnt( *pFrm );
1866 :
1867 0 : if ( pCntnt && pCntnt->IsTxtFrm() )
1868 : {
1869 0 : ppPos[i] = new SwPosition( *pCntnt->GetNode() );
1870 0 : ppPos[i]->nContent.Assign( const_cast<SwCntntNode*>(pCntnt->GetNode()), 0 );
1871 :
1872 : // paPt[i] will not be used any longer, now we use it to store
1873 : // a position inside the content frame
1874 0 : paPt[i] = pCntnt->Frm().Center();
1875 : }
1876 : }
1877 :
1878 : // no calculation of end frame if start frame has not been found.
1879 0 : if ( 1 == i || !ppPos[0] || !pEnd || !pFrm )
1880 : break;
1881 :
1882 : // find 'closest' table frame to pEnd:
1883 0 : const SwTabFrm* pCurrentTab = pFrm->FindTabFrm();
1884 0 : if ( pCurrentTab->IsFollow() )
1885 0 : pCurrentTab = pCurrentTab->FindMaster( true );
1886 :
1887 0 : const Point aProjection = lcl_ProjectOntoClosestTableFrm( *pCurrentTab, *pEnd, bRowDrag );
1888 0 : paPt[1] = aProjection;
1889 : }
1890 :
1891 0 : if ( ppPos[0] )
1892 : {
1893 0 : SwShellCrsr* pCrsr = _GetCrsr();
1894 0 : SwCrsrSaveState aSaveState( *pCrsr );
1895 0 : SwPosition aOldPos( *pCrsr->GetPoint() );
1896 :
1897 0 : pCrsr->DeleteMark();
1898 0 : *pCrsr->GetPoint() = *ppPos[0];
1899 0 : pCrsr->GetPtPos() = paPt[0];
1900 :
1901 0 : if ( !pCrsr->IsInProtectTable( sal_False, sal_True ) )
1902 : {
1903 0 : bool bNewSelection = true;
1904 :
1905 0 : if ( ppPos[1] )
1906 : {
1907 0 : if ( ppPos[1]->nNode.GetNode().StartOfSectionNode() !=
1908 0 : aOldPos.nNode.GetNode().StartOfSectionNode() )
1909 : {
1910 0 : pCrsr->SetMark();
1911 0 : SwCrsrSaveState aSaveState2( *pCrsr );
1912 0 : *pCrsr->GetPoint() = *ppPos[1];
1913 0 : pCrsr->GetPtPos() = paPt[1];
1914 :
1915 0 : if ( pCrsr->IsInProtectTable( sal_False, sal_False ) )
1916 : {
1917 0 : pCrsr->RestoreSavePos();
1918 0 : bNewSelection = false;
1919 0 : }
1920 : }
1921 : else
1922 : {
1923 0 : pCrsr->RestoreSavePos();
1924 0 : bNewSelection = false;
1925 : }
1926 : }
1927 :
1928 0 : if ( bNewSelection )
1929 : {
1930 : // #i35543# SelTblRowCol should remove any existing
1931 : // table cursor:
1932 0 : if ( IsTableMode() )
1933 0 : TblCrsrToCursor();
1934 :
1935 0 : if ( pbRow[0] && pbCol[0] )
1936 0 : bRet = SwCrsrShell::SelTbl();
1937 0 : else if ( pbRow[0] )
1938 0 : bRet = SwCrsrShell::_SelTblRowOrCol( true, true );
1939 0 : else if ( pbCol[0] )
1940 0 : bRet = SwCrsrShell::_SelTblRowOrCol( false, true );
1941 : }
1942 : else
1943 0 : bRet = true;
1944 : }
1945 :
1946 0 : delete ppPos[0];
1947 0 : delete ppPos[1];
1948 : }
1949 :
1950 0 : return bRet;
1951 : }
1952 :
1953 : /*************************************************************************
1954 : |*
1955 : |* SwFEShell::WhichMouseTabCol()
1956 : |*
1957 : |*************************************************************************/
1958 0 : sal_uInt8 SwFEShell::WhichMouseTabCol( const Point &rPt ) const
1959 : {
1960 0 : sal_uInt8 nRet = SW_TABCOL_NONE;
1961 0 : bool bRow = false;
1962 0 : bool bCol = false;
1963 0 : bool bSelect = false;
1964 :
1965 : // First try: Do we get the row/col move cursor?
1966 0 : SwCellFrm* pFrm = (SwCellFrm*)GetBox( rPt, &bRow, 0 );
1967 :
1968 0 : if ( !pFrm )
1969 : {
1970 : // Second try: Do we get the row/col/tab selection cursor?
1971 0 : pFrm = (SwCellFrm*)GetBox( rPt, &bRow, &bCol );
1972 0 : bSelect = true;
1973 : }
1974 :
1975 0 : if( pFrm )
1976 : {
1977 0 : while( pFrm && pFrm->Lower() && pFrm->Lower()->IsRowFrm() )
1978 0 : pFrm = (SwCellFrm*)((SwLayoutFrm*)pFrm->Lower())->Lower();
1979 0 : if( pFrm && pFrm->GetTabBox()->GetSttNd() &&
1980 0 : pFrm->GetTabBox()->GetSttNd()->IsInProtectSect() )
1981 0 : pFrm = 0;
1982 : }
1983 :
1984 0 : if( pFrm )
1985 : {
1986 0 : if ( !bSelect )
1987 : {
1988 0 : if ( pFrm->IsVertical() )
1989 0 : nRet = bRow ? SW_TABCOL_VERT : SW_TABROW_VERT;
1990 : else
1991 0 : nRet = bRow ? SW_TABROW_HORI : SW_TABCOL_HORI;
1992 : }
1993 : else
1994 : {
1995 0 : const SwTabFrm* pTabFrm = pFrm->FindTabFrm();
1996 0 : if ( pTabFrm->IsVertical() )
1997 : {
1998 0 : if ( bRow && bCol )
1999 : {
2000 0 : nRet = SW_TABSEL_VERT;
2001 : }
2002 0 : else if ( bRow )
2003 : {
2004 0 : nRet = SW_TABROWSEL_VERT;
2005 : }
2006 0 : else if ( bCol )
2007 : {
2008 0 : nRet = SW_TABCOLSEL_VERT;
2009 : }
2010 : }
2011 : else
2012 : {
2013 0 : if ( bRow && bCol )
2014 : {
2015 0 : nRet = pTabFrm->IsRightToLeft() ?
2016 : SW_TABSEL_HORI_RTL :
2017 0 : SW_TABSEL_HORI;
2018 : }
2019 0 : else if ( bRow )
2020 : {
2021 0 : nRet = pTabFrm->IsRightToLeft() ?
2022 : SW_TABROWSEL_HORI_RTL :
2023 0 : SW_TABROWSEL_HORI;
2024 : }
2025 0 : else if ( bCol )
2026 : {
2027 0 : nRet = SW_TABCOLSEL_HORI;
2028 : }
2029 : }
2030 : }
2031 : }
2032 :
2033 0 : return nRet;
2034 : }
2035 :
2036 : // -> #i23726#
2037 0 : SwTxtNode * SwFEShell::GetNumRuleNodeAtPos( const Point &rPt)
2038 : {
2039 0 : SwTxtNode * pResult = NULL;
2040 :
2041 : SwContentAtPos aCntntAtPos
2042 0 : (SwContentAtPos::SW_NUMLABEL);
2043 :
2044 0 : if( GetContentAtPos(rPt, aCntntAtPos) && aCntntAtPos.aFnd.pNode)
2045 0 : pResult = aCntntAtPos.aFnd.pNode->GetTxtNode();
2046 :
2047 0 : return pResult;
2048 : }
2049 :
2050 0 : sal_Bool SwFEShell::IsNumLabel( const Point &rPt, int nMaxOffset )
2051 : {
2052 0 : sal_Bool bResult = sal_False;
2053 :
2054 : SwContentAtPos aCntntAtPos
2055 0 : (SwContentAtPos::SW_NUMLABEL);
2056 :
2057 0 : if( GetContentAtPos(rPt, aCntntAtPos))
2058 : {
2059 0 : if ((nMaxOffset >= 0 && aCntntAtPos.nDist <= nMaxOffset) ||
2060 : (nMaxOffset < 0))
2061 0 : bResult = sal_True;
2062 : }
2063 :
2064 0 : return bResult;
2065 : }
2066 : // <- #i23726#
2067 :
2068 : // #i42921#
2069 0 : bool SwFEShell::IsVerticalModeAtNdAndPos( const SwTxtNode& _rTxtNode,
2070 : const Point& _rDocPos ) const
2071 : {
2072 0 : bool bRet( false );
2073 :
2074 : const short nTextDir =
2075 0 : _rTxtNode.GetTextDirection( SwPosition(_rTxtNode), &_rDocPos );
2076 0 : switch ( nTextDir )
2077 : {
2078 : case -1:
2079 : case FRMDIR_HORI_RIGHT_TOP:
2080 : case FRMDIR_HORI_LEFT_TOP:
2081 : {
2082 0 : bRet = false;
2083 : }
2084 0 : break;
2085 : case FRMDIR_VERT_TOP_LEFT:
2086 : case FRMDIR_VERT_TOP_RIGHT:
2087 : {
2088 0 : bRet = true;
2089 : }
2090 0 : break;
2091 : }
2092 :
2093 0 : return bRet;
2094 : }
2095 :
2096 : /*************************************************************************
2097 : |*
2098 : |* SwFEShell::GetMouseTabCols()
2099 : |*
2100 : |*************************************************************************/
2101 0 : void SwFEShell::GetMouseTabCols( SwTabCols &rToFill, const Point &rPt ) const
2102 : {
2103 0 : const SwFrm *pBox = GetBox( rPt );
2104 0 : if ( pBox )
2105 0 : _GetTabCols( rToFill, pBox );
2106 0 : }
2107 :
2108 0 : void SwFEShell::SetMouseTabCols( const SwTabCols &rNew, sal_Bool bCurRowOnly,
2109 : const Point &rPt )
2110 : {
2111 0 : const SwFrm *pBox = GetBox( rPt );
2112 0 : if( pBox )
2113 : {
2114 0 : SET_CURR_SHELL( this );
2115 0 : StartAllAction();
2116 0 : GetDoc()->SetTabCols( rNew, bCurRowOnly, 0, (SwCellFrm*)pBox );
2117 0 : EndAllActionAndCall();
2118 : }
2119 0 : }
2120 :
2121 : /*************************************************************************
2122 : |*
2123 : |* SwFEShell::GetMouseColNum(), GetMouseTabColNum()
2124 : |*
2125 : |*************************************************************************/
2126 0 : sal_uInt16 SwFEShell::GetCurMouseColNum( const Point &rPt,
2127 : SwGetCurColNumPara* pPara ) const
2128 : {
2129 0 : return _GetCurColNum( GetBox( rPt ), pPara );
2130 : }
2131 :
2132 0 : size_t SwFEShell::GetCurMouseTabColNum( const Point &rPt ) const
2133 : {
2134 : //!!!GetCurTabColNum() mitpflegen!!!!
2135 0 : size_t nRet = 0;
2136 :
2137 0 : const SwFrm *pFrm = GetBox( rPt );
2138 : OSL_ENSURE( pFrm, "Table not found" );
2139 0 : if( pFrm )
2140 : {
2141 0 : const long nX = pFrm->Frm().Left();
2142 :
2143 : // get TabCols, only via these we get the position
2144 0 : SwTabCols aTabCols;
2145 0 : GetMouseTabCols( aTabCols, rPt );
2146 :
2147 0 : const long nLeft = aTabCols.GetLeftMin();
2148 :
2149 0 : if ( !::IsSame( nX, nLeft + aTabCols.GetLeft() ) )
2150 : {
2151 0 : for ( size_t i = 0; i < aTabCols.Count(); ++i )
2152 0 : if ( ::IsSame( nX, nLeft + aTabCols[i] ) )
2153 : {
2154 0 : nRet = i + 1;
2155 0 : break;
2156 : }
2157 0 : }
2158 : }
2159 0 : return nRet;
2160 : }
2161 :
2162 0 : void ClearFEShellTabCols()
2163 : {
2164 0 : DELETEZ( pLastCols );
2165 0 : DELETEZ( pLastRows );
2166 0 : }
2167 :
2168 : /*************************************************************************
2169 : |*
2170 : |* SwFEShell::GetTblAttr(), SetTblAttr()
2171 : |*
2172 : |*************************************************************************/
2173 0 : void SwFEShell::GetTblAttr( SfxItemSet &rSet ) const
2174 : {
2175 0 : SwFrm *pFrm = GetCurrFrm();
2176 0 : if( pFrm && pFrm->IsInTab() )
2177 0 : rSet.Put( pFrm->ImplFindTabFrm()->GetFmt()->GetAttrSet() );
2178 0 : }
2179 :
2180 0 : void SwFEShell::SetTblAttr( const SfxItemSet &rNew )
2181 : {
2182 0 : SwFrm *pFrm = GetCurrFrm();
2183 0 : if( pFrm && pFrm->IsInTab() )
2184 : {
2185 0 : SET_CURR_SHELL( this );
2186 0 : StartAllAction();
2187 0 : SwTabFrm *pTab = pFrm->FindTabFrm();
2188 0 : pTab->GetTable()->SetHTMLTableLayout( 0 );
2189 0 : GetDoc()->SetAttr( rNew, *pTab->GetFmt() );
2190 0 : GetDoc()->SetModified();
2191 0 : EndAllActionAndCall();
2192 : }
2193 0 : }
2194 :
2195 : /** move cursor within a table into previous/next row (same column)
2196 : * @param pShell cursor shell whose cursor is to be moved
2197 : * @param bUp true: move up, false: move down
2198 : * @returns true if successful
2199 : */
2200 0 : static bool lcl_GoTableRow( SwCrsrShell* pShell, bool bUp )
2201 : {
2202 : OSL_ENSURE( pShell != NULL, "need shell" );
2203 :
2204 0 : SwPaM* pPam = pShell->GetCrsr();
2205 0 : const SwStartNode* pTableBox = pPam->GetNode()->FindTableBoxStartNode();
2206 : OSL_ENSURE( pTableBox != NULL, "I'm living in a box... NOT!" );
2207 :
2208 : // move cursor to start node of table box
2209 0 : pPam->GetPoint()->nNode = pTableBox->GetIndex();
2210 0 : pPam->GetPoint()->nContent.Assign( NULL, 0 );
2211 0 : GoInCntnt( *pPam, fnMoveForward );
2212 :
2213 : // go to beginning end of table box
2214 0 : SwPosSection fnPosSect = bUp ? fnSectionStart : fnSectionEnd;
2215 0 : pShell->MoveSection( fnSectionCurr, fnPosSect );
2216 :
2217 : // and go up/down into next content
2218 0 : return bUp ? pShell->Up() : pShell->Down();
2219 : }
2220 :
2221 : // aender eine Zellenbreite/-Hoehe/Spaltenbreite/Zeilenhoehe
2222 0 : sal_Bool SwFEShell::SetColRowWidthHeight( sal_uInt16 eType, sal_uInt16 nDiff )
2223 : {
2224 0 : SwFrm *pFrm = GetCurrFrm();
2225 0 : if( !pFrm || !pFrm->IsInTab() )
2226 0 : return sal_False;
2227 :
2228 0 : if( nsTblChgWidthHeightType::WH_FLAG_INSDEL & eType &&
2229 0 : pFrm->ImplFindTabFrm()->GetTable()->ISA( SwDDETable ))
2230 : {
2231 : ErrorHandler::HandleError( ERR_TBLDDECHG_ERROR,
2232 0 : ERRCODE_MSG_INFO | ERRCODE_BUTTON_DEF_OK );
2233 0 : return sal_False;
2234 : }
2235 :
2236 0 : SET_CURR_SHELL( this );
2237 0 : StartAllAction();
2238 :
2239 0 : do {
2240 0 : pFrm = pFrm->GetUpper();
2241 0 : } while( !pFrm->IsCellFrm() );
2242 :
2243 0 : SwTabFrm *pTab = pFrm->ImplFindTabFrm();
2244 :
2245 : // if the table is in relative values (USHRT_MAX)
2246 : // then it should be recalculated to absolute values now
2247 0 : const SwFmtFrmSize& rTblFrmSz = pTab->GetFmt()->GetFrmSize();
2248 0 : SWRECTFN( pTab )
2249 0 : long nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)();
2250 0 : if( TBLVAR_CHGABS == pTab->GetTable()->GetTblChgMode() &&
2251 0 : ( eType & nsTblChgWidthHeightType::WH_COL_LEFT || eType & nsTblChgWidthHeightType::WH_COL_RIGHT ) &&
2252 0 : text::HoriOrientation::NONE == pTab->GetFmt()->GetHoriOrient().GetHoriOrient() &&
2253 0 : nPrtWidth != rTblFrmSz.GetWidth() )
2254 : {
2255 0 : SwFmtFrmSize aSz( rTblFrmSz );
2256 0 : aSz.SetWidth( pTab->Prt().Width() );
2257 0 : pTab->GetFmt()->SetFmtAttr( aSz );
2258 : }
2259 :
2260 0 : if( (eType & (nsTblChgWidthHeightType::WH_FLAG_BIGGER | nsTblChgWidthHeightType::WH_FLAG_INSDEL)) ==
2261 : (nsTblChgWidthHeightType::WH_FLAG_BIGGER | nsTblChgWidthHeightType::WH_FLAG_INSDEL) )
2262 : {
2263 0 : nDiff = sal_uInt16((pFrm->Frm().*fnRect->fnGetWidth)());
2264 :
2265 : // we must move the cursor outside the current cell before
2266 : // deleting the cells.
2267 : TblChgWidthHeightType eTmp =
2268 0 : static_cast<TblChgWidthHeightType>( eType & 0xfff );
2269 0 : switch( eTmp )
2270 : {
2271 : case nsTblChgWidthHeightType::WH_ROW_TOP:
2272 0 : lcl_GoTableRow( this, true );
2273 0 : break;
2274 : case nsTblChgWidthHeightType::WH_ROW_BOTTOM:
2275 0 : lcl_GoTableRow( this, false );
2276 0 : break;
2277 : case nsTblChgWidthHeightType::WH_COL_LEFT:
2278 0 : GoPrevCell();
2279 0 : break;
2280 : case nsTblChgWidthHeightType::WH_COL_RIGHT:
2281 0 : GoNextCell();
2282 0 : break;
2283 : default:
2284 0 : break;
2285 : }
2286 : }
2287 :
2288 0 : SwTwips nLogDiff = nDiff;
2289 0 : nLogDiff *= pTab->GetFmt()->GetFrmSize().GetWidth();
2290 0 : nLogDiff /= nPrtWidth;
2291 :
2292 : /** The cells are destroyed in here */
2293 : sal_Bool bRet = GetDoc()->SetColRowWidthHeight(
2294 0 : *(SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox(),
2295 0 : eType, nDiff, nLogDiff );
2296 :
2297 0 : delete pLastCols, pLastCols = 0;
2298 0 : EndAllActionAndCall();
2299 :
2300 0 : if( bRet && (eType & (nsTblChgWidthHeightType::WH_FLAG_BIGGER | nsTblChgWidthHeightType::WH_FLAG_INSDEL)) == nsTblChgWidthHeightType::WH_FLAG_INSDEL )
2301 : {
2302 0 : switch(eType & ~(nsTblChgWidthHeightType::WH_FLAG_BIGGER | nsTblChgWidthHeightType::WH_FLAG_INSDEL))
2303 : {
2304 : case nsTblChgWidthHeightType::WH_CELL_LEFT:
2305 : case nsTblChgWidthHeightType::WH_COL_LEFT:
2306 0 : GoPrevCell();
2307 0 : break;
2308 :
2309 : case nsTblChgWidthHeightType::WH_CELL_RIGHT:
2310 : case nsTblChgWidthHeightType::WH_COL_RIGHT:
2311 0 : GoNextCell();
2312 0 : break;
2313 :
2314 : case nsTblChgWidthHeightType::WH_CELL_TOP:
2315 : case nsTblChgWidthHeightType::WH_ROW_TOP:
2316 0 : lcl_GoTableRow( this, true );
2317 0 : break;
2318 :
2319 : case nsTblChgWidthHeightType::WH_CELL_BOTTOM:
2320 : case nsTblChgWidthHeightType::WH_ROW_BOTTOM:
2321 0 : lcl_GoTableRow( this, false );
2322 0 : break;
2323 : }
2324 : }
2325 :
2326 0 : return bRet;
2327 : }
2328 :
2329 0 : static bool lcl_IsFormulaSelBoxes( const SwTable& rTbl, const SwTblBoxFormula& rFml,
2330 : SwCellFrms& rCells )
2331 : {
2332 0 : SwTblBoxFormula aTmp( rFml );
2333 0 : SwSelBoxes aBoxes;
2334 0 : aTmp.GetBoxesOfFormula(rTbl, aBoxes);
2335 0 : for (size_t nSelBoxes = aBoxes.size(); nSelBoxes; )
2336 : {
2337 0 : SwTableBox* pBox = aBoxes[ --nSelBoxes ];
2338 0 : SwCellFrms::iterator iC;
2339 0 : for( iC = rCells.begin(); iC != rCells.end(); ++iC )
2340 0 : if( (*iC)->GetTabBox() == pBox )
2341 0 : break; // found
2342 :
2343 0 : if( iC == rCells.end() )
2344 0 : return false;
2345 : }
2346 :
2347 0 : return true;
2348 : }
2349 :
2350 : // ask formula for auto-sum
2351 0 : sal_Bool SwFEShell::GetAutoSum( OUString& rFml ) const
2352 : {
2353 0 : SwFrm *pFrm = GetCurrFrm();
2354 0 : SwTabFrm *pTab = pFrm ? pFrm->ImplFindTabFrm() : 0;
2355 0 : if( !pTab )
2356 0 : return sal_False;
2357 :
2358 0 : SwCellFrms aCells;
2359 0 : OUString sFields;
2360 0 : if( ::GetAutoSumSel( *this, aCells ))
2361 : {
2362 0 : sal_uInt16 nW = 0;
2363 0 : for( size_t n = aCells.size(); n; )
2364 : {
2365 0 : SwCellFrm* pCFrm = aCells[ --n ];
2366 0 : sal_uInt16 nBoxW = pCFrm->GetTabBox()->IsFormulaOrValueBox();
2367 0 : if( !nBoxW )
2368 0 : break;
2369 :
2370 0 : if( !nW )
2371 : {
2372 0 : if( USHRT_MAX == nBoxW )
2373 0 : continue; // skip space at beginning
2374 :
2375 : // formula only if box is contained
2376 0 : if( RES_BOXATR_FORMULA == nBoxW &&
2377 0 : !::lcl_IsFormulaSelBoxes( *pTab->GetTable(), pCFrm->
2378 0 : GetTabBox()->GetFrmFmt()->GetTblBoxFormula(), aCells))
2379 : {
2380 0 : nW = RES_BOXATR_VALUE;
2381 : // restore previous spaces!
2382 0 : for( size_t i = aCells.size(); n+1 < i; )
2383 : {
2384 0 : sFields = "|<" + aCells[--i]->GetTabBox()->GetName() + ">"
2385 0 : + sFields;
2386 : }
2387 : }
2388 : else
2389 0 : nW = nBoxW;
2390 : }
2391 0 : else if( RES_BOXATR_VALUE == nW )
2392 : {
2393 : // search for values, Value/Formula/Text found -> include
2394 0 : if( RES_BOXATR_FORMULA == nBoxW &&
2395 0 : ::lcl_IsFormulaSelBoxes( *pTab->GetTable(), pCFrm->
2396 0 : GetTabBox()->GetFrmFmt()->GetTblBoxFormula(), aCells ))
2397 0 : break;
2398 0 : else if( USHRT_MAX != nBoxW )
2399 0 : sFields = OUString(cListDelim) + sFields;
2400 : else
2401 0 : break;
2402 : }
2403 0 : else if( RES_BOXATR_FORMULA == nW )
2404 : {
2405 : // only continue search when the current formula points to
2406 : // all boxes contained in the selection
2407 0 : if( RES_BOXATR_FORMULA == nBoxW )
2408 : {
2409 0 : if( !::lcl_IsFormulaSelBoxes( *pTab->GetTable(), pCFrm->
2410 0 : GetTabBox()->GetFrmFmt()->GetTblBoxFormula(), aCells ))
2411 : {
2412 : // redo only for values!
2413 :
2414 0 : nW = RES_BOXATR_VALUE;
2415 0 : sFields = OUString();
2416 : // restore previous spaces!
2417 0 : for( size_t i = aCells.size(); n+1 < i; )
2418 : {
2419 0 : sFields = "|<" + aCells[--i]->GetTabBox()->GetName() + ">"
2420 0 : + sFields;
2421 : }
2422 : }
2423 : else
2424 0 : sFields = OUString(cListDelim) + sFields;
2425 : }
2426 0 : else if( USHRT_MAX == nBoxW )
2427 0 : break;
2428 : else
2429 0 : continue; // ignore this box
2430 : }
2431 : else
2432 : // all other stuff terminates the loop
2433 : // possibly allow texts??
2434 0 : break;
2435 :
2436 0 : sFields = "<" + pCFrm->GetTabBox()->GetName() + ">" + sFields;
2437 : }
2438 : }
2439 :
2440 0 : rFml = OUString::createFromAscii( sCalc_Sum );
2441 0 : if (!sFields.isEmpty())
2442 : {
2443 0 : rFml += "(" + sFields + ")";
2444 : }
2445 :
2446 0 : return sal_True;
2447 : }
2448 :
2449 0 : sal_Bool SwFEShell::IsTableRightToLeft() const
2450 : {
2451 0 : SwFrm *pFrm = GetCurrFrm();
2452 0 : if( !pFrm || !pFrm->IsInTab() )
2453 0 : return sal_False;
2454 :
2455 0 : return pFrm->ImplFindTabFrm()->IsRightToLeft();
2456 : }
2457 :
2458 0 : sal_Bool SwFEShell::IsMouseTableRightToLeft(const Point &rPt) const
2459 : {
2460 0 : SwFrm *pFrm = (SwFrm *)GetBox( rPt );
2461 0 : const SwTabFrm* pTabFrm = pFrm ? pFrm->ImplFindTabFrm() : 0;
2462 : OSL_ENSURE( pTabFrm, "Table not found" );
2463 0 : return pTabFrm ? pTabFrm->IsRightToLeft() : sal_False;
2464 : }
2465 :
2466 0 : sal_Bool SwFEShell::IsTableVertical() const
2467 : {
2468 0 : SwFrm *pFrm = GetCurrFrm();
2469 0 : if( !pFrm || !pFrm->IsInTab() )
2470 0 : return sal_False;
2471 :
2472 0 : return pFrm->ImplFindTabFrm()->IsVertical();
2473 : }
2474 :
2475 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|