1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 #include <tools/list.hxx>
27 #include <tools/debug.hxx>
28
29 #include <accel.h>
30 #include <vcl/accel.hxx>
31 #include <accmgr.hxx>
32
33
34
35 // =======================================================================
36
DECLARE_LIST(ImplAccelList,Accelerator *)37 DECLARE_LIST( ImplAccelList, Accelerator* )
38
39 // =======================================================================
40
41 DBG_NAMEEX( Accelerator )
42
43 // =======================================================================
44
45 ImplAccelManager::~ImplAccelManager()
46 {
47 if ( mpAccelList )
48 delete mpAccelList;
49 if ( mpSequenceList )
50 delete mpSequenceList;
51 }
52
53 // -----------------------------------------------------------------------
54
InsertAccel(Accelerator * pAccel)55 sal_Bool ImplAccelManager::InsertAccel( Accelerator* pAccel )
56 {
57 if ( !mpAccelList )
58 mpAccelList = new ImplAccelList;
59 else
60 {
61 // Gibts den schon ?
62 if ( mpAccelList->GetPos( pAccel ) != LIST_ENTRY_NOTFOUND )
63 return sal_False;
64 }
65
66 // Am Anfang der Liste einfuegen
67 mpAccelList->Insert( pAccel, (sal_uLong)0 );
68
69 return sal_True;
70 }
71
72 // -----------------------------------------------------------------------
73
RemoveAccel(Accelerator * pAccel)74 void ImplAccelManager::RemoveAccel( Accelerator* pAccel )
75 {
76 // Haben wir ueberhaupt eine Liste ?
77 if ( !mpAccelList )
78 return;
79
80 //e.g. #i90599#. Someone starts typing a sequence in a dialog, but doesn't
81 //end it, and then closes the dialog, deleting the accelerators. So if
82 //we're removing an accelerator that a sub-accelerator which is in the
83 //sequence list, throw away the entire sequence
84 if ( mpSequenceList )
85 {
86 for (sal_uInt16 i = 0; i < pAccel->GetItemCount(); ++i)
87 {
88 Accelerator* pSubAccel = pAccel->GetAccel(pAccel->GetItemId(i));
89 if ( mpSequenceList->GetPos( pSubAccel ) != LIST_ENTRY_NOTFOUND )
90 {
91 EndSequence( true );
92 break;
93 }
94 }
95 }
96
97 // Raus damit
98 mpAccelList->Remove( pAccel );
99 }
100
101 // -----------------------------------------------------------------------
102
EndSequence(sal_Bool bCancel)103 void ImplAccelManager::EndSequence( sal_Bool bCancel )
104 {
105 // Sind wir ueberhaupt in einer Sequenz ?
106 if ( !mpSequenceList )
107 return;
108
109 // Alle Deactivate-Handler der Acceleratoren in der Sequenz rufen
110 Accelerator* pTempAccel = mpSequenceList->First();
111 while( pTempAccel )
112 {
113 sal_Bool bDel = sal_False;
114 pTempAccel->mbIsCancel = bCancel;
115 pTempAccel->mpDel = &bDel;
116 pTempAccel->Deactivate();
117 if ( !bDel )
118 {
119 pTempAccel->mbIsCancel = sal_False;
120 pTempAccel->mpDel = NULL;
121 }
122
123 pTempAccel = mpSequenceList->Next();
124 }
125
126 // Sequenz-Liste loeschen
127 delete mpSequenceList;
128 mpSequenceList = NULL;
129 }
130
131 // -----------------------------------------------------------------------
132
IsAccelKey(const KeyCode & rKeyCode,sal_uInt16 nRepeat)133 sal_Bool ImplAccelManager::IsAccelKey( const KeyCode& rKeyCode, sal_uInt16 nRepeat )
134 {
135 Accelerator* pAccel;
136
137 // Haben wir ueberhaupt Acceleratoren ??
138 if ( !mpAccelList )
139 return sal_False;
140 if ( !mpAccelList->Count() )
141 return sal_False;
142
143 // Sind wir in einer Sequenz ?
144 if ( mpSequenceList )
145 {
146 pAccel = mpSequenceList->GetObject( 0 );
147 DBG_CHKOBJ( pAccel, Accelerator, NULL );
148
149 // Nicht Gefunden ?
150 if ( !pAccel )
151 {
152 // Sequenz abbrechen
153 FlushAccel();
154 return sal_False;
155 }
156
157 // Ist der Eintrag da drin ?
158 ImplAccelEntry* pEntry = pAccel->ImplGetAccelData( rKeyCode );
159 if ( pEntry )
160 {
161 Accelerator* pNextAccel = pEntry->mpAccel;
162
163 // Ist da ein Accelerator hinter ?
164 if ( pNextAccel )
165 {
166 DBG_CHKOBJ( pNextAccel, Accelerator, NULL );
167
168 mpSequenceList->Insert( pNextAccel, (sal_uLong)0 );
169
170 // Activate-Handler vom Neuen rufen
171 pNextAccel->Activate();
172 return sal_True;
173 }
174 else
175 {
176 // Hat ihn schon !
177 if ( pEntry->mbEnabled )
178 {
179 // Sequence beenden (Deactivate-Handler vorher rufen)
180 EndSequence();
181
182 // Dem Accelerator das aktuelle Item setzen
183 // und Handler rufen
184 sal_Bool bDel = sal_False;
185 pAccel->maCurKeyCode = rKeyCode;
186 pAccel->mnCurId = pEntry->mnId;
187 pAccel->mnCurRepeat = nRepeat;
188 pAccel->mpDel = &bDel;
189 pAccel->Select();
190
191 // Hat Accel den Aufruf ueberlebt
192 if ( !bDel )
193 {
194 DBG_CHKOBJ( pAccel, Accelerator, NULL );
195 pAccel->maCurKeyCode = KeyCode();
196 pAccel->mnCurId = 0;
197 pAccel->mnCurRepeat = 0;
198 pAccel->mpDel = NULL;
199 }
200
201 return sal_True;
202 }
203 else
204 {
205 // Sequenz abbrechen, weil Acceleraor disabled
206 // Taste wird weitergeleitet (ans System)
207 FlushAccel();
208 return sal_False;
209 }
210 }
211 }
212 else
213 {
214 // Sequenz abbrechen wegen falscher Taste
215 FlushAccel();
216 return sal_False;
217 }
218 }
219
220 // Durch die Liste der Acceleratoren wuehlen
221 pAccel = mpAccelList->First();
222 while ( pAccel )
223 {
224 DBG_CHKOBJ( pAccel, Accelerator, NULL );
225
226 // Ist der Eintrag da drin ?
227 ImplAccelEntry* pEntry = pAccel->ImplGetAccelData( rKeyCode );
228 if ( pEntry )
229 {
230 Accelerator* pNextAccel = pEntry->mpAccel;
231
232 // Ist da ein Accelerator hinter ?
233 if ( pNextAccel )
234 {
235 DBG_CHKOBJ( pNextAccel, Accelerator, NULL );
236
237 // Sequenz-Liste erzeugen
238 mpSequenceList = new ImplAccelList;
239 mpSequenceList->Insert( pAccel, (sal_uLong)0 );
240 mpSequenceList->Insert( pNextAccel, (sal_uLong)0 );
241
242 // Activate-Handler vom Neuen rufen
243 pNextAccel->Activate();
244
245 return sal_True;
246 }
247 else
248 {
249 // Hat ihn schon !
250 if ( pEntry->mbEnabled )
251 {
252 // Activate/Deactivate-Handler vorher rufen
253 pAccel->Activate();
254 pAccel->Deactivate();
255
256 // Dem Accelerator das aktuelle Item setzen
257 // und Handler rufen
258 sal_Bool bDel = sal_False;
259 pAccel->maCurKeyCode = rKeyCode;
260 pAccel->mnCurId = pEntry->mnId;
261 pAccel->mnCurRepeat = nRepeat;
262 pAccel->mpDel = &bDel;
263 pAccel->Select();
264
265 // Hat Accel den Aufruf ueberlebt
266 if ( !bDel )
267 {
268 DBG_CHKOBJ( pAccel, Accelerator, NULL );
269 pAccel->maCurKeyCode = KeyCode();
270 pAccel->mnCurId = 0;
271 pAccel->mnCurRepeat = 0;
272 pAccel->mpDel = NULL;
273 }
274
275 return sal_True;
276 }
277 else
278 return sal_False;
279 }
280 }
281
282 // Nicht gefunden, vielleicht im naechsten Accelerator
283 pAccel = mpAccelList->Next();
284 }
285
286 return sal_False;
287 }
288