Bump version to 24.04.3.4
[LibreOffice.git] / idl / source / objects / slot.cxx
blob58b3faa522b4e177fa252349f55291670ba62214
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <osl/diagnose.h>
21 #include <tools/debug.hxx>
22 #include <slot.hxx>
23 #include <globals.hxx>
24 #include <database.hxx>
27 SvMetaSlot::SvMetaSlot()
28 : aRecordPerSet( true )
29 , aRecordAbsolute( false )
30 , pNextSlot(nullptr)
31 , nListPos(0)
32 , aReadOnlyDoc ( true )
36 SvMetaSlot::SvMetaSlot( SvMetaType * pType )
37 : SvMetaAttribute( pType )
38 , aRecordPerSet( true )
39 , aRecordAbsolute( false )
40 , pNextSlot(nullptr)
41 , nListPos(0)
42 , aReadOnlyDoc ( true )
46 bool SvMetaSlot::GetReadOnlyDoc() const
48 if( aReadOnlyDoc.IsSet() || !GetRef() ) return aReadOnlyDoc;
49 return static_cast<SvMetaSlot *>(GetRef())->GetReadOnlyDoc();
52 bool SvMetaSlot::IsVariable() const
54 SvMetaType * pType = GetType();
55 return pType->GetMetaTypeType() != MetaTypeType::Method;
58 bool SvMetaSlot::IsMethod() const
60 SvMetaType * pType = GetType();
61 return pType->GetMetaTypeType() == MetaTypeType::Method;
64 /*************************************************************************
65 |* reference
67 |* description Second FALSE in the SvBOOL-Objects means
68 |* IsSet() provides FALSE (default initialization).
69 *************************************************************************/
70 /** reference disbandment **/
71 const OString& SvMetaSlot::GetGroupId() const
73 if( !aGroupId.getString().isEmpty() || !GetRef() ) return aGroupId.getString();
74 return static_cast<SvMetaSlot *>(GetRef())->GetGroupId();
76 const OString& SvMetaSlot::GetDisableFlags() const
78 if( !aDisableFlags.isEmpty() || !GetRef() ) return aDisableFlags;
79 return static_cast<SvMetaSlot *>(GetRef())->GetDisableFlags();
81 const OString& SvMetaSlot::GetExecMethod() const
83 if( !aExecMethod.getString().isEmpty() || !GetRef() ) return aExecMethod.getString();
84 return static_cast<SvMetaSlot *>(GetRef())->GetExecMethod();
86 const OString& SvMetaSlot::GetStateMethod() const
88 if( !aStateMethod.getString().isEmpty() || !GetRef() ) return aStateMethod.getString();
89 return static_cast<SvMetaSlot *>(GetRef())->GetStateMethod();
91 bool SvMetaSlot::GetToggle() const
93 if( aToggle.IsSet() || !GetRef() ) return aToggle;
94 return static_cast<SvMetaSlot *>(GetRef())->GetToggle();
96 bool SvMetaSlot::GetAutoUpdate() const
98 if( aAutoUpdate.IsSet() || !GetRef() ) return aAutoUpdate;
99 return static_cast<SvMetaSlot *>(GetRef())->GetAutoUpdate();
101 bool SvMetaSlot::GetAsynchron() const
103 // Synchron and Asynchron are exclusive
104 if( !GetRef() || aAsynchron.IsSet() )
105 return aAsynchron;
106 return static_cast<SvMetaSlot *>(GetRef())->GetAsynchron();
108 bool SvMetaSlot::GetRecordPerItem() const
110 // Record- PerItem, No, PerSet and Manual are exclusive
111 if( !GetRef() || aRecordPerItem.IsSet() || aNoRecord.IsSet()
112 || aRecordPerSet.IsSet() )
113 return aRecordPerItem;
114 return static_cast<SvMetaSlot *>(GetRef())->GetRecordPerItem();
116 bool SvMetaSlot::GetRecordPerSet() const
118 // Record- PerItem, No, PerSet and Manual are exclusive
119 if( !GetRef() || aRecordPerItem.IsSet() || aNoRecord.IsSet()
120 || aRecordPerSet.IsSet() )
121 return aRecordPerSet;
122 return static_cast<SvMetaSlot *>(GetRef())->GetRecordPerSet();
124 bool SvMetaSlot::GetNoRecord() const
126 // Record- PerItem, No, PerSet and Manual are exclusive
127 if( !GetRef() || aRecordPerItem.IsSet() || aNoRecord.IsSet()
128 || aRecordPerSet.IsSet() )
129 return aNoRecord;
130 return static_cast<SvMetaSlot *>(GetRef())->GetNoRecord();
132 bool SvMetaSlot::GetRecordAbsolute() const
134 if( !GetRef() || aRecordAbsolute.IsSet() )
135 return aRecordAbsolute;
136 return static_cast<SvMetaSlot *>(GetRef())->GetRecordAbsolute();
138 bool SvMetaSlot::GetMenuConfig() const
140 if( aMenuConfig.IsSet() || !GetRef() ) return aMenuConfig;
141 return static_cast<SvMetaSlot *>(GetRef())->GetMenuConfig();
143 bool SvMetaSlot::GetToolBoxConfig() const
145 if( aToolBoxConfig.IsSet() || !GetRef() ) return aToolBoxConfig;
146 return static_cast<SvMetaSlot *>(GetRef())->GetToolBoxConfig();
148 bool SvMetaSlot::GetAccelConfig() const
150 if( aAccelConfig.IsSet() || !GetRef() ) return aAccelConfig;
151 return static_cast<SvMetaSlot *>(GetRef())->GetAccelConfig();
153 bool SvMetaSlot::GetFastCall() const
155 if( aFastCall.IsSet() || !GetRef() ) return aFastCall;
156 return static_cast<SvMetaSlot *>(GetRef())->GetFastCall();
158 bool SvMetaSlot::GetContainer() const
160 if( aContainer.IsSet() || !GetRef() ) return aContainer;
161 return static_cast<SvMetaSlot *>(GetRef())->GetContainer();
164 void SvMetaSlot::ReadAttributesSvIdl( SvIdlDataBase & rBase,
165 SvTokenStream & rInStm )
167 SvMetaAttribute::ReadAttributesSvIdl( rBase, rInStm );
169 aGroupId.ReadSvIdl( SvHash_GroupId(), rInStm );
170 aExecMethod.ReadSvIdl( SvHash_ExecMethod(), rInStm );
171 aStateMethod.ReadSvIdl( SvHash_StateMethod(), rInStm );
172 ReadStringSvIdl( SvHash_DisableFlags(), rInStm, aDisableFlags );
173 aReadOnlyDoc.ReadSvIdl( SvHash_ReadOnlyDoc(), rInStm );
174 aToggle.ReadSvIdl( SvHash_Toggle(), rInStm );
175 aAutoUpdate.ReadSvIdl( SvHash_AutoUpdate(), rInStm );
176 aAsynchron.ReadSvIdl( SvHash_Asynchron(), rInStm );
177 aRecordAbsolute.ReadSvIdl( SvHash_RecordAbsolute(), rInStm );
179 if( aRecordPerItem.ReadSvIdl( SvHash_RecordPerItem(), rInStm ) )
181 SetRecordPerItem( aRecordPerItem );
183 if( aRecordPerSet.ReadSvIdl( SvHash_RecordPerSet(), rInStm ) )
185 SetRecordPerSet( aRecordPerSet );
187 if( aNoRecord.ReadSvIdl( SvHash_NoRecord(), rInStm ) )
189 SetNoRecord( aNoRecord );
192 aMenuConfig.ReadSvIdl( SvHash_MenuConfig(), rInStm );
193 aToolBoxConfig.ReadSvIdl( SvHash_ToolBoxConfig(), rInStm );
194 aAccelConfig.ReadSvIdl( SvHash_AccelConfig(), rInStm );
196 aFastCall.ReadSvIdl( SvHash_FastCall(), rInStm );
197 aContainer.ReadSvIdl( SvHash_Container(), rInStm );
200 bool SvMetaSlot::Test( SvTokenStream & rInStm )
202 bool bOk = SvMetaAttribute::Test( rInStm );
203 if( bOk )
205 SvMetaType * pType = GetType();
206 if( pType->GetMetaTypeType() == MetaTypeType::Method )
207 pType = pType->GetReturnType();
208 if( !pType->IsItem() )
210 throw SvParseException( rInStm, "this attribute is not a slot"_ostr );
214 return bOk;
217 bool SvMetaSlot::ReadSvIdl( SvIdlDataBase & rBase, SvTokenStream & rInStm )
219 sal_uInt32 nTokPos = rInStm.Tell();
220 bool bOk = true;
222 SvMetaAttribute * pAttr = rBase.ReadKnownAttr( rInStm, GetType() );
223 if( pAttr )
225 // c
226 SvMetaSlot * pKnownSlot = dynamic_cast<SvMetaSlot*>( pAttr );
227 if( !pKnownSlot )
228 throw SvParseException( rInStm, "attribute " + pAttr->GetName() + " is method or variable but not a slot" );
229 SetRef( pKnownSlot );
230 SetName( pKnownSlot->GetName() );
231 bOk = SvMetaObject::ReadSvIdl( rBase, rInStm );
233 else
235 bOk = SvMetaAttribute::ReadSvIdl( rBase, rInStm );
237 SvMetaAttribute *pAttr2 = rBase.FindKnownAttr( GetSlotId() );
238 if( pAttr2 )
240 // for testing purposes: reference in case of complete definition
241 SvMetaSlot * pKnownSlot = dynamic_cast<SvMetaSlot*>( pAttr2 );
242 if( !pKnownSlot )
243 throw SvParseException( rInStm, "attribute " + pAttr2->GetName() + " is method or variable but not a slot" );
244 SetRef( pKnownSlot );
246 // names may differ, because explicitly given
247 if ( pKnownSlot->GetName() != GetName() )
249 OSL_FAIL("Illegal definition!");
250 rInStm.Seek( nTokPos );
251 return false;
254 SetName( pKnownSlot->GetName() );
258 if( !bOk )
259 rInStm.Seek( nTokPos );
261 return bOk;
264 void SvMetaSlot::Insert( SvSlotElementList& rList)
266 // get insert position through binary search in slotlist
267 sal_uInt16 nId = static_cast<sal_uInt16>(GetSlotId().GetValue());
268 sal_uInt16 nListCount = static_cast<sal_uInt16>(rList.size());
269 sal_uInt16 nPos;
271 if ( !nListCount )
272 nPos = 0;
273 else if ( nListCount == 1 )
274 nPos = rList[ 0 ]->GetSlotId().GetValue() >= nId ? 0 : 1;
275 else
277 sal_uInt16 nMid = 0, nLow = 0;
278 sal_uInt16 nHigh = nListCount - 1;
279 bool bFound = false;
280 while ( !bFound && nLow <= nHigh )
282 nMid = (nLow + nHigh) >> 1;
283 DBG_ASSERT( nMid < nListCount, "bsearch is buggy" );
284 int nDiff = static_cast<int>(nId) - static_cast<int>(rList[ nMid ]->GetSlotId().GetValue());
285 if ( nDiff < 0)
287 if ( nMid == 0 )
288 break;
289 nHigh = nMid - 1;
291 else if ( nDiff > 0 )
293 nLow = nMid + 1;
294 if ( nLow == 0 )
295 break;
297 else
298 bFound = true;
301 DBG_ASSERT(!bFound, "Duplicate SlotId!");
302 nPos = bFound ? nMid : nLow;
305 DBG_ASSERT( nPos <= nListCount,
306 "nPos too large" );
307 DBG_ASSERT( nPos == nListCount || nId <=
308 static_cast<sal_uInt16>(rList[ nPos ]->GetSlotId().GetValue()),
309 "Successor has lower SlotId" );
310 DBG_ASSERT( nPos == 0 || nId >
311 static_cast<sal_uInt16>(rList[ nPos-1 ]->GetSlotId().GetValue()),
312 "Predecessor has higher SlotId" );
313 DBG_ASSERT( nPos+1 >= nListCount || nId <
314 static_cast<sal_uInt16>(rList[ nPos+1 ]->GetSlotId().GetValue()),
315 "Successor has lower SlotId" );
317 if ( nPos < rList.size() )
319 SvSlotElementList::iterator it = rList.begin();
320 std::advance( it, nPos );
321 rList.insert( it, this );
323 else
325 rList.push_back( this );
330 static OString MakeSlotName( SvStringHashEntry const * pEntry )
332 return "SfxSlotMode::" + pEntry->GetName().toAsciiUpperCase();
335 void SvMetaSlot::WriteSlotStubs( std::string_view rShellName,
336 std::vector<OString> & rList,
337 SvStream & rOutStm ) const
339 OString aMethodName( GetExecMethod() );
340 if ( !aMethodName.isEmpty() &&
341 aMethodName != "NoExec" )
343 bool bIn = false;
344 for( size_t n = 0; n < rList.size(); n++ )
346 if (rList[n] == aMethodName)
348 bIn = true;
349 break;
353 if ( !bIn )
355 rList.push_back( aMethodName );
356 rOutStm.WriteOString( "SFX_EXEC_STUB(" )
357 .WriteOString( rShellName )
358 .WriteChar( ',' )
359 .WriteOString( aMethodName )
360 .WriteChar( ')' ) << endl;
364 aMethodName = GetStateMethod();
365 if (aMethodName.isEmpty() || aMethodName == "NoState")
366 return;
368 bool bIn = false;
369 for ( size_t n=0; n < rList.size(); n++ )
371 if (rList[n] == aMethodName)
373 bIn = true;
374 break;
378 if ( !bIn )
380 rList.push_back( aMethodName );
381 rOutStm.WriteOString( "SFX_STATE_STUB(" )
382 .WriteOString( rShellName )
383 .WriteChar( ',' )
384 .WriteOString( aMethodName )
385 .WriteChar( ')' ) << endl;
389 void SvMetaSlot::WriteSlot( std::string_view rShellName, sal_uInt16 nCount,
390 std::string_view rSlotId,
391 SvSlotElementList& rSlotList,
392 size_t nStart,
393 SvIdlDataBase & rBase, SvStream & rOutStm )
395 rOutStm.WriteOString( "// Slot Nr. " )
396 .WriteOString( OString::number(nListPos) )
397 .WriteOString( " : " );
398 OString aSlotIdValue(OString::number(GetSlotId().GetValue()));
399 rOutStm.WriteOString( aSlotIdValue ) << endl;
400 WriteTab( rOutStm, 1 );
401 rOutStm.WriteOString( "SFX_NEW_SLOT_ARG( " ).WriteOString( rShellName ).WriteChar( ',' ) ;
403 rOutStm.WriteOString( rSlotId ).WriteChar( ',' );
405 // GroupId
406 if( !GetGroupId().isEmpty() )
407 rOutStm.WriteOString( GetGroupId() );
408 else
409 rOutStm.WriteOString( "SfxGroupId::NONE" );
410 rOutStm.WriteChar( ',' ) << endl;
411 WriteTab( rOutStm, 4 );
413 // look for the next slot with the same StateMethod like me
414 // the slotlist is set to the current slot
415 size_t i = nStart;
416 SvMetaSlot* pEle = ( ++i < rSlotList.size() ) ? rSlotList[ i ] : nullptr;
417 pNextSlot = pEle;
418 while ( pNextSlot )
420 if ( !pNextSlot->pNextSlot &&
421 pNextSlot->GetStateMethod() == GetStateMethod()
423 break;
425 pEle = ( ++i < rSlotList.size() ) ? rSlotList[ i ] : nullptr;
426 pNextSlot = pEle;
429 if ( !pNextSlot )
431 // There is no slot behind me that has the same ExecMethod.
432 // So I search for the first slot with it (could be myself).
433 i = 0;
434 pEle = rSlotList.empty() ? nullptr : rSlotList[ i ];
435 pNextSlot = pEle;
436 while (pNextSlot && pNextSlot != this)
438 if ( pNextSlot->GetStateMethod() == GetStateMethod() )
439 break;
440 pEle = ( ++i < rSlotList.size() ) ? rSlotList[ i ] : nullptr;
441 pNextSlot = pEle;
445 assert(pNextSlot);
447 rOutStm.WriteOString( "&a" ).WriteOString( rShellName ).WriteOString( "Slots_Impl[" )
448 .WriteOString( OString::number(pNextSlot->GetListPos()) )
449 .WriteOString( "] /*Offset Next*/, " ) << endl;
451 WriteTab( rOutStm, 4 );
453 // write ExecMethod, with standard name if not specified
454 if( !GetExecMethod().isEmpty() &&
455 GetExecMethod() != "NoExec")
457 rOutStm.WriteOString( "SFX_STUB_PTR(" ).WriteOString( rShellName ).WriteChar( ',' )
458 .WriteOString( GetExecMethod() ).WriteChar( ')' );
460 else
461 rOutStm.WriteOString( "SFX_STUB_PTR_EXEC_NONE" );
462 rOutStm.WriteChar( ',' );
464 // write StateMethod, with standard name if not specified
465 if( !GetStateMethod().isEmpty() &&
466 GetStateMethod() != "NoState")
468 rOutStm.WriteOString( "SFX_STUB_PTR(" ).WriteOString( rShellName ).WriteChar( ',' )
469 .WriteOString( GetStateMethod() ).WriteChar( ')' );
471 else
472 rOutStm.WriteOString( "SFX_STUB_PTR_STATE_NONE" );
474 rOutStm.WriteChar( ',' ) << endl;
475 WriteTab( rOutStm, 4 );
477 // write flags
478 if( GetToggle() )
479 rOutStm.WriteOString( MakeSlotName( SvHash_Toggle() ) ).WriteChar( '|' );
480 if( GetAutoUpdate() )
481 rOutStm.WriteOString( MakeSlotName( SvHash_AutoUpdate() ) ).WriteChar( '|' );
482 if( GetAsynchron() )
483 rOutStm.WriteOString( MakeSlotName( SvHash_Asynchron() ) ).WriteChar( '|' );
484 if( GetRecordPerItem() )
485 rOutStm.WriteOString( MakeSlotName( SvHash_RecordPerItem() ) ).WriteChar( '|' );
486 if( GetRecordPerSet() )
487 rOutStm.WriteOString( MakeSlotName( SvHash_RecordPerSet() ) ).WriteChar( '|' );
488 if( GetNoRecord() )
489 rOutStm.WriteOString( MakeSlotName( SvHash_NoRecord() ) ).WriteChar( '|' );
490 if( GetRecordAbsolute() )
491 rOutStm.WriteOString( MakeSlotName( SvHash_RecordAbsolute() ) ).WriteChar( '|' );
492 if( GetMenuConfig() )
493 rOutStm.WriteOString( MakeSlotName( SvHash_MenuConfig() ) ).WriteChar( '|' );
494 if( GetToolBoxConfig() )
495 rOutStm.WriteOString( MakeSlotName( SvHash_ToolBoxConfig() ) ).WriteChar( '|' );
496 if( GetAccelConfig() )
497 rOutStm.WriteOString( MakeSlotName( SvHash_AccelConfig() ) ).WriteChar( '|' );
498 if( GetFastCall() )
499 rOutStm.WriteOString( MakeSlotName( SvHash_FastCall() ) ).WriteChar( '|' );
500 if( GetContainer() )
501 rOutStm.WriteOString( MakeSlotName( SvHash_Container() ) ).WriteChar( '|' );
502 if ( GetReadOnlyDoc() )
503 rOutStm.WriteOString( MakeSlotName( SvHash_ReadOnlyDoc() ) ).WriteChar( '|' );
504 rOutStm.WriteOString( "SfxSlotMode::NONE" );
506 rOutStm.WriteChar( ',' ) << endl;
507 WriteTab( rOutStm, 4 );
508 if ( GetDisableFlags().isEmpty() )
509 rOutStm.WriteOString( "SfxDisableFlags::NONE" );
510 else
511 rOutStm.WriteOString( GetDisableFlags() );
513 // write attribute type
514 rOutStm.WriteChar( ',' ) << endl;
515 WriteTab( rOutStm, 4 );
517 SvMetaType * pT = GetType();
518 if( !IsVariable() )
520 SvMetaType * pRT = GetType()->GetReturnType();
521 pT = pRT ? pRT : rBase.FindType( "SfxVoidItem" );
524 if( pT )
526 assert(pT->IsItem());
527 rOutStm.WriteOString( pT->GetName() );
528 if( !SvIdlDataBase::FindType( pT, rBase.aUsedTypes ) )
529 rBase.aUsedTypes.push_back( pT );
531 else
532 rOutStm.WriteOString( "SfxVoidItem not defined" );
535 rOutStm.WriteChar( ',' ) << endl;
536 WriteTab( rOutStm, 4 );
537 rOutStm
538 .WriteOString( OString::number(nCount) )
539 .WriteOString( "/*Offset*/, " );
541 if( IsMethod() )
543 SvMetaType * pType = GetType();
544 size_t nSCount = pType->GetAttrCount();
545 rOutStm
546 .WriteOString( OString::number(nSCount) )
547 .WriteOString( "/*Count*/," );
549 else
550 rOutStm.WriteOString( "0," );
552 rOutStm.WriteOString( " " );
554 // Method/Property flags
555 if( IsMethod() )
556 rOutStm.WriteOString( "SfxSlotMode::METHOD|" );
558 rOutStm.WriteOString( "SfxSlotMode::NONE" );
562 rOutStm.WriteOString( ",\"" );
563 rOutStm.WriteOString( GetName() );
564 rOutStm.WriteOString( "\"" );
567 rOutStm.WriteOString( " )," ) << endl;
570 sal_uInt16 SvMetaSlot::WriteSlotParamArray( SvIdlDataBase & rBase, SvStream & rOutStm ) const
572 if( !IsMethod() )
573 return 0;
575 SvMetaType * pType = GetType();
577 if( !SvIdlDataBase::FindType( pType, rBase.aUsedTypes ) )
578 rBase.aUsedTypes.push_back( pType );
580 const SvRefMemberList<SvMetaAttribute *>& rList =
581 pType->GetAttrList();
582 for( size_t n = 0; n < rList.size(); n++ )
584 SvMetaAttribute * pPar = rList[n];
585 SvMetaType * pPType = pPar->GetType();
586 WriteTab( rOutStm, 1 );
587 rOutStm.WriteOString("{ (const SfxType*) &a")
588 // item type
589 .WriteOString(pPType->GetName()).WriteOString("_Impl, ")
590 // parameter name
591 .WriteOString("\"").WriteOString(pPar->GetName()).WriteOString("\", ")
592 // slot id
593 .WriteOString(pPar->GetSlotId().getString()).WriteOString(" },") << endl;
594 if( !SvIdlDataBase::FindType( pPType, rBase.aUsedTypes ) )
595 rBase.aUsedTypes.push_back( pPType );
597 return static_cast<sal_uInt16>(rList.size());
600 sal_uInt16 SvMetaSlot::WriteSlotMap( std::string_view rShellName, sal_uInt16 nCount,
601 SvSlotElementList& rSlotList,
602 size_t nStart,
603 SvIdlDataBase & rBase,
604 SvStream & rOutStm )
606 // SlotId, if not specified generate from name
607 OString slotId = GetSlotId().getString();
609 sal_uInt16 nSCount = 0;
610 if( IsMethod() )
612 SvMetaType * pType = GetType();
613 nSCount = static_cast<sal_uInt16>(pType->GetAttrCount());
616 WriteSlot( rShellName, nCount, slotId, rSlotList, nStart, rBase, rOutStm );
617 return nSCount;
620 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */