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