feat(master): add cached conversion mode file

This commit is contained in:
2025-06-22 07:17:29 +08:00
parent 2530210d27
commit fa81c1d418

View File

@ -21,7 +21,11 @@
// ReSharper disable CppDeprecatedEntity
// ReSharper disable CppClangTidyCertErr33C
std::ofstream GLogFile;
const std::string LogFilename = "FocusIME.log";
const std::string CachedModeFilename = "FocusIME.json";
std::ofstream GLogStream;
bool GShouldExit = false;
@ -48,7 +52,153 @@ void Tick()
Chinese,
};
static std::map<std::string, EIMEConversionMode> CachedIMEMode;
static std::map<std::string, EIMEConversionMode> CachedIMEMode = []
{
std::map<std::string, EIMEConversionMode> Result;
std::ifstream File(CachedModeFilename);
if (!File.is_open())
{
PrintLog("Cached conversion mode configuration file not found");
return Result;
}
do
{
std::string Buffer;
Buffer.assign(std::istreambuf_iterator<char>(File), std::istreambuf_iterator<char>());
std::string_view View = Buffer;
// { "ItemA": "ValueA", "ItemB": "ValueB" }
while (!View.empty() && std::isspace(View.front())) View.remove_prefix(1);
while (!View.empty() && std::isspace(View.back ())) View.remove_suffix(1);
if (!View.starts_with('{') || !View.ends_with('}')) break;
View.remove_prefix(1);
View.remove_suffix(1);
// "ItemA": "ValueA", "ItemB": "ValueB"
const bool bSuccessful = [&Result, &View]
{
std::string_view::size_type Index = std::string_view::npos;
while (true)
{
while (!View.empty() && std::isspace(View.front())) View.remove_prefix(1);
if (!View.starts_with('"')) return false;
View.remove_prefix(1);
// ItemA": "ValueA", "ItemB": "ValueB"
Index = View.find('"');
if (Index == std::string_view::npos) return false;
std::string_view Process = View.substr(0, Index);
View.remove_prefix(Process.size() + 1);
// : "ValueA", "ItemB": "ValueB"
while (!View.empty() && std::isspace(View.front())) View.remove_prefix(1);
if (!View.starts_with(':')) return false;
View.remove_prefix(1);
// "ValueA", "ItemB": "ValueB"
while (!View.empty() && std::isspace(View.front())) View.remove_prefix(1);
if (!View.starts_with('"')) return false;
View.remove_prefix(1);
// ValueA", "ItemB": "ValueB"
Index = View.find('"');
if (Index == std::string_view::npos) return false;
std::string_view Mode = View.substr(0, Index);
View.remove_prefix(Mode.size() + 1);
// , "ItemB": "ValueB"
while (!View.empty() && std::isspace(View.front())) View.remove_prefix(1);
if (View.empty()) return true;
if (!View.starts_with(',')) return false;
View.remove_prefix(1);
if (Mode != "English" && Mode != "Chinese" && Mode != "Default") return false;
Result[std::string(Process)] =
Mode == "English" ? EIMEConversionMode::English :
Mode == "Chinese" ? EIMEConversionMode::Chinese : EIMEConversionMode::Default;
}
return true;
} ();
if (!bSuccessful) break;
PrintLog("Successfully loaded " + std::to_string(Result.size()) + " cached conversion mode items");
return Result;
}
while (false);
PrintLog("Invalid format detected in cached conversion mode configuration file");
return Result;
} ();
auto SaveCachedIMEMode = []
{
std::ofstream File(CachedModeFilename);
if (!File.is_open())
{
PrintLog("Error: Failed to save cached conversion mode configuration");
return;
}
File << "{";
bool bFirstItem = true;
for (const auto& [Name, Mode] : CachedIMEMode)
{
if (!bFirstItem) File << ",";
File << "\n\t\"" << Name << "\": \"" <<
(Mode == EIMEConversionMode::English ? "English" :
Mode == EIMEConversionMode::Chinese ? "Chinese" : "Default") << "\"";
bFirstItem = false;
}
File << "\n}\n";
File.close();
};
static HWND LastWindow = nullptr;
@ -83,9 +233,11 @@ void Tick()
{
CachedIMEMode[CachedProcess] = CurrentMode;
PrintLog("Update the conversion mode cached for process '" + CachedProcess + "' to " +
PrintLog("Updated cached conversion mode for process '" + CachedProcess + "' to " +
(CurrentMode == EIMEConversionMode::English ? "English" :
CurrentMode == EIMEConversionMode::Chinese ? "Chinese" : "Default"));
CurrentMode == EIMEConversionMode::Chinese ? "Chinese" : "Default"));
SaveCachedIMEMode();
}
}
}
@ -145,11 +297,11 @@ void Tick()
{
if (SendMessage(IMEWindow, WM_IME_CONTROL, IMC_SETCONVERSIONMODE, TargetMode) == 0)
{
PrintLog("Successfully set conversion mode for process '" + CachedProcess + "'");
PrintLog("Successfully applied conversion mode for process '" + CachedProcess + "'");
}
else
{
PrintLog("Failed to set conversion mode for process '" + CachedProcess + "'");
PrintLog("Error: Failed to apply conversion mode for process '" + CachedProcess + "'");
}
}
}
@ -265,9 +417,9 @@ int WINAPI WinMain(HINSTANCE Instance, HINSTANCE, LPSTR, int)
}
# endif
GLogFile.open("Log.txt", std::ios::out | std::ios::app);
GLogStream.open(LogFilename, std::ios::out | std::ios::app);
if (!GLogFile.is_open())
if (!GLogStream.is_open())
{
MessageBox(nullptr, "Failed to open log file.", "FocusIME", MB_OK | MB_ICONERROR);
@ -276,7 +428,7 @@ int WINAPI WinMain(HINSTANCE Instance, HINSTANCE, LPSTR, int)
return 1;
}
PrintLog("FocusIME started successfully");
PrintLog("FocusIME application started successfully");
MSG Message = { };
@ -318,9 +470,9 @@ int WINAPI WinMain(HINSTANCE Instance, HINSTANCE, LPSTR, int)
}
}
PrintLog("FocusIME is shutting down...");
PrintLog("FocusIME application is shutting down");
GLogFile.close();
GLogStream.close();
# if BUILD_DEBUG || BUILD_DEVELOPMENT
{
@ -407,7 +559,7 @@ LRESULT CALLBACK MainWindowProc(const HWND Window, const UINT Message, const WPA
if (LOWORD(WParam) == ID_TRAY_EXIT)
{
PrintLog("Exit command received from tray menu");
PrintLog("Exit command received from system tray menu");
GShouldExit = true;
@ -451,7 +603,7 @@ void PrintLog(const std::string& Text)
Buffer[22] = Digits[Milliseconds / 10 % 10];
Buffer[23] = Digits[Milliseconds / 1 % 10];
GLogFile << Buffer << Text << std::endl;
GLogStream << Buffer << Text << std::endl;
#if BUILD_DEBUG || BUILD_DEVELOPMENT
{