// ========================================================================== // Class Implementation: COXShortkeysOrganizer // ========================================================================== // Version: 9.3 // This software along with its related components, documentation and files ("The Libraries") // is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is // governed by a software license agreement ("Agreement"). Copies of the Agreement are // available at The Code Project (www.codeproject.com), as part of the package you downloaded // to obtain this file, or directly from our office. For a copy of the license governing // this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900. // ////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "OXShortkeysOrganizer.h" #include "OXRegistryValFile.h" #include "UTB64Bit.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// COXShortkeysOrganizer::COXShortkeysOrganizer() : m_pFrameWnd(NULL) { } COXShortkeysOrganizer::~COXShortkeysOrganizer() { m_arrAccelTables.RemoveAll(); m_arrRemovedAccelTables.RemoveAll(); for(int nIndex=0; nIndexAdd(accel); return TRUE; } BOOL COXShortkeysOrganizer::AddAccelerator(ACCEL* pAccel, CMultiDocTemplate* pDocTemplate, BOOL bIgnoreConflict/*=FALSE*/) { ASSERT(pAccel!=NULL); return AddAccelerator(pAccel->fVirt,pAccel->key,pAccel->cmd, pDocTemplate,bIgnoreConflict); } BOOL COXShortkeysOrganizer::RemoveAccelerator(BYTE fVirt, WORD key, WORD cmd, CMultiDocTemplate* pDocTemplate) { if(!IsAttached()) { TRACE(_T("COXShortkeysOrganizer::RemoveAccelerator: there is no attached frame window. You have to attach frame window before calling this function\n")); return FALSE; } COXArrAccelerators* pArrAccels=FindAcceleratorTable(pDocTemplate); if(pArrAccels==NULL) { return FALSE; } COXArrAccelerators* pArrRemovedAccels=FindRemovedAcceleratorTable(pDocTemplate); if(pArrRemovedAccels==NULL) { OXACCELTABLE accelTable; accelTable.m_docTemplate=pDocTemplate; m_arrRemovedAccelTables.Add(accelTable); pArrRemovedAccels=FindRemovedAcceleratorTable(pDocTemplate); } ASSERT(pArrRemovedAccels!=NULL); for(int nAccelIndex=0; nAccelIndexGetSize(); nAccelIndex++) { ACCEL accel=pArrAccels->GetAt(nAccelIndex); if((accel.fVirt&~FNOINVERT)==(fVirt&~FNOINVERT) && accel.key==key && accel.cmd==cmd) { pArrAccels->RemoveAt(nAccelIndex); nAccelIndex--; // save the removed accelerator pArrRemovedAccels->Add(accel); break; } } return TRUE; } BOOL COXShortkeysOrganizer::RemoveAccelerator(ACCEL* pAccel, CMultiDocTemplate* pDocTemplate) { ASSERT(pAccel!=NULL); return RemoveAccelerator(pAccel->fVirt,pAccel->key,pAccel->cmd,pDocTemplate); } BOOL COXShortkeysOrganizer::RemoveAllAccelerators(WORD cmd, CMultiDocTemplate* pDocTemplate) { if(!IsAttached()) { TRACE(_T("COXShortkeysOrganizer::RemoveAllAccelerators: there is no attached frame window. You have to attach frame window before calling this function\n")); return FALSE; } COXArrAccelerators* pArrAccels=FindAcceleratorTable(pDocTemplate); if(pArrAccels==NULL) { return FALSE; } COXArrAccelerators* pArrRemovedAccels=FindRemovedAcceleratorTable(pDocTemplate); if(pArrRemovedAccels==NULL) { OXACCELTABLE accelTable; accelTable.m_docTemplate=pDocTemplate; m_arrRemovedAccelTables.Add(accelTable); pArrRemovedAccels=FindRemovedAcceleratorTable(pDocTemplate); } ASSERT(pArrRemovedAccels!=NULL); for(int nAccelIndex=0; nAccelIndexGetSize(); nAccelIndex++) { ACCEL accel=pArrAccels->GetAt(nAccelIndex); if(accel.cmd==cmd) { pArrAccels->RemoveAt(nAccelIndex); nAccelIndex--; // save the removed accelerator pArrRemovedAccels->Add(accel); } } return TRUE; } WORD COXShortkeysOrganizer::FindAccelerator(BYTE fVirt, WORD key, CMultiDocTemplate* pDocTemplate) { if(!IsAttached()) { TRACE(_T("COXShortkeysOrganizer::FindAccelerator: there is no attached frame window. You have to attach frame window before calling this function\n")); return 0; } COXArrAccelerators* pArrAccels=FindAcceleratorTable(pDocTemplate); if(pArrAccels==NULL) { return 0; } for(int nAccelIndex=0; nAccelIndexGetSize(); nAccelIndex++) { ACCEL accel=pArrAccels->GetAt(nAccelIndex); if((accel.fVirt&~FNOINVERT)==(fVirt&~FNOINVERT) && accel.key==key) { return accel.cmd; } } return 0; } COXArrAccelerators* COXShortkeysOrganizer:: FindAcceleratorTable(CMultiDocTemplate* pDocTemplate) { if(!IsAttached()) { TRACE(_T("COXShortkeysOrganizer::FindAcceleratorTable: there is no attached frame window. You have to attach frame window before calling this function\n")); return NULL; } for(int nIndex=0; nIndexGetSize(); nAccelIndex++) { ACCEL accel=pArrAccels->GetAt(nAccelIndex); if(accel.cmd==cmd) { arrAccels.Add(accel); } } return TRUE; } BOOL COXShortkeysOrganizer::FindAllAccelerators(BYTE fVirt, WORD key, COXArrAccelerators& arrAccels) { if(!IsAttached()) { TRACE(_T("COXShortkeysOrganizer::FindAllAccelerators: there is no attached frame window. You have to attach frame window before calling this function\n")); return FALSE; } for(int nIndex=0; nIndexGetSize(); nAccelIndex++) { ACCEL accel=pArrAccels->GetAt(nAccelIndex); if((accel.fVirt&~FNOINVERT)==(fVirt&~FNOINVERT) && accel.key==key) { arrAccels.Add(accel); } } } return TRUE; } WORD COXShortkeysOrganizer::FindRemovedAccelerator(BYTE fVirt, WORD key, CMultiDocTemplate* pDocTemplate) { if(!IsAttached()) { TRACE(_T("COXShortkeysOrganizer::FindRemovedAccelerator: there is no attached frame window. You have to attach frame window before calling this function\n")); return 0; } COXArrAccelerators* pArrAccels=FindRemovedAcceleratorTable(pDocTemplate); if(pArrAccels==NULL) { return 0; } for(int nAccelIndex=0; nAccelIndexGetSize(); nAccelIndex++) { ACCEL accel=pArrAccels->GetAt(nAccelIndex); if((accel.fVirt&~FNOINVERT)==(fVirt&~FNOINVERT) && accel.key==key) { return accel.cmd; } } return 0; } COXArrAccelerators* COXShortkeysOrganizer:: FindRemovedAcceleratorTable(CMultiDocTemplate* pDocTemplate) { if(!IsAttached()) { TRACE(_T("COXShortkeysOrganizer::FindRemovedAcceleratorTable: there is no attached frame window. You have to attach frame window before calling this function\n")); return NULL; } for(int nIndex=0; nIndexGetSize(); nAccelIndex++) { ACCEL accel=pArrAccels->GetAt(nAccelIndex); if(accel.cmd==cmd) { arrAccels.Add(accel); } } return TRUE; } BOOL COXShortkeysOrganizer::FindAllRemovedAccelerators(BYTE fVirt, WORD key, COXArrAccelerators& arrAccels) { if(!IsAttached()) { TRACE(_T("COXShortkeysOrganizer::FindAllRemovedAccelerators: there is no attached frame window. You have to attach frame window before calling this function\n")); return FALSE; } for(int nIndex=0; nIndexGetSize(); nAccelIndex++) { ACCEL accel=pArrAccels->GetAt(nAccelIndex); if((accel.fVirt&~FNOINVERT)==(fVirt&~FNOINVERT) && accel.key==key) { arrAccels.Add(accel); } } } return TRUE; } BOOL COXShortkeysOrganizer::RetrieveAccelerators() { if(!IsAttached()) { TRACE(_T("COXShortkeysOrganizer::RetrieveAccelerators: there is no attached frame window. You have to attach frame window before calling this function\n")); return FALSE; } ASSERT(m_pFrameWnd!=NULL); ASSERT(m_pFrameWnd->GetSafeHwnd()); m_arrAccelTables.RemoveAll(); if(m_pFrameWnd->m_hAccelTable!=NULL) { VERIFY(AddAccelTable(m_pFrameWnd->m_hAccelTable,NULL)); } // if the attached frame window is an MDI mainframe window then we also // have to retrieve accelerators associated with CMultiDocTemplate objects if(AfxGetMainWnd()==m_pFrameWnd && m_pFrameWnd->IsKindOf(RUNTIME_CLASS(CMDIFrameWnd))) { CWinApp* pApp=AfxGetApp(); ASSERT(pApp!=NULL); POSITION pos=pApp->GetFirstDocTemplatePosition(); while(pos!=NULL) { CMultiDocTemplate* pDocTemplate= (CMultiDocTemplate*)pApp->GetNextDocTemplate(pos); ASSERT(pDocTemplate!=NULL); if(pDocTemplate->m_hAccelTable!=NULL) { VERIFY(AddAccelTable(pDocTemplate->m_hAccelTable,pDocTemplate)); } } } return TRUE; } BOOL COXShortkeysOrganizer::SetAccelerators() { if(!IsAttached()) { TRACE(_T("COXShortkeysOrganizer::SetAccelerators: there is no attached frame window. You have to attach frame window before calling this function\n")); return FALSE; } ASSERT(m_pFrameWnd!=NULL); ASSERT(m_pFrameWnd->GetSafeHwnd()); // first of all build a table for main window HACCEL hNewMainAccelTable=BuildAccelTable(NULL); m_pFrameWnd->m_hAccelTable=hNewMainAccelTable; // if the attached frame window is an MDI mainframe window then we also // have to build accelerators associated with CMultiDocTemplate objects if(AfxGetMainWnd()==m_pFrameWnd && m_pFrameWnd->IsKindOf(RUNTIME_CLASS(CMDIFrameWnd))) { CWinApp* pApp=AfxGetApp(); ASSERT(pApp!=NULL); POSITION pos=pApp->GetFirstDocTemplatePosition(); while(pos!=NULL) { CMultiDocTemplate* pDocTemplate= (CMultiDocTemplate*)pApp->GetNextDocTemplate(pos); ASSERT(pDocTemplate!=NULL); HACCEL hNewAccelTable=BuildAccelTable(pDocTemplate); HACCEL hOldAccelTable=pDocTemplate->m_hAccelTable; pDocTemplate->m_hAccelTable=hNewAccelTable; // change accelerator table for all MDIChild windows that host // documents of this template POSITION posDoc=pDocTemplate->GetFirstDocPosition(); while(posDoc!=NULL) { CDocument* pDoc=pDocTemplate->GetNextDoc(posDoc); ASSERT_VALID(pDoc); // go through all views POSITION posView=pDoc->GetFirstViewPosition(); while(posView!=NULL) { CView* pView=pDoc->GetNextView(posView); ASSERT_VALID(pView); CFrameWnd* pFrame=pView->GetParentFrame(); ASSERT_VALID(pFrame); if(pFrame->m_hAccelTable==hOldAccelTable) { pFrame->m_hAccelTable=hNewAccelTable; } } } } } // clean up information about removed accelerators m_arrRemovedAccelTables.RemoveAll(); return TRUE; } BOOL COXShortkeysOrganizer:: SaveState(LPCTSTR lpszProfileName/*=_T("ShortkeysOrganizerState")*/) { #ifndef _MAC if(!IsAttached()) { TRACE(_T("COXShortkeysOrganizer::SaveState: there is no attached frame window. You have to attach frame window before calling this function\n")); return FALSE; } CString m_sProfileName=lpszProfileName; ASSERT(!m_sProfileName.IsEmpty()); ASSERT(m_pFrameWnd!=NULL); ASSERT(m_pFrameWnd->GetSafeHwnd()); CWinApp* pApp=AfxGetApp(); // make sure you called CWinApp::SetRegistryKey() functions before if(pApp->m_pszRegistryKey==NULL || pApp->m_pszProfileName==NULL) { TRACE(_T("COXShortkeysOrganizer::SaveState: CWinApp::SetRegistryKey() must be called in InitInstance()\n")); return FALSE; } // we use default registry key assigned to your application by MFC HKEY hSecKey=pApp->GetSectionKey(_T("")); if (hSecKey==NULL) { TRACE(_T("COXShortkeysOrganizer::SaveState: unable to get section key\n")); return FALSE; } BOOL bResult=TRUE; try { COXRegistryValFile regAccelState(hSecKey,m_sProfileName, _T("AcceleratorsState")); CArchive ar(®AccelState, CArchive::store); Serialize(ar); ar.Close(); } catch(CException* e) { UNREFERENCED_PARAMETER(e); bResult=FALSE; } ::RegCloseKey(hSecKey); return bResult; #else return FALSE; #endif } BOOL COXShortkeysOrganizer:: LoadState(LPCTSTR lpszProfileName/*=_T("ShortkeysOrganizerState")*/, BOOL bApply/*=TRUE*/) { #ifndef _MAC if(!IsAttached()) { TRACE(_T("COXShortkeysOrganizer::SaveState: there is no attached frame window. You have to attach frame window before calling this function\n")); return FALSE; } CString m_sProfileName=lpszProfileName; ASSERT(!m_sProfileName.IsEmpty()); ASSERT(m_pFrameWnd!=NULL); ASSERT(m_pFrameWnd->GetSafeHwnd()); CWinApp* pApp=AfxGetApp(); // make sure you called CWinApp::SetRegistryKey() functions before if(pApp->m_pszRegistryKey==NULL || pApp->m_pszProfileName==NULL) { TRACE(_T("COXShortkeysOrganizer::SaveState: CWinApp::SetRegistryKey() must be called in InitInstance()\n")); return FALSE; } // we use default registry key assigned to your application by MFC HKEY hSecKey=pApp->GetSectionKey(_T("")); if (hSecKey==NULL) { TRACE(_T("COXShortkeysOrganizer::SaveState: unable to get section key\n")); return FALSE; } BOOL bResult=TRUE; try { COXRegistryValFile regAccelState(hSecKey,m_sProfileName, _T("AcceleratorsState")); if(regAccelState.GetLength()>0) { CArchive ar(®AccelState, CArchive::load); Serialize(ar); ar.Close(); } } catch(CException* e) { UNREFERENCED_PARAMETER(e); bResult=FALSE; } ::RegCloseKey(hSecKey); if(bResult && bApply) VERIFY(SetAccelerators()); return bResult; #else return FALSE; #endif } void COXShortkeysOrganizer::Serialize(CArchive& ar) { if(ar.IsStoring()) { ar<<(DWORD)m_arrAccelTables.GetSize(); for(int nIndex=0; nIndex>dwTableCount; ASSERT(m_arrAccelTables.GetSize()==(int)dwTableCount); if(m_arrAccelTables.GetSize()!=(int)dwTableCount) { TRACE(_T("COXShortkeysOrganizer::Serialize: failed to read the serialized data\n")); return; } for(int nIndex=0; nIndex<(int)dwTableCount; nIndex++) { SerializeAccelTable(ar,&m_arrAccelTables[nIndex]); } } } CString COXShortkeysOrganizer::GetAccelKeyString(ACCEL* pAccel) { ASSERT(pAccel!=NULL); CString sKey(_T("")); if(pAccel->fVirt&FSHIFT) sKey+=_T("Shift+"); if(pAccel->fVirt&FCONTROL) sKey+=_T("Ctrl+"); if(pAccel->fVirt&FALT) sKey+=_T("Alt+"); if(pAccel->fVirt&FVIRTKEY) { TCHAR szKeyName[10]; LPARAM lParam=MAKELPARAM(0,::MapVirtualKey(pAccel->key,0)) | (pAccel->key<0x0030 ? 0x01000000 : 0); if(pAccel->key!=0xbf) { ::GetKeyNameText(PtrToLong(lParam),szKeyName,10); } else { lstrcpy(szKeyName,_T("Slash")); } sKey+=szKeyName; } else { sKey+=(TCHAR)pAccel->key; } return sKey; } BOOL COXShortkeysOrganizer::GetAccelKeyFromString(LPCTSTR lpszString, ACCEL* pAccel) { ASSERT(lpszString!=NULL); ASSERT(pAccel!=NULL); CString sKey=lpszString; sKey.TrimLeft(); sKey.TrimRight(); if(sKey.IsEmpty()) return FALSE; pAccel->fVirt=FVIRTKEY; pAccel->cmd=0; int nPlusPos=sKey.Find(_T("+")); while(nPlusPos!=-1) { CString sSystemKey=sKey.Left(nPlusPos); sKey=sKey.Mid(nPlusPos+1); if(sSystemKey.CompareNoCase(_T("Shift"))==0) pAccel->fVirt|=FSHIFT; else if(sSystemKey.CompareNoCase(_T("Ctrl"))==0) pAccel->fVirt|=FCONTROL; else if(sSystemKey.CompareNoCase(_T("Alt"))==0) pAccel->fVirt|=FALT; if(sKey.GetLength()==1) break; else nPlusPos=sKey.Find(_T("+")); if(nPlusPos==sKey.GetLength()-1) break; } if(sKey.GetLength()==1) { if(sKey.GetAt(0)==_T('/')) { pAccel->key=VK_DIVIDE; } else { SHORT vkKey=::VkKeyScan(sKey.GetAt(0));; pAccel->key=LOBYTE(vkKey); } } else if(sKey.CompareNoCase(_T("Slash"))==0) { pAccel->key=0xbf; } else if(sKey.CompareNoCase(_T("Enter"))==0) { pAccel->key=VK_RETURN; } else if(sKey.CompareNoCase(_T("End"))==0) { pAccel->key=VK_END; } else if(sKey.CompareNoCase(_T("Insert"))==0) { pAccel->key=VK_INSERT; } else if(sKey.CompareNoCase(_T("Del"))==0) { pAccel->key=VK_DELETE; } else if(sKey.CompareNoCase(_T("Home"))==0) { pAccel->key=VK_HOME; } else if(sKey.CompareNoCase(_T("Page Up"))==0) { pAccel->key=VK_PRIOR; } else if(sKey.CompareNoCase(_T("Page Down"))==0) { pAccel->key=VK_NEXT; } else if(sKey.CompareNoCase(_T("Esc"))==0) { pAccel->key=VK_ESCAPE; } else if(sKey.CompareNoCase(_T("Up"))==0) { pAccel->key=VK_UP; } else if(sKey.CompareNoCase(_T("Down"))==0) { pAccel->key=VK_DOWN; } else if(sKey.CompareNoCase(_T("Right"))==0) { pAccel->key=VK_RIGHT; } else if(sKey.CompareNoCase(_T("Left"))==0) { pAccel->key=VK_LEFT; } else if(sKey.CompareNoCase(_T("F1"))==0) { pAccel->key=VK_F1; } else if(sKey.CompareNoCase(_T("F2"))==0) { pAccel->key=VK_F2; } else if(sKey.CompareNoCase(_T("F3"))==0) { pAccel->key=VK_F3; } else if(sKey.CompareNoCase(_T("F4"))==0) { pAccel->key=VK_F4; } else if(sKey.CompareNoCase(_T("F5"))==0) { pAccel->key=VK_F5; } else if(sKey.CompareNoCase(_T("F6"))==0) { pAccel->key=VK_F6; } else if(sKey.CompareNoCase(_T("F7"))==0) { pAccel->key=VK_F7; } else if(sKey.CompareNoCase(_T("F8"))==0) { pAccel->key=VK_F8; } else if(sKey.CompareNoCase(_T("F9"))==0) { pAccel->key=VK_F9; } else if(sKey.CompareNoCase(_T("F10"))==0) { pAccel->key=VK_F10; } else if(sKey.CompareNoCase(_T("F11"))==0) { pAccel->key=VK_F11; } else if(sKey.CompareNoCase(_T("F12"))==0) { pAccel->key=VK_F12; } else if(sKey.CompareNoCase(_T("Num 0"))==0) { pAccel->key=VK_NUMPAD0; } else if(sKey.CompareNoCase(_T("Num 1"))==0) { pAccel->key=VK_NUMPAD1; } else if(sKey.CompareNoCase(_T("Num 2"))==0) { pAccel->key=VK_NUMPAD2; } else if(sKey.CompareNoCase(_T("Num 3"))==0) { pAccel->key=VK_NUMPAD3; } else if(sKey.CompareNoCase(_T("Num 4"))==0) { pAccel->key=VK_NUMPAD4; } else if(sKey.CompareNoCase(_T("Num 5"))==0) { pAccel->key=VK_NUMPAD5; } else if(sKey.CompareNoCase(_T("Num 6"))==0) { pAccel->key=VK_NUMPAD6; } else if(sKey.CompareNoCase(_T("Num 7"))==0) { pAccel->key=VK_NUMPAD7; } else if(sKey.CompareNoCase(_T("Num 8"))==0) { pAccel->key=VK_NUMPAD8; } else if(sKey.CompareNoCase(_T("Num 9"))==0) { pAccel->key=VK_NUMPAD9; } else if(sKey.CompareNoCase(_T("Num /"))==0) { pAccel->key=VK_DIVIDE; } else if(sKey.CompareNoCase(_T("Num *"))==0) { pAccel->key=VK_MULTIPLY; } else if(sKey.CompareNoCase(_T("Num -"))==0) { pAccel->key=VK_SUBTRACT; } else if(sKey.CompareNoCase(_T("Num +"))==0) { pAccel->key=VK_ADD; } else { return FALSE; } return TRUE; } BOOL COXShortkeysOrganizer::AddAccelTable(HACCEL hAccelTable, CMultiDocTemplate* pDocTemplate) { ASSERT(hAccelTable!=NULL); if(!IsAttached()) { TRACE(_T("COXShortkeysOrganizer::AddAccelTable: there is no attached frame window. You have to attach frame window before calling this function\n")); return FALSE; } COXArrAccelerators* pArrAccels=FindAcceleratorTable(pDocTemplate); if(pArrAccels!=NULL) { TRACE(_T("COXShortkeysOrganizer::AddAccelTable: accelerator table for specified CMultiDocTemplate object has already been added\n")); return FALSE; } OXACCELTABLE accelTable; accelTable.m_docTemplate=pDocTemplate; int nAccelCount=::CopyAcceleratorTable(hAccelTable,NULL,0); if(nAccelCount!=0) { ACCEL* pAccel=new ACCEL[nAccelCount]; if (pAccel==NULL) { TRACE(_T("COXShortkeysOrganizer::AddAccelTable: failed to copy an accelerator table\n")); return FALSE; } VERIFY(::CopyAcceleratorTable(hAccelTable,pAccel,nAccelCount)==nAccelCount); for(int nIndex=0; nIndexGetSize()]; if(pAccelTable==NULL) { TRACE(_T("COXShortkeysOrganizer::BuildAccelTable: failed to allocate memory for new accelerator table\n")); return NULL; } for(int nIndex=0; nIndexGetSize(); nIndex++) { pAccelTable[nIndex].fVirt=pArrAccels->GetAt(nIndex).fVirt; pAccelTable[nIndex].key=pArrAccels->GetAt(nIndex).key; pAccelTable[nIndex].cmd=pArrAccels->GetAt(nIndex).cmd; } HACCEL hNewTable=::CreateAcceleratorTable(pAccelTable,PtrToInt(pArrAccels->GetSize())); m_arrCreatedAccel.Add(hNewTable); delete[] pAccelTable; return hNewTable; } void COXShortkeysOrganizer::SerializeAccelTable(CArchive& ar, OXACCELTABLE* pAccelTable) { ASSERT(pAccelTable!=NULL); if(ar.IsStoring()) { ar<<(DWORD)pAccelTable->m_accelerators.GetSize(); for(int nIndex=0; nIndexm_accelerators.GetSize(); nIndex++) { ACCEL accel=pAccelTable->m_accelerators[nIndex]; ar<>dwAccelCount; pAccelTable->m_accelerators.SetSize(dwAccelCount); for(int nIndex=0; nIndex<(int)dwAccelCount; nIndex++) { ACCEL accel; ar>>accel.fVirt; ar>>accel.key; ar>>accel.cmd; pAccelTable->m_accelerators.SetAt(nIndex,accel); } } }