1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 #include <hintids.hxx>
27
28 #include <vcl/svapp.hxx>
29 #include <editeng/protitem.hxx>
30 #include <crsrsh.hxx>
31 #include <doc.hxx>
32 #include <cntfrm.hxx>
33 #include <editsh.hxx> //EndAllAction gibts nur an der EditShell
34 #include <pam.hxx>
35 #include <swtable.hxx>
36 #include <docary.hxx>
37 #include <frmatr.hxx>
38 #include <frmfmt.hxx>
39 #include <viscrs.hxx>
40 #include <callnk.hxx>
41 #include <tabfrm.hxx>
42 #include <ndtxt.hxx>
43 #include <shellres.hxx>
44 #include <cellatr.hxx>
45 #include <cellfrm.hxx>
46 #include <rowfrm.hxx>
47
48
49 // setze Crsr in die naechsten/vorherigen Celle
GoNextCell(sal_Bool bAppendLine)50 sal_Bool SwCrsrShell::GoNextCell( sal_Bool bAppendLine )
51 {
52 sal_Bool bRet = sal_False;
53 const SwTableNode* pTblNd = 0;
54
55 if( IsTableMode() || 0 != ( pTblNd = IsCrsrInTbl() ))
56 {
57 SwCursor* pCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
58 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
59 bRet = sal_True;
60
61 // Check if we have to move the cursor to a covered cell before
62 // proceeding:
63 const SwNode* pTableBoxStartNode = pCrsr->GetNode()->FindTableBoxStartNode();
64 const SwTableBox* pTableBox = 0;
65
66 if ( pCrsr->GetCrsrRowSpanOffset() )
67 {
68 pTableBox = pTableBoxStartNode->GetTblBox();
69 if ( pTableBox->getRowSpan() > 1 )
70 {
71 if ( !pTblNd )
72 pTblNd = IsCrsrInTbl();
73 pTableBox = & pTableBox->FindEndOfRowSpan( pTblNd->GetTable(),
74 (sal_uInt16)(pTableBox->getRowSpan() + pCrsr->GetCrsrRowSpanOffset() ) );
75 pTableBoxStartNode = pTableBox->GetSttNd();
76 }
77 }
78
79 SwNodeIndex aCellStt( *pTableBoxStartNode->EndOfSectionNode(), 1 );
80
81 // folgt nach dem EndNode der Cell ein weiterer StartNode, dann
82 // gibt es auch eine naechste Celle
83
84 if( !aCellStt.GetNode().IsStartNode() )
85 {
86 if( pCrsr->HasMark() || !bAppendLine )
87 bRet = sal_False;
88 else
89 {
90 // auf besonderen Wunsch: keine Line mehr vorhanden, dann
91 // mache doch eine neue:
92 if ( !pTableBox )
93 pTableBox = pTblNd->GetTable().GetTblBox(
94 pCrsr->GetPoint()->nNode.GetNode().
95 StartOfSectionIndex() );
96
97 ASSERT( pTableBox, "Box steht nicht in dieser Tabelle" );
98 SwSelBoxes aBoxes;
99
100 //Das Dokument veraendert sich evtl. ohne Action wuerden die Sichten
101 //nichts mitbekommen.
102 ((SwEditShell*)this)->StartAllAction();
103 bRet = pDoc->InsertRow( pTblNd->GetTable().
104 SelLineFromBox( pTableBox, aBoxes, sal_False ));
105 ((SwEditShell*)this)->EndAllAction();
106 }
107 }
108 if( bRet && 0 != ( bRet = pCrsr->GoNextCell() ))
109 UpdateCrsr(); // und den akt. Updaten
110 }
111 return bRet;
112 }
113
114
GoPrevCell()115 sal_Bool SwCrsrShell::GoPrevCell()
116 {
117 sal_Bool bRet = sal_False;
118 const SwTableNode* pTblNd;
119 if( IsTableMode() || 0 != ( pTblNd = IsCrsrInTbl() ))
120 {
121 SwCursor* pCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
122 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
123 bRet = pCrsr->GoPrevCell();
124 if( bRet )
125 UpdateCrsr(); // und den akt. Updaten
126 }
127 return bRet;
128 }
129
lcl_FindMostUpperCellFrm(const SwFrm * pFrm)130 const SwFrm* lcl_FindMostUpperCellFrm( const SwFrm* pFrm )
131 {
132 while ( pFrm &&
133 ( !pFrm->IsCellFrm() ||
134 !pFrm->GetUpper()->GetUpper()->IsTabFrm() ||
135 pFrm->GetUpper()->GetUpper()->GetUpper()->IsInTab() ) )
136 {
137 pFrm = pFrm->GetUpper();
138 }
139 return pFrm;
140 }
141
_SelTblRowOrCol(bool bRow,bool bRowSimple)142 sal_Bool SwCrsrShell::_SelTblRowOrCol( bool bRow, bool bRowSimple )
143 {
144 // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
145 SwFrm *pFrm = GetCurrFrm();
146 if( !pFrm->IsInTab() )
147 return sal_False;
148
149 const SwTabFrm* pTabFrm = pFrm->FindTabFrm();
150 const SwTabFrm* pMasterTabFrm = pTabFrm->IsFollow() ? pTabFrm->FindMaster( true ) : pTabFrm;
151 const SwTable* pTable = pTabFrm->GetTable();
152
153 SET_CURR_SHELL( this );
154
155 const SwTableBox* pStt = 0;
156 const SwTableBox* pEnd = 0;
157
158 // lasse ueber das Layout die Boxen suchen
159 SwSelBoxes aBoxes;
160 SwTblSearchType eType = bRow ? nsSwTblSearchType::TBLSEARCH_ROW : nsSwTblSearchType::TBLSEARCH_COL;
161 const bool bCheckProtected = !IsReadOnlyAvailable();
162
163 if( bCheckProtected )
164 eType = (SwTblSearchType)(eType | nsSwTblSearchType::TBLSEARCH_PROTECT);
165
166 if ( !bRowSimple )
167 {
168 GetTblSel( *this, aBoxes, eType );
169
170 if( !aBoxes.Count() )
171 return sal_False;
172
173 pStt = aBoxes[0];
174 pEnd = aBoxes[aBoxes.Count() - 1];
175 }
176 // --> FME 2004-07-30 #i32329# Enhanced table selection
177 else if ( pTable->IsNewModel() )
178 {
179 const SwShellCrsr *pCrsr = _GetCrsr();
180 SwTable::SearchType eSearchType = bRow ? SwTable::SEARCH_ROW : SwTable::SEARCH_COL;
181 pTable->CreateSelection( *pCrsr, aBoxes, eSearchType, bCheckProtected );
182 if( !aBoxes.Count() )
183 return sal_False;
184
185 pStt = aBoxes[0];
186 pEnd = aBoxes[aBoxes.Count() - 1];
187 }
188 else
189 {
190 const SwShellCrsr *pCrsr = _GetCrsr();
191 const SwFrm* pStartFrm = pFrm;
192 const SwCntntNode *pCNd = pCrsr->GetCntntNode( sal_False );
193 const SwFrm* pEndFrm = pCNd ? pCNd->getLayoutFrm( GetLayout(), &pCrsr->GetMkPos() ) : 0;
194
195 if ( bRow )
196 {
197 pStartFrm = lcl_FindMostUpperCellFrm( pStartFrm );
198 pEndFrm = lcl_FindMostUpperCellFrm( pEndFrm );
199 }
200
201 if ( !pStartFrm || !pEndFrm )
202 return sal_False;
203
204 const bool bVert = pFrm->ImplFindTabFrm()->IsVertical();
205
206 // If we select upwards it is sufficient to set pStt and pEnd
207 // to the first resp. last box of the selection obtained from
208 // GetTblSel. However, selecting downwards requires the frames
209 // located at the corners of the selection. This does not work
210 // for column selections in vertical tables:
211 const bool bSelectUp = ( bVert && !bRow ) ||
212 *pCrsr->GetPoint() <= *pCrsr->GetMark();
213 SwCellFrms aCells;
214 GetTblSel( static_cast<const SwCellFrm*>(pStartFrm),
215 static_cast<const SwCellFrm*>(pEndFrm),
216 aBoxes, bSelectUp ? 0 : &aCells, eType );
217
218 if( !aBoxes.Count() || ( !bSelectUp && 4 != aCells.Count() ) )
219 return sal_False;
220
221 if ( bSelectUp )
222 {
223 pStt = aBoxes[0];
224 pEnd = aBoxes[aBoxes.Count() - 1];
225 }
226 else
227 {
228 pStt = aCells[ bVert ? (bRow ? 0 : 3) : (bRow ? 2 : 1) ]->GetTabBox(); // will become point of table cursor
229 pEnd = aCells[ bVert ? (bRow ? 3 : 0) : (bRow ? 1 : 2) ]->GetTabBox(); // will become mark of table cursor
230 }
231 }
232 // <--
233
234 // noch kein Tabellen-Cursor vorhanden, dann erzeuge einen
235 if( !pTblCrsr )
236 {
237 pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() );
238 pCurCrsr->DeleteMark();
239 pCurCrsr->SwSelPaintRects::Hide();
240 }
241
242 pTblCrsr->DeleteMark();
243
244 // dann setze mal Anfang und Ende der Spalte
245 pTblCrsr->GetPoint()->nNode = *pEnd->GetSttNd();
246 pTblCrsr->Move( fnMoveForward, fnGoCntnt );
247 pTblCrsr->SetMark();
248 pTblCrsr->GetPoint()->nNode = *pStt->GetSttNd()->EndOfSectionNode();
249 pTblCrsr->Move( fnMoveBackward, fnGoCntnt );
250
251 // set PtPos 'close' to the reference table, otherwise we might get problems with the
252 // repeated headlines check in UpdateCrsr():
253 if ( !bRow )
254 pTblCrsr->GetPtPos() = pMasterTabFrm->IsVertical() ? pMasterTabFrm->Frm().TopRight() : pMasterTabFrm->Frm().TopLeft();
255
256 UpdateCrsr(); // und den akt. Updaten
257 return sal_True;
258 }
259
SelTbl()260 sal_Bool SwCrsrShell::SelTbl()
261 {
262 // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
263 SwFrm *pFrm = GetCurrFrm();
264 if( !pFrm->IsInTab() )
265 return sal_False;
266
267 const SwTabFrm *pTblFrm = pFrm->ImplFindTabFrm();
268 const SwTabFrm* pMasterTabFrm = pTblFrm->IsFollow() ? pTblFrm->FindMaster( true ) : pTblFrm;
269 const SwTableNode* pTblNd = pTblFrm->GetTable()->GetTableNode();
270
271 SET_CURR_SHELL( this );
272
273 if( !pTblCrsr )
274 {
275 pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() );
276 pCurCrsr->DeleteMark();
277 pCurCrsr->SwSelPaintRects::Hide();
278 }
279
280 pTblCrsr->DeleteMark();
281 pTblCrsr->GetPoint()->nNode = *pTblNd;
282 pTblCrsr->Move( fnMoveForward, fnGoCntnt );
283 pTblCrsr->SetMark();
284 // set MkPos 'close' to the master table, otherwise we might get problems with the
285 // repeated headlines check in UpdateCrsr():
286 pTblCrsr->GetMkPos() = pMasterTabFrm->IsVertical() ? pMasterTabFrm->Frm().TopRight() : pMasterTabFrm->Frm().TopLeft();
287 pTblCrsr->GetPoint()->nNode = *pTblNd->EndOfSectionNode();
288 pTblCrsr->Move( fnMoveBackward, fnGoCntnt );
289 UpdateCrsr(); // und den akt. Updaten
290 return sal_True;
291 }
292
293
SelTblBox()294 sal_Bool SwCrsrShell::SelTblBox()
295 {
296 // if we're in a table, create a table cursor, and select the cell
297 // that the current cursor's point resides in
298
299 // search for start node of our table box. If not found, exit really
300 const SwStartNode* pStartNode =
301 pCurCrsr->GetPoint()->nNode.GetNode().FindTableBoxStartNode();
302
303 #ifdef DBG_UTIL
304 // the old code checks whether we're in a table by asking the
305 // frame. This should yield the same result as searching for the
306 // table box start node, right?
307 SwFrm *pFrm = GetCurrFrm();
308 DBG_ASSERT( !pFrm->IsInTab() == !(pStartNode != NULL),
309 "Schroedinger's table: We're in a box, and also we aren't." );
310 #endif
311
312 if( pStartNode == NULL )
313 return sal_False;
314
315
316 SET_CURR_SHELL( this );
317
318 // create a table cursor, if there isn't one already
319 if( !pTblCrsr )
320 {
321 pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() );
322 pCurCrsr->DeleteMark();
323 pCurCrsr->SwSelPaintRects::Hide();
324 }
325
326 // select the complete box with our shiny new pTblCrsr
327 // 1. delete mark, and move point to first content node in box
328 // 2. set mark, and move point to last content node in box
329 // 3. exchange
330
331 pTblCrsr->DeleteMark();
332 *(pTblCrsr->GetPoint()) = SwPosition( *pStartNode );
333 pTblCrsr->Move( fnMoveForward, fnGoNode );
334
335 pTblCrsr->SetMark();
336 *(pTblCrsr->GetPoint()) = SwPosition( *(pStartNode->EndOfSectionNode()) );
337 pTblCrsr->Move( fnMoveBackward, fnGoNode );
338
339 pTblCrsr->Exchange();
340
341 // with some luck, UpdateCrsr() will now update everything that
342 // needs updateing
343 UpdateCrsr();
344
345 return sal_True;
346 }
347
348 // return the next non-protected cell inside a table
349 // rIdx - is on a table node
350 // return:
351 // true - Idx points to content in a suitable cell
352 // false - could not find a suitable cell
lcl_FindNextCell(SwNodeIndex & rIdx,sal_Bool bInReadOnly)353 bool lcl_FindNextCell( SwNodeIndex& rIdx, sal_Bool bInReadOnly )
354 {
355 // ueberpruefe geschuetzte Zellen
356 SwNodeIndex aTmp( rIdx, 2 ); // TableNode + StartNode
357
358 // the resulting cell should be in that table:
359 const SwTableNode* pTblNd = rIdx.GetNode().GetTableNode();
360
361 if ( !pTblNd )
362 {
363 ASSERT( false, "lcl_FindNextCell not celled with table start node!" )
364 return false;
365 }
366
367 const SwNode* pTableEndNode = pTblNd->EndOfSectionNode();
368
369 SwNodes& rNds = aTmp.GetNode().GetNodes();
370 SwCntntNode* pCNd = aTmp.GetNode().GetCntntNode();
371
372 // no content node => go to next content node
373 if( !pCNd )
374 pCNd = rNds.GoNext( &aTmp );
375
376 // robust
377 if ( !pCNd )
378 return false;
379
380 SwCntntFrm* pFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() );
381
382 if ( 0 == pFrm || pCNd->FindTableNode() != pTblNd ||
383 (!bInReadOnly && pFrm->IsProtected() ) )
384 {
385 // we are not located inside a 'valid' cell. We have to continue searching...
386
387 // skip behind current section. This might be the end of the table cell
388 // or behind a inner section or or or...
389 aTmp.Assign( *pCNd->EndOfSectionNode(), 1 );
390
391 // loop to find a suitable cell...
392 for( ;; )
393 {
394 SwNode* pNd = &aTmp.GetNode();
395
396 // we break this loop if we reached the end of the table.
397 // to make this code even more robust, we also break if we are
398 // already behind the table end node:
399 if( pNd == pTableEndNode || /*robust: */ pNd->GetIndex() > pTableEndNode->GetIndex() )
400 return false;
401
402 // ok, get the next content node:
403 pCNd = aTmp.GetNode().GetCntntNode();
404 if( 0 == pCNd )
405 pCNd = rNds.GoNext( &aTmp );
406
407 // robust:
408 if ( !pCNd )
409 return false;
410
411 // check if we have found a suitable table cell:
412 pFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() );
413
414 if ( 0 != pFrm && pCNd->FindTableNode() == pTblNd &&
415 (bInReadOnly || !pFrm->IsProtected() ) )
416 {
417 // finally, we have found a suitable table cell => set index and return
418 rIdx = *pCNd;
419 return true;
420 }
421
422 // continue behind the current section:
423 aTmp.Assign( *pCNd->EndOfSectionNode(), +1 );
424 }
425 }
426
427 rIdx = *pCNd;
428 return true;
429 }
430
431 // comments see lcl_FindNextCell
lcl_FindPrevCell(SwNodeIndex & rIdx,sal_Bool bInReadOnly)432 bool lcl_FindPrevCell( SwNodeIndex& rIdx, sal_Bool bInReadOnly )
433 {
434 SwNodeIndex aTmp( rIdx, -2 ); // TableNode + EndNode
435
436 const SwNode* pTableEndNode = &rIdx.GetNode();
437 const SwTableNode* pTblNd = pTableEndNode->StartOfSectionNode()->GetTableNode();
438
439 if ( !pTblNd )
440 {
441 ASSERT( false, "lcl_FindPrevCell not celled with table start node!" )
442 return false;
443 }
444
445 SwNodes& rNds = aTmp.GetNode().GetNodes();
446 SwCntntNode* pCNd = aTmp.GetNode().GetCntntNode();
447
448 if( !pCNd )
449 pCNd = rNds.GoPrevious( &aTmp );
450
451 if ( !pCNd )
452 return false;
453
454 SwCntntFrm* pFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() );
455
456 if( 0 == pFrm || pCNd->FindTableNode() != pTblNd ||
457 (!bInReadOnly && pFrm->IsProtected() ))
458 {
459 // skip before current section
460 aTmp.Assign( *pCNd->StartOfSectionNode(), -1 );
461 for( ;; )
462 {
463 SwNode* pNd = &aTmp.GetNode();
464
465 if( pNd == pTblNd || pNd->GetIndex() < pTblNd->GetIndex() )
466 return false;
467
468 pCNd = aTmp.GetNode().GetCntntNode();
469 if( 0 == pCNd )
470 pCNd = rNds.GoPrevious( &aTmp );
471
472 if ( !pCNd )
473 return false;
474
475 pFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() );
476
477 if( 0 != pFrm && pCNd->FindTableNode() == pTblNd &&
478 (bInReadOnly || !pFrm->IsProtected() ) )
479 {
480 rIdx = *pCNd;
481 return true; // Ok, nicht geschuetzt
482 }
483 aTmp.Assign( *pCNd->StartOfSectionNode(), - 1 );
484 }
485 }
486
487 rIdx = *pCNd;
488 return true;
489 }
490
491
GotoPrevTable(SwPaM & rCurCrsr,SwPosTable fnPosTbl,sal_Bool bInReadOnly)492 sal_Bool GotoPrevTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl,
493 sal_Bool bInReadOnly )
494 {
495 SwNodeIndex aIdx( rCurCrsr.GetPoint()->nNode );
496
497 SwTableNode* pTblNd = aIdx.GetNode().FindTableNode();
498 if( pTblNd )
499 {
500 // #i26532#: If we are inside a table, we may not go backward
501 // to the table start node, because we would miss any tables
502 // inside this table.
503 SwTableNode* pInnerTblNd = 0;
504 SwNodeIndex aTmpIdx( aIdx );
505 while( aTmpIdx.GetIndex() &&
506 0 == ( pInnerTblNd = aTmpIdx.GetNode().StartOfSectionNode()->GetTableNode()) )
507 aTmpIdx--;
508
509 if( pInnerTblNd == pTblNd )
510 aIdx.Assign( *pTblNd, - 1 );
511 }
512
513 do {
514 while( aIdx.GetIndex() &&
515 0 == ( pTblNd = aIdx.GetNode().StartOfSectionNode()->GetTableNode()) )
516 aIdx--;
517
518 if( pTblNd ) // gibt einen weiteren TableNode ?
519 {
520 if( fnPosTbl == fnMoveForward ) // an Anfang ?
521 {
522 aIdx = *aIdx.GetNode().StartOfSectionNode();
523 if( !lcl_FindNextCell( aIdx, bInReadOnly ))
524 {
525 // Tabelle ueberspringen
526 aIdx.Assign( *pTblNd, -1 );
527 continue;
528 }
529 }
530 else
531 {
532 // ueberpruefe geschuetzte Zellen
533 if( !lcl_FindNextCell( aIdx, bInReadOnly ))
534 {
535 // Tabelle ueberspringen
536 aIdx.Assign( *pTblNd, -1 );
537 continue;
538 }
539 }
540
541 SwTxtNode* pTxtNode = aIdx.GetNode().GetTxtNode();
542 if ( pTxtNode )
543 {
544 rCurCrsr.GetPoint()->nNode = *pTxtNode;
545 rCurCrsr.GetPoint()->nContent.Assign( pTxtNode, fnPosTbl == fnMoveBackward ?
546 pTxtNode->Len() :
547 0 );
548 }
549 return sal_True;
550 }
551 } while( pTblNd );
552
553 return sal_False;
554 }
555
556
GotoNextTable(SwPaM & rCurCrsr,SwPosTable fnPosTbl,sal_Bool bInReadOnly)557 sal_Bool GotoNextTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl,
558 sal_Bool bInReadOnly )
559 {
560 SwNodeIndex aIdx( rCurCrsr.GetPoint()->nNode );
561 SwTableNode* pTblNd = aIdx.GetNode().FindTableNode();
562
563 if( pTblNd )
564 aIdx.Assign( *pTblNd->EndOfSectionNode(), 1 );
565
566 sal_uLong nLastNd = rCurCrsr.GetDoc()->GetNodes().Count() - 1;
567 do {
568 while( aIdx.GetIndex() < nLastNd &&
569 0 == ( pTblNd = aIdx.GetNode().GetTableNode()) )
570 aIdx++;
571 if( pTblNd ) // gibt einen weiteren TableNode ?
572 {
573 if( fnPosTbl == fnMoveForward ) // an Anfang ?
574 {
575 if( !lcl_FindNextCell( aIdx, bInReadOnly ))
576 {
577 // Tabelle ueberspringen
578 aIdx.Assign( *pTblNd->EndOfSectionNode(), + 1 );
579 continue;
580 }
581 }
582 else
583 {
584 aIdx = *aIdx.GetNode().EndOfSectionNode();
585 // ueberpruefe geschuetzte Zellen
586 if( !lcl_FindNextCell( aIdx, bInReadOnly ))
587 {
588 // Tabelle ueberspringen
589 aIdx.Assign( *pTblNd->EndOfSectionNode(), + 1 );
590 continue;
591 }
592 }
593
594 SwTxtNode* pTxtNode = aIdx.GetNode().GetTxtNode();
595 if ( pTxtNode )
596 {
597 rCurCrsr.GetPoint()->nNode = *pTxtNode;
598 rCurCrsr.GetPoint()->nContent.Assign( pTxtNode, fnPosTbl == fnMoveBackward ?
599 pTxtNode->Len() :
600 0 );
601 }
602 return sal_True;
603 }
604 } while( pTblNd );
605
606 return sal_False;
607 }
608
609
GotoCurrTable(SwPaM & rCurCrsr,SwPosTable fnPosTbl,sal_Bool bInReadOnly)610 sal_Bool GotoCurrTable( SwPaM& rCurCrsr, SwPosTable fnPosTbl,
611 sal_Bool bInReadOnly )
612 {
613 SwTableNode* pTblNd = rCurCrsr.GetPoint()->nNode.GetNode().FindTableNode();
614 if( !pTblNd )
615 return sal_False;
616
617 SwTxtNode* pTxtNode = 0;
618 if( fnPosTbl == fnMoveBackward ) // ans Ende der Tabelle
619 {
620 SwNodeIndex aIdx( *pTblNd->EndOfSectionNode() );
621 if( !lcl_FindPrevCell( aIdx, bInReadOnly ))
622 return sal_False;
623 pTxtNode = aIdx.GetNode().GetTxtNode();
624 }
625 else
626 {
627 SwNodeIndex aIdx( *pTblNd );
628 if( !lcl_FindNextCell( aIdx, bInReadOnly ))
629 return sal_False;
630 pTxtNode = aIdx.GetNode().GetTxtNode();
631 }
632
633 if ( pTxtNode )
634 {
635 rCurCrsr.GetPoint()->nNode = *pTxtNode;
636 rCurCrsr.GetPoint()->nContent.Assign( pTxtNode, fnPosTbl == fnMoveBackward ?
637 pTxtNode->Len() :
638 0 );
639 }
640
641 return sal_True;
642 }
643
644
MoveTable(SwWhichTable fnWhichTbl,SwPosTable fnPosTbl)645 sal_Bool SwCursor::MoveTable( SwWhichTable fnWhichTbl, SwPosTable fnPosTbl )
646 {
647 sal_Bool bRet = sal_False;
648 SwTableCursor* pTblCrsr = dynamic_cast<SwTableCursor*>(this);
649
650 if( pTblCrsr || !HasMark() ) // nur wenn kein Mark oder ein TblCrsr
651 {
652 SwCrsrSaveState aSaveState( *this );
653 bRet = (*fnWhichTbl)( *this, fnPosTbl, IsReadOnlyAvailable() ) &&
654 !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
655 nsSwCursorSelOverFlags::SELOVER_TOGGLE );
656 }
657 return bRet;
658 }
659
MoveTable(SwWhichTable fnWhichTbl,SwPosTable fnPosTbl)660 sal_Bool SwCrsrShell::MoveTable( SwWhichTable fnWhichTbl, SwPosTable fnPosTbl )
661 {
662 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
663
664 SwShellCrsr* pCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
665 sal_Bool bCheckPos, bRet;
666 sal_uLong nPtNd = 0;
667 xub_StrLen nPtCnt = 0;
668
669 if( !pTblCrsr && pCurCrsr->HasMark() ) // wenn Mark und kein TblCrsr,
670 {
671 // dann auf jedenfall in den Tabellen-Modus schalten
672 pTblCrsr = new SwShellTableCrsr( *this, *pCurCrsr->GetPoint() );
673 pCurCrsr->DeleteMark();
674 pCurCrsr->SwSelPaintRects::Hide();
675 pTblCrsr->SetMark();
676 pCrsr = pTblCrsr;
677 bCheckPos = sal_False;
678 }
679 else
680 {
681 bCheckPos = sal_True;
682 nPtNd = pCrsr->GetPoint()->nNode.GetIndex();
683 nPtCnt = pCrsr->GetPoint()->nContent.GetIndex();
684 }
685
686 bRet = pCrsr->MoveTable( fnWhichTbl, fnPosTbl );
687
688 if( bRet )
689 {
690 //JP 28.10.97: Bug 45028 - die "oberste" Position setzen fuer
691 // wiederholte Kopfzeilen
692 pCrsr->GetPtPos() = Point();
693
694 UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
695
696 if( bCheckPos &&
697 pCrsr->GetPoint()->nNode.GetIndex() == nPtNd &&
698 pCrsr->GetPoint()->nContent.GetIndex() == nPtCnt )
699 bRet = sal_False;
700 }
701 return bRet;
702 }
703
704
IsTblComplex() const705 sal_Bool SwCrsrShell::IsTblComplex() const
706 {
707 SwFrm *pFrm = GetCurrFrm( sal_False );
708 if ( pFrm && pFrm->IsInTab() )
709 return pFrm->FindTabFrm()->GetTable()->IsTblComplex();
710 return sal_False;
711 }
712
713
IsTblComplexForChart()714 sal_Bool SwCrsrShell::IsTblComplexForChart()
715 {
716 sal_Bool bRet = sal_False;
717
718 StartAction(); // IsTblComplexForChart() may trigger table formatting
719 // we better do that inside an action
720
721 const SwTableNode* pTNd = pCurCrsr->GetPoint()->nNode.GetNode().FindTableNode();
722 if( pTNd )
723 {
724 // wir stehen in der Tabelle, dann teste mal, ob die Tabelle oder die
725 // Selektion ausgeglichen ist.
726 String sSel;
727 if( pTblCrsr )
728 sSel = GetBoxNms();
729 bRet = pTNd->GetTable().IsTblComplexForChart( sSel );
730 }
731
732 EndAction();
733
734 return bRet;
735 }
736
GetBoxNms() const737 String SwCrsrShell::GetBoxNms() const
738 {
739 String sNm;
740 const SwPosition* pPos;
741 SwFrm* pFrm;
742
743 if( IsTableMode() )
744 {
745 SwCntntNode *pCNd = pTblCrsr->Start()->nNode.GetNode().GetCntntNode();
746 pFrm = pCNd ? pCNd->getLayoutFrm( GetLayout() ) : 0;
747 if( !pFrm )
748 return sNm;
749
750 do {
751 pFrm = pFrm->GetUpper();
752 } while ( pFrm && !pFrm->IsCellFrm() );
753
754 ASSERT( pFrm, "kein Frame zur Box" );
755 sNm = ((SwCellFrm*)pFrm)->GetTabBox()->GetName();
756 sNm += ':';
757 pPos = pTblCrsr->End();
758 }
759 else
760 {
761 const SwTableNode* pTblNd = IsCrsrInTbl();
762 if( !pTblNd )
763 return sNm;
764 pPos = GetCrsr()->GetPoint();
765 }
766
767 SwCntntNode* pCNd = pPos->nNode.GetNode().GetCntntNode();
768 pFrm = pCNd ? pCNd->getLayoutFrm( GetLayout() ) : 0;
769
770 if( pFrm )
771 {
772 do {
773 pFrm = pFrm->GetUpper();
774 } while ( pFrm && !pFrm->IsCellFrm() );
775
776 if( pFrm )
777 sNm += ((SwCellFrm*)pFrm)->GetTabBox()->GetName();
778 }
779 return sNm;
780 }
781
782
GotoTable(const String & rName)783 sal_Bool SwCrsrShell::GotoTable( const String& rName )
784 {
785 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
786 sal_Bool bRet = !pTblCrsr && pCurCrsr->GotoTable( rName );
787 if( bRet )
788 {
789 pCurCrsr->GetPtPos() = Point();
790 UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
791 SwCrsrShell::READONLY ); // und den akt. Updaten
792 }
793 return bRet;
794 }
795
796
CheckTblBoxCntnt(const SwPosition * pPos)797 sal_Bool SwCrsrShell::CheckTblBoxCntnt( const SwPosition* pPos )
798 {
799 if( !pBoxIdx || !pBoxPtr || IsSelTblCells() || !IsAutoUpdateCells() )
800 return sal_False;
801
802 // ueberpruefe, ob der Box Inhalt mit dem angegebenen Format der Box
803 // ueber einstimmt. Wenn nicht, setze neu
804 SwTableBox* pChkBox = 0;
805 SwStartNode* pSttNd = 0;
806 if( !pPos )
807 {
808 // gesicherte Position heraus holen.
809 if( pBoxIdx && pBoxPtr &&
810 0 != ( pSttNd = pBoxIdx->GetNode().GetStartNode() ) &&
811 SwTableBoxStartNode == pSttNd->GetStartNodeType() &&
812 pBoxPtr == pSttNd->FindTableNode()->GetTable().
813 GetTblBox( pBoxIdx->GetIndex() ) )
814 pChkBox = pBoxPtr;
815 }
816 else if( 0 != ( pSttNd = pPos->nNode.GetNode().
817 FindSttNodeByType( SwTableBoxStartNode )) )
818 {
819 pChkBox = pSttNd->FindTableNode()->GetTable().GetTblBox( pSttNd->GetIndex() );
820 }
821
822
823 // Box mehr als 1 Absatz?
824 if( pChkBox && pSttNd->GetIndex() + 2 != pSttNd->EndOfSectionIndex() )
825 pChkBox = 0;
826
827 // jetzt sollten wir mal die Pointer zerstoeren, bevor eine erneute
828 // Actionklammerung kommt.
829 if( !pPos && !pChkBox )
830 ClearTblBoxCntnt();
831
832 // liegt der Cursor nicht mehr in dem Bereich ?
833 if( pChkBox && !pPos &&
834 ( pCurCrsr->HasMark() || pCurCrsr->GetNext() != pCurCrsr ||
835 pSttNd->GetIndex() + 1 == pCurCrsr->GetPoint()->nNode.GetIndex() ))
836 pChkBox = 0;
837
838 //JP 12.01.99: hat sich der Inhalt der Box ueberhaupt veraendert?
839 // Ist wichtig, wenn z.B. Undo nicht den richtigen Inhalt wieder
840 // herstellen konnte.
841 if( pChkBox )
842 {
843 const SwTxtNode* pNd = GetDoc()->GetNodes()[
844 pSttNd->GetIndex() + 1 ]->GetTxtNode();
845 if( !pNd ||
846 ( pNd->GetTxt() == ViewShell::GetShellRes()->aCalc_Error &&
847 SFX_ITEM_SET == pChkBox->GetFrmFmt()->
848 GetItemState( RES_BOXATR_FORMULA )) )
849 pChkBox = 0;
850 }
851
852 if( pChkBox )
853 {
854 // jetzt sollten wir mal die Pointer zerstoeren, bevor ein weiterer
855 // aufruf kommt.
856 ClearTblBoxCntnt();
857 StartAction();
858 GetDoc()->ChkBoxNumFmt( *pChkBox, sal_True );
859 EndAction();
860 }
861
862 return 0 != pChkBox;
863 }
864
865
SaveTblBoxCntnt(const SwPosition * pPos)866 void SwCrsrShell::SaveTblBoxCntnt( const SwPosition* pPos )
867 {
868 if( IsSelTblCells() || !IsAutoUpdateCells() )
869 return ;
870
871 if( !pPos )
872 pPos = pCurCrsr->GetPoint();
873
874 SwStartNode* pSttNd = pPos->nNode.GetNode().FindSttNodeByType( SwTableBoxStartNode );
875
876 sal_Bool bCheckBox = sal_False;
877 if( pSttNd && pBoxIdx )
878 {
879 if( pSttNd == &pBoxIdx->GetNode() )
880 pSttNd = 0; // die haben wir schon
881 else
882 bCheckBox = sal_True;
883 }
884 else
885 bCheckBox = 0 != pBoxIdx;
886
887 if( bCheckBox )
888 {
889 // pBoxIdx Checken
890 SwPosition aPos( *pBoxIdx );
891 CheckTblBoxCntnt( &aPos );
892 }
893
894 if( pSttNd )
895 {
896 pBoxPtr = pSttNd->FindTableNode()->GetTable().GetTblBox( pSttNd->GetIndex() );
897
898 if( pBoxIdx )
899 *pBoxIdx = *pSttNd;
900 else
901 pBoxIdx = new SwNodeIndex( *pSttNd );
902 }
903 }
904
905
ClearTblBoxCntnt()906 void SwCrsrShell::ClearTblBoxCntnt()
907 {
908 delete pBoxIdx, pBoxIdx = 0;
909 pBoxPtr = 0;
910 }
911
EndAllTblBoxEdit()912 sal_Bool SwCrsrShell::EndAllTblBoxEdit()
913 {
914 sal_Bool bRet = sal_False;
915 ViewShell *pSh = this;
916 do {
917 if( pSh->IsA( TYPE( SwCrsrShell ) ) )
918 bRet |= ((SwCrsrShell*)pSh)->CheckTblBoxCntnt(
919 ((SwCrsrShell*)pSh)->pCurCrsr->GetPoint() );
920
921 } while( this != (pSh = (ViewShell *)pSh->GetNext()) );
922 return bRet;
923 }
924
925
926
927
928