The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .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
    ├── 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
    ├── 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
├── 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-latest
 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.vs2022.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_<version>`.
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 | <?xml version="1.0" encoding="utf-8"?>
 2 | <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 3 |   <ItemGroup>
 4 |     <Filter Include="Source Files">
 5 |       <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
 6 |       <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
 7 |     </Filter>
 8 |     <Filter Include="Header Files">
 9 |       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
10 |       <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
11 |     </Filter>
12 |     <Filter Include="Resource Files">
13 |       <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
14 |       <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
15 |     </Filter>
16 |   </ItemGroup>
17 |   <ItemGroup>
18 |     <ClCompile Include="RimeWithWeasel.cpp">
19 |       <Filter>Source Files</Filter>
20 |     </ClCompile>
21 |     <ClCompile Include="stdafx.cpp">
22 |       <Filter>Source Files</Filter>
23 |     </ClCompile>
24 |     <ClCompile Include="WeaselUtility.cpp">
25 |       <Filter>Source Files</Filter>
26 |     </ClCompile>
27 |   </ItemGroup>
28 |   <ItemGroup>
29 |     <ClInclude Include="..\include\RimeWithWeasel.h">
30 |       <Filter>Header Files</Filter>
31 |     </ClInclude>
32 |     <ClInclude Include="stdafx.h">
33 |       <Filter>Header Files</Filter>
34 |     </ClInclude>
35 |     <ClInclude Include="targetver.h">
36 |       <Filter>Header Files</Filter>
37 |     </ClInclude>
38 |     <ClInclude Include="..\include\WeaselUtility.h">
39 |       <Filter>Header Files</Filter>
40 |     </ClInclude>
41 |   </ItemGroup>
42 |   <ItemGroup>
43 |     <None Include="ReadMe.txt" />
44 |   </ItemGroup>
45 | </Project>


--------------------------------------------------------------------------------
/RimeWithWeasel/WeaselUtility.cpp:
--------------------------------------------------------------------------------
 1 | #include "stdafx.h"
 2 | #include <filesystem>
 3 | #include <string>
 4 | #include <WeaselUtility.h>
 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 <windows.h>
12 | 
13 | #pragma warning(disable : 4819)
14 | 
15 | #include <boost/interprocess/streams/bufferstream.hpp>
16 | #include <boost/archive/text_woarchive.hpp>
17 | #include <boost/archive/text_oarchive.hpp>
18 | #include <boost/thread.hpp>
19 | 
20 | #pragma warning(default : 4819)
21 | #include <algorithm>
22 | #include <list>
23 | #include <set>
24 | #include <string>
25 | #include <sstream>
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 <WinSDKVer.h>
 9 | 
10 | #define _WIN32_WINNT _WIN32_WINNT_WINBLUE // Specifies that the minimum required platform is Windows 8.1.
11 | 
12 | #include <SDKDDKVer.h>
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 | 
 5 | #include <rime_levers_api.h>
 6 | 
 7 | class DictManagementDialog : public CDialogImpl<DictManagementDialog> {
 8 |  public:
 9 |   enum { IDD = IDD_DICT_MANAGEMENT };
10 | 
11 |   DictManagementDialog();
12 |   ~DictManagementDialog();
13 | 
14 |  protected:
15 |   BEGIN_MSG_MAP(DictManagementDialog)
16 |   MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
17 |   MESSAGE_HANDLER(WM_CLOSE, OnClose)
18 |   COMMAND_ID_HANDLER(IDC_BACKUP, OnBackup)
19 |   COMMAND_ID_HANDLER(IDC_RESTORE, OnRestore)
20 |   COMMAND_ID_HANDLER(IDC_EXPORT, OnExport)
21 |   COMMAND_ID_HANDLER(IDC_IMPORT, OnImport)
22 |   COMMAND_HANDLER(IDC_USER_DICT_LIST, LBN_SELCHANGE, OnUserDictListSelChange)
23 |   END_MSG_MAP()
24 | 
25 |   LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&);
26 |   LRESULT OnClose(UINT, WPARAM, LPARAM, BOOL&);
27 |   LRESULT OnBackup(WORD, WORD code, HWND, BOOL&);
28 |   LRESULT OnRestore(WORD, WORD code, HWND, BOOL&);
29 |   LRESULT OnExport(WORD, WORD code, HWND, BOOL&);
30 |   LRESULT OnImport(WORD, WORD code, HWND, BOOL&);
31 |   LRESULT OnUserDictListSelChange(WORD, WORD, HWND, BOOL&);
32 | 
33 |   void Populate();
34 | 
35 |   CListBox user_dict_list_;
36 |   CButton backup_;
37 |   CButton restore_;
38 |   CButton export_;
39 |   CButton import_;
40 | 
41 |   RimeLeversApi* api_;
42 | };
43 | 


--------------------------------------------------------------------------------
/WeaselDeployer/SwitcherSettingsDialog.h:
--------------------------------------------------------------------------------
 1 | #pragma once
 2 | 
 3 | #include "resource.h"
 4 | #include <rime_levers_api.h>
 5 | 
 6 | class SwitcherSettingsDialog : public CDialogImpl<SwitcherSettingsDialog> {
 7 |  public:
 8 |   enum { IDD = IDD_SWITCHER_SETTING };
 9 | 
10 |   SwitcherSettingsDialog(RimeSwitcherSettings* settings);
11 |   ~SwitcherSettingsDialog();
12 | 
13 |  protected:
14 |   BEGIN_MSG_MAP(SwitcherSettingsDialog)
15 |   MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
16 |   MESSAGE_HANDLER(WM_CLOSE, OnClose)
17 |   COMMAND_HANDLER(IDC_GET_SCHEMATA, BN_CLICKED, OnGetSchemata)
18 |   COMMAND_ID_HANDLER(IDOK, OnOK)
19 |   NOTIFY_HANDLER(IDC_SCHEMA_LIST, LVN_ITEMCHANGED, OnSchemaListItemChanged)
20 |   END_MSG_MAP()
21 | 
22 |   LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&);
23 |   LRESULT OnClose(UINT, WPARAM, LPARAM, BOOL&);
24 |   LRESULT OnGetSchemata(WORD, WORD, HWND, BOOL&);
25 |   LRESULT OnOK(WORD, WORD, HWND, BOOL&);
26 |   LRESULT OnSchemaListItemChanged(int, LPNMHDR, BOOL&);
27 | 
28 |   void Populate();
29 |   void ShowDetails(RimeSchemaInfo* info);
30 | 
31 |   RimeLeversApi* api_;
32 |   RimeSwitcherSettings* settings_;
33 |   bool loaded_;
34 |   bool modified_;
35 | 
36 |   CCheckListViewCtrl schema_list_;
37 |   CStatic description_;
38 |   CEdit hotkeys_;
39 |   CButton get_schemata_;
40 | };
41 | 


--------------------------------------------------------------------------------
/WeaselDeployer/UIStyleSettings.cpp:
--------------------------------------------------------------------------------
 1 | #include "stdafx.h"
 2 | #include <WeaselUtility.h>
 3 | #include "UIStyleSettings.h"
 4 | 
 5 | UIStyleSettings::UIStyleSettings() {
 6 |   api_ = (RimeLeversApi*)rime_get_api()->find_module("levers")->get_api();
 7 |   settings_ = api_->custom_settings_init("weasel", "Weasel::UIStyleSettings");
 8 | }
 9 | 
10 | bool UIStyleSettings::GetPresetColorSchemes(
11 |     std::vector<ColorSchemeInfo>* result) {
12 |   if (!result)
13 |     return false;
14 |   result->clear();
15 |   RimeConfig config = {0};
16 |   api_->settings_get_config(settings_, &config);
17 |   RimeApi* rime = rime_get_api();
18 |   RimeConfigIterator preset = {0};
19 |   if (!rime->config_begin_map(&preset, &config, "preset_color_schemes")) {
20 |     return false;
21 |   }
22 |   while (rime->config_next(&preset)) {
23 |     std::string name_key(preset.path);
24 |     name_key += "/name";
25 |     const char* name = rime->config_get_cstring(&config, name_key.c_str());
26 |     std::string author_key(preset.path);
27 |     author_key += "/author";
28 |     const char* author = rime->config_get_cstring(&config, author_key.c_str());
29 |     if (!name)
30 |       continue;
31 |     ColorSchemeInfo info;
32 |     info.color_scheme_id = preset.key;
33 |     info.name = name;
34 |     if (author)
35 |       info.author = author;
36 |     result->push_back(info);
37 |   }
38 |   return true;
39 | }
40 | 
41 | // check if a file exists
42 | static inline bool IfFileExist(std::string filename) {
43 |   DWORD dwAttrib = GetFileAttributes(acptow(filename).c_str());
44 |   return (INVALID_FILE_ATTRIBUTES != dwAttrib &&
45 |           0 == (dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
46 | }
47 | 
48 | // get preview image from user dir first, then shared_dir
49 | std::string UIStyleSettings::GetColorSchemePreview(
50 |     const std::string& color_scheme_id) {
51 |   std::string shared_dir = rime_get_api()->get_shared_data_dir();
52 |   std::string user_dir = rime_get_api()->get_user_data_dir();
53 |   std::string filename =
54 |       user_dir + "\\preview\\color_scheme_" + color_scheme_id + ".png";
55 |   if (IfFileExist(filename))
56 |     return filename;
57 |   else
58 |     return (shared_dir + "\\preview\\color_scheme_" + color_scheme_id + ".png");
59 | }
60 | 
61 | std::string UIStyleSettings::GetActiveColorScheme() {
62 |   RimeConfig config = {0};
63 |   api_->settings_get_config(settings_, &config);
64 |   const char* value =
65 |       rime_get_api()->config_get_cstring(&config, "style/color_scheme");
66 |   if (!value)
67 |     return std::string();
68 |   return std::string(value);
69 | }
70 | 
71 | bool UIStyleSettings::SelectColorScheme(const std::string& color_scheme_id) {
72 |   api_->customize_string(settings_, "style/color_scheme",
73 |                          color_scheme_id.c_str());
74 |   return true;
75 | }
76 | 


--------------------------------------------------------------------------------
/WeaselDeployer/UIStyleSettings.h:
--------------------------------------------------------------------------------
 1 | #pragma once
 2 | 
 3 | #include <string>
 4 | #include <vector>
 5 | #include <rime_levers_api.h>
 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<ColorSchemeInfo>* result);
18 |   std::string GetColorSchemePreview(const std::string& color_scheme_id);
19 |   std::string GetActiveColorScheme();
20 |   bool SelectColorScheme(const std::string& color_scheme_id);
21 | 
22 |   RimeCustomSettings* settings() { return settings_; }
23 | 
24 |  private:
25 |   RimeLeversApi* api_;
26 |   RimeCustomSettings* settings_;
27 | };
28 | 


--------------------------------------------------------------------------------
/WeaselDeployer/UIStyleSettingsDialog.cpp:
--------------------------------------------------------------------------------
 1 | #include "stdafx.h"
 2 | #include "UIStyleSettingsDialog.h"
 3 | #include "UIStyleSettings.h"
 4 | #include "Configurator.h"
 5 | #include <WeaselUtility.h>
 6 | 
 7 | UIStyleSettingsDialog::UIStyleSettingsDialog(UIStyleSettings* settings)
 8 |     : settings_(settings), loaded_(false) {}
 9 | 
10 | UIStyleSettingsDialog::~UIStyleSettingsDialog() {
11 |   image_.Destroy();
12 | }
13 | 
14 | void UIStyleSettingsDialog::Populate() {
15 |   if (!settings_)
16 |     return;
17 |   std::string active(settings_->GetActiveColorScheme());
18 |   int active_index = -1;
19 |   settings_->GetPresetColorSchemes(&preset_);
20 |   for (size_t i = 0; i < preset_.size(); ++i) {
21 |     std::wstring txt = u8tow(preset_[i].name);
22 |     color_schemes_.AddString(txt.c_str());
23 |     if (preset_[i].color_scheme_id == active) {
24 |       active_index = i;
25 |     }
26 |   }
27 |   if (active_index >= 0) {
28 |     color_schemes_.SetCurSel(active_index);
29 |     Preview(active_index);
30 |   }
31 |   loaded_ = true;
32 | }
33 | 
34 | LRESULT UIStyleSettingsDialog::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) {
35 |   color_schemes_.Attach(GetDlgItem(IDC_COLOR_SCHEME));
36 |   preview_.Attach(GetDlgItem(IDC_PREVIEW));
37 |   select_font_.Attach(GetDlgItem(IDC_SELECT_FONT));
38 |   select_font_.EnableWindow(FALSE);
39 | 
40 |   Populate();
41 | 
42 |   CenterWindow();
43 |   BringWindowToTop();
44 |   return TRUE;
45 | }
46 | 
47 | LRESULT UIStyleSettingsDialog::OnClose(UINT, WPARAM, LPARAM, BOOL&) {
48 |   EndDialog(IDCANCEL);
49 |   return 0;
50 | }
51 | 
52 | LRESULT UIStyleSettingsDialog::OnOK(WORD, WORD code, HWND, BOOL&) {
53 |   EndDialog(code);
54 |   return 0;
55 | }
56 | 
57 | LRESULT UIStyleSettingsDialog::OnColorSchemeSelChange(WORD, WORD, HWND, BOOL&) {
58 |   int index = color_schemes_.GetCurSel();
59 |   if (index >= 0 && index < (int)preset_.size()) {
60 |     settings_->SelectColorScheme(preset_[index].color_scheme_id);
61 |     Preview(index);
62 |   }
63 |   return 0;
64 | }
65 | 
66 | void UIStyleSettingsDialog::Preview(int index) {
67 |   if (index < 0 || index >= (int)preset_.size())
68 |     return;
69 |   const std::string file_path(
70 |       settings_->GetColorSchemePreview(preset_[index].color_scheme_id));
71 |   if (file_path.empty())
72 |     return;
73 |   image_.Destroy();
74 |   // it is from ansi coding, not utf8
75 |   image_.Load(acptow(file_path).c_str());
76 |   if (!image_.IsNull()) {
77 |     preview_.SetBitmap(image_);
78 |   }
79 | }
80 | 


--------------------------------------------------------------------------------
/WeaselDeployer/UIStyleSettingsDialog.h:
--------------------------------------------------------------------------------
 1 | #pragma once
 2 | 
 3 | #include "resource.h"
 4 | #include "UIStyleSettings.h"
 5 | 
 6 | class UIStyleSettingsDialog : public CDialogImpl<UIStyleSettingsDialog> {
 7 |  public:
 8 |   enum { IDD = IDD_STYLE_SETTING };
 9 | 
10 |   UIStyleSettingsDialog(UIStyleSettings* settings);
11 |   ~UIStyleSettingsDialog();
12 | 
13 |  protected:
14 |   BEGIN_MSG_MAP(UIStyleSettingsDialog)
15 |   MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
16 |   MESSAGE_HANDLER(WM_CLOSE, OnClose)
17 |   COMMAND_ID_HANDLER(IDOK, OnOK)
18 |   COMMAND_HANDLER(IDC_COLOR_SCHEME, LBN_SELCHANGE, OnColorSchemeSelChange)
19 |   END_MSG_MAP()
20 | 
21 |   LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&);
22 |   LRESULT OnClose(UINT, WPARAM, LPARAM, BOOL&);
23 |   LRESULT OnOK(WORD, WORD code, HWND, BOOL&);
24 |   LRESULT OnColorSchemeSelChange(WORD, WORD, HWND, BOOL&);
25 | 
26 |   void Populate();
27 |   void Preview(int index);
28 | 
29 |   UIStyleSettings* settings_;
30 |   bool loaded_;
31 |   std::vector<ColorSchemeInfo> preset_;
32 | 
33 |   CListBox color_schemes_;
34 |   CStatic preview_;
35 |   CImage image_;
36 |   CButton select_font_;
37 | };
38 | 


--------------------------------------------------------------------------------
/WeaselDeployer/WeaselDeployer.cpp:
--------------------------------------------------------------------------------
  1 | // WeaselDeployer.cpp : Defines the entry point for the application.
  2 | //
  3 | #include "stdafx.h"
  4 | #include <WeaselUtility.h>
  5 | #include <fstream>
  6 | #include "WeaselDeployer.h"
  7 | #include "Configurator.h"
  8 | 
  9 | CAppModule _Module;
 10 | 
 11 | static int Run(LPTSTR lpCmdLine);
 12 | 
 13 | int APIENTRY _tWinMain(HINSTANCE hInstance,
 14 |                        HINSTANCE hPrevInstance,
 15 |                        LPTSTR lpCmdLine,
 16 |                        int nCmdShow) {
 17 |   UNREFERENCED_PARAMETER(hPrevInstance);
 18 | 
 19 |   LANGID langId = get_language_id();
 20 |   SetThreadUILanguage(langId);
 21 |   SetThreadLocale(langId);
 22 | 
 23 |   HRESULT hRes = ::CoInitialize(NULL);
 24 |   // If you are running on NT 4.0 or higher you can use the following call
 25 |   // instead to make the EXE free threaded. This means that calls come in on a
 26 |   // random RPC thread.
 27 |   // HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
 28 |   ATLASSERT(SUCCEEDED(hRes));
 29 | 
 30 |   // this resolves ATL window thunking problem when Microsoft Layer for Unicode
 31 |   // (MSLU) is used
 32 |   ::DefWindowProc(NULL, 0, 0, 0L);
 33 | 
 34 |   AtlInitCommonControls(
 35 |       ICC_BAR_CLASSES);  // add flags to support other controls
 36 | 
 37 |   hRes = _Module.Init(NULL, hInstance);
 38 |   ATLASSERT(SUCCEEDED(hRes));
 39 | 
 40 |   CreateDirectory(WeaselUserDataPath().c_str(), NULL);
 41 | 
 42 |   int ret = 0;
 43 |   HANDLE hMutex = CreateMutex(NULL, TRUE, L"WeaselDeployerExclusiveMutex");
 44 |   if (!hMutex) {
 45 |     ret = 1;
 46 |   } else if (GetLastError() == ERROR_ALREADY_EXISTS) {
 47 |     ret = 1;
 48 |   } else {
 49 |     ret = Run(lpCmdLine);
 50 |   }
 51 | 
 52 |   if (hMutex) {
 53 |     CloseHandle(hMutex);
 54 |   }
 55 |   _Module.Term();
 56 |   ::CoUninitialize();
 57 | 
 58 |   return ret;
 59 | }
 60 | 
 61 | static int Run(LPTSTR lpCmdLine) {
 62 |   Configurator configurator;
 63 |   configurator.Initialize();
 64 | 
 65 |   if (!wcscmp(L"/?", lpCmdLine) || !wcscmp(L"/help", lpCmdLine)) {
 66 |     WCHAR msg[1024] = {0};
 67 |     if (LoadString(GetModuleHandle(NULL), IDS_STR_HELP, msg,
 68 |                    sizeof(msg) / sizeof(TCHAR))) {
 69 |       MessageBox(NULL, msg, L"Weasel Deployer", MB_ICONINFORMATION | MB_OK);
 70 |     } else {
 71 |       MessageBox(NULL,
 72 |                  L"Usage: WeaselDeployer.exe [options]\n"
 73 |                  L"/? or /help		- Show this help message\n"
 74 |                  L"/deploy		- Update Workspace\n"
 75 |                  L"/dict		- Manage dictionary\n"
 76 |                  L"/sync		- Sync user data\n"
 77 |                  L"/install		- Install Weasel (Initial deployment)",
 78 |                  L"Weasel Deployer", MB_ICONINFORMATION | MB_OK);
 79 |     }
 80 |     return 0;
 81 |   }
 82 | 
 83 |   bool deployment_scheduled = !wcscmp(L"/deploy", lpCmdLine);
 84 |   if (deployment_scheduled) {
 85 |     return configurator.UpdateWorkspace();
 86 |   }
 87 | 
 88 |   bool dict_management = !wcscmp(L"/dict", lpCmdLine);
 89 |   if (dict_management) {
 90 |     return configurator.DictManagement();
 91 |   }
 92 | 
 93 |   bool sync_user_dict = !wcscmp(L"/sync", lpCmdLine);
 94 |   if (sync_user_dict) {
 95 |     return configurator.SyncUserData();
 96 |   }
 97 | 
 98 |   bool installing = !wcscmp(L"/install", lpCmdLine);
 99 |   return configurator.Run(installing);
100 | }
101 | 


--------------------------------------------------------------------------------
/WeaselDeployer/WeaselDeployer.h:
--------------------------------------------------------------------------------
 1 | #pragma once
 2 | 
 3 | #include "resource.h"
 4 | #include <string>
 5 | #include <atlstr.h>
 6 | #include <Windows.h>
 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/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/WeaselDeployer/WeaselDeployer.rc


--------------------------------------------------------------------------------
/WeaselDeployer/WeaselDeployer.vcxproj.filters:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="utf-8"?>
 2 | <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 3 |   <ItemGroup>
 4 |     <Filter Include="Source Files">
 5 |       <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
 6 |       <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
 7 |     </Filter>
 8 |     <Filter Include="Header Files">
 9 |       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
10 |       <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
11 |     </Filter>
12 |     <Filter Include="Resource Files">
13 |       <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
14 |       <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
15 |     </Filter>
16 |   </ItemGroup>
17 |   <ItemGroup>
18 |     <ClInclude Include="stdafx.h">
19 |       <Filter>Header Files</Filter>
20 |     </ClInclude>
21 |     <ClInclude Include="targetver.h">
22 |       <Filter>Header Files</Filter>
23 |     </ClInclude>
24 |     <ClInclude Include="Resource.h">
25 |       <Filter>Header Files</Filter>
26 |     </ClInclude>
27 |     <ClInclude Include="WeaselDeployer.h">
28 |       <Filter>Header Files</Filter>
29 |     </ClInclude>
30 |     <ClInclude Include="Configurator.h">
31 |       <Filter>Header Files</Filter>
32 |     </ClInclude>
33 |     <ClInclude Include="SwitcherSettingsDialog.h">
34 |       <Filter>Header Files</Filter>
35 |     </ClInclude>
36 |     <ClInclude Include="UIStyleSettingsDialog.h">
37 |       <Filter>Header Files</Filter>
38 |     </ClInclude>
39 |     <ClInclude Include="UIStyleSettings.h">
40 |       <Filter>Header Files</Filter>
41 |     </ClInclude>
42 |     <ClInclude Include="DictManagementDialog.h">
43 |       <Filter>Header Files</Filter>
44 |     </ClInclude>
45 |   </ItemGroup>
46 |   <ItemGroup>
47 |     <ClCompile Include="stdafx.cpp">
48 |       <Filter>Source Files</Filter>
49 |     </ClCompile>
50 |     <ClCompile Include="WeaselDeployer.cpp">
51 |       <Filter>Source Files</Filter>
52 |     </ClCompile>
53 |     <ClCompile Include="Configurator.cpp">
54 |       <Filter>Source Files</Filter>
55 |     </ClCompile>
56 |     <ClCompile Include="SwitcherSettingsDialog.cpp">
57 |       <Filter>Source Files</Filter>
58 |     </ClCompile>
59 |     <ClCompile Include="UIStyleSettingsDialog.cpp">
60 |       <Filter>Source Files</Filter>
61 |     </ClCompile>
62 |     <ClCompile Include="UIStyleSettings.cpp">
63 |       <Filter>Source Files</Filter>
64 |     </ClCompile>
65 |     <ClCompile Include="DictManagementDialog.cpp">
66 |       <Filter>Source Files</Filter>
67 |     </ClCompile>
68 |     <ClCompile Include="..\RimeWithWeasel\WeaselUtility.cpp">
69 |       <Filter>Source Files</Filter>
70 |     </ClCompile>
71 |   </ItemGroup>
72 |   <ItemGroup>
73 |     <ResourceCompile Include="WeaselDeployer.rc">
74 |       <Filter>Resource Files</Filter>
75 |     </ResourceCompile>
76 |   </ItemGroup>
77 |   <ItemGroup>
78 |     <None Include="..\resource\weasel.ico">
79 |       <Filter>Resource Files</Filter>
80 |     </None>
81 |   </ItemGroup>
82 | </Project>


--------------------------------------------------------------------------------
/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 | #define IDC_STATIC1                     -1
54 | 
55 | // Next default values for new objects
56 | // 
57 | #ifdef APSTUDIO_INVOKED
58 | #ifndef APSTUDIO_READONLY_SYMBOLS
59 | #define _APS_NO_MFC                     1
60 | #define _APS_NEXT_RESOURCE_VALUE        135
61 | #define _APS_NEXT_COMMAND_VALUE         32771
62 | #define _APS_NEXT_CONTROL_VALUE         1012
63 | #define _APS_NEXT_SYMED_VALUE           110
64 | #endif
65 | #endif
66 | 


--------------------------------------------------------------------------------
/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 <windows.h>
13 | #include <ShellAPI.h>
14 | 
15 | #include <atlbase.h>
16 | #include <atlwin.h>
17 | #include <atlimage.h>
18 | 
19 | #include <wtl/atlapp.h>
20 | #include <wtl/atlctrls.h>
21 | #include <wtl/atlctrlx.h>
22 | #include <wtl/atlmisc.h>
23 | #include <wtl/atldlgs.h>
24 | 
25 | #include <logging.h>
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 <WinSDKVer.h>
 9 | 
10 | #define _WIN32_WINNT _WIN32_WINNT_WINBLUE // Specifies that the minimum required platform is Windows 8.1.
11 | 
12 | #include <SDKDDKVer.h>
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")
 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 <WeaselIPC.h>
 3 | #include <KeyEvent.h>
 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<HIMC, std::shared_ptr<WeaselIME> > {
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<WeaselIME> 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/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/WeaselIME/WeaselIME.rc


--------------------------------------------------------------------------------
/WeaselIME/WeaselIME.vcxproj.filters:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="utf-8"?>
 2 | <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 3 |   <ItemGroup>
 4 |     <Filter Include="Source Files">
 5 |       <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
 6 |       <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
 7 |     </Filter>
 8 |     <Filter Include="Header Files">
 9 |       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
10 |       <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
11 |     </Filter>
12 |     <Filter Include="Resource Files">
13 |       <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
14 |       <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
15 |     </Filter>
16 |   </ItemGroup>
17 |   <ItemGroup>
18 |     <ClCompile Include="dllmain.cpp">
19 |       <Filter>Source Files</Filter>
20 |     </ClCompile>
21 |     <ClCompile Include="ime.cpp">
22 |       <Filter>Source Files</Filter>
23 |     </ClCompile>
24 |     <ClCompile Include="KeyEvent.cpp">
25 |       <Filter>Source Files</Filter>
26 |     </ClCompile>
27 |     <ClCompile Include="stdafx.cpp">
28 |       <Filter>Source Files</Filter>
29 |     </ClCompile>
30 |     <ClCompile Include="WeaselIME.cpp">
31 |       <Filter>Source Files</Filter>
32 |     </ClCompile>
33 |   </ItemGroup>
34 |   <ItemGroup>
35 |     <None Include="weasel.def">
36 |       <Filter>Source Files</Filter>
37 |     </None>
38 |     <None Include="ReadMe.txt" />
39 |     <None Include="..\resource\weasel.ico">
40 |       <Filter>Resource Files</Filter>
41 |     </None>
42 |   </ItemGroup>
43 |   <ItemGroup>
44 |     <ClInclude Include="immdev.h">
45 |       <Filter>Header Files</Filter>
46 |     </ClInclude>
47 |     <ClInclude Include="resource.h">
48 |       <Filter>Header Files</Filter>
49 |     </ClInclude>
50 |     <ClInclude Include="stdafx.h">
51 |       <Filter>Header Files</Filter>
52 |     </ClInclude>
53 |     <ClInclude Include="targetver.h">
54 |       <Filter>Header Files</Filter>
55 |     </ClInclude>
56 |     <ClInclude Include="WeaselIME.h">
57 |       <Filter>Header Files</Filter>
58 |     </ClInclude>
59 |     <ClInclude Include="..\include\WeaselIPC.h">
60 |       <Filter>Header Files</Filter>
61 |     </ClInclude>
62 |     <ClInclude Include="..\include\WeaselUI.h">
63 |       <Filter>Header Files</Filter>
64 |     </ClInclude>
65 |   </ItemGroup>
66 |   <ItemGroup>
67 |     <ResourceCompile Include="WeaselIME.rc">
68 |       <Filter>Resource Files</Filter>
69 |     </ResourceCompile>
70 |   </ItemGroup>
71 | </Project>
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 <windows.h>
14 | #include <shellapi.h>
15 | 
16 | #include "immdev.h"
17 | 
18 | #include <map>
19 | #include <memory>
20 | #include <mutex>
21 | #include <string>
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 <WinSDKVer.h>
 9 | 
10 | #define _WIN32_WINNT _WIN32_WINNT_WINBLUE // Specifies that the minimum required platform is Windows 8.1.
11 | 
12 | #include <SDKDDKVer.h>
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 <StringAlgorithm.hpp>
 3 | #include "Deserializer.h"
 4 | #include "ActionLoader.h"
 5 | #include <algorithm>
 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<std::wstring> 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 <WeaselUtility.h>
 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 |   }
23 | }
24 | 


--------------------------------------------------------------------------------
/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<std::wstring, Deserializer::Factory> 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<std::wstring, Factory>::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 <ResponseParser.h>
 3 | #include <functional>
 4 | 
 5 | namespace weasel {
 6 | 
 7 | template <typename T>
 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<std::wstring> KeyType;
20 |   typedef std::shared_ptr<Deserializer> Ptr;
21 |   typedef std::function<Ptr(ResponseParser* pTarget)> 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<std::wstring, Factory> 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 <StringAlgorithm.hpp>
 3 | #include <WeaselIPC.h>
 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<std::wstring, Deserializer::Ptr>::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 <WeaselIPC.h>
 3 | #include <PipeChannel.h>
 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<PipeMessage> 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 <windows.h>
13 | 
14 | #pragma warning(disable : 4819)
15 | #pragma warning(disable : 4996)
16 | 
17 | #include <boost/interprocess/streams/bufferstream.hpp>
18 | #include <boost/archive/text_wiarchive.hpp> 
19 | 
20 | #pragma warning(default: 4819)
21 | #pragma warning(default: 4996)
22 | 
23 | #include <map>
24 | #include <string>
25 | #include <vector>
26 | #include <sstream>
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 <WinSDKVer.h>
 9 | 
10 | #define _WIN32_WINNT _WIN32_WINNT_WINBLUE // Specifies that the minimum required platform is Windows 8.1.
11 | 
12 | #include <SDKDDKVer.h>
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 <Sddl.h>
 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 <winnt.h>   // for security attributes constants
 3 | #include <aclapi.h>  // 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 | <?xml version="1.0" encoding="utf-8"?>
 2 | <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 3 |   <ItemGroup>
 4 |     <Filter Include="Source Files">
 5 |       <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
 6 |       <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
 7 |     </Filter>
 8 |     <Filter Include="Header Files">
 9 |       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
10 |       <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
11 |     </Filter>
12 |     <Filter Include="Resource Files">
13 |       <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
14 |       <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
15 |     </Filter>
16 |   </ItemGroup>
17 |   <ItemGroup>
18 |     <ClCompile Include="stdafx.cpp">
19 |       <Filter>Source Files</Filter>
20 |     </ClCompile>
21 |     <ClCompile Include="WeaselServerImpl.cpp">
22 |       <Filter>Source Files</Filter>
23 |     </ClCompile>
24 |     <ClCompile Include="SecurityAttribute.cpp">
25 |       <Filter>Source Files</Filter>
26 |     </ClCompile>
27 |   </ItemGroup>
28 |   <ItemGroup>
29 |     <ClInclude Include="stdafx.h">
30 |       <Filter>Header Files</Filter>
31 |     </ClInclude>
32 |     <ClInclude Include="targetver.h">
33 |       <Filter>Header Files</Filter>
34 |     </ClInclude>
35 |     <ClInclude Include="..\include\WeaselIPC.h">
36 |       <Filter>Header Files</Filter>
37 |     </ClInclude>
38 |     <ClInclude Include="WeaselServerImpl.h">
39 |       <Filter>Header Files</Filter>
40 |     </ClInclude>
41 |     <ClInclude Include="SecurityAttribute.h">
42 |       <Filter>Header Files</Filter>
43 |     </ClInclude>
44 |   </ItemGroup>
45 |   <ItemGroup>
46 |     <None Include="ReadMe.txt" />
47 |   </ItemGroup>
48 | </Project>


--------------------------------------------------------------------------------
/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 <windows.h>
13 | 
14 | #include <atlbase.h>
15 | #include <atlwin.h>
16 | 
17 | #include <wtl/atlapp.h>
18 | #include <wtl/atlframe.h>
19 | 
20 | #include <boost/thread.hpp>
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 <WinSDKVer.h>
 9 | 
10 | #define _WIN32_WINNT _WIN32_WINNT_WINBLUE // Specifies that the minimum required platform is Windows 8.1.
11 | 
12 | #include <SDKDDKVer.h>
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/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/WeaselServer/WeaselServer.rc


--------------------------------------------------------------------------------
/WeaselServer/WeaselServer.vcxproj.filters:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="utf-8"?>
 2 | <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 3 |   <ItemGroup>
 4 |     <Filter Include="Source Files">
 5 |       <UniqueIdentifier>{841353c8-3e06-48cf-a570-3bce154c1f21}</UniqueIdentifier>
 6 |       <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm</Extensions>
 7 |     </Filter>
 8 |     <Filter Include="Header Files">
 9 |       <UniqueIdentifier>{e582dfc5-c00c-4d4d-b0fe-64b8e430605e}</UniqueIdentifier>
10 |       <Extensions>h;hpp;hxx;hm;inl;inc</Extensions>
11 |     </Filter>
12 |     <Filter Include="Resource Files">
13 |       <UniqueIdentifier>{cdf05528-dd52-45e1-8ae4-63e02af799fb}</UniqueIdentifier>
14 |       <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest</Extensions>
15 |     </Filter>
16 |   </ItemGroup>
17 |   <ItemGroup>
18 |     <ClCompile Include="stdafx.cpp">
19 |       <Filter>Source Files</Filter>
20 |     </ClCompile>
21 |     <ClCompile Include="WeaselServer.cpp">
22 |       <Filter>Source Files</Filter>
23 |     </ClCompile>
24 |     <ClCompile Include="WeaselService.cpp">
25 |       <Filter>Source Files</Filter>
26 |     </ClCompile>
27 |     <ClCompile Include="WeaselServerApp.cpp">
28 |       <Filter>Source Files</Filter>
29 |     </ClCompile>
30 |     <ClCompile Include="SystemTraySDK.cpp">
31 |       <Filter>Source Files</Filter>
32 |     </ClCompile>
33 |     <ClCompile Include="WeaselTrayIcon.cpp">
34 |       <Filter>Source Files</Filter>
35 |     </ClCompile>
36 |   </ItemGroup>
37 |   <ItemGroup>
38 |     <ClInclude Include="stdafx.h">
39 |       <Filter>Header Files</Filter>
40 |     </ClInclude>
41 |     <ClInclude Include="WeaselService.h">
42 |       <Filter>Header Files</Filter>
43 |     </ClInclude>
44 |     <ClInclude Include="WeaselServerApp.h">
45 |       <Filter>Header Files</Filter>
46 |     </ClInclude>
47 |     <ClInclude Include="SystemTraySDK.h">
48 |       <Filter>Header Files</Filter>
49 |     </ClInclude>
50 |     <ClInclude Include="WeaselTrayIcon.h">
51 |       <Filter>Header Files</Filter>
52 |     </ClInclude>
53 |     <ClInclude Include="resource.h">
54 |       <Filter>Header Files</Filter>
55 |     </ClInclude>
56 |   </ItemGroup>
57 |   <ItemGroup>
58 |     <ResourceCompile Include="WeaselServer.rc">
59 |       <Filter>Resource Files</Filter>
60 |     </ResourceCompile>
61 |   </ItemGroup>
62 |   <ItemGroup>
63 |     <None Include="..\resource\en.ico">
64 |       <Filter>Resource Files</Filter>
65 |     </None>
66 |     <None Include="..\resource\reload.ico">
67 |       <Filter>Resource Files</Filter>
68 |     </None>
69 |     <None Include="..\resource\zh.ico">
70 |       <Filter>Resource Files</Filter>
71 |     </None>
72 |     <None Include="..\resource\weasel.ico">
73 |       <Filter>Resource Files</Filter>
74 |     </None>
75 |   </ItemGroup>
76 |   <ItemGroup>
77 |     <Image Include="..\resource\full.ico">
78 |       <Filter>Resource Files</Filter>
79 |     </Image>
80 |     <Image Include="..\resource\half.ico">
81 |       <Filter>Resource Files</Filter>
82 |     </Image>
83 |   </ItemGroup>
84 | </Project>


--------------------------------------------------------------------------------
/WeaselServer/WeaselServerApp.cpp:
--------------------------------------------------------------------------------
 1 | #include "stdafx.h"
 2 | #include "WeaselServerApp.h"
 3 | #include <filesystem>
 4 | 
 5 | WeaselServerApp::WeaselServerApp()
 6 |     : m_handler(std::make_unique<RimeWithWeaselHandler>(&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 <resource.h>
 5 | #include <WeaselIPC.h>
 6 | #include <WeaselUI.h>
 7 | #include <RimeWithWeasel.h>
 8 | #include <WeaselUtility.h>
 9 | #include <filesystem>
10 | #include <functional>
11 | #include <memory>
12 | #include <winsparkle.h>
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<RimeWithWeaselHandler> m_handler;
70 | };
71 | 


--------------------------------------------------------------------------------
/WeaselServer/WeaselService.h:
--------------------------------------------------------------------------------
 1 | #pragma once
 2 | 
 3 | #include <Windows.h>
 4 | #include <memory>
 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 <atlstr.h>
 4 | 
 5 | // nasty
 6 | #include <resource.h>
 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 <WeaselUI.h>
 3 | #include <WeaselIPC.h>
 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 <atlimpl.cpp>
 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 <atlbase.h>
27 | #include <atlwin.h>
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 <wtl/atlapp.h>
46 | #include <wtl/atlframe.h>
47 | #include <wtl/atlctrls.h>
48 | #include <wtl/atldlgs.h>
49 | 
50 | #include <VersionHelpers.hpp>
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/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/WeaselSetup/WeaselSetup.ico


--------------------------------------------------------------------------------
/WeaselSetup/WeaselSetup.rc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/WeaselSetup/WeaselSetup.rc


--------------------------------------------------------------------------------
/WeaselSetup/WeaselSetup.vcxproj.filters:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="utf-8"?>
 2 | <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 3 |   <ItemGroup>
 4 |     <Filter Include="Source Files">
 5 |       <UniqueIdentifier>{2df80f89-25ee-49a8-a0bf-2dd38ec3b0b2}</UniqueIdentifier>
 6 |       <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm</Extensions>
 7 |     </Filter>
 8 |     <Filter Include="Header Files">
 9 |       <UniqueIdentifier>{30b9a326-3c70-4dd6-99a0-8fc6015e684b}</UniqueIdentifier>
10 |       <Extensions>h;hpp;hxx;hm;inl;inc</Extensions>
11 |     </Filter>
12 |     <Filter Include="Resource Files">
13 |       <UniqueIdentifier>{6ed053d1-845d-4449-a84b-43340151cc7c}</UniqueIdentifier>
14 |       <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest</Extensions>
15 |     </Filter>
16 |   </ItemGroup>
17 |   <ItemGroup>
18 |     <ClCompile Include="stdafx.cpp">
19 |       <Filter>Source Files</Filter>
20 |     </ClCompile>
21 |     <ClCompile Include="WeaselSetup.cpp">
22 |       <Filter>Source Files</Filter>
23 |     </ClCompile>
24 |     <ClCompile Include="InstallOptionsDlg.cpp">
25 |       <Filter>Source Files</Filter>
26 |     </ClCompile>
27 |     <ClCompile Include="imesetup.cpp">
28 |       <Filter>Source Files</Filter>
29 |     </ClCompile>
30 |   </ItemGroup>
31 |   <ItemGroup>
32 |     <ClInclude Include="stdafx.h">
33 |       <Filter>Header Files</Filter>
34 |     </ClInclude>
35 |     <ClInclude Include="resource.h">
36 |       <Filter>Header Files</Filter>
37 |     </ClInclude>
38 |     <ClInclude Include="InstallOptionsDlg.h">
39 |       <Filter>Header Files</Filter>
40 |     </ClInclude>
41 |   </ItemGroup>
42 |   <ItemGroup>
43 |     <ResourceCompile Include="WeaselSetup.rc">
44 |       <Filter>Resource Files</Filter>
45 |     </ResourceCompile>
46 |   </ItemGroup>
47 |   <ItemGroup>
48 |     <Image Include="WeaselSetup.ico">
49 |       <Filter>Resource Files</Filter>
50 |     </Image>
51 |   </ItemGroup>
52 | </Project>


--------------------------------------------------------------------------------
/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 <atlbase.h>
14 | #include <wtl/atlapp.h>
15 | 
16 | extern CAppModule _Module;
17 | 
18 | #include <atlwin.h>
19 | 
20 | #include <wtl/atlframe.h>
21 | #include <wtl/atlctrls.h>
22 | #include <wtl/atldlgs.h>
23 | 
24 | #include <string>
25 | #include <shellapi.h>
26 | #include <imm.h>
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 <WeaselUI.h>
 3 | #include "ctffunc.h"
 4 | 
 5 | class WeaselTSF;
 6 | 
 7 | class CCandidateList : public ITfIntegratableCandidateListUIElement,
 8 |                        public ITfCandidateListUIElementBehavior {
 9 |  public:
10 |   CCandidateList(com_ptr<WeaselTSF> 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<ITfContext> 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<weasel::UI> _ui;
81 |   DWORD _cRef;
82 |   com_ptr<WeaselTSF> _tsf;
83 |   DWORD uiid;
84 |   TfIntegratableCandidateListSelectionStyle _selectionStyle =
85 |       STYLE_ACTIVE_SELECTION;
86 | 
87 |   BOOL _pbShow;
88 |   weasel::UIStyle _style;
89 | 
90 |   com_ptr<ITfContext> _pContextDocument;
91 | };
92 | 


--------------------------------------------------------------------------------
/WeaselTSF/Compartment.h:
--------------------------------------------------------------------------------
 1 | #pragma once
 2 | #include <functional>
 3 | #include <msctf.h>
 4 | 
 5 | class CCompartmentEventSink : public ITfCompartmentEventSink {
 6 |  public:
 7 |   using Callback = std::function<HRESULT(REFGUID guidCompartment)>;
 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<IUnknown> punk, _In_ REFGUID guidCompartment);
22 |   HRESULT _Unadvise();
23 | 
24 |  private:
25 |   com_ptr<ITfCompartment> _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 <msctf.h>
 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<weasel::Context>();
11 |   weasel::ResponseParser parser(&commit, context.get(), &_status, &config,
12 |                                 &_cand->style());
13 | 
14 |   bool ok = m_client.GetResponseData(std::ref(parser));
15 | 
16 |   _UpdateLanguageBar(_status);
17 | 
18 |   if (ok) {
19 |     if (!commit.empty()) {
20 |       // For auto-selecting, commit and preedit can both exist.
21 |       // Commit and close the original composition first.
22 |       if (!_IsComposing()) {
23 |         _StartComposition(_pEditSessionContext,
24 |                           _fCUASWorkaroundEnabled && !config.inline_preedit);
25 |       }
26 |       _InsertText(_pEditSessionContext, commit);
27 |       _EndComposition(_pEditSessionContext, false);
28 |       _committed = TRUE;
29 |     } else {
30 |       _committed = FALSE;
31 |     }
32 |     if (_status.composing && !_IsComposing()) {
33 |       _StartComposition(_pEditSessionContext,
34 |                         _fCUASWorkaroundEnabled && !config.inline_preedit);
35 |     } else if (!_status.composing && _IsComposing()) {
36 |       _EndComposition(_pEditSessionContext, true);
37 |     }
38 |     if (_IsComposing() && config.inline_preedit) {
39 |       _ShowInlinePreedit(_pEditSessionContext, context);
40 |     }
41 |     _UpdateCompositionWindow(_pEditSessionContext);
42 |   }
43 | 
44 |   _UpdateUI(*context, _status);
45 | 
46 |   return TRUE;
47 | }
48 | 


--------------------------------------------------------------------------------
/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<WeaselTSF> pTextService, com_ptr<ITfContext> 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<WeaselTSF> _pTextService;
47 |   com_ptr<ITfContext> _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 <WeaselConstants.h>
 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 <msctf.h>
 3 | #include <WeaselUI.h>
 4 | 
 5 | class CLangBarItemButton : public ITfLangBarItemButton, public ITfSource {
 6 |  public:
 7 |   CLangBarItemButton(com_ptr<WeaselTSF> 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<WeaselTSF> _pTextService;
41 |   com_ptr<ITfLangBarItemSink> _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 <VersionHelpers.hpp>
  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<ITfDocumentMgr> pCandidateListDocumentMgr;
17 |   com_ptr<ITfContext> 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/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/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 <stdio.h>
 5 | #include <Windows.h>
 6 | #include <DbgHelp.h>
 7 | #include <tchar.h>
 8 | #include <time.h>
 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 <Windows.h>
13 | #include <Ole2.h>
14 | #include <OleCtl.h>
15 | #include <msctf.h>
16 | #include <assert.h>
17 | 
18 | #include <atlcomcli.h> 
19 | 
20 | #include <map>
21 | #include <memory>
22 | #include <string>
23 | 
24 | template<typename I>
25 | using com_ptr = CComPtr<I>;
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 <WinSDKVer.h>
 9 | 
10 | #define _WIN32_WINNT _WIN32_WINNT_WINBLUE // Specifies that the minimum required platform is Windows 8.1.
11 | 
12 | #include <SDKDDKVer.h>
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 <gdiplus.h>
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 <atlbase.h>
13 | #include <atlwin.h>
14 | 
15 | #include <wtl/atlapp.h>
16 | #include <wtl/atlframe.h>
17 | #include <wtl/atlgdi.h>
18 | #include <wtl/atlmisc.h>
19 | 
20 | #include <string>
21 | #include <vector>
22 | 
23 | #include <logging.h>
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 <WinSDKVer.h>
 9 | 
10 | #define _WIN32_WINNT _WIN32_WINNT_WINBLUE // Specifies that the minimum required platform is Windows 8.1.
11 | 
12 | #include <SDKDDKVer.h>
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_78_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 | rem OPTIONAL: path to additional build tools
15 | rem set DEVTOOLS_PATH=%ProgramFiles%\Git\cmd;%ProgramFiles%\Git\usr\bin;%ProgramFiles%\CMake\bin;
16 | 


--------------------------------------------------------------------------------
/env.vs2022.bat:
--------------------------------------------------------------------------------
 1 | rem Customize your build environment and save the modified copy to env.bat
 2 | 
 3 | set WEASEL_ROOT=%CD%
 4 | 
 5 | rem REQUIRED: path to Boost source directory
 6 | if not defined BOOST_ROOT set BOOST_ROOT=%WEASEL_ROOT%\deps\boost_1_78_0
 7 | 
 8 | rem OPTIONAL: architecture, Visual Studio version and platform toolset
 9 | 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 | rem OPTIONAL: path to additional build tools
15 | rem set DEVTOOLS_PATH=%ProgramFiles%\Git\cmd;%ProgramFiles%\Git\usr\bin;%ProgramFiles%\CMake\bin;
16 | 


--------------------------------------------------------------------------------
/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 '<a name="(.*)"></a>'
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 <WeaselIPCData.h>
 3 | #include <windows.h>
 4 | #include <map>
 5 | #include <memory>
 6 | #include <string>
 7 | 
 8 | namespace weasel {
 9 | class Deserializer;
10 | 
11 | // 解析server回應文本
12 | struct ResponseParser {
13 |   std::map<std::wstring, std::shared_ptr<Deserializer> > 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 <algorithm>
 3 | #include <clocale>
 4 | #include <cwctype>
 5 | #include <numeric>
 6 | #include <set>
 7 | #include <string>
 8 | #include <vector>
 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<std::string>& 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<std::wstring>& split(std::vector<std::wstring>& 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 <VersionHelpers.h>
 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 <glog/logging.h>
 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 <class T>
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/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/lib/WinSparkle.lib


--------------------------------------------------------------------------------
/lib64/WinSparkle.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/lib64/WinSparkle.lib


--------------------------------------------------------------------------------
/output/7z.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/7z.dll


--------------------------------------------------------------------------------
/output/7z.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/7z.exe


--------------------------------------------------------------------------------
/output/COPYING-curl.txt:
--------------------------------------------------------------------------------
 1 | COPYRIGHT AND PERMISSION NOTICE
 2 | 
 3 | Copyright (c) 1996 - 2024, Daniel Stenberg, <daniel@haxx.se>, 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/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/Win32/WinSparkle.dll


--------------------------------------------------------------------------------
/output/WinSparkle.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/WinSparkle.dll


--------------------------------------------------------------------------------
/output/archives/.placeholder:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/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/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/curl.exe


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_android.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_android.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_aqua.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_aqua.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_azure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_azure.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_brasil.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_brasil.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_brisk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_brisk.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_cool_breeze.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_cool_breeze.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_dark_temple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_dark_temple.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_doraemon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_doraemon.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_dota_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_dota_2.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_espagna.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_espagna.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_flypy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_flypy.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_gholabok.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_gholabok.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_google.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_google.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_google_plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_google_plus.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_ink.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_ink.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_kuma_shuzboz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_kuma_shuzboz.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_kuon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_kuon.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_lost_temple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_lost_temple.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_luna.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_luna.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_macau.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_macau.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_metroblue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_metroblue.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_modern_warfare.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_modern_warfare.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_nba.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_nba.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_ps4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_ps4.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_psionics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_psionics.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_skype.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_skype.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_smurfs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_smurfs.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_so_young.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_so_young.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_solarized_rock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_solarized_rock.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_starcraft.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_starcraft.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_starcraft_ii.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_starcraft_ii.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_steam.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_steam.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_tintin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_tintin.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_wii.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_wii.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_xbox_silver.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/output/data/preview/color_scheme_xbox_silver.png


--------------------------------------------------------------------------------
/output/data/preview/color_scheme_youtube.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/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 + " <TargetFile> 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/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/resource/en.ico


--------------------------------------------------------------------------------
/resource/full.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/resource/full.ico


--------------------------------------------------------------------------------
/resource/half.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/resource/half.ico


--------------------------------------------------------------------------------
/resource/reload.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/resource/reload.ico


--------------------------------------------------------------------------------
/resource/weasel.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/resource/weasel.ico


--------------------------------------------------------------------------------
/resource/zh.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rime/weasel/7bd62cd68e10224c98c1ef0d029bc3e6759b369d/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 <boost/detail/lightweight_test.hpp>
 6 | #include <ResponseParser.h>
 7 | #include <string>
 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 | <?xml version="1.0" encoding="utf-8"?>
 2 | <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 3 |   <ItemGroup>
 4 |     <Filter Include="Source Files">
 5 |       <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
 6 |       <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
 7 |     </Filter>
 8 |     <Filter Include="Header Files">
 9 |       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
10 |       <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
11 |     </Filter>
12 |     <Filter Include="Resource Files">
13 |       <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
14 |       <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
15 |     </Filter>
16 |   </ItemGroup>
17 |   <ItemGroup>
18 |     <ClCompile Include="stdafx.cpp">
19 |       <Filter>Source Files</Filter>
20 |     </ClCompile>
21 |     <ClCompile Include="TestResponseParser.cpp">
22 |       <Filter>Source Files</Filter>
23 |     </ClCompile>
24 |   </ItemGroup>
25 |   <ItemGroup>
26 |     <ClInclude Include="stdafx.h">
27 |       <Filter>Header Files</Filter>
28 |     </ClInclude>
29 |     <ClInclude Include="targetver.h">
30 |       <Filter>Header Files</Filter>
31 |     </ClInclude>
32 |   </ItemGroup>
33 |   <ItemGroup>
34 |     <None Include="ReadMe.txt" />
35 |   </ItemGroup>
36 | </Project>


--------------------------------------------------------------------------------
/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 <stdio.h>
11 | #include <tchar.h>
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 <WinSDKVer.h>
 9 | 
10 | #define _WIN32_WINNT _WIN32_WINNT_WINBLUE // Specifies that the minimum required platform is Windows 8.1.
11 | 
12 | #include <SDKDDKVer.h>
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 | <?xml version="1.0" encoding="utf-8"?>
 2 | <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 3 |   <ItemGroup>
 4 |     <Filter Include="Source Files">
 5 |       <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
 6 |       <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
 7 |     </Filter>
 8 |     <Filter Include="Header Files">
 9 |       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
10 |       <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
11 |     </Filter>
12 |     <Filter Include="Resource Files">
13 |       <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
14 |       <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
15 |     </Filter>
16 |   </ItemGroup>
17 |   <ItemGroup>
18 |     <ClCompile Include="stdafx.cpp">
19 |       <Filter>Source Files</Filter>
20 |     </ClCompile>
21 |     <ClCompile Include="TestWeaselIPC.cpp">
22 |       <Filter>Source Files</Filter>
23 |     </ClCompile>
24 |   </ItemGroup>
25 |   <ItemGroup>
26 |     <ClInclude Include="stdafx.h">
27 |       <Filter>Header Files</Filter>
28 |     </ClInclude>
29 |     <ClInclude Include="targetver.h">
30 |       <Filter>Header Files</Filter>
31 |     </ClInclude>
32 |   </ItemGroup>
33 |   <ItemGroup>
34 |     <None Include="ReadMe.txt" />
35 |   </ItemGroup>
36 | </Project>


--------------------------------------------------------------------------------
/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 <stdio.h>
11 | #include <tchar.h>
12 | 
13 | #include <windows.h>
14 | 
15 | #include <atlbase.h>
16 | 
17 | #include <wtl/atlapp.h>
18 | #include <string>
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 <WinSDKVer.h>
 9 | 
10 | #define _WIN32_WINNT _WIN32_WINNT_WINBLUE // Specifies that the minimum required platform is Windows 8.1.
11 | 
12 | #include <SDKDDKVer.h>
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 | <?xml version="1.0" encoding="utf-8"?>
 2 | <rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle">
 3 | <channel>
 4 |     <title>【小狼毫】輸入法更新頻道</title>
 5 |     <link>http://rime.github.io/release/weasel/appcast.xml</link>
 6 |     <description>小狼毫 Appcast 更新頻道</description>
 7 |     <language>zh</language>
 8 |     <item>
 9 |       <title>小狼毫 0.17.4</title>
10 |       <sparkle:releaseNotesLink>http://rime.github.io/release/weasel/</sparkle:releaseNotesLink>
11 |       <pubDate>Wed, 04 Jun 2025 12:33:57 +0800</pubDate>
12 |       <enclosure url="https://github.com/rime/weasel/releases/download/0.17.4/weasel-0.17.4.0-installer.exe"
13 |                  sparkle:version="0.17.4"
14 |                  type="application/octet-stream"/>
15 |     </item>
16 |   </channel>
17 | </rss>
18 | 


--------------------------------------------------------------------------------
/update/testing-appcast.xml:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="utf-8"?>
 2 | <rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle">
 3 | <channel>
 4 |     <title>【小狼毫】輸入法測試頻道</title>
 5 |     <link>http://rime.github.io/testing/weasel/appcast.xml</link>
 6 |     <description>小狼毫測試版 Appcast 更新頻道</description>
 7 |     <language>zh</language>
 8 |     <item>
 9 |       <title>小狼毫 0.17.4</title>
10 |       <sparkle:releaseNotesLink>http://rime.github.io/release/weasel/</sparkle:releaseNotesLink>
11 |       <pubDate>Wed, 04 Jun 2025 12:33:57 +0800</pubDate>
12 |       <enclosure url="https://github.com/rime/weasel/releases/download/0.17.4/weasel-0.17.4.0-installer.exe"
13 |                  sparkle:version="0.17.4"
14 |                  type="application/octet-stream"/>
15 |     </item>
16 |   </channel>
17 | </rss>
18 | 


--------------------------------------------------------------------------------
/update/write-release-notes.sh:
--------------------------------------------------------------------------------
 1 | #!/bin/bash
 2 | 
 3 | # writes an HTML page for changes in the latest release
 4 | 
 5 | cat <<EOF > release-notes.html
 6 | <!DOCTYPE HTML>
 7 | <html>
 8 | <head>
 9 | <meta charset="utf-8">
10 | </head>
11 | <body>
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 <<EOF >> release-notes.html
23 | </body>
24 | </html>
25 | EOF
26 | 


--------------------------------------------------------------------------------
/weasel.props.template:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="utf-8"?>
 2 | <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 3 |   <PropertyGroup Label="UserMacros">
 4 |     <BOOST_ROOT>$BOOST_ROOT</BOOST_ROOT>
 5 |     <PLATFORM_TOOLSET>$PLATFORM_TOOLSET</PLATFORM_TOOLSET>
 6 |     <VERSION_MAJOR>$VERSION_MAJOR</VERSION_MAJOR>
 7 |     <VERSION_MINOR>$VERSION_MINOR</VERSION_MINOR>
 8 |     <VERSION_PATCH>$VERSION_PATCH</VERSION_PATCH>
 9 |     <PRODUCT_VERSION>$PRODUCT_VERSION</PRODUCT_VERSION>
10 |     <FILE_VERSION>$FILE_VERSION</FILE_VERSION>
11 |   </PropertyGroup>
12 |   <ItemGroup>
13 |     <BuildMacro Include="BOOST_ROOT">
14 |       <Value>$(BOOST_ROOT)</Value>
15 |       <EnvironmentVariable>true</EnvironmentVariable>
16 |     </BuildMacro>
17 |     <BuildMacro Include="PLATFORM_TOOLSET">
18 |       <Value>$(PLATFORM_TOOLSET)</Value>
19 |       <EnvironmentVariable>true</EnvironmentVariable>
20 |     </BuildMacro>
21 |   </ItemGroup>
22 |   <ItemDefinitionGroup>
23 |     <ClCompile>
24 |       <PreprocessorDefinitions>$(PreprocessorDefinitions);VERSION_MAJOR=$(VERSION_MAJOR);VERSION_MINOR=$(VERSION_MINOR);VERSION_PATCH=$(VERSION_PATCH);</PreprocessorDefinitions>
25 |       <AdditionalOptions>/utf-8</AdditionalOptions>
26 |     </ClCompile>
27 |     <ResourceCompile>
28 |       <PreprocessorDefinitions>$(PreprocessorDefinitions);VERSION_MAJOR=$(VERSION_MAJOR);VERSION_MINOR=$(VERSION_MINOR);VERSION_PATCH=$(VERSION_PATCH);PRODUCT_VERSION=$(PRODUCT_VERSION);FILE_VERSION=$(FILE_VERSION);</PreprocessorDefinitions>
29 |     </ResourceCompile>
30 |   </ItemDefinitionGroup>
31 | </Project>
32 | 


--------------------------------------------------------------------------------