mirror of https://github.com/roytam1/kmeleon.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
484 lines
11 KiB
484 lines
11 KiB
/* |
|
* Copyright (C) 2000 Brian Harris |
|
* Copyright (C) 2006 Dorian Boissonnade |
|
* |
|
* This program is free software; you can redistribute it and/or modify |
|
* it under the terms of the GNU General Public License as published by |
|
* the Free Software Foundation; either version 2, or (at your option) |
|
* any later version. |
|
* |
|
* This program is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License |
|
* along with this program; if not, write to the Free Software |
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
*/ |
|
|
|
#include "StdAfx.h" |
|
|
|
#include "MfcEmbed.h" |
|
|
|
#include "AccelParser.h" |
|
#include "Utils.h" |
|
#include "resource.h" |
|
#include "Plugins.h" |
|
|
|
|
|
#define BEGIN_VK_TEST if (0){} |
|
#define VK_TEST(KEY) else if (stricmp(p, #KEY) == 0){ key = VK_##KEY; } |
|
|
|
// a few that winuser.h doesn't have for some reason (snagged from msdn) |
|
#define VK_OEM_PLUS 0xBB |
|
#define VK_OEM_COMMA 0xBC |
|
#define VK_OEM_MINUS 0xBD |
|
#define VK_OEM_PERIOD 0xBE |
|
// and some more friendly definitions... |
|
#define VK_PLUS VK_OEM_PLUS |
|
#define VK_EQUALS VK_OEM_PLUS |
|
#define VK_MINUS VK_OEM_MINUS |
|
#define VK_COMMA VK_OEM_COMMA |
|
#define VK_PERIOD VK_OEM_PERIOD |
|
#define VK_PERIOD VK_OEM_PERIOD |
|
#define VK_PAGE_UP VK_PRIOR |
|
#define VK_PAGE_DOWN VK_NEXT |
|
|
|
//Standard accel to show in menu |
|
|
|
static const ACCEL stdAccels[] = { |
|
{FCONTROL, 'C', ID_EDIT_COPY}, |
|
{FCONTROL, 'V', ID_EDIT_PASTE}, |
|
{FCONTROL, 'X', ID_EDIT_CUT}, |
|
{FVIRTKEY|FALT, VK_F4, ID_FILE_CLOSE} |
|
}; |
|
|
|
extern BOOL ParsePluginCommand(char *pszCommand, char** plugin, char **parameter); |
|
|
|
CAccelParser::CAccelParser() |
|
{ |
|
accelTable = NULL; |
|
numAccelerators = 0; |
|
memset(accelerators, 0, sizeof(ACCEL) * MAX_ACCEL); |
|
numMKeys = 0; |
|
memset(mouse, 0, sizeof(ACCEL) * MAX_MOUSE); |
|
} |
|
|
|
CAccelParser::CAccelParser(LPCTSTR filename) |
|
{ |
|
accelTable = NULL; |
|
numAccelerators = 0; |
|
memset(accelerators, 0, sizeof(ACCEL) * MAX_ACCEL); |
|
|
|
Load(filename); |
|
} |
|
|
|
CAccelParser::~CAccelParser() |
|
{ |
|
if (accelTable){ |
|
DestroyAcceleratorTable(accelTable); |
|
} |
|
} |
|
|
|
int CAccelParser::Load(LPCTSTR filename) |
|
{ |
|
SETUP_LOG("Accel"); |
|
|
|
if (accelTable){ |
|
DestroyAcceleratorTable(accelTable); |
|
accelTable = NULL; |
|
numAccelerators = 0; |
|
} |
|
|
|
int retVal = CParser::Load(filename); |
|
|
|
END_LOG(); |
|
|
|
return retVal; |
|
} |
|
|
|
int CAccelParser::Parse(char *p) |
|
{ |
|
// <modifiers> <key> = <command> |
|
char *e = strchr(p, '='); |
|
if (e){ |
|
*e = 0; |
|
e++; |
|
e = SkipWhiteSpace(e); |
|
TrimWhiteSpace(e); |
|
TrimWhiteSpace(p); |
|
return SetAccel(p, e); |
|
} |
|
return 0; |
|
} |
|
|
|
int CAccelParser::SetAccel(const char* pKey, const char* pCommand) |
|
{ |
|
int command = 0; |
|
const char *alt, *ctrl, *shift; |
|
const char* p; |
|
BYTE virt; |
|
int key; |
|
|
|
command = theApp.commands.GetId(pCommand); |
|
if (!command) { |
|
LOG_ERROR_1( "Command %s is unknow", pCommand); |
|
//return 0; |
|
} |
|
|
|
virt = 0; |
|
p = pKey; |
|
alt = strstr(pKey, "ALT"); |
|
if (alt){ |
|
virt |= FALT; |
|
p = alt + 3; |
|
} |
|
ctrl = strstr(pKey, "CTRL"); |
|
if (ctrl){ |
|
virt |= FCONTROL; |
|
if (ctrl > alt){ |
|
p = ctrl + 4; |
|
} |
|
} |
|
shift = strstr(pKey, "SHIFT"); |
|
if (shift){ |
|
virt |= FSHIFT; |
|
if ((shift > alt) && (shift > ctrl)){ |
|
p = shift + 5; |
|
} |
|
} |
|
|
|
// by now, p should be past the modifiers and point to " <key>" |
|
p = SkipWhiteSpace((char*)p); |
|
|
|
if (strncmp(p, "VK_", 3) == 0){ |
|
p+=3; |
|
key = 0; |
|
|
|
// these should be in order of frequency of use to speed up parsing |
|
BEGIN_VK_TEST |
|
|
|
VK_TEST(ESCAPE) |
|
VK_TEST(LEFT) |
|
VK_TEST(RIGHT) |
|
|
|
VK_TEST(F1) |
|
VK_TEST(F2) |
|
VK_TEST(F3) |
|
VK_TEST(F4) |
|
VK_TEST(F5) |
|
VK_TEST(F6) |
|
VK_TEST(F7) |
|
VK_TEST(F8) |
|
VK_TEST(F9) |
|
VK_TEST(F10) |
|
VK_TEST(F11) |
|
VK_TEST(F12) |
|
|
|
VK_TEST(HOME) |
|
VK_TEST(END) |
|
|
|
VK_TEST(PRIOR) // page up |
|
VK_TEST(NEXT) // page down |
|
VK_TEST(PAGE_UP) |
|
VK_TEST(PAGE_DOWN) |
|
VK_TEST(UP) |
|
VK_TEST(DOWN) |
|
VK_TEST(INSERT) |
|
VK_TEST(DELETE) |
|
VK_TEST(SPACE) |
|
VK_TEST(HELP) |
|
VK_TEST(EXECUTE) |
|
VK_TEST(SELECT) |
|
VK_TEST(PRINT) |
|
VK_TEST(SNAPSHOT) // print screen? |
|
|
|
VK_TEST(PLUS) |
|
VK_TEST(MINUS) |
|
VK_TEST(COMMA) |
|
VK_TEST(PERIOD) |
|
VK_TEST(EQUALS) |
|
|
|
VK_TEST(BACK) |
|
VK_TEST(TAB) |
|
VK_TEST(CLEAR) |
|
|
|
VK_TEST(RETURN) |
|
|
|
VK_TEST(MULTIPLY) |
|
VK_TEST(ADD) |
|
VK_TEST(SUBTRACT) |
|
VK_TEST(DECIMAL) |
|
VK_TEST(DIVIDE) |
|
VK_TEST(SEPARATOR) |
|
|
|
VK_TEST(PAUSE) |
|
VK_TEST(CAPITAL) |
|
VK_TEST(MENU) |
|
|
|
VK_TEST(BROWSER_BACK) |
|
VK_TEST(BROWSER_FORWARD) |
|
VK_TEST(BROWSER_REFRESH) |
|
VK_TEST(BROWSER_STOP) |
|
VK_TEST(BROWSER_SEARCH) |
|
VK_TEST(BROWSER_FAVORITES) |
|
VK_TEST(BROWSER_HOME) |
|
|
|
/* |
|
VK_TEST(KANA) |
|
VK_TEST(JUNJA) |
|
VK_TEST(FINAL) |
|
VK_TEST(HANJA) |
|
VK_TEST(KANJI) |
|
|
|
VK_TEST(CONVERT) |
|
VK_TEST(NONCONVERT) |
|
VK_TEST(ACCEPT) |
|
VK_TEST(MODECHANGE) |
|
*/ |
|
|
|
VK_TEST(LWIN) |
|
VK_TEST(RWIN) |
|
VK_TEST(APPS) |
|
|
|
VK_TEST(NUMPAD0) |
|
VK_TEST(NUMPAD1) |
|
VK_TEST(NUMPAD2) |
|
VK_TEST(NUMPAD3) |
|
VK_TEST(NUMPAD4) |
|
VK_TEST(NUMPAD5) |
|
VK_TEST(NUMPAD6) |
|
VK_TEST(NUMPAD7) |
|
VK_TEST(NUMPAD8) |
|
VK_TEST(NUMPAD9) |
|
|
|
/* |
|
VK_TEST(F13) |
|
VK_TEST(F14) |
|
VK_TEST(F15) |
|
VK_TEST(F16) |
|
VK_TEST(F17) |
|
VK_TEST(F18) |
|
VK_TEST(F19) |
|
VK_TEST(F20) |
|
VK_TEST(F21) |
|
VK_TEST(F22) |
|
VK_TEST(F23) |
|
VK_TEST(F24) |
|
*/ |
|
|
|
VK_TEST(NUMLOCK) |
|
VK_TEST(SCROLL) |
|
} |
|
else if (stricmp(p, "LButton") == 0){ |
|
SetMAccel(command, virt, WM_LBUTTONDOWN); |
|
return true; |
|
} |
|
else if (stricmp(p, "MButton") == 0){ |
|
SetMAccel(command, virt, WM_MBUTTONDOWN); |
|
return true; |
|
} |
|
else if (stricmp(p, "RButton") == 0){ |
|
SetMAccel(command, virt, WM_RBUTTONDOWN); |
|
return true; |
|
} |
|
else { |
|
// regular key, convert it to virtual-key code to |
|
// get the associated key on the keyboard. |
|
key = VkKeyScanA(*p) & 0xff; |
|
} |
|
|
|
virt |= FVIRTKEY; |
|
SetAccel(command, virt, key); |
|
LOG_2("Added accelerator %s with command %s", pKey, pCommand); |
|
|
|
return true; |
|
} |
|
|
|
void CAccelParser::SetAccel(WORD command, BYTE virt, WORD key) |
|
{ |
|
int oldAccel = FindAccel(virt, key); |
|
if (command != 0 && oldAccel == -1) { |
|
if (numAccelerators == MAX_ACCEL) return; |
|
accelerators[numAccelerators].cmd = command; |
|
accelerators[numAccelerators].fVirt = virt; |
|
accelerators[numAccelerators].key = key; |
|
numAccelerators++; |
|
} |
|
else { |
|
if (command != 0) |
|
accelerators[oldAccel].cmd = command; |
|
else if (oldAccel>=0) |
|
DeleteAccel(oldAccel); |
|
} |
|
if (accelTable) { |
|
DestroyAcceleratorTable(accelTable); |
|
accelTable = NULL; |
|
} |
|
} |
|
|
|
void CAccelParser::SetMAccel(WORD command, BYTE virt, WORD button) |
|
{ |
|
int oldAccel = FindMAccel(virt, button); |
|
if (command == 0) { |
|
if(oldAccel != -1) |
|
DeleteMAccel(oldAccel); |
|
return; |
|
} |
|
|
|
if (oldAccel != -1) { |
|
mouse[oldAccel].cmd = command; |
|
return; |
|
} |
|
|
|
if (numMKeys == MAX_MOUSE) return; |
|
mouse[numMKeys].cmd = command; |
|
mouse[numMKeys].fVirt = virt; |
|
mouse[numMKeys].key = button; |
|
numMKeys++; |
|
} |
|
|
|
void CAccelParser::DeleteMAccel(int idx) |
|
{ |
|
ASSERT(idx>=0&&idx<=MAX_MOUSE); |
|
int i; |
|
--numMKeys; |
|
for (i=idx;i<numMKeys;i++) |
|
mouse[i] = mouse[i+1]; |
|
} |
|
|
|
void CAccelParser::DeleteAccel(int idx) |
|
{ |
|
ASSERT(idx>=0&&idx<=MAX_ACCEL); |
|
int i; |
|
--numAccelerators; |
|
for (i=idx;i<numAccelerators;i++) |
|
accelerators[i] = accelerators[i+1]; |
|
} |
|
|
|
int CAccelParser::FindMAccel(WORD virt, DWORD key) |
|
{ |
|
const ACCEL* accel = NULL; |
|
|
|
for (int i=0;i<numAccelerators;i++) |
|
if (mouse[i].key == key && mouse[i].fVirt == virt) |
|
return i; |
|
|
|
return -1; |
|
} |
|
|
|
int CAccelParser::FindAccel(WORD virt, DWORD key) |
|
{ |
|
const ACCEL* accel = NULL; |
|
|
|
for (int i=0;i<numAccelerators;i++) |
|
if (accelerators[i].key == key && accelerators[i].fVirt == virt) |
|
return i; |
|
|
|
return -1; |
|
} |
|
|
|
HACCEL CAccelParser::GetTable(){ |
|
if (!accelTable){ |
|
accelTable = CreateAcceleratorTable(accelerators, numAccelerators); |
|
} |
|
return accelTable; |
|
} |
|
|
|
CString CAccelParser::GetStrAccel(UINT id) |
|
{ |
|
const ACCEL* accel = NULL; |
|
|
|
for (int i=0;i<numAccelerators;i++) { |
|
if (accelerators[i].cmd == id) { |
|
accel = &accelerators[i]; |
|
break; |
|
} |
|
} |
|
|
|
if (!accel) { |
|
for (int i=0;i<sizeof(stdAccels)/sizeof(ACCEL);i++) { |
|
if (stdAccels[i].cmd == id) { |
|
accel = &stdAccels[i]; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
if (accel) { |
|
CString str; |
|
TCHAR buf[25]; |
|
if(accel->fVirt & FCONTROL) { |
|
GetKeyNameText(MapVirtualKey(VK_CONTROL, 0)<<16, buf, sizeof(buf) / sizeof(TCHAR)); |
|
if (*buf) { |
|
CharLowerBuff(buf+1, _tcslen(buf)-1); |
|
str = str + buf + _T("+"); |
|
} |
|
} |
|
if(accel->fVirt & FSHIFT) { |
|
GetKeyNameText(MapVirtualKey(VK_SHIFT, 0)<<16, buf, sizeof(buf) / sizeof(TCHAR)); |
|
if (*buf) { |
|
CharLowerBuff(buf+1, _tcslen(buf)-1); |
|
str = str + buf + _T("+"); |
|
} |
|
} |
|
if(accel->fVirt & FALT) { |
|
GetKeyNameText(MapVirtualKey(VK_MENU, 0)<<16, buf, sizeof(buf) / sizeof(TCHAR)); |
|
if (*buf) { |
|
CharLowerBuff(buf+1, _tcslen(buf)-1); |
|
str = str + buf + _T("+"); |
|
} |
|
} |
|
if(accel->fVirt & FVIRTKEY) { |
|
WORD key = accel->key; |
|
UINT scan = MapVirtualKey(key, 0); |
|
if ((key >= VK_PRIOR) && (key<=VK_DELETE)) |
|
scan |= 0x100; // should remove the numpad text |
|
|
|
if (GetKeyNameText(scan<<16 , buf, sizeof(buf) / sizeof(TCHAR)) == 0) |
|
return _T(""); |
|
|
|
// Since I can't find a way to remove the numpad indication |
|
// for /,* or . I'm removing it the hard way. |
|
TCHAR* parenthesis = _tcschr(buf, '('); |
|
if (parenthesis && parenthesis>buf) |
|
*parenthesis = 0; |
|
|
|
if (*buf) { |
|
CharLowerBuff(buf+1, _tcslen(buf)-1); |
|
str += buf; |
|
} |
|
} |
|
else { |
|
char c[2] = { accel->key & 0xff, '\0' }; |
|
USES_CONVERSION; |
|
str += A2CT(c); |
|
} |
|
return str; |
|
} |
|
|
|
return _T(""); |
|
} |
|
|
|
int CAccelParser::CheckMouse(UINT message){ |
|
|
|
int i, virt = 0; |
|
virt = message >> 8; |
|
switch (message & 0xff) { |
|
case MK_LBUTTON: message = WM_LBUTTONDOWN; break; |
|
case MK_RBUTTON: message = WM_RBUTTONDOWN; break; |
|
case MK_MBUTTON: message = WM_MBUTTONDOWN; break; |
|
default : ; |
|
} |
|
|
|
|
|
|
|
for (i=0; i<numMKeys; i++) { |
|
if (mouse[i].key == message) { |
|
if (mouse[i].fVirt == virt) |
|
return mouse[i].cmd; |
|
} |
|
} |
|
return 0; |
|
}
|
|
|