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