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_sc.hxx"
26
27 //------------------------------------------------------------------
28
29 #include "scitems.hxx"
30
31 #include <svl/slstitm.hxx>
32 #include <svl/stritem.hxx>
33 #include <svl/whiter.hxx>
34 #include <unotools/moduleoptions.hxx>
35 #include <svtools/cliplistener.hxx>
36 #include <svtools/insdlg.hxx>
37 #include <sot/formats.hxx>
38 #include <svx/hlnkitem.hxx>
39 #include <sfx2/app.hxx>
40 #include <sfx2/bindings.hxx>
41 #include <sfx2/childwin.hxx>
42 #include <sfx2/objface.hxx>
43 #include <sfx2/request.hxx>
44 #include <sfx2/viewfrm.hxx>
45 #include <sfx2/sidebar/EnumContext.hxx>
46 #include <svx/clipfmtitem.hxx>
47 #include <svx/sidebar/ContextChangeEventMultiplexer.hxx>
48 #include <editeng/langitem.hxx>
49
50 #include "cellsh.hxx"
51 #include "sc.hrc"
52 #include "docsh.hxx"
53 #include "attrib.hxx"
54 #include "scresid.hxx"
55 #include "tabvwsh.hxx"
56 #include "impex.hxx"
57 #include "cell.hxx"
58 #include "scmod.hxx"
59 #include "globstr.hrc"
60 #include "transobj.hxx"
61 #include "drwtrans.hxx"
62 #include "scabstdlg.hxx"
63 #include "dociter.hxx"
64 #include "postit.hxx"
65
66 //------------------------------------------------------------------
67
68 #define ScCellShell
69 #define CellMovement
70 #include "scslots.hxx"
71
72 TYPEINIT1( ScCellShell, ScFormatShell );
73
SFX_IMPL_INTERFACE(ScCellShell,ScFormatShell,ScResId (SCSTR_CELLSHELL))74 SFX_IMPL_INTERFACE(ScCellShell, ScFormatShell , ScResId(SCSTR_CELLSHELL) )
75 {
76 SFX_OBJECTBAR_REGISTRATION( SFX_OBJECTBAR_OBJECT | SFX_VISIBILITY_STANDARD |
77 SFX_VISIBILITY_SERVER,
78 ScResId(RID_OBJECTBAR_FORMAT));
79 SFX_POPUPMENU_REGISTRATION(ScResId(RID_POPUP_CELLS));
80 }
81
82
ScCellShell(ScViewData * pData)83 ScCellShell::ScCellShell(ScViewData* pData) :
84 ScFormatShell(pData),
85 pImpl( new CellShell_Impl() ),
86 bPastePossible(sal_False)
87 {
88 SetHelpId(HID_SCSHELL_CELLSH);
89 SetName(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Cell")));
90 SfxShell::SetContextName(sfx2::sidebar::EnumContext::GetContextName(sfx2::sidebar::EnumContext::Context_Cell));
91 }
92
~ScCellShell()93 ScCellShell::~ScCellShell()
94 {
95 if ( pImpl->m_pClipEvtLstnr )
96 {
97 pImpl->m_pClipEvtLstnr->AddRemoveListener( GetViewData()->GetActiveWin(), sal_False );
98
99 // #103849# The listener may just now be waiting for the SolarMutex and call the link
100 // afterwards, in spite of RemoveListener. So the link has to be reset, too.
101 pImpl->m_pClipEvtLstnr->ClearCallbackLink();
102
103 pImpl->m_pClipEvtLstnr->release();
104 }
105
106 delete pImpl->m_pLinkedDlg;
107 delete pImpl->m_pRequest;
108 delete pImpl;
109 }
110
111 //------------------------------------------------------------------
112
GetBlockState(SfxItemSet & rSet)113 void ScCellShell::GetBlockState( SfxItemSet& rSet )
114 {
115 ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell();
116 ScRange aMarkRange;
117 ScMarkType eMarkType = GetViewData()->GetSimpleArea( aMarkRange );
118 sal_Bool bSimpleArea = (eMarkType == SC_MARK_SIMPLE);
119 sal_Bool bOnlyNotBecauseOfMatrix;
120 sal_Bool bEditable = pTabViewShell->SelectionEditable( &bOnlyNotBecauseOfMatrix );
121 ScDocument* pDoc = GetViewData()->GetDocument();
122 ScDocShell* pDocShell = GetViewData()->GetDocShell();
123 ScMarkData& rMark = GetViewData()->GetMarkData();
124 SCCOL nCol1, nCol2;
125 SCROW nRow1, nRow2;
126 nCol1 = aMarkRange.aStart.Col();
127 nRow1 = aMarkRange.aStart.Row();
128 nCol2 = aMarkRange.aEnd.Col();
129 nRow2 = aMarkRange.aEnd.Row();
130
131 SfxWhichIter aIter(rSet);
132 sal_uInt16 nWhich = aIter.FirstWhich();
133 while ( nWhich )
134 {
135 sal_Bool bDisable = sal_False;
136 sal_Bool bNeedEdit = sal_True; // muss Selektion editierbar sein?
137 switch ( nWhich )
138 {
139 case FID_FILL_TO_BOTTOM: // Fuellen oben/unten
140 case FID_FILL_TO_TOP: // mind. 2 Zeilen markiert?
141 bDisable = (!bSimpleArea) || (nRow1 == nRow2);
142 if ( !bDisable && bEditable )
143 { // Matrix nicht zerreissen
144 if ( nWhich == FID_FILL_TO_BOTTOM )
145 bDisable = pDoc->HasSelectedBlockMatrixFragment(
146 nCol1, nRow1, nCol2, nRow1, rMark ); // erste Zeile
147 else
148 bDisable = pDoc->HasSelectedBlockMatrixFragment(
149 nCol1, nRow2, nCol2, nRow2, rMark ); // letzte Zeile
150 }
151 break;
152
153 case FID_FILL_TO_RIGHT: // Fuellen links/rechts
154 case FID_FILL_TO_LEFT: // mind. 2 Spalten markiert?
155 bDisable = (!bSimpleArea) || (nCol1 == nCol2);
156 if ( !bDisable && bEditable )
157 { // Matrix nicht zerreissen
158 if ( nWhich == FID_FILL_TO_RIGHT )
159 bDisable = pDoc->HasSelectedBlockMatrixFragment(
160 nCol1, nRow1, nCol1, nRow2, rMark ); // erste Spalte
161 else
162 bDisable = pDoc->HasSelectedBlockMatrixFragment(
163 nCol2, nRow1, nCol2, nRow2, rMark ); // letzte Spalte
164 }
165 break;
166
167 case FID_FILL_SERIES: // Block fuellen
168 case SID_OPENDLG_TABOP: // Mehrfachoperationen, mind. 2 Zellen markiert?
169 if (pDoc->GetChangeTrack()!=NULL &&nWhich ==SID_OPENDLG_TABOP)
170 bDisable = sal_True;
171 else
172 bDisable = (!bSimpleArea) || (nCol1 == nCol2 && nRow1 == nRow2);
173
174 if ( !bDisable && bEditable && nWhich == FID_FILL_SERIES )
175 { // Matrix nicht zerreissen
176 bDisable = pDoc->HasSelectedBlockMatrixFragment(
177 nCol1, nRow1, nCol2, nRow1, rMark ) // erste Zeile
178 || pDoc->HasSelectedBlockMatrixFragment(
179 nCol1, nRow2, nCol2, nRow2, rMark ) // letzte Zeile
180 || pDoc->HasSelectedBlockMatrixFragment(
181 nCol1, nRow1, nCol1, nRow2, rMark ) // erste Spalte
182 || pDoc->HasSelectedBlockMatrixFragment(
183 nCol2, nRow1, nCol2, nRow2, rMark ); // letzte Spalte
184 }
185 break;
186
187 case SID_CUT: // Ausschneiden,
188 case FID_INS_CELL: // Zellen einfuegen, nur einf. Selektion
189 bDisable = (!bSimpleArea);
190 break;
191
192 case FID_INS_ROW: // insert rows
193 case FID_INS_CELLSDOWN:
194 bDisable = (!bSimpleArea) || GetViewData()->SimpleColMarked();
195 break;
196
197 case FID_INS_COLUMN: // insert columns
198 case FID_INS_CELLSRIGHT:
199 bDisable = (!bSimpleArea) || GetViewData()->SimpleRowMarked();
200 break;
201
202 case SID_COPY: // Kopieren
203 // nur wegen Matrix nicht editierbar? Matrix nicht zerreissen
204 //! schlaegt nicht zu, wenn geschuetzt UND Matrix, aber damit
205 //! muss man leben.. wird in Copy-Routine abgefangen, sonst
206 //! muesste hier nochmal Aufwand getrieben werden
207 if ( !(!bEditable && bOnlyNotBecauseOfMatrix) )
208 bNeedEdit = sal_False; // erlaubt, wenn geschuetzt/ReadOnly
209 break;
210
211 case SID_AUTOFORMAT: // Autoformat, mind. 3x3 selektiert
212 bDisable = (!bSimpleArea)
213 || ((nCol2 - nCol1) < 2) || ((nRow2 - nRow1) < 2);
214 break;
215
216 case SID_OPENDLG_CONDFRMT :
217 {
218 if ( !bEditable && bOnlyNotBecauseOfMatrix )
219 {
220 bNeedEdit = sal_False;
221 }
222 if ( pDocShell && pDocShell->IsDocShared() )
223 {
224 bDisable = sal_True;
225 }
226 }
227 break;
228
229 case FID_CONDITIONAL_FORMAT :
230 case SID_CELL_FORMAT_RESET :
231 case FID_CELL_FORMAT :
232 case SID_ENABLE_HYPHENATION :
233 // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
234 if ( !bEditable && bOnlyNotBecauseOfMatrix )
235 bNeedEdit = sal_False;
236 break;
237
238 case FID_VALIDATION:
239 {
240 if ( pDocShell && pDocShell->IsDocShared() )
241 {
242 bDisable = sal_True;
243 }
244 }
245 break;
246
247 case SID_TRANSLITERATE_HALFWIDTH:
248 case SID_TRANSLITERATE_FULLWIDTH:
249 case SID_TRANSLITERATE_HIRAGANA:
250 case SID_TRANSLITERATE_KATAGANA:
251 ScViewUtil::HideDisabledSlot( rSet, GetViewData()->GetBindings(), nWhich );
252 break;
253 }
254 if (!bDisable && bNeedEdit && !bEditable)
255 bDisable = sal_True;
256
257 if (bDisable)
258 rSet.DisableItem(nWhich);
259 else if (nWhich == SID_ENABLE_HYPHENATION)
260 {
261 // toggle slots need a bool item
262 rSet.Put( SfxBoolItem( nWhich, sal_False ) );
263 }
264 nWhich = aIter.NextWhich();
265 }
266 }
267
268 // Funktionen, die je nach Cursorposition disabled sind
269 // Default:
270 // SID_INSERT_POSTIT, SID_CHARMAP, SID_OPENDLG_FUNCTION
271
GetCellState(SfxItemSet & rSet)272 void ScCellShell::GetCellState( SfxItemSet& rSet )
273 {
274 ScDocShell* pDocShell = GetViewData()->GetDocShell();
275 ScDocument* pDoc = GetViewData()->GetDocShell()->GetDocument();
276 ScAddress aCursor( GetViewData()->GetCurX(), GetViewData()->GetCurY(),
277 GetViewData()->GetTabNo() );
278
279 SfxWhichIter aIter(rSet);
280 sal_uInt16 nWhich = aIter.FirstWhich();
281 while ( nWhich )
282 {
283 sal_Bool bDisable = sal_False;
284 sal_Bool bNeedEdit = sal_True; // muss Cursorposition editierbar sein?
285 switch ( nWhich )
286 {
287 case SID_THESAURUS:
288 {
289 CellType eType = pDoc->GetCellType( aCursor );
290 bDisable = ( eType != CELLTYPE_STRING && eType != CELLTYPE_EDIT);
291 if (!bDisable)
292 {
293 // test for available languages
294 sal_uInt16 nLang = ScViewUtil::GetEffLanguage( pDoc, aCursor );
295 bDisable = !ScModule::HasThesaurusLanguage( nLang );
296 }
297 }
298 break;
299 case SID_OPENDLG_FUNCTION:
300 {
301 ScMarkData aMarkData=GetViewData()->GetMarkData();
302 aMarkData.MarkToSimple();
303 ScRange aRange;
304 aMarkData.GetMarkArea(aRange);
305 if(aMarkData.IsMarked())
306 {
307 if (!pDoc->IsBlockEditable( aCursor.Tab(), aRange.aStart.Col(),aRange.aStart.Row(),
308 aRange.aEnd.Col(),aRange.aEnd.Row() ))
309 {
310 bDisable = sal_True;
311 }
312 bNeedEdit=sal_False;
313 }
314
315 }
316 break;
317 case SID_INSERT_POSTIT:
318 {
319 if ( pDocShell && pDocShell->IsDocShared() )
320 {
321 bDisable = sal_True;
322 }
323 }
324 break;
325 }
326 if (!bDisable && bNeedEdit)
327 if (!pDoc->IsBlockEditable( aCursor.Tab(), aCursor.Col(),aCursor.Row(),
328 aCursor.Col(),aCursor.Row() ))
329 bDisable = sal_True;
330 if (bDisable)
331 rSet.DisableItem(nWhich);
332 nWhich = aIter.NextWhich();
333 }
334 }
335
lcl_TestFormat(SvxClipboardFmtItem & rFormats,const TransferableDataHelper & rDataHelper,SotFormatStringId nFormatId)336 sal_Bool lcl_TestFormat( SvxClipboardFmtItem& rFormats, const TransferableDataHelper& rDataHelper,
337 SotFormatStringId nFormatId )
338 {
339 if ( rDataHelper.HasFormat( nFormatId ) )
340 {
341 // #90675# translated format name strings are no longer inserted here,
342 // handled by "paste special" dialog / toolbox controller instead.
343 // Only the object type name has to be set here:
344 String aStrVal;
345 if ( nFormatId == SOT_FORMATSTR_ID_EMBED_SOURCE )
346 {
347 TransferableObjectDescriptor aDesc;
348 if ( ((TransferableDataHelper&)rDataHelper).GetTransferableObjectDescriptor(
349 SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aDesc ) )
350 aStrVal = aDesc.maTypeName;
351 }
352 else if ( nFormatId == SOT_FORMATSTR_ID_EMBED_SOURCE_OLE
353 || nFormatId == SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE )
354 {
355 String aSource;
356 SvPasteObjectHelper::GetEmbeddedName( rDataHelper, aStrVal, aSource, nFormatId );
357 }
358
359 if ( aStrVal.Len() )
360 rFormats.AddClipbrdFormat( nFormatId, aStrVal );
361 else
362 rFormats.AddClipbrdFormat( nFormatId );
363
364 return sal_True;
365 }
366
367 return sal_False;
368 }
369
GetPossibleClipboardFormats(SvxClipboardFmtItem & rFormats)370 void ScCellShell::GetPossibleClipboardFormats( SvxClipboardFmtItem& rFormats )
371 {
372 Window* pWin = GetViewData()->GetActiveWin();
373 sal_Bool bDraw = ( ScDrawTransferObj::GetOwnClipboard( pWin ) != NULL );
374
375 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
376
377 lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_DRAWING );
378 lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_SVXB );
379 lcl_TestFormat( rFormats, aDataHelper, SOT_FORMAT_GDIMETAFILE );
380 lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_PNG );
381 lcl_TestFormat( rFormats, aDataHelper, SOT_FORMAT_BITMAP );
382 lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_EMBED_SOURCE );
383
384 if ( !bDraw )
385 {
386 lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_LINK );
387 lcl_TestFormat( rFormats, aDataHelper, SOT_FORMAT_STRING );
388 lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_DIF );
389 lcl_TestFormat( rFormats, aDataHelper, SOT_FORMAT_RTF );
390 lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_HTML );
391 lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_HTML_SIMPLE );
392 lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_BIFF_8 );
393 lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_BIFF_5 );
394 }
395
396 if ( !lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) )
397 lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE );
398 }
399
400 // Einfuegen, Inhalte einfuegen
401
lcl_IsCellPastePossible(const TransferableDataHelper & rData)402 sal_Bool lcl_IsCellPastePossible( const TransferableDataHelper& rData )
403 {
404 sal_Bool bPossible = sal_False;
405 if ( ScTransferObj::GetOwnClipboard( NULL ) || ScDrawTransferObj::GetOwnClipboard( NULL ) )
406 bPossible = sal_True;
407 else
408 {
409 if ( rData.HasFormat( SOT_FORMATSTR_ID_PNG ) ||
410 rData.HasFormat( SOT_FORMAT_BITMAP ) ||
411 rData.HasFormat( SOT_FORMAT_GDIMETAFILE ) ||
412 rData.HasFormat( SOT_FORMATSTR_ID_SVXB ) ||
413 rData.HasFormat( FORMAT_PRIVATE ) ||
414 rData.HasFormat( SOT_FORMAT_RTF ) ||
415 rData.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ) ||
416 rData.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
417 rData.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) ||
418 rData.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
419 rData.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) ||
420 rData.HasFormat( SOT_FORMAT_STRING ) ||
421 rData.HasFormat( SOT_FORMATSTR_ID_SYLK ) ||
422 rData.HasFormat( SOT_FORMATSTR_ID_LINK ) ||
423 rData.HasFormat( SOT_FORMATSTR_ID_HTML ) ||
424 rData.HasFormat( SOT_FORMATSTR_ID_HTML_SIMPLE ) ||
425 rData.HasFormat( SOT_FORMATSTR_ID_DIF ) )
426 {
427 bPossible = sal_True;
428 }
429 }
430 return bPossible;
431 }
432
IMPL_LINK(ScCellShell,ClipboardChanged,TransferableDataHelper *,pDataHelper)433 IMPL_LINK( ScCellShell, ClipboardChanged, TransferableDataHelper*, pDataHelper )
434 {
435 if ( pDataHelper )
436 {
437 bPastePossible = lcl_IsCellPastePossible( *pDataHelper );
438
439 SfxBindings& rBindings = GetViewData()->GetBindings();
440 rBindings.Invalidate( SID_PASTE );
441 rBindings.Invalidate( SID_PASTE_SPECIAL );
442 rBindings.Invalidate( SID_CLIPBOARD_FORMAT_ITEMS );
443 }
444 return 0;
445 }
446
447
GetClipState(SfxItemSet & rSet)448 void __EXPORT ScCellShell::GetClipState( SfxItemSet& rSet )
449 {
450 // SID_PASTE
451 // SID_PASTE_SPECIAL
452 // SID_CLIPBOARD_FORMAT_ITEMS
453
454 if ( !pImpl->m_pClipEvtLstnr )
455 {
456 // create listener
457 pImpl->m_pClipEvtLstnr = new TransferableClipboardListener( LINK( this, ScCellShell, ClipboardChanged ) );
458 pImpl->m_pClipEvtLstnr->acquire();
459 Window* pWin = GetViewData()->GetActiveWin();
460 pImpl->m_pClipEvtLstnr->AddRemoveListener( pWin, sal_True );
461
462 // get initial state
463 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
464 bPastePossible = lcl_IsCellPastePossible( aDataHelper );
465 }
466
467 sal_Bool bDisable = !bPastePossible;
468
469 // Zellschutz / Multiselektion
470
471 if (!bDisable)
472 {
473 SCCOL nCol = GetViewData()->GetCurX();
474 SCROW nRow = GetViewData()->GetCurY();
475 SCTAB nTab = GetViewData()->GetTabNo();
476 ScDocument* pDoc = GetViewData()->GetDocShell()->GetDocument();
477 if (!pDoc->IsBlockEditable( nTab, nCol,nRow, nCol,nRow ))
478 bDisable = sal_True;
479 ScRange aDummy;
480 ScMarkType eMarkType = GetViewData()->GetSimpleArea( aDummy);
481 if (eMarkType != SC_MARK_SIMPLE && eMarkType != SC_MARK_SIMPLE_FILTERED)
482 bDisable = sal_True;
483 }
484
485 if (bDisable)
486 {
487 rSet.DisableItem( SID_PASTE );
488 rSet.DisableItem( SID_PASTE_SPECIAL );
489 rSet.DisableItem( SID_CLIPBOARD_FORMAT_ITEMS );
490 }
491 else if ( rSet.GetItemState( SID_CLIPBOARD_FORMAT_ITEMS ) != SFX_ITEM_UNKNOWN )
492 {
493 SvxClipboardFmtItem aFormats( SID_CLIPBOARD_FORMAT_ITEMS );
494 GetPossibleClipboardFormats( aFormats );
495 rSet.Put( aFormats );
496 }
497 }
498
499 // only SID_HYPERLINK_GETLINK:
500
GetHLinkState(SfxItemSet & rSet)501 void ScCellShell::GetHLinkState( SfxItemSet& rSet )
502 {
503 // always return an item (or inserting will be disabled)
504 // if the cell at the cursor contains only a link, return that link
505
506 SvxHyperlinkItem aHLinkItem;
507 if ( !GetViewData()->GetView()->HasBookmarkAtCursor( &aHLinkItem ) )
508 {
509 //! put selected text into item?
510 }
511
512 rSet.Put(aHLinkItem);
513 }
514
GetState(SfxItemSet & rSet)515 void ScCellShell::GetState(SfxItemSet &rSet)
516 {
517 // removed: SID_BORDER_OBJECT (old Basic)
518
519 ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell();
520 // sal_Bool bOle = pTabViewShell->GetViewFrame()->GetFrame().IsInPlace();
521 // sal_Bool bTabProt = GetViewData()->GetDocument()->IsTabProtected(GetViewData()->GetTabNo());
522 ScDocShell* pDocSh = GetViewData()->GetDocShell();
523 ScViewData* pData = GetViewData();
524 ScDocument* pDoc = pData->GetDocument();
525 ScMarkData& rMark = pData->GetMarkData();
526 SCCOL nPosX = pData->GetCurX();
527 SCROW nPosY = pData->GetCurY();
528 SCTAB nTab = pData->GetTabNo();
529
530 SCTAB nTabCount = pDoc->GetTableCount();
531 SCTAB nTabSelCount = rMark.GetSelectCount();
532
533
534
535 SfxWhichIter aIter(rSet);
536 sal_uInt16 nWhich = aIter.FirstWhich();
537 while ( nWhich )
538 {
539 switch ( nWhich )
540 {
541 case SID_DETECTIVE_REFRESH:
542 if (!pDoc->HasDetectiveOperations())
543 rSet.DisableItem( nWhich );
544 break;
545
546 case SID_RANGE_ADDRESS:
547 {
548 ScRange aRange;
549 if ( pData->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
550 {
551 String aStr;
552 sal_uInt16 nFlags = SCA_VALID | SCA_TAB_3D;
553 aRange.Format(aStr,nFlags,pDoc);
554 rSet.Put( SfxStringItem( nWhich, aStr ) );
555 }
556 }
557 break;
558
559 case SID_RANGE_NOTETEXT:
560 {
561 // #43343# always take cursor position, do not use top-left cell of selection
562 ScAddress aPos( nPosX, nPosY, nTab );
563 String aNoteText;
564 if ( const ScPostIt* pNote = pDoc->GetNote( aPos ) )
565 aNoteText = pNote->GetText();
566 rSet.Put( SfxStringItem( nWhich, aNoteText ) );
567 }
568 break;
569
570 case SID_RANGE_ROW:
571 rSet.Put( SfxInt32Item( nWhich, nPosY+1 ) );
572 break;
573
574 case SID_RANGE_COL:
575 rSet.Put( SfxInt16Item( nWhich, nPosX+1 ) );
576 break;
577
578 case SID_RANGE_TABLE:
579 rSet.Put( SfxInt16Item( nWhich, nTab+1 ) );
580 break;
581
582 case SID_RANGE_VALUE:
583 {
584 double nValue;
585 pDoc->GetValue( nPosX, nPosY, nTab, nValue );
586 rSet.Put( ScDoubleItem( nWhich, nValue ) );
587 }
588 break;
589
590 case SID_RANGE_FORMULA:
591 {
592 String aString;
593 pDoc->GetFormula( nPosX, nPosY, nTab, aString );
594 if( aString.Len() == 0 )
595 {
596 pDoc->GetInputString( nPosX, nPosY, nTab, aString );
597 }
598 rSet.Put( SfxStringItem( nWhich, aString ) );
599 }
600 break;
601
602 case SID_RANGE_TEXTVALUE:
603 {
604 String aString;
605 pDoc->GetString( nPosX, nPosY, nTab, aString );
606 rSet.Put( SfxStringItem( nWhich, aString ) );
607 }
608 break;
609
610 case SID_STATUS_SELMODE:
611 {
612 /* 0: STD Click hebt Sel auf
613 * 1: ER Click erweitert Selektion
614 * 2: ERG Click definiert weitere Selektion
615 */
616 sal_uInt16 nMode = pTabViewShell->GetLockedModifiers();
617
618 switch ( nMode )
619 {
620 case KEY_SHIFT: nMode = 1; break;
621 case KEY_MOD1: nMode = 2; break; // Control-Taste
622 case 0:
623 default:
624 nMode = 0;
625 }
626
627 rSet.Put( SfxUInt16Item( nWhich, nMode ) );
628 }
629 break;
630
631 case SID_STATUS_DOCPOS:
632 {
633 String aStr( ScGlobal::GetRscString( STR_TABLE ) );
634
635 aStr += ' ';
636 aStr += String::CreateFromInt32( nTab + 1 );
637 aStr.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " / " ));
638 aStr += String::CreateFromInt32( nTabCount );
639 rSet.Put( SfxStringItem( nWhich, aStr ) );
640 }
641 break;
642
643 // Summe etc. mit Datum/Zeit/Fehler/Pos&Groesse zusammengefasst
644
645 // #i34458# The SfxStringItem belongs only into SID_TABLE_CELL. It no longer has to be
646 // duplicated in SID_ATTR_POSITION or SID_ATTR_SIZE for SvxPosSizeStatusBarControl.
647 case SID_TABLE_CELL:
648 {
649 // Testen, ob Fehler unter Cursor
650 // (nicht pDoc->GetErrCode, um keine zirkulaeren Referenzen auszuloesen)
651
652 // In interpreter may happen via rescheduled Basic
653 if ( pDoc->IsInInterpreter() )
654 rSet.Put( SfxStringItem( nWhich,
655 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("...")) ) );
656 else
657 {
658 sal_uInt16 nErrCode = 0;
659 ScBaseCell* pCell;
660 pDoc->GetCell( nPosX, nPosY, nTab, pCell );
661 if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
662 {
663 ScFormulaCell* pFCell = (ScFormulaCell*) pCell;
664 if (!pFCell->IsRunning())
665 nErrCode = pFCell->GetErrCode();
666 }
667
668 String aFuncStr;
669 if ( pTabViewShell->GetFunction( aFuncStr, nErrCode ) )
670 rSet.Put( SfxStringItem( nWhich, aFuncStr ) );
671 }
672 }
673 break;
674
675 case SID_DATA_SELECT:
676 // HasSelectionData includes column content and validity,
677 // page fields have to be checked separately.
678 if ( !pDoc->HasSelectionData( nPosX, nPosY, nTab ) &&
679 !pTabViewShell->HasPageFieldDataAtCursor() )
680 rSet.DisableItem( nWhich );
681 break;
682
683 case SID_STATUS_SUM:
684 {
685 String aFuncStr;
686 if ( pTabViewShell->GetFunction( aFuncStr ) )
687 rSet.Put( SfxStringItem( nWhich, aFuncStr ) );
688 }
689 break;
690
691 case FID_MERGE_ON:
692 if ( pDoc->GetChangeTrack() || !pTabViewShell->TestMergeCells() )
693 rSet.DisableItem( nWhich );
694 break;
695
696 case FID_MERGE_OFF:
697 if ( pDoc->GetChangeTrack() || !pTabViewShell->TestRemoveMerge() )
698 rSet.DisableItem( nWhich );
699 break;
700
701 case FID_MERGE_TOGGLE:
702 if ( pDoc->GetChangeTrack() )
703 rSet.DisableItem( nWhich );
704 else
705 {
706 bool bCanMerge = pTabViewShell->TestMergeCells();
707 bool bCanSplit = pTabViewShell->TestRemoveMerge();
708 if( !bCanMerge && !bCanSplit )
709 rSet.DisableItem( nWhich );
710 else
711 rSet.Put( SfxBoolItem( nWhich, bCanSplit ) );
712 }
713 break;
714
715 case FID_INS_ROWBRK:
716 if ( nPosY==0 || (pDoc->HasRowBreak(nPosY, nTab) & BREAK_MANUAL) )
717 rSet.DisableItem( nWhich );
718 break;
719
720 case FID_INS_COLBRK:
721 if ( nPosX==0 || (pDoc->HasColBreak(nPosX, nTab) & BREAK_MANUAL) )
722 rSet.DisableItem( nWhich );
723 break;
724
725 case FID_DEL_ROWBRK:
726 if ( nPosY==0 || (pDoc->HasRowBreak(nPosY, nTab) & BREAK_MANUAL) == 0 )
727 rSet.DisableItem( nWhich );
728 break;
729
730 case FID_DEL_COLBRK:
731 if ( nPosX==0 || (pDoc->HasColBreak(nPosX, nTab) & BREAK_MANUAL) == 0 )
732 rSet.DisableItem( nWhich );
733 break;
734
735 case FID_FILL_TAB:
736 if ( nTabSelCount < 2 )
737 rSet.DisableItem( nWhich );
738 break;
739
740 case SID_SELECT_SCENARIO:
741 {
742 // ScDocument* pDoc = GetViewData()->GetDocument();
743 // SCTAB nTab = GetViewData()->GetTabNo();
744 List aList;
745
746 Color aDummyCol;
747
748 if ( !pDoc->IsScenario(nTab) )
749 {
750 String aStr;
751 sal_uInt16 nFlags;
752 SCTAB nScTab = nTab + 1;
753 String aProtect;
754 bool bSheetProtected = pDoc->IsTabProtected(nTab);
755
756 while ( pDoc->IsScenario(nScTab) )
757 {
758 pDoc->GetName( nScTab, aStr );
759 aList.Insert( new String( aStr ), LIST_APPEND );
760 pDoc->GetScenarioData( nScTab, aStr, aDummyCol, nFlags );
761 aList.Insert( new String( aStr ), LIST_APPEND );
762 // Protection is sal_True if both Sheet and Scenario are protected
763 aProtect = (bSheetProtected && (nFlags & SC_SCENARIO_PROTECT)) ? '1' : '0';
764 aList.Insert( new String( aProtect), LIST_APPEND );
765 ++nScTab;
766 }
767 }
768 else
769 {
770 String aComment;
771 sal_uInt16 nDummyFlags;
772 pDoc->GetScenarioData( nTab, aComment, aDummyCol, nDummyFlags );
773 DBG_ASSERT( aList.Count() == 0, "List not empty!" );
774 aList.Insert( new String( aComment ) );
775 }
776
777 rSet.Put( SfxStringListItem( nWhich, &aList ) );
778
779 sal_uLong nCount = aList.Count();
780 for ( sal_uLong i=0; i<nCount; i++ )
781 delete (String*) aList.GetObject(i);
782 }
783 break;
784
785 case FID_ROW_HIDE:
786 case FID_ROW_SHOW:
787 case FID_COL_HIDE:
788 case FID_COL_SHOW:
789 case FID_COL_OPT_WIDTH:
790 case FID_ROW_OPT_HEIGHT:
791 case FID_DELETE_CELL:
792 if ( pDoc->IsTabProtected(nTab) || pDocSh->IsReadOnly())
793 rSet.DisableItem( nWhich );
794 break;
795
796 /* Zellschutz bei selektierten Zellen wird bei anderen Funktionen auch nicht abgefragt...
797 case SID_DELETE:
798 {
799 if ( pDoc->IsTabProtected(nTab) )
800 {
801 const SfxItemSet& rAttrSet = GetSelectionPattern()->GetItemSet();
802 const ScProtectionAttr& rProtAttr = (const ScProtectionAttr&)rAttrSet.Get( ATTR_PROTECTION, sal_True );
803 if ( rProtAttr.GetProtection() )
804 rSet.DisableItem( nWhich );
805 }
806 }
807 break;
808 */
809 case SID_OUTLINE_MAKE:
810 {
811 if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
812 GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) )
813 {
814 //! test for data pilot operation
815 }
816 else if (pDoc->GetChangeTrack()!=NULL || GetViewData()->IsMultiMarked())
817 {
818 rSet.DisableItem( nWhich );
819 }
820 }
821 break;
822 case SID_OUTLINE_SHOW:
823 if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
824 GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) )
825 {
826 //! test for data pilot operation
827 }
828 else if (!pTabViewShell->OutlinePossible(sal_False))
829 rSet.DisableItem( nWhich );
830 break;
831
832 case SID_OUTLINE_HIDE:
833 if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
834 GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) )
835 {
836 //! test for data pilot operation
837 }
838 else if (!pTabViewShell->OutlinePossible(sal_True))
839 rSet.DisableItem( nWhich );
840 break;
841
842 case SID_OUTLINE_REMOVE:
843 {
844 if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
845 GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) )
846 {
847 //! test for data pilot operation
848 }
849 else
850 {
851 sal_Bool bCol, bRow;
852 pTabViewShell->TestRemoveOutline( bCol, bRow );
853 if ( !bCol && !bRow )
854 rSet.DisableItem( nWhich );
855 }
856 }
857 break;
858
859 case FID_COL_WIDTH:
860 {
861 //GetViewData()->GetCurX();
862 SfxUInt16Item aWidthItem( FID_COL_WIDTH, pDoc->GetColWidth( nPosX , nTab) );
863 rSet.Put( aWidthItem );
864 if ( pDocSh->IsReadOnly())
865 rSet.DisableItem( nWhich );
866
867 //XXX Disablen wenn nicht eindeutig
868 }
869 break;
870
871 case FID_ROW_HEIGHT:
872 {
873 //GetViewData()->GetCurY();
874 SfxUInt16Item aHeightItem( FID_ROW_HEIGHT, pDoc->GetRowHeight( nPosY , nTab) );
875 rSet.Put( aHeightItem );
876 //XXX Disablen wenn nicht eindeutig
877 if ( pDocSh->IsReadOnly())
878 rSet.DisableItem( nWhich );
879 }
880 break;
881
882 case SID_DETECTIVE_FILLMODE:
883 rSet.Put(SfxBoolItem( nWhich, pTabViewShell->IsAuditShell() ));
884 break;
885
886 case FID_INPUTLINE_STATUS:
887 DBG_ERROR( "Old update method. Use ScTabViewShell::UpdateInputHandler()." );
888 break;
889
890 case SID_SCENARIOS: // Szenarios:
891 if (!(rMark.IsMarked() || rMark.IsMultiMarked())) // nur, wenn etwas selektiert
892 rSet.DisableItem( nWhich );
893 break;
894
895 case FID_NOTE_VISIBLE:
896 {
897 const ScPostIt* pNote = pDoc->GetNote( ScAddress( nPosX, nPosY, nTab ) );
898 if ( pNote && pDoc->IsBlockEditable( nTab, nPosX,nPosY, nPosX,nPosY ) )
899 rSet.Put( SfxBoolItem( nWhich, pNote->IsCaptionShown() ) );
900 else
901 rSet.DisableItem( nWhich );
902 }
903 break;
904
905 case SID_DELETE_NOTE:
906 {
907 sal_Bool bEnable = sal_False;
908 if ( rMark.IsMarked() || rMark.IsMultiMarked() )
909 {
910 if ( pDoc->IsSelectionEditable( rMark ) )
911 {
912 // look for at least one note in selection
913 ScRangeList aRanges;
914 rMark.FillRangeListWithMarks( &aRanges, sal_False );
915 sal_uLong nCount = aRanges.Count();
916 for (sal_uLong nPos=0; nPos<nCount && !bEnable; nPos++)
917 {
918 ScCellIterator aCellIter( pDoc, *aRanges.GetObject(nPos) );
919 for( ScBaseCell* pCell = aCellIter.GetFirst(); pCell && !bEnable; pCell = aCellIter.GetNext() )
920 if ( pCell->HasNote() )
921 bEnable = sal_True; // note found
922 }
923 }
924 }
925 else
926 {
927 bEnable = pDoc->IsBlockEditable( nTab, nPosX,nPosY, nPosX,nPosY ) &&
928 pDoc->GetNote( ScAddress( nPosX, nPosY, nTab ) );
929 }
930 if ( !bEnable )
931 rSet.DisableItem( nWhich );
932 }
933 break;
934
935 case SID_OPENDLG_CONSOLIDATE:
936 case SCITEM_CONSOLIDATEDATA:
937 {
938 if(pDoc->GetChangeTrack()!=NULL)
939 rSet.DisableItem( nWhich);
940 }
941 break;
942
943 case SID_CHINESE_CONVERSION:
944 case SID_HANGUL_HANJA_CONVERSION:
945 ScViewUtil::HideDisabledSlot( rSet, pData->GetBindings(), nWhich );
946 break;
947
948 case FID_USE_NAME:
949 {
950 if ( pDocSh && pDocSh->IsDocShared() )
951 rSet.DisableItem( nWhich );
952 else
953 {
954 ScRange aRange;
955 if ( pData->GetSimpleArea( aRange ) != SC_MARK_SIMPLE )
956 rSet.DisableItem( nWhich );
957 }
958 }
959 break;
960
961 case FID_DEFINE_NAME:
962 case FID_INSERT_NAME:
963 case SID_DEFINE_COLROWNAMERANGES:
964 {
965 if ( pDocSh && pDocSh->IsDocShared() )
966 {
967 rSet.DisableItem( nWhich );
968 }
969 }
970 break;
971
972 case SID_SPELL_DIALOG:
973 {
974 if ( pDoc && pData && pDoc->IsTabProtected( pData->GetTabNo() ) )
975 {
976 bool bVisible = false;
977 SfxViewFrame* pViewFrame = ( pTabViewShell ? pTabViewShell->GetViewFrame() : NULL );
978 if ( pViewFrame && pViewFrame->HasChildWindow( nWhich ) )
979 {
980 SfxChildWindow* pChild = pViewFrame->GetChildWindow( nWhich );
981 Window* pWin = ( pChild ? pChild->GetWindow() : NULL );
982 if ( pWin && pWin->IsVisible() )
983 {
984 bVisible = true;
985 }
986 }
987 if ( !bVisible )
988 {
989 rSet.DisableItem( nWhich );
990 }
991 }
992 }
993 break;
994
995 } // switch ( nWitch )
996 nWhich = aIter.NextWhich();
997 } // while ( nWitch )
998 }
999
1000 //------------------------------------------------------------------
1001
1002
1003
1004