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