Files
envi-code/SourceCode/Code2026/EarthWormMain/CmdQuery.cpp
T
2026-09-28 15:28:50 +08:00

448 lines
12 KiB
C++

#include "StdAfx.h"
#include "CmdQuery.h"
#include "CoreTools.h"
#include <sstream>
#include <fstream>
#include<algorithm>
#include "initools.h"
namespace
{
using namespace CmdQuery;
MnuFiles g_mnuFiles;
std::map<WPARAM, CString> g_VKTable;
std::set<WPARAM> g_hotkeys;
#if ARX > 22
static bool InputKeyWord(MSG* msg)
#else
static BOOL InputKeyWord(MSG* msg)
#endif
{
BOOL bRet = FALSE;
if (!acdbCurDwg())
{
return bRet;
}
// 没有关键字输入的时候支持判断结果
switch (msg->message)
{
case WM_KEYDOWN: // 键盘输入关键字
{
std::set<WPARAM>::const_iterator it = g_hotkeys.begin();
for (; it != g_hotkeys.end(); ++it)
{
if (!(GetKeyState(*it) & 0x8000))
return FALSE;
}
acedPostCommand(_T("cmds "));
return TRUE;
}
break;
default:
break;
}
return FALSE;
}
bool isNormalKey(WPARAM key)
{
if (key != VK_ESCAPE
&& key != VK_TAB
&& key != VK_CAPITAL
&& key != VK_SHIFT
&& key != VK_CONTROL
&& key != VK_LWIN
&& key != VK_RWIN
&& key != VK_MENU
&& key != VK_RETURN
&& key != VK_BACK )
return true;
return false;
}
int initVKTable()
{
g_VKTable.clear();
g_VKTable.insert(std::make_pair(VK_F1, _T("F1")));
g_VKTable.insert(std::make_pair(VK_F2, _T("F2")));
g_VKTable.insert(std::make_pair(VK_F3, _T("F3")));
g_VKTable.insert(std::make_pair(VK_F4, _T("F4")));
g_VKTable.insert(std::make_pair(VK_F5, _T("F5")));
g_VKTable.insert(std::make_pair(VK_F6, _T("F6")));
g_VKTable.insert(std::make_pair(VK_F7, _T("F7")));
g_VKTable.insert(std::make_pair(VK_F8, _T("F8")));
g_VKTable.insert(std::make_pair(VK_F9, _T("F9")));
g_VKTable.insert(std::make_pair(VK_F10, _T("F10")));
g_VKTable.insert(std::make_pair(VK_F11, _T("F11")));
g_VKTable.insert(std::make_pair(VK_F12, _T("F12")));
g_VKTable.insert(std::make_pair(VK_NUMPAD0, _T("Num0")));
g_VKTable.insert(std::make_pair(VK_NUMPAD1, _T("Num1")));
g_VKTable.insert(std::make_pair(VK_NUMPAD2, _T("Num2")));
g_VKTable.insert(std::make_pair(VK_NUMPAD3, _T("Num3")));
g_VKTable.insert(std::make_pair(VK_NUMPAD4, _T("Num4")));
g_VKTable.insert(std::make_pair(VK_NUMPAD5, _T("Num5")));
g_VKTable.insert(std::make_pair(VK_NUMPAD6, _T("Num6")));
g_VKTable.insert(std::make_pair(VK_NUMPAD7, _T("Num7")));
g_VKTable.insert(std::make_pair(VK_NUMPAD8, _T("Num8")));
g_VKTable.insert(std::make_pair(VK_NUMPAD9, _T("Num9")));
g_VKTable.insert(std::make_pair(VK_MULTIPLY, _T("*")));
g_VKTable.insert(std::make_pair(VK_ADD, _T("+")));
g_VKTable.insert(std::make_pair(VK_SEPARATOR, _T("SEP")));
g_VKTable.insert(std::make_pair(VK_SUBTRACT, _T("-")));
g_VKTable.insert(std::make_pair(VK_DECIMAL, _T(".")));
g_VKTable.insert(std::make_pair(VK_DIVIDE, _T("/")));
g_VKTable.insert(std::make_pair(VK_NUMLOCK, _T("NumLock")));
g_VKTable.insert(std::make_pair(VK_SCROLL, _T("SCR")));
g_VKTable.insert(std::make_pair(VK_PAUSE, _T("PAU")));
g_VKTable.insert(std::make_pair(VK_ESCAPE, _T("ESC")));
g_VKTable.insert(std::make_pair(VK_RETURN, _T("RET")));
g_VKTable.insert(std::make_pair(VK_TAB, _T("TAB")));
g_VKTable.insert(std::make_pair(VK_CAPITAL, _T("CAP")));
g_VKTable.insert(std::make_pair(VK_SHIFT, _T("SHIFT")));
g_VKTable.insert(std::make_pair(VK_CONTROL, _T("CTRL")));
g_VKTable.insert(std::make_pair(VK_MENU, _T("ALT")));
g_VKTable.insert(std::make_pair(VK_SPACE, _T("SPA")));
g_VKTable.insert(std::make_pair(VK_BACK, _T("BACK")));
g_VKTable.insert(std::make_pair(VK_LWIN, _T("LWIN")));
g_VKTable.insert(std::make_pair(VK_RWIN, _T("RWIN")));
g_VKTable.insert(std::make_pair(VK_INSERT, _T("INS")));
g_VKTable.insert(std::make_pair(VK_HOME, _T("HOME")));
g_VKTable.insert(std::make_pair(VK_PRIOR, _T("PAUP")));
g_VKTable.insert(std::make_pair(VK_NEXT, _T("PADN")));
g_VKTable.insert(std::make_pair(VK_END, _T("END")));
g_VKTable.insert(std::make_pair(VK_DELETE, _T("DEL")));
g_VKTable.insert(std::make_pair(VK_LEFT, _T("LEFT")));
g_VKTable.insert(std::make_pair(VK_UP, _T("UP")));
g_VKTable.insert(std::make_pair(VK_DOWN, _T("DN")));
g_VKTable.insert(std::make_pair(VK_RIGHT, _T("RIGHT")));
g_VKTable.insert(std::make_pair(VK_OEM_1, _T(";:")));
g_VKTable.insert(std::make_pair(VK_OEM_7, _T("\'\"")));
g_VKTable.insert(std::make_pair(VK_OEM_COMMA, _T(",<")));
g_VKTable.insert(std::make_pair(VK_OEM_PERIOD, _T(".>")));
g_VKTable.insert(std::make_pair(VK_OEM_2, _T("/?")));
g_VKTable.insert(std::make_pair(VK_OEM_3, _T("`~")));
g_VKTable.insert(std::make_pair(VK_OEM_PLUS, _T("=+")));
g_VKTable.insert(std::make_pair(VK_OEM_MINUS, _T("-_")));
g_VKTable.insert(std::make_pair(VK_OEM_4, _T("[{")));
g_VKTable.insert(std::make_pair(VK_OEM_5, _T("\\|")));
g_VKTable.insert(std::make_pair(VK_OEM_6, _T("]}")));
for (WPARAM wp = 0x30; wp <= 0x39; ++wp)
g_VKTable.insert(std::make_pair(wp, CString(wchar_t(wp))));
for (WPARAM wp = 0x41; wp <= 0x5A; ++wp)
g_VKTable.insert(std::make_pair(wp, CString(wchar_t(wp))));
return 0;
}
std::string replace(const std::string& str
, const std::string& src
, const std::string& dest)
{
std::string ret;
std::string::size_type pos_begin = 0;
std::string::size_type pos = str.find(src);
while (pos != std::string::npos)
{
ret.append(str.data() + pos_begin, pos - pos_begin);
ret += dest;
pos_begin = pos + 1;
pos = str.find(src, pos_begin);
}
if (pos_begin < str.length())
{
ret.append(str.begin() + pos_begin, str.end());
}
return ret;
}
// 0-begin 1-normal 2-end
int analyzeCmdLine(const std::string &s, std::string &cmd, std::string &title)
{
std::string sFirst = s.substr(0, 2);
if (sFirst == "//") return -1;
sFirst = s.substr(0, 3);
if (sFirst == "***") return -1;
sFirst = s.substr(0, 9);
if (sFirst == "ID_SCREEN") return -1;
if (s.find("[--]") != -1) return -1;
int iBeginMask = s.find("[->");
int iEndMask = s.find("[<-");
int iTitleBegin = s.find('[');
int iTitleLast = s.find(']');
if (iBeginMask != -1)
{
title = s.substr(iBeginMask + 3, iTitleLast - (iBeginMask + 2) - 1);
return 0;
}
if (iEndMask != -1)
{
title = s.substr(iEndMask + 3, iTitleLast - (iEndMask + 2) - 1);
if (iTitleLast + 1 < s.size())
cmd = s.substr(iTitleLast + 1);
return 2;
}
if (iTitleBegin != -1)
{
title = s.substr(iTitleBegin + 1, iTitleLast - (iTitleBegin + 0) - 1);
if (iTitleLast + 1 < s.size())
cmd = s.substr(iTitleLast + 1);
return 1;
}
return -1;
}
bool makeMnuFile(MnuFile &mf)
{
mf.m_CmdGroups.clear();
std::ifstream fs(mf.m_sFile);
if (!fs.is_open()) return false;
int nRel(-1);
std::string s, cmd, title;
CmdGroup cmdgrp;
CmdItem ci;
while (!fs.eof())
{
s.clear();
std::getline(fs, s);
nRel = analyzeCmdLine(s, cmd, title);
if (nRel == 0)
{
cmdgrp.m_CmdItems.clear();
title = replace(title, " ", "");
title = replace(title, "\t", "");
cmdgrp.m_sGroupName = title.c_str();
}
else if (nRel == 1)
{
ci.m_sCmd = cmd.c_str();
title = replace(title, " ", "");
title = replace(title, "\t", "");
ci.m_sName = title.c_str();
ChiToLetter ch2Le;
ch2Le.m_blnSimaple = TRUE;
ci.m_sFirstLetter = ch2Le.GetLetter(ci.m_sName);
ch2Le.m_blnSimaple = FALSE;
ch2Le.m_blnAllBiG = FALSE;
ci.m_sFullLetter = ch2Le.GetLetter(ci.m_sName);
cmdgrp.m_CmdItems.push_back(ci);
}
else if (nRel == 2)
{
ci.m_sCmd = cmd.c_str();
title = replace(title, " ", "");
title = replace(title, "\t", "");
ci.m_sName = title.c_str();
ChiToLetter ch2Le;
ch2Le.m_blnSimaple = TRUE;
ci.m_sFirstLetter = ch2Le.GetLetter(ci.m_sName);
ch2Le.m_blnSimaple = FALSE;
ch2Le.m_blnAllBiG = FALSE;
ci.m_sFullLetter = ch2Le.GetLetter(ci.m_sName);
cmdgrp.m_CmdItems.push_back(ci);
mf.m_CmdGroups.push_back(cmdgrp);
}
}
fs.close();
return !mf.m_CmdGroups.empty();
}
int initCmdGroups()
{
g_mnuFiles.clear();
std::map<CString, CString> datas;
IniTools::getSectionContent(FilePath::GetSysDir() + _T("\\product.ini")
, _T("MENUS")
, datas);
if (datas.empty()) return 0;
CString sFile(_T("")), sTitle(_T(""));
std::map<CString, CString>::const_iterator it = datas.begin();
MnuFile mf;
for (; it != datas.end(); ++it)
{
mf.m_sFile = FilePath::GetSysDir() + _T("\\") + it->first + _T(".mnu");
mf.m_sTitle = it->second;
if (makeMnuFile(mf))
g_mnuFiles.push_back(mf);
}
startHook();
initVKTable();
getHotKey(g_hotkeys);
return 0;
}
static int g_init = initCmdGroups();
}
namespace CmdQuery
{
#define FILE_HOTKEYS _T("\\cmds_hotkey.conf")
void findCommand(LPCTSTR pszCmd, CmdQueryItems & items)
{
items.clear();
if (!pszCmd) return;
if (g_mnuFiles.empty()) return;
CString sCmd(pszCmd);
sCmd = sCmd.MakeLower();
CmdQueryItem qi;
for (size_t mnu = 0; mnu < g_mnuFiles.size(); ++mnu)
{
MnuFile &mf = g_mnuFiles[mnu];
for (size_t grp = 0; grp < mf.m_CmdGroups.size(); ++grp)
{
CmdGroup &cg = mf.m_CmdGroups[grp];
for (size_t ci = 0; ci < cg.m_CmdItems.size(); ++ci)
{
CmdItem &item = cg.m_CmdItems[ci];
if (item.m_sCmd.MakeLower().Find(sCmd) != -1
|| item.m_sFirstLetter.MakeLower().Find(sCmd) != -1
|| item.m_sFullLetter.MakeLower().Find(sCmd) != -1
|| item.m_sName.Find(sCmd) != -1 )
{
qi.m_cmdItem = item;
qi.m_sGroupName = cg.m_sGroupName;
qi.m_sFile = mf.m_sFile;
qi.m_sMnuTitle = mf.m_sTitle;
items.push_back(qi);
}
}
}
}
}
WPARAM getKeyByChar(LPCTSTR psz)
{
if (!psz) return NULL;
std::map<WPARAM, CString>::const_iterator it = g_VKTable.begin();
for (; it != g_VKTable.end(); ++it)
{
if (it->second.Compare(psz) == 0) return it->first;
}
return NULL;
}
CString getCharByKey(WPARAM key)
{
std::map<WPARAM, CString>::const_iterator it = g_VKTable.find(key);
if (it == g_VKTable.end()) return _T("");
return it->second;
}
bool checkHotkey(const std::map<WPARAM, CString>& keys)
{
if (keys.empty()) return true;
// 先检查有没有一般字符
bool bHasNormalKey(false);
std::map<WPARAM, CString>::const_iterator it = keys.begin();
for (; it != keys.end(); ++it)
{
if (isNormalKey(it->first))
{
bHasNormalKey = true;
break;
}
}
bool bHasCtrlKey(false);
// 再检查有没有(Ctrl、Alt、Shift)至少一种
for (it = keys.begin(); it != keys.end(); ++it)
{
if (it->first == VK_CONTROL
|| it->first == VK_MENU
|| it->first == VK_SHIFT)
{
bHasCtrlKey = true;
break;
}
}
return bHasNormalKey && bHasCtrlKey;
}
CString getHotkeyString()
{
std::set<WPARAM> hotkeys;
getHotKey(hotkeys);
if (hotkeys.empty()) return _T("");
std::wstringstream ws;
std::set<WPARAM>::const_iterator it = hotkeys.begin();
for (; it != hotkeys.end(); ++it)
ws << (LPCTSTR)getCharByKey(*it) << _T(" + ");
return CString(_T("(当前热键:"))
+ ws.str().substr(0, ws.str().size() - 3).c_str()
+ _T(")") ;
}
void getHotKey(std::set<WPARAM>& hotkeys)
{
hotkeys.clear();
hotkeys.insert(VK_CONTROL);
hotkeys.insert(VK_MENU);
hotkeys.insert('C');
CString path(FilePath::getProgramDataFolder() + FILE_HOTKEYS);
if (_taccess(path, 0x0) != 0x0) return;
std::ifstream fs((LPCTSTR)path);
std::string s;
std::vector<CString> vec;
while (!fs.eof())
{
vec.clear();
s.clear();
std::getline(fs, s);
CoreTools::SplitString(CString(s.c_str()), _T(' '), vec);
if (vec.size() < 2) return;
hotkeys.clear();
for (size_t i = 0; i < vec.size(); ++i)
{
hotkeys.insert(TypeConvert::convert<WPARAM, LPCTSTR>((LPCTSTR)vec[i]));
}
break;
}
}
void saveHotKey(std::map<WPARAM, CString>& chs)
{
std::ofstream fs(FilePath::getProgramDataFolder() + FILE_HOTKEYS);
if (fs.is_open())
{
g_hotkeys.clear();
std::map<WPARAM, CString>::const_iterator it = chs.begin();
for (; it != chs.end(); ++it)
{
fs << it->first << " ";
g_hotkeys.insert(it->first);
}
fs.close();
}
}
void startHook()
{
acedRegisterFilterWinMsg(InputKeyWord);
}
void endHook()
{
acedRemoveFilterWinMsg(InputKeyWord);
}
}