build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / vcl / source / window / accel.cxx
blob64b25881cc176d686bb2081b004a3e73a6d73d3f
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 <tools/debug.hxx>
21 #include <tools/rc.h>
23 #include <vcl/window.hxx>
24 #include <vcl/svapp.hxx>
25 #include <accel.h>
26 #include <vcl/accel.hxx>
27 #include <map>
28 #include <vector>
30 typedef ::std::map< sal_uLong, ImplAccelEntry* > ImplAccelMap;
31 typedef ::std::vector< ImplAccelEntry* > ImplAccelList;
33 #define ACCELENTRY_NOTFOUND ((sal_uInt16)0xFFFF)
35 class ImplAccelData
37 public:
38 ImplAccelMap maKeyMap; // for keycodes, generated with a code
39 ImplAccelList maIdList; // Id-List
42 sal_uInt16 ImplAccelEntryGetIndex( ImplAccelList* pList, sal_uInt16 nId,
43 sal_uInt16* pIndex = nullptr )
45 size_t nLow;
46 size_t nHigh;
47 size_t nMid;
48 size_t nCount = pList->size();
49 sal_uInt16 nCompareId;
51 // check if first key is larger then the key to compare
52 if ( !nCount || (nId < (*pList)[ 0 ]->mnId) )
54 if ( pIndex )
55 *pIndex = 0;
56 return ACCELENTRY_NOTFOUND;
59 // Binary search
60 nLow = 0;
61 nHigh = nCount-1;
64 nMid = (nLow + nHigh) / 2;
65 nCompareId = (*pList)[ nMid ]->mnId;
66 if ( nId < nCompareId )
67 nHigh = nMid-1;
68 else
70 if ( nId > nCompareId )
71 nLow = nMid + 1;
72 else
73 return (sal_uInt16)nMid;
76 while ( nLow <= nHigh );
78 if ( pIndex )
80 if ( nId > nCompareId )
81 *pIndex = (sal_uInt16)(nMid+1);
82 else
83 *pIndex = (sal_uInt16)nMid;
86 return ACCELENTRY_NOTFOUND;
89 static void ImplAccelEntryInsert( ImplAccelList* pList, ImplAccelEntry* pEntry )
91 sal_uInt16 nInsIndex(0);
92 sal_uInt16 nIndex = ImplAccelEntryGetIndex( pList, pEntry->mnId, &nInsIndex );
94 if ( nIndex != ACCELENTRY_NOTFOUND )
98 nIndex++;
99 ImplAccelEntry* pTempEntry = nullptr;
100 if ( nIndex < pList->size() )
101 pTempEntry = (*pList)[ nIndex ];
102 if ( !pTempEntry || (pTempEntry->mnId != pEntry->mnId) )
103 break;
105 while ( nIndex < pList->size() );
107 if ( nIndex < pList->size() ) {
108 ImplAccelList::iterator it = pList->begin();
109 ::std::advance( it, nIndex );
110 pList->insert( it, pEntry );
111 } else {
112 pList->push_back( pEntry );
115 else {
116 if ( nInsIndex < pList->size() ) {
117 ImplAccelList::iterator it = pList->begin();
118 ::std::advance( it, nInsIndex );
119 pList->insert( it, pEntry );
120 } else {
121 pList->push_back( pEntry );
126 void Accelerator::ImplInit()
128 mnCurId = 0;
129 mnCurRepeat = 0;
130 mpDel = nullptr;
133 ImplAccelEntry* Accelerator::ImplGetAccelData( const vcl::KeyCode& rKeyCode ) const
135 ImplAccelMap::iterator it = mpData->maKeyMap.find( rKeyCode.GetFullCode() );
136 if( it != mpData->maKeyMap.end() )
137 return it->second;
138 else
139 return nullptr;
142 void Accelerator::ImplCopyData( ImplAccelData& rAccelData )
144 // copy table
145 for (ImplAccelEntry* i : rAccelData.maIdList)
147 ImplAccelEntry* pEntry = new ImplAccelEntry( *i );
149 // sequence accelerator, then copy also
150 if ( pEntry->mpAccel )
152 pEntry->mpAccel = new Accelerator( *(pEntry->mpAccel) );
153 pEntry->mpAutoAccel = pEntry->mpAccel;
155 else
156 pEntry->mpAutoAccel = nullptr;
158 mpData->maKeyMap.insert( std::make_pair( pEntry->maKeyCode.GetFullCode(), pEntry ) );
159 mpData->maIdList.push_back( pEntry );
163 void Accelerator::ImplDeleteData()
165 // delete accelerator-entries using the id-table
166 for (ImplAccelEntry* pEntry : mpData->maIdList) {
167 if ( pEntry->mpAutoAccel ) {
168 delete pEntry->mpAutoAccel;
170 delete pEntry;
172 mpData->maIdList.clear();
175 void Accelerator::ImplInsertAccel( sal_uInt16 nItemId, const vcl::KeyCode& rKeyCode,
176 bool bEnable, Accelerator* pAutoAccel )
178 SAL_WARN_IF( !nItemId, "vcl", "Accelerator::InsertItem(): ItemId == 0" );
180 if ( rKeyCode.IsFunction() )
182 sal_uInt16 nCode1;
183 sal_uInt16 nCode2;
184 sal_uInt16 nCode3;
185 sal_uInt16 nCode4;
186 ImplGetKeyCode( rKeyCode.GetFunction(), nCode1, nCode2, nCode3, nCode4 );
187 if ( nCode1 )
188 ImplInsertAccel( nItemId, vcl::KeyCode( nCode1, nCode1 ), bEnable, pAutoAccel );
189 if ( nCode2 )
191 if ( pAutoAccel )
192 pAutoAccel = new Accelerator( *pAutoAccel );
193 ImplInsertAccel( nItemId, vcl::KeyCode( nCode2, nCode2 ), bEnable, pAutoAccel );
194 if ( nCode3 )
196 if ( pAutoAccel )
197 pAutoAccel = new Accelerator( *pAutoAccel );
198 ImplInsertAccel( nItemId, vcl::KeyCode( nCode3, nCode3 ), bEnable, pAutoAccel );
201 return;
204 // fetch and fill new entries
205 ImplAccelEntry* pEntry = new ImplAccelEntry;
206 pEntry->mnId = nItemId;
207 pEntry->maKeyCode = rKeyCode;
208 pEntry->mpAccel = pAutoAccel;
209 pEntry->mpAutoAccel = pAutoAccel;
210 pEntry->mbEnabled = bEnable;
212 // now into the tables
213 sal_uLong nCode = rKeyCode.GetFullCode();
214 if ( !nCode )
216 OSL_FAIL( "Accelerator::InsertItem(): KeyCode with KeyCode 0 not allowed" );
217 delete pEntry;
219 else if ( !mpData->maKeyMap.insert( std::make_pair( nCode, pEntry ) ).second )
221 SAL_WARN( "vcl.layout", "Accelerator::InsertItem(): KeyCode (Key: " << nCode << ") already exists" );
222 delete pEntry;
224 else
225 ImplAccelEntryInsert( &(mpData->maIdList), pEntry );
228 Accelerator::Accelerator()
231 ImplInit();
232 mpData = new ImplAccelData;
235 Accelerator::Accelerator( const Accelerator& rAccel ) :
236 Resource(),
237 maCurKeyCode( rAccel.maCurKeyCode )
240 ImplInit();
241 mpData = new ImplAccelData;
242 ImplCopyData(*rAccel.mpData);
245 Accelerator::~Accelerator()
248 // inform AccelManager about deleting the Accelerator
249 if ( mpDel )
250 *mpDel = true;
252 ImplDeleteData();
253 delete mpData;
256 void Accelerator::Activate()
258 maActivateHdl.Call( *this );
261 void Accelerator::Select()
263 maSelectHdl.Call( *this );
266 void Accelerator::InsertItem( sal_uInt16 nItemId, const vcl::KeyCode& rKeyCode )
268 ImplInsertAccel( nItemId, rKeyCode, true, nullptr );
271 sal_uInt16 Accelerator::GetItemCount() const
274 return (sal_uInt16)mpData->maIdList.size();
277 sal_uInt16 Accelerator::GetItemId( sal_uInt16 nPos ) const
280 ImplAccelEntry* pEntry = ( nPos < mpData->maIdList.size() ) ? mpData->maIdList[ nPos ] : nullptr;
281 if ( pEntry )
282 return pEntry->mnId;
283 else
284 return 0;
287 Accelerator* Accelerator::GetAccel( sal_uInt16 nItemId ) const
290 sal_uInt16 nIndex = ImplAccelEntryGetIndex( &(mpData->maIdList), nItemId );
291 if ( nIndex != ACCELENTRY_NOTFOUND )
292 return mpData->maIdList[ nIndex ]->mpAccel;
293 else
294 return nullptr;
297 Accelerator& Accelerator::operator=( const Accelerator& rAccel )
300 // assign new data
301 maCurKeyCode = vcl::KeyCode();
302 mnCurId = 0;
303 mnCurRepeat = 0;
305 // delete and copy tables
306 ImplDeleteData();
307 mpData->maKeyMap.clear();
308 ImplCopyData(*rAccel.mpData);
310 return *this;
313 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */