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