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 <assert.h>
21 : #include <stdlib.h>
22 :
23 : #include <sal/log.hxx>
24 :
25 : #include <tools/rcid.h>
26 : #include <tools/stream.hxx>
27 : #include "tools/resmgr.hxx"
28 :
29 : #include <sfx2/module.hxx>
30 : #include <sfx2/objface.hxx>
31 : #include <sfx2/msg.hxx>
32 : #include <sfx2/app.hxx>
33 : #include <sfx2/msgpool.hxx>
34 : #include <sfx2/sfxresid.hxx>
35 : #include <sfx2/objsh.hxx>
36 : #include <rtl/strbuf.hxx>
37 :
38 : extern "C" {
39 :
40 : static int SAL_CALL
41 0 : SfxCompareSlots_qsort( const void* pSmaller, const void* pBigger )
42 : {
43 0 : return ( (int) static_cast<SfxSlot const *>(pSmaller)->GetSlotId() ) -
44 0 : ( (int) static_cast<SfxSlot const *>(pBigger)->GetSlotId() );
45 : }
46 :
47 : static int SAL_CALL
48 66538676 : SfxCompareSlots_bsearch( const void* pSmaller, const void* pBigger )
49 : {
50 133077352 : return ( (int) *static_cast<sal_uInt16 const *>(pSmaller) ) -
51 133077352 : ( (int) static_cast<SfxSlot const *>(pBigger)->GetSlotId() );
52 : }
53 :
54 : }
55 :
56 : struct SfxObjectUI_Impl
57 : {
58 : sal_uInt16 nPos;
59 : sal_uInt32 nResId;
60 : bool bVisible;
61 : bool bContext;
62 : sal_uInt32 nFeature;
63 :
64 11207 : SfxObjectUI_Impl(sal_uInt16 n, sal_uInt32 nId, bool bVis, sal_uInt32 nFeat) :
65 : nPos(n),
66 : nResId(nId),
67 : bVisible(bVis),
68 : bContext(false),
69 11207 : nFeature(nFeat)
70 : {
71 11207 : }
72 : };
73 :
74 : typedef std::vector<SfxObjectUI_Impl*> SfxObjectUIArr_Impl;
75 :
76 : struct SfxInterface_Impl
77 : {
78 : SfxObjectUIArr_Impl aObjectBars; // registered ObjectBars
79 : SfxObjectUIArr_Impl aChildWindows; // registered ChildWindows
80 : ResId aPopupRes; // registered PopupMenu
81 : ResId aStatBarRes; // registered StatusBar
82 : SfxModule* pModule;
83 : bool bRegistered;
84 :
85 4448 : SfxInterface_Impl() :
86 4448 : aPopupRes(nullptr, *SfxApplication::GetSfxResManager()),
87 4448 : aStatBarRes(nullptr, *SfxApplication::GetSfxResManager())
88 : , pModule(NULL)
89 13344 : , bRegistered(false)
90 : {
91 4448 : }
92 :
93 1968 : ~SfxInterface_Impl()
94 1968 : {
95 3450 : for (SfxObjectUIArr_Impl::const_iterator it = aObjectBars.begin(); it != aObjectBars.end(); ++it)
96 1482 : delete *it;
97 :
98 5396 : for (SfxObjectUIArr_Impl::const_iterator it = aChildWindows.begin(); it != aChildWindows.end(); ++it)
99 3428 : delete *it;
100 1968 : }
101 : };
102 :
103 : static SfxObjectUI_Impl* CreateObjectBarUI_Impl(sal_uInt16 nPos, sal_uInt32 nResId, sal_uInt32 nFeature);
104 :
105 : // constuctor, registeres a new unit
106 4448 : SfxInterface::SfxInterface( const char *pClassName,
107 : bool bUsableSuperClass,
108 : SfxInterfaceId nId,
109 : const SfxInterface* pParent,
110 : SfxSlot &rSlotMap, sal_uInt16 nSlotCount ):
111 : pName(pClassName),
112 : pGenoType(pParent),
113 : nClassId(nId),
114 : bSuperClass(bUsableSuperClass),
115 4448 : pImpData(0)
116 : {
117 4448 : pImpData = new SfxInterface_Impl;
118 4448 : SetSlotMap( rSlotMap, nSlotCount );
119 4448 : }
120 :
121 4431 : void SfxInterface::Register( SfxModule* pMod )
122 : {
123 4431 : pImpData->bRegistered = true;
124 4431 : pImpData->pModule = pMod;
125 4431 : if ( pMod )
126 3049 : pMod->GetSlotPool()->RegisterInterface(*this);
127 : else
128 1382 : SfxGetpApp()->GetAppSlotPool_Impl().RegisterInterface(*this);
129 4431 : }
130 :
131 4448 : void SfxInterface::SetSlotMap( SfxSlot& rSlotMap, sal_uInt16 nSlotCount )
132 : {
133 4448 : pSlots = &rSlotMap;
134 4448 : nCount = nSlotCount;
135 4448 : SfxSlot* pIter = pSlots;
136 4448 : if ( 1 == nCount && !pIter->pNextSlot )
137 727 : pIter->pNextSlot = pIter;
138 :
139 4448 : if ( !pIter->pNextSlot )
140 : {
141 : // sort the SfxSlots by id
142 0 : qsort( pSlots, nCount, sizeof(SfxSlot), SfxCompareSlots_qsort );
143 :
144 : // link masters and slaves
145 0 : sal_uInt16 nIter = 1;
146 0 : for ( pIter = pSlots; nIter <= nCount; ++pIter, ++nIter )
147 : {
148 :
149 : assert( nIter == nCount ||
150 : pIter->GetSlotId() != (pIter+1)->GetSlotId() );
151 :
152 : // every master refers to his first slave (ENUM),
153 : // all slaves refer to their master.
154 : // Slaves refer in a circle to the other slaves with the same master
155 0 : if ( pIter->GetKind() == SFX_KIND_ENUM )
156 : {
157 0 : pIter->pLinkedSlot = GetSlot( pIter->nMasterSlotId );
158 : assert( pIter->pLinkedSlot );
159 0 : if ( !pIter->pLinkedSlot->pLinkedSlot )
160 0 : const_cast<SfxSlot*>(pIter->pLinkedSlot)->pLinkedSlot = pIter;
161 :
162 0 : if ( 0 == pIter->GetNextSlot() )
163 : {
164 0 : SfxSlot *pLastSlot = pIter;
165 0 : for ( sal_uInt16 n = nIter; n < Count(); ++n )
166 : {
167 0 : SfxSlot *pCurSlot = (pSlots+n);
168 0 : if ( pCurSlot->nMasterSlotId == pIter->nMasterSlotId )
169 : {
170 0 : pLastSlot->pNextSlot = pCurSlot;
171 0 : pLastSlot = pCurSlot;
172 : }
173 : }
174 0 : pLastSlot->pNextSlot = pIter;
175 : }
176 : }
177 0 : else if ( 0 == pIter->GetNextSlot() )
178 : {
179 : // Slots referring in circle to the next with the same
180 : // Status method.
181 0 : SfxSlot *pLastSlot = pIter;
182 0 : for ( sal_uInt16 n = nIter; n < Count(); ++n )
183 : {
184 0 : SfxSlot *pCurSlot = (pSlots+n);
185 0 : if ( pCurSlot->GetStateFnc() == pIter->GetStateFnc() )
186 : {
187 0 : pLastSlot->pNextSlot = pCurSlot;
188 0 : pLastSlot = pCurSlot;
189 : }
190 : }
191 0 : pLastSlot->pNextSlot = pIter;
192 : }
193 : }
194 : }
195 : #ifdef DBG_UTIL
196 : else
197 : {
198 : sal_uInt16 nIter = 1;
199 : for ( SfxSlot *pNext = pIter+1; nIter < nCount; ++pNext, ++nIter )
200 : {
201 :
202 : if ( pNext->GetSlotId() <= pIter->GetSlotId() )
203 : SAL_WARN( "sfx.control", "Wrong order" );
204 :
205 : if ( pIter->GetKind() == SFX_KIND_ENUM )
206 : {
207 : const SfxSlot *pMasterSlot = GetSlot(pIter->nMasterSlotId);
208 : const SfxSlot *pFirstSlave = pMasterSlot->pLinkedSlot;
209 : const SfxSlot *pSlave = pFirstSlave;
210 : do
211 : {
212 : if ( pSlave->pLinkedSlot != pMasterSlot )
213 : {
214 : OStringBuffer aStr("Wrong Master/Slave- link: ");
215 : aStr.append(static_cast<sal_Int32>(
216 : pMasterSlot->GetSlotId()));
217 : aStr.append(" , ");
218 : aStr.append(static_cast<sal_Int32>(
219 : pSlave->GetSlotId()));
220 : SAL_WARN("sfx.control", aStr.getStr());
221 : }
222 :
223 : if ( pSlave->nMasterSlotId != pMasterSlot->GetSlotId() )
224 : {
225 : OStringBuffer aStr("Wrong Master/Slave-Ids: ");
226 : aStr.append(static_cast<sal_Int32>(
227 : pMasterSlot->GetSlotId()));
228 : aStr.append(" , ");
229 : aStr.append(static_cast<sal_Int32>(
230 : pSlave->GetSlotId()));
231 : SAL_WARN("sfx.control", aStr.getStr());
232 : }
233 :
234 : pSlave = pSlave->pNextSlot;
235 : }
236 : while ( pSlave != pFirstSlave );
237 : }
238 : else
239 : {
240 : if ( pIter->pLinkedSlot )
241 : {
242 : if ( pIter->pLinkedSlot->GetKind() != SFX_KIND_ENUM )
243 : {
244 : OStringBuffer aStr("Slave is no enum: ");
245 : aStr.append(static_cast<sal_Int32>(pIter->GetSlotId()));
246 : aStr.append(" , ");
247 : aStr.append(static_cast<sal_Int32>(
248 : pIter->pLinkedSlot->GetSlotId()));
249 : SAL_WARN("sfx.control", aStr.getStr());
250 : }
251 : }
252 :
253 : const SfxSlot *pCurSlot = pIter;
254 : do
255 : {
256 : pCurSlot = pCurSlot->pNextSlot;
257 : if ( pCurSlot->GetStateFnc() != pIter->GetStateFnc() )
258 : {
259 : OStringBuffer aStr("Linked Slots with different State Methods : ");
260 : aStr.append(static_cast<sal_Int32>(
261 : pCurSlot->GetSlotId()));
262 : aStr.append(" , ");
263 : aStr.append(static_cast<sal_Int32>(pIter->GetSlotId()));
264 : SAL_WARN("sfx.control", aStr.getStr());
265 : }
266 : }
267 : while ( pCurSlot != pIter );
268 : }
269 :
270 : pIter = pNext;
271 : }
272 : }
273 : #endif
274 4448 : }
275 :
276 :
277 :
278 3936 : SfxInterface::~SfxInterface()
279 : {
280 1968 : SfxModule *pMod = pImpData->pModule;
281 1968 : bool bRegistered = pImpData->bRegistered;
282 1968 : delete pImpData;
283 : assert( bRegistered );
284 1968 : if ( bRegistered )
285 : {
286 1968 : if ( pMod )
287 1238 : pMod->GetSlotPool()->ReleaseInterface(*this);
288 : else
289 730 : SfxGetpApp()->GetAppSlotPool_Impl().ReleaseInterface(*this);
290 : }
291 3936 : }
292 :
293 :
294 :
295 : // searches for the specified func
296 :
297 13606054 : const SfxSlot* SfxInterface::GetSlot( sal_uInt16 nFuncId ) const
298 : {
299 :
300 : assert( pSlots );
301 : assert( nCount );
302 :
303 : // find the id using binary search
304 : void* p = bsearch( &nFuncId, pSlots, nCount, sizeof(SfxSlot),
305 13606054 : SfxCompareSlots_bsearch );
306 13606054 : if ( !p && pGenoType )
307 6857289 : return pGenoType->GetSlot( nFuncId );
308 :
309 6748765 : return p ? static_cast<const SfxSlot*>(p) : 0;
310 : }
311 :
312 6290303 : const SfxSlot* SfxInterface::GetSlot( const OUString& rCommand ) const
313 : {
314 : static const char UNO_COMMAND[] = ".uno:";
315 :
316 6290303 : OUString aCommand( rCommand );
317 6290303 : if ( aCommand.startsWith( UNO_COMMAND ) )
318 4253 : aCommand = aCommand.copy( sizeof( UNO_COMMAND )-1 );
319 :
320 287768014 : for ( sal_uInt16 n=0; n<nCount; n++ )
321 : {
322 563606692 : if ( (pSlots+n)->pUnoName &&
323 281794577 : aCommand.compareToIgnoreAsciiCaseAscii( (pSlots+n)->GetUnoName() ) == 0 )
324 334404 : return pSlots+n;
325 : }
326 :
327 5955899 : return pGenoType ? pGenoType->GetSlot( aCommand ) : NULL;
328 : }
329 :
330 :
331 :
332 1740 : const SfxSlot* SfxInterface::GetRealSlot( const SfxSlot *pSlot ) const
333 : {
334 :
335 : assert( pSlots );
336 : assert( nCount );
337 :
338 1740 : if ( !ContainsSlot_Impl(pSlot) )
339 : {
340 0 : if(pGenoType)
341 0 : return pGenoType->GetRealSlot(pSlot);
342 : SAL_WARN( "sfx.control", "unknown Slot" );
343 0 : return 0;
344 : }
345 :
346 1740 : return pSlot->pLinkedSlot;
347 : }
348 :
349 :
350 :
351 0 : const SfxSlot* SfxInterface::GetRealSlot( sal_uInt16 nSlotId ) const
352 : {
353 :
354 : assert( pSlots );
355 : assert( nCount );
356 :
357 0 : const SfxSlot *pSlot = GetSlot(nSlotId);
358 0 : if ( !pSlot )
359 : {
360 0 : if(pGenoType)
361 0 : return pGenoType->GetRealSlot(nSlotId);
362 : SAL_WARN( "sfx.control", "unknown Slot" );
363 0 : return 0;
364 : }
365 :
366 0 : return pSlot->pLinkedSlot;
367 : }
368 :
369 1888 : void SfxInterface::RegisterPopupMenu( const ResId& rResId )
370 : {
371 :
372 1888 : pImpData->aPopupRes = rResId;
373 1888 : }
374 :
375 2824 : void SfxInterface::RegisterObjectBar(sal_uInt16 nPos, sal_uInt32 nResId)
376 : {
377 2824 : RegisterObjectBar(nPos, nResId, 0UL);
378 2824 : }
379 :
380 3508 : void SfxInterface::RegisterObjectBar(sal_uInt16 nPos, sal_uInt32 nResId, sal_uInt32 nFeature)
381 : {
382 3508 : SfxObjectUI_Impl* pUI = CreateObjectBarUI_Impl(nPos, nResId, nFeature);
383 3508 : if ( pUI )
384 3508 : pImpData->aObjectBars.push_back(pUI);
385 3508 : }
386 :
387 3508 : SfxObjectUI_Impl* CreateObjectBarUI_Impl(sal_uInt16 nPos, sal_uInt32 nResId, sal_uInt32 nFeature)
388 : {
389 3508 : if ((nPos & SFX_VISIBILITY_MASK) == 0)
390 1401 : nPos |= SFX_VISIBILITY_STANDARD;
391 :
392 3508 : return new SfxObjectUI_Impl(nPos, nResId, true, nFeature);
393 : }
394 :
395 37467 : sal_uInt32 SfxInterface::GetObjectBarId(sal_uInt16 nNo) const
396 : {
397 37467 : bool bGenoType = (pGenoType != 0 && pGenoType->UseAsSuperClass());
398 37467 : if ( bGenoType )
399 : {
400 : // Are there toolbars in the super class?
401 10244 : sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount();
402 10244 : if ( nNo < nBaseCount )
403 : // The Super class comes first
404 0 : return pGenoType->GetObjectBarId(nNo);
405 : else
406 10244 : nNo = nNo - nBaseCount;
407 : }
408 :
409 : assert( nNo<pImpData->aObjectBars.size() );
410 :
411 37467 : return pImpData->aObjectBars[nNo]->nResId;
412 : }
413 :
414 56834 : sal_uInt16 SfxInterface::GetObjectBarPos( sal_uInt16 nNo ) const
415 : {
416 56834 : bool bGenoType = (pGenoType != 0 && pGenoType->UseAsSuperClass());
417 56834 : if ( bGenoType )
418 : {
419 : // Are there toolbars in the super class?
420 16104 : sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount();
421 16104 : if ( nNo < nBaseCount )
422 : // The Super class comes first
423 0 : return pGenoType->GetObjectBarPos( nNo );
424 : else
425 16104 : nNo = nNo - nBaseCount;
426 : }
427 :
428 : assert( nNo<pImpData->aObjectBars.size() );
429 :
430 56834 : return pImpData->aObjectBars[nNo]->nPos;
431 : }
432 :
433 199549 : sal_uInt16 SfxInterface::GetObjectBarCount() const
434 : {
435 199549 : if (pGenoType && pGenoType->UseAsSuperClass())
436 43021 : return pImpData->aObjectBars.size() + pGenoType->GetObjectBarCount();
437 : else
438 156528 : return pImpData->aObjectBars.size();
439 : }
440 :
441 7011 : void SfxInterface::RegisterChildWindow(sal_uInt16 nId, bool bContext)
442 : {
443 7011 : RegisterChildWindow(nId, bContext, 0UL);
444 7011 : }
445 :
446 7699 : void SfxInterface::RegisterChildWindow(sal_uInt16 nId, bool bContext, sal_uInt32 nFeature)
447 : {
448 7699 : SfxObjectUI_Impl* pUI = new SfxObjectUI_Impl(0, nId, true, nFeature);
449 7699 : pUI->bContext = bContext;
450 7699 : pImpData->aChildWindows.push_back(pUI);
451 7699 : }
452 :
453 354 : void SfxInterface::RegisterStatusBar(const ResId& rResId)
454 : {
455 354 : pImpData->aStatBarRes = rResId;
456 354 : }
457 :
458 254835 : sal_uInt32 SfxInterface::GetChildWindowId (sal_uInt16 nNo) const
459 : {
460 254835 : if ( pGenoType )
461 : {
462 : // Are there ChildWindows in der Superklasse?
463 132775 : sal_uInt16 nBaseCount = pGenoType->GetChildWindowCount();
464 132775 : if ( nNo < nBaseCount )
465 : // The Super class comes first
466 13968 : return pGenoType->GetChildWindowId( nNo );
467 : else
468 118807 : nNo = nNo - nBaseCount;
469 : }
470 :
471 : assert( nNo<pImpData->aChildWindows.size() );
472 :
473 240867 : sal_uInt32 nRet = pImpData->aChildWindows[nNo]->nResId;
474 240867 : if ( pImpData->aChildWindows[nNo]->bContext )
475 6841 : nRet += sal_uInt32( nClassId ) << 16;
476 240867 : return nRet;
477 : }
478 :
479 254715 : sal_uInt32 SfxInterface::GetChildWindowFeature (sal_uInt16 nNo) const
480 : {
481 254715 : if ( pGenoType )
482 : {
483 : // Are there ChildWindows in der Superklasse?
484 132696 : sal_uInt16 nBaseCount = pGenoType->GetChildWindowCount();
485 132696 : if ( nNo < nBaseCount )
486 : // The Super class comes first
487 13948 : return pGenoType->GetChildWindowFeature( nNo );
488 : else
489 118748 : nNo = nNo - nBaseCount;
490 : }
491 :
492 : assert( nNo<pImpData->aChildWindows.size() );
493 :
494 240767 : return pImpData->aChildWindows[nNo]->nFeature;
495 : }
496 :
497 :
498 :
499 :
500 713849 : sal_uInt16 SfxInterface::GetChildWindowCount() const
501 : {
502 713849 : if (pGenoType)
503 160500 : return pImpData->aChildWindows.size() + pGenoType->GetChildWindowCount();
504 : else
505 553349 : return pImpData->aChildWindows.size();
506 : }
507 :
508 0 : const ResId& SfxInterface::GetPopupMenuResId() const
509 : {
510 0 : return pImpData->aPopupRes;
511 : }
512 :
513 68422 : const ResId& SfxInterface::GetStatusBarResId() const
514 : {
515 68422 : if (pImpData->aStatBarRes.GetId() == 0 && pGenoType)
516 21411 : return pGenoType->GetStatusBarResId();
517 : else
518 47011 : return pImpData->aStatBarRes;
519 : }
520 :
521 56798 : sal_uInt32 SfxInterface::GetObjectBarFeature ( sal_uInt16 nNo ) const
522 : {
523 56798 : bool bGenoType = (pGenoType != 0 && pGenoType->UseAsSuperClass());
524 56798 : if ( bGenoType )
525 : {
526 : // Are there toolbars in the super class?
527 16091 : sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount();
528 16091 : if ( nNo < nBaseCount )
529 : // The Super class comes first
530 0 : return pGenoType->GetObjectBarFeature( nNo );
531 : else
532 16091 : nNo = nNo - nBaseCount;
533 : }
534 :
535 : assert( nNo<pImpData->aObjectBars.size() );
536 :
537 56798 : return pImpData->aObjectBars[nNo]->nFeature;
538 : }
539 :
540 37467 : bool SfxInterface::IsObjectBarVisible(sal_uInt16 nNo) const
541 : {
542 37467 : bool bGenoType = (pGenoType != 0 && pGenoType->UseAsSuperClass());
543 37467 : if ( bGenoType )
544 : {
545 : // Are there toolbars in the super class?
546 10244 : sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount();
547 10244 : if ( nNo < nBaseCount )
548 : // The Super class comes first
549 0 : return pGenoType->IsObjectBarVisible( nNo );
550 : else
551 10244 : nNo = nNo - nBaseCount;
552 : }
553 :
554 : assert( nNo<pImpData->aObjectBars.size() );
555 :
556 37467 : return pImpData->aObjectBars[nNo]->bVisible;
557 : }
558 :
559 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|