⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 macros.cpp

📁 MudMaster 2000 的C++源码
💻 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 + -