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 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 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 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 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 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