├── .clang-format ├── .exclude_pattern.txt ├── .git-blame-ignore-revs ├── .github ├── ISSUE_TEMPLATE │ └── bug-上报.md └── workflows │ ├── commit-ci.yml │ ├── release-ci.yml │ └── update-appcast.yml ├── .gitignore ├── .gitmodules ├── CHANGELOG.md ├── INSTALL.md ├── LICENSE.txt ├── README.md ├── RimeWithWeasel ├── ReadMe.txt ├── RimeWithWeasel.cpp ├── RimeWithWeasel.vcxproj ├── RimeWithWeasel.vcxproj.filters ├── WeaselUtility.cpp ├── stdafx.cpp ├── stdafx.h ├── targetver.h └── xmake.lua ├── WeaselDeployer ├── Configurator.cpp ├── Configurator.h ├── DictManagementDialog.cpp ├── DictManagementDialog.h ├── FontSettingDialog.cpp ├── FontSettingDialog.h ├── SwitcherSettingsDialog.cpp ├── SwitcherSettingsDialog.h ├── UIStyleSettings.cpp ├── UIStyleSettings.h ├── UIStyleSettingsDialog.cpp ├── UIStyleSettingsDialog.h ├── WeaselDeployer.cpp ├── WeaselDeployer.h ├── WeaselDeployer.rc ├── WeaselDeployer.vcxproj ├── WeaselDeployer.vcxproj.filters ├── resource.h ├── stdafx.cpp ├── stdafx.h ├── targetver.h └── xmake.lua ├── WeaselIME ├── KeyEvent.cpp ├── ReadMe.txt ├── WeaselIME.cpp ├── WeaselIME.h ├── WeaselIME.rc ├── WeaselIME.vcxproj ├── WeaselIME.vcxproj.filters ├── dllmain.cpp ├── ime.cpp ├── immdev.h ├── resource.h ├── stdafx.cpp ├── stdafx.h ├── targetver.h ├── weasel.def └── xmake.lua ├── WeaselIPC ├── ActionLoader.cpp ├── ActionLoader.h ├── Committer.cpp ├── Committer.h ├── Configurator.cpp ├── Configurator.h ├── ContextUpdater.cpp ├── ContextUpdater.h ├── Deserializer.cpp ├── Deserializer.h ├── PipeChannel.cpp ├── ReadMe.txt ├── ResponseParser.cpp ├── Styler.cpp ├── Styler.h ├── WeaselClientImpl.cpp ├── WeaselClientImpl.h ├── WeaselIPC.vcxproj ├── WeaselIPC.vcxproj.filters ├── stdafx.cpp ├── stdafx.h ├── targetver.h └── xmake.lua ├── WeaselIPCServer ├── ReadMe.txt ├── SecurityAttribute.cpp ├── SecurityAttribute.h ├── WeaselIPCServer.vcxproj ├── WeaselIPCServer.vcxproj.filters ├── WeaselServerImpl.cpp ├── WeaselServerImpl.h ├── stdafx.cpp ├── stdafx.h ├── targetver.h └── xmake.lua ├── WeaselServer ├── SystemTraySDK.cpp ├── SystemTraySDK.h ├── WeaselServer.cpp ├── WeaselServer.h ├── WeaselServer.rc ├── WeaselServer.vcxproj ├── WeaselServer.vcxproj.filters ├── WeaselServerApp.cpp ├── WeaselServerApp.h ├── WeaselService.cpp ├── WeaselService.h ├── WeaselTrayIcon.cpp ├── WeaselTrayIcon.h ├── resource.h ├── stdafx.cpp ├── stdafx.h └── xmake.lua ├── WeaselSetup ├── InstallOptionsDlg.cpp ├── InstallOptionsDlg.h ├── WeaselSetup.cpp ├── WeaselSetup.h ├── WeaselSetup.ico ├── WeaselSetup.rc ├── WeaselSetup.vcxproj ├── WeaselSetup.vcxproj.filters ├── imesetup.cpp ├── resource.h ├── stdafx.cpp ├── stdafx.h └── xmake.lua ├── WeaselTSF ├── CandidateList.cpp ├── CandidateList.h ├── Compartment.cpp ├── Compartment.h ├── Composition.cpp ├── DisplayAttribute.cpp ├── DisplayAttributeInfo.cpp ├── DisplayAttributeInfo.h ├── DisplayAttributeProvider.cpp ├── EditSession.cpp ├── EditSession.h ├── EnumDisplayAttributeInfo.cpp ├── EnumDisplayAttributeInfo.h ├── Globals.cpp ├── Globals.h ├── KeyEvent.cpp ├── KeyEventSink.cpp ├── LanguageBar.cpp ├── LanguageBar.h ├── ReadMe.txt ├── Register.cpp ├── Register.h ├── Server.cpp ├── TextEditSink.cpp ├── ThreadMgrEventSink.cpp ├── WeaselTSF.cpp ├── WeaselTSF.def ├── WeaselTSF.h ├── WeaselTSF.rc ├── WeaselTSF.vcxproj ├── WeaselTSF.vcxproj.filters ├── ctffunc.h ├── dllmain.cpp ├── stdafx.cpp ├── stdafx.h ├── targetver.h └── xmake.lua ├── WeaselUI ├── DirectWriteResources.cpp ├── FullScreenLayout.cpp ├── FullScreenLayout.h ├── GdiplusBlur.cpp ├── GdiplusBlur.h ├── HorizontalLayout.cpp ├── HorizontalLayout.h ├── Layout.cpp ├── Layout.h ├── ReadMe.txt ├── StandardLayout.cpp ├── StandardLayout.h ├── VHorizontalLayout.cpp ├── VHorizontalLayout.h ├── VerticalLayout.cpp ├── VerticalLayout.h ├── WeaselPanel.cpp ├── WeaselPanel.h ├── WeaselUI.cpp ├── WeaselUI.vcxproj ├── WeaselUI.vcxproj.filters ├── stdafx.cpp ├── stdafx.h ├── targetver.h └── xmake.lua ├── arm64x_wrapper ├── WeaselIME_arm64.def ├── WeaselIME_x64.def ├── WeaselTSF_arm64.def ├── WeaselTSF_x64.def ├── build.bat └── dummy.c ├── build.bat ├── clang-format.ps1 ├── clang-format.sh ├── env.bat.template ├── env.vs2019.bat ├── env.vs2022.bat ├── extract_changelog.ps1 ├── get-rime.ps1 ├── include ├── CDialogDpiAware.h ├── KeyEvent.h ├── PipeChannel.h ├── ResponseParser.h ├── RimeWithWeasel.h ├── StringAlgorithm.hpp ├── VersionHelpers.hpp ├── WeaselConstants.h ├── WeaselIPC.h ├── WeaselIPCData.h ├── WeaselUI.h ├── WeaselUtility.h ├── logging.h ├── no_logging.h ├── resource.h ├── winapifamily.h ├── winpackagefamily.h ├── winsparkle-version.h ├── winsparkle.h └── wtl │ ├── atlapp.h │ ├── atlcrack.h │ ├── atlctrls.h │ ├── atlctrlw.h │ ├── atlctrlx.h │ ├── atlddx.h │ ├── atldlgs.h │ ├── atldwm.h │ ├── atlfind.h │ ├── atlframe.h │ ├── atlgdi.h │ ├── atlmisc.h │ ├── atlprint.h │ ├── atlres.h │ ├── atlribbon.h │ ├── atlscrl.h │ ├── atlsplit.h │ ├── atltheme.h │ ├── atluser.h │ └── atlwinx.h ├── install-clang-format.bat ├── install_boost.bat ├── install_nsis.bat ├── lib └── WinSparkle.lib ├── lib64 └── WinSparkle.lib ├── msvc-latest.bat ├── output ├── 7-zip-license.txt ├── 7z.dll ├── 7z.exe ├── COPYING-curl.txt ├── Win32 │ └── WinSparkle.dll ├── WinSparkle.dll ├── archives │ └── .placeholder ├── check_windows_version.js ├── curl-ca-bundle.crt ├── curl.exe ├── data │ ├── preview │ │ ├── color_scheme_android.png │ │ ├── color_scheme_aqua.png │ │ ├── color_scheme_azure.png │ │ ├── color_scheme_brasil.png │ │ ├── color_scheme_brisk.png │ │ ├── color_scheme_cool_breeze.png │ │ ├── color_scheme_dark_temple.png │ │ ├── color_scheme_doraemon.png │ │ ├── color_scheme_dota_2.png │ │ ├── color_scheme_espagna.png │ │ ├── color_scheme_flypy.png │ │ ├── color_scheme_gholabok.png │ │ ├── color_scheme_google.png │ │ ├── color_scheme_google_plus.png │ │ ├── color_scheme_ink.png │ │ ├── color_scheme_kuma_shuzboz.png │ │ ├── color_scheme_kuon.png │ │ ├── color_scheme_lost_temple.png │ │ ├── color_scheme_luna.png │ │ ├── color_scheme_macau.png │ │ ├── color_scheme_metroblue.png │ │ ├── color_scheme_modern_warfare.png │ │ ├── color_scheme_nba.png │ │ ├── color_scheme_ps4.png │ │ ├── color_scheme_psionics.png │ │ ├── color_scheme_skype.png │ │ ├── color_scheme_smurfs.png │ │ ├── color_scheme_so_young.png │ │ ├── color_scheme_solarized_rock.png │ │ ├── color_scheme_starcraft.png │ │ ├── color_scheme_starcraft_ii.png │ │ ├── color_scheme_steam.png │ │ ├── color_scheme_tintin.png │ │ ├── color_scheme_wii.png │ │ ├── color_scheme_xbox_silver.png │ │ └── color_scheme_youtube.png │ └── weasel.yaml ├── install.bat ├── install.nsi ├── rime-install-config.bat ├── start_service.bat ├── stop_service.bat ├── sudo.js └── uninstall.bat ├── render.js ├── resource ├── en.ico ├── full.ico ├── half.ico ├── reload.ico ├── weasel.ico └── zh.ico ├── test ├── TestResponseParser │ ├── ReadMe.txt │ ├── TestResponseParser.cpp │ ├── TestResponseParser.vcxproj │ ├── TestResponseParser.vcxproj.filters │ ├── stdafx.cpp │ ├── stdafx.h │ ├── targetver.h │ └── xmake.lua └── TestWeaselIPC │ ├── ReadMe.txt │ ├── TestWeaselIPC.cpp │ ├── TestWeaselIPC.vcxproj │ ├── TestWeaselIPC.vcxproj.filters │ ├── stdafx.cpp │ ├── stdafx.h │ ├── targetver.h │ └── xmake.lua ├── update ├── appcast.xml ├── bump-version.ps1 ├── bump-version.sh ├── testing-appcast.xml └── write-release-notes.sh ├── weasel.props.template ├── weasel.sln ├── xbuild.bat └── xmake.lua /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Chromium 2 | SortIncludes: false 3 | -------------------------------------------------------------------------------- /.exclude_pattern.txt: -------------------------------------------------------------------------------- 1 | stdafx 2 | targetver 3 | resource.h 4 | winapifamily 5 | winpackagefamily 6 | winsparkle 7 | immdev.h 8 | SystemTraySDK.h 9 | ctffunc.h 10 | -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # apply clang format 2 | 21d2bf9df4227c2f1a738002130a47265e70ada8 3 | 4 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.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-2019 16 | env: 17 | boost_version: 1.84.0 18 | BOOST_ROOT: ${{ github.workspace }}\deps\boost_1_84_0 19 | steps: 20 | - name: Checkout last commit 21 | uses: actions/checkout@v4 22 | with: 23 | submodules: true 24 | fetch-depth: 0 25 | 26 | - name: Fetch all tags 27 | if: github.ref == 'refs/heads/master' 28 | run: git fetch --tags 29 | 30 | - name: Configure build environment 31 | shell: bash 32 | run: | 33 | cp env.vs2019.bat env.bat 34 | 35 | # cache boost 36 | - name: Cache Boost 37 | id: cache-boost 38 | uses: actions/cache@v4 39 | with: 40 | path: | 41 | ${{ env.BOOST_ROOT }} 42 | key: ${{ runner.os }}-boost-${{ env.boost_version }} 43 | 44 | # install boost if not cached 45 | - name: Install Boost 46 | if: steps.cache-boost.outputs.cache-hit != 'true' 47 | shell: bash 48 | run: | 49 | ./install_boost.bat 50 | ./build.bat boost arm64 51 | 52 | # add msbuild to PATH 53 | - name: Add msbuild to PATH 54 | uses: microsoft/setup-msbuild@v2 55 | 56 | # use upper stream released librime files if stable release 57 | - name: Get Rime files 58 | shell: pwsh 59 | run: | 60 | $ErrorActionPreference = 'Stop' 61 | .\get-rime.ps1 -use dev 62 | 63 | - name: Build data 64 | run: | 65 | .\build.bat data 66 | 67 | - name: Build Weasel Release 68 | id: build_weasel 69 | if: startsWith(github.ref, 'refs/tags/') 70 | env: 71 | RELEASE_BUILD: 1 72 | run: | 73 | .\build.bat arm64 installer 74 | 75 | - name: Build Weasel Nightly 76 | id: build_weasel_nightly 77 | if: github.ref == 'refs/heads/master' 78 | run: | 79 | .\build.bat arm64 installer 80 | 81 | - name: Compress Debug Symbols 82 | shell: pwsh 83 | run: | 84 | output\7z.exe a -t7z "./output/archives/debug_symbols.7z" "output/*.pdb" -r 85 | 86 | - name: Extract changelog 87 | shell: pwsh 88 | run: | 89 | .\extract_changelog.ps1 90 | if: startsWith(github.ref, 'refs/tags/') 91 | 92 | # create nightly release 93 | - name: Create Nightly release 94 | if: ${{ github.repository == 'rime/weasel' && github.ref == 'refs/heads/master' }} 95 | uses: 'marvinpinto/action-automatic-releases@latest' 96 | with: 97 | repo_token: ${{ secrets.GITHUB_TOKEN }} 98 | automatic_release_tag: latest 99 | prerelease: true 100 | title: "Nightly Build" 101 | files: | 102 | ./output/archives/weasel*.exe 103 | ./output/archives/debug_symbols.7z 104 | 105 | # create stable release 106 | - name: Release 107 | uses: softprops/action-gh-release@v2 108 | if: ${{ github.repository == 'rime/weasel' && startsWith(github.ref, 'refs/tags/') }} 109 | with: 110 | draft: true 111 | files: | 112 | ./output/archives/weasel*.exe 113 | ./output/archives/debug_symbols.7z 114 | body_path: ${{ github.workspace }}/RELEASE_CHANGELOG.md 115 | -------------------------------------------------------------------------------- /.github/workflows/update-appcast.yml: -------------------------------------------------------------------------------- 1 | name: Update Appcast 2 | on: 3 | release: 4 | types: [published, prereleased] 5 | jobs: 6 | 7 | update_appcast: 8 | 9 | runs-on: windows-2019 10 | 11 | steps: 12 | - name: Update Appcast 13 | if: ${{ github.repository == 'rime/weasel' }} 14 | run: gh workflow run gh-pages.yml -R rime/home --ref master 15 | env: 16 | GH_TOKEN: ${{ secrets.ACTIONS_DEPLOY_KEY }} 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cache 2 | .clangd 3 | .xmake 4 | build 5 | msbuild 6 | compile_commands.json 7 | /output/Win32/*.exe 8 | /output/Win32/rime.dll 9 | /output/Win32/*.pdb 10 | /lib*/rime.lib 11 | /lib*/*.dll 12 | /lib*/*.pdb 13 | /output/*.exp 14 | /output/Win32/*.exp 15 | /output/*.ilk 16 | /output/*.iobj 17 | /output/*.ipdb 18 | /output/*.pdb 19 | /output/*.lib 20 | /output/Win32/*.lib 21 | /output/*.exe 22 | /output/rime.dll 23 | /output/weasel*.dll 24 | /output/*.ime 25 | /output/*.txt 26 | /output/*.bat 27 | /output/data/essay.txt 28 | /output/data/opencc/ 29 | /output/data/*.yaml 30 | /output/archives 31 | /include/glog 32 | /include/rime*.h 33 | /ipch 34 | env.bat 35 | weasel.props 36 | *.log 37 | *.user 38 | *.suo 39 | *.sdf 40 | *.opensdf 41 | *.aps 42 | *~ 43 | .*.swp 44 | *.swp 45 | .vs 46 | Thumbs.db 47 | /.idea 48 | /cmake-build-debug 49 | *.VC.db 50 | release-notes.html 51 | *.7z 52 | RELEASE_CHANGELOG.md 53 | deps/ 54 | arm64x_wrapper/*.o 55 | arm64x_wrapper/*.dll 56 | arm64x_wrapper/*.ime 57 | arm64x_wrapper/*.lib 58 | arm64x_wrapper/*.exp -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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`, `clang-format(>=17.0.6)` 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /RimeWithWeasel/WeaselUtility.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include 3 | #include 4 | #include 5 | 6 | fs::path WeaselUserDataPath() { 7 | WCHAR _path[MAX_PATH] = {0}; 8 | const WCHAR KEY[] = L"Software\\Rime\\Weasel"; 9 | HKEY hKey; 10 | LSTATUS ret = RegOpenKey(HKEY_CURRENT_USER, KEY, &hKey); 11 | if (ret == ERROR_SUCCESS) { 12 | DWORD len = sizeof(_path); 13 | DWORD type = 0; 14 | DWORD data = 0; 15 | ret = 16 | RegQueryValueEx(hKey, L"RimeUserDir", NULL, &type, (LPBYTE)_path, &len); 17 | RegCloseKey(hKey); 18 | if (ret == ERROR_SUCCESS && type == REG_SZ && _path[0]) { 19 | return fs::path(_path); 20 | } 21 | } 22 | // default location 23 | ExpandEnvironmentStringsW(L"%AppData%\\Rime", _path, _countof(_path)); 24 | return fs::path(_path); 25 | } 26 | 27 | fs::path WeaselSharedDataPath() { 28 | wchar_t _path[MAX_PATH] = {0}; 29 | GetModuleFileNameW(NULL, _path, _countof(_path)); 30 | return fs::path(_path).remove_filename().append("data"); 31 | } 32 | 33 | std::string GetCustomResource(const char* name, const char* type) { 34 | const HINSTANCE module = 0; // main executable 35 | HRSRC hRes = FindResourceA(module, name, type); 36 | if (hRes) { 37 | HGLOBAL hData = LoadResource(module, hRes); 38 | if (hData) { 39 | const char* data = (const char*)::LockResource(hData); 40 | size_t size = ::SizeofResource(module, hRes); 41 | 42 | if (data && size) { 43 | if (data[size - 1] == '\0') // null-terminated string 44 | size--; 45 | return std::string(data, size); 46 | } 47 | } 48 | } 49 | 50 | return std::string(); 51 | } 52 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /RimeWithWeasel/xmake.lua: -------------------------------------------------------------------------------- 1 | target("RimeWithWeasel") 2 | set_kind("static") 3 | add_files("./*.cpp") 4 | add_rules("use_weaselconstants") 5 | 6 | -------------------------------------------------------------------------------- /WeaselDeployer/Configurator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class UIStyleSettings; 4 | 5 | class Configurator { 6 | public: 7 | explicit Configurator(); 8 | 9 | void Initialize(); 10 | int Run(bool installing); 11 | int UpdateWorkspace(bool report_errors = false); 12 | int DictManagement(); 13 | int SyncUserData(); 14 | }; 15 | -------------------------------------------------------------------------------- /WeaselDeployer/DictManagementDialog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | #include 5 | 6 | #include 7 | 8 | class DictManagementDialog : public CDialogDpiAware { 9 | public: 10 | enum { IDD = IDD_DICT_MANAGEMENT }; 11 | 12 | DictManagementDialog(); 13 | ~DictManagementDialog(); 14 | 15 | protected: 16 | BEGIN_MSG_MAP(DictManagementDialog) 17 | CHAIN_MSG_MAP(CDialogDpiAware) 18 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 19 | MESSAGE_HANDLER(WM_CLOSE, OnClose) 20 | COMMAND_ID_HANDLER(IDC_BACKUP, OnBackup) 21 | COMMAND_ID_HANDLER(IDC_RESTORE, OnRestore) 22 | COMMAND_ID_HANDLER(IDC_EXPORT, OnExport) 23 | COMMAND_ID_HANDLER(IDC_IMPORT, OnImport) 24 | COMMAND_HANDLER(IDC_USER_DICT_LIST, LBN_SELCHANGE, OnUserDictListSelChange) 25 | END_MSG_MAP() 26 | 27 | LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&); 28 | LRESULT OnClose(UINT, WPARAM, LPARAM, BOOL&); 29 | LRESULT OnBackup(WORD, WORD code, HWND, BOOL&); 30 | LRESULT OnRestore(WORD, WORD code, HWND, BOOL&); 31 | LRESULT OnExport(WORD, WORD code, HWND, BOOL&); 32 | LRESULT OnImport(WORD, WORD code, HWND, BOOL&); 33 | LRESULT OnUserDictListSelChange(WORD, WORD, HWND, BOOL&); 34 | 35 | void Populate(); 36 | 37 | CListBox user_dict_list_; 38 | CButton backup_; 39 | CButton restore_; 40 | CButton export_; 41 | CButton import_; 42 | 43 | RimeLeversApi* api_; 44 | }; 45 | -------------------------------------------------------------------------------- /WeaselDeployer/SwitcherSettingsDialog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | #include 5 | #include 6 | 7 | class SwitcherSettingsDialog : public CDialogDpiAware { 8 | public: 9 | enum { IDD = IDD_SWITCHER_SETTING }; 10 | 11 | SwitcherSettingsDialog(RimeSwitcherSettings* settings); 12 | ~SwitcherSettingsDialog(); 13 | 14 | protected: 15 | BEGIN_MSG_MAP(SwitcherSettingsDialog) 16 | CHAIN_MSG_MAP(CDialogDpiAware) 17 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 18 | MESSAGE_HANDLER(WM_CLOSE, OnClose) 19 | COMMAND_HANDLER(IDC_GET_SCHEMATA, BN_CLICKED, OnGetSchemata) 20 | COMMAND_ID_HANDLER(IDOK, OnOK) 21 | NOTIFY_HANDLER(IDC_SCHEMA_LIST, LVN_ITEMCHANGED, OnSchemaListItemChanged) 22 | END_MSG_MAP() 23 | 24 | LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&); 25 | LRESULT OnClose(UINT, WPARAM, LPARAM, BOOL&); 26 | LRESULT OnGetSchemata(WORD, WORD, HWND, BOOL&); 27 | LRESULT OnOK(WORD, WORD, HWND, BOOL&); 28 | LRESULT OnSchemaListItemChanged(int, LPNMHDR, BOOL&); 29 | 30 | void Populate(); 31 | void ShowDetails(RimeSchemaInfo* info); 32 | 33 | RimeLeversApi* api_; 34 | RimeSwitcherSettings* settings_; 35 | bool loaded_; 36 | bool modified_; 37 | 38 | CCheckListViewCtrl schema_list_; 39 | CStatic description_; 40 | CEdit hotkeys_; 41 | CButton get_schemata_; 42 | }; 43 | -------------------------------------------------------------------------------- /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 | void InitFontSettings(); 22 | bool SetFontFace(const std::string& key, const std::string& font_face); 23 | bool SetFontPoint(const std::string& key, const int font_point); 24 | 25 | RimeCustomSettings* settings() { return settings_; } 26 | std::wstring font_face; 27 | std::wstring label_font_face; 28 | std::wstring comment_font_face; 29 | int font_point; 30 | int label_font_point; 31 | int comment_font_point; 32 | 33 | private: 34 | RimeLeversApi* api_; 35 | RimeCustomSettings* settings_; 36 | }; 37 | -------------------------------------------------------------------------------- /WeaselDeployer/UIStyleSettingsDialog.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "UIStyleSettingsDialog.h" 3 | #include "UIStyleSettings.h" 4 | #include "Configurator.h" 5 | #include 6 | #include "FontSettingDialog.h" 7 | 8 | UIStyleSettingsDialog::UIStyleSettingsDialog(UIStyleSettings* settings) 9 | : settings_(settings), loaded_(false) {} 10 | 11 | UIStyleSettingsDialog::~UIStyleSettingsDialog() { 12 | image_.Destroy(); 13 | } 14 | 15 | void UIStyleSettingsDialog::Populate() { 16 | if (!settings_) 17 | return; 18 | std::string active(settings_->GetActiveColorScheme()); 19 | int active_index = -1; 20 | settings_->GetPresetColorSchemes(&preset_); 21 | for (size_t i = 0; i < preset_.size(); ++i) { 22 | std::wstring txt = u8tow(preset_[i].name); 23 | color_schemes_.AddString(txt.c_str()); 24 | if (preset_[i].color_scheme_id == active) { 25 | active_index = i; 26 | } 27 | } 28 | if (active_index >= 0) { 29 | color_schemes_.SetCurSel(active_index); 30 | Preview(active_index); 31 | } 32 | loaded_ = true; 33 | } 34 | 35 | LRESULT UIStyleSettingsDialog::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) { 36 | color_schemes_.Attach(GetDlgItem(IDC_COLOR_SCHEME)); 37 | preview_.Attach(GetDlgItem(IDC_PREVIEW)); 38 | select_font_.Attach(GetDlgItem(IDC_SELECT_FONT)); 39 | select_font_.EnableWindow(TRUE); 40 | 41 | Populate(); 42 | 43 | InitCtrlRects(); 44 | CenterWindow(); 45 | BringWindowToTop(); 46 | return TRUE; 47 | } 48 | 49 | LRESULT UIStyleSettingsDialog::OnClose(UINT, WPARAM, LPARAM, BOOL&) { 50 | EndDialog(IDCANCEL); 51 | return 0; 52 | } 53 | 54 | LRESULT UIStyleSettingsDialog::OnOK(WORD, WORD code, HWND, BOOL&) { 55 | EndDialog(code); 56 | return 0; 57 | } 58 | 59 | LRESULT UIStyleSettingsDialog::OnSelectFont(WORD, WORD code, HWND, BOOL&) { 60 | FontSettingDialog dialog(settings_, m_hWnd); 61 | 62 | if (dialog.ShowDialog() == IDOK) { 63 | settings_->SetFontFace("style/font_face", wtou8(dialog.m_font_face)); 64 | settings_->SetFontFace("style/label_font_face", 65 | wtou8(dialog.m_label_font_face)); 66 | settings_->SetFontFace("style/comment_font_face", 67 | wtou8(dialog.m_comment_font_face)); 68 | settings_->SetFontPoint("style/font_point", dialog.m_font_point); 69 | settings_->SetFontPoint("style/label_font_point", 70 | dialog.m_label_font_point); 71 | settings_->SetFontPoint("style/comment_font_point", 72 | dialog.m_comment_font_point); 73 | } 74 | return 0; 75 | } 76 | 77 | LRESULT UIStyleSettingsDialog::OnColorSchemeSelChange(WORD, WORD, HWND, BOOL&) { 78 | int index = color_schemes_.GetCurSel(); 79 | if (index >= 0 && index < (int)preset_.size()) { 80 | settings_->SelectColorScheme(preset_[index].color_scheme_id); 81 | Preview(index); 82 | } 83 | return 0; 84 | } 85 | 86 | void UIStyleSettingsDialog::Preview(int index) { 87 | if (index < 0 || index >= (int)preset_.size()) 88 | return; 89 | const std::string file_path( 90 | settings_->GetColorSchemePreview(preset_[index].color_scheme_id)); 91 | if (file_path.empty()) 92 | return; 93 | image_.Destroy(); 94 | // it is from ansi coding, not utf8 95 | image_.Load(acptow(file_path).c_str()); 96 | if (!image_.IsNull()) { 97 | preview_.SetBitmap(image_); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /WeaselDeployer/UIStyleSettingsDialog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | #include "UIStyleSettings.h" 5 | #include 6 | 7 | class UIStyleSettingsDialog : public CDialogDpiAware { 8 | public: 9 | enum { IDD = IDD_STYLE_SETTING }; 10 | 11 | UIStyleSettingsDialog(UIStyleSettings* settings); 12 | ~UIStyleSettingsDialog(); 13 | 14 | protected: 15 | BEGIN_MSG_MAP(UIStyleSettingsDialog) 16 | CHAIN_MSG_MAP(CDialogDpiAware) 17 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 18 | MESSAGE_HANDLER(WM_CLOSE, OnClose) 19 | COMMAND_ID_HANDLER(IDOK, OnOK) 20 | COMMAND_ID_HANDLER(IDC_SELECT_FONT, OnSelectFont) 21 | COMMAND_HANDLER(IDC_COLOR_SCHEME, LBN_SELCHANGE, OnColorSchemeSelChange) 22 | END_MSG_MAP() 23 | 24 | LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&); 25 | LRESULT OnClose(UINT, WPARAM, LPARAM, BOOL&); 26 | LRESULT OnOK(WORD, WORD code, HWND, BOOL&); 27 | LRESULT OnSelectFont(WORD, WORD code, HWND, BOOL&); 28 | LRESULT OnColorSchemeSelChange(WORD, WORD, HWND, BOOL&); 29 | 30 | void Populate(); 31 | void Preview(int index); 32 | 33 | UIStyleSettings* settings_; 34 | bool loaded_; 35 | std::vector preset_; 36 | 37 | CListBox color_schemes_; 38 | CStatic preview_; 39 | CImage image_; 40 | CButton select_font_; 41 | }; 42 | -------------------------------------------------------------------------------- /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 | #include 9 | 10 | CAppModule _Module; 11 | 12 | static int Run(LPTSTR lpCmdLine); 13 | 14 | int APIENTRY _tWinMain(HINSTANCE hInstance, 15 | HINSTANCE hPrevInstance, 16 | LPTSTR lpCmdLine, 17 | int nCmdShow) { 18 | UNREFERENCED_PARAMETER(hPrevInstance); 19 | SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); 20 | LANGID langId = get_language_id(); 21 | SetThreadUILanguage(langId); 22 | SetThreadLocale(langId); 23 | 24 | HRESULT hRes = ::CoInitialize(NULL); 25 | // If you are running on NT 4.0 or higher you can use the following call 26 | // instead to make the EXE free threaded. This means that calls come in on a 27 | // random RPC thread. 28 | // HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); 29 | ATLASSERT(SUCCEEDED(hRes)); 30 | 31 | // this resolves ATL window thunking problem when Microsoft Layer for Unicode 32 | // (MSLU) is used 33 | ::DefWindowProc(NULL, 0, 0, 0L); 34 | 35 | AtlInitCommonControls( 36 | ICC_BAR_CLASSES); // add flags to support other controls 37 | 38 | hRes = _Module.Init(NULL, hInstance); 39 | ATLASSERT(SUCCEEDED(hRes)); 40 | 41 | CreateDirectory(WeaselUserDataPath().c_str(), NULL); 42 | 43 | int ret = 0; 44 | HANDLE hMutex = CreateMutex(NULL, TRUE, L"WeaselDeployerExclusiveMutex"); 45 | if (!hMutex) { 46 | ret = 1; 47 | } else if (GetLastError() == ERROR_ALREADY_EXISTS) { 48 | ret = 1; 49 | } else { 50 | ret = Run(lpCmdLine); 51 | } 52 | 53 | if (hMutex) { 54 | CloseHandle(hMutex); 55 | } 56 | _Module.Term(); 57 | ::CoUninitialize(); 58 | 59 | return ret; 60 | } 61 | 62 | static int Run(LPTSTR lpCmdLine) { 63 | Configurator configurator; 64 | configurator.Initialize(); 65 | 66 | if (!wcscmp(L"/?", lpCmdLine) || !wcscmp(L"/help", lpCmdLine)) { 67 | WCHAR msg[1024] = {0}; 68 | if (LoadString(GetModuleHandle(NULL), IDS_STR_HELP, msg, 69 | sizeof(msg) / sizeof(TCHAR))) { 70 | MessageBox(NULL, msg, L"Weasel Deployer", MB_ICONINFORMATION | MB_OK); 71 | } else { 72 | MessageBox(NULL, 73 | L"Usage: WeaselDeployer.exe [options]\n" 74 | L"/? or /help - Show this help message\n" 75 | L"/deploy - Update Workspace\n" 76 | L"/dict - Manage dictionary\n" 77 | L"/sync - Sync user data\n" 78 | L"/install - Install Weasel (Initial deployment)", 79 | L"Weasel Deployer", MB_ICONINFORMATION | MB_OK); 80 | } 81 | return 0; 82 | } 83 | 84 | bool deployment_scheduled = !wcscmp(L"/deploy", lpCmdLine); 85 | if (deployment_scheduled) { 86 | return configurator.UpdateWorkspace(); 87 | } 88 | 89 | bool dict_management = !wcscmp(L"/dict", lpCmdLine); 90 | if (dict_management) { 91 | return configurator.DictManagement(); 92 | } 93 | 94 | bool sync_user_dict = !wcscmp(L"/sync", lpCmdLine); 95 | if (sync_user_dict) { 96 | return configurator.SyncUserData(); 97 | } 98 | 99 | bool installing = !wcscmp(L"/install", lpCmdLine); 100 | return configurator.Run(installing); 101 | } 102 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /WeaselDeployer/WeaselDeployer.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/WeaselDeployer/WeaselDeployer.rc -------------------------------------------------------------------------------- /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 | Header Files 47 | 48 | 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 | Source Files 73 | 74 | 75 | Source Files 76 | 77 | 78 | 79 | 80 | Resource Files 81 | 82 | 83 | 84 | 85 | Resource Files 86 | 87 | 88 | -------------------------------------------------------------------------------- /WeaselDeployer/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by WeaselDeployer.rc 4 | // 5 | #define IDC_MYICON 2 6 | #define IDD_WEASELDEPLOYER_DIALOG 102 7 | #define IDI_WEASELDEPLOYER 107 8 | #define IDI_SMALL 108 9 | #define IDR_MAINFRAME 128 10 | #define IDD_SWITCHER_SETTING 129 11 | #define IDD_STYLE_SETTING 130 12 | #define IDI_DEPLOY 131 13 | #define IDD_DICT_MANAGEMENT 132 14 | #define IDS_STR_WEASEL 133 15 | #define IDS_STR_SAD 134 16 | #define IDS_STR_HAPPY 135 17 | #define IDS_STR_NOT_REGULAR 136 18 | #define IDS_STR_DEPLOYING_RESTARTREQ 137 19 | #define IDS_STR_DEPLOYING_WAIT 138 20 | #define IDS_STR_SEL_EXPORT_DICT_NAME 139 21 | #define IDS_STR_ERREXPORT_SYNC_UV 140 22 | #define IDS_STR_ERR_EXPORT_UNKNOWN 141 23 | #define IDS_STR_ERR_EXPORT_SNAP_LOST 142 24 | #define IDS_STR_ERR_UNKNOW 143 25 | #define IDS_STR_ERR_UNKNOWN 143 26 | #define IDS_STR_ERR_SUCCESS 144 27 | #define IDS_STR_ERR_EXPORT_FILE_LOST 145 28 | #define IDS_STR_SEL_IMPORT_DICT_NAME 146 29 | #define IDS_STR_ERR_AT_LEAST_ONE_SEL 147 30 | #define IDS_STR_SCHEMA_NAME 148 31 | #define IDS_STR_OPEN 149 32 | #define IDS_STR_SAVE_AS 150 33 | #define IDS_STR_ALL_FILES 151 34 | #define IDS_STR_TXT_FILES 152 35 | #define IDS_STR_IMPORTED 153 36 | #define IDS_STR_EXPORTED 154 37 | #define IDS_STR_RECORD_COUNT 155 38 | #define IDS_STR_DICT_SNAPSHOT 156 39 | #define IDS_STR_KCSS_DICT_SNAPSHOT 157 40 | #define IDS_STR_HELP 158 41 | #define IDC_SCHEMA_LIST 1000 42 | #define IDC_SCHEMA_DESCRIPTION 1001 43 | #define IDC_GET_SCHEMATA 1002 44 | #define IDC_HOTKEYS 1003 45 | #define IDC_COLOR_SCHEME 1004 46 | #define IDC_SELECT_FONT 1005 47 | #define IDC_PREVIEW 1006 48 | #define IDC_USER_DICT_LIST 1007 49 | #define IDC_BACKUP 1008 50 | #define IDC_RESTORE 1009 51 | #define IDC_EXPORT 1010 52 | #define IDC_IMPORT 1011 53 | 54 | #define IDD_DIALOG_FONT 1999 55 | #define IDC_CBB_FONTPICKER 2000 56 | #define IDC_CKB_RANGEEN 2001 57 | #define IDC_EDIT_RANGESTART 2002 58 | #define IDC_EDIT_RANGEEND 2003 59 | #define IDC_BTN_ADDFONT 2004 60 | #define IDC_CBB_FONTFACE_NAME 2005 61 | #define IDC_EDIT_FONTFACE 2006 62 | #define IDC_CBB_FONTSTYLE 2007 63 | #define IDC_CBB_FONTWEIGHT 2008 64 | #define IDC_EDIT_PREVIEW_TEXT 2009 65 | #define IDC_CBB_FONTPOINT 2010 66 | #define IDC_STATIC_PREVIEW 2011 67 | #define IDC_STATIC1 -1 68 | 69 | // Next default values for new objects 70 | // 71 | #ifdef APSTUDIO_INVOKED 72 | #ifndef APSTUDIO_READONLY_SYMBOLS 73 | #define _APS_NO_MFC 1 74 | #define _APS_NEXT_RESOURCE_VALUE 135 75 | #define _APS_NEXT_COMMAND_VALUE 32771 76 | #define _APS_NEXT_CONTROL_VALUE 1012 77 | #define _APS_NEXT_SYMED_VALUE 110 78 | #endif 79 | #endif 80 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | #ifdef _UNICODE 27 | #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") 28 | #endif 29 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /WeaselDeployer/xmake.lua: -------------------------------------------------------------------------------- 1 | target("WeaselDeployer") 2 | set_kind("binary") 3 | add_files("./*.cpp") 4 | add_rules("add_rcfiles", "use_weaselconstants", "subwin") 5 | add_links("imm32", "kernel32", "rime", "d2d1", "dwrite", "Shcore") 6 | add_deps("WeaselIPC", "RimeWithWeasel") 7 | add_files("$(projectdir)/PerMonitorHighDPIAware.manifest") 8 | add_ldflags("/DEBUG /OPT:ICF /LARGEADDRESSAWARE /ERRORREPORT:QUEUE") 9 | before_build(function(target) 10 | local target_dir = path.join(target:targetdir(), target:name()) 11 | if not os.exists(target_dir) then 12 | os.mkdir(target_dir) 13 | end 14 | target:set("targetdir", target_dir) 15 | end) 16 | after_build(function(target) 17 | if is_arch("x86") then 18 | os.cp(path.join(target:targetdir(), "WeaselDeployer.exe"), "$(projectdir)/output/Win32") 19 | os.cp(path.join(target:targetdir(), "WeaselDeployer.pdb"), "$(projectdir)/output/Win32") 20 | else 21 | os.cp(path.join(target:targetdir(), "WeaselDeployer.exe"), "$(projectdir)/output") 22 | os.cp(path.join(target:targetdir(), "WeaselDeployer.pdb"), "$(projectdir)/output") 23 | end 24 | end) 25 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /WeaselIME/WeaselIME.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #define MAX_COMPOSITION_SIZE 256 6 | 7 | struct CompositionInfo { 8 | COMPOSITIONSTRING cs; 9 | WCHAR szCompStr[MAX_COMPOSITION_SIZE]; 10 | WCHAR szResultStr[MAX_COMPOSITION_SIZE]; 11 | void Reset() { 12 | memset(this, 0, sizeof(*this)); 13 | cs.dwSize = sizeof(*this); 14 | cs.dwCompStrOffset = (DWORD)((ptrdiff_t)&szCompStr - (ptrdiff_t)this); 15 | cs.dwResultStrOffset = (DWORD)((ptrdiff_t)&szResultStr - (ptrdiff_t)this); 16 | } 17 | }; 18 | 19 | class WeaselIME; 20 | 21 | class HIMCMap : public std::map > { 22 | public: 23 | HIMCMap() : m_valid(true) {} 24 | ~HIMCMap() { m_valid = false; } 25 | std::mutex& get_mutex() { return m_mutex; } 26 | bool is_valid() const { return m_valid; } 27 | 28 | private: 29 | bool m_valid; 30 | std::mutex m_mutex; 31 | }; 32 | 33 | class WeaselIME { 34 | public: 35 | static HINSTANCE GetModuleInstance(); 36 | static void SetModuleInstance(HINSTANCE hModule); 37 | static HRESULT RegisterUIClass(); 38 | static HRESULT UnregisterUIClass(); 39 | static LPCWSTR GetUIClassName(); 40 | static LRESULT WINAPI UIWndProc(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp); 41 | static BOOL IsIMEMessage(UINT uMsg); 42 | static std::shared_ptr GetInstance(HIMC hIMC); 43 | static void Cleanup(); 44 | 45 | WeaselIME(HIMC hIMC); 46 | LRESULT OnIMESelect(BOOL fSelect); 47 | LRESULT OnIMEFocus(BOOL fFocus); 48 | LRESULT OnUIMessage(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp); 49 | BOOL ProcessKeyEvent(UINT vKey, KeyInfo kinfo, const LPBYTE lpbKeyState); 50 | 51 | private: 52 | HRESULT _Initialize(); 53 | HRESULT _Finalize(); 54 | LRESULT _OnIMENotify(LPINPUTCONTEXT lpIMC, WPARAM wp, LPARAM lp); 55 | HRESULT _StartComposition(); 56 | HRESULT _EndComposition(LPCWSTR composition); 57 | HRESULT _AddIMEMessage(UINT msg, WPARAM wp, LPARAM lp); 58 | void _SetCandidatePos(LPINPUTCONTEXT lpIMC); 59 | void _SetCompositionWindow(LPINPUTCONTEXT lpIMC); 60 | void _UpdateInputPosition(LPINPUTCONTEXT lpIMC, POINT pt); 61 | 62 | private: 63 | static HINSTANCE s_hModule; 64 | static HIMCMap s_instances; 65 | HIMC m_hIMC; 66 | bool m_composing; 67 | bool m_preferCandidatePos; 68 | weasel::Client m_client; 69 | }; 70 | -------------------------------------------------------------------------------- /WeaselIME/WeaselIME.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/WeaselIME/WeaselIME.rc -------------------------------------------------------------------------------- /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 | 67 | 68 | Resource Files 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /WeaselIME/dllmain.cpp: -------------------------------------------------------------------------------- 1 | // dllmain.cpp : Defines the entry point for the DLL application. 2 | #include "stdafx.h" 3 | #include "WeaselIME.h" 4 | 5 | BOOL APIENTRY DllMain(HMODULE hModule, 6 | DWORD ul_reason_for_call, 7 | LPVOID lpReserved) { 8 | WeaselIME::SetModuleInstance(hModule); 9 | 10 | switch (ul_reason_for_call) { 11 | case DLL_PROCESS_ATTACH: { 12 | HRESULT hr = WeaselIME::RegisterUIClass(); 13 | if (FAILED(hr)) 14 | return FALSE; 15 | } break; 16 | case DLL_THREAD_ATTACH: 17 | break; 18 | case DLL_THREAD_DETACH: 19 | break; 20 | case DLL_PROCESS_DETACH: 21 | WeaselIME::Cleanup(); 22 | WeaselIME::UnregisterUIClass(); 23 | break; 24 | } 25 | return TRUE; 26 | } 27 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /WeaselIME/xmake.lua: -------------------------------------------------------------------------------- 1 | target("WeaselIME") 2 | set_kind("shared") 3 | add_files("./*.cpp") 4 | add_rules("add_rcfiles") 5 | add_links("advapi32", "imm32", "user32", "gdi32") 6 | add_deps("WeaselIPC", "WeaselUI") 7 | local fname = '' 8 | 9 | before_build(function(target) 10 | local target_dir = path.join(target:targetdir(), target:name()) 11 | if not os.exists(target_dir) then 12 | os.mkdir(target_dir) 13 | end 14 | target:set("targetdir", target_dir) 15 | end) 16 | 17 | after_build(function(target) 18 | os.cp(path.join(target:targetdir(), "*.ime"), "$(projectdir)/output") 19 | end) 20 | if is_arch("x86") then 21 | fname = "weasel.ime" 22 | elseif is_arch("x64") then 23 | fname = "weaselx64.ime" 24 | elseif is_arch("arm") then 25 | fname = "weaselARM.ime" 26 | elseif is_arch("arm64") then 27 | fname = "weaselARM64.ime" 28 | end 29 | set_filename(fname) 30 | 31 | -------------------------------------------------------------------------------- /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 | Deserializer::Ptr ActionLoader::Create(ResponseParser* pTarget) { 10 | return Deserializer::Ptr(new ActionLoader(pTarget)); 11 | } 12 | 13 | ActionLoader::ActionLoader(ResponseParser* pTarget) : Deserializer(pTarget) {} 14 | 15 | ActionLoader::~ActionLoader() {} 16 | 17 | void ActionLoader::Store(Deserializer::KeyType const& key, 18 | std::wstring const& value) { 19 | if (key.size() == 1) // no extention parts 20 | { 21 | // split value by L"," 22 | std::vector vecAction; 23 | split(vecAction, value, L","); 24 | 25 | // require specified action deserializers 26 | std::for_each(vecAction.begin(), vecAction.end(), 27 | [this](std::wstring& action) { 28 | Deserializer::Require(action, m_pTarget); 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /WeaselIPC/ActionLoader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Deserializer.h" 3 | 4 | class ActionLoader : public weasel::Deserializer { 5 | public: 6 | ActionLoader(weasel::ResponseParser* pTarget); 7 | virtual ~ActionLoader(); 8 | // store data 9 | virtual void Store(weasel::Deserializer::KeyType const& key, 10 | std::wstring const& value); 11 | // factory method 12 | static weasel::Deserializer::Ptr Create(weasel::ResponseParser* pTarget); 13 | }; 14 | -------------------------------------------------------------------------------- /WeaselIPC/Committer.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Deserializer.h" 3 | #include "Committer.h" 4 | #include 5 | 6 | using namespace weasel; 7 | 8 | Deserializer::Ptr Committer::Create(ResponseParser* pTarget) { 9 | return Deserializer::Ptr(new Committer(pTarget)); 10 | } 11 | 12 | Committer::Committer(ResponseParser* pTarget) : Deserializer(pTarget) {} 13 | 14 | Committer::~Committer() {} 15 | 16 | void Committer::Store(Deserializer::KeyType const& key, 17 | std::wstring const& value) { 18 | if (!m_pTarget->p_commit) 19 | return; 20 | if (key.size() == 1) { 21 | *m_pTarget->p_commit = unescape_string(value); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /WeaselIPC/Committer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Deserializer.h" 3 | 4 | class Committer : public weasel::Deserializer { 5 | public: 6 | Committer(weasel::ResponseParser* pTarget); 7 | virtual ~Committer(); 8 | // store data 9 | virtual void Store(weasel::Deserializer::KeyType const& key, 10 | std::wstring const& value); 11 | // factory method 12 | static weasel::Deserializer::Ptr Create(weasel::ResponseParser* pTarget); 13 | }; 14 | -------------------------------------------------------------------------------- /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 | return Deserializer::Ptr(new Configurator(pTarget)); 9 | } 10 | 11 | Configurator::Configurator(ResponseParser* pTarget) : Deserializer(pTarget) {} 12 | 13 | Configurator::~Configurator() {} 14 | 15 | void Configurator::Store(Deserializer::KeyType const& key, 16 | std::wstring const& value) { 17 | if (!m_pTarget->p_context || key.size() < 2) 18 | return; 19 | bool bool_value = (!value.empty() && value != L"0"); 20 | if (key[1] == L"inline_preedit") { 21 | m_pTarget->p_config->inline_preedit = bool_value; 22 | return; 23 | } 24 | 25 | if (key[1] == L"hide_ime_mode_icon") { 26 | m_pTarget->p_config->hide_ime_mode_icon = bool_value; 27 | return; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /WeaselIPC/Configurator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Deserializer.h" 3 | 4 | class Configurator : public weasel::Deserializer { 5 | public: 6 | Configurator(weasel::ResponseParser* pTarget); 7 | virtual ~Configurator(); 8 | // store data 9 | virtual void Store(weasel::Deserializer::KeyType const& key, 10 | std::wstring const& value); 11 | // factory method 12 | static weasel::Deserializer::Ptr Create(weasel::ResponseParser* pTarget); 13 | }; 14 | -------------------------------------------------------------------------------- /WeaselIPC/ContextUpdater.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Deserializer.h" 3 | 4 | class ContextUpdater : public weasel::Deserializer { 5 | public: 6 | ContextUpdater(weasel::ResponseParser* pTarget); 7 | virtual ~ContextUpdater(); 8 | virtual void Store(weasel::Deserializer::KeyType const& key, 9 | std::wstring const& value); 10 | 11 | void _StoreText(weasel::Text& target, 12 | Deserializer::KeyType k, 13 | std::wstring const& value); 14 | void _StoreCand(Deserializer::KeyType k, std::wstring const& value); 15 | 16 | static weasel::Deserializer::Ptr Create(weasel::ResponseParser* pTarget); 17 | }; 18 | 19 | class StatusUpdater : public weasel::Deserializer { 20 | public: 21 | StatusUpdater(weasel::ResponseParser* pTarget); 22 | virtual ~StatusUpdater(); 23 | virtual void Store(weasel::Deserializer::KeyType const& key, 24 | std::wstring const& value); 25 | 26 | static weasel::Deserializer::Ptr Create(weasel::ResponseParser* pTarget); 27 | }; 28 | -------------------------------------------------------------------------------- /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 | std::map Deserializer::s_factories; 12 | 13 | void Deserializer::Initialize(ResponseParser* pTarget) { 14 | if (s_factories.empty()) { 15 | // register factory methods 16 | // TODO: extend the parser's functionality in the future by defining more 17 | // actions here 18 | Define(L"action", ActionLoader::Create); 19 | Define(L"commit", Committer::Create); 20 | Define(L"ctx", ContextUpdater::Create); 21 | Define(L"status", StatusUpdater::Create); 22 | Define(L"config", Configurator::Create); 23 | Define(L"style", Styler::Create); 24 | } 25 | 26 | // loaded by default 27 | Require(L"action", pTarget); 28 | } 29 | 30 | void Deserializer::Define(std::wstring const& action, Factory factory) { 31 | s_factories[action] = factory; 32 | // s_factories.insert(make_pair(action, factory)); 33 | } 34 | 35 | bool Deserializer::Require(std::wstring const& action, 36 | ResponseParser* pTarget) { 37 | if (!pTarget) 38 | return false; 39 | 40 | std::map::iterator i = s_factories.find(action); 41 | if (i == s_factories.end()) { 42 | // unknown action type 43 | return false; 44 | } 45 | 46 | Factory& factory = i->second; 47 | 48 | pTarget->deserializers[action] = factory(pTarget); 49 | // pTarget->deserializers.insert(make_pair(action, factory(pTarget))); 50 | return true; 51 | } -------------------------------------------------------------------------------- /WeaselIPC/Deserializer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace weasel { 6 | 7 | template 8 | void TryDeserialize(boost::archive::text_wiarchive& ia, T& t) { 9 | try { 10 | ia >> t; 11 | } catch (const boost::archive::archive_exception& e) { 12 | const std::string msg = 13 | std::string("boost::archive::archive_exception: ") + e.what(); 14 | MessageBoxA(NULL, msg.c_str(), "IPC exception", MB_OK | MB_ICONERROR); 15 | } 16 | } 17 | class Deserializer { 18 | public: 19 | typedef std::vector KeyType; 20 | typedef std::shared_ptr Ptr; 21 | typedef std::function Factory; 22 | 23 | Deserializer(ResponseParser* pTarget) : m_pTarget(pTarget) {} 24 | virtual ~Deserializer() {} 25 | virtual void Store(KeyType const& key, std::wstring const& value) {} 26 | 27 | static void Initialize(ResponseParser* pTarget); 28 | static void Define(std::wstring const& action, Factory factory); 29 | static bool Require(std::wstring const& action, ResponseParser* pTarget); 30 | 31 | protected: 32 | ResponseParser* m_pTarget; 33 | 34 | private: 35 | static std::map s_factories; 36 | }; 37 | 38 | } // namespace weasel 39 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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, 9 | Context* context, 10 | Status* status, 11 | Config* config, 12 | UIStyle* style) 13 | : p_commit(commit), 14 | p_context(context), 15 | p_status(status), 16 | p_config(config), 17 | p_style(style) { 18 | Deserializer::Initialize(this); 19 | } 20 | 21 | bool ResponseParser::operator()(LPWSTR buffer, UINT length) { 22 | wbufferstream bs(buffer, length); 23 | std::wstring line; 24 | while (bs.good()) { 25 | std::getline(bs, line); 26 | if (!bs.good()) 27 | return false; 28 | 29 | // file ends 30 | if (line == L".") 31 | break; 32 | 33 | Feed(line); 34 | } 35 | return bs.good(); 36 | } 37 | 38 | void ResponseParser::Feed(const std::wstring& line) { 39 | // ignore blank lines and comments 40 | if (line.empty() || line.find_first_of(L'#') == 0) 41 | return; 42 | 43 | Deserializer::KeyType key; 44 | std::wstring value; 45 | 46 | // extract key (split by L'.') and value 47 | std::wstring::size_type sep_pos = line.find_first_of(L'='); 48 | if (sep_pos == std::wstring::npos) 49 | return; 50 | split(key, line.substr(0, sep_pos), L"."); 51 | if (key.empty()) 52 | return; 53 | value = line.substr(sep_pos + 1); 54 | 55 | // first part of the key serve as action type 56 | std::wstring const& action = key[0]; 57 | 58 | // get required action deserializer instance 59 | std::map::iterator i = 60 | deserializers.find(action); 61 | if (i == deserializers.end()) { 62 | // line ignored... since corresponding deserializer is not active 63 | return; 64 | } 65 | 66 | // dispatch 67 | Deserializer::Ptr p = i->second; 68 | p->Store(key, value); 69 | } 70 | -------------------------------------------------------------------------------- /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) : Deserializer(pTarget) {} 8 | 9 | Styler::~Styler() {} 10 | 11 | void Styler::Store(weasel::Deserializer::KeyType const& key, 12 | std::wstring const& value) { 13 | if (!m_pTarget->p_style) 14 | return; 15 | 16 | UIStyle& sty = *m_pTarget->p_style; 17 | std::wstringstream ss(value); 18 | boost::archive::text_wiarchive ia(ss); 19 | 20 | TryDeserialize(ia, sty); 21 | } 22 | 23 | weasel::Deserializer::Ptr Styler::Create(weasel::ResponseParser* pTarget) { 24 | return Deserializer::Ptr(new Styler(pTarget)); 25 | } 26 | -------------------------------------------------------------------------------- /WeaselIPC/Styler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace weasel { 4 | class Deserializr; 5 | } 6 | 7 | class Styler : public weasel::Deserializer { 8 | public: 9 | Styler(weasel::ResponseParser* pTarget); 10 | virtual ~Styler(); 11 | // store data 12 | virtual void Store(weasel::Deserializer::KeyType const& key, 13 | std::wstring const& value); 14 | // factory method 15 | static weasel::Deserializer::Ptr Create(weasel::ResponseParser* pTarget); 16 | }; 17 | -------------------------------------------------------------------------------- /WeaselIPC/WeaselClientImpl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace weasel { 6 | 7 | class ClientImpl { 8 | public: 9 | ClientImpl(); 10 | ~ClientImpl(); 11 | 12 | bool Connect(ServerLauncher const& launcher); 13 | void Disconnect(); 14 | void ShutdownServer(); 15 | void StartSession(); 16 | void EndSession(); 17 | void StartMaintenance(); 18 | void EndMaintenance(); 19 | bool Echo(); 20 | bool ProcessKeyEvent(KeyEvent const& keyEvent); 21 | bool CommitComposition(); 22 | bool ClearComposition(); 23 | bool SelectCandidateOnCurrentPage(size_t index); 24 | bool HighlightCandidateOnCurrentPage(size_t index); 25 | bool ChangePage(bool backward); 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 | } // namespace weasel -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /WeaselIPC/xmake.lua: -------------------------------------------------------------------------------- 1 | target("WeaselIPC") 2 | set_kind("static") 3 | add_files("./*.cpp") 4 | 5 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 \ 10 | SDDL_SACL \ 11 | SDDL_DELIMINATOR \ 12 | SDDL_ACE_BEGIN \ 13 | SDDL_MANDATORY_LABEL \ 14 | SDDL_SEPERATOR \ 15 | SDDL_SEPERATOR \ 16 | SDDL_NO_WRITE_UP \ 17 | SDDL_SEPERATOR \ 18 | SDDL_SEPERATOR \ 19 | SDDL_SEPERATOR \ 20 | SDDL_ML_LOW \ 21 | SDDL_ACE_END 22 | 23 | #define LOCAL_SYSTEM_FILE_ACCESS \ 24 | SDDL_ACE_BEGIN \ 25 | SDDL_ACCESS_ALLOWED \ 26 | SDDL_SEPERATOR \ 27 | SDDL_SEPERATOR \ 28 | SDDL_FILE_ALL \ 29 | SDDL_SEPERATOR \ 30 | SDDL_SEPERATOR \ 31 | SDDL_SEPERATOR \ 32 | SDDL_LOCAL_SYSTEM \ 33 | SDDL_ACE_END 34 | 35 | #define EVERYONE_FILE_ACCESS \ 36 | SDDL_ACE_BEGIN \ 37 | SDDL_ACCESS_ALLOWED \ 38 | SDDL_SEPERATOR \ 39 | SDDL_SEPERATOR \ 40 | SDDL_FILE_ALL \ 41 | SDDL_SEPERATOR \ 42 | SDDL_SEPERATOR \ 43 | SDDL_SEPERATOR \ 44 | SDDL_EVERYONE \ 45 | SDDL_ACE_END 46 | 47 | #define ALL_APP_PACKAGES_FILE_ACCESS \ 48 | SDDL_ACE_BEGIN \ 49 | SDDL_ACCESS_ALLOWED \ 50 | SDDL_SEPERATOR \ 51 | SDDL_SEPERATOR \ 52 | SDDL_FILE_ALL \ 53 | SDDL_SEPERATOR \ 54 | SDDL_SEPERATOR \ 55 | SDDL_SEPERATOR \ 56 | SDDL_ALL_APP_PACKAGES \ 57 | SDDL_ACE_END 58 | 59 | namespace weasel { 60 | 61 | void SecurityAttribute::_Init() { 62 | // Privileges for UWP and IE protected mode 63 | // https://stackoverflow.com/questions/39138674/accessing-named-pipe-servers-from-within-ie-epm-bho 64 | 65 | ConvertStringSecurityDescriptorToSecurityDescriptor( 66 | LOW_INTEGRITY_SDDL_SACL SDDL_DACL SDDL_DELIMINATOR 67 | LOCAL_SYSTEM_FILE_ACCESS EVERYONE_FILE_ACCESS 68 | ALL_APP_PACKAGES_FILE_ACCESS, 69 | SDDL_REVISION_1, &pd, NULL); 70 | sa.nLength = sizeof(SECURITY_ATTRIBUTES); 71 | sa.lpSecurityDescriptor = pd; 72 | sa.bInheritHandle = TRUE; 73 | } 74 | 75 | SECURITY_ATTRIBUTES* SecurityAttribute::get_attr() { 76 | return &sa; 77 | } 78 | }; // namespace weasel 79 | -------------------------------------------------------------------------------- /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 | 12 | public: 13 | SecurityAttribute() : pd(NULL) { _Init(); } 14 | SECURITY_ATTRIBUTES* get_attr(); 15 | }; 16 | }; // namespace weasel 17 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /WeaselIPCServer/xmake.lua: -------------------------------------------------------------------------------- 1 | target("WeaselIPCServer") 2 | set_kind("static") 3 | add_files("./*.cpp") 4 | 5 | -------------------------------------------------------------------------------- /WeaselServer/WeaselServer.h: -------------------------------------------------------------------------------- 1 | // WeaselServer.h 2 | -------------------------------------------------------------------------------- /WeaselServer/WeaselServer.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/WeaselServer/WeaselServer.rc -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | // m_handler.reset(new RimeWithWeaselHandler(&m_ui)); 9 | m_server.SetRequestHandler(m_handler.get()); 10 | SetupMenuHandlers(); 11 | } 12 | 13 | WeaselServerApp::~WeaselServerApp() {} 14 | 15 | int WeaselServerApp::Run() { 16 | if (!m_server.Start()) 17 | return -1; 18 | 19 | // win_sparkle_set_appcast_url("http://localhost:8000/weasel/update/appcast.xml"); 20 | win_sparkle_set_registry_path("Software\\Rime\\Weasel\\Updates"); 21 | if (GetThreadUILanguage() == 22 | MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)) 23 | win_sparkle_set_lang("zh-TW"); 24 | else if (GetThreadUILanguage() == 25 | MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)) 26 | win_sparkle_set_lang("zh-CN"); 27 | else 28 | win_sparkle_set_lang("en"); 29 | win_sparkle_init(); 30 | m_ui.Create(m_server.GetHWnd()); 31 | 32 | m_handler->Initialize(); 33 | m_handler->OnUpdateUI([this]() { tray_icon.Refresh(); }); 34 | 35 | tray_icon.Create(m_server.GetHWnd()); 36 | tray_icon.Refresh(); 37 | 38 | int ret = m_server.Run(); 39 | 40 | m_handler->Finalize(); 41 | m_ui.Destroy(); 42 | tray_icon.RemoveIcon(); 43 | win_sparkle_cleanup(); 44 | 45 | return ret; 46 | } 47 | 48 | void WeaselServerApp::SetupMenuHandlers() { 49 | std::filesystem::path dir = install_dir(); 50 | m_server.AddMenuHandler(ID_WEASELTRAY_QUIT, 51 | [this] { return m_server.Stop() == 0; }); 52 | m_server.AddMenuHandler(ID_WEASELTRAY_DEPLOY, 53 | std::bind(execute, dir / L"WeaselDeployer.exe", 54 | std::wstring(L"/deploy"))); 55 | m_server.AddMenuHandler( 56 | ID_WEASELTRAY_SETTINGS, 57 | std::bind(execute, dir / L"WeaselDeployer.exe", std::wstring())); 58 | m_server.AddMenuHandler( 59 | ID_WEASELTRAY_DICT_MANAGEMENT, 60 | std::bind(execute, dir / L"WeaselDeployer.exe", std::wstring(L"/dict"))); 61 | m_server.AddMenuHandler( 62 | ID_WEASELTRAY_SYNC, 63 | std::bind(execute, dir / L"WeaselDeployer.exe", std::wstring(L"/sync"))); 64 | m_server.AddMenuHandler(ID_WEASELTRAY_WIKI, 65 | std::bind(open, L"https://rime.im/docs/")); 66 | m_server.AddMenuHandler(ID_WEASELTRAY_HOMEPAGE, 67 | std::bind(open, L"https://rime.im/")); 68 | m_server.AddMenuHandler(ID_WEASELTRAY_FORUM, 69 | std::bind(open, L"https://rime.im/discuss/")); 70 | m_server.AddMenuHandler(ID_WEASELTRAY_CHECKUPDATE, check_update); 71 | m_server.AddMenuHandler(ID_WEASELTRAY_INSTALLDIR, std::bind(explore, dir)); 72 | m_server.AddMenuHandler(ID_WEASELTRAY_USERCONFIG, 73 | std::bind(explore, WeaselUserDataPath())); 74 | m_server.AddMenuHandler(ID_WEASELTRAY_LOGDIR, 75 | std::bind(explore, WeaselLogPath())); 76 | } 77 | -------------------------------------------------------------------------------- /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 | #include 13 | 14 | #include "WeaselTrayIcon.h" 15 | 16 | namespace fs = std::filesystem; 17 | 18 | class WeaselServerApp { 19 | public: 20 | static bool execute(const fs::path& cmd, const std::wstring& args) { 21 | return (uintptr_t)ShellExecuteW(NULL, NULL, cmd.c_str(), args.c_str(), NULL, 22 | SW_SHOWNORMAL) > 32; 23 | } 24 | 25 | static bool explore(const fs::path& path) { 26 | std::wstring quoted_path(L"\"" + path.wstring() + L"\""); 27 | return (uintptr_t)ShellExecuteW(NULL, L"explore", quoted_path.c_str(), NULL, 28 | NULL, SW_SHOWNORMAL) > 32; 29 | } 30 | 31 | static bool open(const fs::path& path) { 32 | return (uintptr_t)ShellExecuteW(NULL, L"open", path.c_str(), NULL, NULL, 33 | SW_SHOWNORMAL) > 32; 34 | } 35 | 36 | static bool check_update() { 37 | // when checked manually, show testing versions too 38 | std::string feed_url = GetCustomResource("ManualUpdateFeedURL", "APPCAST"); 39 | std::wstring channel{}; 40 | auto ret = RegGetStringValue(HKEY_CURRENT_USER, L"Software\\Rime\\Weasel", 41 | L"UpdateChannel", channel); 42 | if (!ret && channel == L"testing") { 43 | feed_url = GetCustomResource("TestingManualUpdateFeedURL", "APPCAST"); 44 | } 45 | if (!feed_url.empty()) { 46 | win_sparkle_set_appcast_url(feed_url.c_str()); 47 | } 48 | win_sparkle_check_update_with_ui(); 49 | return true; 50 | } 51 | 52 | static fs::path install_dir() { 53 | WCHAR exe_path[MAX_PATH] = {0}; 54 | GetModuleFileNameW(GetModuleHandle(NULL), exe_path, _countof(exe_path)); 55 | return fs::path(exe_path).remove_filename(); 56 | } 57 | 58 | public: 59 | WeaselServerApp(); 60 | ~WeaselServerApp(); 61 | int Run(); 62 | 63 | protected: 64 | void SetupMenuHandlers(); 65 | 66 | weasel::Server m_server; 67 | weasel::UI m_ui; 68 | WeaselTrayIcon tray_icon; 69 | std::unique_ptr m_handler; 70 | }; 71 | -------------------------------------------------------------------------------- /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(BOOL fCanStop, BOOL fCanShutdown, BOOL fCanPauseContinue); 13 | ~WeaselService(); 14 | static BOOL Run(WeaselService& serv); 15 | 16 | void Stop(); 17 | // Start the service. 18 | void Start(DWORD dwArgc, PWSTR* pszArgv); 19 | 20 | protected: 21 | // Entry point for the service. It registers the handler function for the 22 | // service and starts the service. 23 | static void WINAPI ServiceMain(DWORD dwArgc, PWSTR* pszArgv); 24 | 25 | // The function is called by the SCM whenever a control code is sent to 26 | // the service. 27 | static void WINAPI ServiceCtrlHandler(DWORD dwCtrl); 28 | 29 | void SetServiceStatus(DWORD dwCurrentState, 30 | DWORD dwWin32ExitCode = NO_ERROR, 31 | DWORD dwWaitHint = 0); 32 | 33 | // Execute when the system is shutting down. 34 | void Shutdown(); 35 | 36 | private: 37 | static WeaselService* _service; 38 | 39 | // The status of the service 40 | SERVICE_STATUS _status; 41 | 42 | // The service status handle 43 | SERVICE_STATUS_HANDLE _statusHandle; 44 | 45 | BOOL _stopping; 46 | HANDLE _stoppedEvent; 47 | 48 | WeaselServerApp app; 49 | }; 50 | -------------------------------------------------------------------------------- /WeaselServer/WeaselTrayIcon.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "WeaselTrayIcon.h" 3 | #include 4 | 5 | // nasty 6 | #include 7 | 8 | static UINT mode_icon[] = {IDI_ZH, IDI_ZH, IDI_EN, IDI_RELOAD}; 9 | static const WCHAR* mode_label[] = {NULL, /*L"中文"*/ NULL, /*L"西文"*/ NULL, 10 | L"Under maintenance"}; 11 | 12 | WeaselTrayIcon::WeaselTrayIcon(weasel::UI& ui) 13 | : m_style(ui.style()), 14 | m_status(ui.status()), 15 | m_mode(INITIAL), 16 | m_schema_zhung_icon(), 17 | m_schema_ascii_icon(), 18 | m_disabled(false) {} 19 | 20 | void WeaselTrayIcon::CustomizeMenu(HMENU hMenu) {} 21 | 22 | BOOL WeaselTrayIcon::Create(HWND hTargetWnd) { 23 | HMODULE hModule = GetModuleHandle(NULL); 24 | CIcon icon; 25 | icon.LoadIconW(IDI_ZH); 26 | BOOL bRet = 27 | CSystemTray::Create(hModule, NULL, WM_WEASEL_TRAY_NOTIFY, 28 | get_weasel_ime_name().c_str(), icon, IDR_MENU_POPUP); 29 | if (hTargetWnd) { 30 | SetTargetWnd(hTargetWnd); 31 | } 32 | if (!m_style.display_tray_icon) { 33 | RemoveIcon(); 34 | } else { 35 | AddIcon(); 36 | } 37 | return bRet; 38 | } 39 | 40 | void WeaselTrayIcon::Refresh() { 41 | if (!m_style.display_tray_icon && 42 | !m_status.disabled) // display notification when deploying 43 | { 44 | if (m_mode != INITIAL) { 45 | RemoveIcon(); 46 | m_mode = INITIAL; 47 | } 48 | m_disabled = false; 49 | return; 50 | } 51 | WeaselTrayMode mode = m_status.disabled ? DISABLED 52 | : m_status.ascii_mode ? ASCII 53 | : ZHUNG; 54 | /* change icon, when 55 | 1,mode changed 56 | 2,icon changed 57 | 3,both m_schema_zhung_icon and m_style.current_zhung_icon empty(for 58 | initialize) 4,both m_schema_ascii_icon and m_style.current_ascii_icon 59 | empty(for initialize) 60 | */ 61 | if (mode != m_mode || m_schema_zhung_icon != m_style.current_zhung_icon || 62 | (m_schema_zhung_icon.empty() && m_style.current_zhung_icon.empty()) || 63 | m_schema_ascii_icon != m_style.current_ascii_icon || 64 | (m_schema_ascii_icon.empty() && m_style.current_ascii_icon.empty())) { 65 | ShowIcon(); 66 | m_mode = mode; 67 | m_schema_zhung_icon = m_style.current_zhung_icon; 68 | m_schema_ascii_icon = m_style.current_ascii_icon; 69 | if (mode == ASCII) { 70 | if (m_schema_ascii_icon.empty()) 71 | SetIcon(mode_icon[mode]); 72 | else 73 | SetIcon(m_schema_ascii_icon.c_str()); 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 | } else 80 | SetIcon(mode_icon[mode]); 81 | 82 | if (mode_label[mode] && m_disabled == false) { 83 | CString info; 84 | info.LoadStringW(IDS_STR_UNDER_MAINTENANCE); 85 | ShowBalloon(info, get_weasel_ime_name().c_str()); 86 | m_disabled = true; 87 | } 88 | if (m_mode != DISABLED) 89 | m_disabled = false; 90 | } else if (!Visible()) { 91 | ShowIcon(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /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 | class WeaselTrayIcon : public CSystemTray { 9 | public: 10 | enum WeaselTrayMode { 11 | INITIAL, 12 | ZHUNG, 13 | ASCII, 14 | DISABLED, 15 | }; 16 | 17 | WeaselTrayIcon(weasel::UI& ui); 18 | 19 | BOOL Create(HWND hTargetWnd); 20 | void Refresh(); 21 | 22 | protected: 23 | virtual void CustomizeMenu(HMENU hMenu); 24 | 25 | weasel::UIStyle& m_style; 26 | weasel::Status& m_status; 27 | WeaselTrayMode m_mode; 28 | std::wstring m_schema_zhung_icon; 29 | std::wstring m_schema_ascii_icon; 30 | bool m_disabled; 31 | }; 32 | -------------------------------------------------------------------------------- /WeaselServer/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by WeaselServer.rc 4 | // 5 | #define IDI_WEASEL 100 6 | #define IDI_EN 101 7 | #define IDI_ZH 102 8 | #define IDI_RELOAD 103 9 | #define IDR_MENU_POPUP 105 10 | #define IDI_FULL_SHAPE 106 11 | #define IDI_HALF_SHAPE 107 12 | #define IDS_STR_SYSTEM_VERSION_WARNING_CAPTION 300 13 | #define IDS_STR_SYSTEM_VERSION_WARNING 301 14 | #define IDS_STR_UNDER_MAINTENANCE 302 15 | #define ID_WEASELTRAY_QUIT 40001 16 | #define ID_WEASELTRAY_DEPLOY 40002 17 | #define ID_WEASELTRAY_CHECKUPDATE 40003 18 | #define ID_WEASELTRAY_FORUM 40004 19 | #define ID_WEASELTRAY_HOMEPAGE 40005 20 | #define ID_WEASELTRAY_INSTALLDIR 40006 21 | #define ID_WEASELTRAY_USERCONFIG 40007 22 | #define ID_WEASELTRAY_SETTINGS 40008 23 | #define ID_WEASELTRAY_WIKI 40009 24 | #define ID_WEASELTRAY_DICT_MANAGEMENT 40010 25 | #define ID_WEASELTRAY_SYNC 40012 26 | #define ID_WEASELTRAY_ENABLE_ASCII 40013 27 | #define ID_WEASELTRAY_DISABLE_ASCII 40014 28 | #define ID_WEASELTRAY_RERUN_SERVICE 40015 29 | #define ID_WEASELTRAY_LOGDIR 40016 30 | 31 | // Next default values for new objects 32 | // 33 | #ifdef APSTUDIO_INVOKED 34 | #ifndef APSTUDIO_READONLY_SYMBOLS 35 | #define _APS_NEXT_RESOURCE_VALUE 104 36 | #define _APS_NEXT_COMMAND_VALUE 40003 37 | #define _APS_NEXT_CONTROL_VALUE 1001 38 | #define _APS_NEXT_SYMED_VALUE 101 39 | #endif 40 | #endif 41 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | 54 | #if defined _M_IX86 55 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") 56 | #elif defined _M_X64 57 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") 58 | #else 59 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") 60 | #endif 61 | -------------------------------------------------------------------------------- /WeaselServer/xmake.lua: -------------------------------------------------------------------------------- 1 | target("WeaselServer") 2 | set_kind("binary") 3 | add_files("./*.cpp") 4 | add_rules("add_rcfiles", "subwin") 5 | add_links("imm32", "kernel32", "rime") 6 | add_deps("WeaselUI", "WeaselIPC", "RimeWithWeasel", "WeaselIPCServer") 7 | 8 | add_files("$(projectdir)/PerMonitorHighDPIAware.manifest") 9 | add_ldflags("/DEBUG /OPT:REF /OPT:ICF /LARGEADDRESSAWARE /ERRORREPORT:QUEUE") 10 | set_policy("windows.manifest.uac", "invoker") 11 | before_build(function(target) 12 | local target_dir = path.join(target:targetdir(), target:name()) 13 | if not os.exists(target_dir) then 14 | os.mkdir(target_dir) 15 | end 16 | target:set("targetdir", target_dir) 17 | end) 18 | after_build(function(target) 19 | if is_arch("x86") then 20 | os.cp(path.join(target:targetdir(), "WeaselServer.exe"), "$(projectdir)/output/Win32") 21 | os.cp(path.join(target:targetdir(), "WeaselServer.pdb"), "$(projectdir)/output/Win32") 22 | else 23 | os.cp(path.join(target:targetdir(), "WeaselServer.exe"), "$(projectdir)/output") 24 | os.cp(path.join(target:targetdir(), "WeaselServer.pdb"), "$(projectdir)/output") 25 | end 26 | end) 27 | 28 | -------------------------------------------------------------------------------- /WeaselSetup/WeaselSetup.h: -------------------------------------------------------------------------------- 1 | // WeaselSetup.h 2 | -------------------------------------------------------------------------------- /WeaselSetup/WeaselSetup.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/WeaselSetup/WeaselSetup.ico -------------------------------------------------------------------------------- /WeaselSetup/WeaselSetup.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/WeaselSetup/WeaselSetup.rc -------------------------------------------------------------------------------- /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/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by WeaselSetup.rc 4 | // 5 | #define IDI_WEASELSETUP 107 6 | #define IDR_WEASELSETUP 107 7 | #define IDR_MAINFRAME 128 8 | #define IDS_STRING_INSTALL 129 9 | #define IDS_STRING_MODIFY 130 10 | #define IDS_STR_INSTALL_FAILED 131 11 | #define IDS_STR_INSTALL_SUCCESS_CAP 132 12 | #define IDS_STR_UNINSTALL_SUCCESS_CAP 133 13 | #define IDS_STR_UNINSTALL_FAILED 134 14 | #define IDS_STR_ERRCANCELFSREDIRECT 135 15 | #define IDS_STR_ERRRECOVERFSREDIRECT 136 16 | #define IDS_STR_ERRREGIME 137 17 | #define IDS_STR_ERRREGTSF 138 18 | #define IDS_STR_ERRREGIMEWRITESVREXE 139 19 | #define IDS_STR_INORUN_FAILED 140 20 | #define IDS_STR_ERRWRITEWEASELROOT 141 21 | #define IDS_STR_INSTALL_SUCCESS_INFO 142 22 | #define IDS_STR_UNINSTALL_SUCCESS_INFO 143 23 | #define IDS_STR_ERR_WRITE_USER_DIR 144 24 | #define IDS_STR_ERR_WRITE_HANT 145 25 | #define IDS_STR_MODIFY_SUCCESS_INFO 146 26 | #define IDS_STR_MODIFY_SUCCESS_CAP 147 27 | #define IDS_STR_HELP 148 28 | #define IDD_INSTALL_OPTIONS 201 29 | #define IDD_DIALOG1 203 30 | #define IDC_RADIO_CN 1000 31 | #define IDC_RADIO_TW 1001 32 | #define IDC_RADIO_DEFAULT_DIR 1002 33 | #define IDC_RADIO_CUSTOM_DIR 1003 34 | #define IDC_EDIT_DIR 1004 35 | #define IDC_REMOVE 1005 36 | #define IDC_CHECK1 1006 37 | #define IDC_CHECK_INSTIME 1006 38 | #define IDC_BUTTON_CUSTOM_DIR 1007 39 | 40 | // Next default values for new objects 41 | // 42 | #ifdef APSTUDIO_INVOKED 43 | #ifndef APSTUDIO_READONLY_SYMBOLS 44 | #define _APS_NEXT_RESOURCE_VALUE 205 45 | #define _APS_NEXT_COMMAND_VALUE 32775 46 | #define _APS_NEXT_CONTROL_VALUE 1008 47 | #define _APS_NEXT_SYMED_VALUE 101 48 | #endif 49 | #endif 50 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /WeaselSetup/xmake.lua: -------------------------------------------------------------------------------- 1 | target("WeaselSetup") 2 | set_kind("binary") 3 | add_files("./*.cpp") 4 | add_rules("add_rcfiles", "use_weaselconstants", "subwin") 5 | add_links("imm32", "kernel32") 6 | 7 | set_policy("windows.manifest.uac", "invoker") 8 | add_files("$(projectdir)/PerMonitorHighDPIAware.manifest") 9 | add_ldflags("/DEBUG /OPT:REF /OPT:ICF /LARGEADDRESSAWARE /ERRORREPORT:QUEUE") 10 | 11 | before_build(function(target) 12 | local target_dir = path.join(target:targetdir(), target:name()) 13 | if not os.exists(target_dir) then 14 | os.mkdir(target_dir) 15 | end 16 | target:set("targetdir", target_dir) 17 | local level = target:policy("windows.manifest.uac") 18 | if level then 19 | local level_maps = { 20 | invoker = "asInvoker", 21 | admin = "requireAdministrator", 22 | highest = "highestAvailable" 23 | } 24 | assert(level_maps[level], "unknown uac level %s, please set invoker, admin or highest", level) 25 | local ui = target:policy("windows.manifest.uac.ui") or false 26 | target:add("ldflags", "/manifest:embed", {("/manifestuac:level='%s' uiAccess='%s'"):format(level_maps[level], ui)}, {force = true, expand = false}) 27 | end 28 | end) 29 | 30 | after_build(function(target) 31 | os.cp(path.join(target:targetdir(), "WeaselSetup.exe"), "$(projectdir)/output") 32 | os.cp(path.join(target:targetdir(), "WeaselSetup.pdb"), "$(projectdir)/output") 33 | end) 34 | -------------------------------------------------------------------------------- /WeaselTSF/CandidateList.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "ctffunc.h" 4 | 5 | class WeaselTSF; 6 | 7 | class CCandidateList : public ITfIntegratableCandidateListUIElement, 8 | public ITfCandidateListUIElementBehavior { 9 | public: 10 | CCandidateList(com_ptr pTextService); 11 | ~CCandidateList(); 12 | 13 | // IUnknown 14 | STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void** ppvObj); 15 | STDMETHODIMP_(ULONG) AddRef(void); 16 | STDMETHODIMP_(ULONG) Release(void); 17 | 18 | // ITfUIElement 19 | STDMETHODIMP GetDescription(BSTR* pbstr); 20 | STDMETHODIMP GetGUID(GUID* pguid); 21 | STDMETHODIMP Show(BOOL showCandidateWindow); 22 | STDMETHODIMP IsShown(BOOL* pIsShow); 23 | 24 | // ITfCandidateListUIElement 25 | STDMETHODIMP GetUpdatedFlags(DWORD* pdwFlags); 26 | STDMETHODIMP GetDocumentMgr(ITfDocumentMgr** ppdim); 27 | STDMETHODIMP GetCount(UINT* pCandidateCount); 28 | STDMETHODIMP GetSelection(UINT* pSelectedCandidateIndex); 29 | STDMETHODIMP GetString(UINT uIndex, BSTR* pbstr); 30 | STDMETHODIMP GetPageIndex(UINT* pIndex, UINT uSize, UINT* puPageCnt); 31 | STDMETHODIMP SetPageIndex(UINT* pIndex, UINT uPageCnt); 32 | STDMETHODIMP GetCurrentPage(UINT* puPage); 33 | 34 | // ITfCandidateListUIElementBehavior methods 35 | STDMETHODIMP SetSelection(UINT nIndex); 36 | STDMETHODIMP Finalize(void); 37 | STDMETHODIMP Abort(void); 38 | 39 | // ITfIntegratableCandidateListUIElement methods 40 | STDMETHODIMP SetIntegrationStyle(GUID guidIntegrationStyle); 41 | STDMETHODIMP GetSelectionStyle( 42 | _Out_ TfIntegratableCandidateListSelectionStyle* ptfSelectionStyle); 43 | STDMETHODIMP OnKeyDown(_In_ WPARAM wParam, 44 | _In_ LPARAM lParam, 45 | _Out_ BOOL* pIsEaten); 46 | STDMETHODIMP ShowCandidateNumbers(_Out_ BOOL* pIsShow); 47 | STDMETHODIMP FinalizeExactCompositionString(); 48 | 49 | /* Update */ 50 | void UpdateUI(const weasel::Context& ctx, const weasel::Status& status); 51 | void UpdateStyle(const weasel::UIStyle& sty); 52 | void UpdateInputPosition(RECT const& rc); 53 | void Destroy(); 54 | void DestroyAll(); 55 | void StartUI(); 56 | void EndUI(); 57 | 58 | com_ptr GetContextDocument(); 59 | bool GetIsReposition() { 60 | if (_ui) 61 | return _ui->GetIsReposition(); 62 | else 63 | return false; 64 | } 65 | 66 | weasel::UIStyle& style(); 67 | 68 | private: 69 | // void _UpdateOwner(); 70 | HWND _GetActiveWnd(); 71 | HRESULT _UpdateUIElement(); 72 | 73 | // for CCandidateList::EndUI(), after ending composition || 74 | // WeaselTSF::_EndUI() 75 | void _DisposeUIWindow(); 76 | // for CCandidateList::Destroy(), when inputing app exit 77 | void _DisposeUIWindowAll(); 78 | void _MakeUIWindow(); 79 | 80 | std::unique_ptr _ui; 81 | DWORD _cRef; 82 | com_ptr _tsf; 83 | DWORD uiid; 84 | TfIntegratableCandidateListSelectionStyle _selectionStyle = 85 | STYLE_ACTIVE_SELECTION; 86 | 87 | BOOL _pbShow; 88 | weasel::UIStyle _style; 89 | 90 | com_ptr _pContextDocument; 91 | }; 92 | -------------------------------------------------------------------------------- /WeaselTSF/Compartment.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class CCompartmentEventSink : public ITfCompartmentEventSink { 6 | public: 7 | using Callback = std::function; 8 | CCompartmentEventSink(Callback callback) 9 | : _callback(callback), _refCount(1) {}; 10 | ~CCompartmentEventSink() = default; 11 | 12 | // IUnknown 13 | STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void** ppvObj); 14 | STDMETHODIMP_(ULONG) AddRef(void); 15 | STDMETHODIMP_(ULONG) Release(void); 16 | 17 | // ITfCompartmentEventSink 18 | STDMETHODIMP OnChange(_In_ REFGUID guid); 19 | 20 | // function 21 | HRESULT _Advise(_In_ com_ptr punk, _In_ REFGUID guidCompartment); 22 | HRESULT _Unadvise(); 23 | 24 | private: 25 | com_ptr _compartment; 26 | DWORD _cookie; 27 | Callback _callback; 28 | 29 | LONG _refCount; 30 | }; 31 | -------------------------------------------------------------------------------- /WeaselTSF/DisplayAttribute.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "WeaselTSF.h" 4 | 5 | void WeaselTSF::_ClearCompositionDisplayAttributes(TfEditCookie ec, 6 | _In_ ITfContext* pContext) { 7 | ITfRange* pRangeComposition = nullptr; 8 | ITfProperty* pDisplayAttributeProperty = nullptr; 9 | 10 | if (FAILED(_pComposition->GetRange(&pRangeComposition))) { 11 | return; 12 | } 13 | 14 | if (SUCCEEDED(pContext->GetProperty(GUID_PROP_ATTRIBUTE, 15 | &pDisplayAttributeProperty))) { 16 | pDisplayAttributeProperty->Clear(ec, pRangeComposition); 17 | 18 | pDisplayAttributeProperty->Release(); 19 | } 20 | 21 | pRangeComposition->Release(); 22 | } 23 | 24 | BOOL WeaselTSF::_SetCompositionDisplayAttributes(TfEditCookie ec, 25 | _In_ ITfContext* pContext, 26 | ITfRange* pRangeComposition) { 27 | ITfProperty* pDisplayAttributeProperty = nullptr; 28 | HRESULT hr = S_OK; 29 | 30 | if (pRangeComposition == nullptr) 31 | hr = _pComposition->GetRange(&pRangeComposition); 32 | if (FAILED(hr)) { 33 | return FALSE; 34 | } 35 | 36 | hr = E_FAIL; 37 | 38 | if (SUCCEEDED(pContext->GetProperty(GUID_PROP_ATTRIBUTE, 39 | &pDisplayAttributeProperty))) { 40 | VARIANT var; 41 | var.vt = VT_I4; // we're going to set a TfGuidAtom 42 | var.lVal = _gaDisplayAttributeInput; 43 | 44 | hr = pDisplayAttributeProperty->SetValue(ec, pRangeComposition, &var); 45 | 46 | pDisplayAttributeProperty->Release(); 47 | } 48 | 49 | // DO NOT release range composition here 50 | // it will be released in another function 51 | // pRangeComposition->Release(); 52 | return (hr == S_OK); 53 | } 54 | 55 | BOOL WeaselTSF::_InitDisplayAttributeGuidAtom() { 56 | ITfCategoryMgr* pCategoryMgr = nullptr; 57 | HRESULT hr = 58 | CoCreateInstance(CLSID_TF_CategoryMgr, nullptr, CLSCTX_INPROC_SERVER, 59 | IID_ITfCategoryMgr, (void**)&pCategoryMgr); 60 | 61 | if (FAILED(hr)) { 62 | return FALSE; 63 | } 64 | 65 | hr = pCategoryMgr->RegisterGUID(c_guidDisplayAttributeInput, 66 | &_gaDisplayAttributeInput); 67 | if (FAILED(hr)) { 68 | goto Exit; 69 | } 70 | 71 | Exit: 72 | pCategoryMgr->Release(); 73 | 74 | return (hr == S_OK); 75 | } 76 | -------------------------------------------------------------------------------- /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 | {TF_CT_NONE, 0}, // text color 12 | {TF_CT_NONE, 0}, // background color (TF_CT_NONE => app default) 13 | TF_LS_DOT, // underline style 14 | FALSE, // underline boldness 15 | {TF_CT_NONE, 0}, // underline color 16 | TF_ATTR_INPUT // attribute info 17 | }; 18 | 19 | CDisplayAttributeInfoInput::CDisplayAttributeInfoInput() { 20 | DllAddRef(); 21 | _refCount = 1; 22 | 23 | _pguid = &c_guidDisplayAttributeInput; 24 | _pDisplayAttribute = &_daiDisplayAttribute; 25 | _pDescription = _daiDescription; 26 | _pValueName = _daiInputName; 27 | } 28 | 29 | CDisplayAttributeInfoInput::~CDisplayAttributeInfoInput() { 30 | DllRelease(); 31 | } 32 | 33 | STDAPI CDisplayAttributeInfoInput::QueryInterface(REFIID riid, 34 | _Outptr_ void** ppvObj) { 35 | if (ppvObj == nullptr) 36 | return E_INVALIDARG; 37 | 38 | *ppvObj = nullptr; 39 | 40 | if (IsEqualIID(riid, IID_IUnknown) || 41 | IsEqualIID(riid, IID_ITfDisplayAttributeInfo)) { 42 | *ppvObj = (ITfDisplayAttributeInfo*)this; 43 | } 44 | 45 | if (*ppvObj) { 46 | AddRef(); 47 | return S_OK; 48 | } 49 | 50 | return E_NOINTERFACE; 51 | } 52 | 53 | ULONG CDisplayAttributeInfoInput::AddRef(void) { 54 | return ++_refCount; 55 | } 56 | 57 | ULONG CDisplayAttributeInfoInput::Release(void) { 58 | LONG cr = --_refCount; 59 | 60 | assert(_refCount >= 0); 61 | 62 | if (_refCount == 0) { 63 | delete this; 64 | } 65 | 66 | return cr; 67 | } 68 | 69 | STDAPI CDisplayAttributeInfoInput::GetGUID(_Out_ GUID* pguid) { 70 | if (pguid == nullptr) 71 | return E_INVALIDARG; 72 | 73 | if (_pguid == nullptr) 74 | return E_FAIL; 75 | 76 | *pguid = *_pguid; 77 | 78 | return S_OK; 79 | } 80 | 81 | STDAPI CDisplayAttributeInfoInput::GetDescription(_Out_ BSTR* pbstrDesc) { 82 | BSTR tempDesc; 83 | 84 | if (pbstrDesc == nullptr) { 85 | return E_INVALIDARG; 86 | } 87 | 88 | *pbstrDesc = nullptr; 89 | 90 | if ((tempDesc = SysAllocString(_pDescription)) == nullptr) { 91 | return E_OUTOFMEMORY; 92 | } 93 | 94 | *pbstrDesc = tempDesc; 95 | 96 | return S_OK; 97 | } 98 | 99 | STDAPI CDisplayAttributeInfoInput::GetAttributeInfo( 100 | _Out_ TF_DISPLAYATTRIBUTE* ptfDisplayAttr) { 101 | if (ptfDisplayAttr == nullptr) { 102 | return E_INVALIDARG; 103 | } 104 | 105 | *ptfDisplayAttr = *_pDisplayAttribute; 106 | 107 | return S_OK; 108 | } 109 | 110 | STDAPI CDisplayAttributeInfoInput::SetAttributeInfo( 111 | _In_ const TF_DISPLAYATTRIBUTE* /*ptfDisplayAttr*/) { 112 | return E_NOTIMPL; 113 | } 114 | 115 | STDAPI CDisplayAttributeInfoInput::Reset() { 116 | return SetAttributeInfo(_pDisplayAttribute); 117 | } 118 | -------------------------------------------------------------------------------- /WeaselTSF/DisplayAttributeInfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class CDisplayAttributeInfoInput : public ITfDisplayAttributeInfo { 6 | public: 7 | CDisplayAttributeInfoInput(); 8 | ~CDisplayAttributeInfoInput(); 9 | 10 | // IUnknown 11 | STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void** ppvObj); 12 | STDMETHODIMP_(ULONG) AddRef(void); 13 | STDMETHODIMP_(ULONG) Release(void); 14 | 15 | // ITfDisplayAttributeInfo 16 | STDMETHODIMP GetGUID(_Out_ GUID* pguid); 17 | STDMETHODIMP GetDescription(_Out_ BSTR* pbstrDesc); 18 | STDMETHODIMP GetAttributeInfo(_Out_ TF_DISPLAYATTRIBUTE* pTSFDisplayAttr); 19 | STDMETHODIMP SetAttributeInfo(_In_ const TF_DISPLAYATTRIBUTE* ptfDisplayAttr); 20 | STDMETHODIMP Reset(); 21 | 22 | private: 23 | const GUID* _pguid; 24 | const TF_DISPLAYATTRIBUTE* _pDisplayAttribute; 25 | const WCHAR* _pDescription; 26 | const WCHAR* _pValueName; 27 | LONG _refCount; // COM ref count 28 | }; 29 | -------------------------------------------------------------------------------- /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( 8 | __RPC__deref_out_opt IEnumTfDisplayAttributeInfo** ppEnum) { 9 | CEnumDisplayAttributeInfo* pAttributeEnum = nullptr; 10 | 11 | if (ppEnum == nullptr) { 12 | return E_INVALIDARG; 13 | } 14 | 15 | *ppEnum = nullptr; 16 | 17 | pAttributeEnum = new (std::nothrow) CEnumDisplayAttributeInfo(); 18 | if (pAttributeEnum == nullptr) { 19 | return E_OUTOFMEMORY; 20 | } 21 | 22 | *ppEnum = pAttributeEnum; 23 | 24 | return S_OK; 25 | } 26 | 27 | STDAPI WeaselTSF::GetDisplayAttributeInfo( 28 | __RPC__in REFGUID guidInfo, 29 | __RPC__deref_out_opt ITfDisplayAttributeInfo** ppInfo) { 30 | if (ppInfo == nullptr) { 31 | return E_INVALIDARG; 32 | } 33 | 34 | *ppInfo = nullptr; 35 | 36 | if (IsEqualGUID(guidInfo, c_guidDisplayAttributeInput)) { 37 | *ppInfo = new (std::nothrow) CDisplayAttributeInfoInput(); 38 | if ((*ppInfo) == nullptr) { 39 | return E_OUTOFMEMORY; 40 | } 41 | } else { 42 | return E_INVALIDARG; 43 | } 44 | 45 | return S_OK; 46 | } 47 | -------------------------------------------------------------------------------- /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 | // get commit string from server 8 | std::wstring commit; 9 | weasel::Config config; 10 | auto context = std::make_shared(); 11 | weasel::ResponseParser parser(&commit, context.get(), &_status, &config, 12 | &_cand->style()); 13 | 14 | bool ok = m_client.GetResponseData(std::ref(parser)); 15 | 16 | if (config.hide_ime_mode_icon != _config.hide_ime_mode_icon) { 17 | _config = config; 18 | _UninitLanguageBar(); 19 | _InitLanguageBar(); 20 | } 21 | _UpdateLanguageBar(_status); 22 | 23 | if (ok) { 24 | if (!commit.empty()) { 25 | // For auto-selecting, commit and preedit can both exist. 26 | // Commit and close the original composition first. 27 | if (!_IsComposing()) { 28 | _StartComposition(_pEditSessionContext, 29 | _fCUASWorkaroundEnabled && !config.inline_preedit); 30 | } 31 | _InsertText(_pEditSessionContext, commit); 32 | _EndComposition(_pEditSessionContext, false); 33 | _committed = TRUE; 34 | } else { 35 | _committed = FALSE; 36 | } 37 | if (_status.composing && !_IsComposing()) { 38 | _StartComposition(_pEditSessionContext, 39 | _fCUASWorkaroundEnabled && !config.inline_preedit); 40 | } else if (!_status.composing && _IsComposing()) { 41 | _EndComposition(_pEditSessionContext, true); 42 | } 43 | if (_IsComposing() && config.inline_preedit) { 44 | _ShowInlinePreedit(_pEditSessionContext, context); 45 | } 46 | _UpdateCompositionWindow(_pEditSessionContext); 47 | } 48 | 49 | _UpdateUI(*context, _status); 50 | 51 | return TRUE; 52 | } 53 | -------------------------------------------------------------------------------- /WeaselTSF/EditSession.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "stdafx.h" 4 | #include "WeaselTSF.h" 5 | 6 | class CEditSession : public ITfEditSession { 7 | public: 8 | CEditSession(com_ptr pTextService, com_ptr pContext) 9 | : _pTextService(pTextService), _pContext(pContext) { 10 | _cRef = 1; 11 | } 12 | 13 | virtual ~CEditSession() {} 14 | 15 | /* IUnknown */ 16 | STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject) { 17 | if (ppvObject == NULL) 18 | return E_INVALIDARG; 19 | 20 | *ppvObject = NULL; 21 | 22 | if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfEditSession)) 23 | *ppvObject = (ITfEditSession*)this; 24 | 25 | if (*ppvObject) { 26 | AddRef(); 27 | return S_OK; 28 | } 29 | return E_NOINTERFACE; 30 | } 31 | 32 | STDMETHODIMP_(ULONG) AddRef() { return ++_cRef; } 33 | 34 | STDMETHODIMP_(ULONG) Release() { 35 | LONG cr = --_cRef; 36 | assert(_cRef >= 0); 37 | if (_cRef == 0) 38 | delete this; 39 | return cr; 40 | } 41 | 42 | /* ITfEditSession */ 43 | virtual STDMETHODIMP DoEditSession(TfEditCookie ec) = 0; 44 | 45 | protected: 46 | com_ptr _pTextService; 47 | com_ptr _pContext; 48 | 49 | private: 50 | LONG _cRef; /* COM reference count */ 51 | }; -------------------------------------------------------------------------------- /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 | DllAddRef(); 9 | 10 | _index = 0; 11 | _refCount = 1; 12 | } 13 | 14 | CEnumDisplayAttributeInfo::~CEnumDisplayAttributeInfo() { 15 | DllRelease(); 16 | } 17 | 18 | STDAPI CEnumDisplayAttributeInfo::QueryInterface(REFIID riid, 19 | _Outptr_ void** ppvObj) { 20 | if (ppvObj == nullptr) 21 | return E_INVALIDARG; 22 | 23 | *ppvObj = nullptr; 24 | 25 | if (IsEqualIID(riid, IID_IUnknown) || 26 | IsEqualIID(riid, IID_IEnumTfDisplayAttributeInfo)) { 27 | *ppvObj = (IEnumTfDisplayAttributeInfo*)this; 28 | } 29 | 30 | if (*ppvObj) { 31 | AddRef(); 32 | return S_OK; 33 | } 34 | 35 | return E_NOINTERFACE; 36 | } 37 | 38 | STDAPI_(ULONG) CEnumDisplayAttributeInfo::AddRef() { 39 | return ++_refCount; 40 | } 41 | 42 | STDAPI_(ULONG) CEnumDisplayAttributeInfo::Release() { 43 | LONG cr = --_refCount; 44 | 45 | assert(_refCount >= 0); 46 | 47 | if (_refCount == 0) { 48 | delete this; 49 | } 50 | 51 | return cr; 52 | } 53 | 54 | STDAPI CEnumDisplayAttributeInfo::Clone( 55 | _Out_ IEnumTfDisplayAttributeInfo** ppEnum) { 56 | CEnumDisplayAttributeInfo* pClone = nullptr; 57 | 58 | if (ppEnum == nullptr) { 59 | return E_INVALIDARG; 60 | } 61 | 62 | *ppEnum = nullptr; 63 | 64 | pClone = new (std::nothrow) CEnumDisplayAttributeInfo(); 65 | if ((pClone) == nullptr) { 66 | return E_OUTOFMEMORY; 67 | } 68 | 69 | // the clone should match this object's state 70 | pClone->_index = _index; 71 | 72 | *ppEnum = pClone; 73 | 74 | return S_OK; 75 | } 76 | 77 | STDAPI CEnumDisplayAttributeInfo::Next(ULONG ulCount, 78 | __RPC__out_ecount_part(ulCount, 79 | *pcFetched) 80 | ITfDisplayAttributeInfo** rgInfo, 81 | __RPC__out ULONG* pcFetched) { 82 | ULONG fetched; 83 | 84 | fetched = 0; 85 | 86 | if (ulCount == 0) { 87 | return S_OK; 88 | } 89 | if (rgInfo == nullptr) { 90 | return E_INVALIDARG; 91 | } 92 | *rgInfo = nullptr; 93 | 94 | while (fetched < ulCount) { 95 | ITfDisplayAttributeInfo* pDisplayAttributeInfo = nullptr; 96 | 97 | if (_index == 0) { 98 | pDisplayAttributeInfo = new (std::nothrow) CDisplayAttributeInfoInput(); 99 | if ((pDisplayAttributeInfo) == nullptr) { 100 | return E_OUTOFMEMORY; 101 | } 102 | } else { 103 | break; 104 | } 105 | 106 | *rgInfo = pDisplayAttributeInfo; 107 | rgInfo++; 108 | fetched++; 109 | _index++; 110 | } 111 | 112 | if (pcFetched != nullptr) { 113 | *pcFetched = fetched; 114 | } 115 | 116 | return (fetched == ulCount) ? S_OK : S_FALSE; 117 | } 118 | 119 | STDAPI CEnumDisplayAttributeInfo::Reset() { 120 | _index = 0; 121 | return S_OK; 122 | } 123 | 124 | STDAPI CEnumDisplayAttributeInfo::Skip(ULONG ulCount) { 125 | if ((ulCount + _index) > 1 || (ulCount + _index) < ulCount) { 126 | _index = 1; 127 | return S_FALSE; 128 | } 129 | _index += ulCount; 130 | return S_OK; 131 | } 132 | -------------------------------------------------------------------------------- /WeaselTSF/EnumDisplayAttributeInfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class CEnumDisplayAttributeInfo : public IEnumTfDisplayAttributeInfo { 4 | public: 5 | CEnumDisplayAttributeInfo(); 6 | ~CEnumDisplayAttributeInfo(); 7 | 8 | // IUnknown 9 | STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void** ppvObj); 10 | STDMETHODIMP_(ULONG) AddRef(void); 11 | STDMETHODIMP_(ULONG) Release(void); 12 | 13 | // IEnumTfDisplayAttributeInfo 14 | STDMETHODIMP Clone(_Out_ IEnumTfDisplayAttributeInfo** ppEnum); 15 | STDMETHODIMP Next(ULONG ulCount, 16 | __RPC__out_ecount_part(ulCount, *pcFetched) 17 | ITfDisplayAttributeInfo** rgInfo, 18 | __RPC__out ULONG* pcFetched); 19 | STDMETHODIMP Reset(); 20 | STDMETHODIMP Skip(ULONG ulCount); 21 | 22 | private: 23 | LONG _index; // next display attribute to enum 24 | LONG _refCount; // COM ref count 25 | }; 26 | -------------------------------------------------------------------------------- /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, 13 | 0xb1e9, 14 | 0x41ee, 15 | {0x9c, 0xa6, 0x7b, 0x4d, 0xd, 0xe6, 0xcb, 0xa}}; 16 | 17 | // {3D02CAB6-2B8E-4781-BA20-1C9267529467} 18 | static const GUID c_guidProfile = { 19 | 0x3d02cab6, 20 | 0x2b8e, 21 | 0x4781, 22 | {0xba, 0x20, 0x1c, 0x92, 0x67, 0x52, 0x94, 0x67}}; 23 | 24 | // {341F9E3A-B8AD-499D-936C-48701E329FB2} 25 | static const GUID c_guidLangBarItemButton = { 26 | 0x341f9e3a, 27 | 0xb8ad, 28 | 0x499d, 29 | {0x93, 0x6c, 0x48, 0x70, 0x1e, 0x32, 0x9f, 0xb2}}; 30 | 31 | // {2AC87E79-3260-4B32-9DEA-F8390976C20B} 32 | static const GUID c_guidDisplayAttributeInput = { 33 | 0x2ac87e79, 34 | 0x3260, 35 | 0x4b32, 36 | {0x9d, 0xea, 0xf8, 0x39, 0x09, 0x76, 0xc2, 0x0b}}; 37 | 38 | #ifdef WEASEL_USING_OLDER_TSF_SDK 39 | 40 | /* For Windows 8 */ 41 | const GUID GUID_TFCAT_TIPCAP_IMMERSIVESUPPORT = { 42 | 0x13A016DF, 43 | 0x560B, 44 | 0x46CD, 45 | {0x94, 0x7A, 0x4C, 0x3A, 0xF1, 0xE0, 0xE3, 0x5D}}; 46 | 47 | const GUID GUID_TFCAT_TIPCAP_SYSTRAYSUPPORT = { 48 | 0x25504FB4, 49 | 0x7BAB, 50 | 0x4BC1, 51 | {0x9C, 0x69, 0xCF, 0x81, 0x89, 0x0F, 0x0E, 0xF5}}; 52 | 53 | #endif 54 | 55 | const GUID GUID_LBI_INPUTMODE = { 56 | 0x2C77A81E, 57 | 0x41CC, 58 | 0x4178, 59 | {0xA3, 0xA7, 0x5F, 0x8A, 0x98, 0x75, 0x68, 0xE6}}; 60 | 61 | const GUID GUID_IME_MODE_PRESERVED_KEY = { 62 | 0x0bd899fc, 63 | 0xa8f7, 64 | 0x4b42, 65 | {0xa9, 0x6d, 0xce, 0xc7, 0xc5, 0x0e, 0x0e, 0xae}}; 66 | -------------------------------------------------------------------------------- /WeaselTSF/Globals.h: -------------------------------------------------------------------------------- 1 | /* Global definitions */ 2 | #pragma once 3 | 4 | #include "stdafx.h" 5 | #include 6 | 7 | #define TEXTSERVICE_LANGID_HANT \ 8 | MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL) 9 | #define TEXTSERVICE_LANGID_HONGKONG \ 10 | MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_HONGKONG) 11 | #define TEXTSERVICE_LANGID_MACAU MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_MACAU) 12 | #define TEXTSERVICE_LANGID_SINGAPORE \ 13 | MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SINGAPORE) 14 | #define TEXTSERVICE_LANGID_HANS \ 15 | MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED) 16 | 17 | #define TEXTSERVICE_DESC_A WEASEL_CODE_NAME 18 | #define TEXTSERVICE_MODEL "Apartment" 19 | 20 | #define TEXTSERVICE_ICON_INDEX 0 21 | 22 | void DllAddRef(); 23 | void DllRelease(); 24 | 25 | extern HINSTANCE g_hInst; 26 | 27 | extern LONG g_cRefDll; 28 | 29 | extern CRITICAL_SECTION g_cs; 30 | 31 | extern const CLSID c_clsidTextService; 32 | 33 | extern const GUID c_guidProfile; 34 | 35 | extern const GUID c_guidLangBarItemButton; 36 | 37 | extern const GUID c_guidDisplayAttributeInput; 38 | 39 | #ifndef TF_IPP_CAPS_IMMERSIVESUPPORT 40 | 41 | #define WEASEL_USING_OLDER_TSF_SDK 42 | 43 | /* for Windows 8 */ 44 | #define TF_TMF_IMMERSIVEMODE 0x40000000 45 | #define TF_IPP_CAPS_IMMERSIVESUPPORT 0x00010000 46 | #define TF_IPP_CAPS_SYSTRAYSUPPORT 0x00020000 47 | 48 | extern const GUID GUID_TFCAT_TIPCAP_IMMERSIVESUPPORT; 49 | extern const GUID GUID_TFCAT_TIPCAP_SYSTRAYSUPPORT; 50 | 51 | #endif 52 | 53 | extern const GUID GUID_LBI_INPUTMODE; 54 | extern const GUID GUID_IME_MODE_PRESERVED_KEY; 55 | -------------------------------------------------------------------------------- /WeaselTSF/LanguageBar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class CLangBarItemButton : public ITfLangBarItemButton, public ITfSource { 6 | public: 7 | CLangBarItemButton(com_ptr pTextService, 8 | REFGUID guid, 9 | weasel::UIStyle& style); 10 | ~CLangBarItemButton(); 11 | 12 | /* IUnknown */ 13 | STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject); 14 | STDMETHODIMP_(ULONG) AddRef(); 15 | STDMETHODIMP_(ULONG) Release(); 16 | 17 | /* ITfLangBarItem */ 18 | STDMETHODIMP GetInfo(TF_LANGBARITEMINFO* pInfo); 19 | STDMETHODIMP GetStatus(DWORD* pdwStatus); 20 | STDMETHODIMP Show(BOOL fShow); 21 | STDMETHODIMP GetTooltipString(BSTR* pbstrToolTip); 22 | 23 | /* ITfLangBarItemButton */ 24 | STDMETHODIMP OnClick(TfLBIClick click, POINT pt, const RECT* prcArea); 25 | STDMETHODIMP InitMenu(ITfMenu* pMenu); 26 | STDMETHODIMP OnMenuSelect(UINT wID); 27 | STDMETHODIMP GetIcon(HICON* phIcon); 28 | STDMETHODIMP GetText(BSTR* pbstrText); 29 | 30 | /* ITfSource */ 31 | STDMETHODIMP AdviseSink(REFIID riid, IUnknown* punk, DWORD* pdwCookie); 32 | STDMETHODIMP UnadviseSink(DWORD dwCookie); 33 | BOOL IsLangBarDisabled() { return (_status & TF_LBI_STATUS_DISABLED); } 34 | 35 | void UpdateWeaselStatus(weasel::Status stat); 36 | void SetLangbarStatus(DWORD dwStatus, BOOL fSet); 37 | 38 | private: 39 | GUID _guid; 40 | com_ptr _pTextService; 41 | com_ptr _pLangBarItemSink; 42 | LONG _cRef; /* COM Reference count */ 43 | DWORD _status; 44 | bool ascii_mode; 45 | weasel::UIStyle& _style; 46 | std::wstring _current_schema_zhung_icon; 47 | std::wstring _current_schema_ascii_icon; 48 | }; 49 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | InterlockedIncrement(&g_cRefDll); 10 | } 11 | 12 | void DllRelease() { 13 | InterlockedDecrement(&g_cRefDll); 14 | } 15 | 16 | class CClassFactory : public IClassFactory { 17 | public: 18 | // IUnknown methods 19 | STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject); 20 | STDMETHODIMP_(ULONG) AddRef(); 21 | STDMETHODIMP_(ULONG) Release(); 22 | 23 | // IClassFactory methods 24 | STDMETHODIMP CreateInstance(IUnknown* pUnkOuter, 25 | REFIID riid, 26 | void** ppvObject); 27 | STDMETHODIMP LockServer(BOOL fLock); 28 | }; 29 | 30 | STDAPI CClassFactory::QueryInterface(REFIID riid, void** ppvObject) { 31 | if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown)) { 32 | *ppvObject = this; 33 | DllAddRef(); 34 | return NOERROR; 35 | } 36 | *ppvObject = NULL; 37 | return E_NOINTERFACE; 38 | } 39 | 40 | STDAPI_(ULONG) CClassFactory::AddRef() { 41 | DllAddRef(); 42 | return g_cRefDll + 1; 43 | } 44 | 45 | STDAPI_(ULONG) CClassFactory::Release() { 46 | DllRelease(); 47 | return g_cRefDll + 1; 48 | } 49 | 50 | STDAPI CClassFactory::CreateInstance(IUnknown* pUnkOuter, 51 | REFIID riid, 52 | void** ppvObject) { 53 | WeaselTSF* pCase; 54 | HRESULT hr; 55 | if (ppvObject == NULL) 56 | return E_INVALIDARG; 57 | *ppvObject = NULL; 58 | if (pUnkOuter != NULL) 59 | return CLASS_E_NOAGGREGATION; 60 | if ((pCase = new WeaselTSF()) == NULL) 61 | return E_OUTOFMEMORY; 62 | hr = pCase->QueryInterface(riid, ppvObject); 63 | pCase->Release(); // caller still holds ref if hr == S_OK 64 | return hr; 65 | } 66 | 67 | STDAPI CClassFactory::LockServer(BOOL fLock) { 68 | if (fLock) 69 | DllAddRef(); 70 | else 71 | DllRelease(); 72 | return S_OK; 73 | } 74 | 75 | static CClassFactory* g_classFactory = NULL; 76 | 77 | static void BuildGlobalObjects() { 78 | g_classFactory = new CClassFactory(); 79 | } 80 | 81 | STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void** ppvObject) { 82 | if (g_classFactory == NULL) { 83 | EnterCriticalSection(&g_cs); 84 | if (g_classFactory == NULL) 85 | BuildGlobalObjects(); 86 | LeaveCriticalSection(&g_cs); 87 | } 88 | if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown)) { 89 | *ppvObject = g_classFactory; 90 | DllAddRef(); 91 | return NOERROR; 92 | } 93 | *ppvObject = NULL; 94 | return CLASS_E_CLASSNOTAVAILABLE; 95 | } 96 | 97 | STDAPI DllCanUnloadNow() { 98 | if (g_cRefDll >= 0) 99 | return S_FALSE; 100 | return S_OK; 101 | } 102 | 103 | STDAPI DllRegisterServer() { 104 | if (!RegisterServer() || !RegisterProfiles() || !RegisterCategories()) { 105 | DllUnregisterServer(); 106 | return E_FAIL; 107 | } 108 | return S_OK; 109 | } 110 | 111 | STDAPI DllUnregisterServer() { 112 | UnregisterProfiles(); 113 | UnregisterCategories(); 114 | UnregisterServer(); 115 | return S_OK; 116 | } 117 | -------------------------------------------------------------------------------- /WeaselTSF/ThreadMgrEventSink.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "WeaselTSF.h" 3 | 4 | STDAPI WeaselTSF::OnInitDocumentMgr(ITfDocumentMgr* pDocMgr) { 5 | return S_OK; 6 | } 7 | 8 | STDAPI WeaselTSF::OnUninitDocumentMgr(ITfDocumentMgr* pDocMgr) { 9 | return S_OK; 10 | } 11 | 12 | STDAPI WeaselTSF::OnSetFocus(ITfDocumentMgr* pDocMgrFocus, 13 | ITfDocumentMgr* pDocMgrPrevFocus) { 14 | _InitTextEditSink(pDocMgrFocus); 15 | 16 | com_ptr pCandidateListDocumentMgr; 17 | com_ptr pTfContext = _GetUIContextDocument(); 18 | if ((nullptr != pTfContext) && 19 | SUCCEEDED(pTfContext->GetDocumentMgr(&pCandidateListDocumentMgr))) { 20 | if (pCandidateListDocumentMgr != pDocMgrFocus) { 21 | _HideUI(); 22 | } else { 23 | _ShowUI(); 24 | } 25 | } 26 | 27 | return S_OK; 28 | } 29 | 30 | STDAPI WeaselTSF::OnPushContext(ITfContext* pContext) { 31 | return S_OK; 32 | } 33 | 34 | STDAPI WeaselTSF::OnPopContext(ITfContext* pContext) { 35 | return S_OK; 36 | } 37 | 38 | BOOL WeaselTSF::_InitThreadMgrEventSink() { 39 | ITfSource* pSource; 40 | if (_pThreadMgr->QueryInterface(IID_ITfSource, (void**)&pSource) != S_OK) 41 | return FALSE; 42 | if (pSource->AdviseSink(IID_ITfThreadMgrEventSink, 43 | (ITfThreadMgrEventSink*)this, 44 | &_dwThreadMgrEventSinkCookie) != S_OK) { 45 | _dwThreadMgrEventSinkCookie = TF_INVALID_COOKIE; 46 | pSource->Release(); 47 | return FALSE; 48 | } 49 | pSource->Release(); 50 | return TRUE; 51 | } 52 | 53 | void WeaselTSF::_UninitThreadMgrEventSink() { 54 | ITfSource* pSource; 55 | if (_dwThreadMgrEventSinkCookie == TF_INVALID_COOKIE) 56 | return; 57 | if (SUCCEEDED(_pThreadMgr->QueryInterface(IID_ITfSource, (void**)&pSource))) { 58 | pSource->UnadviseSink(_dwThreadMgrEventSinkCookie); 59 | pSource->Release(); 60 | } 61 | _dwThreadMgrEventSinkCookie = TF_INVALID_COOKIE; 62 | } 63 | -------------------------------------------------------------------------------- /WeaselTSF/WeaselTSF.def: -------------------------------------------------------------------------------- 1 | LIBRARY 2 | 3 | EXPORTS 4 | DllGetClassObject PRIVATE 5 | DllCanUnloadNow PRIVATE 6 | DllRegisterServer PRIVATE 7 | DllUnregisterServer PRIVATE -------------------------------------------------------------------------------- /WeaselTSF/WeaselTSF.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/WeaselTSF/WeaselTSF.rc -------------------------------------------------------------------------------- /WeaselTSF/dllmain.cpp: -------------------------------------------------------------------------------- 1 | // dllmain.cpp : Defines the entry point for the DLL application. 2 | #include "stdafx.h" 3 | #include "Globals.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #pragma comment(lib, "DbgHelp.lib") 10 | 11 | LONG WINAPI _UnhandledExceptionFilter(EXCEPTION_POINTERS* pExceptionPointers) { 12 | TCHAR szFileName[MAX_PATH]; 13 | TCHAR szAppName[MAX_PATH]; 14 | TCHAR szDllName[MAX_PATH]; 15 | DWORD dwProcessId = GetCurrentProcessId(); 16 | SYSTEMTIME st; 17 | TCHAR szDateTime[20]; // 用于存储日期时间字符串 18 | // 获取当前系统时间 19 | GetLocalTime(&st); 20 | // 格式化日期时间字符串 21 | _stprintf_s(szDateTime, 20, _T("%04d%02d%02d-%02d%02d%02d"), st.wYear, 22 | st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); 23 | // 获取应用程序名称 24 | GetModuleFileName(NULL, szAppName, MAX_PATH); 25 | // 从完整路径中提取应用程序名称 26 | TCHAR* pszBaseName = _tcsrchr(szAppName, '\\'); 27 | if (pszBaseName) { 28 | pszBaseName++; // 移过 '\\' 29 | } else { 30 | pszBaseName = szAppName; 31 | } 32 | // 获取当前dll模块的文件名 33 | GetModuleFileName(g_hInst, szDllName, MAX_PATH); 34 | TCHAR* pszDllBaseName = _tcsrchr(szDllName, '\\'); 35 | if (pszDllBaseName) { 36 | pszDllBaseName++; // 移过 '\\' 37 | } else { 38 | pszDllBaseName = szDllName; 39 | } 40 | WCHAR _path[MAX_PATH] = {0}; 41 | // default location 42 | ExpandEnvironmentStringsW(L"%TEMP%\\rime.weasel", _path, _countof(_path)); 43 | // 构造 dump 文件名:应用程序名称-DLL名称-时间.进程号.dmp 44 | _stprintf_s(szFileName, MAX_PATH, _T("%s\\%s-%s-%s.%lu.dmp"), _path, 45 | pszBaseName, pszDllBaseName, szDateTime, dwProcessId); 46 | HANDLE hDumpFile = CreateFile(szFileName, GENERIC_WRITE, 0, NULL, 47 | CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 48 | if (hDumpFile != INVALID_HANDLE_VALUE) { 49 | MINIDUMP_EXCEPTION_INFORMATION dumpInfo; 50 | dumpInfo.ExceptionPointers = pExceptionPointers; 51 | dumpInfo.ThreadId = GetCurrentThreadId(); 52 | dumpInfo.ClientPointers = TRUE; 53 | MiniDumpWriteDump(GetCurrentProcess(), dwProcessId, hDumpFile, 54 | MiniDumpNormal, &dumpInfo, NULL, NULL); 55 | CloseHandle(hDumpFile); 56 | } 57 | return EXCEPTION_EXECUTE_HANDLER; 58 | } 59 | 60 | BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID pvReserved) { 61 | switch (dwReason) { 62 | case DLL_PROCESS_ATTACH: 63 | g_hInst = hInstance; 64 | SetUnhandledExceptionFilter(_UnhandledExceptionFilter); 65 | if (!InitializeCriticalSectionAndSpinCount(&g_cs, 0)) 66 | return FALSE; 67 | break; 68 | case DLL_PROCESS_DETACH: 69 | DeleteCriticalSection(&g_cs); 70 | break; 71 | } 72 | return TRUE; 73 | } 74 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /WeaselTSF/xmake.lua: -------------------------------------------------------------------------------- 1 | target("WeaselTSF") 2 | set_kind("shared") 3 | add_files("./*.cpp", "WeaselTSF.def") 4 | add_rules("add_rcfiles", "use_weaselconstants") 5 | add_deps("WeaselIPC", "WeaselUI") 6 | local fname = '' 7 | if is_arch("x86") then 8 | fname = "weasel.dll" 9 | elseif is_arch("x64") then 10 | fname = "weaselx64.dll" 11 | elseif is_arch("arm") then 12 | fname = "weaselARM.dll" 13 | elseif is_arch("arm64") then 14 | fname = "weaselARM64.dll" 15 | end 16 | set_filename(fname) 17 | 18 | add_files("$(projectdir)/PerMonitorHighDPIAware.manifest") 19 | add_shflags("/DEBUG /OPT:REF /OPT:ICF") 20 | before_build(function(target) 21 | local target_dir = path.join(target:targetdir(), target:name()) 22 | if not os.exists(target_dir) then 23 | os.mkdir(target_dir) 24 | end 25 | target:set("targetdir", target_dir) 26 | end) 27 | 28 | after_build(function(target) 29 | os.cp(path.join(target:targetdir(), "weasel*.dll"), "$(projectdir)/output") 30 | os.cp(path.join(target:targetdir(), "weasel*.pdb"), "$(projectdir)/output") 31 | end) 32 | -------------------------------------------------------------------------------- /WeaselUI/FullScreenLayout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "StandardLayout.h" 4 | 5 | namespace weasel { 6 | class FullScreenLayout : public StandardLayout { 7 | public: 8 | FullScreenLayout(const UIStyle& style, 9 | const Context& context, 10 | const Status& status, 11 | const CRect& inputPos, 12 | Layout* layout, 13 | PDWR pDWR) 14 | : StandardLayout(style, context, status, pDWR), 15 | mr_inputPos(inputPos), 16 | m_layout(layout) {} 17 | virtual ~FullScreenLayout() { delete m_layout; } 18 | 19 | virtual void DoLayout(CDCHandle dc, PDWR pDWR = NULL); 20 | 21 | private: 22 | bool AdjustFontPoint(CDCHandle dc, 23 | const CRect& workArea, 24 | int& step, 25 | PDWR pDWR = NULL); 26 | 27 | const CRect& mr_inputPos; 28 | Layout* m_layout; 29 | }; 30 | }; // namespace weasel 31 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /WeaselUI/HorizontalLayout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "StandardLayout.h" 4 | 5 | namespace weasel { 6 | class HorizontalLayout : public StandardLayout { 7 | public: 8 | HorizontalLayout(const UIStyle& style, 9 | const Context& context, 10 | const Status& status, 11 | PDWR pDWR) 12 | : StandardLayout(style, context, status, pDWR) {} 13 | virtual void DoLayout(CDCHandle dc, PDWR pDWR = NULL); 14 | }; 15 | }; // namespace weasel 16 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /WeaselUI/VHorizontalLayout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "StandardLayout.h" 4 | 5 | namespace weasel { 6 | class VHorizontalLayout : public StandardLayout { 7 | public: 8 | VHorizontalLayout(const UIStyle& style, 9 | const Context& context, 10 | const Status& status, 11 | PDWR pDWR) 12 | : StandardLayout(style, context, status, pDWR) {} 13 | virtual void DoLayout(CDCHandle dc, PDWR pDWR = NULL); 14 | 15 | private: 16 | void DoLayoutWithWrap(CDCHandle dc, PDWR pDWR = NULL); 17 | }; 18 | }; // namespace weasel 19 | -------------------------------------------------------------------------------- /WeaselUI/VerticalLayout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "StandardLayout.h" 4 | 5 | namespace weasel { 6 | class VerticalLayout : public StandardLayout { 7 | public: 8 | VerticalLayout(const UIStyle& style, 9 | const Context& context, 10 | const Status& status, 11 | PDWR pDWR) 12 | : StandardLayout(style, context, status, pDWR) {} 13 | virtual void DoLayout(CDCHandle dc, PDWR pDWR = NULL); 14 | }; 15 | }; // namespace weasel 16 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /WeaselUI/xmake.lua: -------------------------------------------------------------------------------- 1 | target("WeaselUI") 2 | set_kind("static") 3 | add_files("./*.cpp") 4 | 5 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /arm64x_wrapper/dummy.c: -------------------------------------------------------------------------------- 1 | // This file is left blank on purpose to invoke the ARM64EC compiler and build ARM64EC thunks. -------------------------------------------------------------------------------- /clang-format.ps1: -------------------------------------------------------------------------------- 1 | param ( 2 | [switch]$n, 3 | [switch]$i 4 | ) 5 | 6 | $WEASEL_SOURCE_PATH = @("RimeWithWeasel", "WeaselDeployer", "WeaselIME", 7 | "WeaselIPC", "WeaselIPCServer", "WeaselServer", "WeaselSetup", 8 | "WeaselTSF", "WeaselUI", "include", "test") 9 | $excludePatterns = Get-Content .exclude_pattern.txt 10 | 11 | function ShouldExclude($filePath) { 12 | foreach ($pattern in $excludePatterns) { 13 | if ($filePath -like "*$pattern*") { 14 | return $true 15 | } 16 | } 17 | return $false 18 | } 19 | 20 | $filesToProcess = @() 21 | 22 | $WEASEL_SOURCE_PATH | ForEach-Object { 23 | $filesToProcess += Get-ChildItem -Path $_ -Recurse -Include *.cpp, *.h | 24 | Where-Object { $_.FullName -notmatch "include[\\/]wtl[\\/]" -and -not (ShouldExclude $_.FullName) } | 25 | ForEach-Object { $_.FullName } 26 | } 27 | 28 | if ($filesToProcess.Count -gt 0) { 29 | if ($n) { 30 | clang-format --verbose -i $filesToProcess 31 | Write-Host "Formatting done!" 32 | } elseif ($i) { 33 | clang-format --verbose -Werror --dry-run $filesToProcess 34 | if ($LASTEXITCODE -ne 0) { 35 | Write-Host "Please lint your code by './clang-format.ps1 -n'." 36 | exit 1 37 | } 38 | Write-Host "Format checking pass!" 39 | } 40 | } else { 41 | Write-Host "No files to process." 42 | } 43 | -------------------------------------------------------------------------------- /clang-format.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | WEASEL_SOURCE_PATH="RimeWithWeasel WeaselDeployer WeaselIME WeaselIPC WeaselIPCServer WeaselServer WeaselSetup WeaselTSF WeaselUI include test" 4 | 5 | # clang format options 6 | method="-i" 7 | 8 | while getopts "in" option; do 9 | case "${option}" in 10 | n) # format code 11 | find ${WEASEL_SOURCE_PATH} -name '*.cpp' -o -name '*.h' ! -path "include/wtl/*" | grep -wiv -f .exclude_pattern.txt | xargs clang-format --verbose -i 12 | ;; 13 | i) # dry run and changes formatting warnings to errors 14 | find ${WEASEL_SOURCE_PATH} -name '*.cpp' -o -name '*.h' ! -path "include/wtl/*" | grep -wiv -f .exclude_pattern.txt | xargs clang-format --verbose -Werror --dry-run || { echo Please lint your code by '"'"./clang-format.sh -n"'"'.; false; } 15 | ;; 16 | \?) # invalid option 17 | echo "invalid option, please use -i or -n." 18 | exit 1 19 | ;; 20 | esac 21 | done 22 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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_84_0 7 | 8 | rem OPTIONAL: architecture, Visual Studio version and platform toolset 9 | rem 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 | set RIME_PLUGINS=hchunhui/librime-lua lotem/librime-octagram rime/librime-predict 15 | rem OPTIONAL: path to additional build tools 16 | rem set DEVTOOLS_PATH=%ProgramFiles%\Git\cmd;%ProgramFiles%\Git\usr\bin;%ProgramFiles%\CMake\bin; 17 | -------------------------------------------------------------------------------- /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_84_0 7 | 8 | rem OPTIONAL: architecture, Visual Studio version and platform toolset 9 | rem 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 | set RIME_PLUGINS=hchunhui/librime-lua lotem/librime-octagram rime/librime-predict 15 | rem OPTIONAL: path to additional build tools 16 | rem set DEVTOOLS_PATH=%ProgramFiles%\Git\cmd;%ProgramFiles%\Git\usr\bin;%ProgramFiles%\CMake\bin; 17 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /include/ResponseParser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace weasel { 9 | class Deserializer; 10 | 11 | // 解析server回應文本 12 | struct ResponseParser { 13 | std::map > deserializers; 14 | 15 | std::wstring* p_commit; 16 | Context* p_context; 17 | Status* p_status; 18 | Config* p_config; 19 | UIStyle* p_style; 20 | 21 | ResponseParser(std::wstring* commit, 22 | Context* context = 0, 23 | Status* status = 0, 24 | Config* config = 0, 25 | UIStyle* style = 0); 26 | 27 | // 重載函數調用運算符, 以扮做ResponseHandler 28 | bool operator()(LPWSTR buffer, UINT length); 29 | 30 | // 處理一行回應文本 31 | void Feed(const std::wstring& line); 32 | }; 33 | 34 | } // namespace weasel 35 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /include/VersionHelpers.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef NTSTATUS 4 | typedef __success(return >= 0) LONG NTSTATUS; 5 | #endif 6 | 7 | // Visual Studio comes with Windows SDK 10, VersionHelpers.h came with Windows 8.1 SDK, while windows sdk 8.1 came with VS2013 _MSC_VER=1800 8 | #include 9 | 10 | inline BOOL GetVersionEx2(LPOSVERSIONINFOW lpVersionInformation) 11 | { 12 | HMODULE hNtDll = GetModuleHandleW(L"NTDLL"); // 获取ntdll.dll的句柄 13 | typedef NTSTATUS(NTAPI* tRtlGetVersion)(PRTL_OSVERSIONINFOW povi); // RtlGetVersion的原型 14 | tRtlGetVersion pRtlGetVersion = NULL; 15 | if (hNtDll) 16 | { 17 | pRtlGetVersion = (tRtlGetVersion)GetProcAddress(hNtDll, "RtlGetVersion"); // 获取RtlGetVersion地址 18 | } 19 | if (pRtlGetVersion) 20 | { 21 | return pRtlGetVersion((PRTL_OSVERSIONINFOW)lpVersionInformation) >= 0; // 调用RtlGetVersion 22 | } 23 | return FALSE; 24 | } 25 | 26 | static inline BOOL IsWinVersionGreaterThan(DWORD dwMajorVersion, DWORD dwMinorVersion) 27 | { 28 | OSVERSIONINFOEXW ovi = { sizeof ovi }; 29 | GetVersionEx2((LPOSVERSIONINFOW)&ovi); 30 | if ((ovi.dwMajorVersion == dwMajorVersion && ovi.dwMinorVersion >= dwMinorVersion) || ovi.dwMajorVersion > dwMajorVersion) 31 | return true; 32 | else 33 | return false; 34 | } 35 | 36 | static inline BOOL IsBlurAvailable() 37 | { 38 | OSVERSIONINFOEXW ovi = { sizeof ovi }; 39 | GetVersionEx2((LPOSVERSIONINFOW)&ovi); 40 | return (ovi.dwMajorVersion >= 10 && ovi.dwBuildNumber <= 22000); 41 | } 42 | 43 | // Use WinBlue for Windows 8.1 44 | #define IsWindowsBlueOrLaterEx() IsWinVersionGreaterThan(6, 3) 45 | #define IsWindows10OrGreaterEx() IsWinVersionGreaterThan(10, 0) 46 | -------------------------------------------------------------------------------- /include/WeaselConstants.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WEASEL_CODE_NAME "Weasel" 4 | #define WEASEL_REG_KEY L"Software\\Rime\\Weasel" 5 | #define RIME_REG_KEY L"Software\\Rime" 6 | 7 | #define STRINGIZE(x) #x 8 | #define VERSION_STR(x) STRINGIZE(x) 9 | #define WEASEL_VERSION VERSION_STR(VERSION_MAJOR.VERSION_MINOR.VERSION_PATCH) 10 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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) { 15 | return *this; 16 | } 17 | }; 18 | 19 | // to avoid compiler warnings 20 | class Voidify { 21 | public: 22 | Voidify() {} 23 | void operator&(VoidLogger&) {} 24 | }; 25 | 26 | } // namespace rime 27 | 28 | #define RIME_NO_LOG \ 29 | true ? (void)0 : rime::Voidify() & rime::VoidLogger().stream() 30 | 31 | #define LOG(severity) RIME_NO_LOG 32 | #define VLOG(verboselevel) RIME_NO_LOG 33 | #define LOG_IF(severity, condition) RIME_NO_LOG 34 | #define LOG_EVERY_N(severity, n) RIME_NO_LOG 35 | #define LOG_IF_EVERY_N(severity, condition, n) RIME_NO_LOG 36 | #define LOG_ASSERT(condition) RIME_NO_LOG 37 | 38 | #define RIME_NO_CHECK (void)0 39 | 40 | #define CHECK(condition) RIME_NO_CHECK 41 | #define CHECK_EQ(val1, val2) RIME_NO_CHECK 42 | #define CHECK_NE(val1, val2) RIME_NO_CHECK 43 | #define CHECK_LE(val1, val2) RIME_NO_CHECK 44 | #define CHECK_LT(val1, val2) RIME_NO_CHECK 45 | #define CHECK_GE(val1, val2) RIME_NO_CHECK 46 | #define CHECK_GT(val1, val2) RIME_NO_CHECK 47 | #define CHECK_NOTNULL(val) RIME_NO_CHECK 48 | #define CHECK_STREQ(str1, str2) RIME_NO_CHECK 49 | #define CHECK_STRCASEEQ(str1, str2) RIME_NO_CHECK 50 | #define CHECK_STRNE(str1, str2) RIME_NO_CHECK 51 | #define CHECK_STRCASENE(str1, str2) RIME_NO_CHECK 52 | 53 | #define DLOG(severity) LOG(severity) 54 | #define DVLOG(verboselevel) VLOG(verboselevel) 55 | #define DLOG_IF(severity, condition) LOG_IF(severity, condition) 56 | #define DLOG_EVERY_N(severity, n) LOG_EVERY_N(severity, n) 57 | #define DLOG_IF_EVERY_N(severity, condition, n) \ 58 | LOG_IF_EVERY_N(severity, condition, n) 59 | #define DLOG_ASSERT(condition) LOG_ASSERT(condition) 60 | 61 | #define DCHECK(condition) CHECK(condition) 62 | #define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2) 63 | #define DCHECK_NE(val1, val2) CHECK_NE(val1, val2) 64 | #define DCHECK_LE(val1, val2) CHECK_LE(val1, val2) 65 | #define DCHECK_LT(val1, val2) CHECK_LT(val1, val2) 66 | #define DCHECK_GE(val1, val2) CHECK_GE(val1, val2) 67 | #define DCHECK_GT(val1, val2) CHECK_GT(val1, val2) 68 | #define DCHECK_NOTNULL(val) CHECK_NOTNULL(val) 69 | #define DCHECK_STREQ(str1, str2) CHECK_STREQ(str1, str2) 70 | #define DCHECK_STRCASEEQ(str1, str2) CHECK_STRCASEEQ(str1, str2) 71 | #define DCHECK_STRNE(str1, str2) CHECK_STRNE(str1, str2) 72 | #define DCHECK_STRCASENE(str1, str2) CHECK_STRCASENE(str1, str2) 73 | 74 | #endif // RIME_NO_LOGGING_H_ 75 | -------------------------------------------------------------------------------- /include/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by WeaselTSF.rc 4 | // 5 | #define IDI_WEASEL 100 6 | #define IDI_EN 101 7 | #define IDI_ZH 102 8 | #define IDI_RELOAD 103 9 | #define IDR_MENU_POPUP 105 10 | #define IDI_FULL_SHAPE 106 11 | #define IDI_HALF_SHAPE 107 12 | #define IDR_MENU_POPUP_HANT 108 13 | #define IDR_MENU_POPUP_HANS 109 14 | #define IDS_STR_UNDER_MAINTENANCE 302 15 | #define ID_WEASELTRAY_QUIT 40001 16 | #define ID_WEASELTRAY_DEPLOY 40002 17 | #define ID_WEASELTRAY_CHECKUPDATE 40003 18 | #define ID_WEASELTRAY_FORUM 40004 19 | #define ID_WEASELTRAY_HOMEPAGE 40005 20 | #define ID_WEASELTRAY_INSTALLDIR 40006 21 | #define ID_WEASELTRAY_USERCONFIG 40007 22 | #define ID_WEASELTRAY_SETTINGS 40008 23 | #define ID_WEASELTRAY_WIKI 40009 24 | #define ID_WEASELTRAY_DICT_MANAGEMENT 40010 25 | #define ID_WEASELTRAY_SYNC 40012 26 | #define ID_WEASELTRAY_ENABLE_ASCII 40013 27 | #define ID_WEASELTRAY_DISABLE_ASCII 40014 28 | #define ID_WEASELTRAY_RERUN_SERVICE 40015 29 | #define ID_WEASELTRAY_LOGDIR 40016 30 | 31 | // Next default values for new objects 32 | // 33 | #ifdef APSTUDIO_INVOKED 34 | #ifndef APSTUDIO_READONLY_SYMBOLS 35 | #define _APS_NEXT_RESOURCE_VALUE 104 36 | #define _APS_NEXT_COMMAND_VALUE 40001 37 | #define _APS_NEXT_CONTROL_VALUE 1001 38 | #define _APS_NEXT_SYMED_VALUE 101 39 | #endif 40 | #endif 41 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /install-clang-format.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | if "%PROCESSOR_ARCHITECTURE%"=="AMD64" ( 4 | rem 64 bit system 5 | rem powershell -Command "(New-Object Net.WebClient).DownloadFile('https://github.com/llvm/llvm-project/releases/download/llvmorg-18.1.6/LLVM-18.1.6-win64.exe', 'LLVM-18.1.6-win64.exe')" 6 | rem LLVM-18.1.6-win64.exe /S 7 | rem or maybe 8 | rem output/7z.exe e LLVM-18.1.6-win64.exe bin/clang-format.exe -o. 9 | rem rm LLVM-18.1.6-win64.exe 10 | ) else ( 11 | rem 32 bit system 12 | rem powershell -Command "(New-Object Net.WebClient).DownloadFile('https://github.com/llvm/llvm-project/releases/download/llvmorg-18.1.6/LLVM-18.1.6-win32.exe', 'LLVM-18.1.6-win32.exe')" 13 | rem LLVM-18.1.6-win32.exe /S 14 | rem or maybe 15 | rem output/7z.exe e LLVM-18.1.6-win32.exe bin/clang-format.exe -o. 16 | rem rm LLVM-18.1.6-win32.exe 17 | ) 18 | pause 19 | -------------------------------------------------------------------------------- /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://archives.boost.io/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /lib/WinSparkle.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/lib/WinSparkle.lib -------------------------------------------------------------------------------- /lib64/WinSparkle.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/lib64/WinSparkle.lib -------------------------------------------------------------------------------- /msvc-latest.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | rem To be used on MS-Windows for Visual C++ 2017 or later. 3 | rem See INSTALLpc.txt for information. 4 | rem 5 | rem Usage: 6 | rem For x86 builds run this with "x86" option: 7 | rem msvc-latest x86 8 | rem For x64 builds run this with "x86_amd64" option or "x64" option: 9 | rem msvc-latest x86_amd64 10 | rem msvc-latest x64 11 | rem 12 | rem Optional environment variables: 13 | rem VSWHERE: 14 | rem Full path to vswhere.exe. 15 | rem VSVEROPT: 16 | rem Option to search specific version of Visual Studio. 17 | rem Default: -latest 18 | rem To search VS2017: 19 | rem set "VSVEROPT=-version [15.0^,16.0^)" 20 | rem To search VS2019: 21 | rem set "VSVEROPT=-version [16.0^,17.0^)" 22 | rem To search VS2022: 23 | rem set "VSVEROPT=-version [17.0^,18.0^)" 24 | 25 | if "%VSWHERE%"=="" ( 26 | set "VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" 27 | set VSWHERE_SET=yes 28 | ) 29 | if not exist "%VSWHERE%" ( 30 | echo Error: vswhere not found. 31 | set VSWHERE= 32 | set VSWHERE_SET= 33 | exit /b 1 34 | ) 35 | 36 | if "%VSVEROPT%"=="" ( 37 | set VSVEROPT=-latest 38 | set VSVEROPT_SET=yes 39 | ) 40 | 41 | rem Search Visual Studio Community, Professional or above. 42 | for /f "usebackq tokens=*" %%i in (`"%VSWHERE%" %VSVEROPT% -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do ( 43 | set InstallDir=%%i 44 | ) 45 | if exist "%InstallDir%\VC\Auxiliary\Build\vcvarsall.bat" ( 46 | call "%InstallDir%\VC\Auxiliary\Build\vcvarsall.bat" %* 47 | goto done 48 | ) 49 | 50 | rem Search Visual Studio 2017 Express. 51 | rem (Visual Studio 2017 Express uses different component IDs.) 52 | for /f "usebackq tokens=*" %%i in (`"%VSWHERE%" %VSVEROPT% -products Microsoft.VisualStudio.Product.WDExpress -property installationPath`) do ( 53 | set InstallDir=%%i 54 | ) 55 | if exist "%InstallDir%\VC\Auxiliary\Build\vcvarsall.bat" ( 56 | call "%InstallDir%\VC\Auxiliary\Build\vcvarsall.bat" %* 57 | ) else ( 58 | echo Error: vcvarsall.bat not found. 59 | rem Set ERRORLEVEL to 1. 60 | call 61 | ) 62 | 63 | :done 64 | if "%VSWHERE_SET%"=="yes" ( 65 | set VSWHERE= 66 | set VSWHERE_SET= 67 | ) 68 | if "%VSVEROPT_SET%"=="yes" ( 69 | set VSVEROPT= 70 | set VSVEROPT_SET= 71 | ) 72 | set InstallDir= -------------------------------------------------------------------------------- /output/7z.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/7z.dll -------------------------------------------------------------------------------- /output/7z.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/7z.exe -------------------------------------------------------------------------------- /output/COPYING-curl.txt: -------------------------------------------------------------------------------- 1 | COPYRIGHT AND PERMISSION NOTICE 2 | 3 | Copyright (c) 1996 - 2024, 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 | -------------------------------------------------------------------------------- /output/Win32/WinSparkle.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/Win32/WinSparkle.dll -------------------------------------------------------------------------------- /output/WinSparkle.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/WinSparkle.dll -------------------------------------------------------------------------------- /output/archives/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/archives/.placeholder -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /output/curl.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/curl.exe -------------------------------------------------------------------------------- /output/data/preview/color_scheme_android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_android.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_aqua.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_aqua.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_azure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_azure.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_brasil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_brasil.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_brisk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_brisk.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_cool_breeze.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_cool_breeze.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_dark_temple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_dark_temple.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_doraemon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_doraemon.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_dota_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_dota_2.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_espagna.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_espagna.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_flypy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_flypy.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_gholabok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_gholabok.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_google.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_google_plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_google_plus.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_ink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_ink.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_kuma_shuzboz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_kuma_shuzboz.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_kuon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_kuon.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_lost_temple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_lost_temple.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_luna.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_luna.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_macau.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_macau.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_metroblue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_metroblue.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_modern_warfare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_modern_warfare.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_nba.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_nba.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_ps4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_ps4.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_psionics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_psionics.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_skype.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_skype.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_smurfs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_smurfs.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_so_young.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_so_young.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_solarized_rock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_solarized_rock.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_starcraft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_starcraft.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_starcraft_ii.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_starcraft_ii.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_steam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_steam.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_tintin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_tintin.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_wii.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_wii.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_xbox_silver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_xbox_silver.png -------------------------------------------------------------------------------- /output/data/preview/color_scheme_youtube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/output/data/preview/color_scheme_youtube.png -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /output/rime-install-config.bat: -------------------------------------------------------------------------------- 1 | rem Location of download cache 2 | rem set download_cache_dir=%TEMP% 3 | 4 | rem Do not update packages; only download missing files. 5 | rem CAUTION: may suffer from incomplete downloads. 6 | rem set no_update=1 7 | 8 | rem Rime configuration manager and downloaded packages 9 | set plum_dir=%APPDATA%\plum 10 | 11 | rem Location of Rime user directory 12 | rem set rime_dir=%APPDATA%\Rime 13 | 14 | set key=HKEY_CURRENT_USER\SOFTWARE\Rime\Weasel 15 | set name=RimeUserDir 16 | for /f "tokens=2*" %%a in ('reg query "%key%" /v "%name%"') do set rime_dir=%%b 17 | 18 | rem Disable /plum/ bash script; use batch installer only. 19 | rem set use_plum=0 20 | 21 | rem set git version as 2.45.1 22 | set git_version=2.45.1 23 | -------------------------------------------------------------------------------- /output/start_service.bat: -------------------------------------------------------------------------------- 1 | cd "%~dp0" 2 | start "" WeaselServer.exe -------------------------------------------------------------------------------- /output/stop_service.bat: -------------------------------------------------------------------------------- 1 | cd "%~dp0" 2 | weaselserver.exe /q 3 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /resource/en.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/resource/en.ico -------------------------------------------------------------------------------- /resource/full.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/resource/full.ico -------------------------------------------------------------------------------- /resource/half.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/resource/half.ico -------------------------------------------------------------------------------- /resource/reload.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/resource/reload.ico -------------------------------------------------------------------------------- /resource/weasel.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/resource/weasel.ico -------------------------------------------------------------------------------- /resource/zh.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fxliang/weasel/98922860d7ab3af34f9ee6243edfd9e3b12b388c/resource/zh.ico -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | WCHAR resp[] = L"action=noop\n"; 11 | DWORD len = wcslen(resp); 12 | std::wstring commit; 13 | weasel::Context ctx; 14 | weasel::Status status; 15 | weasel::ResponseParser parser(&commit, &ctx, &status); 16 | parser(resp, len); 17 | BOOST_TEST(commit.empty()); 18 | BOOST_TEST(ctx.empty()); 19 | } 20 | 21 | void test_2() { 22 | WCHAR resp[] = 23 | L"action=commit\n" 24 | L"commit=教這句話上屏=3.14\n"; 25 | DWORD len = wcslen(resp); 26 | std::wstring commit; 27 | weasel::Context ctx; 28 | weasel::Status status; 29 | ctx.aux.str = L"從前的值"; 30 | weasel::ResponseParser parser(&commit, &ctx, &status); 31 | parser(resp, len); 32 | BOOST_TEST(commit == L"教這句話上屏=3.14"); 33 | BOOST_TEST(ctx.preedit.empty()); 34 | BOOST_TEST(ctx.aux.str == L"從前的值"); 35 | BOOST_TEST(ctx.cinfo.candies.empty()); 36 | } 37 | 38 | void test_3() { 39 | WCHAR resp[] = 40 | L"action=ctx\n" 41 | L"ctx.preedit=寫作串=3.14\n" 42 | L"ctx.aux=sie'zuoh'chuan=3.14\n"; 43 | DWORD len = wcslen(resp); 44 | std::wstring commit; 45 | weasel::Context ctx; 46 | weasel::Status status; 47 | weasel::ResponseParser parser(&commit, &ctx, &status); 48 | parser(resp, len); 49 | BOOST_TEST(commit.empty()); 50 | BOOST_TEST(ctx.preedit.str == L"寫作串=3.14"); 51 | BOOST_TEST(ctx.preedit.attributes.empty()); 52 | BOOST_TEST(ctx.aux.str == L"sie'zuoh'chuan=3.14"); 53 | } 54 | 55 | void test_4() { 56 | WCHAR resp[] = 57 | L"action=commit,ctx\n" 58 | L"ctx.preedit=候選乙=3.14\n" 59 | L"ctx.preedit.cursor=0,3\n" 60 | L"ctx.cand.length=2\n" 61 | L"ctx.cand.0=候選甲\n" 62 | L"ctx.cand.1=候選乙\n" 63 | L"ctx.cand.cursor=1\n" 64 | L"ctx.cand.page=0/1\n"; 65 | DWORD len = wcslen(resp); 66 | std::wstring commit; 67 | weasel::Context ctx; 68 | weasel::Status status; 69 | weasel::ResponseParser parser(&commit, &ctx, &status); 70 | parser(resp, len); 71 | BOOST_TEST(commit.empty()); 72 | BOOST_TEST(ctx.preedit.str == L"候選乙=3.14"); 73 | BOOST_ASSERT(1 == ctx.preedit.attributes.size()); 74 | weasel::TextAttribute attr0 = ctx.preedit.attributes[0]; 75 | BOOST_TEST_EQ(weasel::HIGHLIGHTED, attr0.type); 76 | BOOST_TEST_EQ(0, attr0.range.start); 77 | BOOST_TEST_EQ(3, attr0.range.end); 78 | BOOST_TEST(ctx.aux.empty()); 79 | weasel::CandidateInfo& c = ctx.cinfo; 80 | BOOST_ASSERT(2 == c.candies.size()); 81 | BOOST_TEST(c.candies[0].str == L"候選甲"); 82 | BOOST_TEST(c.candies[1].str == L"候選乙"); 83 | BOOST_TEST_EQ(1, c.highlighted); 84 | BOOST_TEST_EQ(0, c.currentPage); 85 | BOOST_TEST_EQ(1, c.totalPages); 86 | } 87 | 88 | int _tmain(int argc, _TCHAR* argv[]) { 89 | test_1(); 90 | test_2(); 91 | test_3(); 92 | test_4(); 93 | 94 | system("pause"); 95 | return boost::report_errors(); 96 | } 97 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /test/TestResponseParser/xmake.lua: -------------------------------------------------------------------------------- 1 | target("TestResponseParser") 2 | set_kind("binary") 3 | add_files("./*.cpp") 4 | add_deps("WeaselIPC", "WeaselIPCServer") 5 | add_rules("subcmd") 6 | before_build(function(target) 7 | local target_dir = path.join(target:targetdir(), target:name()) 8 | if not os.exists(target_dir) then 9 | os.mkdir(target_dir) 10 | end 11 | target:set("targetdir", target_dir) 12 | end) 13 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/TestWeaselIPC/xmake.lua: -------------------------------------------------------------------------------- 1 | target("TestWeaselIPC") 2 | set_kind("binary") 3 | add_files("./*.cpp") 4 | add_deps("WeaselIPC", "WeaselIPCServer") 5 | add_rules("subcmd") 6 | before_build(function(target) 7 | local target_dir = path.join(target:targetdir(), target:name()) 8 | if not os.exists(target_dir) then 9 | os.mkdir(target_dir) 10 | end 11 | target:set("targetdir", target_dir) 12 | end) 13 | -------------------------------------------------------------------------------- /update/appcast.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 【小狼毫】輸入法更新頻道 5 | http://rime.github.io/release/weasel/appcast.xml 6 | 小狼毫 Appcast 更新頻道 7 | zh 8 | 9 | 小狼毫 0.17.0 10 | http://rime.github.io/release/weasel/ 11 | Sat, 17 May 2025 22:29:58 +0800 12 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /update/testing-appcast.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 【小狼毫】輸入法測試頻道 5 | http://rime.github.io/testing/weasel/appcast.xml 6 | 小狼毫測試版 Appcast 更新頻道 7 | zh 8 | 9 | 小狼毫 0.17.0 10 | http://rime.github.io/release/weasel/ 11 | Sat, 17 May 2025 22:29:58 +0800 12 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /weasel.props.template: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $BOOST_ROOT 5 | $PLATFORM_TOOLSET 6 | $VERSION_MAJOR 7 | $VERSION_MINOR 8 | $VERSION_PATCH 9 | $PRODUCT_VERSION 10 | $FILE_VERSION 11 | 12 | 13 | 14 | $(BOOST_ROOT) 15 | true 16 | 17 | 18 | $(PLATFORM_TOOLSET) 19 | true 20 | 21 | 22 | 23 | 24 | $(PreprocessorDefinitions);VERSION_MAJOR=$(VERSION_MAJOR);VERSION_MINOR=$(VERSION_MINOR);VERSION_PATCH=$(VERSION_PATCH); 25 | /utf-8 26 | 27 | 28 | $(PreprocessorDefinitions);VERSION_MAJOR=$(VERSION_MAJOR);VERSION_MINOR=$(VERSION_MINOR);VERSION_PATCH=$(VERSION_PATCH);PRODUCT_VERSION=$(PRODUCT_VERSION);FILE_VERSION=$(FILE_VERSION); 29 | 30 | 31 | 32 | --------------------------------------------------------------------------------