📄 macros.cpp
字号:
/************************************************************************************
Copyright (c) 2000 Aaron O'Neil
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1) Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2) Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3) Redistributions in binary form must reproduce the above copyright notice on
program startup. Additional credits for program modification are acceptable
but original copyright and credits must be visible at startup.
4) You may charge a reasonable copying fee for any distribution of Mud Master.
You may charge any fee you choose for support of Mud Master. You may not
charge a fee for Mud Master itself.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**************************************************************************************/
#include "StdAfx.h"
#include "Extern.h"
#include "Macros.h"
#include "Keyboard.h"
KEYVALUES _keyValues[] =
{
{"f1",VK_F1},
{"f2",VK_F2},
{"f3",VK_F3},
{"f4",VK_F4},
{"f5",VK_F5},
{"f6",VK_F6},
{"f7",VK_F7},
{"f8",VK_F8},
{"f9",VK_F9},
{"f10",VK_F10},
{"f11",VK_F11},
{"f12",VK_F12},
{"del",VK_DELETE+KEYBOARD_ENHANCED},
{"kpdel",VK_DELETE},
{"kp1",VK_END},
{"kp2",VK_DOWN},
{"kp3",VK_NEXT},
{"kp4",VK_LEFT},
{"kp5",VK_CLEAR},
{"kp6",VK_RIGHT},
{"kp7",VK_HOME},
{"kp8",VK_UP},
{"kp9",VK_PRIOR},
{"kp0",VK_INSERT},
{"ins",VK_INSERT+KEYBOARD_ENHANCED},
{"home",VK_HOME+KEYBOARD_ENHANCED},
{"pgup",VK_PRIOR+KEYBOARD_ENHANCED},
{"pgdn",VK_NEXT+KEYBOARD_ENHANCED},
{"end",VK_END+KEYBOARD_ENHANCED},
{"uparrow",VK_UP+KEYBOARD_ENHANCED},
{"dnarrow",VK_DOWN+KEYBOARD_ENHANCED},
{"rtarrow",VK_RIGHT+KEYBOARD_ENHANCED},
{"ltarrow",VK_LEFT+KEYBOARD_ENHANCED},
{"kpstar",VK_MULTIPLY},
{"kpplus",VK_ADD},
{"kpminus",VK_SUBTRACT},
{"kpslash",VK_DIVIDE},
{"",0},
};
CMacros::CMacros()
{
m_ptrList.SetSize(DEFAULT_MACRO_ARRAY_SIZE,DEFAULT_MACRO_GROW_SIZE);
m_nCount = 0;
m_nGetIndex = 0;
}
CMacros::~CMacros()
{
RemoveAll();
}
void CMacros::RemoveAll()
{
MACRO *pMac;
for (int i=0;i<m_nCount;i++)
{
pMac = (MACRO *)m_ptrList.GetAt(i);
delete pMac;
}
m_ptrList.RemoveAll();
m_nCount = 0;
m_nGetIndex = 0;
}
int CMacros::RemoveGroup(const char *pszGroup)
{
MACRO *pMac;
int nCount = 0;
for (int i=m_nCount-1;i>-1;i--)
{
pMac = (MACRO *)m_ptrList.GetAt(i);
if (pMac->strGroup == pszGroup)
{
Remove(i);
nCount++;
}
}
return(nCount);
}
BOOL CMacros::Remove(const char *pszKey)
{
CString strKey(pszKey);
strKey.MakeLower();
int nKeyID = NameToKeyID(strKey);
if (!nKeyID)
return(FALSE);
MACRO *pMac;
for (int i=0;i<m_nCount;i++)
{
pMac = (MACRO *)m_ptrList.GetAt(i);
if (pMac->nKeyID == nKeyID)
{
Remove(i);
return(TRUE);
}
}
return(FALSE);
}
BOOL CMacros::Remove(int nIndex)
{
if (nIndex < 0 || nIndex >= m_nCount)
return(FALSE);
MACRO *pMac = (MACRO *)m_ptrList.GetAt(nIndex);
if (pMac == NULL)
return(FALSE);
m_ptrList.RemoveAt(nIndex);
m_nCount--;
delete pMac;
return(TRUE);
}
int CMacros::NameToKeyID(const char *pszKey)
{
CString strKey(pszKey);
// Need to first pull the key name off the right side of
// the string.
CString strName;
// Shift+Alpha is an invalid combination. Shift-a needs to
// give you an 'A' not a macro. When a key name is found that
// is an ascii char this is set to TRUE.
BOOL bAscii = FALSE;
// If it ends with a digit it must be either a function key
// or a keypad digit.
int nIndex = strKey.GetLength()-1;
if (isdigit(strKey.GetAt(nIndex)))
{
while(nIndex && isdigit(strKey.GetAt(nIndex)))
nIndex--;
// If the key isn't a p or f, then is probably a single
// digit key.
if (strKey.GetAt(nIndex) != 'p' && strKey.GetAt(nIndex) != 'f')
{
// If there was more than 1 digit, something went wrong.
if (nIndex != strKey.GetLength()-2)
return(0);
strName = strKey.Right(1);
strKey = strKey.Left(strKey.GetLength()-1);
bAscii = TRUE;
}
else
{
// After last digit has been found, it has to either
// be an 'f' or a 'p'. If it is a 'p' then need to subtract
// 1 more from the index, key name will be "kp<num>" or
// "f<num>"
if (strKey.GetAt(nIndex) == 'p')
if (nIndex)
nIndex--;
else
return(0); // Would go past head of buffer.
// Pull off the name.
strName = strKey.Right(strKey.GetLength()-nIndex);
strKey = strKey.Left(nIndex);
}
}
else
{
CString strTemp;
BOOL bFoundMatch = FALSE;
int nLen = strKey.GetLength();
for (int i=7;i>2 && !bFoundMatch;i--)
{
if (nLen >= i)
{
strTemp = strKey.Right(i);
switch(i)
{
case 7 :
if (strTemp == "kpslash")
bFoundMatch = TRUE;
if (strTemp == "kpminus")
bFoundMatch = TRUE;
if (strTemp == "uparrow")
bFoundMatch = TRUE;
if (strTemp == "dnarrow")
bFoundMatch = TRUE;
if (strTemp == "ltarrow")
bFoundMatch = TRUE;
if (strTemp == "rtarrow")
bFoundMatch = TRUE;
break;
case 6 :
if (strTemp == "kpstar")
bFoundMatch = TRUE;
if (strTemp == "kpplus")
bFoundMatch = TRUE;
break;
case 5 :
if (strTemp == "kpdel")
bFoundMatch = TRUE;
break;
case 4 :
if (strTemp == "home")
bFoundMatch = TRUE;
if (strTemp == "pgup")
bFoundMatch = TRUE;
if (strTemp == "pgdn")
bFoundMatch = TRUE;
break;
case 3 :
if (strTemp == "del")
bFoundMatch = TRUE;
if (strTemp == "ins")
bFoundMatch = TRUE;
if (strTemp == "end")
bFoundMatch = TRUE;
break;
} // switch(i)
} // if (nLen > = i)
} // for (int i=8;i>2,!bFoundMatch;i--)
// If we didn't find a match, assume it was an alpha key.
if (!bFoundMatch)
{
// Needs to have at least 1 modifier. If the length is
// 1, then there isn't one.
if (nLen < 2)
return(0);
strName = strKey.Right(1);
strKey = strKey.Left(nLen-1);
bAscii = TRUE;
}
else
{
strName = strTemp;
strKey = strKey.Left(nLen-i);
}
}
int nKeyID = KeyCodeFromName(strName);
if (!nKeyID)
return(0);
// strKey should now be equal to the modifiers if there were
// any.
BOOL bAlt = FALSE;
BOOL bShift = FALSE;
BOOL bCtrl = FALSE;
int nLen = strKey.GetLength();
for (int i=0;i<nLen;i++)
{
switch(strKey.GetAt(i))
{
case 'a' :
bAlt = TRUE;
break;
case 's' :
bShift = TRUE;
break;
case 'c' :
bCtrl = TRUE;
break;
}
}
if (bAlt)
nKeyID += KEYBOARD_ALT;
if (bShift)
nKeyID += KEYBOARD_SHIFT;
if (bCtrl)
nKeyID += KEYBOARD_CONTROL;
// There are a bunch of keys people shouldn't be able to define.
// These are the keys the client used to do stuff. For example
// up-arrow starts scrollback, remapping that one would be stupid.
switch(nKeyID)
{
case VK_UP + KEYBOARD_ENHANCED : // Up arrow.
case VK_DOWN + KEYBOARD_ENHANCED : // Down arrow.
case VK_UP + KEYBOARD_ENHANCED + KEYBOARD_ALT : // Alt up arrow.
case VK_HOME + KEYBOARD_ENHANCED : // Home.
case VK_END + KEYBOARD_ENHANCED : // End.
case VK_RIGHT + KEYBOARD_ENHANCED : // Right arrow.
case VK_LEFT + KEYBOARD_ENHANCED : // Left arrow.
case VK_RIGHT + KEYBOARD_ENHANCED + KEYBOARD_CONTROL : // Ctrl+right arrow
case VK_LEFT + KEYBOARD_ENHANCED + KEYBOARD_CONTROL : // Ctrl+left arrow.
case 'X' + KEYBOARD_CONTROL : // Ctrl+x.
case 'C' + KEYBOARD_CONTROL : // Ctrl+c.
case ']' + KEYBOARD_CONTROL : // Ctrl+].
nKeyID = 0;
break;
}
// Make sure if an ASCII character that they aren't trying to
// define a macro with just a shifted state.
if (bAscii && bShift)
if (!bAlt && !bCtrl)
nKeyID = 0;
return(nKeyID);
}
int CMacros::KeyCodeFromName(const char *pszKey)
{
if (*(pszKey+1) == '\x0')
{
// Now that I'm using virtual key codes, there are a bunch
// of combinations that return OEM specific codes. Modifed
// single keys that are not digits or alpha return funky
// OEM codes.
if (isalpha(*pszKey) && islower(*pszKey))
return(toupper(*pszKey));
if (isdigit(*pszKey))
return(*pszKey);
return(0);
}
else
for (int i=0;_keyValues[i].nKeyCode;i++)
if (!strcmp(pszKey,_keyValues[i].szKeyName))
return(_keyValues[i].nKeyCode);
return(0);
}
BOOL CMacros::Assign(const char *pszKey, const char *pszText,
const char *pszGroup)
{
CString strKey(pszKey);
strKey.MakeLower();
int nKeyID = NameToKeyID(strKey);
if (!nKeyID)
return(FALSE);
// Macro text with a semicolon at the end means you want to have
// the macro text in the input line, not sent to the mud.
BOOL bSend = TRUE;
int nLen = strlen(pszText);
if (nLen > 1)
if (*(pszText+nLen-1) == ';' && *(pszText+nLen-2) != _config.chEscape)
bSend = FALSE;
// Macro text with a colon means send to input line with a carriage
// return.
BOOL bCR = FALSE;
if (nLen > 1)
if (*(pszText+nLen-1) == ':' && *(pszText+nLen-2) != _config.chEscape)
{
bSend = FALSE;
bCR = TRUE;
}
MACRO *pMac;
for (int i=0;i<m_nCount;i++)
{
pMac = (MACRO *)m_ptrList.GetAt(i);
// Replace the existing event.
if (pMac->strKeyName == strKey)
{
pMac->strText = pszText;
pMac->strGroup = pszGroup;
pMac->bSend = bSend;
pMac->bCR = bCR;
return(TRUE);
}
// Insert a new event.
if (pMac->strKeyName > strKey)
{
MACRO *pNew = new MACRO;
pNew->strKeyName = strKey;
pNew->strText = pszText;
pNew->nKeyID = nKeyID;
pNew->strGroup = pszGroup;
pNew->bEnabled = TRUE;
pNew->bSend = bSend;
pNew->bCR = bCR;
m_ptrList.InsertAt(i,pNew);
m_nCount++;
return(TRUE);
}
}
// Add it to the tail.
MACRO *pNew = new MACRO;
pNew->strKeyName = strKey;
pNew->strText = pszText;
pNew->nKeyID = nKeyID;
pNew->strGroup = pszGroup;
pNew->bEnabled = TRUE;
pNew->bSend = bSend;
pNew->bCR = bCR;
m_ptrList.SetAtGrow(i,pNew);
m_nCount++;
return(TRUE);
}
BOOL CMacros::DisableMacro(const char *pszKey)
{
CString strKey(pszKey);
strKey.MakeLower();
int nKeyID = NameToKeyID(strKey);
if (!nKeyID)
return(FALSE);
MACRO *pMac;
for (int i=0;i<m_nCount;i++)
{
pMac = (MACRO *)m_ptrList.GetAt(i);
if (pMac->nKeyID == nKeyID)
{
pMac->bEnabled = FALSE;
return(TRUE);
}
}
return(FALSE);
}
BOOL CMacros::EnableMacro(const char *pszKey)
{
CString strKey(pszKey);
strKey.MakeLower();
int nKeyID = NameToKeyID(strKey);
if (!nKeyID)
return(FALSE);
MACRO *pMac;
for (int i=0;i<m_nCount;i++)
{
pMac = (MACRO *)m_ptrList.GetAt(i);
if (pMac->nKeyID == nKeyID)
{
pMac->bEnabled = TRUE;
return(TRUE);
}
}
return(FALSE);
}
int CMacros::DisableGroup(const char *pszGroup)
{
MACRO *pMac;
int nCount = 0;
for (int i=0;i<m_nCount;i++)
{
pMac = (MACRO *)m_ptrList.GetAt(i);
if (pMac->strGroup == pszGroup)
{
pMac->bEnabled = FALSE;
nCount++;
}
}
return(nCount);
}
int CMacros::EnableGroup(const char *pszGroup)
{
MACRO *pMac;
int nCount = 0;
for (int i=0;i<m_nCount;i++)
{
pMac = (MACRO *)m_ptrList.GetAt(i);
if (pMac->strGroup == pszGroup)
{
pMac->bEnabled = TRUE;
nCount++;
}
}
return(nCount);
}
MACRO* CMacros::GetFirst()
{
if (!m_nCount)
return(NULL);
m_nGetIndex = 0;
return((MACRO *)m_ptrList.GetAt(m_nGetIndex));
}
MACRO* CMacros::GetNext()
{
if (m_nGetIndex+1 == m_nCount)
return(NULL);
m_nGetIndex++;
return((MACRO *)m_ptrList.GetAt(m_nGetIndex));
}
MACRO* CMacros::GetAt(int nIndex)
{
if (nIndex < 0 || nIndex >= m_nCount)
return(NULL);
return((MACRO *)m_ptrList.GetAt(nIndex));
}
MACRO* CMacros::FindKeyByName(const char *pszKey)
{
CString strKey(pszKey);
strKey.MakeLower();
int nKeyID = NameToKeyID(strKey);
if (!nKeyID)
return(NULL);
MACRO *pMac;
for (int i=0;i<m_nCount;i++)
{
pMac = (MACRO *)m_ptrList.GetAt(i);
if (pMac->nKeyID == nKeyID)
return(pMac);
}
return(NULL);
}
MACRO* CMacros::FindKeyByValue(KEYBOARDCHAR &kbch)
{
MACRO *pMac;
for (int i=0;i<m_nCount;i++)
{
pMac = (MACRO *)m_ptrList.GetAt(i);
if (pMac->nKeyID == kbch.wKeyID)
return(pMac);
}
return(NULL);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -