├── output ├── archives │ └── .placeholder ├── start_service.bat ├── stop_service.bat ├── 7z.dll ├── 7z.exe ├── curl.exe ├── WinSparkle.dll ├── data │ └── preview │ │ ├── color_scheme_ink.png │ │ ├── color_scheme_nba.png │ │ ├── color_scheme_ps4.png │ │ ├── color_scheme_wii.png │ │ ├── color_scheme_aqua.png │ │ ├── color_scheme_azure.png │ │ ├── color_scheme_brisk.png │ │ ├── color_scheme_flypy.png │ │ ├── color_scheme_kuon.png │ │ ├── color_scheme_luna.png │ │ ├── color_scheme_macau.png │ │ ├── color_scheme_skype.png │ │ ├── color_scheme_steam.png │ │ ├── color_scheme_android.png │ │ ├── color_scheme_brasil.png │ │ ├── color_scheme_doraemon.png │ │ ├── color_scheme_dota_2.png │ │ ├── color_scheme_espagna.png │ │ ├── color_scheme_gholabok.png │ │ ├── color_scheme_google.png │ │ ├── color_scheme_psionics.png │ │ ├── color_scheme_smurfs.png │ │ ├── color_scheme_so_young.png │ │ ├── color_scheme_tintin.png │ │ ├── color_scheme_youtube.png │ │ ├── color_scheme_metroblue.png │ │ ├── color_scheme_starcraft.png │ │ ├── color_scheme_cool_breeze.png │ │ ├── color_scheme_dark_temple.png │ │ ├── color_scheme_google_plus.png │ │ ├── color_scheme_kuma_shuzboz.png │ │ ├── color_scheme_lost_temple.png │ │ ├── color_scheme_starcraft_ii.png │ │ ├── color_scheme_xbox_silver.png │ │ ├── color_scheme_modern_warfare.png │ │ └── color_scheme_solarized_rock.png ├── rime-install-config.bat ├── sudo.js ├── check_windows_version.js ├── uninstall.bat ├── COPYING-curl.txt └── install.bat ├── WeaselSetup ├── WeaselSetup.h ├── resource.h ├── WeaselSetup.ico ├── WeaselSetup.rc ├── stdafx.cpp ├── stdafx.h ├── WeaselSetup.vcxproj.filters ├── InstallOptionsDlg.h └── InstallOptionsDlg.cpp ├── WeaselServer ├── WeaselServer.h ├── resource.h ├── WeaselServer.rc ├── stdafx.cpp ├── WeaselTrayIcon.h ├── WeaselService.h ├── stdafx.h ├── WeaselServerApp.h ├── WeaselServerApp.cpp ├── WeaselTrayIcon.cpp ├── WeaselServer.vcxproj.filters └── WeaselServer.cpp ├── resource ├── en.ico ├── zh.ico ├── full.ico ├── half.ico ├── reload.ico └── weasel.ico ├── include ├── resource.h ├── VersionHelpers.hpp ├── WeaselVersion.h ├── logging.h ├── ResponseParser.h ├── StringAlgorithm.hpp ├── WeaselUtility.h ├── no_logging.h └── winsparkle-version.h ├── lib └── WinSparkle.lib ├── WeaselIME ├── WeaselIME.rc ├── stdafx.cpp ├── targetver.h ├── resource.h ├── stdafx.h ├── weasel.def ├── dllmain.cpp ├── ReadMe.txt ├── WeaselIME.h └── WeaselIME.vcxproj.filters ├── WeaselTSF ├── WeaselTSF.rc ├── WeaselTSF.def ├── Register.h ├── stdafx.cpp ├── targetver.h ├── dllmain.cpp ├── stdafx.h ├── EnumDisplayAttributeInfo.h ├── Compartment.h ├── DisplayAttributeInfo.h ├── EditSession.h ├── DisplayAttributeProvider.cpp ├── Globals.h ├── ReadMe.txt ├── Globals.cpp ├── EditSession.cpp ├── LanguageBar.h ├── ThreadMgrEventSink.cpp ├── DisplayAttribute.cpp ├── CandidateList.h ├── Server.cpp ├── DisplayAttributeInfo.cpp ├── EnumDisplayAttributeInfo.cpp └── TextEditSink.cpp ├── WeaselDeployer ├── resource.h ├── WeaselDeployer.rc ├── stdafx.cpp ├── Configurator.h ├── targetver.h ├── WeaselDeployer.h ├── stdafx.h ├── UIStyleSettings.h ├── UIStyleSettingsDialog.h ├── SwitcherSettingsDialog.h ├── DictManagementDialog.h ├── UIStyleSettingsDialog.cpp ├── UIStyleSettings.cpp ├── WeaselDeployer.cpp └── WeaselDeployer.vcxproj.filters ├── WeaselUI ├── StandardLayout.cpp ├── GdiplusBlur.h ├── stdafx.cpp ├── VerticalLayout.h ├── HorizontalLayout.h ├── VHorizontalLayout.h ├── targetver.h ├── stdafx.h ├── FullScreenLayout.h ├── ReadMe.txt └── StandardLayout.h ├── arm64x_wrapper ├── dummy.c ├── WeaselTSF_x64.def ├── WeaselTSF_arm64.def ├── WeaselIME_x64.def ├── WeaselIME_arm64.def └── build.bat ├── .gitmodules ├── install_nsis.bat ├── WeaselIPC ├── stdafx.cpp ├── Committer.h ├── Configurator.h ├── Styler.h ├── ActionLoader.h ├── targetver.h ├── Committer.cpp ├── Styler.cpp ├── Configurator.cpp ├── stdafx.h ├── Deserializer.h ├── ContextUpdater.h ├── ActionLoader.cpp ├── WeaselClientImpl.h ├── ReadMe.txt ├── Deserializer.cpp ├── ResponseParser.cpp ├── PipeChannel.cpp └── ContextUpdater.cpp ├── RimeWithWeasel ├── stdafx.cpp ├── targetver.h ├── stdafx.h ├── ReadMe.txt ├── RimeWithWeasel.vcxproj.filters └── WeaselUtility.cpp ├── WeaselIPCServer ├── stdafx.cpp ├── SecurityAttribute.h ├── targetver.h ├── stdafx.h ├── ReadMe.txt ├── WeaselIPCServer.vcxproj.filters ├── SecurityAttribute.cpp └── WeaselServerImpl.h ├── test ├── TestWeaselIPC │ ├── stdafx.cpp │ ├── stdafx.h │ ├── targetver.h │ ├── ReadMe.txt │ └── TestWeaselIPC.vcxproj.filters └── TestResponseParser │ ├── stdafx.cpp │ ├── stdafx.h │ ├── targetver.h │ ├── TestResponseParser.vcxproj.filters │ ├── ReadMe.txt │ └── TestResponseParser.cpp ├── env.bat.template ├── update ├── write-release-notes.sh ├── appcast.xml └── testing-appcast.xml ├── env.vs2019.bat ├── env.vs2022.bat ├── install_boost.bat ├── .github ├── ISSUE_TEMPLATE │ └── bug-上报.md └── workflows │ ├── commit-ci.yml │ └── release-ci.yml ├── .gitignore ├── github.install.bat ├── extract_changelog.ps1 ├── weasel.props.template ├── render.js └── INSTALL.md /output/archives/.placeholder: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /WeaselSetup/WeaselSetup.h: -------------------------------------------------------------------------------- 1 | // WeaselSetup.h 2 | -------------------------------------------------------------------------------- /WeaselServer/WeaselServer.h: -------------------------------------------------------------------------------- 1 | // WeaselServer.h 2 | -------------------------------------------------------------------------------- /output/start_service.bat: -------------------------------------------------------------------------------- 1 | cd "%~dp0" 2 | start "" WeaselServer.exe -------------------------------------------------------------------------------- /output/stop_service.bat: -------------------------------------------------------------------------------- 1 | cd "%~dp0" 2 | weaselserver.exe /q 3 | -------------------------------------------------------------------------------- /output/7z.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/7z.dll -------------------------------------------------------------------------------- /output/7z.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/7z.exe -------------------------------------------------------------------------------- /output/curl.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/curl.exe -------------------------------------------------------------------------------- /resource/en.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/resource/en.ico -------------------------------------------------------------------------------- /resource/zh.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/resource/zh.ico -------------------------------------------------------------------------------- /resource/full.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/resource/full.ico -------------------------------------------------------------------------------- /resource/half.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/resource/half.ico -------------------------------------------------------------------------------- /include/resource.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/include/resource.h -------------------------------------------------------------------------------- /lib/WinSparkle.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/lib/WinSparkle.lib -------------------------------------------------------------------------------- /resource/reload.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/resource/reload.ico -------------------------------------------------------------------------------- /resource/weasel.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/resource/weasel.ico -------------------------------------------------------------------------------- /WeaselIME/WeaselIME.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/WeaselIME/WeaselIME.rc -------------------------------------------------------------------------------- /WeaselSetup/resource.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/WeaselSetup/resource.h -------------------------------------------------------------------------------- /WeaselTSF/WeaselTSF.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/WeaselTSF/WeaselTSF.rc -------------------------------------------------------------------------------- /output/WinSparkle.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/WinSparkle.dll -------------------------------------------------------------------------------- /WeaselDeployer/resource.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/WeaselDeployer/resource.h -------------------------------------------------------------------------------- /WeaselServer/resource.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/WeaselServer/resource.h -------------------------------------------------------------------------------- /WeaselSetup/WeaselSetup.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/WeaselSetup/WeaselSetup.ico -------------------------------------------------------------------------------- /WeaselSetup/WeaselSetup.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/WeaselSetup/WeaselSetup.rc -------------------------------------------------------------------------------- /WeaselUI/StandardLayout.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/WeaselUI/StandardLayout.cpp -------------------------------------------------------------------------------- /include/VersionHelpers.hpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/include/VersionHelpers.hpp -------------------------------------------------------------------------------- /WeaselServer/WeaselServer.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/WeaselServer/WeaselServer.rc -------------------------------------------------------------------------------- /WeaselDeployer/WeaselDeployer.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/WeaselDeployer/WeaselDeployer.rc -------------------------------------------------------------------------------- /arm64x_wrapper/dummy.c: -------------------------------------------------------------------------------- 1 | // This file is left blank on purpose to invoke the ARM64EC compiler and build ARM64EC thunks. -------------------------------------------------------------------------------- /output/data/preview/color_scheme_ink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_ink.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_nba.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_nba.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_ps4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_ps4.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_wii.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_wii.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_aqua.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_aqua.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_azure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_azure.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_brisk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_brisk.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_flypy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_flypy.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_kuon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_kuon.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_luna.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_luna.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_macau.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_macau.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_skype.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_skype.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_steam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_steam.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_android.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_brasil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_brasil.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_doraemon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_doraemon.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_dota_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_dota_2.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_espagna.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_espagna.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_gholabok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_gholabok.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_google.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_psionics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_psionics.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_smurfs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_smurfs.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_so_young.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_so_young.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_tintin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_tintin.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_youtube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_youtube.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_metroblue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_metroblue.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_starcraft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_starcraft.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_cool_breeze.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_cool_breeze.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_dark_temple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_dark_temple.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_google_plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_google_plus.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_kuma_shuzboz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_kuma_shuzboz.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_lost_temple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_lost_temple.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_starcraft_ii.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_starcraft_ii.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_xbox_silver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_xbox_silver.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_modern_warfare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_modern_warfare.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_solarized_rock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/driver1998/weasel/HEAD/output/data/preview/color_scheme_solarized_rock.png -------------------------------------------------------------------------------- /WeaselTSF/WeaselTSF.def: -------------------------------------------------------------------------------- 1 | LIBRARY 2 | 3 | EXPORTS 4 | DllGetClassObject PRIVATE 5 | DllCanUnloadNow PRIVATE 6 | DllRegisterServer PRIVATE 7 | DllUnregisterServer PRIVATE -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "librime"] 2 | path = librime 3 | url = https://github.com/rime/librime.git 4 | [submodule "plum"] 5 | path = plum 6 | url = https://github.com/rime/plum.git 7 | -------------------------------------------------------------------------------- /output/rime-install-config.bat: -------------------------------------------------------------------------------- 1 | rem for downloading Git for Windows installer 2 | set git_mirror=taobao 3 | 4 | rem Rime configuration manager and downloaded packages 5 | set plum_dir=%APPDATA%\plum -------------------------------------------------------------------------------- /include/WeaselVersion.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WEASEL_VERSION_STR "0.15.0.0" 4 | #define WEASEL_VERSION_NUM 0,15,0,0 5 | 6 | #define WEASEL_CODE_NAME "Weasel" 7 | #define WEASEL_VERSION WEASEL_VERSION_STR 8 | -------------------------------------------------------------------------------- /WeaselUI/GdiplusBlur.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #pragma comment(lib, "gdiplus.lib") 4 | 5 | namespace weasel{ 6 | void DoGaussianBlur(Gdiplus::Bitmap* img, float radiusX, float radiusY); 7 | } 8 | -------------------------------------------------------------------------------- /WeaselSetup/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // WeaselSetup.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | -------------------------------------------------------------------------------- /WeaselTSF/Register.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Globals.h" 4 | 5 | BOOL RegisterProfiles(); 6 | void UnregisterProfiles(); 7 | BOOL RegisterCategories(); 8 | void UnregisterCategories(); 9 | BOOL RegisterServer(); 10 | void UnregisterServer(); 11 | -------------------------------------------------------------------------------- /arm64x_wrapper/WeaselTSF_x64.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | DllGetClassObject = weaselx64.dll.DllGetClassObject 3 | DllCanUnloadNow = weaselx64.dll.DllCanUnloadNow 4 | DllRegisterServer = weaselx64.dll.DllRegisterServer 5 | DllUnregisterServer = weaselx64.dll.DllUnregisterServer -------------------------------------------------------------------------------- /arm64x_wrapper/WeaselTSF_arm64.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | DllGetClassObject = weaselARM64.dll.DllGetClassObject 3 | DllCanUnloadNow = weaselARM64.dll.DllCanUnloadNow 4 | DllRegisterServer = weaselARM64.dll.DllRegisterServer 5 | DllUnregisterServer = weaselARM64.dll.DllUnregisterServer -------------------------------------------------------------------------------- /install_nsis.bat: -------------------------------------------------------------------------------- 1 | set nsis_version=3.08 2 | 3 | mkdir deps 4 | powershell -c "iwr -UserAgent \"Wget\" -Uri \"https://sourceforge.net/projects/nsis/files/NSIS%%203/%nsis_version%/nsis-%nsis_version%-setup.exe/download\" -OutFile deps\nsis-setup.exe" 5 | deps\nsis-setup.exe /S 6 | 7 | -------------------------------------------------------------------------------- /WeaselIME/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // WeaselIME.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /WeaselIPC/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // WeaselIPC.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /WeaselTSF/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // WeaselTSF.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /WeaselUI/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // WeaselUI.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /RimeWithWeasel/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // RimeWithWeasel.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /WeaselDeployer/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // WeaselDeployer.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /WeaselServer/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // WeaselServer.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | #if (_ATL_VER < 0x0700) 8 | #include 9 | #endif //(_ATL_VER < 0x0700) 10 | -------------------------------------------------------------------------------- /WeaselIPCServer/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // WeaselIPCServer.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /test/TestWeaselIPC/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // TestWeaselIPC.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /WeaselDeployer/Configurator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class UIStyleSettings; 4 | 5 | class Configurator 6 | { 7 | public: 8 | explicit Configurator(); 9 | 10 | void Initialize(); 11 | int Run(bool installing); 12 | int UpdateWorkspace(bool report_errors = false); 13 | int DictManagement(); 14 | int SyncUserData(); 15 | }; 16 | 17 | -------------------------------------------------------------------------------- /test/TestResponseParser/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // TestResponseParser.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /include/logging.h: -------------------------------------------------------------------------------- 1 | #ifndef WEASEL_LOGGGING_H_ 2 | #define WEASEL_LOGGGING_H_ 3 | 4 | #ifdef WEASEL_ENABLE_LOGGING 5 | #define GLOG_NO_ABBREVIATED_SEVERITIES 6 | #pragma warning(disable : 4244) 7 | #include 8 | #pragma warning(default : 4244) 9 | #else 10 | #include "no_logging.h" 11 | #endif // WEASEL_ENABLE_LOGGING 12 | 13 | #endif // WEASEL_LOGGGING_H_ 14 | -------------------------------------------------------------------------------- /WeaselUI/VerticalLayout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "StandardLayout.h" 4 | 5 | namespace weasel 6 | { 7 | class VerticalLayout: public StandardLayout 8 | { 9 | public: 10 | VerticalLayout(const UIStyle &style, const Context &context, const Status &status) 11 | : StandardLayout(style, context, status) {} 12 | virtual void DoLayout(CDCHandle dc, PDWR pDWR = NULL); 13 | }; 14 | }; 15 | -------------------------------------------------------------------------------- /WeaselUI/HorizontalLayout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "StandardLayout.h" 4 | 5 | namespace weasel 6 | { 7 | class HorizontalLayout: public StandardLayout 8 | { 9 | public: 10 | HorizontalLayout(const UIStyle &style, const Context &context, const Status &status) 11 | : StandardLayout(style, context, status) {} 12 | virtual void DoLayout(CDCHandle dc, PDWR pDWR = NULL); 13 | }; 14 | }; 15 | -------------------------------------------------------------------------------- /test/TestResponseParser/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #include 11 | #include 12 | 13 | 14 | 15 | // TODO: reference additional headers your program requires here 16 | -------------------------------------------------------------------------------- /WeaselIPCServer/SecurityAttribute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include // for security attributes constants 3 | #include // for ACL 4 | 5 | namespace weasel { 6 | class SecurityAttribute { 7 | private: 8 | PSECURITY_DESCRIPTOR pd; 9 | SECURITY_ATTRIBUTES sa; 10 | void _Init(); 11 | public: 12 | SecurityAttribute() : pd(NULL) { _Init(); } 13 | SECURITY_ATTRIBUTES *get_attr(); 14 | }; 15 | }; 16 | -------------------------------------------------------------------------------- /WeaselIPC/Committer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Deserializer.h" 3 | 4 | class Committer : public weasel::Deserializer 5 | { 6 | public: 7 | Committer(weasel::ResponseParser* pTarget); 8 | virtual ~Committer(); 9 | // store data 10 | virtual void Store(weasel::Deserializer::KeyType const& key, std::wstring const& value); 11 | // factory method 12 | static weasel::Deserializer::Ptr Create(weasel::ResponseParser* pTarget); 13 | }; 14 | -------------------------------------------------------------------------------- /WeaselIPC/Configurator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Deserializer.h" 3 | 4 | class Configurator : public weasel::Deserializer 5 | { 6 | public: 7 | Configurator(weasel::ResponseParser* pTarget); 8 | virtual ~Configurator(); 9 | // store data 10 | virtual void Store(weasel::Deserializer::KeyType const& key, std::wstring const& value); 11 | // factory method 12 | static weasel::Deserializer::Ptr Create(weasel::ResponseParser* pTarget); 13 | }; 14 | -------------------------------------------------------------------------------- /WeaselIPC/Styler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace weasel { 4 | class Deserializr; 5 | } 6 | 7 | class Styler : public weasel::Deserializer 8 | { 9 | public: 10 | Styler(weasel::ResponseParser* pTarget); 11 | virtual ~Styler(); 12 | // store data 13 | virtual void Store(weasel::Deserializer::KeyType const& key, std::wstring const& value); 14 | // factory method 15 | static weasel::Deserializer::Ptr Create(weasel::ResponseParser* pTarget); 16 | }; 17 | -------------------------------------------------------------------------------- /WeaselIPC/ActionLoader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Deserializer.h" 3 | 4 | class ActionLoader : public weasel::Deserializer 5 | { 6 | public: 7 | ActionLoader(weasel::ResponseParser* pTarget); 8 | virtual ~ActionLoader(); 9 | // store data 10 | virtual void Store(weasel::Deserializer::KeyType const& key, std::wstring const& value); 11 | // factory method 12 | static weasel::Deserializer::Ptr Create(weasel::ResponseParser* pTarget); 13 | }; 14 | -------------------------------------------------------------------------------- /test/TestWeaselIPC/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | extern CAppModule _Module; 21 | -------------------------------------------------------------------------------- /env.bat.template: -------------------------------------------------------------------------------- 1 | rem Customize your build environment and save the modified copy to env.bat 2 | 3 | rem REQUIRED: path to Boost source directory 4 | set BOOST_ROOT=C:\Libraries\boost_1_78_0 5 | 6 | rem OPTIONAL: Visual Studio version and platform toolset 7 | rem set BJAM_TOOLSET=msvc-14.2 8 | rem set PLATFORM_TOOLSET=v142 9 | 10 | rem OPTIONAL: path to additional build tools 11 | rem set DEVTOOLS_PATH=%ProgramFiles%\Git\cmd;%ProgramFiles%\Git\usr\bin;%ProgramFiles%\CMake\bin; 12 | -------------------------------------------------------------------------------- /WeaselUI/VHorizontalLayout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "StandardLayout.h" 4 | 5 | namespace weasel 6 | { 7 | class VHorizontalLayout: public StandardLayout 8 | { 9 | public: 10 | VHorizontalLayout(const UIStyle &style, const Context &context, const Status &status) 11 | : StandardLayout(style, context, status){} 12 | virtual void DoLayout(CDCHandle dc, PDWR pDWR = NULL); 13 | private: 14 | void DoLayoutWithWrap(CDCHandle dc, PDWR pDWR = NULL); 15 | }; 16 | }; 17 | -------------------------------------------------------------------------------- /WeaselIME/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | 10 | #define _WIN32_WINNT _WIN32_WINNT_WINBLUE // Specifies that the minimum required platform is Windows 8.1. 11 | 12 | #include 13 | -------------------------------------------------------------------------------- /WeaselIPC/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | 10 | #define _WIN32_WINNT _WIN32_WINNT_WINBLUE // Specifies that the minimum required platform is Windows 8.1. 11 | 12 | #include 13 | -------------------------------------------------------------------------------- /WeaselTSF/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | 10 | #define _WIN32_WINNT _WIN32_WINNT_WINBLUE // Specifies that the minimum required platform is Windows 8.1. 11 | 12 | #include 13 | -------------------------------------------------------------------------------- /WeaselUI/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | 10 | #define _WIN32_WINNT _WIN32_WINNT_WINBLUE // Specifies that the minimum required platform is Windows 8.1. 11 | 12 | #include 13 | -------------------------------------------------------------------------------- /RimeWithWeasel/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | 10 | #define _WIN32_WINNT _WIN32_WINNT_WINBLUE // Specifies that the minimum required platform is Windows 8.1. 11 | 12 | #include 13 | -------------------------------------------------------------------------------- /WeaselDeployer/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | 10 | #define _WIN32_WINNT _WIN32_WINNT_WINBLUE // Specifies that the minimum required platform is Windows 8.1. 11 | 12 | #include 13 | -------------------------------------------------------------------------------- /WeaselIPCServer/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | 10 | #define _WIN32_WINNT _WIN32_WINNT_WINBLUE // Specifies that the minimum required platform is Windows 8.1. 11 | 12 | #include 13 | -------------------------------------------------------------------------------- /test/TestWeaselIPC/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | 10 | #define _WIN32_WINNT _WIN32_WINNT_WINBLUE // Specifies that the minimum required platform is Windows 8.1. 11 | 12 | #include 13 | -------------------------------------------------------------------------------- /test/TestResponseParser/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | 10 | #define _WIN32_WINNT _WIN32_WINNT_WINBLUE // Specifies that the minimum required platform is Windows 8.1. 11 | 12 | #include 13 | -------------------------------------------------------------------------------- /WeaselIME/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by WeaselIME.rc 4 | // 5 | #define IDI_WEASEL 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 102 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /WeaselIPCServer/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | #include 21 | -------------------------------------------------------------------------------- /WeaselTSF/dllmain.cpp: -------------------------------------------------------------------------------- 1 | // dllmain.cpp : Defines the entry point for the DLL application. 2 | #include "stdafx.h" 3 | #include "Globals.h" 4 | 5 | BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID pvReserved) 6 | { 7 | switch (dwReason) 8 | { 9 | case DLL_PROCESS_ATTACH: 10 | g_hInst = hInstance; 11 | if (!InitializeCriticalSectionAndSpinCount(&g_cs, 0)) 12 | return FALSE; 13 | break; 14 | 15 | case DLL_PROCESS_DETACH: 16 | DeleteCriticalSection(&g_cs); 17 | break; 18 | } 19 | return TRUE; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /WeaselIME/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #define NOIME 11 | 12 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 13 | #include 14 | #include 15 | 16 | #include "immdev.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | -------------------------------------------------------------------------------- /output/sudo.js: -------------------------------------------------------------------------------- 1 | // elevate.js -- runs target command line elevated 2 | if (WScript.Arguments.Length >= 1) { 3 | Application = WScript.Arguments(0); 4 | Arguments = ""; 5 | for (Index = 1; Index < WScript.Arguments.Length; Index += 1) { 6 | if (Index > 1) { 7 | Arguments += " "; 8 | } 9 | Arguments += WScript.Arguments(Index); 10 | } 11 | new ActiveXObject("Shell.Application").ShellExecute(Application, Arguments, "", "runas"); 12 | } else { 13 | WScript.Echo("Usage: elevate Application Arguments"); 14 | } 15 | -------------------------------------------------------------------------------- /WeaselIME/weasel.def: -------------------------------------------------------------------------------- 1 | LIBRARY 2 | 3 | EXPORTS 4 | ImeConversionList 5 | ImeConfigure 6 | ImeDestroy 7 | ImeEscape 8 | ImeInquire 9 | ImeProcessKey 10 | ImeSelect 11 | ImeSetActiveContext 12 | ImeToAsciiEx 13 | NotifyIME 14 | ImeRegisterWord 15 | ImeUnregisterWord 16 | ImeGetRegisterWordStyle 17 | ImeEnumRegisterWord 18 | ImeSetCompositionString 19 | -------------------------------------------------------------------------------- /update/write-release-notes.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # writes an HTML page for changes in the latest release 4 | 5 | cat < release-notes.html 6 | 7 | 8 | 9 | 10 | 11 | 12 | EOF 13 | 14 | # take advantage of the fact that change log generator 15 | # places 3 new lines after each chapter for a new release. 16 | cat CHANGELOG.md | awk '{ 17 | print; 18 | if ($0 == "") ++new_lines; else new_lines = 0; 19 | if (new_lines >= 3) exit; 20 | }' | marked >> release-notes.html 21 | 22 | cat <> release-notes.html 23 | 24 | 25 | EOF 26 | -------------------------------------------------------------------------------- /env.vs2019.bat: -------------------------------------------------------------------------------- 1 | rem Customize your build environment and save the modified copy to env.bat 2 | 3 | set WEASEL_ROOT=%CD% 4 | 5 | rem REQUIRED: path to Boost source directory 6 | if not defined BOOST_ROOT set BOOST_ROOT=%WEASEL_ROOT%\deps\boost_1_78_0 7 | 8 | rem OPTIONAL: architecture, Visual Studio version and platform toolset 9 | set ARCH=Win32 10 | set BJAM_TOOLSET=msvc-14.2 11 | set CMAKE_GENERATOR="Visual Studio 16 2019" 12 | set PLATFORM_TOOLSET=v142 13 | 14 | rem OPTIONAL: path to additional build tools 15 | rem set DEVTOOLS_PATH=%ProgramFiles%\Git\cmd;%ProgramFiles%\Git\usr\bin;%ProgramFiles%\CMake\bin; 16 | -------------------------------------------------------------------------------- /env.vs2022.bat: -------------------------------------------------------------------------------- 1 | rem Customize your build environment and save the modified copy to env.bat 2 | 3 | set WEASEL_ROOT=%CD% 4 | 5 | rem REQUIRED: path to Boost source directory 6 | if not defined BOOST_ROOT set BOOST_ROOT=%WEASEL_ROOT%\deps\boost_1_78_0 7 | 8 | rem OPTIONAL: architecture, Visual Studio version and platform toolset 9 | set ARCH=Win32 10 | set BJAM_TOOLSET=msvc-14.3 11 | set CMAKE_GENERATOR="Visual Studio 17 2022" 12 | set PLATFORM_TOOLSET=v143 13 | 14 | rem OPTIONAL: path to additional build tools 15 | rem set DEVTOOLS_PATH=%ProgramFiles%\Git\cmd;%ProgramFiles%\Git\usr\bin;%ProgramFiles%\CMake\bin; 16 | -------------------------------------------------------------------------------- /WeaselUI/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | //#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | #include 24 | #define GDIPVER 0x0110 25 | -------------------------------------------------------------------------------- /WeaselIPC/Committer.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Deserializer.h" 3 | #include "Committer.h" 4 | 5 | using namespace weasel; 6 | 7 | 8 | Deserializer::Ptr Committer::Create(ResponseParser* pTarget) 9 | { 10 | return Deserializer::Ptr(new Committer(pTarget)); 11 | } 12 | 13 | Committer::Committer(ResponseParser* pTarget) 14 | : Deserializer(pTarget) 15 | { 16 | } 17 | 18 | Committer::~Committer() 19 | { 20 | } 21 | 22 | void Committer::Store(Deserializer::KeyType const& key, std::wstring const& value) 23 | { 24 | if (!m_pTarget->p_commit) 25 | return; 26 | if (key.size() == 1) 27 | *m_pTarget->p_commit = value; 28 | } 29 | -------------------------------------------------------------------------------- /install_boost.bat: -------------------------------------------------------------------------------- 1 | setlocal 2 | 3 | if not defined RIME_ROOT set RIME_ROOT=%CD% 4 | 5 | if not defined boost_version set boost_version=1.84.0 6 | set boost_x_y_z=%boost_version:.=_% 7 | 8 | if not defined BOOST_ROOT set BOOST_ROOT=%RIME_ROOT%\deps\boost_%boost_x_y_z% 9 | 10 | if exist "%BOOST_ROOT%\boost" goto boost_found 11 | for %%I in ("%BOOST_ROOT%\.") do set src_dir=%%~dpI 12 | rem download boost source 13 | aria2c https://boostorg.jfrog.io/artifactory/main/release/%boost_version%/source/boost_%boost_x_y_z%.7z -d %src_dir% 14 | pushd %src_dir% 15 | 7z x boost_%boost_x_y_z%.7z 16 | popd 17 | :boost_found 18 | 19 | call .\build.bat boost 20 | -------------------------------------------------------------------------------- /WeaselDeployer/WeaselDeployer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | #include 5 | #include 6 | #include 7 | #include "resource.h" 8 | 9 | #define MSG_BY_IDS(idInfo, idCap, uType) \ 10 | {\ 11 | CString info, cap;\ 12 | info.LoadStringW(idInfo);\ 13 | cap.LoadStringW(idCap);\ 14 | LANGID langID = GetThreadUILanguage();\ 15 | MessageBoxExW(NULL, info, cap, uType, langID);\ 16 | } 17 | 18 | #define MSG_ID_CAP(info, idCap, uType) \ 19 | {\ 20 | CString cap;\ 21 | cap.LoadStringW(idCap);\ 22 | LANGID langID = GetThreadUILanguage();\ 23 | MessageBoxExW(NULL, info, cap, uType, langID);\ 24 | } 25 | 26 | -------------------------------------------------------------------------------- /WeaselTSF/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | // Windows Header Files: 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | template 25 | using com_ptr = CComPtr; 26 | -------------------------------------------------------------------------------- /WeaselIPC/Styler.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Deserializer.h" 3 | #include "Styler.h" 4 | 5 | using namespace weasel; 6 | 7 | Styler::Styler(weasel::ResponseParser * pTarget) 8 | : Deserializer(pTarget) 9 | { 10 | } 11 | 12 | Styler::~Styler() 13 | { 14 | } 15 | 16 | void Styler::Store(weasel::Deserializer::KeyType const & key, std::wstring const & value) 17 | { 18 | if (!m_pTarget->p_style) return; 19 | 20 | UIStyle &sty = *m_pTarget->p_style; 21 | std::wstringstream ss(value); 22 | boost::archive::text_wiarchive ia(ss); 23 | 24 | ia >> sty; 25 | } 26 | 27 | weasel::Deserializer::Ptr Styler::Create(weasel::ResponseParser * pTarget) 28 | { 29 | return Deserializer::Ptr(new Styler(pTarget)); 30 | } 31 | -------------------------------------------------------------------------------- /WeaselUI/FullScreenLayout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "StandardLayout.h" 4 | 5 | namespace weasel 6 | { 7 | class FullScreenLayout: public StandardLayout 8 | { 9 | public: 10 | FullScreenLayout(const UIStyle &style, const Context &context, const Status &status, const CRect& inputPos, Layout* layout) 11 | : StandardLayout(style, context, status), mr_inputPos(inputPos), m_layout(layout) { } 12 | virtual ~FullScreenLayout(){ delete m_layout; } 13 | 14 | virtual void DoLayout(CDCHandle dc, PDWR pDWR = NULL); 15 | 16 | private: 17 | bool AdjustFontPoint(CDCHandle dc, const CRect& workArea, int& step, PDWR pDWR = NULL); 18 | 19 | const CRect& mr_inputPos; 20 | Layout* m_layout; 21 | }; 22 | }; 23 | -------------------------------------------------------------------------------- /WeaselDeployer/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | // Windows Header Files: 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | -------------------------------------------------------------------------------- /WeaselServer/WeaselTrayIcon.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "SystemTraySDK.h" 5 | 6 | #define WM_WEASEL_TRAY_NOTIFY (WEASEL_IPC_LAST_COMMAND + 100) 7 | 8 | 9 | class WeaselTrayIcon : public CSystemTray 10 | { 11 | public: 12 | enum WeaselTrayMode { 13 | INITIAL, ZHUNG, ASCII, DISABLED, 14 | }; 15 | 16 | WeaselTrayIcon(weasel::UI &ui); 17 | 18 | BOOL Create(HWND hTargetWnd); 19 | void Refresh(); 20 | 21 | protected: 22 | virtual void CustomizeMenu(HMENU hMenu); 23 | 24 | weasel::UIStyle &m_style; 25 | weasel::Status &m_status; 26 | WeaselTrayMode m_mode; 27 | std::wstring m_schema_zhung_icon; 28 | std::wstring m_schema_ascii_icon; 29 | bool m_disabled; 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-上报.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug 上报 3 | about: 我在使用时遇到了一个小狼毫的问题 4 | title: '' 5 | labels: Bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **上报前请检查** 11 | - [ ] 我遇到的问题没有其他人在 issue 里提到过 12 | - [ ] 我的小狼毫版本于 rime/weasel 下载 13 | - [ ] 我在使用小狼毫的最新发布版本,或最新发布版本后的 CI 构建 14 | 15 | **操作系统信息** 16 | - OS 详细版本: [ 运行 winver.exe 获取,如 Windows 11 22H2 22621.1555] 17 | - 小狼毫版本: [ 如 0.15.0.0 , CI 构建版请附短 commit hash ,如 372c9c ] 18 | 19 | **描述遇到的问题** 20 | 简短地描述你所遇到的问题 21 | 22 | **复现步骤** 23 | 重现问题的步骤,如: 24 | 1. 打开 '...' 软件 25 | 2. 输入 '...' 26 | 3. 进行 '...' 操作 27 | 4. 遇到了 '...' 问题 28 | 29 | **预期行为** 30 | 简短地描述你预期小狼毫怎么反馈 31 | 32 | **用户文件** 33 | 请于此附上 weasel 用户文件夹下的内容,方便开发者调试问题 34 | 35 | **截图** 36 | 如果问题需要,可附上 GIF 图片 37 | 38 | **其他补充说明** 39 | 如果有其他补充说明,可以写在这里 40 | -------------------------------------------------------------------------------- /WeaselDeployer/UIStyleSettings.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | struct ColorSchemeInfo { 8 | std::string color_scheme_id; 9 | std::string name; 10 | std::string author; 11 | }; 12 | 13 | class UIStyleSettings { 14 | public: 15 | UIStyleSettings(); 16 | 17 | bool GetPresetColorSchemes(std::vector* result); 18 | std::string GetColorSchemePreview(const std::string& color_scheme_id); 19 | std::string GetActiveColorScheme(); 20 | bool SelectColorScheme(const std::string& color_scheme_id); 21 | 22 | RimeCustomSettings* settings() { return settings_; } 23 | 24 | private: 25 | RimeLeversApi* api_; 26 | RimeCustomSettings* settings_; 27 | }; 28 | -------------------------------------------------------------------------------- /WeaselIPC/Configurator.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Deserializer.h" 3 | #include "Configurator.h" 4 | 5 | using namespace weasel; 6 | 7 | Deserializer::Ptr Configurator::Create(ResponseParser* pTarget) 8 | { 9 | return Deserializer::Ptr(new Configurator(pTarget)); 10 | } 11 | 12 | Configurator::Configurator(ResponseParser* pTarget) 13 | : Deserializer(pTarget) 14 | { 15 | } 16 | 17 | Configurator::~Configurator() 18 | { 19 | } 20 | 21 | void Configurator::Store(Deserializer::KeyType const& key, std::wstring const& value) 22 | { 23 | if (!m_pTarget->p_context || key.size() < 2) 24 | return; 25 | bool bool_value = (!value.empty() && value != L"0"); 26 | if (key[1] == L"inline_preedit") 27 | { 28 | m_pTarget->p_config->inline_preedit = bool_value; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Debug/ 2 | Release/ 3 | ReleaseHant/ 4 | /output/*.exp 5 | /output/*.ilk 6 | /output/*.iobj 7 | /output/*.ipdb 8 | /output/*.pdb 9 | /output/*.lib 10 | /output/*.exe 11 | /output/*.dll 12 | /output/*.ime 13 | /output/*.txt 14 | /output/*.bat 15 | /output/data/essay.txt 16 | /output/data/opencc/ 17 | /output/data/*.yaml 18 | /output/archives 19 | /lib/*.lib 20 | /include/glog 21 | /include/rime*.h 22 | /ipch 23 | env.bat 24 | weasel.props 25 | *.log 26 | *.user 27 | *.suo 28 | *.sdf 29 | *.opensdf 30 | *.aps 31 | *~ 32 | .*.swp 33 | *.swp 34 | .vs 35 | Thumbs.db 36 | /.idea 37 | /cmake-build-debug 38 | *.VC.db 39 | release-notes.html 40 | *.7z 41 | RELEASE_CHANGELOG.md 42 | deps/ 43 | arm64x_wrapper/*.o 44 | arm64x_wrapper/*.dll 45 | arm64x_wrapper/*.ime 46 | arm64x_wrapper/*.lib 47 | arm64x_wrapper/*.exp -------------------------------------------------------------------------------- /WeaselIPC/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | 12 | #include 13 | 14 | #pragma warning(disable : 4819) 15 | #pragma warning(disable : 4996) 16 | 17 | #include 18 | #include 19 | 20 | #pragma warning(default: 4819) 21 | #pragma warning(default: 4996) 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | using boost::interprocess::wbufferstream; 29 | -------------------------------------------------------------------------------- /arm64x_wrapper/WeaselIME_x64.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | ImeConversionList = weaselx64.ime.ImeConversionList 3 | ImeConfigure = weaselx64.ime.ImeConfigure 4 | ImeDestroy = weaselx64.ime.ImeDestroy 5 | ImeEscape = weaselx64.ime.ImeEscape 6 | ImeInquire = weaselx64.ime.ImeInquire 7 | ImeProcessKey = weaselx64.ime.ImeProcessKey 8 | ImeSelect = weaselx64.ime.ImeSelect 9 | ImeSetActiveContext = weaselx64.ime.ImeSetActiveContext 10 | ImeToAsciiEx = weaselx64.ime.ImeToAsciiEx 11 | NotifyIME = weaselx64.ime.NotifyIME 12 | ImeRegisterWord = weaselx64.ime.ImeRegisterWord 13 | ImeUnregisterWord = weaselx64.ime.ImeUnregisterWord 14 | ImeGetRegisterWordStyle = weaselx64.ime.ImeGetRegisterWordStyle 15 | ImeEnumRegisterWord = weaselx64.ime.ImeEnumRegisterWord 16 | ImeSetCompositionString = weaselx64.ime.ImeSetCompositionString 17 | -------------------------------------------------------------------------------- /WeaselIME/dllmain.cpp: -------------------------------------------------------------------------------- 1 | // dllmain.cpp : Defines the entry point for the DLL application. 2 | #include "stdafx.h" 3 | #include "WeaselIME.h" 4 | 5 | 6 | BOOL APIENTRY DllMain( HMODULE hModule, 7 | DWORD ul_reason_for_call, 8 | LPVOID lpReserved 9 | ) 10 | { 11 | WeaselIME::SetModuleInstance(hModule); 12 | 13 | switch (ul_reason_for_call) 14 | { 15 | case DLL_PROCESS_ATTACH: 16 | { 17 | HRESULT hr = WeaselIME::RegisterUIClass(); 18 | if (FAILED(hr)) 19 | return FALSE; 20 | } 21 | break; 22 | case DLL_THREAD_ATTACH: 23 | break; 24 | case DLL_THREAD_DETACH: 25 | break; 26 | case DLL_PROCESS_DETACH: 27 | WeaselIME::Cleanup(); 28 | WeaselIME::UnregisterUIClass(); 29 | break; 30 | } 31 | return TRUE; 32 | } 33 | -------------------------------------------------------------------------------- /output/check_windows_version.js: -------------------------------------------------------------------------------- 1 | var wbemFlagReturnImmediately = 0x10; 2 | var wbemFlagForwardOnly = 0x20; 3 | 4 | var objWMIService = GetObject("winmgmts:\\\\.\\root\\CIMV2"); 5 | var colItems = objWMIService.ExecQuery("SELECT * FROM Win32_OperatingSystem", "WQL", wbemFlagReturnImmediately | wbemFlagForwardOnly); 6 | 7 | var isWinXP = 0; 8 | var isX64 = 0; 9 | var enumItems = new Enumerator(colItems); 10 | for (; !enumItems.atEnd(); enumItems.moveNext()) { 11 | var objItem = enumItems.item(); 12 | if (objItem.Caption.indexOf("Windows XP") != -1) { 13 | isWinXP = 1; 14 | break; 15 | } 16 | else if (objItem.OSArchitecture.indexOf("64") != -1) { 17 | isX64 = 2; 18 | break; 19 | } 20 | } 21 | // 0: Win7 32-bit, 1: WinXP 32-bit, 2: Win7 64-bit 22 | WScript.Quit(isWinXP + isX64); 23 | -------------------------------------------------------------------------------- /RimeWithWeasel/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | #include 12 | 13 | #pragma warning(disable : 4819) 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #pragma warning(default : 4819) 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | using boost::interprocess::wbufferstream; 28 | -------------------------------------------------------------------------------- /github.install.bat: -------------------------------------------------------------------------------- 1 | setlocal 2 | 3 | git submodule init 4 | git submodule update plum 5 | 6 | set rime_version=1.9.0 7 | 8 | set download_archive=rime-a608767-Windows-msvc.7z 9 | set download_archive_deps=rime-deps-a608767-Windows-msvc.7z 10 | 11 | curl -LO https://github.com/rime/librime/releases/download/%rime_version%/%download_archive% 12 | curl -LO https://github.com/rime/librime/releases/download/%rime_version%/%download_archive_deps% 13 | 14 | 7z x %download_archive% * -olibrime\ -y 15 | 7z x %download_archive_deps% * -olibrime\ -y 16 | 17 | copy /Y librime\dist\include\rime_*.h include\ 18 | copy /Y librime\dist\lib\rime.lib lib\ 19 | copy /Y librime\dist\lib\rime.dll output\ 20 | 21 | if not exist output\data\opencc mkdir output\data\opencc 22 | copy /Y librime\share\opencc\*.* output\data\opencc\ 23 | 24 | -------------------------------------------------------------------------------- /update/appcast.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 【小狼毫】輸入法更新頻道 5 | http://rime.github.io/release/weasel/appcast.xml 6 | 小狼毫 Appcast 更新頻道 7 | zh 8 | 9 | 小狼毫 0.15.0 10 | http://rime.github.io/release/weasel/release-notes.html 11 | Sat, 10 Jun 2023 23:00:00 +0800 12 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /arm64x_wrapper/WeaselIME_arm64.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | ImeConversionList = weaselARM64.ime.ImeConversionList 3 | ImeConfigure = weaselARM64.ime.ImeConfigure 4 | ImeDestroy = weaselARM64.ime.ImeDestroy 5 | ImeEscape = weaselARM64.ime.ImeEscape 6 | ImeInquire = weaselARM64.ime.ImeInquire 7 | ImeProcessKey = weaselARM64.ime.ImeProcessKey 8 | ImeSelect = weaselARM64.ime.ImeSelect 9 | ImeSetActiveContext = weaselARM64.ime.ImeSetActiveContext 10 | ImeToAsciiEx = weaselARM64.ime.ImeToAsciiEx 11 | NotifyIME = weaselARM64.ime.NotifyIME 12 | ImeRegisterWord = weaselARM64.ime.ImeRegisterWord 13 | ImeUnregisterWord = weaselARM64.ime.ImeUnregisterWord 14 | ImeGetRegisterWordStyle = weaselARM64.ime.ImeGetRegisterWordStyle 15 | ImeEnumRegisterWord = weaselARM64.ime.ImeEnumRegisterWord 16 | ImeSetCompositionString = weaselARM64.ime.ImeSetCompositionString 17 | -------------------------------------------------------------------------------- /include/ResponseParser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | namespace weasel 10 | { 11 | class Deserializer; 12 | 13 | // 解析server回應文本 14 | struct ResponseParser 15 | { 16 | std::map > deserializers; 17 | 18 | std::wstring* p_commit; 19 | Context* p_context; 20 | Status* p_status; 21 | Config* p_config; 22 | UIStyle* p_style; 23 | 24 | ResponseParser(std::wstring* commit, Context* context = 0, Status* status = 0, Config* config = 0, UIStyle* style = 0); 25 | 26 | // 重載函數調用運算符, 以扮做ResponseHandler 27 | bool operator() (LPWSTR buffer, UINT length); 28 | 29 | // 處理一行回應文本 30 | void Feed(const std::wstring& line); 31 | }; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /update/testing-appcast.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 【小狼毫】輸入法測試頻道 5 | http://rime.github.io/testing/weasel/appcast.xml 6 | 小狼毫測試版 Appcast 更新頻道 7 | zh 8 | 9 | 小狼毫 0.15.0 10 | http://rime.github.io/testing/weasel/release-notes.html 11 | Sat, 10 Jun 2023 23:00:00 +0800 12 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /WeaselTSF/EnumDisplayAttributeInfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class CEnumDisplayAttributeInfo : public IEnumTfDisplayAttributeInfo 4 | { 5 | public: 6 | CEnumDisplayAttributeInfo(); 7 | ~CEnumDisplayAttributeInfo(); 8 | 9 | // IUnknown 10 | STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void** ppvObj); 11 | STDMETHODIMP_(ULONG) AddRef(void); 12 | STDMETHODIMP_(ULONG) Release(void); 13 | 14 | // IEnumTfDisplayAttributeInfo 15 | STDMETHODIMP Clone(_Out_ IEnumTfDisplayAttributeInfo** ppEnum); 16 | STDMETHODIMP Next(ULONG ulCount, __RPC__out_ecount_part(ulCount, *pcFetched) ITfDisplayAttributeInfo** rgInfo, __RPC__out ULONG* pcFetched); 17 | STDMETHODIMP Reset(); 18 | STDMETHODIMP Skip(ULONG ulCount); 19 | 20 | private: 21 | LONG _index; // next display attribute to enum 22 | LONG _refCount; // COM ref count 23 | }; 24 | -------------------------------------------------------------------------------- /WeaselTSF/Compartment.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class CCompartmentEventSink : public ITfCompartmentEventSink 6 | { 7 | public: 8 | using Callback = std::function; 9 | CCompartmentEventSink(Callback callback) 10 | : _callback(callback), _refCount(1) {}; 11 | ~CCompartmentEventSink() = default; 12 | 13 | // IUnknown 14 | STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj); 15 | STDMETHODIMP_(ULONG) AddRef(void); 16 | STDMETHODIMP_(ULONG) Release(void); 17 | 18 | // ITfCompartmentEventSink 19 | STDMETHODIMP OnChange(_In_ REFGUID guid); 20 | 21 | // function 22 | HRESULT _Advise(_In_ com_ptr punk, _In_ REFGUID guidCompartment); 23 | HRESULT _Unadvise(); 24 | 25 | private: 26 | com_ptr _compartment; 27 | DWORD _cookie; 28 | Callback _callback; 29 | 30 | LONG _refCount; 31 | }; 32 | -------------------------------------------------------------------------------- /extract_changelog.ps1: -------------------------------------------------------------------------------- 1 | $tag = $env:GITHUB_REF -replace 'refs/tags/' 2 | $changelogPath = Join-Path $PSScriptRoot "CHANGELOG.md" 3 | $outputPath = Join-Path $PSScriptRoot "RELEASE_CHANGELOG.md" 4 | 5 | $changeLog = Get-Content $changelogPath 6 | Out-File -FilePath $outputPath -NoNewline 7 | 8 | $found = $false 9 | foreach ($line in $changeLog) { 10 | $versionLine = $line -match '' 11 | if ($versionLine) { 12 | $version = $Matches.1 13 | if (-Not $found) { 14 | if ($version -ne $tag) { 15 | # version mismatch 16 | Write-Output "version mismatch: changelog is ${version} but tag is ${tag}" 17 | exit 1 18 | } else { 19 | $found = $true 20 | Write-Output "extracting changelog for ${version}" 21 | continue 22 | } 23 | } else { 24 | exit 0 25 | } 26 | } 27 | $line | Out-File -FilePath $outputPath -Append 28 | } 29 | -------------------------------------------------------------------------------- /WeaselIPC/Deserializer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace weasel 6 | { 7 | 8 | class Deserializer 9 | { 10 | public: 11 | typedef std::vector KeyType; 12 | typedef std::shared_ptr Ptr; 13 | typedef std::function Factory; 14 | 15 | Deserializer(ResponseParser* pTarget) : m_pTarget(pTarget) {} 16 | virtual ~Deserializer() {} 17 | virtual void Store(KeyType const& key, std::wstring const& value) {} 18 | 19 | static void Initialize(ResponseParser* pTarget); 20 | static void Define(std::wstring const& action, Factory factory); 21 | static bool Require(std::wstring const& action, ResponseParser* pTarget); 22 | 23 | protected: 24 | ResponseParser* m_pTarget; 25 | 26 | private: 27 | static std::map s_factories; 28 | }; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /weasel.props.template: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $BOOST_ROOT 5 | $PLATFORM_TOOLSET 6 | 7 | 8 | <_ProjectFileVersion>10.0.40219.1 9 | <_PropertySheetDisplayName>Weasel Project Properties 10 | 11 | 12 | 13 | $(BOOST_ROOT) 14 | true 15 | 16 | 17 | $(PLATFORM_TOOLSET) 18 | true 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /WeaselIPC/ContextUpdater.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Deserializer.h" 3 | 4 | class ContextUpdater : public weasel::Deserializer 5 | { 6 | public: 7 | ContextUpdater(weasel::ResponseParser* pTarget); 8 | virtual ~ContextUpdater(); 9 | virtual void Store(weasel::Deserializer::KeyType const& key, std::wstring const& value); 10 | 11 | void _StoreText(weasel::Text& target, Deserializer::KeyType k, std::wstring const& value); 12 | void _StoreCand(Deserializer::KeyType k, std::wstring const& value); 13 | 14 | static weasel::Deserializer::Ptr Create(weasel::ResponseParser* pTarget); 15 | }; 16 | 17 | class StatusUpdater : public weasel::Deserializer 18 | { 19 | public: 20 | StatusUpdater(weasel::ResponseParser* pTarget); 21 | virtual ~StatusUpdater(); 22 | virtual void Store(weasel::Deserializer::KeyType const& key, std::wstring const& value); 23 | 24 | static weasel::Deserializer::Ptr Create(weasel::ResponseParser* pTarget); 25 | }; 26 | -------------------------------------------------------------------------------- /WeaselTSF/DisplayAttributeInfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class CDisplayAttributeInfoInput : public ITfDisplayAttributeInfo 6 | { 7 | public: 8 | CDisplayAttributeInfoInput(); 9 | ~CDisplayAttributeInfoInput(); 10 | 11 | // IUnknown 12 | STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void** ppvObj); 13 | STDMETHODIMP_(ULONG) AddRef(void); 14 | STDMETHODIMP_(ULONG) Release(void); 15 | 16 | // ITfDisplayAttributeInfo 17 | STDMETHODIMP GetGUID(_Out_ GUID* pguid); 18 | STDMETHODIMP GetDescription(_Out_ BSTR* pbstrDesc); 19 | STDMETHODIMP GetAttributeInfo(_Out_ TF_DISPLAYATTRIBUTE* pTSFDisplayAttr); 20 | STDMETHODIMP SetAttributeInfo(_In_ const TF_DISPLAYATTRIBUTE* ptfDisplayAttr); 21 | STDMETHODIMP Reset(); 22 | 23 | private: 24 | const GUID* _pguid; 25 | const TF_DISPLAYATTRIBUTE* _pDisplayAttribute; 26 | const WCHAR* _pDescription; 27 | const WCHAR* _pValueName; 28 | LONG _refCount; // COM ref count 29 | }; 30 | -------------------------------------------------------------------------------- /WeaselIPC/ActionLoader.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include 3 | #include "Deserializer.h" 4 | #include "ActionLoader.h" 5 | #include 6 | 7 | using namespace weasel; 8 | 9 | 10 | Deserializer::Ptr ActionLoader::Create(ResponseParser* pTarget) 11 | { 12 | return Deserializer::Ptr(new ActionLoader(pTarget)); 13 | } 14 | 15 | ActionLoader::ActionLoader(ResponseParser* pTarget) 16 | : Deserializer(pTarget) 17 | { 18 | } 19 | 20 | ActionLoader::~ActionLoader() 21 | { 22 | } 23 | 24 | void ActionLoader::Store(Deserializer::KeyType const& key, std::wstring const& value) 25 | { 26 | if (key.size() == 1) // no extention parts 27 | { 28 | // split value by L"," 29 | std::vector vecAction; 30 | split(vecAction, value, L","); 31 | 32 | // require specified action deserializers 33 | std::for_each(vecAction.begin(), vecAction.end(), [this](std::wstring& action) 34 | { 35 | Deserializer::Require(action, m_pTarget); 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /WeaselDeployer/UIStyleSettingsDialog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | #include "UIStyleSettings.h" 5 | 6 | 7 | class UIStyleSettingsDialog : public CDialogImpl { 8 | public: 9 | enum { IDD = IDD_STYLE_SETTING }; 10 | 11 | UIStyleSettingsDialog(UIStyleSettings* settings); 12 | ~UIStyleSettingsDialog(); 13 | 14 | protected: 15 | BEGIN_MSG_MAP(UIStyleSettingsDialog) 16 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 17 | MESSAGE_HANDLER(WM_CLOSE, OnClose) 18 | COMMAND_ID_HANDLER(IDOK, OnOK) 19 | COMMAND_HANDLER(IDC_COLOR_SCHEME, LBN_SELCHANGE, OnColorSchemeSelChange) 20 | END_MSG_MAP() 21 | 22 | LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&); 23 | LRESULT OnClose(UINT, WPARAM, LPARAM, BOOL&); 24 | LRESULT OnOK(WORD, WORD code, HWND, BOOL&); 25 | LRESULT OnColorSchemeSelChange(WORD, WORD, HWND, BOOL&); 26 | 27 | void Populate(); 28 | void Preview(int index); 29 | 30 | UIStyleSettings* settings_; 31 | bool loaded_; 32 | std::vector preset_; 33 | 34 | CListBox color_schemes_; 35 | CStatic preview_; 36 | CImage image_; 37 | CButton select_font_; 38 | }; 39 | 40 | -------------------------------------------------------------------------------- /output/uninstall.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set CD_BACK=%CD% 4 | cd "%~dp0" 5 | 6 | if /i "%1" == "/unregister" goto unregister 7 | 8 | echo stopping service. 9 | call stop_service.bat 10 | 11 | echo administrative permissions required. detecting permissions... 12 | net session >nul 2>&1 13 | if not %errorlevel% == 0 ( 14 | echo elevating command prompt... 15 | cscript sudo.js "%~nx0" /unregister 16 | exit /b 17 | ) 18 | 19 | :unregister 20 | echo uninstalling Weasel ime. 21 | 22 | cscript check_windows_version.js 23 | if errorlevel 2 goto win7_x64_uninstall 24 | if errorlevel 1 goto xp_uninstall 25 | 26 | :win7_uninstall 27 | WeaselSetup.exe /u 28 | rem regsvr32.exe /s /u "%CD%\weasel.dll" 29 | goto next 30 | 31 | :win7_x64_uninstall 32 | WeaselSetupx64.exe /u 33 | rem regsvr32.exe /s /u "%CD%\weasel.dll" 34 | rem regsvr32.exe /s /u "%CD%\weaselx64.dll" 35 | goto next 36 | 37 | :xp_uninstall 38 | WeaselSetup.exe /u 39 | goto next 40 | 41 | :next 42 | reg delete "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run" /v WeaselServer /f 43 | 44 | :done 45 | if /i "%1" == "/unregister" pause 46 | echo uninstalled. 47 | cd "%CD_BACK%" 48 | -------------------------------------------------------------------------------- /output/COPYING-curl.txt: -------------------------------------------------------------------------------- 1 | COPYRIGHT AND PERMISSION NOTICE 2 | 3 | Copyright (c) 1996 - 2018, Daniel Stenberg, , and many 4 | contributors, see the THANKS file. 5 | 6 | All rights reserved. 7 | 8 | Permission to use, copy, modify, and distribute this software for any purpose 9 | with or without fee is hereby granted, provided that the above copyright 10 | notice and this permission notice appear in all copies. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN 15 | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 16 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 17 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 18 | OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | Except as contained in this notice, the name of a copyright holder shall not 21 | be used in advertising or otherwise to promote the sale, use or other dealings 22 | in this Software without prior written authorization of the copyright holder. 23 | -------------------------------------------------------------------------------- /WeaselTSF/EditSession.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "stdafx.h" 4 | #include "WeaselTSF.h" 5 | 6 | class CEditSession: public ITfEditSession 7 | { 8 | public: 9 | CEditSession(com_ptr pTextService, com_ptr pContext) 10 | : _pTextService(pTextService), _pContext(pContext) 11 | { 12 | _cRef = 1; 13 | } 14 | 15 | virtual ~CEditSession() 16 | { 17 | } 18 | 19 | /* IUnknown */ 20 | STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) 21 | { 22 | if (ppvObject == NULL) 23 | return E_INVALIDARG; 24 | 25 | *ppvObject = NULL; 26 | 27 | if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfEditSession)) 28 | *ppvObject = (ITfEditSession *) this; 29 | 30 | if (*ppvObject) 31 | { 32 | AddRef(); 33 | return S_OK; 34 | } 35 | return E_NOINTERFACE; 36 | } 37 | 38 | STDMETHODIMP_(ULONG) AddRef() 39 | { 40 | return ++_cRef; 41 | } 42 | 43 | STDMETHODIMP_(ULONG) Release() 44 | { 45 | LONG cr = --_cRef; 46 | assert(_cRef >= 0); 47 | if (_cRef == 0) 48 | delete this; 49 | return cr; 50 | } 51 | 52 | /* ITfEditSession */ 53 | virtual STDMETHODIMP DoEditSession(TfEditCookie ec) = 0; 54 | 55 | protected: 56 | com_ptr _pTextService; 57 | com_ptr _pContext; 58 | 59 | private: 60 | LONG _cRef; /* COM reference count */ 61 | }; -------------------------------------------------------------------------------- /WeaselDeployer/SwitcherSettingsDialog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | #include 5 | 6 | class SwitcherSettingsDialog : public CDialogImpl { 7 | public: 8 | enum { IDD = IDD_SWITCHER_SETTING }; 9 | 10 | SwitcherSettingsDialog(RimeSwitcherSettings* settings); 11 | ~SwitcherSettingsDialog(); 12 | 13 | protected: 14 | BEGIN_MSG_MAP(SwitcherSettingsDialog) 15 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 16 | MESSAGE_HANDLER(WM_CLOSE, OnClose) 17 | COMMAND_HANDLER(IDC_GET_SCHEMATA, BN_CLICKED, OnGetSchemata) 18 | COMMAND_ID_HANDLER(IDOK, OnOK) 19 | NOTIFY_HANDLER(IDC_SCHEMA_LIST, LVN_ITEMCHANGED, OnSchemaListItemChanged) 20 | END_MSG_MAP() 21 | 22 | LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&); 23 | LRESULT OnClose(UINT, WPARAM, LPARAM, BOOL&); 24 | LRESULT OnGetSchemata(WORD, WORD, HWND, BOOL&); 25 | LRESULT OnOK(WORD, WORD, HWND, BOOL&); 26 | LRESULT OnSchemaListItemChanged(int, LPNMHDR, BOOL&); 27 | 28 | void Populate(); 29 | void ShowDetails(RimeSchemaInfo* info); 30 | 31 | RimeLeversApi* api_; 32 | RimeSwitcherSettings* settings_; 33 | bool loaded_; 34 | bool modified_; 35 | 36 | CCheckListViewCtrl schema_list_; 37 | CStatic description_; 38 | CEdit hotkeys_; 39 | CButton get_schemata_; 40 | }; 41 | 42 | -------------------------------------------------------------------------------- /WeaselIPC/WeaselClientImpl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace weasel 6 | { 7 | 8 | class ClientImpl 9 | { 10 | public: 11 | ClientImpl(); 12 | ~ClientImpl(); 13 | 14 | bool Connect(ServerLauncher const& launcher); 15 | void Disconnect(); 16 | void ShutdownServer(); 17 | void StartSession(); 18 | void EndSession(); 19 | void StartMaintenance(); 20 | void EndMaintenance(); 21 | bool Echo(); 22 | bool ProcessKeyEvent(KeyEvent const& keyEvent); 23 | bool CommitComposition(); 24 | bool ClearComposition(); 25 | bool SelectCandidateOnCurrentPage(size_t index); 26 | void UpdateInputPosition(RECT const& rc); 27 | void FocusIn(); 28 | void FocusOut(); 29 | void TrayCommand(UINT menuId); 30 | bool GetResponseData(ResponseHandler const& handler); 31 | 32 | protected: 33 | void _InitializeClientInfo(); 34 | bool _WriteClientInfo(); 35 | 36 | LRESULT _SendMessage(WEASEL_IPC_COMMAND Msg, DWORD wParam, DWORD lParam); 37 | 38 | bool _Connected() const { return channel.Connected(); } 39 | bool _Active() const { return channel.Connected() && session_id != 0; } 40 | 41 | private: 42 | UINT session_id; 43 | std::wstring app_name; 44 | bool is_ime; 45 | 46 | PipeChannel channel; 47 | }; 48 | 49 | } -------------------------------------------------------------------------------- /WeaselTSF/DisplayAttributeProvider.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "WeaselTSF.h" 4 | #include "EnumDisplayAttributeInfo.h" 5 | #include "DisplayAttributeInfo.h" 6 | 7 | STDAPI WeaselTSF::EnumDisplayAttributeInfo(__RPC__deref_out_opt IEnumTfDisplayAttributeInfo** ppEnum) 8 | { 9 | CEnumDisplayAttributeInfo* pAttributeEnum = nullptr; 10 | 11 | if (ppEnum == nullptr) 12 | { 13 | return E_INVALIDARG; 14 | } 15 | 16 | *ppEnum = nullptr; 17 | 18 | pAttributeEnum = new (std::nothrow) CEnumDisplayAttributeInfo(); 19 | if (pAttributeEnum == nullptr) 20 | { 21 | return E_OUTOFMEMORY; 22 | } 23 | 24 | *ppEnum = pAttributeEnum; 25 | 26 | return S_OK; 27 | } 28 | 29 | STDAPI WeaselTSF::GetDisplayAttributeInfo(__RPC__in REFGUID guidInfo, __RPC__deref_out_opt ITfDisplayAttributeInfo** ppInfo) 30 | { 31 | if (ppInfo == nullptr) 32 | { 33 | return E_INVALIDARG; 34 | } 35 | 36 | *ppInfo = nullptr; 37 | 38 | if (IsEqualGUID(guidInfo, c_guidDisplayAttributeInput)) 39 | { 40 | *ppInfo = new (std::nothrow) CDisplayAttributeInfoInput(); 41 | if ((*ppInfo) == nullptr) 42 | { 43 | return E_OUTOFMEMORY; 44 | } 45 | } 46 | else 47 | { 48 | return E_INVALIDARG; 49 | } 50 | 51 | 52 | return S_OK; 53 | } 54 | -------------------------------------------------------------------------------- /WeaselUI/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | STATIC LIBRARY : WeaselUI Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this WeaselUI library project for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your WeaselUI application. 9 | 10 | 11 | WeaselUI.vcproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | 18 | ///////////////////////////////////////////////////////////////////////////// 19 | 20 | StdAfx.h, StdAfx.cpp 21 | These files are used to build a precompiled header (PCH) file 22 | named WeaselUI.pch and a precompiled types file named StdAfx.obj. 23 | 24 | ///////////////////////////////////////////////////////////////////////////// 25 | Other notes: 26 | 27 | AppWizard uses "TODO:" comments to indicate parts of the source code you 28 | should add to or customize. 29 | 30 | ///////////////////////////////////////////////////////////////////////////// 31 | -------------------------------------------------------------------------------- /WeaselIPC/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | STATIC LIBRARY : WeaselIPC Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this WeaselIPC library project for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your WeaselIPC application. 9 | 10 | 11 | WeaselIPC.vcproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | 18 | ///////////////////////////////////////////////////////////////////////////// 19 | 20 | StdAfx.h, StdAfx.cpp 21 | These files are used to build a precompiled header (PCH) file 22 | named WeaselIPC.pch and a precompiled types file named StdAfx.obj. 23 | 24 | ///////////////////////////////////////////////////////////////////////////// 25 | Other notes: 26 | 27 | AppWizard uses "TODO:" comments to indicate parts of the source code you 28 | should add to or customize. 29 | 30 | ///////////////////////////////////////////////////////////////////////////// 31 | -------------------------------------------------------------------------------- /WeaselServer/WeaselService.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "WeaselServerApp.h" 7 | 8 | #define WEASEL_SERVICE_NAME L"WeaselInputService" 9 | 10 | class WeaselService { 11 | public: 12 | WeaselService( 13 | BOOL fCanStop, 14 | BOOL fCanShutdown, 15 | BOOL fCanPauseContinue); 16 | ~WeaselService(); 17 | static BOOL Run(WeaselService &serv); 18 | 19 | void Stop(); 20 | // Start the service. 21 | void Start(DWORD dwArgc, PWSTR *pszArgv); 22 | 23 | protected: 24 | // Entry point for the service. It registers the handler function for the 25 | // service and starts the service. 26 | static void WINAPI ServiceMain(DWORD dwArgc, PWSTR *pszArgv); 27 | 28 | // The function is called by the SCM whenever a control code is sent to 29 | // the service. 30 | static void WINAPI ServiceCtrlHandler(DWORD dwCtrl); 31 | 32 | void SetServiceStatus(DWORD dwCurrentState, 33 | DWORD dwWin32ExitCode = NO_ERROR, 34 | DWORD dwWaitHint = 0); 35 | 36 | // Execute when the system is shutting down. 37 | void Shutdown(); 38 | private: 39 | static WeaselService *_service; 40 | 41 | // The status of the service 42 | SERVICE_STATUS _status; 43 | 44 | // The service status handle 45 | SERVICE_STATUS_HANDLE _statusHandle; 46 | 47 | BOOL _stopping; 48 | HANDLE _stoppedEvent; 49 | 50 | WeaselServerApp app; 51 | 52 | }; 53 | -------------------------------------------------------------------------------- /RimeWithWeasel/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | STATIC LIBRARY : RimeWithWeasel Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this RimeWithWeasel library project for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your RimeWithWeasel application. 9 | 10 | 11 | RimeWithWeasel.vcproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | 18 | ///////////////////////////////////////////////////////////////////////////// 19 | 20 | StdAfx.h, StdAfx.cpp 21 | These files are used to build a precompiled header (PCH) file 22 | named RimeWithWeasel.pch and a precompiled types file named StdAfx.obj. 23 | 24 | ///////////////////////////////////////////////////////////////////////////// 25 | Other notes: 26 | 27 | AppWizard uses "TODO:" comments to indicate parts of the source code you 28 | should add to or customize. 29 | 30 | ///////////////////////////////////////////////////////////////////////////// 31 | -------------------------------------------------------------------------------- /WeaselTSF/Globals.h: -------------------------------------------------------------------------------- 1 | /* Global definitions */ 2 | #pragma once 3 | 4 | #include "stdafx.h" 5 | #include 6 | 7 | #ifdef WEASEL_HANT 8 | #define TEXTSERVICE_LANGID MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL) 9 | #else 10 | #define TEXTSERVICE_LANGID MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED) 11 | #endif 12 | 13 | #define TEXTSERVICE_DESC WEASEL_IME_NAME 14 | #define TEXTSERVICE_DESC_A "Weasel" 15 | #define TEXTSERVICE_MODEL "Apartment" 16 | 17 | #define TEXTSERVICE_ICON_INDEX 0 18 | 19 | void DllAddRef(); 20 | void DllRelease(); 21 | 22 | extern HINSTANCE g_hInst; 23 | 24 | extern LONG g_cRefDll; 25 | 26 | extern CRITICAL_SECTION g_cs; 27 | 28 | extern const CLSID c_clsidTextService; 29 | 30 | extern const GUID c_guidProfile; 31 | 32 | extern const GUID c_guidLangBarItemButton; 33 | 34 | extern const GUID c_guidDisplayAttributeInput; 35 | 36 | #ifndef TF_IPP_CAPS_IMMERSIVESUPPORT 37 | 38 | #define WEASEL_USING_OLDER_TSF_SDK 39 | 40 | /* for Windows 8 */ 41 | #define TF_TMF_IMMERSIVEMODE 0x40000000 42 | #define TF_IPP_CAPS_IMMERSIVESUPPORT 0x00010000 43 | #define TF_IPP_CAPS_SYSTRAYSUPPORT 0x00020000 44 | 45 | extern const GUID GUID_TFCAT_TIPCAP_IMMERSIVESUPPORT; 46 | extern const GUID GUID_TFCAT_TIPCAP_SYSTRAYSUPPORT; 47 | 48 | #endif 49 | 50 | extern const GUID GUID_LBI_INPUTMODE; 51 | extern const GUID GUID_IME_MODE_PRESERVED_KEY; 52 | 53 | -------------------------------------------------------------------------------- /WeaselIPCServer/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | STATIC LIBRARY : WeaselIPCServer Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this WeaselIPCServer library project for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your WeaselIPCServer application. 9 | 10 | 11 | WeaselIPCServer.vcproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | 18 | ///////////////////////////////////////////////////////////////////////////// 19 | 20 | StdAfx.h, StdAfx.cpp 21 | These files are used to build a precompiled header (PCH) file 22 | named WeaselIPCServer.pch and a precompiled types file named StdAfx.obj. 23 | 24 | ///////////////////////////////////////////////////////////////////////////// 25 | Other notes: 26 | 27 | AppWizard uses "TODO:" comments to indicate parts of the source code you 28 | should add to or customize. 29 | 30 | ///////////////////////////////////////////////////////////////////////////// 31 | -------------------------------------------------------------------------------- /WeaselDeployer/DictManagementDialog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | 5 | #include 6 | 7 | 8 | class DictManagementDialog : public CDialogImpl { 9 | public: 10 | enum { IDD = IDD_DICT_MANAGEMENT }; 11 | 12 | DictManagementDialog(); 13 | ~DictManagementDialog(); 14 | 15 | protected: 16 | BEGIN_MSG_MAP(DictManagementDialog) 17 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 18 | MESSAGE_HANDLER(WM_CLOSE, OnClose) 19 | COMMAND_ID_HANDLER(IDC_BACKUP, OnBackup) 20 | COMMAND_ID_HANDLER(IDC_RESTORE, OnRestore) 21 | COMMAND_ID_HANDLER(IDC_EXPORT, OnExport) 22 | COMMAND_ID_HANDLER(IDC_IMPORT, OnImport) 23 | COMMAND_HANDLER(IDC_USER_DICT_LIST, LBN_SELCHANGE, OnUserDictListSelChange) 24 | END_MSG_MAP() 25 | 26 | LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&); 27 | LRESULT OnClose(UINT, WPARAM, LPARAM, BOOL&); 28 | LRESULT OnBackup(WORD, WORD code, HWND, BOOL&); 29 | LRESULT OnRestore(WORD, WORD code, HWND, BOOL&); 30 | LRESULT OnExport(WORD, WORD code, HWND, BOOL&); 31 | LRESULT OnImport(WORD, WORD code, HWND, BOOL&); 32 | LRESULT OnUserDictListSelChange(WORD, WORD, HWND, BOOL&); 33 | 34 | void Populate(); 35 | 36 | CListBox user_dict_list_; 37 | CButton backup_; 38 | CButton restore_; 39 | CButton export_; 40 | CButton import_; 41 | 42 | RimeLeversApi* api_; 43 | }; 44 | 45 | -------------------------------------------------------------------------------- /WeaselSetup/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | // Change these values to use different versions 9 | #define WINVER 0x0603 10 | #define _WIN32_WINNT 0x0603 11 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 12 | 13 | #include 14 | #include 15 | 16 | extern CAppModule _Module; 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #if defined _M_IX86 29 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") 30 | #elif defined _M_X64 31 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") 32 | #else 33 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") 34 | #endif 35 | -------------------------------------------------------------------------------- /WeaselIME/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | DYNAMIC LINK LIBRARY : WeaselIME Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this WeaselIME DLL for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your WeaselIME application. 9 | 10 | 11 | WeaselIME.vcproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | WeaselIME.cpp 18 | This is the main DLL source file. 19 | 20 | ///////////////////////////////////////////////////////////////////////////// 21 | Other standard files: 22 | 23 | StdAfx.h, StdAfx.cpp 24 | These files are used to build a precompiled header (PCH) file 25 | named WeaselIME.pch and a precompiled types file named StdAfx.obj. 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | Other notes: 29 | 30 | AppWizard uses "TODO:" comments to indicate parts of the source code you 31 | should add to or customize. 32 | 33 | ///////////////////////////////////////////////////////////////////////////// 34 | -------------------------------------------------------------------------------- /WeaselTSF/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | DYNAMIC LINK LIBRARY : WeaselTSF Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this WeaselTSF DLL for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your WeaselTSF application. 9 | 10 | 11 | WeaselTSF.vcproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | WeaselTSF.cpp 18 | This is the main DLL source file. 19 | 20 | ///////////////////////////////////////////////////////////////////////////// 21 | Other standard files: 22 | 23 | StdAfx.h, StdAfx.cpp 24 | These files are used to build a precompiled header (PCH) file 25 | named WeaselTSF.pch and a precompiled types file named StdAfx.obj. 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | Other notes: 29 | 30 | AppWizard uses "TODO:" comments to indicate parts of the source code you 31 | should add to or customize. 32 | 33 | ///////////////////////////////////////////////////////////////////////////// 34 | -------------------------------------------------------------------------------- /test/TestWeaselIPC/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | CONSOLE APPLICATION : TestWeaselIPC Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this TestWeaselIPC application for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your TestWeaselIPC application. 9 | 10 | 11 | TestWeaselIPC.vcproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | TestWeaselIPC.cpp 18 | This is the main application source file. 19 | 20 | ///////////////////////////////////////////////////////////////////////////// 21 | Other standard files: 22 | 23 | StdAfx.h, StdAfx.cpp 24 | These files are used to build a precompiled header (PCH) file 25 | named TestWeaselIPC.pch and a precompiled types file named StdAfx.obj. 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | Other notes: 29 | 30 | AppWizard uses "TODO:" comments to indicate parts of the source code you 31 | should add to or customize. 32 | 33 | ///////////////////////////////////////////////////////////////////////////// 34 | -------------------------------------------------------------------------------- /test/TestWeaselIPC/TestWeaselIPC.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /test/TestResponseParser/TestResponseParser.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /test/TestResponseParser/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | CONSOLE APPLICATION : TestResponseParser Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this TestResponseParser application for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your TestResponseParser application. 9 | 10 | 11 | TestResponseParser.vcproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | TestResponseParser.cpp 18 | This is the main application source file. 19 | 20 | ///////////////////////////////////////////////////////////////////////////// 21 | Other standard files: 22 | 23 | StdAfx.h, StdAfx.cpp 24 | These files are used to build a precompiled header (PCH) file 25 | named TestResponseParser.pch and a precompiled types file named StdAfx.obj. 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | Other notes: 29 | 30 | AppWizard uses "TODO:" comments to indicate parts of the source code you 31 | should add to or customize. 32 | 33 | ///////////////////////////////////////////////////////////////////////////// 34 | -------------------------------------------------------------------------------- /WeaselTSF/Globals.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Globals.h" 3 | 4 | HINSTANCE g_hInst; 5 | 6 | LONG g_cRefDll = -1; 7 | 8 | CRITICAL_SECTION g_cs; 9 | 10 | // {A3F4CDED-B1E9-41EE-9CA6-7B4D0DE6CB0A} 11 | static const GUID c_clsidTextService = 12 | { 0xa3f4cded, 0xb1e9, 0x41ee, { 0x9c, 0xa6, 0x7b, 0x4d, 0xd, 0xe6, 0xcb, 0xa } }; 13 | 14 | // {3D02CAB6-2B8E-4781-BA20-1C9267529467} 15 | static const GUID c_guidProfile = 16 | { 0x3d02cab6, 0x2b8e, 0x4781, { 0xba, 0x20, 0x1c, 0x92, 0x67, 0x52, 0x94, 0x67 } }; 17 | 18 | // {341F9E3A-B8AD-499D-936C-48701E329FB2} 19 | static const GUID c_guidLangBarItemButton = 20 | { 0x341f9e3a, 0xb8ad, 0x499d, { 0x93, 0x6c, 0x48, 0x70, 0x1e, 0x32, 0x9f, 0xb2 } }; 21 | 22 | // {2AC87E79-3260-4B32-9DEA-F8390976C20B} 23 | static const GUID c_guidDisplayAttributeInput = 24 | { 0x2ac87e79, 0x3260, 0x4b32, { 0x9d, 0xea, 0xf8, 0x39, 0x09, 0x76, 0xc2, 0x0b } }; 25 | 26 | #ifdef WEASEL_USING_OLDER_TSF_SDK 27 | 28 | /* For Windows 8 */ 29 | const GUID GUID_TFCAT_TIPCAP_IMMERSIVESUPPORT = 30 | { 0x13A016DF, 0x560B, 0x46CD, { 0x94, 0x7A, 0x4C, 0x3A, 0xF1, 0xE0, 0xE3, 0x5D } }; 31 | 32 | const GUID GUID_TFCAT_TIPCAP_SYSTRAYSUPPORT = 33 | { 0x25504FB4, 0x7BAB, 0x4BC1, { 0x9C, 0x69, 0xCF, 0x81, 0x89, 0x0F, 0x0E, 0xF5 } }; 34 | 35 | #endif 36 | 37 | const GUID GUID_LBI_INPUTMODE = 38 | { 0x2C77A81E, 0x41CC, 0x4178, { 0xA3, 0xA7, 0x5F, 0x8A, 0x98, 0x75, 0x68, 0xE6 } }; 39 | 40 | const GUID GUID_IME_MODE_PRESERVED_KEY = 41 | { 0x0bd899fc, 0xa8f7, 0x4b42, { 0xa9, 0x6d, 0xce, 0xc7, 0xc5, 0x0e, 0x0e, 0xae } }; 42 | -------------------------------------------------------------------------------- /WeaselTSF/EditSession.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "WeaselTSF.h" 3 | #include "CandidateList.h" 4 | #include "ResponseParser.h" 5 | 6 | STDAPI WeaselTSF::DoEditSession(TfEditCookie ec) 7 | { 8 | // get commit string from server 9 | std::wstring commit; 10 | weasel::Config config; 11 | auto context = std::make_shared(); 12 | weasel::ResponseParser parser(&commit, context.get(), &_status, &config, &_cand->style()); 13 | 14 | bool ok = m_client.GetResponseData(std::ref(parser)); 15 | 16 | _UpdateLanguageBar(_status); 17 | 18 | if (ok) 19 | { 20 | if (!commit.empty()) 21 | { 22 | // For auto-selecting, commit and preedit can both exist. 23 | // Commit and close the original composition first. 24 | if (!_IsComposing()) { 25 | _StartComposition(_pEditSessionContext, _fCUASWorkaroundEnabled && !config.inline_preedit); 26 | } 27 | _InsertText(_pEditSessionContext, commit); 28 | _EndComposition(_pEditSessionContext, false); 29 | } 30 | if (_status.composing && !_IsComposing()) 31 | { 32 | _StartComposition(_pEditSessionContext, _fCUASWorkaroundEnabled && !config.inline_preedit); 33 | } 34 | else if (!_status.composing && _IsComposing()) 35 | { 36 | _EndComposition(_pEditSessionContext, true); 37 | } 38 | _UpdateCompositionWindow(_pEditSessionContext); 39 | if (_IsComposing() && config.inline_preedit) 40 | { 41 | _ShowInlinePreedit(_pEditSessionContext, context); 42 | } 43 | } 44 | 45 | _UpdateUI(*context, _status); 46 | 47 | return TRUE; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /WeaselTSF/LanguageBar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class CLangBarItemButton : public ITfLangBarItemButton, public ITfSource 6 | { 7 | public: 8 | CLangBarItemButton(com_ptr pTextService, REFGUID guid, weasel::UIStyle& style ); 9 | ~CLangBarItemButton(); 10 | 11 | /* IUnknown */ 12 | STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject); 13 | STDMETHODIMP_(ULONG) AddRef(); 14 | STDMETHODIMP_(ULONG) Release(); 15 | 16 | /* ITfLangBarItem */ 17 | STDMETHODIMP GetInfo(TF_LANGBARITEMINFO *pInfo); 18 | STDMETHODIMP GetStatus(DWORD *pdwStatus); 19 | STDMETHODIMP Show(BOOL fShow); 20 | STDMETHODIMP GetTooltipString(BSTR *pbstrToolTip); 21 | 22 | /* ITfLangBarItemButton */ 23 | STDMETHODIMP OnClick(TfLBIClick click, POINT pt, const RECT *prcArea); 24 | STDMETHODIMP InitMenu(ITfMenu *pMenu); 25 | STDMETHODIMP OnMenuSelect(UINT wID); 26 | STDMETHODIMP GetIcon(HICON *phIcon); 27 | STDMETHODIMP GetText(BSTR *pbstrText); 28 | 29 | /* ITfSource */ 30 | STDMETHODIMP AdviseSink(REFIID riid, IUnknown *punk, DWORD *pdwCookie); 31 | STDMETHODIMP UnadviseSink(DWORD dwCookie); 32 | 33 | void UpdateWeaselStatus(weasel::Status stat); 34 | void SetLangbarStatus(DWORD dwStatus, BOOL fSet); 35 | 36 | private: 37 | GUID _guid; 38 | com_ptr _pTextService; 39 | com_ptr _pLangBarItemSink; 40 | LONG _cRef; /* COM Reference count */ 41 | DWORD _status; 42 | bool ascii_mode; 43 | weasel::UIStyle& _style; 44 | std::wstring _current_schema_zhung_icon; 45 | std::wstring _current_schema_ascii_icon; 46 | }; 47 | 48 | -------------------------------------------------------------------------------- /output/install.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem argument 1: [ /s | /t ] register ime as zh_CN | zh_TW keyboard layout 4 | set install_option=/s 5 | if /i "%1" == "/t" set install_option=/t 6 | 7 | set CD_BACK=%CD% 8 | cd "%~dp0" 9 | 10 | if /i "%2" == "/register" goto register 11 | 12 | echo stopping service from an older version. 13 | call stop_service.bat 14 | 15 | echo configuring preset input schemas... 16 | WeaselDeployer.exe /install 17 | 18 | echo administrative permissions required. detecting permissions... 19 | net session >nul 2>&1 20 | if not %errorlevel% == 0 ( 21 | echo elevating command prompt... 22 | cscript sudo.js "%~nx0" %install_option% /register 23 | exit /b 24 | ) 25 | 26 | :register 27 | echo registering Weasel IME to your system. 28 | echo install_option=%install_option% 29 | 30 | cscript check_windows_version.js 31 | if errorlevel 2 goto win7_x64_install 32 | if errorlevel 1 goto xp_install 33 | 34 | :win7_install 35 | WeaselSetup.exe %install_option% 36 | rem regsvr32.exe /s "%CD%\weasel.dll" 37 | goto next 38 | 39 | :win7_x64_install 40 | WeaselSetupx64.exe %install_option% 41 | rem regsvr32.exe /s "%CD%\weasel.dll" 42 | rem regsvr32.exe /s "%CD%\weaselx64.dll" 43 | goto next 44 | 45 | :xp_install 46 | WeaselSetup.exe %install_option% 47 | goto next 48 | 49 | :next 50 | reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run" /v WeaselServer /t REG_SZ /d "%CD%\WeaselServer.exe" /f 51 | 52 | :done 53 | start WeaselServer.exe 54 | 55 | if /i "%2" == "/register" pause 56 | echo installed. 57 | cd "%CD_BACK%" 58 | -------------------------------------------------------------------------------- /WeaselIPC/Deserializer.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Deserializer.h" 3 | #include "ActionLoader.h" 4 | #include "Committer.h" 5 | #include "ContextUpdater.h" 6 | #include "Configurator.h" 7 | #include "Styler.h" 8 | 9 | using namespace weasel; 10 | 11 | 12 | std::map Deserializer::s_factories; 13 | 14 | 15 | void Deserializer::Initialize(ResponseParser* pTarget) 16 | { 17 | if (s_factories.empty()) 18 | { 19 | // register factory methods 20 | // TODO: extend the parser's functionality in the future by defining more actions here 21 | Define(L"action", ActionLoader::Create); 22 | Define(L"commit", Committer::Create); 23 | Define(L"ctx", ContextUpdater::Create); 24 | Define(L"status", StatusUpdater::Create); 25 | Define(L"config", Configurator::Create); 26 | Define(L"style", Styler::Create); 27 | } 28 | 29 | // loaded by default 30 | Require(L"action", pTarget); 31 | } 32 | 33 | void Deserializer::Define(std::wstring const& action, Factory factory) 34 | { 35 | s_factories[action] = factory; 36 | //s_factories.insert(make_pair(action, factory)); 37 | } 38 | 39 | bool Deserializer::Require(std::wstring const& action, ResponseParser* pTarget) 40 | { 41 | if (!pTarget) 42 | return false; 43 | 44 | std::map::iterator i = s_factories.find(action); 45 | if (i == s_factories.end()) 46 | { 47 | // unknown action type 48 | return false; 49 | } 50 | 51 | Factory& factory = i->second; 52 | 53 | pTarget->deserializers[action] = factory(pTarget); 54 | //pTarget->deserializers.insert(make_pair(action, factory(pTarget))); 55 | return true; 56 | } -------------------------------------------------------------------------------- /WeaselServer/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | // Change these values to use different versions 9 | #define WINVER 0x0603 10 | #define _WIN32_WINNT 0x0603 11 | #define _WIN32_IE 0x0600 12 | #define _RICHEDIT_VER 0x0200 13 | #define NTDDI_VERSION NTDDI_WINBLUE 14 | // This project was generated for VC++ 2005 Express and ATL 3.0 from Platform SDK. 15 | // Comment out this line to build the project with different versions of VC++ and ATL. 16 | //#define _WTL_SUPPORT_SDK_ATL3 17 | 18 | // Support for VS2005 Express & SDK ATL 19 | #ifdef _WTL_SUPPORT_SDK_ATL3 20 | #define _CRT_SECURE_NO_DEPRECATE 21 | #pragma conform(forScope, off) 22 | #pragma comment(linker, "/NODEFAULTLIB:atlthunk.lib") 23 | #endif // _WTL_SUPPORT_SDK_ATL3 24 | // wtl10 require _RICHEDIT_VER > 0x0300, undef it first 25 | #undef _RICHEDIT_VER 26 | #include 27 | #include 28 | 29 | // Support for VS2005 Express & SDK ATL 30 | #ifdef _WTL_SUPPORT_SDK_ATL3 31 | namespace ATL 32 | { 33 | inline void * __stdcall __AllocStdCallThunk() 34 | { 35 | return ::HeapAlloc(::GetProcessHeap(), 0, sizeof(_stdcallthunk)); 36 | } 37 | 38 | inline void __stdcall __FreeStdCallThunk(void *p) 39 | { 40 | ::HeapFree(::GetProcessHeap(), 0, p); 41 | } 42 | }; 43 | #endif // _WTL_SUPPORT_SDK_ATL3 44 | 45 | #include 46 | #include 47 | #include 48 | #include 49 | 50 | #include 51 | 52 | extern CAppModule _Module; 53 | -------------------------------------------------------------------------------- /RimeWithWeasel/RimeWithWeasel.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | 29 | 30 | Header Files 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /WeaselServer/WeaselServerApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "WeaselTrayIcon.h" 14 | 15 | namespace fs = boost::filesystem; 16 | 17 | class WeaselServerApp { 18 | public: 19 | static bool execute(const fs::path &cmd, const std::wstring &args) 20 | { 21 | return (int)ShellExecuteW(NULL, NULL, cmd.c_str(), args.c_str(), NULL, SW_SHOWNORMAL) > 32; 22 | } 23 | 24 | static bool explore(const fs::path &path) 25 | { 26 | std::wstring quoted_path(L"\"" + path.wstring() + L"\""); 27 | return (int)ShellExecuteW(NULL, L"open", L"explorer", quoted_path.c_str(), NULL, SW_SHOWNORMAL) > 32; 28 | } 29 | 30 | static bool open(const fs::path &path) 31 | { 32 | return (int)ShellExecuteW(NULL, L"open", path.c_str(), NULL, NULL, SW_SHOWNORMAL) > 32; 33 | } 34 | 35 | static bool check_update() 36 | { 37 | // when checked manually, show testing versions too 38 | std::string feed_url = GetCustomResource("ManualUpdateFeedURL", "APPCAST"); 39 | if (!feed_url.empty()) 40 | { 41 | win_sparkle_set_appcast_url(feed_url.c_str()); 42 | } 43 | win_sparkle_check_update_with_ui(); 44 | return true; 45 | } 46 | 47 | static fs::path install_dir() 48 | { 49 | WCHAR exe_path[MAX_PATH] = { 0 }; 50 | GetModuleFileNameW(GetModuleHandle(NULL), exe_path, _countof(exe_path)); 51 | return fs::path(exe_path).remove_filename(); 52 | } 53 | 54 | public: 55 | WeaselServerApp(); 56 | ~WeaselServerApp(); 57 | int Run(); 58 | 59 | protected: 60 | void SetupMenuHandlers(); 61 | 62 | weasel::Server m_server; 63 | weasel::UI m_ui; 64 | WeaselTrayIcon tray_icon; 65 | std::unique_ptr m_handler; 66 | }; 67 | -------------------------------------------------------------------------------- /RimeWithWeasel/WeaselUtility.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include 3 | #include 4 | #include 5 | 6 | namespace fs = boost::filesystem; 7 | 8 | fs::path WeaselUserDataPath() { 9 | WCHAR _path[MAX_PATH] = {0}; 10 | const WCHAR KEY[] = L"Software\\Rime\\Weasel"; 11 | HKEY hKey; 12 | LSTATUS ret = RegOpenKey(HKEY_CURRENT_USER, KEY, &hKey); 13 | if (ret == ERROR_SUCCESS) 14 | { 15 | DWORD len = sizeof(_path); 16 | DWORD type = 0; 17 | DWORD data = 0; 18 | ret = RegQueryValueEx(hKey, L"RimeUserDir", NULL, &type, (LPBYTE)_path, &len); 19 | RegCloseKey(hKey); 20 | if (ret == ERROR_SUCCESS && type == REG_SZ && _path[0]) 21 | { 22 | return fs::path(_path); 23 | } 24 | } 25 | // default location 26 | ExpandEnvironmentStringsW(L"%AppData%\\Rime", _path, _countof(_path)); 27 | return fs::path(_path); 28 | } 29 | 30 | fs::path WeaselSharedDataPath() { 31 | wchar_t _path[MAX_PATH] = {0}; 32 | GetModuleFileNameW(NULL, _path, _countof(_path)); 33 | return fs::path(_path).remove_filename().append("data"); 34 | } 35 | 36 | std::string GetCustomResource(const char *name, const char *type) 37 | { 38 | const HINSTANCE module = 0; // main executable 39 | HRSRC hRes = FindResourceA(module, name, type); 40 | if ( hRes ) 41 | { 42 | HGLOBAL hData = LoadResource(module, hRes); 43 | if ( hData ) 44 | { 45 | const char *data = (const char*)::LockResource(hData); 46 | size_t size = ::SizeofResource(module, hRes); 47 | 48 | if ( data && size ) 49 | { 50 | if ( data[size-1] == '\0' ) // null-terminated string 51 | size--; 52 | return std::string(data, size); 53 | } 54 | } 55 | } 56 | 57 | return std::string(); 58 | } 59 | -------------------------------------------------------------------------------- /WeaselIPC/ResponseParser.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include 3 | #include 4 | #include "Deserializer.h" 5 | 6 | using namespace weasel; 7 | 8 | ResponseParser::ResponseParser(std::wstring* commit, Context* context, Status* status, Config* config, UIStyle* style) 9 | : p_commit(commit), p_context(context), p_status(status), p_config(config), p_style(style) 10 | { 11 | Deserializer::Initialize(this); 12 | } 13 | 14 | bool ResponseParser::operator() (LPWSTR buffer, UINT length) 15 | { 16 | wbufferstream bs(buffer, length); 17 | std::wstring line; 18 | while (bs.good()) 19 | { 20 | std::getline(bs, line); 21 | if (!bs.good()) 22 | return false; 23 | 24 | // file ends 25 | if (line == L".") 26 | break; 27 | 28 | Feed(line); 29 | } 30 | return bs.good(); 31 | } 32 | 33 | void ResponseParser::Feed(const std::wstring& line) 34 | { 35 | // ignore blank lines and comments 36 | if (line.empty() || line.find_first_of(L'#') == 0) 37 | return; 38 | 39 | Deserializer::KeyType key; 40 | std::wstring value; 41 | 42 | // extract key (split by L'.') and value 43 | std::wstring::size_type sep_pos = line.find_first_of(L'='); 44 | if (sep_pos == std::wstring::npos) 45 | return; 46 | split(key, line.substr(0, sep_pos), L"."); 47 | if (key.empty()) 48 | return; 49 | value = line.substr(sep_pos + 1); 50 | 51 | // first part of the key serve as action type 52 | std::wstring const& action = key[0]; 53 | 54 | // get required action deserializer instance 55 | std::map::iterator i = deserializers.find(action); 56 | if (i == deserializers.end()) 57 | { 58 | // line ignored... since corresponding deserializer is not active 59 | return; 60 | } 61 | 62 | // dispatch 63 | Deserializer::Ptr p = i->second; 64 | p->Store(key, value); 65 | } 66 | -------------------------------------------------------------------------------- /WeaselTSF/ThreadMgrEventSink.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "WeaselTSF.h" 3 | 4 | STDAPI WeaselTSF::OnInitDocumentMgr(ITfDocumentMgr *pDocMgr) 5 | { 6 | return S_OK; 7 | } 8 | 9 | STDAPI WeaselTSF::OnUninitDocumentMgr(ITfDocumentMgr *pDocMgr) 10 | { 11 | return S_OK; 12 | } 13 | 14 | STDAPI WeaselTSF::OnSetFocus(ITfDocumentMgr *pDocMgrFocus, ITfDocumentMgr *pDocMgrPrevFocus) 15 | { 16 | _InitTextEditSink(pDocMgrFocus); 17 | 18 | com_ptr pCandidateListDocumentMgr; 19 | com_ptr pTfContext = _GetUIContextDocument(); 20 | if ((nullptr != pTfContext) && SUCCEEDED(pTfContext->GetDocumentMgr(&pCandidateListDocumentMgr))) 21 | { 22 | if (pCandidateListDocumentMgr != pDocMgrFocus) 23 | { 24 | _HideUI(); 25 | } 26 | else 27 | { 28 | _ShowUI(); 29 | } 30 | } 31 | 32 | return S_OK; 33 | } 34 | 35 | STDAPI WeaselTSF::OnPushContext(ITfContext *pContext) 36 | { 37 | return S_OK; 38 | } 39 | 40 | STDAPI WeaselTSF::OnPopContext(ITfContext *pContext) 41 | { 42 | return S_OK; 43 | } 44 | 45 | BOOL WeaselTSF::_InitThreadMgrEventSink() 46 | { 47 | ITfSource *pSource; 48 | if (_pThreadMgr->QueryInterface(IID_ITfSource, (void **) &pSource) != S_OK) 49 | return FALSE; 50 | if (pSource->AdviseSink(IID_ITfThreadMgrEventSink, (ITfThreadMgrEventSink *) this, &_dwThreadMgrEventSinkCookie) != S_OK) 51 | { 52 | _dwThreadMgrEventSinkCookie = TF_INVALID_COOKIE; 53 | pSource->Release(); 54 | return FALSE; 55 | } 56 | pSource->Release(); 57 | return TRUE; 58 | } 59 | 60 | void WeaselTSF::_UninitThreadMgrEventSink() 61 | { 62 | ITfSource *pSource; 63 | if (_dwThreadMgrEventSinkCookie == TF_INVALID_COOKIE) 64 | return; 65 | if (SUCCEEDED(_pThreadMgr->QueryInterface(IID_ITfSource, (void **) &pSource))) 66 | { 67 | pSource->UnadviseSink(_dwThreadMgrEventSinkCookie); 68 | pSource->Release(); 69 | } 70 | _dwThreadMgrEventSinkCookie = TF_INVALID_COOKIE; 71 | } 72 | -------------------------------------------------------------------------------- /render.js: -------------------------------------------------------------------------------- 1 | // nanotemplate 2 | (function() { 3 | var _tregex = /(\$\w+)/g; 4 | 5 | String.prototype.template = String.prototype.t = String.prototype.template || function() { 6 | if (arguments[0] instanceof Array) 7 | return arguments[0].map(this.t, this).join(""); 8 | else { 9 | var args = typeof arguments[0] === "object" ? arguments[0] : arguments; 10 | return this.replace(_tregex, function(match) { return args[match.substr(1)]; }); 11 | } 12 | }; 13 | 14 | if (typeof Element === "function" || typeof Element === "object") 15 | Element.prototype.template = Element.prototype.t = Element.prototype.template || function() { 16 | this._tcache = this._tcache || this.innerHTML; 17 | this.innerHTML = this._tcache.t.apply(this._tcache, arguments); 18 | }; 19 | })(); 20 | 21 | // main 22 | var objStream = WScript.CreateObject("ADODB.Stream"); 23 | var shell = WScript.CreateObject("Wscript.Shell"); 24 | var env = shell.Environment("Process"); 25 | 26 | function Render(filename, params) { 27 | objStream.Charset = "utf-8"; 28 | objStream.Open(); 29 | objStream.LoadFromFile(filename + '.template'); 30 | var input = objStream.ReadText(); 31 | objStream.Close(); 32 | 33 | var output = input.template(params); 34 | objStream.Charset = "utf-8"; 35 | objStream.Open(); 36 | objStream.WriteText(output); 37 | objStream.SaveToFile(filename, 2); 38 | objStream.Close(); 39 | } 40 | 41 | if (WScript.Arguments.length == 0) { 42 | WScript.Echo("Usage: " + WScript.ScriptName + " ENV_VAR ..."); 43 | WScript.Quit(1); 44 | } 45 | 46 | var filename = WScript.Arguments(0); 47 | var params = {}; 48 | var variable; 49 | for (var i = 1; i < WScript.Arguments.length; i++) { 50 | variable = WScript.Arguments(i); 51 | params[variable] = env(variable); 52 | WScript.Echo(variable + "=" + params[variable]); 53 | } 54 | Render(filename, params); 55 | WScript.Echo("Generated " + filename); 56 | -------------------------------------------------------------------------------- /arm64x_wrapper/build.bat: -------------------------------------------------------------------------------- 1 | 2 | @echo off 3 | setlocal 4 | 5 | call :find_toolchain 6 | if errorlevel 1 exit /b 1 7 | 8 | REM Build dummy object files 9 | cl.exe /c /Fo:dummy.o dummy.c || exit /b 1 10 | cl.exe /c /arm64EC /Fo:dummy_x64.o dummy.c || exit /b 1 11 | 12 | REM Build weasel.dll wrapper 13 | link.exe /lib /machine:x64 /def:WeaselTSF_x64.def /out:WeaselTSF_x64.lib /ignore:4104 14 | link.exe /lib /machine:arm64 /def:WeaselTSF_arm64.def /out:WeaselTSF_arm64.lib /ignore:4104 15 | link.exe /dll /noentry /machine:arm64x /defArm64Native:WeaselTSF_arm64.def /def:WeaselTSF_x64.def ^ 16 | /out:weaselARM64X.dll dummy.o dummy_x64.o WeaselTSF_x64.lib WeaselTSF_arm64.lib /ignore:4104 17 | 18 | REM Build weasel.ime wrapper 19 | link.exe /lib /machine:x64 /def:WeaselIME_x64.def /out:WeaselIME_x64.lib /ignore:4104 20 | link.exe /lib /machine:arm64 /def:WeaselIME_arm64.def /out:WeaselIME_arm64.lib /ignore:4104 21 | link.exe /dll /noentry /machine:arm64x /defArm64Native:WeaselIME_arm64.def /def:WeaselIME_x64.def ^ 22 | /out:weaselARM64X.ime dummy.o dummy_x64.o WeaselIME_x64.lib WeaselIME_arm64.lib /ignore:4104 23 | 24 | endlocal 25 | exit /b 26 | 27 | :find_toolchain 28 | set VSWHERE="%PROGRAMFILES%\Microsoft Visual Studio\Installer\vswhere.exe" 29 | if not exist %VSWHERE% ( 30 | set VSWHERE="%PROGRAMFILES(X86)%\Microsoft Visual Studio\Installer\vswhere.exe" 31 | ) 32 | if not exist %VSWHERE% ( 33 | echo vswhere not found, could not find a working MSVC install. 34 | exit /b 1 35 | ) 36 | 37 | for /f "usebackq tokens=*" %%i in (`%VSWHERE% -latest -requires Microsoft.VisualStudio.Component.VC.Tools.ARM64EC -property installationPath`) do ( 38 | set ARM64EC_TOOLCHAIN=%%i 39 | ) 40 | 41 | if exist "%ARM64EC_TOOLCHAIN%\Common7\Tools\vsdevcmd.bat" ( 42 | call "%ARM64EC_TOOLCHAIN%\Common7\Tools\vsdevcmd.bat" -arch=arm64 -host_arch=x86 43 | echo. 44 | ) else ( 45 | echo ARM64EC capable toolchain not found 46 | exit /b 1 47 | ) 48 | 49 | exit /b 50 | 51 | -------------------------------------------------------------------------------- /WeaselIPCServer/WeaselIPCServer.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | 29 | 30 | Header Files 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /WeaselSetup/WeaselSetup.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {2df80f89-25ee-49a8-a0bf-2dd38ec3b0b2} 6 | cpp;c;cxx;def;odl;idl;hpj;bat;asm 7 | 8 | 9 | {30b9a326-3c70-4dd6-99a0-8fc6015e684b} 10 | h;hpp;hxx;hm;inl;inc 11 | 12 | 13 | {6ed053d1-845d-4449-a84b-43340151cc7c} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | 43 | 44 | Resource Files 45 | 46 | 47 | 48 | 49 | Resource Files 50 | 51 | 52 | -------------------------------------------------------------------------------- /WeaselSetup/InstallOptionsDlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | #include 5 | 6 | #define MSG_BY_IDS(idInfo, idCap, uType) \ 7 | {\ 8 | CString info, cap;\ 9 | info.LoadStringW(idInfo);\ 10 | cap.LoadStringW(idCap);\ 11 | LANGID langID = GetThreadUILanguage();\ 12 | MessageBoxExW(NULL, info, cap, uType, langID);\ 13 | } 14 | 15 | #define MSG_ID_CAP(info, idCap, uType) \ 16 | {\ 17 | CString cap;\ 18 | cap.LoadStringW(idCap);\ 19 | LANGID langID = GetThreadUILanguage();\ 20 | MessageBoxExW(NULL, info, cap, uType, langID);\ 21 | } 22 | 23 | #define MSG_NOT_SILENT_BY_IDS(silent, idInfo, idCap, uType) {if(!silent) MSG_BY_IDS(idInfo, idCap, uType); } 24 | #define MSG_NOT_SILENT_ID_CAP(silent, info, idCap, uType) {if(!silent) MSG_ID_CAP(info, idCap, uType);} 25 | 26 | class InstallOptionsDialog : public CDialogImpl 27 | { 28 | public: 29 | enum { IDD = IDD_INSTALL_OPTIONS }; 30 | 31 | InstallOptionsDialog(); 32 | ~InstallOptionsDialog(); 33 | 34 | bool installed; 35 | bool hant; 36 | bool old_ime_support; 37 | std::wstring user_dir; 38 | 39 | protected: 40 | BEGIN_MSG_MAP(InstallOptionsDialog) 41 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 42 | MESSAGE_HANDLER(WM_CLOSE, OnClose) 43 | COMMAND_ID_HANDLER(IDOK, OnOK) 44 | COMMAND_ID_HANDLER(IDC_REMOVE, OnRemove) 45 | COMMAND_ID_HANDLER(IDC_RADIO_DEFAULT_DIR, OnUseDefaultDir) 46 | COMMAND_ID_HANDLER(IDC_RADIO_CUSTOM_DIR, OnUseCustomDir) 47 | END_MSG_MAP() 48 | 49 | LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&); 50 | LRESULT OnClose(UINT, WPARAM, LPARAM, BOOL&); 51 | LRESULT OnOK(WORD, WORD code, HWND, BOOL&); 52 | LRESULT OnRemove(WORD, WORD code, HWND, BOOL&); 53 | LRESULT OnUseDefaultDir(WORD, WORD code, HWND, BOOL&); 54 | LRESULT OnUseCustomDir(WORD, WORD code, HWND, BOOL&); 55 | 56 | void UpdateWidgets(); 57 | 58 | CButton cn_; 59 | CButton tw_; 60 | CButton remove_; 61 | CButton default_dir_; 62 | CButton custom_dir_; 63 | CButton ok_; 64 | CButton ime_; 65 | CEdit dir_; 66 | }; 67 | -------------------------------------------------------------------------------- /include/StringAlgorithm.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | inline bool ends_with(const std::wstring& wstr, const std::wstring& wsub) 11 | { 12 | if (wstr.size() < wsub.size()) 13 | return false; 14 | else 15 | return std::equal(wsub.rbegin(), wsub.rend(), wstr.rbegin()); 16 | } 17 | 18 | inline bool iequals(const std::wstring& str1, const std::wstring& str2) 19 | { 20 | return std::equal(str1.begin(), str1.end(), str2.begin(), [](const wchar_t& wc1, const wchar_t& wc2) 21 | { 22 | return std::towlower(wc1) == std::towlower(wc2); 23 | }); 24 | } 25 | 26 | inline void ireplace_last(std::wstring& input, const std::wstring& search, const std::wstring& sub) 27 | { 28 | std::size_t pos = input.rfind(search); 29 | if (pos != std::wstring::npos) 30 | input.replace(pos, search.length(), sub); 31 | } 32 | 33 | inline std::string join(const std::set& list, const std::string& delim) 34 | { 35 | return std::accumulate(list.begin(), list.end(), std::string(), [&delim](std::string& str1, const std::string& str2) 36 | { 37 | return str1.empty() ? str2 : str1 + delim + str2; 38 | }); 39 | } 40 | 41 | inline std::vector& split(std::vector& result, const std::wstring& input, const wchar_t* delim) 42 | { 43 | result.clear(); 44 | size_t current = 0; 45 | size_t next = std::wstring::npos; 46 | do 47 | { 48 | current = next + 1; 49 | next = input.find_first_of(delim, next + 1); 50 | result.push_back(input.substr(current, next - current)); 51 | } while (next != std::wstring::npos); 52 | return result; 53 | } 54 | 55 | inline bool starts_with(const std::wstring& wstr, const std::wstring& wsub) 56 | { 57 | if (wstr.size() < wsub.size()) 58 | return false; 59 | else 60 | return std::equal(wsub.begin(), wsub.end(), wstr.begin()); 61 | } 62 | 63 | inline void to_lower(std::wstring& wstr) 64 | { 65 | std::setlocale(LC_ALL, ""); 66 | std::transform(wstr.begin(), wstr.end(), wstr.begin(), std::towlower); 67 | } 68 | -------------------------------------------------------------------------------- /WeaselTSF/DisplayAttribute.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "WeaselTSF.h" 4 | 5 | void WeaselTSF::_ClearCompositionDisplayAttributes(TfEditCookie ec, _In_ ITfContext* pContext) 6 | { 7 | ITfRange* pRangeComposition = nullptr; 8 | ITfProperty* pDisplayAttributeProperty = nullptr; 9 | 10 | if (FAILED(_pComposition->GetRange(&pRangeComposition))) 11 | { 12 | return; 13 | } 14 | 15 | if (SUCCEEDED(pContext->GetProperty(GUID_PROP_ATTRIBUTE, &pDisplayAttributeProperty))) 16 | { 17 | pDisplayAttributeProperty->Clear(ec, pRangeComposition); 18 | 19 | pDisplayAttributeProperty->Release(); 20 | } 21 | 22 | pRangeComposition->Release(); 23 | } 24 | 25 | BOOL WeaselTSF::_SetCompositionDisplayAttributes(TfEditCookie ec, _In_ ITfContext* pContext, ITfRange *pRangeComposition) 26 | { 27 | ITfProperty* pDisplayAttributeProperty = nullptr; 28 | HRESULT hr = S_OK; 29 | 30 | if (pRangeComposition == nullptr) 31 | hr = _pComposition->GetRange(&pRangeComposition); 32 | if (FAILED(hr)) 33 | { 34 | return FALSE; 35 | } 36 | 37 | hr = E_FAIL; 38 | 39 | if (SUCCEEDED(pContext->GetProperty(GUID_PROP_ATTRIBUTE, &pDisplayAttributeProperty))) 40 | { 41 | VARIANT var; 42 | var.vt = VT_I4; // we're going to set a TfGuidAtom 43 | var.lVal = _gaDisplayAttributeInput; 44 | 45 | hr = pDisplayAttributeProperty->SetValue(ec, pRangeComposition, &var); 46 | 47 | pDisplayAttributeProperty->Release(); 48 | } 49 | 50 | // DO NOT release range composition here 51 | // it will be released in another function 52 | // pRangeComposition->Release(); 53 | return (hr == S_OK); 54 | } 55 | 56 | BOOL WeaselTSF::_InitDisplayAttributeGuidAtom() 57 | { 58 | ITfCategoryMgr* pCategoryMgr = nullptr; 59 | HRESULT hr = CoCreateInstance(CLSID_TF_CategoryMgr, nullptr, CLSCTX_INPROC_SERVER, IID_ITfCategoryMgr, (void**)&pCategoryMgr); 60 | 61 | if (FAILED(hr)) 62 | { 63 | return FALSE; 64 | } 65 | 66 | hr = pCategoryMgr->RegisterGUID(c_guidDisplayAttributeInput, &_gaDisplayAttributeInput); 67 | if (FAILED(hr)) 68 | { 69 | goto Exit; 70 | } 71 | 72 | Exit: 73 | pCategoryMgr->Release(); 74 | 75 | return (hr == S_OK); 76 | } 77 | -------------------------------------------------------------------------------- /WeaselServer/WeaselServerApp.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "WeaselServerApp.h" 3 | #include 4 | 5 | WeaselServerApp::WeaselServerApp() 6 | : m_handler(std::make_unique(&m_ui)) 7 | , tray_icon(m_ui) 8 | { 9 | //m_handler.reset(new RimeWithWeaselHandler(&m_ui)); 10 | m_server.SetRequestHandler(m_handler.get()); 11 | SetupMenuHandlers(); 12 | } 13 | 14 | WeaselServerApp::~WeaselServerApp() 15 | { 16 | } 17 | 18 | int WeaselServerApp::Run() 19 | { 20 | if (!m_server.Start()) 21 | return -1; 22 | 23 | //win_sparkle_set_appcast_url("http://localhost:8000/weasel/update/appcast.xml"); 24 | win_sparkle_set_registry_path("Software\\Rime\\Weasel\\Updates"); 25 | win_sparkle_init(); 26 | m_ui.Create(m_server.GetHWnd()); 27 | 28 | tray_icon.Create(m_server.GetHWnd()); 29 | tray_icon.Refresh(); 30 | 31 | m_handler->Initialize(); 32 | m_handler->OnUpdateUI([this]() { 33 | tray_icon.Refresh(); 34 | }); 35 | 36 | int ret = m_server.Run(); 37 | 38 | m_handler->Finalize(); 39 | m_ui.Destroy(); 40 | tray_icon.RemoveIcon(); 41 | win_sparkle_cleanup(); 42 | 43 | return ret; 44 | } 45 | 46 | void WeaselServerApp::SetupMenuHandlers() 47 | { 48 | boost::filesystem::path dir = install_dir(); 49 | m_server.AddMenuHandler(ID_WEASELTRAY_QUIT, [this] { return m_server.Stop() == 0; }); 50 | m_server.AddMenuHandler(ID_WEASELTRAY_DEPLOY, std::bind(execute, dir / L"WeaselDeployer.exe", std::wstring(L"/deploy"))); 51 | m_server.AddMenuHandler(ID_WEASELTRAY_SETTINGS, std::bind(execute, dir / L"WeaselDeployer.exe", std::wstring())); 52 | m_server.AddMenuHandler(ID_WEASELTRAY_DICT_MANAGEMENT, std::bind(execute, dir / L"WeaselDeployer.exe", std::wstring(L"/dict"))); 53 | m_server.AddMenuHandler(ID_WEASELTRAY_SYNC, std::bind(execute, dir / L"WeaselDeployer.exe", std::wstring(L"/sync"))); 54 | m_server.AddMenuHandler(ID_WEASELTRAY_WIKI, std::bind(open, L"https://rime.im/docs/")); 55 | m_server.AddMenuHandler(ID_WEASELTRAY_HOMEPAGE, std::bind(open, L"https://rime.im/")); 56 | m_server.AddMenuHandler(ID_WEASELTRAY_FORUM, std::bind(open, L"https://rime.im/discuss/")); 57 | m_server.AddMenuHandler(ID_WEASELTRAY_CHECKUPDATE, check_update); 58 | m_server.AddMenuHandler(ID_WEASELTRAY_INSTALLDIR, std::bind(explore, dir)); 59 | m_server.AddMenuHandler(ID_WEASELTRAY_USERCONFIG, std::bind(explore, WeaselUserDataPath())); 60 | } 61 | -------------------------------------------------------------------------------- /WeaselIME/WeaselIME.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "KeyEvent.h" 4 | 5 | #define MAX_COMPOSITION_SIZE 256 6 | 7 | struct CompositionInfo 8 | { 9 | COMPOSITIONSTRING cs; 10 | WCHAR szCompStr[MAX_COMPOSITION_SIZE]; 11 | WCHAR szResultStr[MAX_COMPOSITION_SIZE]; 12 | void Reset() 13 | { 14 | memset(this, 0, sizeof(*this)); 15 | cs.dwSize = sizeof(*this); 16 | cs.dwCompStrOffset = (DWORD)((ptrdiff_t)&szCompStr - (ptrdiff_t)this); 17 | cs.dwResultStrOffset = (DWORD)((ptrdiff_t)&szResultStr - (ptrdiff_t)this); 18 | } 19 | }; 20 | 21 | class WeaselIME; 22 | 23 | class HIMCMap : public std::map > 24 | { 25 | public: 26 | HIMCMap() : m_valid(true) {} 27 | ~HIMCMap() { m_valid = false; } 28 | std::mutex& get_mutex() { return m_mutex; } 29 | bool is_valid() const { return m_valid; } 30 | private: 31 | bool m_valid; 32 | std::mutex m_mutex; 33 | }; 34 | 35 | class WeaselIME 36 | { 37 | public: 38 | static HINSTANCE GetModuleInstance(); 39 | static void SetModuleInstance(HINSTANCE hModule); 40 | static HRESULT RegisterUIClass(); 41 | static HRESULT UnregisterUIClass(); 42 | static LPCWSTR GetUIClassName(); 43 | static LRESULT WINAPI UIWndProc(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp); 44 | static BOOL IsIMEMessage(UINT uMsg); 45 | static std::shared_ptr GetInstance(HIMC hIMC); 46 | static void Cleanup(); 47 | 48 | WeaselIME(HIMC hIMC); 49 | LRESULT OnIMESelect(BOOL fSelect); 50 | LRESULT OnIMEFocus(BOOL fFocus); 51 | LRESULT OnUIMessage(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp); 52 | BOOL ProcessKeyEvent(UINT vKey, KeyInfo kinfo, const LPBYTE lpbKeyState); 53 | 54 | private: 55 | HRESULT _Initialize(); 56 | HRESULT _Finalize(); 57 | LRESULT _OnIMENotify(LPINPUTCONTEXT lpIMC, WPARAM wp, LPARAM lp); 58 | HRESULT _StartComposition(); 59 | HRESULT _EndComposition(LPCWSTR composition); 60 | HRESULT _AddIMEMessage(UINT msg, WPARAM wp, LPARAM lp); 61 | void _SetCandidatePos(LPINPUTCONTEXT lpIMC); 62 | void _SetCompositionWindow(LPINPUTCONTEXT lpIMC); 63 | void _UpdateInputPosition(LPINPUTCONTEXT lpIMC, POINT pt); 64 | 65 | private: 66 | static HINSTANCE s_hModule; 67 | static HIMCMap s_instances; 68 | HIMC m_hIMC; 69 | bool m_composing; 70 | bool m_preferCandidatePos; 71 | weasel::Client m_client; 72 | }; 73 | -------------------------------------------------------------------------------- /WeaselDeployer/UIStyleSettingsDialog.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "UIStyleSettingsDialog.h" 3 | #include "UIStyleSettings.h" 4 | #include "Configurator.h" 5 | #include 6 | 7 | 8 | UIStyleSettingsDialog::UIStyleSettingsDialog(UIStyleSettings* settings) 9 | : settings_(settings), loaded_(false) 10 | { 11 | } 12 | 13 | 14 | UIStyleSettingsDialog::~UIStyleSettingsDialog() 15 | { 16 | image_.Destroy(); 17 | } 18 | 19 | 20 | void UIStyleSettingsDialog::Populate() { 21 | if (!settings_) return; 22 | std::string active(settings_->GetActiveColorScheme()); 23 | int active_index = -1; 24 | settings_->GetPresetColorSchemes(&preset_); 25 | for (size_t i = 0; i < preset_.size(); ++i) { 26 | std::wstring txt = string_to_wstring(preset_[i].name.c_str(), CP_UTF8); 27 | color_schemes_.AddString(txt.c_str()); 28 | if (preset_[i].color_scheme_id == active) { 29 | active_index = i; 30 | } 31 | } 32 | if (active_index >= 0) { 33 | color_schemes_.SetCurSel(active_index); 34 | Preview(active_index); 35 | } 36 | loaded_ = true; 37 | } 38 | 39 | LRESULT UIStyleSettingsDialog::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) { 40 | color_schemes_.Attach(GetDlgItem(IDC_COLOR_SCHEME)); 41 | preview_.Attach(GetDlgItem(IDC_PREVIEW)); 42 | select_font_.Attach(GetDlgItem(IDC_SELECT_FONT)); 43 | select_font_.EnableWindow(FALSE); 44 | 45 | Populate(); 46 | 47 | CenterWindow(); 48 | BringWindowToTop(); 49 | return TRUE; 50 | } 51 | 52 | LRESULT UIStyleSettingsDialog::OnClose(UINT, WPARAM, LPARAM, BOOL&) { 53 | EndDialog(IDCANCEL); 54 | return 0; 55 | } 56 | 57 | LRESULT UIStyleSettingsDialog::OnOK(WORD, WORD code, HWND, BOOL&) { 58 | EndDialog(code); 59 | return 0; 60 | } 61 | 62 | LRESULT UIStyleSettingsDialog::OnColorSchemeSelChange(WORD, WORD, HWND, BOOL&) { 63 | int index = color_schemes_.GetCurSel(); 64 | if (index >= 0 && index < (int)preset_.size()) { 65 | settings_->SelectColorScheme(preset_[index].color_scheme_id); 66 | Preview(index); 67 | } 68 | return 0; 69 | } 70 | 71 | void UIStyleSettingsDialog::Preview(int index) { 72 | if (index < 0 || index >= (int)preset_.size()) return; 73 | const std::string file_path(settings_->GetColorSchemePreview(preset_[index].color_scheme_id)); 74 | if (file_path.empty()) return; 75 | image_.Destroy(); 76 | // it is from ansi coding, not utf8 77 | image_.Load(string_to_wstring(file_path).c_str()); 78 | if (!image_.IsNull()) { 79 | preview_.SetBitmap(image_); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /include/WeaselUtility.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | inline int utf8towcslen(const char* utf8_str, int utf8_len) 6 | { 7 | return MultiByteToWideChar(CP_UTF8, 0, utf8_str, utf8_len, NULL, 0); 8 | } 9 | 10 | inline std::wstring getUsername() { 11 | DWORD len = 0; 12 | GetUserName(NULL, &len); 13 | 14 | if (len <= 0) { 15 | return L""; 16 | } 17 | 18 | wchar_t *username = new wchar_t[len + 1]; 19 | 20 | GetUserName(username, &len); 21 | if (len <= 0) { 22 | delete[] username; 23 | return L""; 24 | } 25 | auto res = std::wstring(username); 26 | delete[] username; 27 | return res; 28 | } 29 | 30 | // data directories 31 | boost::filesystem::path WeaselSharedDataPath(); 32 | boost::filesystem::path WeaselUserDataPath(); 33 | 34 | inline BOOL IsUserDarkMode() 35 | { 36 | constexpr const LPCWSTR key = L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; 37 | constexpr const LPCWSTR value = L"AppsUseLightTheme"; 38 | 39 | DWORD type; 40 | DWORD data; 41 | DWORD size = sizeof(DWORD); 42 | LSTATUS st = RegGetValue(HKEY_CURRENT_USER, key, value, RRF_RT_REG_DWORD, &type, &data, &size); 43 | 44 | if (st == ERROR_SUCCESS && type == REG_DWORD) return data == 0; 45 | return false; 46 | } 47 | 48 | inline std::wstring string_to_wstring(const std::string& str, int code_page = CP_ACP) 49 | { 50 | // support CP_ACP and CP_UTF8 only 51 | if (code_page != 0 && code_page != CP_UTF8) return L""; 52 | // calc len 53 | int len = MultiByteToWideChar(code_page, 0, str.c_str(), (int)str.size(), NULL, 0); 54 | if(len <= 0) return L""; 55 | std::wstring res; 56 | TCHAR* buffer = new TCHAR[len + 1]; 57 | MultiByteToWideChar(code_page, 0, str.c_str(), (int)str.size(), buffer, len); 58 | buffer[len] = '\0'; 59 | res.append(buffer); 60 | delete[] buffer; 61 | return res; 62 | } 63 | 64 | inline std::string wstring_to_string(const std::wstring& wstr, int code_page = CP_ACP) 65 | { 66 | // support CP_ACP and CP_UTF8 only 67 | if (code_page != 0 && code_page != CP_UTF8) return ""; 68 | int len = WideCharToMultiByte(code_page, 0, wstr.c_str(), (int)wstr.size(), NULL, 0, NULL, NULL); 69 | if(len <= 0) return ""; 70 | std::string res; 71 | char* buffer = new char[len + 1]; 72 | WideCharToMultiByte(code_page, 0, wstr.c_str(), (int)wstr.size(), buffer, len, NULL, NULL); 73 | buffer[len] = '\0'; 74 | res.append(buffer); 75 | delete[] buffer; 76 | return res; 77 | } 78 | 79 | // resource 80 | std::string GetCustomResource(const char *name, const char *type); 81 | -------------------------------------------------------------------------------- /.github/workflows/commit-ci.yml: -------------------------------------------------------------------------------- 1 | name: Commit CI 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - '*' 8 | tags: 9 | - '![0-9]+.*' 10 | paths: 11 | - '**/**' 12 | - '!*.md' 13 | - '!.gitignore' 14 | pull_request: 15 | 16 | jobs: 17 | build: 18 | runs-on: windows-2022 19 | env: 20 | librime_build: 'submodule' 21 | boost_version: 1.84.0 22 | BOOST_ROOT: ${{ github.workspace }}\deps\boost_1_84_0 23 | steps: 24 | - name: Checkout last commit 25 | uses: actions/checkout@v3 26 | with: 27 | submodules: recursive 28 | 29 | - name: Configure build environment 30 | run: | 31 | copy env.vs2022.bat env.bat 32 | $git_ref_name = git describe --always 33 | echo "git_ref_name=$git_ref_name" >> $env:GITHUB_ENV 34 | 35 | - name: Cache Boost 36 | id: cache-boost 37 | uses: actions/cache@v3 38 | with: 39 | path: | 40 | ${{ env.BOOST_ROOT }} 41 | key: ${{ runner.os }}-boost-${{ env.boost_version }} 42 | 43 | - name: Install Boost 44 | if: steps.cache-boost.outputs.cache-hit != 'true' 45 | shell: bash 46 | run: | 47 | ./install_boost.bat 48 | ./build.bat boost arm64 49 | 50 | - name: Add msbuild to PATH 51 | uses: microsoft/setup-msbuild@v1.1.3 52 | 53 | - name: Copy Rime files 54 | if: env.librime_build == 'stable' 55 | run: .\github.install.bat 56 | 57 | - name: Build librime 58 | if: env.librime_build == 'submodule' 59 | env: 60 | RIME_PLUGINS: hchunhui/librime-lua lotem/librime-octagram rime/librime-predict 61 | shell: bash 62 | run: | 63 | # load plugins 64 | pushd librime 65 | ./action-install-plugins-windows.bat 66 | popd 67 | ./build.bat librime 68 | 69 | - name: Build Weasel 70 | id: build_weasel 71 | shell: bash 72 | run: | 73 | ./build.bat data 74 | ./build.bat hant arm64 75 | ./build.bat installer 76 | 77 | - name: Compress Debug Symbols 78 | shell: pwsh 79 | run: | 80 | Compress-Archive -Path output\*.pdb -CompressionLevel Optimal -DestinationPath .\output\archives\symbols.zip 81 | 82 | - name: Upload artifacts 83 | uses: actions/upload-artifact@v3 84 | with: 85 | if-no-files-found: error 86 | path: | 87 | .\output\archives\weasel*.exe 88 | .\output\archives\symbols.zip 89 | -------------------------------------------------------------------------------- /include/no_logging.h: -------------------------------------------------------------------------------- 1 | #ifndef RIME_NO_LOGGING_H_ 2 | #define RIME_NO_LOGGING_H_ 3 | 4 | namespace rime { 5 | 6 | class VoidLogger { 7 | public: 8 | VoidLogger() {} 9 | 10 | // hack: an unnamed VoidLogger() cannot be used as an l-value 11 | VoidLogger& stream() { return *this; } 12 | 13 | template 14 | VoidLogger& operator<< (const T& x) { return *this; } 15 | }; 16 | 17 | // to avoid compiler warnings 18 | class Voidify { 19 | public: 20 | Voidify() {} 21 | void operator& (VoidLogger&) {} 22 | }; 23 | 24 | } // namespace rime 25 | 26 | #define RIME_NO_LOG true ? (void) 0 : rime::Voidify() & rime::VoidLogger().stream() 27 | 28 | #define LOG(severity) RIME_NO_LOG 29 | #define VLOG(verboselevel) RIME_NO_LOG 30 | #define LOG_IF(severity, condition) RIME_NO_LOG 31 | #define LOG_EVERY_N(severity, n) RIME_NO_LOG 32 | #define LOG_IF_EVERY_N(severity, condition, n) RIME_NO_LOG 33 | #define LOG_ASSERT(condition) RIME_NO_LOG 34 | 35 | #define RIME_NO_CHECK (void) 0 36 | 37 | #define CHECK(condition) RIME_NO_CHECK 38 | #define CHECK_EQ(val1, val2) RIME_NO_CHECK 39 | #define CHECK_NE(val1, val2) RIME_NO_CHECK 40 | #define CHECK_LE(val1, val2) RIME_NO_CHECK 41 | #define CHECK_LT(val1, val2) RIME_NO_CHECK 42 | #define CHECK_GE(val1, val2) RIME_NO_CHECK 43 | #define CHECK_GT(val1, val2) RIME_NO_CHECK 44 | #define CHECK_NOTNULL(val) RIME_NO_CHECK 45 | #define CHECK_STREQ(str1, str2) RIME_NO_CHECK 46 | #define CHECK_STRCASEEQ(str1, str2) RIME_NO_CHECK 47 | #define CHECK_STRNE(str1, str2) RIME_NO_CHECK 48 | #define CHECK_STRCASENE(str1, str2) RIME_NO_CHECK 49 | 50 | #define DLOG(severity) LOG(severity) 51 | #define DVLOG(verboselevel) VLOG(verboselevel) 52 | #define DLOG_IF(severity, condition) LOG_IF(severity, condition) 53 | #define DLOG_EVERY_N(severity, n) LOG_EVERY_N(severity, n) 54 | #define DLOG_IF_EVERY_N(severity, condition, n) \ 55 | LOG_IF_EVERY_N(severity, condition, n) 56 | #define DLOG_ASSERT(condition) LOG_ASSERT(condition) 57 | 58 | #define DCHECK(condition) CHECK(condition) 59 | #define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2) 60 | #define DCHECK_NE(val1, val2) CHECK_NE(val1, val2) 61 | #define DCHECK_LE(val1, val2) CHECK_LE(val1, val2) 62 | #define DCHECK_LT(val1, val2) CHECK_LT(val1, val2) 63 | #define DCHECK_GE(val1, val2) CHECK_GE(val1, val2) 64 | #define DCHECK_GT(val1, val2) CHECK_GT(val1, val2) 65 | #define DCHECK_NOTNULL(val) CHECK_NOTNULL(val) 66 | #define DCHECK_STREQ(str1, str2) CHECK_STREQ(str1, str2) 67 | #define DCHECK_STRCASEEQ(str1, str2) CHECK_STRCASEEQ(str1, str2) 68 | #define DCHECK_STRNE(str1, str2) CHECK_STRNE(str1, str2) 69 | #define DCHECK_STRCASENE(str1, str2) CHECK_STRCASENE(str1, str2) 70 | 71 | #endif // RIME_NO_LOGGING_H_ 72 | -------------------------------------------------------------------------------- /WeaselDeployer/UIStyleSettings.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include 3 | #include "UIStyleSettings.h" 4 | 5 | 6 | UIStyleSettings::UIStyleSettings() 7 | { 8 | api_ = (RimeLeversApi*)rime_get_api()->find_module("levers")->get_api(); 9 | settings_ = api_->custom_settings_init("weasel", "Weasel::UIStyleSettings"); 10 | } 11 | 12 | bool UIStyleSettings::GetPresetColorSchemes(std::vector* result) { 13 | if (!result) return false; 14 | result->clear(); 15 | RimeConfig config = {0}; 16 | api_->settings_get_config(settings_, &config); 17 | RimeApi* rime = rime_get_api(); 18 | RimeConfigIterator preset = {0}; 19 | if (!rime->config_begin_map(&preset, &config, "preset_color_schemes")) { 20 | return false; 21 | } 22 | while (rime->config_next(&preset)) { 23 | std::string name_key(preset.path); 24 | name_key += "/name"; 25 | const char* name = rime->config_get_cstring(&config, name_key.c_str()); 26 | std::string author_key(preset.path); 27 | author_key += "/author"; 28 | const char* author = rime->config_get_cstring(&config, author_key.c_str()); 29 | if (!name) continue; 30 | ColorSchemeInfo info; 31 | info.color_scheme_id = preset.key; 32 | info.name = name; 33 | if (author) info.author = author; 34 | result->push_back(info); 35 | } 36 | return true; 37 | } 38 | 39 | // check if a file exists 40 | static inline bool IfFileExist(std::string filename) 41 | { 42 | DWORD dwAttrib = GetFileAttributes(string_to_wstring(filename).c_str()); 43 | return (INVALID_FILE_ATTRIBUTES != dwAttrib && 0 == (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); 44 | } 45 | 46 | // get preview image from user dir first, then shared_dir 47 | std::string UIStyleSettings::GetColorSchemePreview(const std::string& color_scheme_id) { 48 | std::string shared_dir = rime_get_api()->get_shared_data_dir(); 49 | std::string user_dir = rime_get_api()->get_user_data_dir(); 50 | std::string filename = user_dir + "\\preview\\color_scheme_" + color_scheme_id + ".png"; 51 | if (IfFileExist(filename)) 52 | return filename; 53 | else 54 | return (shared_dir + "\\preview\\color_scheme_" + color_scheme_id + ".png"); 55 | } 56 | 57 | std::string UIStyleSettings::GetActiveColorScheme() { 58 | RimeConfig config = {0}; 59 | api_->settings_get_config(settings_, &config); 60 | const char* value = rime_get_api()->config_get_cstring(&config, "style/color_scheme"); 61 | if (!value) return std::string(); 62 | return std::string(value); 63 | } 64 | 65 | bool UIStyleSettings::SelectColorScheme(const std::string& color_scheme_id) { 66 | api_->customize_string(settings_, "style/color_scheme", color_scheme_id.c_str()); 67 | return true; 68 | } 69 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | # How to Rime with Weasel 2 | 3 | ## Preparation 4 | 5 | - Install **Visual Studio 2017** for *Desktop development in C++* 6 | with components *ATL*, *MFC* and *Windows XP support*. 7 | Visual Studio 2015 or later versions may work with additional configuration. 8 | 9 | - Install dev tools: `git`, `cmake` 10 | 11 | - Download third-party libraries: `boost(>=1.60.0)` 12 | 13 | Optional: 14 | 15 | - install `bash` via *Git for Windows*, for installing data files with `plum`; 16 | - install `python` for building OpenCC dictionaries; 17 | - install [NSIS](http://nsis.sourceforge.net/Download) for creating installer. 18 | 19 | ## Checkout source code 20 | 21 | Make sure all git submodules are checked out recursively. 22 | 23 | ```batch 24 | git clone --recursive https://github.com/rime/weasel.git 25 | ``` 26 | 27 | ## Build and Install Weasel 28 | 29 | Locate `weasel` source directory. 30 | 31 | ### Setup build environment 32 | 33 | Edit your build environment settings in `env.bat`. 34 | You can create the file by copying `env.bat.template` in the source tree. 35 | 36 | Make sure `BOOST_ROOT` is set to the existing path `X:\path\to\boost_`. 37 | 38 | When using a different version of Visual Studio or platform toolset, un-comment 39 | lines to set corresponding variables. 40 | 41 | Alternatively, start a *Developer Command Prompt* window and set environment 42 | variables directly in the console, before invocation of `build.bat`: 43 | 44 | ```batch 45 | set BOOST_ROOT=X:\path\to\boost_N_NN_N 46 | ``` 47 | 48 | ### Build 49 | 50 | ```batch 51 | cd weasel 52 | build.bat all 53 | ``` 54 | 55 | Voila. 56 | 57 | Installer will be generated in `output\archives` directory. 58 | 59 | ### Alternative: using prebuilt Rime binaries 60 | 61 | If you've already got a copy of prebuilt binaries of librime, you can simply 62 | copy `.dll`s / `.lib`s into `weasel\output` / `weasel\lib` directories 63 | respectively, then build Weasel without the `all` command line option. 64 | 65 | ```batch 66 | build.bat boost data opencc 67 | build.bat weasel 68 | ``` 69 | 70 | ### Install and try it live 71 | 72 | ```batch 73 | cd output 74 | install.bat 75 | ``` 76 | 77 | ### Optional: play with Rime command line tools 78 | 79 | `librime` comes with a REPL application which can be used to test if the library 80 | is working. 81 | 82 | ```batch 83 | cd librime 84 | copy /Y build\lib\Release\rime.dll build\bin 85 | cd build\bin 86 | echo zhongzhouyunshurufa | Release\rime_api_console.exe > output.txt 87 | ``` 88 | 89 | Instead of redirecting output to a file, you can set appropriate code page 90 | (`chcp 65001`) and font in the console to work with the REPL interactively. 91 | -------------------------------------------------------------------------------- /WeaselServer/WeaselTrayIcon.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "WeaselTrayIcon.h" 3 | 4 | // nasty 5 | #include 6 | 7 | static UINT mode_icon[] = { IDI_ZH, IDI_ZH, IDI_EN, IDI_RELOAD }; 8 | static const WCHAR *mode_label[] = { NULL, /*L"中文"*/ NULL, /*L"西文"*/ NULL, L"維護中" }; 9 | 10 | WeaselTrayIcon::WeaselTrayIcon(weasel::UI &ui) 11 | : m_style(ui.style()), m_status(ui.status()), m_mode(INITIAL), m_schema_zhung_icon(), m_schema_ascii_icon(), m_disabled(false) 12 | { 13 | } 14 | 15 | void WeaselTrayIcon::CustomizeMenu(HMENU hMenu) 16 | { 17 | } 18 | 19 | BOOL WeaselTrayIcon::Create(HWND hTargetWnd) 20 | { 21 | HMODULE hModule = GetModuleHandle(NULL); 22 | CIcon icon; 23 | icon.LoadIconW(IDI_ZH); 24 | BOOL bRet = CSystemTray::Create(hModule, NULL, WM_WEASEL_TRAY_NOTIFY, 25 | WEASEL_IME_NAME, icon, IDR_MENU_POPUP); 26 | if (hTargetWnd) 27 | { 28 | SetTargetWnd(hTargetWnd); 29 | } 30 | if (!m_style.display_tray_icon) 31 | { 32 | RemoveIcon(); 33 | } 34 | return bRet; 35 | } 36 | 37 | void WeaselTrayIcon::Refresh() 38 | { 39 | if (!m_style.display_tray_icon && !m_status.disabled) // display notification when deploying 40 | { 41 | if (m_mode != INITIAL) 42 | { 43 | RemoveIcon(); 44 | m_mode = INITIAL; 45 | } 46 | m_disabled = false; 47 | return; 48 | } 49 | WeaselTrayMode mode = m_status.disabled ? DISABLED : 50 | m_status.ascii_mode ? ASCII : ZHUNG; 51 | /* change icon, when 52 | 1,mode changed 53 | 2,icon changed 54 | 3,both m_schema_zhung_icon and m_style.current_zhung_icon empty(for initialize) 55 | 4,both m_schema_ascii_icon and m_style.current_ascii_icon empty(for initialize) 56 | */ 57 | if (mode != m_mode 58 | || m_schema_zhung_icon != m_style.current_zhung_icon 59 | || (m_schema_zhung_icon.empty() && m_style.current_zhung_icon.empty()) 60 | || m_schema_ascii_icon != m_style.current_ascii_icon 61 | || (m_schema_ascii_icon.empty() && m_style.current_ascii_icon.empty()) 62 | ) 63 | { 64 | ShowIcon(); 65 | m_mode = mode; 66 | m_schema_zhung_icon = m_style.current_zhung_icon; 67 | m_schema_ascii_icon = m_style.current_ascii_icon; 68 | if(mode == ASCII) { 69 | if(m_schema_ascii_icon.empty()) 70 | SetIcon(mode_icon[mode]); 71 | else 72 | SetIcon(m_schema_ascii_icon.c_str()); 73 | } 74 | else if(mode == ZHUNG) { 75 | if(m_schema_zhung_icon.empty()) 76 | SetIcon(mode_icon[mode]); 77 | else 78 | SetIcon(m_schema_zhung_icon.c_str()); 79 | } 80 | else 81 | SetIcon(mode_icon[mode]); 82 | 83 | if (mode_label[mode] && m_disabled == false) 84 | { 85 | ShowBalloon(mode_label[mode], WEASEL_IME_NAME); 86 | m_disabled = true; 87 | } 88 | if(m_mode != DISABLED) 89 | m_disabled = false; 90 | } 91 | else if (!Visible()) 92 | { 93 | ShowIcon(); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /WeaselSetup/InstallOptionsDlg.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "InstallOptionsDlg.h" 3 | #include 4 | 5 | int uninstall(bool silent); 6 | 7 | InstallOptionsDialog::InstallOptionsDialog() 8 | : installed(false), hant(false), user_dir() 9 | { 10 | } 11 | 12 | InstallOptionsDialog::~InstallOptionsDialog() 13 | { 14 | } 15 | 16 | LRESULT InstallOptionsDialog::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) { 17 | cn_.Attach(GetDlgItem(IDC_RADIO_CN)); 18 | tw_.Attach(GetDlgItem(IDC_RADIO_TW)); 19 | remove_.Attach(GetDlgItem(IDC_REMOVE)); 20 | default_dir_.Attach(GetDlgItem(IDC_RADIO_DEFAULT_DIR)); 21 | custom_dir_.Attach(GetDlgItem(IDC_RADIO_CUSTOM_DIR)); 22 | dir_.Attach(GetDlgItem(IDC_EDIT_DIR)); 23 | 24 | CheckRadioButton(IDC_RADIO_CN, IDC_RADIO_TW, 25 | (hant ? IDC_RADIO_TW : IDC_RADIO_CN)); 26 | CheckRadioButton(IDC_RADIO_DEFAULT_DIR, IDC_RADIO_CUSTOM_DIR, 27 | (user_dir.empty() ? IDC_RADIO_DEFAULT_DIR : IDC_RADIO_CUSTOM_DIR)); 28 | dir_.SetWindowTextW(user_dir.c_str()); 29 | 30 | cn_.EnableWindow(!installed); 31 | tw_.EnableWindow(!installed); 32 | remove_.EnableWindow(installed); 33 | dir_.EnableWindow(user_dir.empty() ? FALSE : TRUE); 34 | 35 | ok_.Attach(GetDlgItem(IDOK)); 36 | if (installed) { 37 | CString str; 38 | str.LoadStringW(IDS_STRING_MODIFY); 39 | ok_.SetWindowTextW(str); 40 | } 41 | 42 | ime_.Attach(GetDlgItem(IDC_CHECK_INSTIME)); 43 | if (installed) 44 | ime_.EnableWindow(FALSE); 45 | 46 | CenterWindow(); 47 | return 0; 48 | } 49 | 50 | LRESULT InstallOptionsDialog::OnClose(UINT, WPARAM, LPARAM, BOOL&) { 51 | EndDialog(IDCANCEL); 52 | return 0; 53 | } 54 | 55 | LRESULT InstallOptionsDialog::OnOK(WORD, WORD code, HWND, BOOL&) { 56 | hant = (IsDlgButtonChecked(IDC_RADIO_TW) == BST_CHECKED); 57 | old_ime_support = (IsDlgButtonChecked(IDC_CHECK_INSTIME) == BST_CHECKED); 58 | if (IsDlgButtonChecked(IDC_RADIO_CUSTOM_DIR) == BST_CHECKED) { 59 | CStringW text; 60 | dir_.GetWindowTextW(text); 61 | user_dir = text; 62 | } 63 | else { 64 | user_dir.clear(); 65 | } 66 | EndDialog(IDOK); 67 | return 0; 68 | } 69 | 70 | LRESULT InstallOptionsDialog::OnRemove(WORD, WORD code, HWND, BOOL&) { 71 | const bool non_silent = false; 72 | uninstall(non_silent); 73 | installed = false; 74 | ime_.EnableWindow(!installed); 75 | CString str; 76 | str.LoadStringW(IDS_STRING_INSTALL); 77 | ok_.SetWindowTextW(str); 78 | cn_.EnableWindow(!installed); 79 | tw_.EnableWindow(!installed); 80 | remove_.EnableWindow(installed); 81 | return 0; 82 | } 83 | 84 | LRESULT InstallOptionsDialog::OnUseDefaultDir(WORD, WORD code, HWND, BOOL&) { 85 | dir_.EnableWindow(FALSE); 86 | return 0; 87 | } 88 | 89 | LRESULT InstallOptionsDialog::OnUseCustomDir(WORD, WORD code, HWND, BOOL&) { 90 | dir_.EnableWindow(TRUE); 91 | dir_.SetFocus(); 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /WeaselIME/WeaselIME.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | 35 | 36 | Source Files 37 | 38 | 39 | 40 | Resource Files 41 | 42 | 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | Header Files 55 | 56 | 57 | Header Files 58 | 59 | 60 | Header Files 61 | 62 | 63 | Header Files 64 | 65 | 66 | Header Files 67 | 68 | 69 | 70 | 71 | Resource Files 72 | 73 | 74 | -------------------------------------------------------------------------------- /WeaselDeployer/WeaselDeployer.cpp: -------------------------------------------------------------------------------- 1 | // WeaselDeployer.cpp : Defines the entry point for the application. 2 | // 3 | #include "stdafx.h" 4 | #include 5 | #include 6 | #include "WeaselDeployer.h" 7 | #include "Configurator.h" 8 | 9 | CAppModule _Module; 10 | 11 | static int Run(LPTSTR lpCmdLine); 12 | 13 | int APIENTRY _tWinMain(HINSTANCE hInstance, 14 | HINSTANCE hPrevInstance, 15 | LPTSTR lpCmdLine, 16 | int nCmdShow) 17 | { 18 | UNREFERENCED_PARAMETER(hPrevInstance); 19 | 20 | LCID lcid = GetUserDefaultLCID(); 21 | if (lcid == 2052 || lcid == 3072 || lcid == 4100) { 22 | LANGID langId = SetThreadUILanguage(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)); 23 | SetThreadLocale(langId); 24 | } 25 | else { 26 | LANGID langId = SetThreadUILanguage(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)); 27 | SetThreadLocale(langId); 28 | } 29 | 30 | HRESULT hRes = ::CoInitialize(NULL); 31 | // If you are running on NT 4.0 or higher you can use the following call instead to 32 | // make the EXE free threaded. This means that calls come in on a random RPC thread. 33 | //HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); 34 | ATLASSERT(SUCCEEDED(hRes)); 35 | 36 | // this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used 37 | ::DefWindowProc(NULL, 0, 0, 0L); 38 | 39 | AtlInitCommonControls(ICC_BAR_CLASSES); // add flags to support other controls 40 | 41 | hRes = _Module.Init(NULL, hInstance); 42 | ATLASSERT(SUCCEEDED(hRes)); 43 | 44 | CreateDirectory(WeaselUserDataPath().c_str(), NULL); 45 | 46 | int ret = 0; 47 | HANDLE hMutex = CreateMutex(NULL, TRUE, L"WeaselDeployerExclusiveMutex"); 48 | if (!hMutex) 49 | { 50 | ret = 1; 51 | } 52 | else if (GetLastError() == ERROR_ALREADY_EXISTS) 53 | { 54 | ret = 1; 55 | } 56 | else 57 | { 58 | ret = Run(lpCmdLine); 59 | } 60 | 61 | if (hMutex) 62 | { 63 | CloseHandle(hMutex); 64 | } 65 | _Module.Term(); 66 | ::CoUninitialize(); 67 | 68 | return ret; 69 | } 70 | 71 | static int Run(LPTSTR lpCmdLine) 72 | { 73 | Configurator configurator; 74 | configurator.Initialize(); 75 | bool deployment_scheduled = !wcscmp(L"/deploy", lpCmdLine); 76 | if (deployment_scheduled) 77 | { 78 | return configurator.UpdateWorkspace(); 79 | } 80 | 81 | bool dict_management = !wcscmp(L"/dict", lpCmdLine); 82 | if (dict_management) 83 | { 84 | return configurator.DictManagement(); 85 | } 86 | 87 | bool sync_user_dict = !wcscmp(L"/sync", lpCmdLine); 88 | if (sync_user_dict) 89 | { 90 | return configurator.SyncUserData(); 91 | } 92 | 93 | bool installing = !wcscmp(L"/install", lpCmdLine); 94 | return configurator.Run(installing); 95 | } -------------------------------------------------------------------------------- /WeaselTSF/CandidateList.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "ctffunc.h" 4 | 5 | class WeaselTSF; 6 | 7 | class CCandidateList : 8 | public ITfIntegratableCandidateListUIElement, 9 | public ITfCandidateListUIElementBehavior 10 | { 11 | public: 12 | CCandidateList(com_ptr pTextService); 13 | ~CCandidateList(); 14 | 15 | // IUnknown 16 | STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj); 17 | STDMETHODIMP_(ULONG) AddRef(void); 18 | STDMETHODIMP_(ULONG) Release(void); 19 | 20 | // ITfUIElement 21 | STDMETHODIMP GetDescription(BSTR *pbstr); 22 | STDMETHODIMP GetGUID(GUID *pguid); 23 | STDMETHODIMP Show(BOOL showCandidateWindow); 24 | STDMETHODIMP IsShown(BOOL *pIsShow); 25 | 26 | // ITfCandidateListUIElement 27 | STDMETHODIMP GetUpdatedFlags(DWORD *pdwFlags); 28 | STDMETHODIMP GetDocumentMgr(ITfDocumentMgr **ppdim); 29 | STDMETHODIMP GetCount(UINT *pCandidateCount); 30 | STDMETHODIMP GetSelection(UINT *pSelectedCandidateIndex); 31 | STDMETHODIMP GetString(UINT uIndex, BSTR *pbstr); 32 | STDMETHODIMP GetPageIndex(UINT *pIndex, UINT uSize, UINT *puPageCnt); 33 | STDMETHODIMP SetPageIndex(UINT *pIndex, UINT uPageCnt); 34 | STDMETHODIMP GetCurrentPage(UINT *puPage); 35 | 36 | // ITfCandidateListUIElementBehavior methods 37 | STDMETHODIMP SetSelection(UINT nIndex); 38 | STDMETHODIMP Finalize(void); 39 | STDMETHODIMP Abort(void); 40 | 41 | // ITfIntegratableCandidateListUIElement methods 42 | STDMETHODIMP SetIntegrationStyle(GUID guidIntegrationStyle); 43 | STDMETHODIMP GetSelectionStyle(_Out_ TfIntegratableCandidateListSelectionStyle *ptfSelectionStyle); 44 | STDMETHODIMP OnKeyDown(_In_ WPARAM wParam, _In_ LPARAM lParam, _Out_ BOOL *pIsEaten); 45 | STDMETHODIMP ShowCandidateNumbers(_Out_ BOOL *pIsShow); 46 | STDMETHODIMP FinalizeExactCompositionString(); 47 | 48 | /* Update */ 49 | void UpdateUI(const weasel::Context &ctx, const weasel::Status &status); 50 | void UpdateStyle(const weasel::UIStyle &sty); 51 | void UpdateInputPosition(RECT const& rc); 52 | void Destroy(); 53 | void StartUI(); 54 | void EndUI(); 55 | 56 | com_ptr GetContextDocument(); 57 | bool GetIsReposition(){ if(_ui) return _ui->GetIsReposition(); else return false; } 58 | 59 | weasel::UIStyle &style(); 60 | 61 | 62 | private: 63 | //void _UpdateOwner(); 64 | HWND _GetActiveWnd(); 65 | HRESULT _UpdateUIElement(); 66 | 67 | // for CCandidateList::EndUI(), after ending composition || WeaselTSF::_EndUI() 68 | void _DisposeUIWindow(); 69 | // for CCandidateList::Destroy(), when inputing app exit 70 | void _DisposeUIWindowAll(); 71 | void _MakeUIWindow(); 72 | 73 | std::unique_ptr _ui; 74 | DWORD _cRef; 75 | com_ptr _tsf; 76 | DWORD uiid; 77 | TfIntegratableCandidateListSelectionStyle _selectionStyle = STYLE_ACTIVE_SELECTION; 78 | 79 | BOOL _pbShow; 80 | weasel::UIStyle _style; 81 | 82 | com_ptr _pContextDocument; 83 | }; 84 | 85 | -------------------------------------------------------------------------------- /include/winsparkle-version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of WinSparkle (https://winsparkle.org) 3 | * 4 | * Copyright (C) 2009-2018 Vaclav Slavik 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #ifndef _winsparkle_version_h_ 27 | #define _winsparkle_version_h_ 28 | 29 | /*--------------------------------------------------------------------------* 30 | Version information 31 | *--------------------------------------------------------------------------*/ 32 | 33 | #define WIN_SPARKLE_VERSION_MAJOR 0 34 | #define WIN_SPARKLE_VERSION_MINOR 6 35 | #define WIN_SPARKLE_VERSION_MICRO 0 36 | 37 | /** 38 | Checks if WinSparkle version is at least @a major.@a minor.@a micro. 39 | */ 40 | #define WIN_SPARKLE_CHECK_VERSION(major, minor, micro) \ 41 | ( \ 42 | WIN_SPARKLE_VERSION_MAJOR > (major) \ 43 | || \ 44 | (WIN_SPARKLE_VERSION_MAJOR == (major) && \ 45 | WIN_SPARKLE_VERSION_MINOR >= (minor)) \ 46 | || \ 47 | (WIN_SPARKLE_VERSION_MAJOR == (major) && \ 48 | WIN_SPARKLE_VERSION_MINOR == (minor) && \ 49 | WIN_SPARKLE_VERSION_MICRO >= (micro)) \ 50 | ) 51 | 52 | #define _WIN_SPARKLE_MAKE_STR(x) #x 53 | #define _WIN_SPARKLE_MAKE_VERSION_STR(a,b,c) \ 54 | _WIN_SPARKLE_MAKE_STR(a) "." _WIN_SPARKLE_MAKE_STR(b) "." _WIN_SPARKLE_MAKE_STR(c) 55 | 56 | /** 57 | WinSparkle version as a string in the form of e.g. "0.1.3". 58 | */ 59 | #define WIN_SPARKLE_VERSION_STRING \ 60 | _WIN_SPARKLE_MAKE_VERSION_STR(WIN_SPARKLE_VERSION_MAJOR, \ 61 | WIN_SPARKLE_VERSION_MINOR, \ 62 | WIN_SPARKLE_VERSION_MICRO) 63 | 64 | #endif // _winsparkle_version_h_ 65 | -------------------------------------------------------------------------------- /WeaselServer/WeaselServer.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {841353c8-3e06-48cf-a570-3bce154c1f21} 6 | cpp;c;cxx;def;odl;idl;hpj;bat;asm 7 | 8 | 9 | {e582dfc5-c00c-4d4d-b0fe-64b8e430605e} 10 | h;hpp;hxx;hm;inl;inc 11 | 12 | 13 | {cdf05528-dd52-45e1-8ae4-63e02af799fb} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | Header Files 55 | 56 | 57 | 58 | 59 | Resource Files 60 | 61 | 62 | 63 | 64 | Resource Files 65 | 66 | 67 | Resource Files 68 | 69 | 70 | Resource Files 71 | 72 | 73 | Resource Files 74 | 75 | 76 | 77 | 78 | Resource Files 79 | 80 | 81 | Resource Files 82 | 83 | 84 | -------------------------------------------------------------------------------- /WeaselTSF/Server.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "Globals.h" 4 | #include "Register.h" 5 | #include "WeaselTSF.h" 6 | #include 7 | 8 | void DllAddRef() 9 | { 10 | InterlockedIncrement(&g_cRefDll); 11 | } 12 | 13 | void DllRelease() 14 | { 15 | InterlockedDecrement(&g_cRefDll); 16 | } 17 | 18 | class CClassFactory: public IClassFactory 19 | { 20 | public: 21 | // IUnknown methods 22 | STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject); 23 | STDMETHODIMP_(ULONG) AddRef(); 24 | STDMETHODIMP_(ULONG) Release(); 25 | 26 | // IClassFactory methods 27 | STDMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject); 28 | STDMETHODIMP LockServer(BOOL fLock); 29 | }; 30 | 31 | STDAPI CClassFactory::QueryInterface(REFIID riid, void **ppvObject) 32 | { 33 | if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown)) 34 | { 35 | *ppvObject = this; 36 | DllAddRef(); 37 | return NOERROR; 38 | } 39 | *ppvObject = NULL; 40 | return E_NOINTERFACE; 41 | } 42 | 43 | STDAPI_(ULONG) CClassFactory::AddRef() 44 | { 45 | DllAddRef(); 46 | return g_cRefDll + 1; 47 | } 48 | 49 | STDAPI_(ULONG) CClassFactory::Release() 50 | { 51 | DllRelease(); 52 | return g_cRefDll + 1; 53 | } 54 | 55 | STDAPI CClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject) 56 | { 57 | WeaselTSF *pCase; 58 | HRESULT hr; 59 | if (ppvObject == NULL) 60 | return E_INVALIDARG; 61 | *ppvObject = NULL; 62 | if (pUnkOuter != NULL) 63 | return CLASS_E_NOAGGREGATION; 64 | if ((pCase = new WeaselTSF()) == NULL) 65 | return E_OUTOFMEMORY; 66 | hr = pCase->QueryInterface(riid, ppvObject); 67 | pCase->Release(); // caller still holds ref if hr == S_OK 68 | return hr; 69 | } 70 | 71 | STDAPI CClassFactory::LockServer(BOOL fLock) 72 | { 73 | if (fLock) 74 | DllAddRef(); 75 | else 76 | DllRelease(); 77 | return S_OK; 78 | } 79 | 80 | static CClassFactory *g_classFactory = NULL; 81 | 82 | static void BuildGlobalObjects() 83 | { 84 | g_classFactory = new CClassFactory(); 85 | } 86 | 87 | STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppvObject) 88 | { 89 | if (g_classFactory == NULL) 90 | { 91 | EnterCriticalSection(&g_cs); 92 | if (g_classFactory == NULL) 93 | BuildGlobalObjects(); 94 | LeaveCriticalSection(&g_cs); 95 | } 96 | if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown)) 97 | { 98 | *ppvObject = g_classFactory; 99 | DllAddRef(); 100 | return NOERROR; 101 | } 102 | *ppvObject = NULL; 103 | return CLASS_E_CLASSNOTAVAILABLE; 104 | } 105 | 106 | STDAPI DllCanUnloadNow() 107 | { 108 | if (g_cRefDll >= 0) 109 | return S_FALSE; 110 | return S_OK; 111 | } 112 | 113 | STDAPI DllRegisterServer() 114 | { 115 | if (!RegisterServer() || !RegisterProfiles() || !RegisterCategories()) 116 | { 117 | DllUnregisterServer(); 118 | return E_FAIL; 119 | } 120 | return S_OK; 121 | } 122 | 123 | STDAPI DllUnregisterServer() 124 | { 125 | UnregisterProfiles(); 126 | UnregisterCategories(); 127 | UnregisterServer(); 128 | return S_OK; 129 | } 130 | -------------------------------------------------------------------------------- /test/TestResponseParser/TestResponseParser.cpp: -------------------------------------------------------------------------------- 1 | // TestResponseParser.cpp : Defines the entry point for the console application. 2 | // 3 | 4 | #include "stdafx.h" 5 | #include 6 | #include 7 | #include 8 | 9 | void test_1() 10 | { 11 | WCHAR resp[] = 12 | L"action=noop\n" 13 | ; 14 | DWORD len = wcslen(resp); 15 | std::wstring commit; 16 | weasel::Context ctx; 17 | weasel::Status status; 18 | weasel::ResponseParser parser(&commit, &ctx, &status); 19 | parser(resp, len); 20 | BOOST_TEST(commit.empty()); 21 | BOOST_TEST(ctx.empty()); 22 | } 23 | 24 | void test_2() 25 | { 26 | WCHAR resp[] = 27 | L"action=commit\n" 28 | L"commit=教這句話上屏=3.14\n" 29 | ; 30 | DWORD len = wcslen(resp); 31 | std::wstring commit; 32 | weasel::Context ctx; 33 | weasel::Status status; 34 | ctx.aux.str = L"從前的值"; 35 | weasel::ResponseParser parser(&commit, &ctx, &status); 36 | parser(resp, len); 37 | BOOST_TEST(commit == L"教這句話上屏=3.14"); 38 | BOOST_TEST(ctx.preedit.empty()); 39 | BOOST_TEST(ctx.aux.str == L"從前的值"); 40 | BOOST_TEST(ctx.cinfo.candies.empty()); 41 | } 42 | 43 | void test_3() 44 | { 45 | WCHAR resp[] = 46 | L"action=ctx\n" 47 | L"ctx.preedit=寫作串=3.14\n" 48 | L"ctx.aux=sie'zuoh'chuan=3.14\n" 49 | ; 50 | DWORD len = wcslen(resp); 51 | std::wstring commit; 52 | weasel::Context ctx; 53 | weasel::Status status; 54 | weasel::ResponseParser parser(&commit, &ctx, &status); 55 | parser(resp, len); 56 | BOOST_TEST(commit.empty()); 57 | BOOST_TEST(ctx.preedit.str == L"寫作串=3.14"); 58 | BOOST_TEST(ctx.preedit.attributes.empty()); 59 | BOOST_TEST(ctx.aux.str == L"sie'zuoh'chuan=3.14"); 60 | } 61 | 62 | void test_4() 63 | { 64 | WCHAR resp[] = 65 | L"action=commit,ctx\n" 66 | L"ctx.preedit=候選乙=3.14\n" 67 | L"ctx.preedit.cursor=0,3\n" 68 | L"ctx.cand.length=2\n" 69 | L"ctx.cand.0=候選甲\n" 70 | L"ctx.cand.1=候選乙\n" 71 | L"ctx.cand.cursor=1\n" 72 | L"ctx.cand.page=0/1\n" 73 | ; 74 | DWORD len = wcslen(resp); 75 | std::wstring commit; 76 | weasel::Context ctx; 77 | weasel::Status status; 78 | weasel::ResponseParser parser(&commit, &ctx, &status); 79 | parser(resp, len); 80 | BOOST_TEST(commit.empty()); 81 | BOOST_TEST(ctx.preedit.str == L"候選乙=3.14"); 82 | BOOST_ASSERT(1 == ctx.preedit.attributes.size()); 83 | weasel::TextAttribute attr0 = ctx.preedit.attributes[0]; 84 | BOOST_TEST_EQ(weasel::HIGHLIGHTED, attr0.type); 85 | BOOST_TEST_EQ(0, attr0.range.start); 86 | BOOST_TEST_EQ(3, attr0.range.end); 87 | BOOST_TEST(ctx.aux.empty()); 88 | weasel::CandidateInfo& c = ctx.cinfo; 89 | BOOST_ASSERT(2 == c.candies.size()); 90 | BOOST_TEST(c.candies[0].str == L"候選甲"); 91 | BOOST_TEST(c.candies[1].str == L"候選乙"); 92 | BOOST_TEST_EQ(1, c.highlighted); 93 | BOOST_TEST_EQ(0, c.currentPage); 94 | BOOST_TEST_EQ(1, c.totalPages); 95 | } 96 | 97 | int _tmain(int argc, _TCHAR* argv[]) 98 | { 99 | test_1(); 100 | test_2(); 101 | test_3(); 102 | test_4(); 103 | 104 | system("pause"); 105 | return boost::report_errors(); 106 | } 107 | 108 | -------------------------------------------------------------------------------- /WeaselDeployer/WeaselDeployer.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | 47 | 48 | Source Files 49 | 50 | 51 | Source Files 52 | 53 | 54 | Source Files 55 | 56 | 57 | Source Files 58 | 59 | 60 | Source Files 61 | 62 | 63 | Source Files 64 | 65 | 66 | Source Files 67 | 68 | 69 | Source Files 70 | 71 | 72 | 73 | 74 | Resource Files 75 | 76 | 77 | 78 | 79 | Resource Files 80 | 81 | 82 | -------------------------------------------------------------------------------- /WeaselUI/StandardLayout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Layout.h" 4 | #include 5 | #include 6 | #pragma comment(lib, "d2d1.lib") 7 | #pragma comment(lib, "dwrite.lib") 8 | 9 | namespace weasel 10 | { 11 | const int MAX_CANDIDATES_COUNT = 100; 12 | const int STATUS_ICON_SIZE = GetSystemMetrics(SM_CXICON); 13 | 14 | class StandardLayout: public Layout 15 | { 16 | public: 17 | StandardLayout(const UIStyle &style, const Context &context, const Status &status) : Layout(style, context, status){} 18 | 19 | /* Layout */ 20 | 21 | virtual void DoLayout(CDCHandle dc, PDWR pDWR = NULL) = 0; 22 | virtual CSize GetContentSize() const { return _contentSize; } 23 | virtual CRect GetPreeditRect() const { return _preeditRect; } 24 | virtual CRect GetAuxiliaryRect() const { return _auxiliaryRect; } 25 | virtual CRect GetHighlightRect() const { return _highlightRect; } 26 | virtual CRect GetCandidateLabelRect(int id) const { return _candidateLabelRects[id]; } 27 | virtual CRect GetCandidateTextRect(int id) const { return _candidateTextRects[id]; } 28 | virtual CRect GetCandidateCommentRect(int id) const { return _candidateCommentRects[id]; } 29 | virtual CRect GetCandidateRect(int id) const { return _candidateRects[id]; } 30 | virtual CRect GetStatusIconRect() const { return _statusIconRect; } 31 | virtual std::wstring GetLabelText(const std::vector &labels, int id, const wchar_t *format) const; 32 | virtual bool IsInlinePreedit() const; 33 | virtual bool ShouldDisplayStatusIcon() const; 34 | virtual IsToRoundStruct GetRoundInfo(int id) { return _roundInfo[id]; } 35 | virtual IsToRoundStruct GetTextRoundInfo() { return _textRoundInfo; } 36 | virtual CRect GetContentRect() { return _contentRect; } 37 | virtual CRect GetPrepageRect() { return _prePageRect; } 38 | virtual CRect GetNextpageRect() { return _nextPageRect; } 39 | virtual CSize GetBeforeSize() { return _beforesz; } 40 | virtual CSize GetHilitedSize() { return _hilitedsz; } 41 | virtual CSize GetAfterSize() { return _aftersz; } 42 | virtual weasel::TextRange GetPreeditRange() { return _range; } 43 | 44 | void GetTextSizeDW(const std::wstring text, size_t nCount, ComPtr pTextFormat, PDWR pDWR, LPSIZE lpSize) const; 45 | 46 | protected: 47 | /* Utility functions */ 48 | CSize GetPreeditSize(CDCHandle dc, const weasel::Text& text, ComPtr pTextFormat = NULL, PDWR pDWR = NULL); 49 | bool _IsHighlightOverCandidateWindow(CRect& rc, CDCHandle& dc); 50 | void _PrepareRoundInfo(CDCHandle& dc); 51 | 52 | void UpdateStatusIconLayout(int* width, int* height); 53 | 54 | CSize _beforesz, _hilitedsz, _aftersz; 55 | weasel::TextRange _range; 56 | CSize _contentSize; 57 | CRect _preeditRect, _auxiliaryRect, _highlightRect; 58 | CRect _candidateRects[MAX_CANDIDATES_COUNT]; 59 | CRect _candidateLabelRects[MAX_CANDIDATES_COUNT]; 60 | CRect _candidateTextRects[MAX_CANDIDATES_COUNT]; 61 | CRect _candidateCommentRects[MAX_CANDIDATES_COUNT]; 62 | CRect _statusIconRect; 63 | CRect _bgRect; 64 | CRect _contentRect; 65 | IsToRoundStruct _roundInfo[MAX_CANDIDATES_COUNT]; 66 | IsToRoundStruct _textRoundInfo; 67 | CRect _prePageRect; 68 | CRect _nextPageRect; 69 | const std::wstring pre = L"<"; 70 | const std::wstring next = L">"; 71 | }; 72 | }; 73 | -------------------------------------------------------------------------------- /WeaselTSF/DisplayAttributeInfo.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "DisplayAttributeInfo.h" 4 | #include "Globals.h" 5 | 6 | const WCHAR _daiInputName[] = L"DisplayAttributeInput"; 7 | const WCHAR _daiDescription[] = L"Weasel Display Attribute Input"; 8 | 9 | // change style only, leave color to app 10 | const TF_DISPLAYATTRIBUTE _daiDisplayAttribute = 11 | { 12 | { TF_CT_NONE, 0 }, // text color 13 | { TF_CT_NONE, 0 }, // background color (TF_CT_NONE => app default) 14 | TF_LS_DOT, // underline style 15 | FALSE, // underline boldness 16 | { TF_CT_NONE, 0 }, // underline color 17 | TF_ATTR_INPUT // attribute info 18 | }; 19 | 20 | CDisplayAttributeInfoInput::CDisplayAttributeInfoInput() 21 | { 22 | DllAddRef(); 23 | _refCount = 1; 24 | 25 | _pguid = &c_guidDisplayAttributeInput; 26 | _pDisplayAttribute = &_daiDisplayAttribute; 27 | _pDescription = _daiDescription; 28 | _pValueName = _daiInputName; 29 | } 30 | 31 | CDisplayAttributeInfoInput::~CDisplayAttributeInfoInput() 32 | { 33 | DllRelease(); 34 | } 35 | 36 | STDAPI CDisplayAttributeInfoInput::QueryInterface(REFIID riid, _Outptr_ void** ppvObj) 37 | { 38 | if (ppvObj == nullptr) 39 | return E_INVALIDARG; 40 | 41 | *ppvObj = nullptr; 42 | 43 | if (IsEqualIID(riid, IID_IUnknown) || 44 | IsEqualIID(riid, IID_ITfDisplayAttributeInfo)) 45 | { 46 | *ppvObj = (ITfDisplayAttributeInfo*)this; 47 | } 48 | 49 | if (*ppvObj) 50 | { 51 | AddRef(); 52 | return S_OK; 53 | } 54 | 55 | return E_NOINTERFACE; 56 | } 57 | 58 | ULONG CDisplayAttributeInfoInput::AddRef(void) 59 | { 60 | return ++_refCount; 61 | } 62 | 63 | ULONG CDisplayAttributeInfoInput::Release(void) 64 | { 65 | LONG cr = --_refCount; 66 | 67 | assert(_refCount >= 0); 68 | 69 | if (_refCount == 0) 70 | { 71 | delete this; 72 | } 73 | 74 | return cr; 75 | } 76 | 77 | STDAPI CDisplayAttributeInfoInput::GetGUID(_Out_ GUID* pguid) 78 | { 79 | if (pguid == nullptr) 80 | return E_INVALIDARG; 81 | 82 | if (_pguid == nullptr) 83 | return E_FAIL; 84 | 85 | *pguid = *_pguid; 86 | 87 | return S_OK; 88 | } 89 | 90 | STDAPI CDisplayAttributeInfoInput::GetDescription(_Out_ BSTR* pbstrDesc) 91 | { 92 | BSTR tempDesc; 93 | 94 | if (pbstrDesc == nullptr) 95 | { 96 | return E_INVALIDARG; 97 | } 98 | 99 | *pbstrDesc = nullptr; 100 | 101 | if ((tempDesc = SysAllocString(_pDescription)) == nullptr) 102 | { 103 | return E_OUTOFMEMORY; 104 | } 105 | 106 | *pbstrDesc = tempDesc; 107 | 108 | return S_OK; 109 | } 110 | 111 | STDAPI CDisplayAttributeInfoInput::GetAttributeInfo(_Out_ TF_DISPLAYATTRIBUTE* ptfDisplayAttr) 112 | { 113 | if (ptfDisplayAttr == nullptr) 114 | { 115 | return E_INVALIDARG; 116 | } 117 | 118 | *ptfDisplayAttr = *_pDisplayAttribute; 119 | 120 | return S_OK; 121 | } 122 | 123 | STDAPI CDisplayAttributeInfoInput::SetAttributeInfo(_In_ const TF_DISPLAYATTRIBUTE* /*ptfDisplayAttr*/) 124 | { 125 | return E_NOTIMPL; 126 | } 127 | 128 | STDAPI CDisplayAttributeInfoInput::Reset() 129 | { 130 | return SetAttributeInfo(_pDisplayAttribute); 131 | } 132 | -------------------------------------------------------------------------------- /.github/workflows/release-ci.yml: -------------------------------------------------------------------------------- 1 | name: Release CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | tags: 8 | - '[0-9]+.*' 9 | workflow_dispatch: 10 | 11 | jobs: 12 | build-and-release: 13 | permissions: 14 | contents: write 15 | runs-on: windows-2022 16 | env: 17 | librime_build: submodule 18 | boost_version: 1.84.0 19 | BOOST_ROOT: ${{ github.workspace }}\deps\boost_1_84_0 20 | steps: 21 | - name: Checkout last commit 22 | uses: actions/checkout@v3 23 | with: 24 | submodules: true 25 | 26 | - name: Configure build environment 27 | run: | 28 | copy env.vs2022.bat env.bat 29 | $git_ref_name = git describe --always 30 | echo "git_ref_name=$git_ref_name" >> $env:GITHUB_ENV 31 | 32 | - name: Cache Boost 33 | id: cache-boost 34 | uses: actions/cache@v3 35 | with: 36 | path: | 37 | ${{ env.BOOST_ROOT }} 38 | key: ${{ runner.os }}-boost-${{ env.boost_version }} 39 | 40 | - name: Install Boost 41 | if: steps.cache-boost.outputs.cache-hit != 'true' 42 | shell: bash 43 | run: | 44 | ./install_boost.bat 45 | ./build.bat boost arm64 46 | 47 | - name: Add msbuild to PATH 48 | uses: microsoft/setup-msbuild@v1.1.3 49 | 50 | - name: Copy Rime files 51 | if: env.librime_build == 'stable' 52 | run: | 53 | .\github.install.bat 54 | 55 | - name: Build librime 56 | if: env.librime_build == 'submodule' 57 | env: 58 | RIME_PLUGINS: hchunhui/librime-lua lotem/librime-octagram rime/librime-predict 59 | shell: bash 60 | run: | 61 | # load plugins 62 | pushd librime 63 | ./action-install-plugins-windows.bat 64 | popd 65 | ./build.bat librime 66 | 67 | - name: Build Weasel 68 | id: build_weasel 69 | shell: bash 70 | run: | 71 | ./build.bat data 72 | ./build.bat hant arm64 73 | ./build.bat installer 74 | 75 | - name: Compress Debug Symbols 76 | shell: pwsh 77 | run: | 78 | Compress-Archive -Path output\*.pdb -CompressionLevel Optimal -DestinationPath .\output\archives\symbols.zip 79 | 80 | - name: Extract changelog 81 | shell: pwsh 82 | run: | 83 | .\extract_changelog.ps1 84 | if: startsWith(github.ref, 'refs/tags/') 85 | 86 | - name: Create Nightly release 87 | if: github.ref == 'refs/heads/master' 88 | uses: 'marvinpinto/action-automatic-releases@latest' 89 | with: 90 | repo_token: ${{ secrets.GITHUB_TOKEN }} 91 | automatic_release_tag: latest 92 | prerelease: true 93 | title: "Nightly Build" 94 | files: | 95 | ./output/archives/weasel*.exe 96 | ./output/archives/symbols.zip 97 | 98 | - name: Release 99 | uses: softprops/action-gh-release@v1 100 | if: startsWith(github.ref, 'refs/tags/') 101 | with: 102 | files: | 103 | ./output/archives/weasel*.exe 104 | ./output/archives/symbols.zip 105 | body_path: ${{ github.workspace }}/RELEASE_CHANGELOG.md 106 | 107 | -------------------------------------------------------------------------------- /WeaselTSF/EnumDisplayAttributeInfo.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "EnumDisplayAttributeInfo.h" 4 | #include "Globals.h" 5 | #include "DisplayAttributeInfo.h" 6 | 7 | CEnumDisplayAttributeInfo::CEnumDisplayAttributeInfo() 8 | { 9 | DllAddRef(); 10 | 11 | _index = 0; 12 | _refCount = 1; 13 | } 14 | 15 | CEnumDisplayAttributeInfo::~CEnumDisplayAttributeInfo() 16 | { 17 | DllRelease(); 18 | } 19 | 20 | STDAPI CEnumDisplayAttributeInfo::QueryInterface(REFIID riid, _Outptr_ void** ppvObj) 21 | { 22 | if (ppvObj == nullptr) 23 | return E_INVALIDARG; 24 | 25 | *ppvObj = nullptr; 26 | 27 | if (IsEqualIID(riid, IID_IUnknown) || 28 | IsEqualIID(riid, IID_IEnumTfDisplayAttributeInfo)) 29 | { 30 | *ppvObj = (IEnumTfDisplayAttributeInfo*)this; 31 | } 32 | 33 | if (*ppvObj) 34 | { 35 | AddRef(); 36 | return S_OK; 37 | } 38 | 39 | return E_NOINTERFACE; 40 | } 41 | 42 | STDAPI_(ULONG) CEnumDisplayAttributeInfo::AddRef() 43 | { 44 | return ++_refCount; 45 | } 46 | 47 | STDAPI_(ULONG) CEnumDisplayAttributeInfo::Release() 48 | { 49 | LONG cr = --_refCount; 50 | 51 | assert(_refCount >= 0); 52 | 53 | if (_refCount == 0) 54 | { 55 | delete this; 56 | } 57 | 58 | return cr; 59 | } 60 | 61 | STDAPI CEnumDisplayAttributeInfo::Clone(_Out_ IEnumTfDisplayAttributeInfo** ppEnum) 62 | { 63 | CEnumDisplayAttributeInfo* pClone = nullptr; 64 | 65 | if (ppEnum == nullptr) 66 | { 67 | return E_INVALIDARG; 68 | } 69 | 70 | *ppEnum = nullptr; 71 | 72 | pClone = new (std::nothrow) CEnumDisplayAttributeInfo(); 73 | if ((pClone) == nullptr) 74 | { 75 | return E_OUTOFMEMORY; 76 | } 77 | 78 | // the clone should match this object's state 79 | pClone->_index = _index; 80 | 81 | *ppEnum = pClone; 82 | 83 | return S_OK; 84 | } 85 | 86 | STDAPI CEnumDisplayAttributeInfo::Next(ULONG ulCount, __RPC__out_ecount_part(ulCount, *pcFetched) ITfDisplayAttributeInfo** rgInfo, __RPC__out ULONG* pcFetched) 87 | { 88 | ULONG fetched; 89 | 90 | fetched = 0; 91 | 92 | if (ulCount == 0) 93 | { 94 | return S_OK; 95 | } 96 | if (rgInfo == nullptr) 97 | { 98 | return E_INVALIDARG; 99 | } 100 | *rgInfo = nullptr; 101 | 102 | while (fetched < ulCount) 103 | { 104 | ITfDisplayAttributeInfo* pDisplayAttributeInfo = nullptr; 105 | 106 | if (_index == 0) 107 | { 108 | pDisplayAttributeInfo = new (std::nothrow) CDisplayAttributeInfoInput(); 109 | if ((pDisplayAttributeInfo) == nullptr) 110 | { 111 | return E_OUTOFMEMORY; 112 | } 113 | } 114 | else 115 | { 116 | break; 117 | } 118 | 119 | *rgInfo = pDisplayAttributeInfo; 120 | rgInfo++; 121 | fetched++; 122 | _index++; 123 | } 124 | 125 | if (pcFetched != nullptr) 126 | { 127 | *pcFetched = fetched; 128 | } 129 | 130 | return (fetched == ulCount) ? S_OK : S_FALSE; 131 | } 132 | 133 | STDAPI CEnumDisplayAttributeInfo::Reset() 134 | { 135 | _index = 0; 136 | return S_OK; 137 | } 138 | 139 | STDAPI CEnumDisplayAttributeInfo::Skip(ULONG ulCount) 140 | { 141 | if ((ulCount + _index) > 1 || (ulCount + _index) < ulCount) 142 | { 143 | _index = 1; 144 | return S_FALSE; 145 | } 146 | _index += ulCount; 147 | return S_OK; 148 | } 149 | -------------------------------------------------------------------------------- /WeaselTSF/TextEditSink.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "WeaselTSF.h" 3 | 4 | static BOOL IsRangeCovered(TfEditCookie ec, ITfRange *pRangeTest, ITfRange *pRangeCover) 5 | { 6 | LONG lResult; 7 | 8 | if (pRangeCover->CompareStart(ec, pRangeTest, TF_ANCHOR_START, &lResult) != S_OK || lResult > 0) 9 | return FALSE; 10 | if (pRangeCover->CompareEnd(ec, pRangeTest, TF_ANCHOR_END, &lResult) != S_OK || lResult < 0) 11 | return FALSE; 12 | return TRUE; 13 | } 14 | 15 | STDAPI WeaselTSF::OnEndEdit(ITfContext *pContext, TfEditCookie ecReadOnly, ITfEditRecord *pEditRecord) 16 | { 17 | BOOL fSelectionChanged; 18 | IEnumTfRanges *pEnumTextChanges; 19 | ITfRange *pRange; 20 | 21 | /* did the selection change? */ 22 | if (pEditRecord->GetSelectionStatus(&fSelectionChanged) == S_OK && fSelectionChanged) 23 | { 24 | if (_IsComposing()) 25 | { 26 | /* if the caret moves out of composition range, stop the composition */ 27 | TF_SELECTION tfSelection; 28 | ULONG cFetched; 29 | 30 | if (pContext->GetSelection(ecReadOnly, TF_DEFAULT_SELECTION, 1, &tfSelection, &cFetched) == S_OK && cFetched == 1) 31 | { 32 | ITfRange *pRangeComposition; 33 | if (_pComposition->GetRange(&pRangeComposition) == S_OK) 34 | { 35 | if (!IsRangeCovered(ecReadOnly, tfSelection.range, pRangeComposition)) 36 | _EndComposition(pContext, true); 37 | pRangeComposition->Release(); 38 | } 39 | } 40 | } 41 | } 42 | 43 | /* text modification? */ 44 | if (pEditRecord->GetTextAndPropertyUpdates(TF_GTP_INCL_TEXT, NULL, 0, &pEnumTextChanges) == S_OK) 45 | { 46 | if (pEnumTextChanges->Next(1, &pRange, NULL) == S_OK) 47 | { 48 | pRange->Release(); 49 | } 50 | pEnumTextChanges->Release(); 51 | } 52 | return S_OK; 53 | } 54 | 55 | STDAPI WeaselTSF::OnLayoutChange(ITfContext *pContext, TfLayoutCode lcode, ITfContextView *pContextView) 56 | { 57 | if (!_IsComposing()) 58 | return S_OK; 59 | 60 | if (pContext != _pTextEditSinkContext) 61 | return S_OK; 62 | 63 | if (lcode == TF_LC_CHANGE) 64 | _UpdateCompositionWindow(pContext); 65 | return S_OK; 66 | } 67 | 68 | BOOL WeaselTSF::_InitTextEditSink(com_ptr pDocMgr) 69 | { 70 | com_ptr pSource; 71 | BOOL fRet; 72 | 73 | /* clear out any previous sink first */ 74 | if (_dwTextEditSinkCookie != TF_INVALID_COOKIE) 75 | { 76 | _pTextEditSinkContext->QueryInterface(&pSource); 77 | if (pSource != nullptr) 78 | { 79 | pSource->UnadviseSink(_dwTextEditSinkCookie); 80 | pSource->UnadviseSink(_dwTextLayoutSinkCookie); 81 | } 82 | _pTextEditSinkContext = nullptr; 83 | _dwTextEditSinkCookie = TF_INVALID_COOKIE; 84 | } 85 | if (pDocMgr == NULL) 86 | return TRUE; 87 | 88 | if (pDocMgr->GetTop(&_pTextEditSinkContext) != S_OK) 89 | return FALSE; 90 | 91 | if (_pTextEditSinkContext == NULL) 92 | return TRUE; 93 | 94 | fRet = FALSE; 95 | 96 | pSource.Release(); 97 | 98 | if (_pTextEditSinkContext->QueryInterface(IID_ITfSource, (void **) &pSource) == S_OK) 99 | { 100 | if (pSource->AdviseSink(IID_ITfTextEditSink, (ITfTextEditSink *) this, &_dwTextEditSinkCookie) == S_OK) 101 | fRet = TRUE; 102 | else 103 | _dwTextEditSinkCookie = TF_INVALID_COOKIE; 104 | if (pSource->AdviseSink(IID_ITfTextLayoutSink, (ITfTextLayoutSink *) this, &_dwTextLayoutSinkCookie) == S_OK) 105 | { 106 | fRet = TRUE; 107 | } 108 | else 109 | _dwTextLayoutSinkCookie = TF_INVALID_COOKIE; 110 | } 111 | if (fRet == FALSE) 112 | { 113 | _pTextEditSinkContext = nullptr; 114 | } 115 | 116 | return fRet; 117 | } 118 | -------------------------------------------------------------------------------- /WeaselIPC/PipeChannel.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include 4 | 5 | using namespace weasel; 6 | using namespace std; 7 | using namespace boost; 8 | 9 | #define _ThrowLastError throw ::GetLastError() 10 | #define _ThrowCode(__c) throw __c 11 | #define _ThrowIfNot(__c) { DWORD err; if ((err = ::GetLastError()) != __c) throw err; } 12 | 13 | PipeChannelBase::PipeChannelBase(std::wstring &&pn_cmd, size_t bs = 4 * 1024, SECURITY_ATTRIBUTES *s = NULL) 14 | : pname(pn_cmd), 15 | write_stream(nullptr), 16 | buff_size(bs), 17 | buffer(std::make_unique(bs)), 18 | hpipe(INVALID_HANDLE_VALUE), 19 | has_body(false), 20 | sa(s) {}; 21 | 22 | PipeChannelBase::PipeChannelBase(PipeChannelBase &&r) 23 | : write_stream(std::move(r.write_stream)), 24 | pname(std::move(r.pname)), 25 | buff_size(r.buff_size), 26 | buffer(std::move(r.buffer)), 27 | hpipe(r.hpipe), 28 | has_body(r.has_body), 29 | sa(r.sa) {}; 30 | 31 | 32 | PipeChannelBase::~PipeChannelBase() 33 | { 34 | _FinalizePipe(hpipe); 35 | } 36 | 37 | bool PipeChannelBase::_Ensure() 38 | { 39 | try { 40 | if (_Invalid(hpipe)) { 41 | hpipe = _Connect(pname.c_str()); 42 | return !_Invalid(hpipe); 43 | } 44 | } 45 | catch (...) { 46 | return false; 47 | } 48 | 49 | return true; 50 | } 51 | 52 | HANDLE PipeChannelBase::_Connect(const wchar_t *name) 53 | { 54 | HANDLE pipe = INVALID_HANDLE_VALUE; 55 | while (_Invalid(pipe = _TryConnect())) 56 | ::WaitNamedPipe(name, 500); 57 | DWORD mode = PIPE_READMODE_MESSAGE; 58 | if (!SetNamedPipeHandleState(pipe, &mode, NULL, NULL)) { 59 | _ThrowLastError; 60 | } 61 | return pipe; 62 | } 63 | 64 | void PipeChannelBase::_Reconnect() 65 | { 66 | _FinalizePipe(hpipe); 67 | _Ensure(); 68 | } 69 | 70 | HANDLE PipeChannelBase::_TryConnect() 71 | { 72 | auto pipe = ::CreateFile(pname.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 73 | if (!_Invalid(pipe)) { 74 | // connected to the pipe 75 | return pipe; 76 | } 77 | // being busy is not really an error since we just need to wait. 78 | _ThrowIfNot(ERROR_PIPE_BUSY); 79 | // All pipe instances are busy 80 | return INVALID_HANDLE_VALUE; 81 | } 82 | 83 | size_t PipeChannelBase::_WritePipe(HANDLE pipe, size_t s, char *b) 84 | { 85 | DWORD lwritten; 86 | if (!::WriteFile(pipe, b, s, &lwritten, NULL) || lwritten <= 0) { 87 | _ThrowLastError; 88 | } 89 | ::FlushFileBuffers(pipe); 90 | return lwritten; 91 | } 92 | 93 | void PipeChannelBase::_FinalizePipe(HANDLE &p) 94 | { 95 | if (!_Invalid(p)) { 96 | DisconnectNamedPipe(p); 97 | CloseHandle(p); 98 | } 99 | p = INVALID_HANDLE_VALUE; 100 | } 101 | 102 | void PipeChannelBase::_Receive(HANDLE pipe, LPVOID msg, size_t rec_len) 103 | { 104 | DWORD lread; 105 | BOOL success = ::ReadFile(pipe, msg, rec_len, &lread, NULL); 106 | if (!success) { 107 | _ThrowIfNot(ERROR_MORE_DATA); 108 | 109 | memset(buffer.get(), 0, buff_size); 110 | success = ::ReadFile(pipe, buffer.get(), buff_size, &lread, NULL); 111 | if (!success) { 112 | _ThrowLastError; 113 | } 114 | } 115 | has_body = false; 116 | } 117 | 118 | HANDLE PipeChannelBase::_ConnectServerPipe(std::wstring &pn) 119 | { 120 | HANDLE pipe = CreateNamedPipe( 121 | pn.c_str(), 122 | PIPE_ACCESS_DUPLEX, 123 | PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 124 | PIPE_UNLIMITED_INSTANCES, 125 | buff_size, 126 | buff_size, 127 | 0, 128 | sa); 129 | if (pipe == INVALID_HANDLE_VALUE || !::ConnectNamedPipe(pipe, NULL)) { 130 | _ThrowLastError; 131 | } 132 | return pipe; 133 | } 134 | 135 | -------------------------------------------------------------------------------- /WeaselIPC/ContextUpdater.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include 3 | #include 4 | 5 | #include "Deserializer.h" 6 | #include "ContextUpdater.h" 7 | 8 | using namespace weasel; 9 | 10 | // ContextUpdater 11 | 12 | Deserializer::Ptr ContextUpdater::Create(ResponseParser* pTarget) 13 | { 14 | return Deserializer::Ptr(new ContextUpdater(pTarget)); 15 | } 16 | 17 | ContextUpdater::ContextUpdater(ResponseParser* pTarget) 18 | : Deserializer(pTarget) 19 | { 20 | } 21 | 22 | ContextUpdater::~ContextUpdater() 23 | { 24 | } 25 | 26 | void ContextUpdater::Store(Deserializer::KeyType const& k, std::wstring const& value) 27 | { 28 | if(!m_pTarget->p_context || k.size() < 2) 29 | return; 30 | 31 | if (k[1] == L"preedit") 32 | { 33 | _StoreText(m_pTarget->p_context->preedit, k, value); 34 | return; 35 | } 36 | 37 | if (k[1] == L"aux") 38 | { 39 | _StoreText(m_pTarget->p_context->aux, k, value); 40 | return; 41 | } 42 | 43 | if (k[1] == L"cand") 44 | { 45 | _StoreCand(k, value); 46 | return; 47 | } 48 | } 49 | 50 | void ContextUpdater::_StoreText(Text& target, Deserializer::KeyType k, std::wstring const& value) 51 | { 52 | if(k.size() == 2) 53 | { 54 | target.clear(); 55 | target.str = value; 56 | return; 57 | } 58 | if(k.size() == 3) 59 | { 60 | // ctx.preedit.cursor 61 | if (k[2] == L"cursor") 62 | { 63 | std::vector vec; 64 | split(vec, value, L","); 65 | if (vec.size() < 2) 66 | return; 67 | 68 | weasel::TextAttribute attr; 69 | attr.type = HIGHLIGHTED; 70 | attr.range.start = _wtoi(vec[0].c_str()); 71 | attr.range.end = _wtoi(vec[1].c_str()); 72 | attr.range.cursor = _wtoi(vec[2].c_str()); 73 | if (attr.range.cursor < attr.range.start || attr.range.cursor > attr.range.end) 74 | { 75 | attr.range.cursor = attr.range.end; 76 | } 77 | 78 | target.attributes.push_back(attr); 79 | return; 80 | } 81 | } 82 | } 83 | 84 | void ContextUpdater::_StoreCand(Deserializer::KeyType k, std::wstring const& value) 85 | { 86 | CandidateInfo& cinfo = m_pTarget->p_context->cinfo; 87 | std::wstringstream ss(value); 88 | boost::archive::text_wiarchive ia(ss); 89 | 90 | ia >> cinfo; 91 | } 92 | 93 | // StatusUpdater 94 | 95 | Deserializer::Ptr StatusUpdater::Create(ResponseParser* pTarget) 96 | { 97 | return Deserializer::Ptr(new StatusUpdater(pTarget)); 98 | } 99 | 100 | StatusUpdater::StatusUpdater(ResponseParser* pTarget) 101 | : Deserializer(pTarget) 102 | { 103 | } 104 | 105 | StatusUpdater::~StatusUpdater() 106 | { 107 | } 108 | 109 | void StatusUpdater::Store(Deserializer::KeyType const& k, std::wstring const& value) 110 | { 111 | if(!m_pTarget->p_status || k.size() < 2) 112 | return; 113 | 114 | bool bool_value = (!value.empty() && value != L"0"); 115 | 116 | if (k[1] == L"schema_id") 117 | { 118 | m_pTarget->p_status->schema_id = value; 119 | return; 120 | } 121 | 122 | if (k[1] == L"ascii_mode") 123 | { 124 | m_pTarget->p_status->ascii_mode = bool_value; 125 | return; 126 | } 127 | 128 | if (k[1] == L"composing") 129 | { 130 | m_pTarget->p_status->composing = bool_value; 131 | return; 132 | } 133 | 134 | if (k[1] == L"disabled") 135 | { 136 | m_pTarget->p_status->disabled = bool_value; 137 | return; 138 | } 139 | 140 | if (k[1] == L"full_shape") 141 | { 142 | m_pTarget->p_status->full_shape = bool_value; 143 | return; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /WeaselIPCServer/SecurityAttribute.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "SecurityAttribute.h" 3 | #include 4 | 5 | #ifndef SDDL_ALL_APP_PACKAGES 6 | #define SDDL_ALL_APP_PACKAGES TEXT("AC") 7 | #endif 8 | 9 | #define LOW_INTEGRITY_SDDL_SACL SDDL_SACL \ 10 | SDDL_DELIMINATOR \ 11 | SDDL_ACE_BEGIN \ 12 | SDDL_MANDATORY_LABEL \ 13 | SDDL_SEPERATOR \ 14 | SDDL_SEPERATOR \ 15 | SDDL_NO_WRITE_UP \ 16 | SDDL_SEPERATOR \ 17 | SDDL_SEPERATOR \ 18 | SDDL_SEPERATOR \ 19 | SDDL_ML_LOW \ 20 | SDDL_ACE_END 21 | 22 | #define LOCAL_SYSTEM_FILE_ACCESS SDDL_ACE_BEGIN \ 23 | SDDL_ACCESS_ALLOWED \ 24 | SDDL_SEPERATOR \ 25 | SDDL_SEPERATOR \ 26 | SDDL_FILE_ALL \ 27 | SDDL_SEPERATOR \ 28 | SDDL_SEPERATOR \ 29 | SDDL_SEPERATOR \ 30 | SDDL_LOCAL_SYSTEM \ 31 | SDDL_ACE_END 32 | 33 | #define EVERYONE_FILE_ACCESS SDDL_ACE_BEGIN \ 34 | SDDL_ACCESS_ALLOWED \ 35 | SDDL_SEPERATOR \ 36 | SDDL_SEPERATOR \ 37 | SDDL_FILE_ALL \ 38 | SDDL_SEPERATOR \ 39 | SDDL_SEPERATOR \ 40 | SDDL_SEPERATOR \ 41 | SDDL_EVERYONE \ 42 | SDDL_ACE_END 43 | 44 | #define ALL_APP_PACKAGES_FILE_ACCESS SDDL_ACE_BEGIN \ 45 | SDDL_ACCESS_ALLOWED \ 46 | SDDL_SEPERATOR \ 47 | SDDL_SEPERATOR \ 48 | SDDL_FILE_ALL \ 49 | SDDL_SEPERATOR \ 50 | SDDL_SEPERATOR \ 51 | SDDL_SEPERATOR \ 52 | SDDL_ALL_APP_PACKAGES \ 53 | SDDL_ACE_END 54 | 55 | namespace weasel { 56 | 57 | void SecurityAttribute::_Init() 58 | { 59 | // Privileges for UWP and IE protected mode 60 | // https://stackoverflow.com/questions/39138674/accessing-named-pipe-servers-from-within-ie-epm-bho 61 | 62 | ConvertStringSecurityDescriptorToSecurityDescriptor( 63 | LOW_INTEGRITY_SDDL_SACL 64 | SDDL_DACL 65 | SDDL_DELIMINATOR 66 | LOCAL_SYSTEM_FILE_ACCESS 67 | EVERYONE_FILE_ACCESS 68 | ALL_APP_PACKAGES_FILE_ACCESS 69 | , 70 | SDDL_REVISION_1, 71 | &pd, 72 | NULL); 73 | sa.nLength = sizeof(SECURITY_ATTRIBUTES); 74 | sa.lpSecurityDescriptor = pd; 75 | sa.bInheritHandle = TRUE; 76 | } 77 | 78 | SECURITY_ATTRIBUTES *SecurityAttribute::get_attr() 79 | { 80 | return &sa; 81 | } 82 | }; 83 | -------------------------------------------------------------------------------- /WeaselIPCServer/WeaselServerImpl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include // for security attributes constants 5 | #include // for ACL 6 | #include 7 | #include 8 | 9 | #include "SecurityAttribute.h" 10 | 11 | namespace weasel 12 | { 13 | class PipeServer; 14 | 15 | typedef CWinTraits ServerWinTraits; 16 | 17 | class ServerImpl : 18 | public CWindowImpl 19 | //class ServerImpl 20 | { 21 | public: 22 | DECLARE_WND_CLASS (WEASEL_IPC_WINDOW) 23 | 24 | BEGIN_MSG_MAP(WEASEL_IPC_WINDOW) 25 | MESSAGE_HANDLER(WM_CREATE, OnCreate) 26 | MESSAGE_HANDLER(WM_DESTROY, OnDestroy) 27 | MESSAGE_HANDLER(WM_CLOSE, OnClose) 28 | MESSAGE_HANDLER(WM_QUERYENDSESSION, OnQueryEndSystemSession) 29 | MESSAGE_HANDLER(WM_ENDSESSION, OnEndSystemSession) 30 | MESSAGE_HANDLER(WM_DWMCOLORIZATIONCOLORCHANGED, OnColorChange) 31 | MESSAGE_HANDLER(WM_SETTINGCHANGE, OnColorChange) 32 | MESSAGE_HANDLER(WM_COMMAND, OnCommand) 33 | END_MSG_MAP() 34 | 35 | LRESULT OnColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); 36 | LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); 37 | LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); 38 | LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); 39 | LRESULT OnQueryEndSystemSession(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); 40 | LRESULT OnEndSystemSession(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); 41 | LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); 42 | DWORD OnCommand(WEASEL_IPC_COMMAND uMsg, DWORD wParam, DWORD lParam); 43 | DWORD OnEcho(WEASEL_IPC_COMMAND uMsg, DWORD wParam, DWORD lParam); 44 | DWORD OnStartSession(WEASEL_IPC_COMMAND uMsg, DWORD wParam, DWORD lParam); 45 | DWORD OnEndSession(WEASEL_IPC_COMMAND uMsg, DWORD wParam, DWORD lParam); 46 | DWORD OnKeyEvent(WEASEL_IPC_COMMAND uMsg, DWORD wParam, DWORD lParam); 47 | DWORD OnShutdownServer(WEASEL_IPC_COMMAND uMsg, DWORD wParam, DWORD lParam); 48 | DWORD OnFocusIn(WEASEL_IPC_COMMAND uMsg, DWORD wParam, DWORD lParam); 49 | DWORD OnFocusOut(WEASEL_IPC_COMMAND uMsg, DWORD wParam, DWORD lParam); 50 | DWORD OnUpdateInputPosition(WEASEL_IPC_COMMAND uMsg, DWORD wParam, DWORD lParam); 51 | DWORD OnStartMaintenance(WEASEL_IPC_COMMAND uMsg, DWORD wParam, DWORD lParam); 52 | DWORD OnEndMaintenance(WEASEL_IPC_COMMAND uMsg, DWORD wParam, DWORD lParam); 53 | DWORD OnCommitComposition(WEASEL_IPC_COMMAND uMsg, DWORD wParam, DWORD lParam); 54 | DWORD OnClearComposition(WEASEL_IPC_COMMAND uMsg, DWORD wParam, DWORD lParam); 55 | DWORD OnSelectCandidateOnCurrentPage(WEASEL_IPC_COMMAND uMsg, DWORD wParam, DWORD lParam); 56 | 57 | public: 58 | ServerImpl(); 59 | ~ServerImpl(); 60 | 61 | int Start(); 62 | int Stop(); 63 | int Run(); 64 | 65 | void SetRequestHandler(RequestHandler* pHandler) 66 | { 67 | m_pRequestHandler = pHandler; 68 | } 69 | void AddMenuHandler(UINT uID, CommandHandler &handler) 70 | { 71 | m_MenuHandlers[uID] = handler; 72 | } 73 | 74 | private: 75 | void _Finailize(); 76 | template 77 | void HandlePipeMessage(PipeMessage pipe_msg, _Resp resp); 78 | 79 | std::unique_ptr channel; 80 | std::unique_ptr pipeThread; 81 | RequestHandler *m_pRequestHandler; // reference 82 | std::map m_MenuHandlers; 83 | HMODULE m_hUser32Module; 84 | SecurityAttribute sa; 85 | BOOL m_darkMode; 86 | }; 87 | 88 | 89 | } 90 | -------------------------------------------------------------------------------- /WeaselServer/WeaselServer.cpp: -------------------------------------------------------------------------------- 1 | // WeaselServer.cpp : main source file for WeaselServer.exe 2 | // 3 | // WTL MessageLoop 封装了消息循环. 实现了 getmessage/dispatchmessage.... 4 | 5 | #include "stdafx.h" 6 | #include "resource.h" 7 | #include "WeaselService.h" 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #pragma comment(lib, "Shcore.lib") 18 | CAppModule _Module; 19 | 20 | int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow) 21 | { 22 | LCID lcid = GetUserDefaultLCID(); 23 | if (lcid == 2052 || lcid == 3072 || lcid == 4100) { 24 | LANGID langId = SetThreadUILanguage(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)); 25 | SetThreadLocale(langId); 26 | } 27 | else { 28 | LANGID langId = SetThreadUILanguage(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)); 29 | SetThreadLocale(langId); 30 | } 31 | 32 | if( !IsWindowsBlueOrLaterEx() ) 33 | { 34 | if(GetThreadUILanguage() == MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)) 35 | ::MessageBox(NULL, L"僅支持Windows 8.1或更高版本系統", L"系統版本過低", MB_ICONERROR); 36 | else 37 | ::MessageBox(NULL, L"仅支持Windows 8.1或更高版本系统", L"系统版本过低", MB_ICONERROR); 38 | return 0; 39 | } 40 | SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); 41 | 42 | // 防止服务进程开启输入法 43 | ImmDisableIME(-1); 44 | 45 | WCHAR user_name[20] = {0}; 46 | DWORD size = _countof(user_name); 47 | GetUserName(user_name, &size); 48 | if (!_wcsicmp(user_name, L"SYSTEM")) 49 | { 50 | return 1; 51 | } 52 | 53 | HRESULT hRes = ::CoInitialize(NULL); 54 | // If you are running on NT 4.0 or higher you can use the following call instead to 55 | // make the EXE free threaded. This means that calls come in on a random RPC thread. 56 | //HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); 57 | ATLASSERT(SUCCEEDED(hRes)); 58 | 59 | // this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used 60 | ::DefWindowProc(NULL, 0, 0, 0L); 61 | 62 | AtlInitCommonControls(ICC_BAR_CLASSES); // add flags to support other controls 63 | 64 | hRes = _Module.Init(NULL, hInstance); 65 | ATLASSERT(SUCCEEDED(hRes)); 66 | 67 | if (!wcscmp(L"/userdir", lpstrCmdLine)) 68 | { 69 | CreateDirectory(WeaselUserDataPath().c_str(), NULL); 70 | WeaselServerApp::explore(WeaselUserDataPath()); 71 | return 0; 72 | } 73 | if (!wcscmp(L"/weaseldir", lpstrCmdLine)) 74 | { 75 | WeaselServerApp::explore(WeaselServerApp::install_dir()); 76 | return 0; 77 | } 78 | 79 | // command line option /q stops the running server 80 | bool quit = !wcscmp(L"/q", lpstrCmdLine) || !wcscmp(L"/quit", lpstrCmdLine); 81 | // restart if already running 82 | if(quit) 83 | { 84 | weasel::Client client; 85 | if (client.Connect()) // try to connect to running server 86 | { 87 | client.ShutdownServer(); 88 | } 89 | return 0; 90 | } 91 | 92 | bool check_updates = !wcscmp(L"/update", lpstrCmdLine); 93 | if (check_updates) 94 | { 95 | WeaselServerApp::check_update(); 96 | } 97 | 98 | CreateDirectory(WeaselUserDataPath().c_str(), NULL); 99 | 100 | int nRet = 0; 101 | try 102 | { 103 | WeaselServerApp app; 104 | RegisterApplicationRestart(NULL, 0); 105 | nRet = app.Run(); 106 | } 107 | catch (...) 108 | { 109 | // bad luck... 110 | nRet = -1; 111 | } 112 | 113 | _Module.Term(); 114 | ::CoUninitialize(); 115 | 116 | return nRet; 117 | } 118 | --------------------------------------------------------------------------------