Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <tools/debug.hxx>
31 : : #include <tools/rc.h>
32 : :
33 : : #include <vcl/svapp.hxx>
34 : : #include <accel.h>
35 : : #include <vcl/accel.hxx>
36 : : #include <map>
37 : : #include <vector>
38 : :
39 : : // =======================================================================
40 : :
41 : : typedef ::std::map< sal_uLong, ImplAccelEntry* > ImplAccelMap;
42 : : typedef ::std::vector< ImplAccelEntry* > ImplAccelList;
43 : :
44 : : #define ACCELENTRY_NOTFOUND ((sal_uInt16)0xFFFF)
45 : :
46 : : // =======================================================================
47 : :
48 [ + - ]: 3166 : class ImplAccelData
49 : : {
50 : : public:
51 : : ImplAccelMap maKeyMap; // for keycodes, generated with a code
52 : : ImplAccelList maIdList; // Id-List
53 : : };
54 : :
55 : : // =======================================================================
56 : :
57 : : DBG_NAME( Accelerator )
58 : :
59 : : // =======================================================================
60 : :
61 : 2932 : sal_uInt16 ImplAccelEntryGetIndex( ImplAccelList* pList, sal_uInt16 nId,
62 : : sal_uInt16* pIndex = NULL )
63 : : {
64 : : size_t nLow;
65 : : size_t nHigh;
66 : : size_t nMid;
67 : 2932 : size_t nCount = pList->size();
68 : : sal_uInt16 nCompareId;
69 : :
70 : : // check if first key is larger then the key to compare
71 [ - + ][ + + ]: 2932 : if ( !nCount || (nId < (*pList)[ 0 ]->mnId) )
[ + + ]
72 : : {
73 [ + - ]: 1466 : if ( pIndex )
74 : 1466 : *pIndex = 0;
75 : 1466 : return ACCELENTRY_NOTFOUND;
76 : : }
77 : :
78 : : // Binairy search
79 : 1466 : nLow = 0;
80 : 1466 : nHigh = nCount-1;
81 [ - + ]: 1466 : do
82 : : {
83 : 1466 : nMid = (nLow + nHigh) / 2;
84 : 1466 : nCompareId = (*pList)[ nMid ]->mnId;
85 [ - + ]: 1466 : if ( nId < nCompareId )
86 : 0 : nHigh = nMid-1;
87 : : else
88 : : {
89 [ + - ]: 1466 : if ( nId > nCompareId )
90 : 1466 : nLow = nMid + 1;
91 : : else
92 : 0 : return (sal_uInt16)nMid;
93 : : }
94 : : }
95 : : while ( nLow <= nHigh );
96 : :
97 [ + - ]: 1466 : if ( pIndex )
98 : : {
99 [ + - ]: 1466 : if ( nId > nCompareId )
100 : 1466 : *pIndex = (sal_uInt16)(nMid+1);
101 : : else
102 : 0 : *pIndex = (sal_uInt16)nMid;
103 : : }
104 : :
105 : 2932 : return ACCELENTRY_NOTFOUND;
106 : : }
107 : :
108 : : // -----------------------------------------------------------------------
109 : :
110 : 2932 : static void ImplAccelEntryInsert( ImplAccelList* pList, ImplAccelEntry* pEntry )
111 : : {
112 : : sal_uInt16 nInsIndex;
113 [ + - ]: 2932 : sal_uInt16 nIndex = ImplAccelEntryGetIndex( pList, pEntry->mnId, &nInsIndex );
114 : :
115 [ - + ]: 2932 : if ( nIndex != ACCELENTRY_NOTFOUND )
116 : : {
117 [ # # ]: 0 : do
118 : : {
119 : 0 : nIndex++;
120 : 0 : ImplAccelEntry* pTempEntry = NULL;
121 [ # # ]: 0 : if ( nIndex < pList->size() )
122 : 0 : pTempEntry = (*pList)[ nIndex ];
123 [ # # ][ # # ]: 0 : if ( !pTempEntry || (pTempEntry->mnId != pEntry->mnId) )
124 : 0 : break;
125 : : }
126 : 0 : while ( nIndex < pList->size() );
127 : :
128 [ # # ]: 0 : if ( nIndex < pList->size() ) {
129 : 0 : ImplAccelList::iterator it = pList->begin();
130 [ # # ]: 0 : ::std::advance( it, nIndex );
131 [ # # ]: 0 : pList->insert( it, pEntry );
132 : : } else {
133 [ # # ]: 0 : pList->push_back( pEntry );
134 : : }
135 : : }
136 : : else {
137 [ - + ]: 2932 : if ( nInsIndex < pList->size() ) {
138 : 0 : ImplAccelList::iterator it = pList->begin();
139 [ # # ]: 0 : ::std::advance( it, nInsIndex );
140 [ # # ]: 0 : pList->insert( it, pEntry );
141 : : } else {
142 [ + - ]: 2932 : pList->push_back( pEntry );
143 : : }
144 : : }
145 : 2932 : }
146 : :
147 : : // -----------------------------------------------------------------------
148 : :
149 : 0 : static sal_uInt16 ImplAccelEntryGetFirstPos( ImplAccelList* pList, sal_uInt16 nId )
150 : : {
151 : 0 : sal_uInt16 nIndex = ImplAccelEntryGetIndex( pList, nId );
152 [ # # ]: 0 : if ( nIndex != ACCELENTRY_NOTFOUND )
153 : : {
154 [ # # ]: 0 : while ( nIndex )
155 : : {
156 : 0 : nIndex--;
157 [ # # ]: 0 : if ( (*pList)[ nIndex ]->mnId != nId )
158 : 0 : break;
159 : : }
160 : :
161 [ # # ]: 0 : if ( (*pList)[ nIndex ]->mnId != nId )
162 : 0 : nIndex++;
163 : : }
164 : :
165 : 0 : return nIndex;
166 : : }
167 : :
168 : : // =======================================================================
169 : :
170 : 1588 : void Accelerator::ImplInit()
171 : : {
172 : 1588 : mnCurId = 0;
173 : 1588 : mnCurRepeat = 0;
174 : 1588 : mbIsCancel = sal_False;
175 : 1588 : mpDel = NULL;
176 : 1588 : }
177 : :
178 : : // -----------------------------------------------------------------------
179 : :
180 : 0 : ImplAccelEntry* Accelerator::ImplGetAccelData( const KeyCode& rKeyCode ) const
181 : : {
182 [ # # ]: 0 : ImplAccelMap::iterator it = mpData->maKeyMap.find( rKeyCode.GetFullKeyCode() );
183 [ # # ]: 0 : if( it != mpData->maKeyMap.end() )
184 : 0 : return it->second;
185 : : else
186 : 0 : return NULL;
187 : : }
188 : :
189 : : // -----------------------------------------------------------------------
190 : :
191 : 0 : void Accelerator::ImplCopyData( ImplAccelData& rAccelData )
192 : : {
193 : : // copy table
194 [ # # ]: 0 : for ( size_t i = 0, n = rAccelData.maIdList.size(); i < n; ++i )
195 : : {
196 [ # # ]: 0 : ImplAccelEntry* pEntry = new ImplAccelEntry( *rAccelData.maIdList[ i ] );
197 : :
198 : : // sequence accelerator, then copy also
199 [ # # ]: 0 : if ( pEntry->mpAccel )
200 : : {
201 [ # # ][ # # ]: 0 : pEntry->mpAccel = new Accelerator( *(pEntry->mpAccel) );
202 : 0 : pEntry->mpAutoAccel = pEntry->mpAccel;
203 : : }
204 : : else
205 : 0 : pEntry->mpAutoAccel = NULL;
206 : :
207 [ # # ]: 0 : mpData->maKeyMap.insert( std::make_pair( pEntry->maKeyCode.GetFullKeyCode(), pEntry ) );
208 [ # # ]: 0 : mpData->maIdList.push_back( pEntry );
209 : : }
210 : 0 : }
211 : :
212 : : // -----------------------------------------------------------------------
213 : :
214 : 1578 : void Accelerator::ImplDeleteData()
215 : : {
216 : : // delete accelerator-entries using the id-table
217 [ + + ]: 4490 : for ( size_t i = 0, n = mpData->maIdList.size(); i < n; ++i ) {
218 : 2912 : ImplAccelEntry* pEntry = mpData->maIdList[ i ];
219 [ - + ]: 2912 : if ( pEntry->mpAutoAccel ) {
220 [ # # ]: 0 : delete pEntry->mpAutoAccel;
221 : : }
222 : 2912 : delete pEntry;
223 : : }
224 : 1578 : mpData->maIdList.clear();
225 : 1578 : }
226 : :
227 : : // -----------------------------------------------------------------------
228 : :
229 : 2932 : void Accelerator::ImplInsertAccel( sal_uInt16 nItemId, const KeyCode& rKeyCode,
230 : : sal_Bool bEnable, Accelerator* pAutoAccel )
231 : : {
232 : : DBG_CHKTHIS( Accelerator, NULL );
233 : : DBG_ASSERT( nItemId, "Accelerator::InsertItem(): ItemId == 0" );
234 : :
235 [ - + ]: 2932 : if ( rKeyCode.IsFunction() )
236 : : {
237 : : sal_uInt16 nCode1;
238 : : sal_uInt16 nCode2;
239 : : sal_uInt16 nCode3;
240 : : sal_uInt16 nCode4;
241 [ # # ][ # # ]: 0 : ImplGetKeyCode( rKeyCode.GetFunction(), nCode1, nCode2, nCode3, nCode4 );
242 [ # # ]: 0 : if ( nCode1 )
243 [ # # ]: 0 : ImplInsertAccel( nItemId, KeyCode( nCode1, nCode1 ), bEnable, pAutoAccel );
244 [ # # ]: 0 : if ( nCode2 )
245 : : {
246 [ # # ]: 0 : if ( pAutoAccel )
247 [ # # ][ # # ]: 0 : pAutoAccel = new Accelerator( *pAutoAccel );
248 [ # # ]: 0 : ImplInsertAccel( nItemId, KeyCode( nCode2, nCode2 ), bEnable, pAutoAccel );
249 [ # # ]: 0 : if ( nCode3 )
250 : : {
251 [ # # ]: 0 : if ( pAutoAccel )
252 [ # # ][ # # ]: 0 : pAutoAccel = new Accelerator( *pAutoAccel );
253 [ # # ]: 0 : ImplInsertAccel( nItemId, KeyCode( nCode3, nCode3 ), bEnable, pAutoAccel );
254 : : }
255 : : }
256 : 2932 : return;
257 : : }
258 : :
259 : : // fetch and fill new entries
260 [ + - ]: 2932 : ImplAccelEntry* pEntry = new ImplAccelEntry;
261 : 2932 : pEntry->mnId = nItemId;
262 [ + - ]: 2932 : pEntry->maKeyCode = rKeyCode;
263 : 2932 : pEntry->mpAccel = pAutoAccel;
264 : 2932 : pEntry->mpAutoAccel = pAutoAccel;
265 : 2932 : pEntry->mbEnabled = bEnable;
266 : :
267 : : // now into the tables
268 : 2932 : sal_uLong nCode = rKeyCode.GetFullKeyCode();
269 [ - + ]: 2932 : if ( !nCode )
270 : : {
271 : : OSL_FAIL( "Accelerator::InsertItem(): KeyCode with KeyCode 0 not allowed" );
272 : 0 : delete pEntry;
273 : : }
274 [ + - ][ - + ]: 2932 : else if ( !mpData->maKeyMap.insert( std::make_pair( nCode, pEntry ) ).second )
275 : : {
276 : : OSL_TRACE( "Accelerator::InsertItem(): KeyCode (Key: %lx) already exists", nCode );
277 : 0 : delete pEntry;
278 : : }
279 : : else
280 [ + - ]: 2932 : ImplAccelEntryInsert( &(mpData->maIdList), pEntry );
281 : : }
282 : :
283 : : // -----------------------------------------------------------------------
284 : :
285 [ + - ][ + - ]: 1588 : Accelerator::Accelerator()
[ + - ][ + - ]
286 : : {
287 : : DBG_CTOR( Accelerator, NULL );
288 : :
289 : 1588 : ImplInit();
290 [ + - ][ + - ]: 1588 : mpData = new ImplAccelData;
291 : 1588 : }
292 : :
293 : : // -----------------------------------------------------------------------
294 : :
295 : 0 : Accelerator::Accelerator( const Accelerator& rAccel ) :
296 : : Resource(),
297 : : maHelpStr( rAccel.maHelpStr ),
298 [ # # ][ # # ]: 0 : maCurKeyCode( rAccel.maCurKeyCode )
[ # # ][ # # ]
299 : : {
300 : : DBG_CTOR( Accelerator, NULL );
301 : : DBG_CHKOBJ( &rAccel, Accelerator, NULL );
302 : :
303 : 0 : ImplInit();
304 [ # # ][ # # ]: 0 : mpData = new ImplAccelData;
305 [ # # ]: 0 : ImplCopyData( *((ImplAccelData*)(rAccel.mpData)) );
306 : 0 : }
307 : :
308 : : // -----------------------------------------------------------------------
309 : :
310 [ # # ][ # # ]: 0 : Accelerator::Accelerator( const ResId& rResId )
[ # # ][ # # ]
311 : : {
312 : : DBG_CTOR( Accelerator, NULL );
313 : :
314 : 0 : ImplInit();
315 [ # # ][ # # ]: 0 : mpData = new ImplAccelData;
316 : 0 : rResId.SetRT( RSC_ACCEL );
317 [ # # ]: 0 : ImplLoadRes( rResId );
318 : 0 : }
319 : :
320 : : // -----------------------------------------------------------------------
321 : :
322 : 0 : void Accelerator::ImplLoadRes( const ResId& rResId )
323 : : {
324 : 0 : GetRes( rResId );
325 : :
326 [ # # ]: 0 : maHelpStr = ReadStringRes();
327 : 0 : sal_uLong nObjFollows = ReadLongRes();
328 : :
329 [ # # ]: 0 : for( sal_uLong i = 0; i < nObjFollows; i++ )
330 : : {
331 [ # # ]: 0 : InsertItem( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
332 : 0 : IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
333 : : }
334 : 0 : }
335 : :
336 : : // -----------------------------------------------------------------------
337 : :
338 [ + - ]: 1578 : Accelerator::~Accelerator()
339 : : {
340 : : DBG_DTOR( Accelerator, NULL );
341 : :
342 : : // inform AccelManager about deleting the Accelerator
343 [ - + ]: 1578 : if ( mpDel )
344 : 0 : *mpDel = sal_True;
345 : :
346 [ + - ]: 1578 : ImplDeleteData();
347 [ + - ]: 1578 : delete mpData;
348 [ - + ]: 1578 : }
349 : :
350 : : // -----------------------------------------------------------------------
351 : :
352 : 0 : void Accelerator::Activate()
353 : : {
354 : 0 : maActivateHdl.Call( this );
355 : 0 : }
356 : :
357 : : // -----------------------------------------------------------------------
358 : :
359 : 0 : void Accelerator::Deactivate()
360 : : {
361 : 0 : maDeactivateHdl.Call( this );
362 : 0 : }
363 : :
364 : : // -----------------------------------------------------------------------
365 : :
366 : 0 : void Accelerator::Select()
367 : : {
368 : 0 : maSelectHdl.Call( this );
369 : 0 : }
370 : :
371 : : // -----------------------------------------------------------------------
372 : :
373 : 2932 : void Accelerator::InsertItem( sal_uInt16 nItemId, const KeyCode& rKeyCode )
374 : : {
375 : 2932 : ImplInsertAccel( nItemId, rKeyCode, sal_True, NULL );
376 : 2932 : }
377 : :
378 : : // -----------------------------------------------------------------------
379 : :
380 : 0 : void Accelerator::InsertItem( const ResId& rResId )
381 : : {
382 : : DBG_CHKTHIS( Accelerator, NULL );
383 : :
384 : : sal_uLong nObjMask;
385 : : sal_uInt16 nAccelKeyId;
386 : : sal_uInt16 bDisable;
387 : 0 : KeyCode aKeyCode;
388 : 0 : Accelerator* pAutoAccel = NULL;
389 : :
390 [ # # ]: 0 : GetRes( rResId.SetRT( RSC_ACCELITEM ) );
391 [ # # ]: 0 : nObjMask = ReadLongRes();
392 [ # # ]: 0 : nAccelKeyId = sal::static_int_cast<sal_uInt16>(ReadLongRes());
393 [ # # ]: 0 : bDisable = ReadShortRes();
394 : :
395 [ # # ]: 0 : if ( nObjMask & ACCELITEM_KEY )
396 : : {
397 : : // new context was created
398 [ # # ]: 0 : RSHEADER_TYPE * pKeyCodeRes = (RSHEADER_TYPE *)GetClassRes();
399 : 0 : ResId aResId( pKeyCodeRes, *rResId.GetResMgr());
400 [ # # ][ # # ]: 0 : aKeyCode = KeyCode( aResId );
401 [ # # ][ # # ]: 0 : IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
[ # # ]
402 : : }
403 : :
404 [ # # ]: 0 : if ( nObjMask & ACCELITEM_ACCEL )
405 : : {
406 [ # # ][ # # ]: 0 : pAutoAccel = new Accelerator( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
[ # # ]
407 [ # # ][ # # ]: 0 : IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) );
[ # # ]
408 : : }
409 : :
410 [ # # ]: 0 : ImplInsertAccel( nAccelKeyId, aKeyCode, !bDisable, pAutoAccel );
411 : 0 : }
412 : :
413 : : // -----------------------------------------------------------------------
414 : :
415 : 0 : sal_uInt16 Accelerator::GetItemCount() const
416 : : {
417 : : DBG_CHKTHIS( Accelerator, NULL );
418 : :
419 : 0 : return (sal_uInt16)mpData->maIdList.size();
420 : : }
421 : :
422 : : // -----------------------------------------------------------------------
423 : :
424 : 0 : KeyCode Accelerator::GetKeyCode( sal_uInt16 nItemId ) const
425 : : {
426 : : DBG_CHKTHIS( Accelerator, NULL );
427 : :
428 : 0 : sal_uInt16 nIndex = ImplAccelEntryGetFirstPos( &(mpData->maIdList), nItemId );
429 [ # # ]: 0 : if ( nIndex != ACCELENTRY_NOTFOUND )
430 : 0 : return mpData->maIdList[ nIndex ]->maKeyCode;
431 : : else
432 : 0 : return KeyCode();
433 : : }
434 : :
435 : : // -----------------------------------------------------------------------
436 : :
437 : 0 : sal_uInt16 Accelerator::GetItemId( sal_uInt16 nPos ) const
438 : : {
439 : : DBG_CHKTHIS( Accelerator, NULL );
440 : :
441 [ # # ]: 0 : ImplAccelEntry* pEntry = ( nPos < mpData->maIdList.size() ) ? mpData->maIdList[ nPos ] : NULL;
442 [ # # ]: 0 : if ( pEntry )
443 : 0 : return pEntry->mnId;
444 : : else
445 : 0 : return 0;
446 : : }
447 : :
448 : : // -----------------------------------------------------------------------
449 : :
450 : 0 : Accelerator* Accelerator::GetAccel( sal_uInt16 nItemId ) const
451 : : {
452 : : DBG_CHKTHIS( Accelerator, NULL );
453 : :
454 : 0 : sal_uInt16 nIndex = ImplAccelEntryGetIndex( &(mpData->maIdList), nItemId );
455 [ # # ]: 0 : if ( nIndex != ACCELENTRY_NOTFOUND )
456 : 0 : return mpData->maIdList[ nIndex ]->mpAccel;
457 : : else
458 : 0 : return NULL;
459 : : }
460 : :
461 : : // -----------------------------------------------------------------------
462 : :
463 : 0 : Accelerator& Accelerator::operator=( const Accelerator& rAccel )
464 : : {
465 : : DBG_CHKTHIS( Accelerator, NULL );
466 : : DBG_CHKOBJ( &rAccel, Accelerator, NULL );
467 : :
468 : : // assign new data
469 : 0 : maHelpStr = rAccel.maHelpStr;
470 [ # # ]: 0 : maCurKeyCode = KeyCode();
471 : 0 : mnCurId = 0;
472 : 0 : mnCurRepeat = 0;
473 : 0 : mbIsCancel = sal_False;
474 : :
475 : : // delete and copy tables
476 : 0 : ImplDeleteData();
477 : 0 : mpData->maKeyMap.clear();
478 : 0 : ImplCopyData( *((ImplAccelData*)(rAccel.mpData)) );
479 : :
480 : 0 : return *this;
481 : : }
482 : :
483 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|