├── .github
└── FUNDING.yml
├── .gitignore
├── EverythingExt
├── EverythingExt.vcxproj
├── EverythingExt.vcxproj.filters
├── PinyinSearch.cpp
├── PinyinSearch.hpp
├── PinyinSearchEdit.cpp
├── PinyinSearchEdit.hpp
├── PinyinSearchPcre.cpp
├── PinyinSearchPcre.hpp
├── common.hpp
├── config.cpp
├── config.hpp
├── dllmain.cpp
├── framework.h
├── helper.cpp
├── helper.hpp
├── ipc.cpp
├── ipc.hpp
├── ipc_window.cpp
├── ipc_window.hpp
├── match.cpp
├── match.hpp
├── pch.cpp
├── pch.h
├── pinyin.cpp
├── pinyin.hpp
├── quick_select.cpp
├── quick_select.hpp
├── resource.h
├── resource.rc
├── search_history.cpp
├── search_history.hpp
└── toupper_gen.py
├── IbEverythingExt.sln
├── LICENSE.txt
├── README.md
├── Updater
├── Updater.vcxproj
├── Updater.vcxproj.filters
└── updater.cpp
├── docs
├── Disk space
│ └── images
│ │ ├── VisualStudio.png
│ │ └── dupe.png
├── development.md
├── pinyin_search.png
├── pinyin_search
│ ├── edit_mode.md
│ └── edit_mode.png
├── preview.png
├── quick_select_dark_mode.png
└── third_party
│ ├── EverythingToolbar.png
│ ├── FlowLauncher.png
│ ├── HuoChat.png
│ ├── PowerToys.png
│ ├── README.md
│ ├── Wox.png
│ └── uTools.png
├── external
└── CMakeLists.txt
└── test
├── common.hpp
├── main.cpp
├── match.cpp
├── pcre.cpp
├── test.vcxproj
├── test.vcxproj.filters
├── v1.4.cpp
└── v1.5a.cpp
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: ["https://chaoses-ib.github.io/funding/微信赞赏码.png", "https://chaoses-ib.github.io/funding/支付宝收款码.png", "感谢捐赠,捐赠时请备注仓库名,便于记录。"]
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 |
3 | private/
4 | *.private
5 | *.private.*
6 |
7 | ## Ignore Visual Studio temporary files, build results, and
8 | ## files generated by popular Visual Studio add-ons.
9 | ##
10 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
11 |
12 | # User-specific files
13 | *.rsuser
14 | *.suo
15 | *.user
16 | *.userosscache
17 | *.sln.docstates
18 |
19 | # User-specific files (MonoDevelop/Xamarin Studio)
20 | *.userprefs
21 |
22 | # Build results
23 | [Dd]ebug/
24 | [Dd]ebugPublic/
25 | [Rr]elease/
26 | [Rr]eleases/
27 | x64/
28 | x86/
29 | [Aa][Rr][Mm]/
30 | [Aa][Rr][Mm]64/
31 | bld/
32 | [Bb]in/
33 | [Oo]bj/
34 | [Ll]og/
35 |
36 | # Visual Studio 2015/2017 cache/options directory
37 | .vs/
38 | # Uncomment if you have tasks that create the project's static files in wwwroot
39 | #wwwroot/
40 |
41 | # Visual Studio 2017 auto generated files
42 | Generated\ Files/
43 |
44 | # MSTest test Results
45 | [Tt]est[Rr]esult*/
46 | [Bb]uild[Ll]og.*
47 |
48 | # NUNIT
49 | *.VisualState.xml
50 | TestResult.xml
51 |
52 | # Build Results of an ATL Project
53 | [Dd]ebugPS/
54 | [Rr]eleasePS/
55 | dlldata.c
56 |
57 | # Benchmark Results
58 | BenchmarkDotNet.Artifacts/
59 |
60 | # .NET Core
61 | project.lock.json
62 | project.fragment.lock.json
63 | artifacts/
64 |
65 | # StyleCop
66 | StyleCopReport.xml
67 |
68 | # Files built by Visual Studio
69 | *_i.c
70 | *_p.c
71 | *_h.h
72 | *.ilk
73 | *.meta
74 | *.obj
75 | *.iobj
76 | *.pch
77 | *.pdb
78 | *.ipdb
79 | *.pgc
80 | *.pgd
81 | *.rsp
82 | *.sbr
83 | *.tlb
84 | *.tli
85 | *.tlh
86 | *.tmp
87 | *.tmp_proj
88 | *_wpftmp.csproj
89 | *.log
90 | *.vspscc
91 | *.vssscc
92 | .builds
93 | *.pidb
94 | *.svclog
95 | *.scc
96 |
97 | # Chutzpah Test files
98 | _Chutzpah*
99 |
100 | # Visual C++ cache files
101 | ipch/
102 | *.aps
103 | *.ncb
104 | *.opendb
105 | *.opensdf
106 | *.sdf
107 | *.cachefile
108 | *.VC.db
109 | *.VC.VC.opendb
110 |
111 | # Visual Studio profiler
112 | *.psess
113 | *.vsp
114 | *.vspx
115 | *.sap
116 |
117 | # Visual Studio Trace Files
118 | *.e2e
119 |
120 | # TFS 2012 Local Workspace
121 | $tf/
122 |
123 | # Guidance Automation Toolkit
124 | *.gpState
125 |
126 | # ReSharper is a .NET coding add-in
127 | _ReSharper*/
128 | *.[Rr]e[Ss]harper
129 | *.DotSettings.user
130 |
131 | # JustCode is a .NET coding add-in
132 | .JustCode
133 |
134 | # TeamCity is a build add-in
135 | _TeamCity*
136 |
137 | # DotCover is a Code Coverage Tool
138 | *.dotCover
139 |
140 | # AxoCover is a Code Coverage Tool
141 | .axoCover/*
142 | !.axoCover/settings.json
143 |
144 | # Visual Studio code coverage results
145 | *.coverage
146 | *.coveragexml
147 |
148 | # NCrunch
149 | _NCrunch_*
150 | .*crunch*.local.xml
151 | nCrunchTemp_*
152 |
153 | # MightyMoose
154 | *.mm.*
155 | AutoTest.Net/
156 |
157 | # Web workbench (sass)
158 | .sass-cache/
159 |
160 | # Installshield output folder
161 | [Ee]xpress/
162 |
163 | # DocProject is a documentation generator add-in
164 | DocProject/buildhelp/
165 | DocProject/Help/*.HxT
166 | DocProject/Help/*.HxC
167 | DocProject/Help/*.hhc
168 | DocProject/Help/*.hhk
169 | DocProject/Help/*.hhp
170 | DocProject/Help/Html2
171 | DocProject/Help/html
172 |
173 | # Click-Once directory
174 | publish/
175 |
176 | # Publish Web Output
177 | *.[Pp]ublish.xml
178 | *.azurePubxml
179 | # Note: Comment the next line if you want to checkin your web deploy settings,
180 | # but database connection strings (with potential passwords) will be unencrypted
181 | *.pubxml
182 | *.publishproj
183 |
184 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
185 | # checkin your Azure Web App publish settings, but sensitive information contained
186 | # in these scripts will be unencrypted
187 | PublishScripts/
188 |
189 | # NuGet Packages
190 | *.nupkg
191 | # The packages folder can be ignored because of Package Restore
192 | **/[Pp]ackages/*
193 | # except build/, which is used as an MSBuild target.
194 | !**/[Pp]ackages/build/
195 | # Uncomment if necessary however generally it will be regenerated when needed
196 | #!**/[Pp]ackages/repositories.config
197 | # NuGet v3's project.json files produces more ignorable files
198 | *.nuget.props
199 | *.nuget.targets
200 |
201 | # Microsoft Azure Build Output
202 | csx/
203 | *.build.csdef
204 |
205 | # Microsoft Azure Emulator
206 | ecf/
207 | rcf/
208 |
209 | # Windows Store app package directories and files
210 | AppPackages/
211 | BundleArtifacts/
212 | Package.StoreAssociation.xml
213 | _pkginfo.txt
214 | *.appx
215 |
216 | # Visual Studio cache files
217 | # files ending in .cache can be ignored
218 | *.[Cc]ache
219 | # but keep track of directories ending in .cache
220 | !?*.[Cc]ache/
221 |
222 | # Others
223 | ClientBin/
224 | ~$*
225 | *~
226 | *.dbmdl
227 | *.dbproj.schemaview
228 | *.jfm
229 | *.pfx
230 | *.publishsettings
231 | orleans.codegen.cs
232 |
233 | # Including strong name files can present a security risk
234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
235 | #*.snk
236 |
237 | # Since there are multiple workflows, uncomment next line to ignore bower_components
238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
239 | #bower_components/
240 |
241 | # RIA/Silverlight projects
242 | Generated_Code/
243 |
244 | # Backup & report files from converting an old project file
245 | # to a newer Visual Studio version. Backup files are not needed,
246 | # because we have git ;-)
247 | _UpgradeReport_Files/
248 | Backup*/
249 | UpgradeLog*.XML
250 | UpgradeLog*.htm
251 | ServiceFabricBackup/
252 | *.rptproj.bak
253 |
254 | # SQL Server files
255 | *.mdf
256 | *.ldf
257 | *.ndf
258 |
259 | # Business Intelligence projects
260 | *.rdl.data
261 | *.bim.layout
262 | *.bim_*.settings
263 | *.rptproj.rsuser
264 | *- Backup*.rdl
265 |
266 | # Microsoft Fakes
267 | FakesAssemblies/
268 |
269 | # GhostDoc plugin setting file
270 | *.GhostDoc.xml
271 |
272 | # Node.js Tools for Visual Studio
273 | .ntvs_analysis.dat
274 | node_modules/
275 |
276 | # Visual Studio 6 build log
277 | *.plg
278 |
279 | # Visual Studio 6 workspace options file
280 | *.opt
281 |
282 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
283 | *.vbw
284 |
285 | # Visual Studio LightSwitch build output
286 | **/*.HTMLClient/GeneratedArtifacts
287 | **/*.DesktopClient/GeneratedArtifacts
288 | **/*.DesktopClient/ModelManifest.xml
289 | **/*.Server/GeneratedArtifacts
290 | **/*.Server/ModelManifest.xml
291 | _Pvt_Extensions
292 |
293 | # Paket dependency manager
294 | .paket/paket.exe
295 | paket-files/
296 |
297 | # FAKE - F# Make
298 | .fake/
299 |
300 | # JetBrains Rider
301 | .idea/
302 | *.sln.iml
303 |
304 | # CodeRush personal settings
305 | .cr/personal
306 |
307 | # Python Tools for Visual Studio (PTVS)
308 | __pycache__/
309 | *.pyc
310 |
311 | # Cake - Uncomment if you are using it
312 | # tools/**
313 | # !tools/packages.config
314 |
315 | # Tabs Studio
316 | *.tss
317 |
318 | # Telerik's JustMock configuration file
319 | *.jmconfig
320 |
321 | # BizTalk build output
322 | *.btp.cs
323 | *.btm.cs
324 | *.odx.cs
325 | *.xsd.cs
326 |
327 | # OpenCover UI analysis results
328 | OpenCover/
329 |
330 | # Azure Stream Analytics local run output
331 | ASALocalRun/
332 |
333 | # MSBuild Binary and Structured Log
334 | *.binlog
335 |
336 | # NVidia Nsight GPU debugger configuration file
337 | *.nvuser
338 |
339 | # MFractors (Xamarin productivity tool) working folder
340 | .mfractor/
341 |
342 | # Local History for Visual Studio
343 | .localhistory/
344 |
345 | # BeatPulse healthcheck temp database
346 | healthchecksdb
--------------------------------------------------------------------------------
/EverythingExt/EverythingExt.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | Win32Proj
24 | {102eefa7-f37c-4fa7-ac25-d4ddc2e797e7}
25 | EverythingExt
26 | 10.0
27 |
28 |
29 |
30 | DynamicLibrary
31 | true
32 | v143
33 | Unicode
34 |
35 |
36 | DynamicLibrary
37 | false
38 | v143
39 | true
40 | Unicode
41 |
42 |
43 | DynamicLibrary
44 | true
45 | v143
46 | Unicode
47 |
48 |
49 | DynamicLibrary
50 | false
51 | v143
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | true
75 | WindowsCodecs
76 |
77 |
78 | false
79 | WindowsCodecs
80 |
81 |
82 | true
83 | WindowsCodecs
84 |
85 |
86 | false
87 | WindowsCodecs
88 |
89 |
90 | x64-windows-static-md
91 |
92 |
93 | x64-windows-static-md
94 |
95 |
96 |
97 | Level3
98 | true
99 | IB_DEBUG;WIN32;_DEBUG;EVERYTHINGEXT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
100 | true
101 | Use
102 | pch.h
103 | stdcpplatest
104 | $(SolutionDir)external\build\_deps\ibwincpp-src\include;$(SolutionDir)external\build\_deps\ibeverything-src\include;$(SolutionDir)external\build\_deps\ibpinyin-src\include;$(SolutionDir)external\build\_deps\sigmatch-src\include;$(SolutionDir)external\build\_deps\ibdllhijack-src\include;%(AdditionalIncludeDirectories)
105 |
106 |
107 | Windows
108 | true
109 | false
110 |
111 |
112 |
113 |
114 | Level3
115 | true
116 | true
117 | true
118 | WIN32;NDEBUG;EVERYTHINGEXT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
119 | true
120 | Use
121 | pch.h
122 | stdcpplatest
123 | $(SolutionDir)external\build\_deps\ibwincpp-src\include;$(SolutionDir)external\build\_deps\ibeverything-src\include;$(SolutionDir)external\build\_deps\ibpinyin-src\include;$(SolutionDir)external\build\_deps\sigmatch-src\include;$(SolutionDir)external\build\_deps\ibdllhijack-src\include;%(AdditionalIncludeDirectories)
124 |
125 |
126 | Windows
127 | true
128 | true
129 | true
130 | false
131 | /PDBALTPATH:https://github.com/Chaoses-Ib/IbEverythingExt %(AdditionalOptions)
132 |
133 |
134 |
135 |
136 | Level3
137 | true
138 | IB_DEBUG;_DEBUG;EVERYTHINGEXT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
139 | true
140 | Use
141 | pch.h
142 | stdcpplatest
143 | $(SolutionDir)external\build\_deps\ibwincpp-src\include;$(SolutionDir)external\build\_deps\ibeverything-src\include;$(SolutionDir)external\build\_deps\ibpinyin-src\include;$(SolutionDir)external\build\_deps\sigmatch-src\include;$(SolutionDir)external\build\_deps\ibdllhijack-src\include;%(AdditionalIncludeDirectories)
144 |
145 |
146 | Windows
147 | true
148 | false
149 |
150 |
151 |
152 |
153 | Level3
154 | true
155 | true
156 | true
157 | NDEBUG;EVERYTHINGEXT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
158 | true
159 | Use
160 | pch.h
161 | stdcpplatest
162 | $(SolutionDir)external\build\_deps\ibwincpp-src\include;$(SolutionDir)external\build\_deps\ibeverything-src\include;$(SolutionDir)external\build\_deps\ibpinyin-src\include;$(SolutionDir)external\build\_deps\sigmatch-src\include;$(SolutionDir)external\build\_deps\ibdllhijack-src\include;%(AdditionalIncludeDirectories)
163 |
164 |
165 | Windows
166 | true
167 | true
168 | true
169 | false
170 | /PDBALTPATH:https://github.com/Chaoses-Ib/IbEverythingExt %(AdditionalOptions)
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 | Create
199 | Create
200 | Create
201 | Create
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 | {1dbb8594-6baf-34c0-9998-6aa359588998}
216 |
217 |
218 | {169d9787-0f47-3ee4-9056-c52dfc6e922a}
219 |
220 |
221 | {81a0272a-5ef3-30a8-9154-3a5a8df9aa70}
222 |
223 |
224 |
225 |
226 |
227 |
--------------------------------------------------------------------------------
/EverythingExt/EverythingExt.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Header Files
20 |
21 |
22 | Header Files
23 |
24 |
25 | Header Files
26 |
27 |
28 | Header Files
29 |
30 |
31 | Header Files
32 |
33 |
34 | Header Files
35 |
36 |
37 | Header Files
38 |
39 |
40 | Header Files
41 |
42 |
43 | Header Files
44 |
45 |
46 | Header Files
47 |
48 |
49 | Header Files
50 |
51 |
52 | Header Files
53 |
54 |
55 | Header Files
56 |
57 |
58 | Header Files
59 |
60 |
61 | Header Files
62 |
63 |
64 |
65 |
66 | Source Files
67 |
68 |
69 | Source Files
70 |
71 |
72 | Source Files
73 |
74 |
75 | Source Files
76 |
77 |
78 | Source Files
79 |
80 |
81 | Source Files
82 |
83 |
84 | Source Files
85 |
86 |
87 | Source Files
88 |
89 |
90 | Source Files
91 |
92 |
93 | Source Files
94 |
95 |
96 | Source Files
97 |
98 |
99 | Source Files
100 |
101 |
102 | Source Files
103 |
104 |
105 |
106 |
107 | Resource Files
108 |
109 |
110 |
--------------------------------------------------------------------------------
/EverythingExt/PinyinSearch.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "PinyinSearch.hpp"
3 | #include "PinyinSearchPcre.hpp"
4 | #include "PinyinSearchEdit.hpp"
5 | #include
6 |
7 | std::unique_ptr make_pinyin_search(PinyinSearchMode mode, std::wstring& instance_name, HWND ipc_window) {
8 | switch (mode) {
9 | case PinyinSearchMode::Pcre:
10 | return std::make_unique();
11 | case PinyinSearchMode::Edit:
12 | return std::make_unique(instance_name, ipc_window);
13 | default:
14 | assert(false);
15 | }
16 | }
--------------------------------------------------------------------------------
/EverythingExt/PinyinSearch.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "common.hpp"
3 | #include
4 | #include
5 |
6 | #include
7 | #define IB_PINYIN_ENCODING 32
8 | #include
9 |
10 | enum class PinyinSearchMode {
11 | Pcre,
12 | Edit
13 | };
14 |
15 | class PinyinSearch {
16 | public:
17 | virtual ~PinyinSearch() {}
18 |
19 | virtual void everything_created() {}
20 | virtual void edit_created(HWND edit) {}
21 | };
22 |
23 | // std::runtime_error: current version is not supported
24 | std::unique_ptr make_pinyin_search(PinyinSearchMode mode, std::wstring& instance_name, HWND ipc_window);
--------------------------------------------------------------------------------
/EverythingExt/PinyinSearchEdit.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "PinyinSearchEdit.hpp"
3 | #include
4 | #include
5 | #include "helper.hpp"
6 | #include "pinyin.hpp"
7 | #include "search_history.hpp"
8 | #include "ipc_window.hpp"
9 |
10 | bool is_modifier_in_blacklist(std::wstring_view modifier) {
11 | using namespace std::literals;
12 |
13 | // must be sorted
14 | static constexpr std::wstring_view blacklist[]{
15 | L"attrib:"sv,
16 | L"attributes:"sv,
17 | L"bitdepth:"sv,
18 | L"case:"sv,
19 | L"childcount:"sv,
20 | L"childfilecount:"sv,
21 | L"childfoldercount:"sv,
22 | L"count:"sv,
23 | L"da:"sv,
24 | L"dateaccessed:"sv,
25 | L"datecreated:"sv,
26 | L"datemodified:"sv,
27 | L"daterun:"sv,
28 | L"dc:"sv,
29 | L"dimensions:"sv,
30 | L"dm:"sv,
31 | L"dr:"sv,
32 | L"ext:"sv,
33 | L"frn:"sv,
34 | L"fsi:"sv,
35 | L"height:"sv,
36 | L"len:"sv,
37 | L"orientation:"sv,
38 | L"parents:"sv,
39 | L"rc:"sv,
40 | L"recentchange:"sv,
41 | L"regex:"sv,
42 | L"runcount:"sv,
43 | L"size:"sv,
44 | L"track:"sv,
45 | L"type:"sv,
46 | L"width:"sv
47 | };
48 | return std::ranges::binary_search(blacklist, modifier);
49 | }
50 |
51 | // #TODO: may be buggy, need tests
52 | std::wstring* edit_process_content(const std::wstring& content) {
53 | using namespace std::literals;
54 |
55 | if (content.size() <= 1) { // ignore empty and single-char contents
56 | return new std::wstring(content);
57 | } else if (content.starts_with(L"nopy:"sv)) {
58 | return new std::wstring(content, L"nopy:"sv.size());
59 | }
60 |
61 | std::wistringstream in{ content }; // (content.data(), content.size()) is not what we want
62 | std::wostringstream out;
63 |
64 | bool disabled = false;
65 | struct {
66 | bool py = false;
67 | bool endwith = false;
68 | bool startwith = false;
69 | bool nowholefilename = false;
70 | bool nowildcards = false;
71 | } modifiers;
72 |
73 | auto process_keyword = [&out, &disabled, &modifiers](const std::wstring_view& keyword) {
74 | if (keyword.empty())
75 | disabled = true;
76 | else if (keyword[0] == L'"') {
77 | if (keyword.size() >= 4 && keyword[2] == L':') // '"C:"'
78 | disabled = true;
79 | } else {
80 | if (keyword.size() >= 2 && keyword[1] == L':') // 'C:'
81 | disabled = true;
82 | }
83 |
84 | if (disabled) {
85 | disabled = false;
86 | if (modifiers.startwith)
87 | out << L"startwith:";
88 | if (modifiers.endwith)
89 | out << L"endwith:";
90 | out << keyword;
91 | return;
92 | }
93 |
94 | // check whether wildcards exist
95 | bool wildcards = false;
96 | if (!modifiers.nowildcards) {
97 | bool escape = false;
98 | uint32_t i = 0;
99 | while (!wildcards && i < keyword.size()) {
100 | wchar_t c = keyword[i++];
101 |
102 | if (escape) {
103 | escape = false;
104 | continue;
105 | }
106 |
107 | switch (c) {
108 | case L'\\':
109 | escape = true;
110 | break;
111 | case L'*':
112 | case L'?':
113 | wildcards = true;
114 | break;
115 | }
116 | }
117 | }
118 |
119 | out << L"regex:";
120 |
121 | /*
122 | // keyword must be quoted if you use branch in the group of your regex
123 | bool quoted = keyword[0] == L'"';
124 | if (!quoted)
125 | out << L'"';
126 | */
127 |
128 | if (modifiers.startwith || (wildcards && !modifiers.nowildcards && !modifiers.nowholefilename)) {
129 | out << L'^';
130 | }
131 |
132 | // pinyin output functions
133 | auto output_pinyin_common = [&out, &modifiers](wchar_t cur, std::wstring_view regex) {
134 | out << L'[';
135 | if (!modifiers.py)
136 | out << cur;
137 | out << regex << L']';
138 | };
139 | auto output_pinyin = [&output_pinyin_common](wchar_t cur) {
140 | output_pinyin_common(cur, pinyin_regexs[cur - L'a']);
141 | };
142 | auto output_pinyin_next = [&output_pinyin_common](wchar_t cur, wchar_t next) {
143 | output_pinyin_common(cur, pinyin_pair_regexs[cur - L'a'][next - L'a'].first);
144 | };
145 | auto output_pinyin_last = [&output_pinyin_common](wchar_t last, wchar_t cur) {
146 | output_pinyin_common(cur, pinyin_pair_regexs[last - L'a'][cur - L'a'].second);
147 | };
148 | auto output_pinyin_last_next = [&out, &modifiers](wchar_t last, wchar_t cur, wchar_t next) {
149 | out << L'[';
150 | if (!modifiers.py)
151 | out << cur;
152 |
153 | std::wstring& first = pinyin_pair_regexs[cur - L'a'][next - L'a'].first;
154 | std::wstring& second = pinyin_pair_regexs[last - L'a'][cur - L'a'].second;
155 |
156 | // intersect
157 | uint32_t i = 0;
158 | while (i < first.size()) {
159 | wchar_t c = first[i++];
160 |
161 | Utf16Pair cur;
162 | if (0xD800 <= c && c <= 0xDBFF) {
163 | if (i < first.size())
164 | cur = { c, first[i++] };
165 | else
166 | break;
167 | } else {
168 | cur = { c };
169 | }
170 |
171 | if (cur.in(second)) {
172 | out << cur.l;
173 | if (cur.h)
174 | out << cur.h;
175 | }
176 | }
177 |
178 | out << L']';
179 | };
180 |
181 | wchar_t last = L'\0';
182 | bool escape = false;
183 | uint32_t i = 0;
184 | while (i < keyword.size()) {
185 | wchar_t c = keyword[i++];
186 |
187 | if (escape) {
188 | escape = false;
189 |
190 | // only \! is escaped
191 | if (c == L'!') {
192 | out << c;
193 | continue;
194 | }
195 | out << L'\\';
196 | }
197 | if (L'a' <= c && c <= L'z') { // only process lowercase letters
198 | wchar_t next = L'\0';
199 | if (i < keyword.size()) {
200 | next = keyword[i];
201 | if (!(L'a' <= next && next <= L'z'))
202 | next = L'\0';
203 | }
204 |
205 | if (next) {
206 | if (last)
207 | output_pinyin_last_next(last, c, next);
208 | else
209 | output_pinyin_next(c, next);
210 | } else {
211 | if (last)
212 | output_pinyin_last(last, c);
213 | else
214 | output_pinyin(c);
215 | }
216 | last = c;
217 | } else if (L'A' <= c && c <= L'Z') {
218 | last = static_cast(c - 'A' + 'a');
219 | out << c;
220 | } else {
221 | switch (c) {
222 | case L'\\':
223 | escape = true;
224 | out << c;
225 | break;
226 |
227 | // escape regex chars
228 | case L'.':
229 | case L'[':
230 | case L']':
231 | case L'^':
232 | case L'$':
233 | case L'+':
234 | case L'{':
235 | case L'}':
236 | case L'(':
237 | case L')':
238 | out << L'\\' << c;
239 | break;
240 |
241 | // wildcards to regex
242 | case L'*':
243 | if (!modifiers.nowildcards)
244 | out << L".*";
245 | else
246 | out << L'\\' << c;
247 | break;
248 | case L'?':
249 | if (!modifiers.nowildcards)
250 | out << L".";
251 | else
252 | out << L'\\' << c;
253 | break;
254 |
255 | default:
256 | out << c;
257 | }
258 |
259 | last = L'\0';
260 | }
261 | }
262 | if (escape) //R"(abc\)"
263 | out << L'\\';
264 |
265 | if (modifiers.endwith || (wildcards && !modifiers.nowildcards && !modifiers.nowholefilename)) {
266 | out << L'$';
267 | }
268 |
269 | /*
270 | if (!quoted)
271 | out << L'"';
272 | */
273 | };
274 |
275 | wchar_t c;
276 | bool in_quotes = false;
277 | std::wistringstream::pos_type last_colon_next{};
278 | while (in.get(c)) {
279 | switch (c) {
280 | case L'"':
281 | in_quotes = !in_quotes;
282 | break;
283 | case L':':
284 | if (!in_quotes) {
285 | // modifier/function
286 |
287 | auto colon_next = in.tellg();
288 | size_t size = colon_next - last_colon_next;
289 | if (size <= 2) // "C:"
290 | break;
291 | std::wstring modifier(size, L'\0');
292 | in.seekg(last_colon_next);
293 | in.read(modifier.data(), size);
294 | last_colon_next = colon_next;
295 |
296 | if (disabled || is_modifier_in_blacklist(modifier)) {
297 | disabled = true;
298 | out << modifier;
299 | } else if (modifier == L"py:"sv || modifier == L"endwith:"sv || modifier == L"startwith:"sv) {
300 | if (modifier == L"py:"sv)
301 | modifiers.py = true;
302 | else if (modifier == L"endwith:"sv)
303 | modifiers.endwith = true;
304 | else if (modifier == L"startwith:"sv)
305 | modifiers.startwith = true;
306 | // remove (these modifiers will be implemented with regex)
307 | } else {
308 | if (modifier == L"nowholefilename:"sv)
309 | modifiers.nowholefilename = true;
310 | else if (modifier == L"nowildcards:"sv)
311 | modifiers.nowildcards = true;
312 | out << modifier;
313 | }
314 | }
315 | break;
316 | case L'!':
317 | if (in.tellg() == last_colon_next + std::streamoff(1)) {
318 | out << c;
319 | last_colon_next += 1;
320 | }
321 | break;
322 | case L' ':
323 | if (!in_quotes) {
324 | // keyword
325 |
326 | size_t size = in.tellg() - last_colon_next - 1;
327 | std::wstring keyword(size, L'\0');
328 | if (size) {
329 | in.seekg(last_colon_next);
330 | in.read(keyword.data(), size);
331 | in.ignore(); // ignore L' '
332 | }
333 |
334 | process_keyword(keyword);
335 | out << L' ';
336 |
337 | modifiers = {};
338 | last_colon_next = in.tellg();
339 | }
340 | break;
341 | }
342 | }
343 | // stream EOF
344 | in.clear();
345 |
346 | size_t size = in.tellg() - last_colon_next;
347 | std::wstring keyword(size, L'\0');
348 | in.seekg(last_colon_next);
349 | in.read(keyword.data(), size);
350 |
351 | process_keyword(keyword);
352 |
353 | // return the result
354 | if constexpr (debug)
355 | DebugOStream() << content << L" -> " << out.str() << std::endl;
356 | return new std::wstring(out.str());
357 | }
358 |
359 | constexpr wchar_t prop_main_title[] = L"IbEverythingExt.Title";
360 | constexpr wchar_t prop_edit_content[] = L"IbEverythingExt.Content";
361 | constexpr wchar_t prop_edit_processed_content[] = L"IbEverythingExt.ProcessedContent";
362 |
363 | std::wstring title_suffix = L" - Everything";
364 | std::unordered_map content_map{};
365 |
366 | WNDPROC edit_window_proc_0;
367 | LRESULT CALLBACK edit_window_proc_1(
368 | _In_ HWND hwnd,
369 | _In_ UINT uMsg,
370 | _In_ WPARAM wParam,
371 | _In_ LPARAM lParam)
372 | {
373 | switch (uMsg) {
374 | case WM_GETTEXTLENGTH:
375 | {
376 | if constexpr (debug)
377 | DebugOStream() << L"WM_GETTEXTLENGTH\n";
378 |
379 | // retrieve the content
380 | LRESULT result = CallWindowProcW(edit_window_proc_0, hwnd, uMsg, wParam, lParam);
381 | wchar_t* buf = new wchar_t[result + 1 + title_suffix.size()]; // for both the content and the title
382 | LRESULT content_len = CallWindowProcW(edit_window_proc_0, hwnd, WM_GETTEXT, result + 1, (LPARAM)buf);
383 |
384 | // save the content
385 | auto content = (std::wstring*)GetPropW(hwnd, prop_edit_content);
386 | auto processed_content = (std::wstring*)GetPropW(hwnd, prop_edit_processed_content);
387 | if (content && *content == std::wstring_view(buf, content_len)) {
388 | delete[] buf;
389 | return processed_content->size();
390 | }
391 | delete content;
392 | delete processed_content;
393 | content = new std::wstring(buf, content_len);
394 | SetPropW(hwnd, prop_edit_content, content);
395 |
396 | // process the content
397 | processed_content = edit_process_content(*content);
398 | SetPropW(hwnd, prop_edit_processed_content, processed_content);
399 |
400 | // make the title
401 | if (content_len)
402 | std::copy_n(title_suffix.c_str(), title_suffix.size() + 1, buf + content_len);
403 | else
404 | std::copy_n(title_suffix.c_str() + std::size(L" - ") - 1, title_suffix.size() + 1 - (std::size(L" - ") - 1), buf);
405 |
406 | // save the title
407 | HWND main = GetAncestor(hwnd, GA_ROOT);
408 | delete[] (wchar_t*)GetPropW(main, prop_main_title);
409 | SetPropW(main, prop_main_title, buf);
410 |
411 | return processed_content->size();
412 | }
413 | break;
414 | case WM_GETTEXT:
415 | {
416 | if constexpr (debug)
417 | DebugOStream() << L"WM_GETTEXT\n";
418 |
419 | if (auto processed_content = (std::wstring*)GetPropW(hwnd, prop_edit_processed_content)) {
420 | LRESULT n = min(processed_content->size() + 1, wParam);
421 | std::copy_n(processed_content->c_str(), n, (wchar_t*)lParam);
422 | return n - 1;
423 | }
424 | }
425 | break;
426 | case WM_KILLFOCUS:
427 | {
428 | if constexpr (debug)
429 | DebugOStream() << L"WM_KILLFOCUS\n";
430 |
431 | // save the content to map
432 | if (auto content = (std::wstring*)GetPropW(hwnd, prop_edit_content)) {
433 | auto processed_content = (std::wstring*)GetPropW(hwnd, prop_edit_processed_content);
434 | content_map[*processed_content] = *content;
435 | }
436 | }
437 | break;
438 | }
439 | return CallWindowProcW(edit_window_proc_0, hwnd, uMsg, wParam, lParam);
440 | }
441 |
442 | /*
443 | WNDPROC edit_window_proc_2;
444 | LRESULT CALLBACK edit_window_proc_3(
445 | _In_ HWND hwnd,
446 | _In_ UINT uMsg,
447 | _In_ WPARAM wParam,
448 | _In_ LPARAM lParam)
449 | {
450 | switch (uMsg) {
451 | case WM_KEYDOWN:
452 | case WM_SYSKEYDOWN:
453 | if constexpr (debug)
454 | DebugOStream() << (uMsg == WM_KEYDOWN ? L"WM_KEYDOWN: " : L"WM_SYSKEYDOWN: ") << wParam << L'\n';
455 | break;
456 | }
457 | return CallWindowProcW(edit_window_proc_2, hwnd, uMsg, wParam, lParam);
458 | }
459 | */
460 |
461 | extern std::wstring class_everything;
462 |
463 | auto SetWindowTextW_real = SetWindowTextW;
464 | BOOL WINAPI SetWindowTextW_detour(
465 | _In_ HWND hWnd,
466 | _In_opt_ LPCWSTR lpString)
467 | {
468 | using namespace std::literals;
469 |
470 | wchar_t buf[256];
471 | if (int len = GetClassNameW(hWnd, buf, std::size(buf))) {
472 | std::wstring_view sv(buf, len);
473 |
474 | if (sv == class_everything) {
475 | // set the title
476 | if (auto title = (const wchar_t*)GetPropW(hWnd, prop_main_title)) {
477 | SetWindowTextW_real(hWnd, title);
478 | return true;
479 | }
480 | } else if (sv == L"Edit"sv) {
481 | auto processed_content = (std::wstring*)GetPropW(hWnd, prop_edit_processed_content);
482 | if (processed_content && *processed_content == lpString) {
483 | // prevent modifying edit
484 | return true;
485 | }
486 |
487 | auto iter = content_map.find(lpString);
488 | if (iter != content_map.end())
489 | return SetWindowTextW_real(hWnd, iter->second.c_str());
490 | }
491 | }
492 | return SetWindowTextW_real(hWnd, lpString);
493 | }
494 |
495 | PinyinSearchEdit::PinyinSearchEdit(const std::wstring& instance_name, HWND ipc_window) {
496 | using namespace std::literals;
497 |
498 | std::thread t(pinyin_query_and_merge);
499 | t.detach();
500 |
501 | title_suffix += L" ("sv;
502 | if (!instance_name.empty()) {
503 | title_suffix += instance_name;
504 | title_suffix += L", "sv;
505 | }
506 | title_suffix += L"Edit 模式)"sv;
507 |
508 | IbDetourAttach(&SetWindowTextW_real, SetWindowTextW_detour);
509 |
510 | search_history_init();
511 |
512 | ipc_window_init(ipc_window);
513 | }
514 |
515 | PinyinSearchEdit::~PinyinSearchEdit() {
516 | ipc_window_destroy();
517 |
518 | search_history_destroy();
519 |
520 | IbDetourDetach(&SetWindowTextW_real, SetWindowTextW_detour);
521 | }
522 |
523 | void PinyinSearchEdit::everything_created() {
524 | std::thread t(pinyin_query_and_merge);
525 | t.detach();
526 | }
527 |
528 | void PinyinSearchEdit::edit_created(HWND edit) {
529 | edit_window_proc_0 = (WNDPROC)SetWindowLongPtrW(edit, GWLP_WNDPROC, (LONG_PTR)edit_window_proc_1);
530 | }
--------------------------------------------------------------------------------
/EverythingExt/PinyinSearchEdit.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "PinyinSearch.hpp"
3 |
4 | class PinyinSearchEdit : public PinyinSearch {
5 | public:
6 | PinyinSearchEdit(const std::wstring& instance_name, HWND ipc_window);
7 | ~PinyinSearchEdit() override;
8 |
9 | void everything_created() override;
10 | void edit_created(HWND edit) override;
11 | };
--------------------------------------------------------------------------------
/EverythingExt/PinyinSearchPcre.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include "PinyinSearch.hpp"
4 |
5 | class PinyinSearchPcre : public PinyinSearch {
6 | public:
7 | // throw std::runtime_error for unsupported Everything version
8 | PinyinSearchPcre();
9 | ~PinyinSearchPcre() override;
10 | };
--------------------------------------------------------------------------------
/EverythingExt/common.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
--------------------------------------------------------------------------------
/EverythingExt/config.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "common.hpp"
3 | #include "config.hpp"
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #pragma comment(lib, "Shlwapi.lib")
10 |
11 | Config config{};
12 |
13 | std::wstring u8_to_u16(const std::string& u8) {
14 | std::wstring u16;
15 | u16.resize(MultiByteToWideChar(CP_UTF8, 0, u8.c_str(), u8.size(), nullptr, 0));
16 | MultiByteToWideChar(CP_UTF8, 0, u8.c_str(), u8.size(), u16.data(), u16.size());
17 | return u16;
18 | }
19 |
20 | bool config_init() {
21 | using namespace std::literals;
22 |
23 | config.enable = false;
24 |
25 | wchar_t root_path[MAX_PATH];
26 | GetModuleFileNameW(nullptr, root_path, std::size(root_path));
27 | PathRemoveFileSpecW(root_path);
28 | PathAppendW(root_path, LR"(IbEverythingExt\)");
29 |
30 | wchar_t config_path[MAX_PATH];
31 | wcscpy_s(config_path, root_path);
32 | PathAppendW(config_path, LR"(config.yaml)");
33 |
34 | std::ifstream in(config_path);
35 | if (!in) {
36 | MessageBoxW(nullptr, L"配置文件 config.yaml 不存在!", L"IbEverythingExt", MB_ICONERROR);
37 | return false;
38 | }
39 | try {
40 | YAML::Node root = YAML::Load(in);
41 |
42 | {
43 | YAML::Node node = root["pinyin_search"];
44 | config.pinyin_search = {
45 | .enable = node["enable"].as(),
46 | .mode = [&node] {
47 | auto mode = node["mode"].as();
48 | if (mode == "Pcre")
49 | return PinyinSearchMode::Pcre;
50 | else if (mode == "Edit")
51 | return PinyinSearchMode::Edit;
52 | throw YAML::Exception(YAML::Mark::null_mark(), "Invalid pinyin_search.mode");
53 | }(),
54 | .flags = [&node] {
55 | std::vector flags;
56 |
57 | // mind the order
58 | if (node["pinyin_ascii_digit"].as())
59 | flags.push_back(pinyin::PinyinFlag::PinyinAsciiDigit);
60 | if (node["pinyin_ascii"].as())
61 | flags.push_back(pinyin::PinyinFlag::PinyinAscii);
62 | if (node["double_pinyin_abc"].as())
63 | flags.push_back(pinyin::PinyinFlag::DoublePinyinAbc);
64 | if (node["double_pinyin_jiajia"].as())
65 | flags.push_back(pinyin::PinyinFlag::DoublePinyinJiajia);
66 | if (node["double_pinyin_microsoft"].as())
67 | flags.push_back(pinyin::PinyinFlag::DoublePinyinMicrosoft);
68 | if (node["double_pinyin_thunisoft"].as())
69 | flags.push_back(pinyin::PinyinFlag::DoublePinyinThunisoft);
70 | if (node["double_pinyin_xiaohe"].as())
71 | flags.push_back(pinyin::PinyinFlag::DoublePinyinXiaohe);
72 | if (node["double_pinyin_zrm"].as())
73 | flags.push_back(pinyin::PinyinFlag::DoublePinyinZrm);
74 | if (node["initial_letter"].as())
75 | flags.push_back(pinyin::PinyinFlag::InitialLetter);
76 | return flags;
77 | }()
78 | };
79 | }
80 |
81 | {
82 | YAML::Node node = root["quick_select"];
83 | config.quick_select = {
84 | .enable = node["enable"].as(),
85 |
86 | .search_edit = [](const YAML::Node& node) {
87 | return decltype(config.quick_select.search_edit) {
88 | .alt = node["alt"].as()
89 | };
90 | }(node["search_edit"]),
91 |
92 | .result_list = [](const YAML::Node& node) {
93 | decltype(config.quick_select.result_list) result_list {
94 | .select = node["select"].as(),
95 | .alt = node["alt"].as()
96 | };
97 | std::wstring terminal = u8_to_u16(node["terminal"].as());
98 | if (terminal.size()) {
99 | std::wregex reg(LR"__((?:"([^"]*)"|([^ ]*)) ?(.*))__");
100 | std::wsmatch match;
101 | std::regex_match(terminal, match, reg);
102 | result_list.terminal_file = match[1].str() + match[2].str();
103 | result_list.terminal_parameter = match[3].str();
104 | }
105 | return result_list;
106 | }(node["result_list"]),
107 |
108 | .close_everything = node["close_everything"].as(),
109 |
110 | .input_mode = [&node] {
111 | auto mode = node["input_mode"].as();
112 | if (mode == "Auto")
113 | return quick::InputMode::Auto;
114 | else if (mode == "WmKey")
115 | return quick::InputMode::WmKey;
116 | else if (mode == "SendInput")
117 | return quick::InputMode::SendInput;
118 | throw YAML::Exception(YAML::Mark::null_mark(), "Invalid quick_select.input_mode");
119 | }()
120 | };
121 | }
122 |
123 | if (config.update.check = root["update"]["check"].as()) {
124 | wchar_t update_path[MAX_PATH];
125 | wcscpy_s(update_path, root_path);
126 | PathAppendW(update_path, L"Updater.exe");
127 | config.update.update_path = update_path;
128 |
129 | // to avoid checking on system startup and when calling Everything through command line,
130 | // we do the check after the main window is created
131 | }
132 | }
133 | catch (YAML::Exception& e) {
134 | MessageBoxA(nullptr, ("配置文件读取错误:\n"s + e.what()).c_str(), "IbEverythingExt", MB_ICONERROR);
135 | return false;
136 | }
137 |
138 | pinyin::PinyinFlagValue flags{};
139 | for (pinyin::PinyinFlagValue flag : config.pinyin_search.flags)
140 | flags |= flag;
141 | pinyin::init(flags);
142 |
143 | config.enable = true;
144 | return true;
145 | }
146 |
147 | void config_destroy() {
148 | pinyin::destroy();
149 | }
--------------------------------------------------------------------------------
/EverythingExt/config.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "PinyinSearch.hpp"
3 | #include "quick_select.hpp"
4 |
5 | struct Config {
6 | // set to false when config_init fails
7 | bool enable;
8 |
9 | struct {
10 | bool enable;
11 | PinyinSearchMode mode;
12 | std::vector flags;
13 | } pinyin_search;
14 |
15 | struct {
16 | bool enable;
17 |
18 | struct {
19 | uint8_t alt;
20 | } search_edit;
21 |
22 | struct {
23 | bool select;
24 | uint8_t alt;
25 | std::wstring terminal_file;
26 | std::wstring terminal_parameter;
27 | } result_list;
28 |
29 | bool close_everything;
30 |
31 | quick::InputMode input_mode;
32 | } quick_select;
33 |
34 | struct {
35 | bool check;
36 | std::wstring update_path;
37 | } update;
38 | };
39 | extern Config config;
40 |
41 | bool config_init();
42 | void config_destroy();
--------------------------------------------------------------------------------
/EverythingExt/dllmain.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "common.hpp"
3 | #include "helper.hpp"
4 | #include "config.hpp"
5 | #include "ipc.hpp"
6 | #include "PinyinSearch.hpp"
7 | #include "quick_select.hpp"
8 |
9 | std::wstring instance_name{};
10 | std::wstring class_everything = L"EVERYTHING";
11 |
12 | std::unique_ptr pinyin_search;
13 |
14 | /*
15 | WNDPROC list_window_proc_0;
16 | LRESULT CALLBACK list_window_proc_1(
17 | _In_ HWND hwnd,
18 | _In_ UINT uMsg,
19 | _In_ WPARAM wParam,
20 | _In_ LPARAM lParam)
21 | {
22 | switch (uMsg) {
23 | }
24 | return CallWindowProcW(list_window_proc_0, hwnd, uMsg, wParam, lParam);
25 | }
26 | */
27 |
28 | WNDPROC list_window_proc_2;
29 | LRESULT CALLBACK list_window_proc_3(
30 | _In_ HWND hwnd,
31 | _In_ UINT uMsg,
32 | _In_ WPARAM wParam,
33 | _In_ LPARAM lParam)
34 | {
35 | return quick::list_window_proc(list_window_proc_2, hwnd, uMsg, wParam, lParam);
36 | }
37 |
38 | auto SetWindowLongPtrW_real = SetWindowLongPtrW;
39 | LONG_PTR WINAPI SetWindowLongPtrW_detour(
40 | _In_ HWND hWnd,
41 | _In_ int nIndex,
42 | _In_ LONG_PTR dwNewLong)
43 | {
44 | using namespace std::literals;
45 |
46 | if (nIndex == GWLP_WNDPROC) {
47 | wchar_t buf[256];
48 | if (int len = GetClassNameW(hWnd, buf, std::size(buf))) {
49 | std::wstring_view class_name(buf, len);
50 | /*
51 | if (class_name == L"Edit"sv) {
52 | if (int len = GetClassNameW(GetParent(hWnd), buf, std::size(buf));
53 | std::wstring_view(buf, len) == L"EVERYTHING_TOOLBAR"sv)
54 | {
55 | edit_window_proc_0 = (WNDPROC)SetWindowLongPtrW_real(hWnd, nIndex, (LONG_PTR)edit_window_proc_3);
56 | edit_window_proc_2 = (WNDPROC)dwNewLong;
57 | return (LONG_PTR)edit_window_proc_1;
58 | }
59 | }
60 | */
61 | if (class_name == L"SysListView32"sv) {
62 | if (int len = GetClassNameW(GetParent(hWnd), buf, std::size(buf));
63 | std::wstring_view(buf, len) == class_everything)
64 | {
65 | // the caller could be Everything.exe or comctl32.dll
66 | HMODULE module, everything;
67 | GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCWSTR)_ReturnAddress(), &module);
68 | GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, nullptr, &everything);
69 | if (module == everything) {
70 | /*
71 | list_window_proc_0 = (WNDPROC)SetWindowLongPtrW_real(hWnd, nIndex, (LONG_PTR)list_window_proc_3);
72 | list_window_proc_2 = (WNDPROC)dwNewLong;
73 | return (LONG_PTR)list_window_proc_1;
74 | */
75 | list_window_proc_2 = (WNDPROC)dwNewLong;
76 | return (LONG_PTR)SetWindowLongPtrW_real(hWnd, nIndex, (LONG_PTR)list_window_proc_3);
77 | }
78 | }
79 | }
80 | }
81 | }
82 | return SetWindowLongPtrW_real(hWnd, nIndex, dwNewLong);
83 | }
84 |
85 | auto CreateWindowExW_real = CreateWindowExW;
86 | HWND WINAPI CreateWindowExW_detour(
87 | _In_ DWORD dwExStyle,
88 | _In_opt_ LPCWSTR lpClassName,
89 | _In_opt_ LPCWSTR lpWindowName,
90 | _In_ DWORD dwStyle,
91 | _In_ int X,
92 | _In_ int Y,
93 | _In_ int nWidth,
94 | _In_ int nHeight,
95 | _In_opt_ HWND hWndParent,
96 | _In_opt_ HMENU hMenu,
97 | _In_opt_ HINSTANCE hInstance,
98 | _In_opt_ LPVOID lpParam)
99 | {
100 | using namespace std::literals;
101 |
102 | // EVERYTHING
103 | // EVERYTHING_TOOLBAR
104 | // Edit
105 | // SysListView32
106 | // msctls_statusbar32
107 | // ComboBox
108 | // EVERYTHING_PREVIEW
109 |
110 | HWND wnd = CreateWindowExW_real(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
111 |
112 | if ((uintptr_t)lpClassName > 0xFFFF) {
113 | std::wstring_view class_name(lpClassName);
114 | if constexpr (debug)
115 | DebugOStream() << class_name << L", parent: " << hWndParent << L'\n';
116 |
117 | // named instances
118 | if (class_name.ends_with(L')') && instance_name.empty()) {
119 | size_t n = class_name.find(L"_("sv);
120 | if (n != class_name.npos) {
121 | size_t begin = n + std::size(L"_("sv);
122 | instance_name = class_name.substr(begin, class_name.size() - 1 - begin);
123 |
124 | class_everything += class_name.substr(n);
125 | }
126 | }
127 |
128 | if (class_name == class_everything) {
129 | if (config.pinyin_search.enable)
130 | pinyin_search->everything_created();
131 |
132 | if (config.update.check) {
133 | // We only want to check for updates when the main window is (first) displayed.
134 | // However:
135 | // * `Everything64.exe` will create a window without WS_VISIBLE
136 | // * `-startup` will not create a window **but with some unknown exceptions**
137 | // * `-minimized` will create the same window as `(empty)`
138 | // To solve this, we use a simple trick - only check for updates when the main window is created at the second time.
139 |
140 | static bool created = false;
141 | if (created) {
142 | wchar_t cmd_line[] = L"--quiet";
143 | STARTUPINFOW startup_info{ sizeof STARTUPINFOW };
144 | PROCESS_INFORMATION process_info{};
145 |
146 | if (CreateProcessW(config.update.update_path.c_str(), cmd_line, nullptr, nullptr, false, 0, nullptr, nullptr, &startup_info, &process_info)) {
147 | CloseHandle(process_info.hThread);
148 | CloseHandle(process_info.hProcess);
149 | }
150 |
151 | // only check once
152 | config.update.check = false;
153 | config.update.update_path = {};
154 | }
155 | created = true;
156 | }
157 | } else if (class_name == L"Edit"sv) {
158 | if (config.pinyin_search.enable) {
159 | wchar_t buf[std::size(L"EVERYTHING_TOOLBAR")];
160 | if (int len = GetClassNameW(hWndParent, buf, std::size(buf))) {
161 | if (std::wstring_view(buf, len) == L"EVERYTHING_TOOLBAR"sv) {
162 | pinyin_search->edit_created(wnd);
163 | }
164 | }
165 | }
166 | } else if (class_name == L"SysListView32"sv) {
167 | if (config.quick_select.enable) {
168 | wchar_t buf[256];
169 | if (int len = GetClassNameW(hWndParent, buf, std::size(buf))) {
170 | if (std::wstring_view(buf, len) == class_everything) {
171 | // find Edit
172 | HWND toolbar = FindWindowExW(hWndParent, nullptr, L"EVERYTHING_TOOLBAR", nullptr);
173 | HWND edit = FindWindowExW(toolbar, nullptr, L"Edit", nullptr);
174 |
175 | // create quick list
176 | // X == Y == nWidth == nHeight == 0
177 | HWND quick_list = quick::create_quick_list(hWndParent, wnd, edit, hInstance);
178 | }
179 | }
180 | }
181 | } else if (class_name.starts_with(L"EVERYTHING_TASKBAR_NOTIFICATION"sv)) {
182 | ipc_init(instance_name);
183 |
184 | if (config.pinyin_search.enable) {
185 | try {
186 | pinyin_search = make_pinyin_search(config.pinyin_search.mode, instance_name, wnd);
187 | }
188 | catch (std::runtime_error& e) {
189 | config.pinyin_search.enable = false;
190 | MessageBoxW(0, L"拼音搜索 PCRE 模式不支持当前 Everything 版本,请更换至受支持的版本或禁用拼音搜索", L"IbEverythingExt", MB_ICONERROR);
191 | }
192 | }
193 |
194 | if (config.quick_select.enable)
195 | quick::init();
196 | }
197 | }
198 | return wnd;
199 | }
200 |
201 | /*
202 | BOOL CALLBACK enum_window_proc(
203 | _In_ HWND hwnd,
204 | _In_ LPARAM lParam)
205 | {
206 | using namespace std::literals;
207 |
208 | if (GetWindowThreadProcessId(hwnd, nullptr) == static_cast(lParam)) {
209 | // hwnd may be a window other than EVERYTHING, such as "#32770 (Dialog)" (Everything Options).
210 | wchar_t buf[std::size(L"EVERYTHING")];
211 | if (int len = GetClassNameW(hwnd, buf, std::size(buf))) {
212 | if (std::wstring_view(buf, len) == L"EVERYTHING"sv) {
213 | if (HWND toolbar = FindWindowExW(hwnd, 0, L"EVERYTHING_TOOLBAR", nullptr))
214 | if (HWND edit = FindWindowExW(toolbar, 0, L"Edit", nullptr))
215 | edit_window_proc_0 = (WNDPROC)SetWindowLongPtrW(edit, GWLP_WNDPROC, (LONG_PTR)edit_window_proc_1);
216 | }
217 | }
218 | }
219 |
220 | return true;
221 | }
222 | */
223 |
224 | #include
225 |
226 | BOOL APIENTRY DllMain( HMODULE hModule,
227 | DWORD ul_reason_for_call,
228 | LPVOID lpReserved
229 | )
230 | {
231 | switch (ul_reason_for_call)
232 | {
233 | case DLL_PROCESS_ATTACH:
234 | if constexpr (debug)
235 | DebugOStream() << L"DLL_PROCESS_ATTACH\n";
236 |
237 | if (!config_init())
238 | break;
239 |
240 | IbDetourAttach(&CreateWindowExW_real, CreateWindowExW_detour);
241 | if (config.quick_select.enable)
242 | IbDetourAttach(&SetWindowLongPtrW_real, SetWindowLongPtrW_detour);
243 |
244 | // may be loaded after creating windows? it seems that only netutil.dll does
245 | //EnumWindows(enum_window_proc, GetCurrentThreadId());
246 | break;
247 | case DLL_THREAD_ATTACH:
248 | break;
249 | case DLL_THREAD_DETACH:
250 | break;
251 | case DLL_PROCESS_DETACH:
252 | if constexpr (debug)
253 | DebugOStream() << L"DLL_PROCESS_DETACH\n";
254 |
255 | if (!config.enable)
256 | break;
257 |
258 | if (config.quick_select.enable)
259 | quick::destroy();
260 | if (config.pinyin_search.enable)
261 | pinyin_search.reset();
262 |
263 | ipc_destroy();
264 |
265 | if (config.quick_select.enable)
266 | IbDetourDetach(&SetWindowLongPtrW_real, SetWindowLongPtrW_detour);
267 | IbDetourDetach(&CreateWindowExW_real, CreateWindowExW_detour);
268 |
269 | config_destroy();
270 | break;
271 | }
272 | return TRUE;
273 | }
--------------------------------------------------------------------------------
/EverythingExt/framework.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | //#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
4 | // Windows Header Files
5 | #include
6 |
--------------------------------------------------------------------------------
/EverythingExt/helper.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "helper.hpp"
3 |
4 | namespace ib {
5 | char8_t toupper(char8_t c) {
6 | // toupper_gen.py
7 | static char8_t table[] = {
8 | 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
9 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
10 | 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
11 | 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
12 | 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
13 | 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
14 | 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
15 | 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
16 | 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
17 | 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
18 | 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
19 | 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
20 | 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
21 | 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
22 | 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
23 | 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
24 | };
25 | return table[c];
26 | }
27 | }
--------------------------------------------------------------------------------
/EverythingExt/helper.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 |
5 | constexpr bool debug =
6 | #ifdef IB_DEBUG
7 | 1;
8 | #else
9 | 0;
10 | #endif
11 |
12 | constexpr bool debug_verbose =
13 | #ifdef IB_DEBUG_VERBOSE
14 | 1;
15 | #else
16 | 0;
17 | #endif
18 |
19 | inline ib::DebugOStream<> DebugOStream() {
20 | return ib::DebugOStream(L"IbEverythingExt: ");
21 | }
22 |
23 | template
24 | LONG IbDetourAttach(_Inout_ T* ppPointer, _In_ T pDetour) {
25 | DetourTransactionBegin();
26 | DetourUpdateThread(GetCurrentThread());
27 | DetourAttach((void**)ppPointer, pDetour);
28 | return DetourTransactionCommit();
29 | }
30 |
31 | template
32 | LONG IbDetourDetach(_Inout_ T* ppPointer, _In_ T pDetour) {
33 | DetourTransactionBegin();
34 | DetourUpdateThread(GetCurrentThread());
35 | DetourDetach((void**)ppPointer, pDetour);
36 | return DetourTransactionCommit();
37 | }
38 |
39 | namespace ib {
40 | // MSVC's implementation has lower performance since it doesn't use a map
41 | // (_mbbtoupper uses a map, but it's a two-way case map and therefore needs a check).
42 | char8_t toupper(char8_t c);
43 | }
--------------------------------------------------------------------------------
/EverythingExt/ipc.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "ipc.hpp"
3 | #include "helper.hpp"
4 |
5 | ib::Holder ipc_ev;
6 | Everythings::EverythingMT::Version ipc_version;
7 |
8 | void ipc_init(std::wstring_view instance_name) {
9 | ipc_ev.create(instance_name);
10 | ipc_version = ipc_ev->get_version();
11 | }
12 |
13 | void ipc_destroy() {
14 | ipc_ev.destroy();
15 | }
--------------------------------------------------------------------------------
/EverythingExt/ipc.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | extern ib::Holder ipc_ev;
5 | extern Everythings::EverythingMT::Version ipc_version;
6 |
7 | void ipc_init(std::wstring_view instance_name);
8 | void ipc_destroy();
--------------------------------------------------------------------------------
/EverythingExt/ipc_window.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "ipc_window.hpp"
3 | #include
4 | #include "helper.hpp"
5 |
6 | extern std::wstring* edit_process_content(const std::wstring& content);
7 |
8 | #pragma pack(push, 1)
9 | template
10 | struct EVERYTHING_IPC_QUERY2 {
11 | // something wrong with MSVC
12 | //using namespace Everythings;
13 |
14 | DWORD reply_hwnd; // !: not sizeof(HWND)
15 | DWORD reply_copydata_message;
16 | Everythings::SearchFlags search_flags;
17 | DWORD offset;
18 | DWORD max_results;
19 | Everythings::RequestFlags request_flags;
20 | Everythings::Sort sort_type;
21 | CharT search_string[1]; // '\0'
22 |
23 | static size_t query_size() {
24 | return sizeof(EVERYTHING_IPC_QUERY2) - sizeof(CharT);
25 | }
26 | };
27 |
28 | template
29 | struct EVERYTHING_IPC_QUERY {
30 | // something wrong with MSVC
31 | //using namespace Everythings;
32 |
33 | DWORD reply_hwnd; // !: not sizeof(HWND)
34 | DWORD reply_copydata_message;
35 | Everythings::SearchFlags search_flags;
36 | DWORD offset;
37 | DWORD max_results;
38 | CharT search_string[1]; // '\0'
39 |
40 | static size_t query_size() {
41 | return sizeof(EVERYTHING_IPC_QUERY) - sizeof(CharT);
42 | }
43 | };
44 | #pragma pack(pop)
45 |
46 | WNDPROC ipc_window_proc_prev;
47 | LRESULT CALLBACK ipc_window_proc(
48 | _In_ HWND hwnd,
49 | _In_ UINT uMsg,
50 | _In_ WPARAM wParam,
51 | _In_ LPARAM lParam)
52 | {
53 | using namespace Everythings;
54 |
55 | switch (uMsg) {
56 | case WM_COPYDATA:
57 | {
58 | if constexpr (debug)
59 | DebugOStream() << L"WM_COPYDATA\n";
60 | if (!wParam)
61 | break;
62 |
63 | bool known = false;
64 |
65 | static DWORD last_pid = 0; // window will be different every time when using the official SDK
66 | static bool last_known = false;
67 | DWORD pid;
68 | GetWindowThreadProcessId((HWND)wParam, &pid);
69 | if (pid == last_pid)
70 | known = last_known;
71 | else {
72 | HANDLE process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, pid);
73 |
74 | wchar_t path_buf[MAX_PATH];
75 | DWORD size = std::size(path_buf);
76 | QueryFullProcessImageNameW(process, 0, path_buf, &size);
77 | std::wstring_view path(path_buf, size);
78 | if constexpr (debug)
79 | DebugOStream() << path << L'\n';
80 |
81 | if (path.ends_with(L"\\explorer.exe")) // stnkl/EverythingToolbar
82 | known = true;
83 | else if (path.ends_with(L"\\Flow.Launcher.exe")) // Flow Launcher
84 | known = true;
85 | else if (path.ends_with(L"\\HuoChat.exe")) // HuoChat
86 | known = true;
87 | else if (path.ends_with(L"\\uTools.exe")) // uTools
88 | known = true;
89 | else if (path.ends_with(L"\\Wox.exe")) // Wox
90 | known = true;
91 |
92 | CloseHandle(process);
93 |
94 | last_pid = pid;
95 | last_known = known;
96 | }
97 | if (!known)
98 | break;
99 |
100 | constexpr uintptr_t EVERYTHING_IPC_COPYDATAQUERYA = 1;
101 | constexpr uintptr_t EVERYTHING_IPC_COPYDATAQUERYW = 2;
102 | constexpr uintptr_t EVERYTHING_IPC_COPYDATA_QUERY2A = 17;
103 | constexpr uintptr_t EVERYTHING_IPC_COPYDATA_QUERY2W = 18;
104 | auto common_process = [hwnd, uMsg, wParam](uintptr_t command, uint8_t* query, size_t query_size, std::wstring_view search) {
105 | std::unique_ptr processed_search{ edit_process_content(std::wstring(search)) };
106 |
107 | size_t size = query_size + processed_search->size() * sizeof(wchar_t) + sizeof L'\0';
108 | auto buf = std::make_unique(size);
109 | std::copy_n(query, query_size, buf.get());
110 | processed_search->copy((wchar_t*)(buf.get() + query_size), processed_search->size() + 1);
111 |
112 | COPYDATASTRUCT processed_copydata{
113 | command,
114 | size,
115 | (PVOID)buf.get()
116 | };
117 |
118 | return CallWindowProcW(ipc_window_proc_prev, hwnd, uMsg, wParam, (LPARAM)&processed_copydata);
119 | };
120 | COPYDATASTRUCT* copydata = ib::Addr(lParam);
121 | switch (copydata->dwData) {
122 | case EVERYTHING_IPC_COPYDATA_QUERY2W:
123 | {
124 | EVERYTHING_IPC_QUERY2 *query = ib::Addr(copydata->lpData);
125 | if (query->search_flags & Search::Regex)
126 | break;
127 |
128 | std::wstring_view search{ query->search_string, (copydata->cbData - query->query_size()) / sizeof(wchar_t) - 1 };
129 | return common_process(copydata->dwData, (uint8_t*)query, query->query_size(), search);
130 | }
131 | break;
132 | case EVERYTHING_IPC_COPYDATA_QUERY2A:
133 | {
134 | EVERYTHING_IPC_QUERY2 *query = ib::Addr(copydata->lpData);
135 | if (query->search_flags & Search::Regex)
136 | break;
137 |
138 | size_t search_len = copydata->cbData - query->query_size() - sizeof(char);
139 | auto search_buf = std::make_unique(search_len);
140 |
141 | std::wstring_view search{ search_buf.get(), (size_t)MultiByteToWideChar(CP_ACP, 0, query->search_string, search_len, search_buf.get(), search_len) };
142 | return common_process(EVERYTHING_IPC_COPYDATA_QUERY2W, (uint8_t*)query, query->query_size(), search);
143 | }
144 | break;
145 | case EVERYTHING_IPC_COPYDATAQUERYW:
146 | {
147 | EVERYTHING_IPC_QUERY *query = ib::Addr(copydata->lpData);
148 | if (query->search_flags & Search::Regex)
149 | break;
150 |
151 | std::wstring_view search{ query->search_string, (copydata->cbData - query->query_size()) / sizeof(wchar_t) - 1 };
152 | return common_process(copydata->dwData, (uint8_t*)query, query->query_size(), search);
153 | }
154 | break;
155 | case EVERYTHING_IPC_COPYDATAQUERYA:
156 | {
157 | EVERYTHING_IPC_QUERY *query = ib::Addr(copydata->lpData);
158 | if (query->search_flags & Search::Regex)
159 | break;
160 |
161 | size_t search_len = copydata->cbData - query->query_size() - sizeof(char);
162 | auto search_buf = std::make_unique(search_len);
163 |
164 | std::wstring_view search{ search_buf.get(), (size_t)MultiByteToWideChar(CP_ACP, 0, query->search_string, search_len, search_buf.get(), search_len) };
165 | return common_process(EVERYTHING_IPC_COPYDATAQUERYW, (uint8_t*)query, query->query_size(), search);
166 | }
167 | break;
168 | default:
169 | if constexpr (debug)
170 | DebugOStream() << L"command: " << copydata->dwData << L'\n';
171 | }
172 | }
173 | break;
174 | }
175 | return CallWindowProcW(ipc_window_proc_prev, hwnd, uMsg, wParam, lParam);
176 | }
177 |
178 | void ipc_window_init(HWND ipc_window) {
179 | ipc_window_proc_prev = (WNDPROC)SetWindowLongPtrW(ipc_window, GWLP_WNDPROC, (LONG_PTR)ipc_window_proc);
180 | }
181 |
182 | void ipc_window_destroy() {}
--------------------------------------------------------------------------------
/EverythingExt/ipc_window.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "common.hpp"
3 |
4 | void ipc_window_init(HWND ipc_window);
5 | void ipc_window_destroy();
--------------------------------------------------------------------------------
/EverythingExt/match.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "match.hpp"
3 |
4 | #ifndef NDEBUG
5 | #pragma optimize("gt", on)
6 | #endif
7 |
8 | char32_t read_char32(const char8_t* str, int* length) {
9 | char c = str[0];
10 | switch (*length = 1 + ((c & 0b11000000) == 0b11000000) + ((c & 0b11100000) == 0b11100000) + ((c & 0b11110000) == 0b11110000)) {
11 | case 1: return c;
12 | case 2: return (c & 0b11111) << 6 | (str[1] & 0b111111);
13 | case 3: return (c & 0b1111) << 12 | (str[1] & 0b111111) << 6 | (str[2] & 0b111111);
14 | case 4: return (c & 0b111) << 18 | (str[1] & 0b111111) << 12 | (str[2] & 0b111111) << 6 | (str[3] & 0b111111);
15 | }
16 | }
17 |
18 | Pattern* compile(const char8_t* pattern, CompileFlag flags, std::vector* pinyin_flags) {
19 | // get length
20 | size_t length = 0;
21 | size_t length_u8 = 0;
22 | {
23 | const char8_t* p = pattern;
24 | int char_len;
25 | for (char32_t c = read_char32(p, &char_len); c; c = read_char32(p += char_len, &char_len)) {
26 | length++;
27 | length_u8 += char_len;
28 | }
29 | }
30 |
31 | // parse parse post-modifiers
32 | PatternFlag temp_flags{
33 | .match_at_start = flags.match_at_start,
34 | .match_at_end = flags.match_at_end
35 | };
36 | {
37 | // parse post-modifiers
38 | std::u8string_view pat(pattern, length_u8);
39 | if (pat.ends_with(u8";py")) {
40 | temp_flags.pinyin = true;
41 | length -= 3;
42 | length_u8 -= 3;
43 | }
44 | }
45 |
46 | // make Pattern
47 | std::u8string pattern_u8_upper(length_u8, u8'\0');
48 | std::transform(pattern, pattern + length_u8, pattern_u8_upper.begin(), [](char8_t c) {
49 | return ib::toupper(c);
50 | });
51 |
52 | #ifdef SEARCH_BOOST_XPRESSIVE
53 | boost::xpressive::regex_traits traits;
54 | #endif
55 | Pattern* pat = new Pattern{
56 | .flags = temp_flags,
57 | .pinyin_flags = pinyin_flags,
58 | .pattern = std::u32string(length, U'\0'),
59 | .pattern_u8_upper = pattern_u8_upper,
60 | .pattern_u8_len = length_u8,
61 | #ifdef SEARCH_STD_SEARCHER
62 | .searcher{ ((std::u8string_view)pattern_u8_upper).begin(), ((std::u8string_view)pattern_u8_upper).end() }
63 | #endif
64 | #ifdef SEARCH_BOOST_XPRESSIVE
65 | .traits = traits,
66 | .searcher{ pattern, pattern + length_u8, traits, true }
67 | #endif
68 | };
69 |
70 | const char8_t* p = pattern;
71 | int char_len;
72 | for (size_t i = 0; i < length; i++) {
73 | char32_t c = read_char32(p, &char_len);
74 | pat->pattern[i] = c;
75 | p += char_len;
76 | }
77 |
78 | // flags
79 | pat->flags.no_lower_letter = std::find_if(pat->pattern.begin(), pat->pattern.end(), [](char32_t c) {
80 | return U'a' <= c && c <= U'z';
81 | }) == pat->pattern.end();
82 |
83 | // match at the start if pattern is an absolute path
84 | if (!pat->flags.match_at_start && pattern_u8_upper[1] == u8':' && u8'A' <= pattern_u8_upper[0] && pattern_u8_upper[0] <= u8'Z') {
85 | pat->flags.match_at_start = true;
86 | }
87 |
88 | return pat;
89 | }
90 |
91 | int exec(Pattern* pattern, const char8_t* subject, int length, size_t nmatch, int pmatch[], ExecuteFlag exec_flags)
92 | {
93 | PatternFlag flags = pattern->flags;
94 | if (flags.match_at_start && exec_flags.not_begin_of_line)
95 | return -1;
96 |
97 | const char8_t* subject_end = subject + length;
98 |
99 | // no-hanzi text match
100 | bool no_hanzi = flags.no_lower_letter;
101 | if (!no_hanzi) [[likely]] {
102 | no_hanzi = true;
103 |
104 | /*
105 | const char8_t* s = subject;
106 | int char_len;
107 | for (char32_t c = read_char32(s, &char_len); s != subject_end; c = read_char32(s += char_len, &char_len)) {
108 | if (c >= 0x3007) [[unlikely]] {
109 | no_hanzi = false;
110 | break;
111 | }
112 | }
113 | */
114 |
115 | // 6.9%
116 | for (const char8_t* s = subject; s != subject_end; s++) {
117 | char8_t c = *s;
118 | // U+3007: 1110[0011] 10[000000] 10[000111]
119 | if (c >= 0b1110'0011) [[unlikely]] {
120 | no_hanzi = false;
121 | break;
122 | }
123 | }
124 |
125 | // 8.1%
126 | /*
127 | if (std::find_if(subject, subject_end, [](char8_t c) { return c >= 0b1110'0011; }) != subject_end)
128 | no_hanzi = false;
129 | */
130 | }
131 | if (no_hanzi) {
132 | // main performance influencing code
133 |
134 | // default: a -> [aA嗷] -> [aA], A -> [aA]
135 | // pinyin: a -> [嗷] -> (?!), A -> [aA]
136 |
137 | std::u8string_view sv(subject, length);
138 | std::u8string_view pt = pattern->pattern_u8_upper;
139 | if (sv.size() < pt.size())
140 | return -1;
141 |
142 | std::u8string_view::const_iterator begin = sv.begin(), end = sv.end();
143 | if (flags.match_at_start && flags.match_at_end) [[unlikely]] {
144 | if (sv.size() != pt.size())
145 | return -1;
146 | }
147 | else {
148 | if (flags.match_at_end) [[unlikely]] {
149 | begin = sv.end() - pt.size();
150 | }
151 | if (flags.match_at_start) [[unlikely]] {
152 | end = sv.begin() + pt.size();
153 | }
154 | }
155 |
156 | /*
157 | std::search: 57%
158 | // std::boyer_moore_searcher
159 | // std::boyer_moore_horspool_searcher
160 | boost::algorithm::ifind_first: unbelievably slow
161 | boost::xpressive::detail::boyer_moore: 58%
162 | */
163 | #ifdef SEARCH_STD
164 | std::function pred;
165 | std::u8string_view::const_iterator it;
166 | if (!flags.pinyin) /* default */ [[likely]] {
167 | pred = [](char8_t c1, char8_t c2) {
168 | return ib::toupper(c1) == c2; // don't use std::toupper, it's slow
169 | };
170 | }
171 | else /* pinyin */ {
172 | if (!flags.no_lower_letter) [[likely]]
173 | return -1;
174 | else /* pattern is all-caps */
175 | ;
176 |
177 | pred = [](char8_t c1, char8_t c2) {
178 | return ib::toupper(c1) == c2; // don't use std::toupper, it's slow
179 | };
180 | }
181 | it = std::search(begin, end, pt.begin(), pt.end(), pred);
182 | #endif
183 | #ifdef SEARCH_STD_SEARCHER
184 | auto it = std::search(begin, end, pattern->searcher);
185 | #endif
186 | #ifdef SEARCH_BOOST_ALGORITHM
187 | auto input = boost::make_iterator_range(begin, end);
188 | auto match = boost::algorithm::ifind_first(input, pattern->pattern_u8_upper);
189 | auto it = match.begin();
190 | #endif
191 | #ifdef SEARCH_BOOST_XPRESSIVE
192 | auto it = pattern->searcher.find(begin, end, pattern->traits);
193 | #endif
194 |
195 | if (it == end) [[likely]] {
196 | return -1;
197 | } else {
198 | if (nmatch) {
199 | pmatch[0] = it - sv.begin();
200 | pmatch[1] = it - sv.begin() + pt.size();
201 | return 1;
202 | } else {
203 | return 0;
204 | }
205 | }
206 | }
207 |
208 | // DFA?
209 | auto char_match = [pattern, flags](char32_t c, const char32_t* pat) -> std::vector {
210 | std::vector v;
211 | if (flags.pinyin) {
212 | if (c >= 0x3007) {
213 | for (pinyin::PinyinFlagValue flag : *pattern->pinyin_flags) {
214 | if (size_t size = pinyin::match_pinyin(c, pat, flag)) [[unlikely]]
215 | v.push_back(size);
216 | }
217 | }
218 | }
219 | else [[likely]] {
220 | if (c == *pat)
221 | v.push_back(1);
222 | else {
223 | if (c < 0x3007) {
224 | /*
225 | if (U'A' <= c && c <= U'Z') {
226 | if (*pat == c - U'A' + U'a')
227 | v.push_back(1);
228 | }
229 | else if (U'a' <= c && c <= U'z') {
230 | if (*pat == c - U'a' + U'A')
231 | v.push_back(1);
232 | }
233 | */
234 | if (c <= U'z' && ib::toupper(*pat) == ib::toupper(c))
235 | v.push_back(1);
236 | }
237 | else {
238 | for (pinyin::PinyinFlagValue flag : *pattern->pinyin_flags) {
239 | if (size_t size = pinyin::match_pinyin(c, pat, flag)) [[unlikely]]
240 | v.push_back(size);
241 | }
242 | }
243 | }
244 | }
245 | return v;
246 | };
247 | std::function subject_match = [&char_match, &subject_match, subject_end](const char8_t* sub, const char32_t* pattern) -> const char8_t* {
248 | if (!*pattern)
249 | return sub;
250 |
251 | if (sub == subject_end)
252 | return nullptr;
253 | int char_len;
254 | char32_t c = read_char32(sub, &char_len);
255 |
256 | std::vector v = char_match(c, pattern);
257 | for (size_t size : v) {
258 | if (const char8_t* s = subject_match(sub + char_len, pattern + size))
259 | return s;
260 | }
261 | return nullptr;
262 | };
263 |
264 | // global match
265 | const char8_t* sub = subject;
266 | int char_len;
267 | while (sub != subject_end) {
268 | if (const char8_t* s = subject_match(sub, pattern->pattern.c_str())) {
269 | if (flags.match_at_end && s != subject_end)
270 | goto next;
271 |
272 | if (nmatch) {
273 | pmatch[0] = sub - subject;
274 | pmatch[1] = s - subject;
275 | return 1;
276 | } else {
277 | return 0;
278 | }
279 | /*
280 | sub = s;
281 | continue;
282 | */
283 | }
284 | next:
285 | if (flags.match_at_start) [[unlikely]]
286 | break;
287 |
288 | read_char32(sub, &char_len);
289 | sub += char_len;
290 | }
291 |
292 | return -1;
293 | }
294 |
295 | // because match.cpp is included by test/match.cpp, we need to reset the optimizations
296 | #ifndef NDEBUG
297 | #pragma optimize("", on)
298 | #endif
--------------------------------------------------------------------------------
/EverythingExt/match.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "helper.hpp"
3 | #include
4 | #include
5 | #include
6 | #define IB_PINYIN_ENCODING 32
7 | #include
8 |
9 | /*
10 | SEARCH_STD
11 | // SEARCH_STD_SEARCHER
12 | SEARCH_BOOST_ALGORITHM
13 | SEARCH_BOOST_XPRESSIVE
14 | */
15 | #define SEARCH_STD
16 |
17 | #ifdef SEARCH_BOOST_ALGORITHM
18 | #include
19 | #endif
20 | #ifdef SEARCH_BOOST_XPRESSIVE
21 | #include
22 | #endif
23 |
24 | struct CompileFlag {
25 | bool match_at_start : 1;
26 | bool match_at_end : 1;
27 | };
28 |
29 | struct PatternFlag {
30 | bool pinyin : 1;
31 |
32 | // note that regcomp_p2 will filter out content containing no lower letter
33 | // completely
34 | bool no_lower_letter : 1;
35 |
36 | bool match_at_start : 1;
37 | bool match_at_end : 1;
38 | };
39 |
40 | struct ExecuteFlag {
41 | bool not_begin_of_line : 1;
42 | };
43 |
44 | struct Pattern {
45 | PatternFlag flags;
46 | std::vector* pinyin_flags;
47 | std::u32string pattern;
48 | std::u8string pattern_u8_upper;
49 | size_t pattern_u8_len;
50 | #ifdef SEARCH_STD_SEARCHER
51 | std::boyer_moore_horspool_searcher()(ib::toupper(c)); }),
53 | decltype([](char8_t c1, char8_t c2) {
54 | //DebugOStream() << wchar_t(c1) << L' ' << wchar_t(c2) << L'\n';
55 | // c2 is not guaranteed to be from pattern?
56 | return ib::toupper(c1) == ib::toupper(c2); // don't use std::toupper, it's slow
57 | })
58 | > searcher;
59 | #endif
60 | #ifdef SEARCH_BOOST_XPRESSIVE
61 | boost::xpressive::regex_traits traits;
62 | boost::xpressive::detail::boyer_moore> searcher;
63 | #endif
64 | };
65 |
66 | Pattern* compile(const char8_t* pattern, CompileFlag flags, std::vector* pinyin_flags);
67 |
68 | int exec(Pattern* pattern, const char8_t* subject, int length, size_t nmatch, int pmatch[], ExecuteFlag flags);
--------------------------------------------------------------------------------
/EverythingExt/pch.cpp:
--------------------------------------------------------------------------------
1 | // pch.cpp: source file corresponding to the pre-compiled header
2 |
3 | #include "pch.h"
4 |
5 | // When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
6 |
--------------------------------------------------------------------------------
/EverythingExt/pch.h:
--------------------------------------------------------------------------------
1 | // pch.h: This is a precompiled header file.
2 | // Files listed below are compiled only once, improving build performance for future builds.
3 | // This also affects IntelliSense performance, including code completion and many code browsing features.
4 | // However, files listed here are ALL re-compiled if any one of them is updated between builds.
5 | // Do not add files here that you will be updating frequently as this negates the performance advantage.
6 |
7 | #ifndef PCH_H
8 | #define PCH_H
9 |
10 | // add headers that you want to pre-compile here
11 | #include "framework.h"
12 |
13 | #endif //PCH_H
14 |
--------------------------------------------------------------------------------
/EverythingExt/pinyin.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "common.hpp"
3 | #include "pinyin.hpp"
4 | #include
5 | #include
6 | #include "helper.hpp"
7 | #include "ipc.hpp"
8 |
9 | std::wstring pinyin_regexs[26]{};
10 | std::pair pinyin_pair_regexs[26][26]{};
11 | std::set pinyin_merged_set;
12 |
13 | bool Utf16Pair::in(std::wstring_view sv) const {
14 | if (!h) {
15 | return sv.find(l) != sv.npos;
16 | } else {
17 | size_t pos = sv.find(l);
18 | while (pos != sv.npos && pos != sv.size() - 1) {
19 | if (sv[pos + 1] == h)
20 | return true;
21 | pos = sv.find(l, pos + 1);
22 | }
23 | return false;
24 | }
25 | }
26 |
27 | struct Utf16PairOrd : Utf16Pair {
28 | char32_t ord;
29 |
30 | Utf16PairOrd() : Utf16Pair(), ord(0) {}
31 | Utf16PairOrd(wchar_t l) : Utf16Pair(l), ord(l) {}
32 | Utf16PairOrd(wchar_t l, wchar_t h) : Utf16Pair(l, h), ord(to_ord(l, h)) {}
33 |
34 | protected:
35 | static char32_t to_ord(wchar_t l, wchar_t h) {
36 | return 0x10000 + ((l - 0xD800) << 10) + (h - 0xDC00);
37 | }
38 | };
39 |
40 | void pinyin_query_and_merge() {
41 | using namespace Everythings;
42 | using namespace std::literals;
43 |
44 | static DWORD last_query = 0;
45 |
46 | static std::mutex mutex; // be careful
47 | if (!mutex.try_lock())
48 | return;
49 |
50 | // query
51 | std::wstring query;
52 | if (!last_query) {
53 | query = L"regex:[〇-𰻞]";
54 | ipc_ev->database_loaded_future().get();
55 | last_query = GetTickCount() / 1000;
56 | } else {
57 | DWORD time = GetTickCount() / 1000;
58 | query = L"rc:last" + std::to_wstring(time - last_query + 1) + L"secs regex:[〇-𰻞]";
59 | last_query = time;
60 | }
61 | QueryResults results = ipc_ev->query_send(query, Search::MatchCase, Request::FileName).get();
62 |
63 | // merge functions
64 | //"拼"
65 | auto merge = [](Utf16PairOrd pair) -> uint32_t {
66 | uint32_t flags = pinyin::get_initial_pinyin_letters(pair.ord);
67 | if (!flags)
68 | return 0;
69 |
70 | if (!pinyin_merged_set.contains(pair.ord)) {
71 | pinyin_merged_set.insert(pair.ord);
72 |
73 | for (int i = 0; i < 26; i++) {
74 | if (flags & 1 << i) {
75 | pinyin_regexs[i].push_back(pair.l);
76 | if (pair.h) pinyin_regexs[i].push_back(pair.h);
77 | }
78 | }
79 | }
80 |
81 | return flags;
82 | };
83 | //"拼音"
84 | auto merge_pair = [&merge](Utf16PairOrd pair1, Utf16PairOrd pair2, uint32_t py1) -> uint32_t {
85 | uint32_t py2 = merge(pair2);
86 | if (!py1 || !py2)
87 | return py2;
88 | for (int i = 0; i < 26; i++) {
89 | if (py1 & 1 << i) {
90 | for (int j = 0; j < 26; j++) {
91 | if (py2 & 1 << j) {
92 | auto& [first, second] = pinyin_pair_regexs[i][j];
93 |
94 | if (!pair1.in(first)) {
95 | first.push_back(pair1.l);
96 | if (pair1.h) first.push_back(pair1.h);
97 | }
98 |
99 | if (!pair2.in(second)) {
100 | second.push_back(pair2.l);
101 | if (pair2.h) second.push_back(pair2.h);
102 | }
103 | }
104 | }
105 | }
106 | }
107 | return py2;
108 | };
109 | // "p音"
110 | auto merge_letter_hanzi = [&merge](wchar_t letter, Utf16PairOrd hanzi) -> uint32_t {
111 | uint32_t py = merge(hanzi);
112 | if (!py)
113 | return py;
114 |
115 | uint32_t i = letter - 'a';
116 | for (int j = 0; j < 26; j++) {
117 | if (py & 1 << j) {
118 | std::wstring& second = pinyin_pair_regexs[i][j].second;
119 | if (!hanzi.in(second)) {
120 | second.push_back(hanzi.l);
121 | if (hanzi.h) second.push_back(hanzi.h);
122 | }
123 | }
124 | }
125 | return py;
126 | };
127 | // "拼y"
128 | auto merge_hanzi_letter = [](Utf16PairOrd hanzi, wchar_t letter, uint32_t py) -> void {
129 | if (!py)
130 | return;
131 |
132 | uint32_t j = letter - 'a';
133 | for (int i = 0; i < 26; i++) {
134 | if (py & 1 << i) {
135 | std::wstring& first = pinyin_pair_regexs[i][j].first;
136 | if (!hanzi.in(first)) {
137 | first.push_back(hanzi.l);
138 | if (hanzi.h) first.push_back(hanzi.h);
139 | }
140 | }
141 | }
142 | };
143 |
144 | // merge chars in results
145 | for (DWORD j = 0; j < results.available_num; j++) {
146 | std::wstring_view filename = results[j].get_str(Request::FileName);
147 |
148 | Utf16PairOrd last_hanzi{};
149 | uint32_t last_py = 0;
150 | wchar_t last_letter = L'\0';
151 | uint32_t i = 0;
152 | while (i < filename.size()) {
153 | wchar_t c = filename[i++];
154 | if (c < 0x3007) {
155 | last_letter = L'\0';
156 | if (c <= L'z') {
157 | if (c <= L'Z')
158 | c += L'a' - L'A';
159 | if (L'a' <= c) { // [a-z]
160 | if (last_hanzi.l) {
161 | merge_hanzi_letter(last_hanzi, c, last_py);
162 | last_hanzi = {};
163 | }
164 | last_letter = c;
165 | }
166 | }
167 | } else {
168 | Utf16PairOrd cur;
169 | if (0xD800 <= c && c <= 0xDBFF) {
170 | if (i < filename.size())
171 | cur = { c, filename[i++] };
172 | else
173 | break;
174 | } else {
175 | cur = { c };
176 | }
177 |
178 | if (last_letter) {
179 | last_py = merge_letter_hanzi(last_letter, cur);
180 | last_letter = L'\0';
181 | } else if (last_hanzi.l)
182 | last_py = merge_pair(last_hanzi, cur, last_py);
183 | else
184 | last_py = merge(cur);
185 |
186 | last_hanzi = cur;
187 | }
188 | }
189 | }
190 |
191 | mutex.unlock();
192 |
193 | if constexpr (debug) {
194 | for (uint32_t i = 0; i < std::size(pinyin_regexs); i++)
195 | DebugOStream() << static_cast(L'a' + i) << L": " << pinyin_regexs[i] << L"\n";
196 | /*
197 | // may be very long
198 | for (uint32_t i = 0; i < std::size(pinyin_regexs); i++) {
199 | ib::DebugOStream dout = DebugOStream();
200 | for (uint32_t j = 0; j < std::size(pinyin_regexs); j++)
201 | dout << static_cast(L'a' + i) << static_cast(L'a' + j) << L": "
202 | << pinyin_pair_regexs[i][j].first << L' ' << pinyin_pair_regexs[i][j].second << L", ";
203 | dout << L'\n';
204 | }
205 | */
206 | }
207 | }
--------------------------------------------------------------------------------
/EverythingExt/pinyin.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include
5 | #define IB_PINYIN_ENCODING 32
6 | #include
7 |
8 | extern std::wstring pinyin_regexs[26];
9 | extern std::pair pinyin_pair_regexs[26][26];
10 |
11 | struct Utf16Pair {
12 | wchar_t l;
13 | wchar_t h;
14 |
15 | Utf16Pair() : l(0), h(0) {}
16 | Utf16Pair(wchar_t l) : l(l), h(0) {}
17 | Utf16Pair(wchar_t l, wchar_t h) : l(l), h(h) {}
18 |
19 | bool in(std::wstring_view sv) const;
20 | };
21 |
22 | // require ipc_init
23 | void pinyin_query_and_merge();
--------------------------------------------------------------------------------
/EverythingExt/quick_select.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "common.hpp"
3 |
4 | namespace quick {
5 | enum InputMode {
6 | Auto,
7 | WmKey,
8 | SendInput
9 | };
10 |
11 | // require ipc_init
12 | void init();
13 | void destroy();
14 |
15 | HWND create_quick_list(HWND everything, HWND list, HWND edit, HINSTANCE instance);
16 | LRESULT CALLBACK list_window_proc(
17 | WNDPROC prev_proc,
18 | _In_ HWND hwnd,
19 | _In_ UINT uMsg,
20 | _In_ WPARAM wParam,
21 | _In_ LPARAM lParam);
22 | }
--------------------------------------------------------------------------------
/EverythingExt/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by resource.rc
4 |
5 | // Next default values for new objects
6 | //
7 | #ifdef APSTUDIO_INVOKED
8 | #ifndef APSTUDIO_READONLY_SYMBOLS
9 | #define _APS_NEXT_RESOURCE_VALUE 101
10 | #define _APS_NEXT_COMMAND_VALUE 40001
11 | #define _APS_NEXT_CONTROL_VALUE 1001
12 | #define _APS_NEXT_SYMED_VALUE 101
13 | #endif
14 | #endif
15 |
--------------------------------------------------------------------------------
/EverythingExt/resource.rc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Chaoses-Ib/IbEverythingExt/6c5b33636eaae51e9eea48e7d1434c579053a668/EverythingExt/resource.rc
--------------------------------------------------------------------------------
/EverythingExt/search_history.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "common.hpp"
3 | #include "search_history.hpp"
4 | #include
5 | #include
6 | #include "helper.hpp"
7 |
8 | extern std::unordered_map content_map;
9 |
10 | static HANDLE search_history_handle = nullptr;
11 | static std::string search_history_to_write{};
12 |
13 | auto WriteFile_real = WriteFile;
14 | BOOL WINAPI WriteFile_detour(
15 | _In_ HANDLE hFile,
16 | _In_reads_bytes_opt_(nNumberOfBytesToWrite) LPCVOID lpBuffer,
17 | _In_ DWORD nNumberOfBytesToWrite,
18 | _Out_opt_ LPDWORD lpNumberOfBytesWritten,
19 | _Inout_opt_ LPOVERLAPPED lpOverlapped
20 | ) {
21 | // UTF-8
22 | // the max size is 0x10000
23 |
24 | using namespace std::literals;
25 |
26 | do {
27 | std::string_view sv(static_cast(lpBuffer), nNumberOfBytesToWrite);
28 | if (!search_history_handle) {
29 | if (!sv.starts_with("Search,Search Count,Last Search Date\r\n"sv))
30 | break;
31 | search_history_handle = hFile;
32 | } else if (hFile != search_history_handle)
33 | break;
34 |
35 | search_history_to_write += sv;
36 |
37 | *lpNumberOfBytesWritten = nNumberOfBytesToWrite; // required
38 | return true; // be careful
39 | } while (false);
40 |
41 | return WriteFile_real(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
42 | }
43 |
44 | auto MoveFileExW_real = MoveFileExW;
45 | BOOL WINAPI MoveFileExW_detour(
46 | _In_ LPCWSTR lpExistingFileName,
47 | _In_opt_ LPCWSTR lpNewFileName,
48 | _In_ DWORD dwFlags
49 | ) {
50 | using namespace std::literals;
51 |
52 | if (search_history_handle) {
53 | if (std::wstring_view existing_file(lpExistingFileName);
54 | existing_file.ends_with(L".csv.tmp"sv) && existing_file.find(L"\\Search History") != existing_file.npos)
55 | {
56 | search_history_handle = nullptr;
57 |
58 | /*
59 | Search,Search Count,Last Search Date
60 | "a",4,132767094406609228
61 | "case:regex:""[aA][bB][cC]""[dD单到的]",2,132767108299260960
62 | */
63 | auto& history = search_history_to_write;
64 |
65 | std::ostringstream out(std::ios_base::binary); // may be longer than buffer (such as "a" -> "nopy:a")
66 | out << "Search,Search Count,Last Search Date\r\n"sv;
67 |
68 | std::unordered_map search_map{};
69 | uint32_t i = "Search,Search Count,Last Search Date\r\n"sv.size();
70 | while (i < history.size()) {
71 | if (history[i++] != '"')
72 | break;
73 | out << '"';
74 |
75 | // parse Search and convert processed content to raw content
76 | std::string search;
77 | while (i < history.size()) {
78 | char c = history[i++];
79 | if (c == '"') {
80 | if (i < history.size() && history[i] == '"') { // ""
81 | search.push_back('"');
82 | i++;
83 | } else
84 | break;
85 | } else
86 | search.push_back(c);
87 | }
88 | {
89 | // search to search_u16
90 | // std::wstring_convert is deprecated in C++ 17
91 | std::wstring search_u16(search.size(), L'\0');
92 | search_u16.resize(MultiByteToWideChar(CP_UTF8, 0, search.data(), search.size(), search_u16.data(), search_u16.size()));
93 |
94 | // processed content -> content
95 | auto iter = content_map.find(search_u16);
96 | if (iter != content_map.end()) {
97 | // content to content_u8
98 | std::string content_u8(iter->second.size() * 3, '\0');
99 | int length = WideCharToMultiByte(CP_UTF8, 0, iter->second.data(), iter->second.size(), content_u8.data(), content_u8.size(), nullptr, nullptr);
100 | if (!length) {
101 | if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
102 | break;
103 | content_u8.resize(iter->second.size() * 4);
104 | length = WideCharToMultiByte(CP_UTF8, 0, iter->second.data(), iter->second.size(), content_u8.data(), content_u8.size(), nullptr, nullptr);
105 | }
106 | content_u8.resize(length);
107 |
108 | search = content_u8;
109 | }
110 | }
111 | for (char c : search) {
112 | if (c == '"')
113 | out << '"';
114 | out << c;
115 | }
116 | out << '"' << ',';
117 | i++; // ','
118 |
119 | // parse Search Count and do sums
120 | uint32_t j = i;
121 | while (j < history.size()) {
122 | if (history[j++] == ',')
123 | break;
124 | }
125 | j--;
126 | uint32_t count = std::atoi(&history[i]); // (i, j - i)
127 | auto iter = search_map.find(search);
128 | if (iter == search_map.end()) {
129 | search_map[search] = count;
130 | } else {
131 | count += iter->second;
132 | search_map.erase(iter);
133 | out << count;
134 | i = j;
135 | }
136 |
137 | // the remaining
138 | while (i < history.size()) {
139 | char c = history[i++];
140 | out << c;
141 | if (c == '\n')
142 | break;
143 | }
144 | }
145 | history.clear();
146 |
147 | HANDLE file = CreateFileW(lpExistingFileName, GENERIC_WRITE, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, 0, nullptr);
148 | if (!file)
149 | return false;
150 |
151 | const std::string& out_str = out.str();
152 | DWORD written;
153 | bool result = WriteFile_real(file, out_str.data(), out_str.size(), &written, nullptr);
154 |
155 | CloseHandle(file);
156 | if (!result)
157 | return false;
158 | }
159 | }
160 | return MoveFileExW_real(lpExistingFileName, lpNewFileName, dwFlags);
161 | }
162 |
163 | auto TextOutW_real = TextOutW;
164 | BOOL WINAPI TextOutW_detour(_In_ HDC hdc, _In_ int x, _In_ int y, _In_reads_(c) LPCWSTR lpString, _In_ int c) {
165 | // TextOutW will only be called from:
166 | // DropdownList
167 | // WindowFromDC() == NULL
168 | // Options: Fonts and Colors
169 | // WindowFromDC() != NULL
170 |
171 | /*
172 | using namespace std::literals;
173 |
174 | static HDC last_hdc = 0;
175 | static bool is_dropdown_list = false;
176 | if (hdc != last_hdc) { // there may be a collision?
177 | last_hdc = hdc;
178 | is_dropdown_list = false;
179 |
180 | HWND hwnd = WindowFromDC(hdc);
181 | wchar_t buf[std::size(L"EVERYTHING_DROPDOWNLIST")];
182 | if (int len = GetClassNameW(hwnd, buf, std::size(buf))) {
183 | if (std::wstring_view(buf, len) == L"EVERYTHING_DROPDOWNLIST"sv) {
184 | is_dropdown_list = true;
185 | }
186 | }
187 | }
188 | if (is_dropdown_list) {
189 | }
190 | */
191 |
192 | if (!WindowFromDC(hdc)) {
193 | std::wstring_view sv(lpString, c);
194 | if (c == 4096) { // max length
195 | sv = std::wstring_view(lpString); // #TODO: is it always zero-terminated?
196 | }
197 |
198 | auto iter = content_map.find(std::wstring(sv)); // #TODO: directly use sv
199 | if (iter != content_map.end()) {
200 | return TextOutW_real(hdc, x, y, iter->second.c_str(), iter->second.size());
201 | }
202 | }
203 | return TextOutW_real(hdc, x, y, lpString, c);
204 | }
205 |
206 | void search_history_init() {
207 | // #TODO: transaction
208 | IbDetourAttach(&WriteFile_real, WriteFile_detour);
209 | IbDetourAttach(&MoveFileExW_real, MoveFileExW_detour);
210 | IbDetourAttach(&TextOutW_real, TextOutW_detour);
211 | }
212 |
213 | void search_history_destroy() {
214 | IbDetourDetach(&TextOutW_real, TextOutW_detour);
215 | IbDetourDetach(&MoveFileExW_real, MoveFileExW_detour);
216 | IbDetourDetach(&WriteFile_real, WriteFile_detour);
217 | }
--------------------------------------------------------------------------------
/EverythingExt/search_history.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | void search_history_init();
4 | void search_history_destroy();
--------------------------------------------------------------------------------
/EverythingExt/toupper_gen.py:
--------------------------------------------------------------------------------
1 | import string
2 |
3 | table = [i for i in range(256)]
4 |
5 | for letter in string.ascii_lowercase:
6 | table[ord(letter)] = ord(letter.upper())
7 |
8 | code = ''
9 | for i in range(0, 256, 16):
10 | code += ', '.join(hex(table[j]) for j in range(i, i+16)) + ',\n'
11 |
12 | print(code)
--------------------------------------------------------------------------------
/IbEverythingExt.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.1.32319.34
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EverythingExt", "EverythingExt\EverythingExt.vcxproj", "{102EEFA7-F37C-4FA7-AC25-D4DDC2E797E7}"
7 | EndProject
8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcxproj", "{80718343-F2B4-4358-8D44-321CBE687F92}"
9 | EndProject
10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IbWinCpp", "external\build\_deps\ibwincpp-build\IbWinCpp.vcxproj", "{81A0272A-5EF3-30A8-9154-3A5A8DF9AA70}"
11 | EndProject
12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IbEverything", "external\build\_deps\ibeverything-build\IbEverything.vcxproj", "{1DBB8594-6BAF-34C0-9998-6AA359588998}"
13 | EndProject
14 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IbPinyin", "external\build\_deps\ibpinyin-build\IbPinyin.vcxproj", "{169D9787-0F47-3EE4-9056-C52DFC6E922A}"
15 | EndProject
16 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IbUpdate", "external\build\_deps\ibupdate-build\C++\IbUpdate.vcxproj", "{90572FC6-3F72-3CB1-A7E3-14D1FC6BF226}"
17 | EndProject
18 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Updater", "Updater\Updater.vcxproj", "{F1492EF6-27C2-44CD-A34B-E55F45DA5222}"
19 | EndProject
20 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "github_api", "external\build\_deps\github_api-build\github_api.vcxproj", "{9A48DEA3-C71B-30FC-AC03-8929973872CE}"
21 | EndProject
22 | Global
23 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
24 | Debug|x64 = Debug|x64
25 | Debug|x86 = Debug|x86
26 | MinSizeRel|x64 = MinSizeRel|x64
27 | MinSizeRel|x86 = MinSizeRel|x86
28 | Release|x64 = Release|x64
29 | Release|x86 = Release|x86
30 | RelWithDebInfo|x64 = RelWithDebInfo|x64
31 | RelWithDebInfo|x86 = RelWithDebInfo|x86
32 | EndGlobalSection
33 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
34 | {102EEFA7-F37C-4FA7-AC25-D4DDC2E797E7}.Debug|x64.ActiveCfg = Debug|x64
35 | {102EEFA7-F37C-4FA7-AC25-D4DDC2E797E7}.Debug|x64.Build.0 = Debug|x64
36 | {102EEFA7-F37C-4FA7-AC25-D4DDC2E797E7}.Debug|x86.ActiveCfg = Debug|Win32
37 | {102EEFA7-F37C-4FA7-AC25-D4DDC2E797E7}.Debug|x86.Build.0 = Debug|Win32
38 | {102EEFA7-F37C-4FA7-AC25-D4DDC2E797E7}.MinSizeRel|x64.ActiveCfg = Release|x64
39 | {102EEFA7-F37C-4FA7-AC25-D4DDC2E797E7}.MinSizeRel|x64.Build.0 = Release|x64
40 | {102EEFA7-F37C-4FA7-AC25-D4DDC2E797E7}.MinSizeRel|x86.ActiveCfg = Release|Win32
41 | {102EEFA7-F37C-4FA7-AC25-D4DDC2E797E7}.MinSizeRel|x86.Build.0 = Release|Win32
42 | {102EEFA7-F37C-4FA7-AC25-D4DDC2E797E7}.Release|x64.ActiveCfg = Release|x64
43 | {102EEFA7-F37C-4FA7-AC25-D4DDC2E797E7}.Release|x64.Build.0 = Release|x64
44 | {102EEFA7-F37C-4FA7-AC25-D4DDC2E797E7}.Release|x86.ActiveCfg = Release|Win32
45 | {102EEFA7-F37C-4FA7-AC25-D4DDC2E797E7}.Release|x86.Build.0 = Release|Win32
46 | {102EEFA7-F37C-4FA7-AC25-D4DDC2E797E7}.RelWithDebInfo|x64.ActiveCfg = Release|x64
47 | {102EEFA7-F37C-4FA7-AC25-D4DDC2E797E7}.RelWithDebInfo|x64.Build.0 = Release|x64
48 | {102EEFA7-F37C-4FA7-AC25-D4DDC2E797E7}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
49 | {102EEFA7-F37C-4FA7-AC25-D4DDC2E797E7}.RelWithDebInfo|x86.Build.0 = Release|Win32
50 | {80718343-F2B4-4358-8D44-321CBE687F92}.Debug|x64.ActiveCfg = Debug|x64
51 | {80718343-F2B4-4358-8D44-321CBE687F92}.Debug|x64.Build.0 = Debug|x64
52 | {80718343-F2B4-4358-8D44-321CBE687F92}.Debug|x86.ActiveCfg = Debug|Win32
53 | {80718343-F2B4-4358-8D44-321CBE687F92}.Debug|x86.Build.0 = Debug|Win32
54 | {80718343-F2B4-4358-8D44-321CBE687F92}.MinSizeRel|x64.ActiveCfg = Debug|x64
55 | {80718343-F2B4-4358-8D44-321CBE687F92}.MinSizeRel|x64.Build.0 = Debug|x64
56 | {80718343-F2B4-4358-8D44-321CBE687F92}.MinSizeRel|x86.ActiveCfg = Debug|Win32
57 | {80718343-F2B4-4358-8D44-321CBE687F92}.MinSizeRel|x86.Build.0 = Debug|Win32
58 | {80718343-F2B4-4358-8D44-321CBE687F92}.Release|x64.ActiveCfg = Release|x64
59 | {80718343-F2B4-4358-8D44-321CBE687F92}.Release|x64.Build.0 = Release|x64
60 | {80718343-F2B4-4358-8D44-321CBE687F92}.Release|x86.ActiveCfg = Release|Win32
61 | {80718343-F2B4-4358-8D44-321CBE687F92}.Release|x86.Build.0 = Release|Win32
62 | {80718343-F2B4-4358-8D44-321CBE687F92}.RelWithDebInfo|x64.ActiveCfg = Release|x64
63 | {80718343-F2B4-4358-8D44-321CBE687F92}.RelWithDebInfo|x64.Build.0 = Release|x64
64 | {80718343-F2B4-4358-8D44-321CBE687F92}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
65 | {80718343-F2B4-4358-8D44-321CBE687F92}.RelWithDebInfo|x86.Build.0 = Release|Win32
66 | {81A0272A-5EF3-30A8-9154-3A5A8DF9AA70}.Debug|x64.ActiveCfg = Debug|x64
67 | {81A0272A-5EF3-30A8-9154-3A5A8DF9AA70}.Debug|x64.Build.0 = Debug|x64
68 | {81A0272A-5EF3-30A8-9154-3A5A8DF9AA70}.Debug|x86.ActiveCfg = Debug|x64
69 | {81A0272A-5EF3-30A8-9154-3A5A8DF9AA70}.Debug|x86.Build.0 = Debug|x64
70 | {81A0272A-5EF3-30A8-9154-3A5A8DF9AA70}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
71 | {81A0272A-5EF3-30A8-9154-3A5A8DF9AA70}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
72 | {81A0272A-5EF3-30A8-9154-3A5A8DF9AA70}.MinSizeRel|x86.ActiveCfg = MinSizeRel|x64
73 | {81A0272A-5EF3-30A8-9154-3A5A8DF9AA70}.MinSizeRel|x86.Build.0 = MinSizeRel|x64
74 | {81A0272A-5EF3-30A8-9154-3A5A8DF9AA70}.Release|x64.ActiveCfg = Release|x64
75 | {81A0272A-5EF3-30A8-9154-3A5A8DF9AA70}.Release|x64.Build.0 = Release|x64
76 | {81A0272A-5EF3-30A8-9154-3A5A8DF9AA70}.Release|x86.ActiveCfg = Release|x64
77 | {81A0272A-5EF3-30A8-9154-3A5A8DF9AA70}.Release|x86.Build.0 = Release|x64
78 | {81A0272A-5EF3-30A8-9154-3A5A8DF9AA70}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
79 | {81A0272A-5EF3-30A8-9154-3A5A8DF9AA70}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
80 | {81A0272A-5EF3-30A8-9154-3A5A8DF9AA70}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64
81 | {81A0272A-5EF3-30A8-9154-3A5A8DF9AA70}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|x64
82 | {1DBB8594-6BAF-34C0-9998-6AA359588998}.Debug|x64.ActiveCfg = Debug|x64
83 | {1DBB8594-6BAF-34C0-9998-6AA359588998}.Debug|x64.Build.0 = Debug|x64
84 | {1DBB8594-6BAF-34C0-9998-6AA359588998}.Debug|x86.ActiveCfg = Debug|x64
85 | {1DBB8594-6BAF-34C0-9998-6AA359588998}.Debug|x86.Build.0 = Debug|x64
86 | {1DBB8594-6BAF-34C0-9998-6AA359588998}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
87 | {1DBB8594-6BAF-34C0-9998-6AA359588998}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
88 | {1DBB8594-6BAF-34C0-9998-6AA359588998}.MinSizeRel|x86.ActiveCfg = MinSizeRel|x64
89 | {1DBB8594-6BAF-34C0-9998-6AA359588998}.MinSizeRel|x86.Build.0 = MinSizeRel|x64
90 | {1DBB8594-6BAF-34C0-9998-6AA359588998}.Release|x64.ActiveCfg = Release|x64
91 | {1DBB8594-6BAF-34C0-9998-6AA359588998}.Release|x64.Build.0 = Release|x64
92 | {1DBB8594-6BAF-34C0-9998-6AA359588998}.Release|x86.ActiveCfg = Release|x64
93 | {1DBB8594-6BAF-34C0-9998-6AA359588998}.Release|x86.Build.0 = Release|x64
94 | {1DBB8594-6BAF-34C0-9998-6AA359588998}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
95 | {1DBB8594-6BAF-34C0-9998-6AA359588998}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
96 | {1DBB8594-6BAF-34C0-9998-6AA359588998}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64
97 | {1DBB8594-6BAF-34C0-9998-6AA359588998}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|x64
98 | {169D9787-0F47-3EE4-9056-C52DFC6E922A}.Debug|x64.ActiveCfg = Debug|x64
99 | {169D9787-0F47-3EE4-9056-C52DFC6E922A}.Debug|x64.Build.0 = Debug|x64
100 | {169D9787-0F47-3EE4-9056-C52DFC6E922A}.Debug|x86.ActiveCfg = Debug|x64
101 | {169D9787-0F47-3EE4-9056-C52DFC6E922A}.Debug|x86.Build.0 = Debug|x64
102 | {169D9787-0F47-3EE4-9056-C52DFC6E922A}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
103 | {169D9787-0F47-3EE4-9056-C52DFC6E922A}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
104 | {169D9787-0F47-3EE4-9056-C52DFC6E922A}.MinSizeRel|x86.ActiveCfg = MinSizeRel|x64
105 | {169D9787-0F47-3EE4-9056-C52DFC6E922A}.MinSizeRel|x86.Build.0 = MinSizeRel|x64
106 | {169D9787-0F47-3EE4-9056-C52DFC6E922A}.Release|x64.ActiveCfg = Release|x64
107 | {169D9787-0F47-3EE4-9056-C52DFC6E922A}.Release|x64.Build.0 = Release|x64
108 | {169D9787-0F47-3EE4-9056-C52DFC6E922A}.Release|x86.ActiveCfg = Release|x64
109 | {169D9787-0F47-3EE4-9056-C52DFC6E922A}.Release|x86.Build.0 = Release|x64
110 | {169D9787-0F47-3EE4-9056-C52DFC6E922A}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
111 | {169D9787-0F47-3EE4-9056-C52DFC6E922A}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
112 | {169D9787-0F47-3EE4-9056-C52DFC6E922A}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64
113 | {169D9787-0F47-3EE4-9056-C52DFC6E922A}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|x64
114 | {90572FC6-3F72-3CB1-A7E3-14D1FC6BF226}.Debug|x64.ActiveCfg = Debug|x64
115 | {90572FC6-3F72-3CB1-A7E3-14D1FC6BF226}.Debug|x64.Build.0 = Debug|x64
116 | {90572FC6-3F72-3CB1-A7E3-14D1FC6BF226}.Debug|x86.ActiveCfg = Debug|x64
117 | {90572FC6-3F72-3CB1-A7E3-14D1FC6BF226}.Debug|x86.Build.0 = Debug|x64
118 | {90572FC6-3F72-3CB1-A7E3-14D1FC6BF226}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
119 | {90572FC6-3F72-3CB1-A7E3-14D1FC6BF226}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
120 | {90572FC6-3F72-3CB1-A7E3-14D1FC6BF226}.MinSizeRel|x86.ActiveCfg = MinSizeRel|x64
121 | {90572FC6-3F72-3CB1-A7E3-14D1FC6BF226}.MinSizeRel|x86.Build.0 = MinSizeRel|x64
122 | {90572FC6-3F72-3CB1-A7E3-14D1FC6BF226}.Release|x64.ActiveCfg = Release|x64
123 | {90572FC6-3F72-3CB1-A7E3-14D1FC6BF226}.Release|x64.Build.0 = Release|x64
124 | {90572FC6-3F72-3CB1-A7E3-14D1FC6BF226}.Release|x86.ActiveCfg = Release|x64
125 | {90572FC6-3F72-3CB1-A7E3-14D1FC6BF226}.Release|x86.Build.0 = Release|x64
126 | {90572FC6-3F72-3CB1-A7E3-14D1FC6BF226}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
127 | {90572FC6-3F72-3CB1-A7E3-14D1FC6BF226}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
128 | {90572FC6-3F72-3CB1-A7E3-14D1FC6BF226}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64
129 | {90572FC6-3F72-3CB1-A7E3-14D1FC6BF226}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|x64
130 | {F1492EF6-27C2-44CD-A34B-E55F45DA5222}.Debug|x64.ActiveCfg = Debug|x64
131 | {F1492EF6-27C2-44CD-A34B-E55F45DA5222}.Debug|x64.Build.0 = Debug|x64
132 | {F1492EF6-27C2-44CD-A34B-E55F45DA5222}.Debug|x86.ActiveCfg = Debug|Win32
133 | {F1492EF6-27C2-44CD-A34B-E55F45DA5222}.Debug|x86.Build.0 = Debug|Win32
134 | {F1492EF6-27C2-44CD-A34B-E55F45DA5222}.MinSizeRel|x64.ActiveCfg = Debug|x64
135 | {F1492EF6-27C2-44CD-A34B-E55F45DA5222}.MinSizeRel|x64.Build.0 = Debug|x64
136 | {F1492EF6-27C2-44CD-A34B-E55F45DA5222}.MinSizeRel|x86.ActiveCfg = Debug|Win32
137 | {F1492EF6-27C2-44CD-A34B-E55F45DA5222}.MinSizeRel|x86.Build.0 = Debug|Win32
138 | {F1492EF6-27C2-44CD-A34B-E55F45DA5222}.Release|x64.ActiveCfg = Release|x64
139 | {F1492EF6-27C2-44CD-A34B-E55F45DA5222}.Release|x64.Build.0 = Release|x64
140 | {F1492EF6-27C2-44CD-A34B-E55F45DA5222}.Release|x86.ActiveCfg = Release|Win32
141 | {F1492EF6-27C2-44CD-A34B-E55F45DA5222}.Release|x86.Build.0 = Release|Win32
142 | {F1492EF6-27C2-44CD-A34B-E55F45DA5222}.RelWithDebInfo|x64.ActiveCfg = Release|x64
143 | {F1492EF6-27C2-44CD-A34B-E55F45DA5222}.RelWithDebInfo|x64.Build.0 = Release|x64
144 | {F1492EF6-27C2-44CD-A34B-E55F45DA5222}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
145 | {F1492EF6-27C2-44CD-A34B-E55F45DA5222}.RelWithDebInfo|x86.Build.0 = Release|Win32
146 | {9A48DEA3-C71B-30FC-AC03-8929973872CE}.Debug|x64.ActiveCfg = Debug|x64
147 | {9A48DEA3-C71B-30FC-AC03-8929973872CE}.Debug|x64.Build.0 = Debug|x64
148 | {9A48DEA3-C71B-30FC-AC03-8929973872CE}.Debug|x86.ActiveCfg = Debug|x64
149 | {9A48DEA3-C71B-30FC-AC03-8929973872CE}.Debug|x86.Build.0 = Debug|x64
150 | {9A48DEA3-C71B-30FC-AC03-8929973872CE}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
151 | {9A48DEA3-C71B-30FC-AC03-8929973872CE}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
152 | {9A48DEA3-C71B-30FC-AC03-8929973872CE}.MinSizeRel|x86.ActiveCfg = MinSizeRel|x64
153 | {9A48DEA3-C71B-30FC-AC03-8929973872CE}.MinSizeRel|x86.Build.0 = MinSizeRel|x64
154 | {9A48DEA3-C71B-30FC-AC03-8929973872CE}.Release|x64.ActiveCfg = Release|x64
155 | {9A48DEA3-C71B-30FC-AC03-8929973872CE}.Release|x64.Build.0 = Release|x64
156 | {9A48DEA3-C71B-30FC-AC03-8929973872CE}.Release|x86.ActiveCfg = Release|x64
157 | {9A48DEA3-C71B-30FC-AC03-8929973872CE}.Release|x86.Build.0 = Release|x64
158 | {9A48DEA3-C71B-30FC-AC03-8929973872CE}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
159 | {9A48DEA3-C71B-30FC-AC03-8929973872CE}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
160 | {9A48DEA3-C71B-30FC-AC03-8929973872CE}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64
161 | {9A48DEA3-C71B-30FC-AC03-8929973872CE}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|x64
162 | EndGlobalSection
163 | GlobalSection(SolutionProperties) = preSolution
164 | HideSolutionNode = FALSE
165 | EndGlobalSection
166 | GlobalSection(ExtensibilityGlobals) = postSolution
167 | SolutionGuid = {D8EC0771-ED08-4A28-8799-80ABD0EF07C9}
168 | EndGlobalSection
169 | EndGlobal
170 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Chaoses-Ib
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # IbEverythingExt
2 | [Everything](https://www.voidtools.com/) 拼音搜索、快速选择扩展。
3 |
4 | 
5 |
6 | ## 目录
7 | * [安装](#安装)
8 | * [拼音搜索](#拼音搜索)
9 | * [第三方程序支持](#第三方程序支持)
10 | * [配置](#配置)
11 | * [快速选择](#快速选择)
12 | * [热键](#热键)
13 | * [键列表](#键列表)
14 | * [配置](#配置-1)
15 | * [其它](#其它)
16 | * [快速启动器](#快速启动器)
17 | * [硬盘占用分析](#硬盘占用分析)
18 | * [检查更新](#检查更新)
19 | * [→开发](docs/development.md)
20 | * [致谢](#致谢)
21 | * [相关链接](#相关链接)
22 |
23 | ## 安装
24 | 1. 安装 [Everything](https://www.voidtools.com/zh-cn/downloads/) x64 安装版或便携版(不支持其它架构和精简版)
25 | 如果你能接受英文界面,也可以选择安装 [Everything 1.5 预览版](https://www.voidtools.com/forum/viewtopic.php?f=12&t=9787#download)。
26 | 2. 安装 [VC++ 2022 x64 运行库](https://aka.ms/vs/17/release/vc_redist.x64.exe)
27 | ([PowerToys](https://github.com/microsoft/PowerToys) 在安装时会同时安装 VC++ 2022 运行库,如果你安装了 PowerToys 就可以跳过这一步)
28 | 3. 从 [Releases](../../releases) 下载压缩包
29 | 4. 解压压缩包,将文件放入 Everything 安装目录( `C:\Program Files\Everything` )
30 | 5. 重启 Everything
31 |
32 | ## 拼音搜索
33 | 允许用拼音在 Everything 中搜索文件。
34 |
35 | * 默认小写字母匹配拼音或字母,大写字母只匹配字母。
36 | * 支持简拼、全拼、带声调全拼和双拼搜索,默认只开启简拼和全拼。
37 | 双拼搜索支持以下方案:
38 | * 微软双拼
39 | * 自然码双拼
40 | * 小鹤双拼
41 | * 拼音加加双拼
42 | * 智能 ABC 双拼
43 | * 华宇双拼(紫光双拼)
44 |
45 | 支持多音字和 Unicode 辅助平面汉字。
46 | * 后置修饰符:
47 | * `;py`:小写字母只匹配拼音
48 | * `;np`:禁用拼音搜索
49 |
50 |
51 |
52 | ### [第三方程序支持](docs/third_party/README.md)
53 | 拼音搜索对调用 Everything 进行搜索的第三方程序同样生效,例如:
54 | * [EverythingToolbar](https://github.com/stnkl/EverythingToolbar)
55 |
56 | * [Flow Launcher](https://github.com/Flow-Launcher/Flow.Launcher) 的 [Everything 插件](https://github.com/Flow-Launcher/Flow.Launcher.Plugin.Everything)
57 |
58 | * [PowerToys Run](https://learn.microsoft.com/windows/powertoys/run) 的 [Everything 插件](https://github.com/lin-ycv/EverythingPowerToys)
59 |
60 | * [uTools](https://u.tools) 本地搜索
61 |
62 | * [Wox](https://github.com/Wox-launcher/Wox) 的 Everything 插件
63 | * [火柴(火萤酱)](https://www.huochaipro.com/)本地搜索
64 |
65 | 如果使用的是 Everything 1.5 预览版,因为预览版默认启用了命名实例,大部分程序都不支持调用,需要[通过配置关闭命名实例](https://github.com/Chaoses-Ib/IbEverythingExt/issues/5)。
66 |
67 | ### 配置
68 | `config.yaml` 文件:
69 | ```yaml
70 | # 拼音搜索
71 | pinyin_search:
72 | # true:开启,false:关闭
73 | enable: true
74 |
75 | # 模式
76 | # Pcre:默认模式
77 | # Edit:版本兼容性好,但只支持简拼搜索,性能较低,且存在许多 bug
78 | mode: Pcre
79 |
80 | initial_letter: true # 简拼
81 | pinyin_ascii: true # 全拼
82 | pinyin_ascii_digit: false # 带声调全拼
83 | double_pinyin_abc: false # 智能 ABC 双拼
84 | double_pinyin_jiajia: false # 拼音加加双拼
85 | double_pinyin_microsoft: false # 微软双拼
86 | double_pinyin_thunisoft: false # 华宇双拼(紫光双拼)
87 | double_pinyin_xiaohe: false # 小鹤双拼
88 | double_pinyin_zrm: false # 自然码双拼
89 | ```
90 | Edit 模式详见 [Edit 模式](docs/pinyin_search/edit_mode.md)。
91 |
92 | ## 快速选择
93 | 在 Everything 结果列表的左侧插入一个显示 0\~9、A\~Z 的键列表,并允许在搜索编辑框和结果列表中通过热键快速打开对应文件。
94 |
95 | ### 热键
96 | 搜索编辑框:
97 | 热键 | 功能
98 | --- | ---
99 | `Alt+0~9` | 打开文件(Enter)并关闭窗口
100 | `Alt+Ctrl+0~9` | 定位文件(Ctrl+Enter)并关闭窗口
101 | `Alt+Shift+0~9` | 打开右键菜单
102 | `Alt+Shift+0~9, R` | 查看文件属性
103 | `Tab` / `Enter` | 转移焦点到结果列表\*
104 | `Esc` / `Ctrl+W` | 关闭窗口\*
105 |
106 | 结果列表:
107 | 热键 | 功能
108 | --- | ---
109 | `[0-9A-Z]` | 选中项目
110 | `Enter` | 打开文件\*
111 | `Ctrl+Enter` | 定位文件\*
112 | `Shift+F10` / `Menu` | 打开右键菜单\*
113 | `Alt+Enter` | 查看文件属性\*
114 | `Esc` / `Ctrl+W` | 关闭窗口\*
115 | `$ (Shift+4)` | 复制文件名,在文件所属目录下启动终端
116 | `# (Shift+3)` | 复制文件名,以管理员身份在文件所属目录下启动终端
117 |
118 | 注:
119 | * 操作之后是否关闭窗口可以通过配置进行控制。
120 | * 标 \* 的热键为 Everything 默认热键,不是扩展增加的,在这里列出是为了完整性。
121 |
122 | ### 键列表
123 | 键列表支持高 DPI,但只在 Everything v1.5a 上支持缩放(热键为 `Ctrl+=` 和 `Ctrl+-`),在 Everything v1.4 上则不支持。
124 |
125 | 支持 Everything v1.5a 深色模式:
126 | 
127 |
128 | ### 配置
129 | `config.yaml` 文件:
130 | ```yaml
131 | # 快速选择
132 | quick_select:
133 | # true:开启,false:关闭
134 | enable: true
135 |
136 | # 搜索编辑框
137 | search_edit:
138 | # Alt 组合键范围
139 | # 0:禁用
140 | # 10:Alt+0~9
141 | # 36:Alt+[0-9A-Z]
142 | # 原本的 Alt+A~Z 访问菜单功能可以通过先单击 Alt 键再按 A~Z 实现
143 | # 默认的 Alt+1~4 调整窗口大小、Alt+P 预览和 Alt+D 聚焦搜索编辑框则无法使用,可以通过更改 Everything 选项来绑定到其它热键上(其中 Alt+D 也可使用相同功能的 Ctrl+F 和 F3 来代替)
144 | alt: 10
145 |
146 | # 结果列表
147 | result_list:
148 | # 同上
149 | alt: 0
150 |
151 | # [0-9A-Z] 选中项目
152 | select: true
153 |
154 | # 终端
155 | # Windows Terminal:"wt -d ${fileDirname}"
156 | # Windows Console:"conhost"(不支持以管理员身份启动)
157 | # 禁用:""
158 | terminal: "wt -d ${fileDirname}"
159 |
160 | # 打开或定位文件后关闭窗口(不对 Everything 默认热键生效)
161 | # 如果想要默认 Enter 热键也关闭窗口,可在 Everything 快捷键选项中将“打开选中对象,并退出 Everything”设置为 Enter
162 | close_everything: true
163 |
164 | # 输入模拟模式
165 | # Auto:v1.5a→WmKey,v1.4→SendInput
166 | # WmKey
167 | # SendInput
168 | input_mode: Auto
169 | ```
170 |
171 | ## 其它
172 | ### 快速启动器
173 | 相较于使用传统的快速启动器,使用 Everything 这类文件搜索器的主要好处是可以实现去中心化——不必将所有的启动入口集中到一个地方,而是可以在任意个文件夹下分散放置启动入口(快捷方式、笔记文件等),不仅降低了维护成本,还能让个人的文件管理结构更加统一,更适合有大量启动入口的情况。
174 |
175 | 若要将 Everything 用作快速启动器,推荐进行以下配置:
176 | 1. 添加运行次数列:右键结果列表表头,选中运行次数
177 | 2. 设置默认按运行次数排序:`选项 → 常规 → 首页 → 排序 → 运行次数(降序)`
178 | 3. 配合扩展的拼音搜索和快速选择启动文件
179 |
180 | 若要更进一步地提高启动效率,可以建立限定路径和扩展名的过滤器或书签,并通过快捷方式或 AutoHotkey 等工具注册全局热键,通过命令行新建 Everything 窗口并应用指定的过滤器或书签。
181 |
182 | ### 硬盘占用分析
183 | * 重复文件
184 | `dupe: sizedupe:`
185 | 其中 `dupe:` 用于限定文件名重复,`sizedupe:` 用于限定文件大小重复。
186 |
187 | 
188 | * 大于 100MB 的文件
189 | `size:>100mb`
190 | * 空文件夹
191 | `empty:`
192 | * Visual Studio 解决方案缓存
193 | `wfn:.vs`
194 |
195 | 
196 |
197 | 或者也可使用基于 Everything 实现的专用于清理 `.vs` 的工具 [VsCacheCleaner](https://github.com/SpriteOvO/VsCacheCleaner)。
198 |
199 | 注意,显示文件夹大小需要在 Everything 选项中开启 `索引 → 索引文件夹大小`。
200 |
201 | 对于文件管理器 [Directory Opus](https://github.com/Chaoses-Ib/DirectoryOpus) 的用户,亦可使用 [IbDOpusExt](https://github.com/Chaoses-Ib/IbDOpusExt) 从 Everything 获取文件夹大小并显示为列,便于分析硬盘占用:
202 | 
203 |
204 | ### 检查更新
205 | `config.yaml` 文件:
206 | ```yaml
207 | # 更新
208 | update:
209 | # 检查更新
210 | check: true
211 |
212 | # 包括预览版
213 | prerelease: false
214 | ```
215 |
216 | ## 开发
217 | 见 [开发](docs/development.md)。
218 |
219 | ## 致谢
220 | 日期 | 捐赠者 | 备注
221 | --- | --- | ---
222 | 2023-04-28 | Xudong.He@CN |
223 | 2024-07-09 | 田昊 \| JLL仲量联行 |
224 |
225 | ## 相关链接
226 | 群组:
227 | - [Telegram 文件管理交流群](https://t.me/IbDirectoryOpusGroup)
228 |
229 | 库:
230 | - [IbPinyinLib: 一个高性能 Rust 拼音匹配库,支持 C、AHK2](https://github.com/Chaoses-Ib/IbPinyinLib)
231 | - [IbDllHijackLib: A C library for Windows DLL hijacking.](https://github.com/Chaoses-Ib/IbDllHijackLib)
232 | - [IbEverythingLib: A C++17 library for voidtool's Everything.](https://github.com/Chaoses-Ib/IbEverythingLib)
233 |
234 | 项目:
235 | - [DirectoryOpus: 一款上手简单、系统集成度高、功能强大的 Windows 文件管理器](https://github.com/Chaoses-Ib/DirectoryOpus)
236 | - [ObsidianShell: 关联 Markdown 文件到 Obsidian](https://github.com/Chaoses-Ib/ObsidianShell)
237 |
--------------------------------------------------------------------------------
/Updater/Updater.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | Win32Proj
24 | {f1492ef6-27c2-44cd-a34b-e55f45da5222}
25 | Updater
26 | 10.0
27 |
28 |
29 |
30 | Application
31 | true
32 | v143
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v143
39 | true
40 | Unicode
41 |
42 |
43 | Application
44 | true
45 | v143
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v143
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | true
75 |
76 |
77 | false
78 |
79 |
80 | true
81 |
82 |
83 | false
84 |
85 |
86 | x64-windows-static-md
87 |
88 |
89 | x64-windows-static-md
90 |
91 |
92 |
93 |
94 | Level3
95 | true
96 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
97 | true
98 | $(SolutionDir)external\build\_deps\ibupdate-src\C++\include
99 | stdcpp20
100 |
101 |
102 | Windows
103 | true
104 |
105 |
106 |
107 |
108 | Level3
109 | true
110 | true
111 | true
112 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
113 | true
114 | $(SolutionDir)external\build\_deps\ibupdate-src\C++\include
115 | stdcpp20
116 |
117 |
118 | Windows
119 | true
120 | true
121 | true
122 |
123 |
124 |
125 |
126 | Level3
127 | true
128 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
129 | true
130 | $(SolutionDir)external\build\_deps\ibupdate-src\C++\include
131 | stdcpp20
132 |
133 |
134 | Windows
135 | true
136 |
137 |
138 |
139 |
140 | Level3
141 | true
142 | true
143 | true
144 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
145 | true
146 | $(SolutionDir)external\build\_deps\ibupdate-src\C++\include
147 | stdcpp20
148 |
149 |
150 | Windows
151 | true
152 | true
153 | true
154 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 | {90572fc6-3f72-3cb1-a7e3-14d1fc6bf226}
163 |
164 |
165 |
166 |
167 |
168 |
--------------------------------------------------------------------------------
/Updater/Updater.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Updater/updater.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | // IbUpdate -> github_api -> cURL
7 | // See https://github.com/microsoft/vcpkg/issues/2621
8 | #pragma comment(lib, "Ws2_32.Lib")
9 | //#pragma comment(lib, "Wldap32.Lib")
10 | #pragma comment(lib, "Crypt32.Lib")
11 |
12 | #pragma comment(lib, "Shlwapi.lib")
13 |
14 | std::wstring u8_to_u16(std::string u8) {
15 | int u16_size = MultiByteToWideChar(CP_UTF8, 0, u8.c_str(), (int)u8.length(), nullptr, 0);
16 | std::wstring u16(u16_size, L'\0');
17 | MultiByteToWideChar(CP_UTF8, 0, u8.c_str(), (int)u8.length(), u16.data(), u16_size);
18 | return u16;
19 | }
20 |
21 | ///
22 | ///
23 | ///
24 | ///
25 | ///
26 | /// Ends with '\n'
27 | std::string truncate_lines(std::string s, size_t lines) {
28 | std::istringstream in(s);
29 | std::ostringstream out;
30 |
31 | size_t i = 0;
32 | for (std::string line; i < lines && std::getline(in, line); i++) {
33 | out << line << '\n';
34 | }
35 | if (i == lines)
36 | out << (const char*)u8"……\n";
37 | return out.str();
38 | }
39 |
40 | bool check_for_update(bool prerelease, bool quiet, bool silent_error) {
41 | try {
42 | GitHubUpdater updater{ "Chaoses-Ib", "IbEverythingExt", "v0.6-alpha.5" };
43 | YAML::Node release = updater.check_for_new_release(prerelease);
44 | if (release.IsNull()) {
45 | if (!quiet)
46 | MessageBoxW(nullptr, L"无可用更新", L"IbEverythingExt", MB_ICONINFORMATION);
47 | return true;
48 | }
49 |
50 | std::wostringstream ss;
51 | ss << L"检测到新版本 " << u8_to_u16(release["tag_name"].as())
52 | << L"\n发布时间:" << u8_to_u16(release["published_at"].as())
53 | << L"\n更新内容:\n" << u8_to_u16(truncate_lines(release["body"].as(), 10))
54 | << L"\n是否打开发布页面?";
55 | if (MessageBoxW(nullptr, ss.str().c_str(), L"IbEverythingExt", MB_ICONINFORMATION | MB_YESNO) == IDYES) {
56 | ShellExecuteW(nullptr, nullptr, u8_to_u16(release["html_url"].as()).c_str(), nullptr, nullptr, SW_SHOWNORMAL);
57 | }
58 | return true;
59 | }
60 | catch (std::runtime_error& e) {
61 | if (!silent_error) {
62 | std::ostringstream ss;
63 | ss << "检查更新失败:\n" << e.what();
64 | MessageBoxA(nullptr, ss.str().c_str(), "IbEverythingExt", MB_ICONWARNING);
65 | }
66 | return false;
67 | }
68 | }
69 |
70 | int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR lpCmdLine, int nShowCmd) {
71 | using namespace std::literals;
72 |
73 | // lpCmdLine is empty for unknown reason
74 | //MessageBoxW(nullptr, lpCmdLine, nullptr, 0);
75 | //MessageBoxW(nullptr, GetCommandLineW(), nullptr, 0);
76 | lpCmdLine = GetCommandLineW();
77 |
78 | bool quiet = false;
79 | if (std::wstring_view(lpCmdLine) == L"--quiet")
80 | quiet = true;
81 |
82 | wchar_t path[MAX_PATH];
83 | GetModuleFileNameW(nullptr, path, std::size(path));
84 | PathRemoveFileSpecW(path);
85 | PathAppendW(path, L"config.yaml");
86 |
87 | std::ifstream in(path);
88 | if (!in) {
89 | MessageBoxW(nullptr, L"配置文件 config.yaml 不存在!", L"IbEverythingExt", MB_ICONERROR);
90 | return 1;
91 | }
92 | try {
93 | YAML::Node root = YAML::Load(in);
94 | YAML::Node update = root["update"];
95 | if (update["check"].as()) {
96 | // try twice
97 | if (!check_for_update(update["prerelease"].as(), quiet, true))
98 | check_for_update(update["prerelease"].as(), quiet, false);
99 | }
100 | }
101 | catch (YAML::Exception& e) {
102 | MessageBoxA(nullptr, ("配置文件读取错误:\n"s + e.what()).c_str(), "IbEverythingExt", MB_ICONERROR);
103 | return 1;
104 | }
105 | return 0;
106 | }
--------------------------------------------------------------------------------
/docs/Disk space/images/VisualStudio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Chaoses-Ib/IbEverythingExt/6c5b33636eaae51e9eea48e7d1434c579053a668/docs/Disk space/images/VisualStudio.png
--------------------------------------------------------------------------------
/docs/Disk space/images/dupe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Chaoses-Ib/IbEverythingExt/6c5b33636eaae51e9eea48e7d1434c579053a668/docs/Disk space/images/dupe.png
--------------------------------------------------------------------------------
/docs/development.md:
--------------------------------------------------------------------------------
1 | # 开发
2 | ## 构建
3 | [vcpkg](https://github.com/microsoft/vcpkg):
4 | ```cmd
5 | vcpkg install fmt detours yaml-cpp curl --triplet=x64-windows-static-md
6 | ```
7 | [CMake](https://cliutils.gitlab.io/modern-cmake/):
8 | ```cmd
9 | cd IbEverythingExt
10 | cd external
11 | cmake -B build -DCMAKE_TOOLCHAIN_FILE="C:\...\vcpkg\scripts\buildsystems\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=x64-windows-static-md
12 | ```
13 |
14 | 对于 test 还需要:
15 | ```
16 | vcpkg install boost-test pcre pcre2 --triplet=x64-windows-static-md
17 | ```
18 |
19 | ## Bump version
20 | - EverythingExt\resource.rc
21 | - Updater\updater.cpp
--------------------------------------------------------------------------------
/docs/pinyin_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Chaoses-Ib/IbEverythingExt/6c5b33636eaae51e9eea48e7d1434c579053a668/docs/pinyin_search.png
--------------------------------------------------------------------------------
/docs/pinyin_search/edit_mode.md:
--------------------------------------------------------------------------------
1 | # Edit 模式(停止维护)
2 | * 默认小写字母匹配拼音或字母,大写字母只匹配字母。
3 | * 只支持简拼搜索。
4 | * 支持多音字和 Unicode 辅助平面汉字。
5 | * 支持 Everything x64 安装版和便携版,不支持精简版。
6 | * 修饰符:
7 | * `py:` 小写字母只匹配拼音
8 | * `nopy:` 禁用拼音搜索(对所有关键字生效)
9 | * 出于稳定性考虑,Edit 模式只支持 [第三方程序](../third_party/README.md) 中列出的第三方程序。
10 |
11 | 
12 |
13 | 已知问题:
14 | * [搜索历史功能破坏 #4](https://github.com/Chaoses-Ib/IbEverythingExt/issues/4)
15 | * [不支持正则表达式 #8](https://github.com/Chaoses-Ib/IbEverythingExt/issues/8)
16 | * [提高性能 #13](https://github.com/Chaoses-Ib/IbEverythingExt/issues/13)
17 | * [拼音搜索不支持命令行搜索选项 #26](https://github.com/Chaoses-Ib/IbEverythingExt/issues/26)
18 | * [filters don't wrok #32](https://github.com/Chaoses-Ib/IbEverythingExt/issues/32)
19 | * [输入搜索并切换窗口,everything输入框出现乱码 #33](https://github.com/Chaoses-Ib/IbEverythingExt/issues/33)
20 | * [搜索框中文输入变成从右至左了 #38](https://github.com/Chaoses-Ib/IbEverythingExt/issues/38)
--------------------------------------------------------------------------------
/docs/pinyin_search/edit_mode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Chaoses-Ib/IbEverythingExt/6c5b33636eaae51e9eea48e7d1434c579053a668/docs/pinyin_search/edit_mode.png
--------------------------------------------------------------------------------
/docs/preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Chaoses-Ib/IbEverythingExt/6c5b33636eaae51e9eea48e7d1434c579053a668/docs/preview.png
--------------------------------------------------------------------------------
/docs/quick_select_dark_mode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Chaoses-Ib/IbEverythingExt/6c5b33636eaae51e9eea48e7d1434c579053a668/docs/quick_select_dark_mode.png
--------------------------------------------------------------------------------
/docs/third_party/EverythingToolbar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Chaoses-Ib/IbEverythingExt/6c5b33636eaae51e9eea48e7d1434c579053a668/docs/third_party/EverythingToolbar.png
--------------------------------------------------------------------------------
/docs/third_party/FlowLauncher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Chaoses-Ib/IbEverythingExt/6c5b33636eaae51e9eea48e7d1434c579053a668/docs/third_party/FlowLauncher.png
--------------------------------------------------------------------------------
/docs/third_party/HuoChat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Chaoses-Ib/IbEverythingExt/6c5b33636eaae51e9eea48e7d1434c579053a668/docs/third_party/HuoChat.png
--------------------------------------------------------------------------------
/docs/third_party/PowerToys.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Chaoses-Ib/IbEverythingExt/6c5b33636eaae51e9eea48e7d1434c579053a668/docs/third_party/PowerToys.png
--------------------------------------------------------------------------------
/docs/third_party/README.md:
--------------------------------------------------------------------------------
1 | # 第三方程序
2 | ## [EverythingToolbar](https://github.com/stnkl/EverythingToolbar)
3 | > Everything integration for the Windows taskbar.
4 |
5 |
6 |
7 | ## [Flow Launcher](https://github.com/Flow-Launcher/Flow.Launcher)
8 | > Quick file search & app launcher for Windows with community-made plugins.
9 |
10 | [Everything 插件](https://github.com/Flow-Launcher/Flow.Launcher.Plugin.Everything):
11 |
12 |
13 | ## [PowerToys Run](https://learn.microsoft.com/windows/powertoys/run)
14 | [Everything 插件](https://github.com/lin-ycv/EverythingPowerToys):
15 |
16 |
17 | ## [uTools](https://u.tools)
18 | > 新一代效率工具平台
19 | > 自由组合丰富插件,打造随手可取的终极神器
20 |
21 | 本地搜索:
22 |
23 |
24 | ## [Wox](https://github.com/Wox-launcher/Wox)
25 | > Launcher for Windows, an alternative to Alfred and Launchy.
26 |
27 | Everything 插件:
28 |
29 |
30 | ## [火柴(火萤酱)](https://www.huochaipro.com/)
31 | > “电脑必备,效率神器。快速查找文件、打开应用程序、局域网秒传文件、局域网聊天...”
32 |
33 | 本地搜索:
34 |
35 |
36 | ## [Total Commander](https://www.ghisler.com/)
37 | > Total Commander is a Shareware file manager for Windows® 95/98/ME/NT/2000/XP/Vista/7/8/8.1/10/11, and Windows® 3.1.
38 |
39 | 由于 TC 调用 Everything 搜索时是先获取所有文件,再通过自己的匹配机制匹配文件,扩展的拼音搜索无法对 TC 生效。
--------------------------------------------------------------------------------
/docs/third_party/Wox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Chaoses-Ib/IbEverythingExt/6c5b33636eaae51e9eea48e7d1434c579053a668/docs/third_party/Wox.png
--------------------------------------------------------------------------------
/docs/third_party/uTools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Chaoses-Ib/IbEverythingExt/6c5b33636eaae51e9eea48e7d1434c579053a668/docs/third_party/uTools.png
--------------------------------------------------------------------------------
/external/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.14)
2 |
3 | project(external)
4 |
5 | include(FetchContent)
6 | FetchContent_Declare(IbWinCpp
7 | GIT_REPOSITORY https://github.com/Chaoses-Ib/IbWinCppLib.git
8 | GIT_TAG a29ac95537f403ac5ae221cb744d3e82076efbf7
9 | )
10 | FetchContent_Declare(IbDllHijack
11 | GIT_REPOSITORY https://github.com/Chaoses-Ib/IbDllHijackLib.git
12 | GIT_TAG a82533aff8a73129aee2a3757069f7aa89e7dd6a
13 | )
14 | FetchContent_Declare(IbEverything
15 | GIT_REPOSITORY https://github.com/Chaoses-Ib/IbEverythingLib.git
16 | GIT_TAG 0fda1b6a2db79112b08ebdfb1443a84959ddc042
17 | )
18 | FetchContent_Declare(IbPinyin
19 | GIT_REPOSITORY https://github.com/Chaoses-Ib/IbPinyinLib.git
20 | GIT_TAG e576e81ca06a297436bba7b124630b5d64e3106f
21 | )
22 | FetchContent_Declare(IbUpdate
23 | GIT_REPOSITORY https://github.com/Chaoses-Ib/IbUpdateLib.git
24 | GIT_TAG eaa36c76e29409aeb89b1d7f493f48d0b54d819c
25 | )
26 | FetchContent_Declare(sigmatch
27 | GIT_REPOSITORY https://github.com/SpriteOvO/sigmatch.git
28 | GIT_TAG 2ca983dc0cb78fe4f4406b67655e7ee132ecf5da
29 | )
30 | FetchContent_MakeAvailable(IbWinCpp IbDllHijack IbEverything IbPinyin IbUpdate sigmatch)
--------------------------------------------------------------------------------
/test/common.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #pragma comment(lib, "winmm.lib")
9 |
10 | using namespace std::literals;
11 |
12 | // GBK
13 | inline std::wstring pinyin_regex = L"〇一丂与业丣严丫丿乁乂么义乊乐乑乙乚乛也乵乻亄予于-云亚亜亞亦亪亱亴亿仡以仪仰仸伃伇伊伒众优伛伝伢伿佁但佑佒佗余佚佣佯佻佾侇侌侑依侥俁俋俑俓俞俣俨俹俺俼倄倚倻偀偃偊偐偞偠偣偤偯傆傊傛傜傟傭傴傿僌僥僪僷儀億儗儥優儼允元兖兗兪养兿円冘冝冤冶凐刈刖剈剡剦劓劜劮劷勇勈勚勜勩勻匀匇匋匜匬医匽卣卬印厂厃厊压厌厑厓原厡厣厭厳厴厵又友叕台右叶叹吁吆吋吔吖吚吟听吲吳吾呀呎呓员呦呭呹呾咉咏咦咬咽咿哊哑哕哟員哩哽哾唀唁唈唌唖唡唫唷唹啘啞啢啨啱喁喅喐喑喓喗喛喝喦喩喭喲営喻嗂嗈嗌嘢嘤噊噎噖噞噟噢噦噫噮噰噳噾嚈嚘-嚛嚥嚴嚶囈囐囙囝因囦囩园囿圁圄圆圉圎園圓圔圛圜圠圧圩圪圫圯圻坄均块坨坱坳垔垚垟垠垣垦垭垸垼垽埇埏埜域埡埯埶埸堉堊堐堙堣堨堬堯堰堷塋塎塩塬墅墉墕墷墿壄壅壓壛壧壱壹夁夃夕夗夜夤夭央失夵夷夽奄奇奕奥奫妁妋妍妖妘妜妟妤妧妪妴妷姎姚姨姬姲姶姷姸姻娅娛娪娫娮娯娱婣婬婭婴婸婹媀媐媕媖媛媪媮媱媴媵嫄嫈嫕嫗嫚嫛嫞嫣嬄嬈嬊嬐嬑嬟嬩嬮嬰嬳嬴嬽嬿孆孍孕孧孲孴孾它宇宎宐宛宜宥宧宴容寃寅寓寙寱寲射將尉尢尤尧尭尹尾屵屹屿岄岆岈岟岩岳峄峓峟峣峪峫峳峾峿崎崕崖崛崟崤崦崯崳崵崸崺崾嵃嵎嵒嵓嵛嵤嵱嶎嶖嶢嶤嶧嶪嶫嶬嶮嶷嶼嶽嶾巆巊巌巖巗巘巚巡已巳巸币帟帠幆幺幼幽广庌应庘庡庮庵庸庽庾廕廙廮廱廴延异弇弈弋弌引弬弲彛-彠彥彦彧彮影彵役徉御徭徼忆忔応忧忬怈怏怞怠怡怣怨怮怺怿恌恙恞恱恹恽恿悀悁悅悆悇悒悘悠悥悦惌惐惥惲愈愉意愑愓愔愚愝愠愥愪愮愹愿慂慃慇慍慭慵慾憂憖憗憶應懊懌懕懙懚懨懩懮懿戉或戫戭戲戺扅扆扊扚扜扡扬扰扵抁抈抎抑抣抭抰抴押拁拗拥拸拽挜挧挹挻捐捓捙捝捥捳掎掖掗掜掞掩掾揂揄揅揖揘揚揜揞揠揲援揶揺搋搖搤摇摬摿撄撎撽擁擇擖擛擨擪擫擽攁攍攖攸攺敔敡敥敭敼斁斔斜斞斦於施斿旑旕旖旟旲旸昀昂易昖昙昜映昱昳晏晔晕景晹晻暆暈暍暎暘暚暥曀曄曅曎曕曗曜曣曮曰曱曳曵朄月有朓朠札杅杙杝杨杬杳枂枍枒枖枟枻枼枽柂柍柚柡柼栎栐栘栧栩栯栶样栺桋桙桜桠桯梀梄梎梧梬棛棜棩棪棫棭椅椏椬椰椸椻椼楀楆楊楌楡楢楥楧楪業楰楹榅榆榏榚榞榣榬様槦槱槷槸樂樣樮樱樴樾橒橪橼檃檍檐檥檭檹檼檿櫌櫞櫟櫩櫲櫻櫽櫾櫿欎欕欝欤欥欭欲欹欽歅歇歈歋歍歖歝歟歶殀殃殒殔殕殗殞殥殪殷殹殽毅毉毓毹氀氜氤氧氩氬氱氲氳永汋汓汙汧汩汼汽沂沄沅沇沋沶油沿泂泄泅泆泑泱泳泿洂洇洋洕洝洢洩洫洮浂浟浥浧浳浴涂涌涎涒涓涢涯液涴淊淡淢淤淫淯淵淹淾渁渆渊渏渔渕渝温渫渰渶渷游湙湚湛湡湧湮湯湲湵溁溋溎源溒溔溢溳溵滎滛滟滢滧滪滺滽漁漄演漜漪漹漾潁潆潏潒潝潩潭潯潱澐澚澞澤澦澭澲澳澺濙濚濥濦濴瀀瀁瀅瀛瀠瀯瀴瀷瀹灁灉灎灐灔灜灧灩灪灹炀炈炎炏炴烄烊烎烏烑烟烨烻焆焉焑焔焬焰焱焲焴焸煇煐煙煜煠煨煬煴煾熀熅熉熎熒熖熙熠熤熨熪熼燁燄燏燕燚營燠燡燱燿爍爓爗爚爩爰爷爺爻牅牏牖牗牙牪牰犄犹犽犾狁狋狏狕狖狠狱狳狺狿猌猒猗猚猨猰猶猷猺猿獂獄獈獝獟獶玅玉王玗玙玚玡玥玧玪玴珆珚珜珢珧珱琂琊琙琟琰瑀瑒瑗瑘瑛瑜瑤瑩瑶瑿璌璍璎璵瓔瓛瓵甇甖甗用甬由甴甸畇畩畬畭異畹疋疑疙疟疡疣疨疫痈痍痏痒痖痬痷瘀瘂瘉瘍瘐瘖瘗瘞瘟瘧瘱瘾瘿癊癌癒癔癕癢癭癮癰皣盁盂盈益盐盓盶盾眃眏眑眙眢眻眼睚睪睮瞖瞱瞸矅矆矞矣矨矱砑研砚砡砽硍硏硛硢硧硪硬硯硲硽碒碞碣碤磍磒磘磤礇礏礒礖礙礜礢礯礹礿祅祎祐祤禉禋禐禓禕禜禦禴禹禺秇秐秗秞秧秵移稏稢稦稶穎穓穥穵穻穾穿窅窈窑窔窨窫窬窯窰窳竩竽笌笎笖筃筄筍筠筩筵筼箊箢箷箹篔篗篶篽簃簷籅籆籎籝籞籥籯籰籲粌粤粥粵糿約紆紜紲紻絏絪綖維綺緎緓緣緤緰緷緸緼縁縈縊縕縜縯繄繇繘繧繩繶繹纅纋纓纡约纭绎绬缊缘缢缨罂罃罌罨罭羊羏羐羑羕羗羛羠羡義羪羬羭羱羽羿翊翌翳翼耀耘耛耰耴耶耺聈聐聱聶聿肀肄肊肙肬育肴胤胦胭胰脜脩腋腌腧腪腰腴膁膉膡膺臃臆臒臙臾舀舁舆與舒舣艅艈艗艞艤艳艶艷艺艾芅芋芌芩芫芸芽苂苃苅苑苚苡苢苭英茒茔茚茟茰茵荑荥荧荫药荶荺荼莖莚莜莠莤莸莹莺菀菴菸萒萓萟萤营萦萭萮萸萾葉葕葯葽葾蒀蒏蒑蒕蒝蒬蒮蒷蓔蓣蓥蓹蓺蔅蔚蔩蔫蔭蕍蕓蕕蕘蕥蕰蕴蕷蕹薀薁薏薗薟薬薳藀藇藙藝藥藴蘊蘌蘙蘛蘟蘡蘥蘨虉虞虤虵虶蚁蚎蚏蚓蚖蚘蚜蚰蚴蛇蛍蛘蛜蛡蛦蛹蛾蜍蜎蜏蜒蜕蜟蜮蜴蜵蝆蝇蝓蝘蝝蝣蝤蝧蝯蝹蝺蝿螈螔螘螠螢螸螾蟈蟫蟻蠅蠖蠮蠱蠳衍衏衘衙衣衤衧衪衵袁袂袎袘袣袬裀裔裕裛裫裷裺裿褎褑褕褗褘褞褤褮褹襗襼襾要覃覎覞覦覮觃觎觺觾言訁訑訔訚訝訞訡訢訧訮訲訳詇詍詏詑詒詠詣詳詽誃誉誒誘語説誼誾諛諭諲諹諺謁謍謚謜謠謡謣謻譍譩譯議譺譻譽讉讌讑讔讛讞讠议讶译诒诣语诱说谀谊谒谕谚谣谳谷豓豔豙豛豣豫豷貁貍貐貖貗貟貤貽賏賱賹贀贇贋贏贗贠贻赝赟赢赺越趛趯趼跀跃跇跠踊踦踰踴躍躒躽軅軈軉軋軏軮軺軼輅輍輏輐輑輗輢輰輵輶輼輿轅轙轝轧轶轺辕辥辷込迂迃迆迎运迓远迤迭迱迶迻逌逘這逞逰逳逸逺逾遃遇遊運遗遙遠遥遹遺邀邍邎邑邕邘邧邪邮邺郁郓郔郚郢郧郵郺郼郾鄅鄆鄓鄖鄘鄞鄢鄴鄾酀酉酏酑酓酛酝酭酳酽醃醖醞醟醧醫醳醶醷醼釅釉釋野釔釪釴釶釾釿鈅鈏鈗鈘鈝鈠鈨鈺鈾鉇鉈鉛鉞鉠鉯銀銉銕銚銥銦銪銹銿鋆鋊鋋鋙鋣鋭鋺錏錟錡錥鍈鍚鍝鍱鎁鎐鎑鎣鎰鎱鏔鏞鐊鐍鐚鐛鐭鐷鐿鑍鑠鑰钀钇钖钥钰钺铀铅铔铕铘铟铫铱银铻锳镒镛镱閆閘閱閲閹閻閼閾闄闇闉闫阅阈阉阎阏阣-阦阭阮阳阴阽陁陓院陨陭陰陶陻陽隁隂隃隅隐隒隕隠隩險隱隶隿雁雅雉雍雓雝雨雩雲雵霅霒霙霠霣霪霬霱霷靉靥靨靷靾靿鞅鞇鞕韗韞韫音韵韹韺韻韾頁頉預頤頥頨頴頵顊顏顑顒顔顗願顤顩页预颍颐颕颖颙颜颺颻飏飖食飫飬飮飲飴餆養餍餘餚餣餫饁饇饐饔饜饫饮饴馀馌馧馭馻駀駅駌駚駰騐験騕騟騴騵驁驈驗驛驜驠驭驿骃验骬骮髃髺鬰鬱鬳鬻魇魊魘魚魣魭魷鮋鮣鮧鮨鮽鯈鯒鯣鯲鰅鰋鰑鰩鰫鱅鱊鱦鱮鱼鱿鲉鲬鳐鳙鳦鳫鳱鳶鳿鴁鴈鴉鴛鴢鴥-鴨鴪鴬鴳鴹鴺鵒鵪鵶鵷鵺鶂鶃鶍鶑鶠鶢鶧鶯鶰鷁鷂鷃鷊鷕鷖鷛鷠鷣鷧鷪鷰鷸鷹鷾鸃鸆鸈鸉鸎鸑鸒鸙鸚鸢鸦鸭鸯鸳鹆鹓鹝鹞鹢鹥鹦鹬鹰鹽麀麌麙麣麲黓黝黟黡黤黦黫黬黭黰黳黶黿鼋鼘鼝鼬鼴鼹鼼齖齗齞齦齩齫齬齮齳齴齵齸齾龂龈龉龑龠龥";
14 | inline std::wstring pinyin_branch = L"〇|一|丂|与|业|丣|严|丫|丿|乁|乂|么|义|乊|乐|乑|乙|乚|乛|也|乵|乻|亄|予|于|亏|亐|云|亚|亜|亞|亦|亪|亱|亴|亿|仡|以|仪|仰|仸|伃|伇|伊|伒|众|优|伛|伝|伢|伿|佁|但|佑|佒|佗|余|佚|佣|佯|佻|佾|侇|侌|侑|依|侥|俁|俋|俑|俓|俞|俣|俨|俹|俺|俼|倄|倚|倻|偀|偃|偊|偐|偞|偠|偣|偤|偯|傆|傊|傛|傜|傟|傭|傴|傿|僌|僥|僪|僷|儀|億|儗|儥|優|儼|允|元|兖|兗|兪|养|兿|円|冘|冝|冤|冶|凐|刈|刖|剈|剡|剦|劓|劜|劮|劷|勇|勈|勚|勜|勩|勻|匀|匇|匋|匜|匬|医|匽|卣|卬|印|厂|厃|厊|压|厌|厑|厓|原|厡|厣|厭|厳|厴|厵|又|友|叕|台|右|叶|叹|吁|吆|吋|吔|吖|吚|吟|听|吲|吳|吾|呀|呎|呓|员|呦|呭|呹|呾|咉|咏|咦|咬|咽|咿|哊|哑|哕|哟|員|哩|哽|哾|唀|唁|唈|唌|唖|唡|唫|唷|唹|啘|啞|啢|啨|啱|喁|喅|喐|喑|喓|喗|喛|喝|喦|喩|喭|喲|営|喻|嗂|嗈|嗌|嘢|嘤|噊|噎|噖|噞|噟|噢|噦|噫|噮|噰|噳|噾|嚈|嚘|嚙|嚚|嚛|嚥|嚴|嚶|囈|囐|囙|囝|因|囦|囩|园|囿|圁|圄|圆|圉|圎|園|圓|圔|圛|圜|圠|圧|圩|圪|圫|圯|圻|坄|均|块|坨|坱|坳|垔|垚|垟|垠|垣|垦|垭|垸|垼|垽|埇|埏|埜|域|埡|埯|埶|埸|堉|堊|堐|堙|堣|堨|堬|堯|堰|堷|塋|塎|塩|塬|墅|墉|墕|墷|墿|壄|壅|壓|壛|壧|壱|壹|夁|夃|夕|夗|夜|夤|夭|央|失|夵|夷|夽|奄|奇|奕|奥|奫|妁|妋|妍|妖|妘|妜|妟|妤|妧|妪|妴|妷|姎|姚|姨|姬|姲|姶|姷|姸|姻|娅|娛|娪|娫|娮|娯|娱|婣|婬|婭|婴|婸|婹|媀|媐|媕|媖|媛|媪|媮|媱|媴|媵|嫄|嫈|嫕|嫗|嫚|嫛|嫞|嫣|嬄|嬈|嬊|嬐|嬑|嬟|嬩|嬮|嬰|嬳|嬴|嬽|嬿|孆|孍|孕|孧|孲|孴|孾|它|宇|宎|宐|宛|宜|宥|宧|宴|容|寃|寅|寓|寙|寱|寲|射|將|尉|尢|尤|尧|尭|尹|尾|屵|屹|屿|岄|岆|岈|岟|岩|岳|峄|峓|峟|峣|峪|峫|峳|峾|峿|崎|崕|崖|崛|崟|崤|崦|崯|崳|崵|崸|崺|崾|嵃|嵎|嵒|嵓|嵛|嵤|嵱|嶎|嶖|嶢|嶤|嶧|嶪|嶫|嶬|嶮|嶷|嶼|嶽|嶾|巆|巊|巌|巖|巗|巘|巚|巡|已|巳|巸|币|帟|帠|幆|幺|幼|幽|广|庌|应|庘|庡|庮|庵|庸|庽|庾|廕|廙|廮|廱|廴|延|异|弇|弈|弋|弌|引|弬|弲|彛|彜|彝|彞|彟|彠|彥|彦|彧|彮|影|彵|役|徉|御|徭|徼|忆|忔|応|忧|忬|怈|怏|怞|怠|怡|怣|怨|怮|怺|怿|恌|恙|恞|恱|恹|恽|恿|悀|悁|悅|悆|悇|悒|悘|悠|悥|悦|惌|惐|惥|惲|愈|愉|意|愑|愓|愔|愚|愝|愠|愥|愪|愮|愹|愿|慂|慃|慇|慍|慭|慵|慾|憂|憖|憗|憶|應|懊|懌|懕|懙|懚|懨|懩|懮|懿|戉|或|戫|戭|戲|戺|扅|扆|扊|扚|扜|扡|扬|扰|扵|抁|抈|抎|抑|抣|抭|抰|抴|押|拁|拗|拥|拸|拽|挜|挧|挹|挻|捐|捓|捙|捝|捥|捳|掎|掖|掗|掜|掞|掩|掾|揂|揄|揅|揖|揘|揚|揜|揞|揠|揲|援|揶|揺|搋|搖|搤|摇|摬|摿|撄|撎|撽|擁|擇|擖|擛|擨|擪|擫|擽|攁|攍|攖|攸|攺|敔|敡|敥|敭|敼|斁|斔|斜|斞|斦|於|施|斿|旑|旕|旖|旟|旲|旸|昀|昂|易|昖|昙|昜|映|昱|昳|晏|晔|晕|景|晹|晻|暆|暈|暍|暎|暘|暚|暥|曀|曄|曅|曎|曕|曗|曜|曣|曮|曰|曱|曳|曵|朄|月|有|朓|朠|札|杅|杙|杝|杨|杬|杳|枂|枍|枒|枖|枟|枻|枼|枽|柂|柍|柚|柡|柼|栎|栐|栘|栧|栩|栯|栶|样|栺|桋|桙|桜|桠|桯|梀|梄|梎|梧|梬|棛|棜|棩|棪|棫|棭|椅|椏|椬|椰|椸|椻|椼|楀|楆|楊|楌|楡|楢|楥|楧|楪|業|楰|楹|榅|榆|榏|榚|榞|榣|榬|様|槦|槱|槷|槸|樂|樣|樮|樱|樴|樾|橒|橪|橼|檃|檍|檐|檥|檭|檹|檼|檿|櫌|櫞|櫟|櫩|櫲|櫻|櫽|櫾|櫿|欎|欕|欝|欤|欥|欭|欲|欹|欽|歅|歇|歈|歋|歍|歖|歝|歟|歶|殀|殃|殒|殔|殕|殗|殞|殥|殪|殷|殹|殽|毅|毉|毓|毹|氀|氜|氤|氧|氩|氬|氱|氲|氳|永|汋|汓|汙|汧|汩|汼|汽|沂|沄|沅|沇|沋|沶|油|沿|泂|泄|泅|泆|泑|泱|泳|泿|洂|洇|洋|洕|洝|洢|洩|洫|洮|浂|浟|浥|浧|浳|浴|涂|涌|涎|涒|涓|涢|涯|液|涴|淊|淡|淢|淤|淫|淯|淵|淹|淾|渁|渆|渊|渏|渔|渕|渝|温|渫|渰|渶|渷|游|湙|湚|湛|湡|湧|湮|湯|湲|湵|溁|溋|溎|源|溒|溔|溢|溳|溵|滎|滛|滟|滢|滧|滪|滺|滽|漁|漄|演|漜|漪|漹|漾|潁|潆|潏|潒|潝|潩|潭|潯|潱|澐|澚|澞|澤|澦|澭|澲|澳|澺|濙|濚|濥|濦|濴|瀀|瀁|瀅|瀛|瀠|瀯|瀴|瀷|瀹|灁|灉|灎|灐|灔|灜|灧|灩|灪|灹|炀|炈|炎|炏|炴|烄|烊|烎|烏|烑|烟|烨|烻|焆|焉|焑|焔|焬|焰|焱|焲|焴|焸|煇|煐|煙|煜|煠|煨|煬|煴|煾|熀|熅|熉|熎|熒|熖|熙|熠|熤|熨|熪|熼|燁|燄|燏|燕|燚|營|燠|燡|燱|燿|爍|爓|爗|爚|爩|爰|爷|爺|爻|牅|牏|牖|牗|牙|牪|牰|犄|犹|犽|犾|狁|狋|狏|狕|狖|狠|狱|狳|狺|狿|猌|猒|猗|猚|猨|猰|猶|猷|猺|猿|獂|獄|獈|獝|獟|獶|玅|玉|王|玗|玙|玚|玡|玥|玧|玪|玴|珆|珚|珜|珢|珧|珱|琂|琊|琙|琟|琰|瑀|瑒|瑗|瑘|瑛|瑜|瑤|瑩|瑶|瑿|璌|璍|璎|璵|瓔|瓛|瓵|甇|甖|甗|用|甬|由|甴|甸|畇|畩|畬|畭|異|畹|疋|疑|疙|疟|疡|疣|疨|疫|痈|痍|痏|痒|痖|痬|痷|瘀|瘂|瘉|瘍|瘐|瘖|瘗|瘞|瘟|瘧|瘱|瘾|瘿|癊|癌|癒|癔|癕|癢|癭|癮|癰|皣|盁|盂|盈|益|盐|盓|盶|盾|眃|眏|眑|眙|眢|眻|眼|睚|睪|睮|瞖|瞱|瞸|矅|矆|矞|矣|矨|矱|砑|研|砚|砡|砽|硍|硏|硛|硢|硧|硪|硬|硯|硲|硽|碒|碞|碣|碤|磍|磒|磘|磤|礇|礏|礒|礖|礙|礜|礢|礯|礹|礿|祅|祎|祐|祤|禉|禋|禐|禓|禕|禜|禦|禴|禹|禺|秇|秐|秗|秞|秧|秵|移|稏|稢|稦|稶|穎|穓|穥|穵|穻|穾|穿|窅|窈|窑|窔|窨|窫|窬|窯|窰|窳|竩|竽|笌|笎|笖|筃|筄|筍|筠|筩|筵|筼|箊|箢|箷|箹|篔|篗|篶|篽|簃|簷|籅|籆|籎|籝|籞|籥|籯|籰|籲|粌|粤|粥|粵|糿|約|紆|紜|紲|紻|絏|絪|綖|維|綺|緎|緓|緣|緤|緰|緷|緸|緼|縁|縈|縊|縕|縜|縯|繄|繇|繘|繧|繩|繶|繹|纅|纋|纓|纡|约|纭|绎|绬|缊|缘|缢|缨|罂|罃|罌|罨|罭|羊|羏|羐|羑|羕|羗|羛|羠|羡|義|羪|羬|羭|羱|羽|羿|翊|翌|翳|翼|耀|耘|耛|耰|耴|耶|耺|聈|聐|聱|聶|聿|肀|肄|肊|肙|肬|育|肴|胤|胦|胭|胰|脜|脩|腋|腌|腧|腪|腰|腴|膁|膉|膡|膺|臃|臆|臒|臙|臾|舀|舁|舆|與|舒|舣|艅|艈|艗|艞|艤|艳|艶|艷|艺|艾|芅|芋|芌|芩|芫|芸|芽|苂|苃|苅|苑|苚|苡|苢|苭|英|茒|茔|茚|茟|茰|茵|荑|荥|荧|荫|药|荶|荺|荼|莖|莚|莜|莠|莤|莸|莹|莺|菀|菴|菸|萒|萓|萟|萤|营|萦|萭|萮|萸|萾|葉|葕|葯|葽|葾|蒀|蒏|蒑|蒕|蒝|蒬|蒮|蒷|蓔|蓣|蓥|蓹|蓺|蔅|蔚|蔩|蔫|蔭|蕍|蕓|蕕|蕘|蕥|蕰|蕴|蕷|蕹|薀|薁|薏|薗|薟|薬|薳|藀|藇|藙|藝|藥|藴|蘊|蘌|蘙|蘛|蘟|蘡|蘥|蘨|虉|虞|虤|虵|虶|蚁|蚎|蚏|蚓|蚖|蚘|蚜|蚰|蚴|蛇|蛍|蛘|蛜|蛡|蛦|蛹|蛾|蜍|蜎|蜏|蜒|蜕|蜟|蜮|蜴|蜵|蝆|蝇|蝓|蝘|蝝|蝣|蝤|蝧|蝯|蝹|蝺|蝿|螈|螔|螘|螠|螢|螸|螾|蟈|蟫|蟻|蠅|蠖|蠮|蠱|蠳|衍|衏|衘|衙|衣|衤|衧|衪|衵|袁|袂|袎|袘|袣|袬|裀|裔|裕|裛|裫|裷|裺|裿|褎|褑|褕|褗|褘|褞|褤|褮|褹|襗|襼|襾|要|覃|覎|覞|覦|覮|觃|觎|觺|觾|言|訁|訑|訔|訚|訝|訞|訡|訢|訧|訮|訲|訳|詇|詍|詏|詑|詒|詠|詣|詳|詽|誃|誉|誒|誘|語|説|誼|誾|諛|諭|諲|諹|諺|謁|謍|謚|謜|謠|謡|謣|謻|譍|譩|譯|議|譺|譻|譽|讉|讌|讑|讔|讛|讞|讠|议|讶|译|诒|诣|语|诱|说|谀|谊|谒|谕|谚|谣|谳|谷|豓|豔|豙|豛|豣|豫|豷|貁|貍|貐|貖|貗|貟|貤|貽|賏|賱|賹|贀|贇|贋|贏|贗|贠|贻|赝|赟|赢|赺|越|趛|趯|趼|跀|跃|跇|跠|踊|踦|踰|踴|躍|躒|躽|軅|軈|軉|軋|軏|軮|軺|軼|輅|輍|輏|輐|輑|輗|輢|輰|輵|輶|輼|輿|轅|轙|轝|轧|轶|轺|辕|辥|辷|込|迂|迃|迆|迎|运|迓|远|迤|迭|迱|迶|迻|逌|逘|這|逞|逰|逳|逸|逺|逾|遃|遇|遊|運|遗|遙|遠|遥|遹|遺|邀|邍|邎|邑|邕|邘|邧|邪|邮|邺|郁|郓|郔|郚|郢|郧|郵|郺|郼|郾|鄅|鄆|鄓|鄖|鄘|鄞|鄢|鄴|鄾|酀|酉|酏|酑|酓|酛|酝|酭|酳|酽|醃|醖|醞|醟|醧|醫|醳|醶|醷|醼|釅|釉|釋|野|釔|釪|釴|釶|釾|釿|鈅|鈏|鈗|鈘|鈝|鈠|鈨|鈺|鈾|鉇|鉈|鉛|鉞|鉠|鉯|銀|銉|銕|銚|銥|銦|銪|銹|銿|鋆|鋊|鋋|鋙|鋣|鋭|鋺|錏|錟|錡|錥|鍈|鍚|鍝|鍱|鎁|鎐|鎑|鎣|鎰|鎱|鏔|鏞|鐊|鐍|鐚|鐛|鐭|鐷|鐿|鑍|鑠|鑰|钀|钇|钖|钥|钰|钺|铀|铅|铔|铕|铘|铟|铫|铱|银|铻|锳|镒|镛|镱|閆|閘|閱|閲|閹|閻|閼|閾|闄|闇|闉|闫|阅|阈|阉|阎|阏|阣|阤|阥|阦|阭|阮|阳|阴|阽|陁|陓|院|陨|陭|陰|陶|陻|陽|隁|隂|隃|隅|隐|隒|隕|隠|隩|險|隱|隶|隿|雁|雅|雉|雍|雓|雝|雨|雩|雲|雵|霅|霒|霙|霠|霣|霪|霬|霱|霷|靉|靥|靨|靷|靾|靿|鞅|鞇|鞕|韗|韞|韫|音|韵|韹|韺|韻|韾|頁|頉|預|頤|頥|頨|頴|頵|顊|顏|顑|顒|顔|顗|願|顤|顩|页|预|颍|颐|颕|颖|颙|颜|颺|颻|飏|飖|食|飫|飬|飮|飲|飴|餆|養|餍|餘|餚|餣|餫|饁|饇|饐|饔|饜|饫|饮|饴|馀|馌|馧|馭|馻|駀|駅|駌|駚|駰|騐|験|騕|騟|騴|騵|驁|驈|驗|驛|驜|驠|驭|驿|骃|验|骬|骮|髃|髺|鬰|鬱|鬳|鬻|魇|魊|魘|魚|魣|魭|魷|鮋|鮣|鮧|鮨|鮽|鯈|鯒|鯣|鯲|鰅|鰋|鰑|鰩|鰫|鱅|鱊|鱦|鱮|鱼|鱿|鲉|鲬|鳐|鳙|鳦|鳫|鳱|鳶|鳿|鴁|鴈|鴉|鴛|鴢|鴥|鴦|鴧|鴨|鴪|鴬|鴳|鴹|鴺|鵒|鵪|鵶|鵷|鵺|鶂|鶃|鶍|鶑|鶠|鶢|鶧|鶯|鶰|鷁|鷂|鷃|鷊|鷕|鷖|鷛|鷠|鷣|鷧|鷪|鷰|鷸|鷹|鷾|鸃|鸆|鸈|鸉|鸎|鸑|鸒|鸙|鸚|鸢|鸦|鸭|鸯|鸳|鹆|鹓|鹝|鹞|鹢|鹥|鹦|鹬|鹰|鹽|麀|麌|麙|麣|麲|黓|黝|黟|黡|黤|黦|黫|黬|黭|黰|黳|黶|黿|鼋|鼘|鼝|鼬|鼴|鼹|鼼|齖|齗|齞|齦|齩|齫|齬|齮|齳|齴|齵|齸|齾|龂|龈|龉|龑|龠|龥";
15 | inline std::wstring pinyin_range = L"〇-龥";
16 |
17 | inline std::wstring pinyin_regex_gb2312 = L"一与业严丫丿么义乐乙也予于亏云亚亦亿仡以仪仰伊众优伛伢但佑佗余佚佣佯佻佾侑依侥俑俞俣俨俺倚偃允元兖养冤冶刈刖剡劓勇匀医卣印厂压厌原厣又友台右叶叹吁吆吖吟听吲吾呀呓员呦咏咦咬咽咿哑哕哟哩哽唁唷喁喑喝喻嗌嘤噎噢噫囝因园囿圄圆圉圜圩圪圯圻均块坨坳垠垣垦垭垸埏域埯埸堙堰塬墅墉壅壹夕夜夤夭央失夷奄奇奕奥妁妍妖妤妪姚姨姬姻娅娱婴媛媪媵嫣嬴孕它宇宛宜宥宴容寅寓射尉尢尤尧尹尾屹屿岈岩岳峄峪崎崖崛崤崦崾嵛嶷巡已巳币幺幼幽广应庵庸庾廴延异弈弋引彝彦影役徉御徭徼忆忧怏怠怡怨怿恙恹恽恿悒悠悦愈愉意愚愠愿慵懊懿或扬扰抑押拗拥拽挹捐掎掖掩掾揄揖揞揠揲援揶搋摇撄攸斜於施旖昀昂易昙映昱晏晔晕景曜曰曳月有札杨杳柚栎栩样桠梧椅椰楹榆樱樾橼檐欤欲欹歇殃殒殪殷毅毓毹氤氧氩氲永汩汽沂沅油沿泄泅泱泳洇洋洫洮浴涂涌涎涓涯液淡淤淫淹渊渔渝温渫游湛湮源溢滟滢演漪漾潆潭澳瀛瀹炀炎烊烟烨焉焰焱煜煨熙熠熨燕燠爰爷爻牖牙犄犹狁狠狱狳狺猗猷猿玉王珧琊琰瑗瑛瑜瑶璎用甬由甸畹疋疑疙疟疡疣疫痈痍痒痖瘀瘐瘗瘟瘾瘿癌癔盂盈益盐盾眙眢眼睚矣砑研砚硪硬碣禹禺秧移穿窈窑窨窬窳竽筠筵箢粤粥繇纡约纭绎缘缢缨罂罨羊羡羽羿翊翌翳翼耀耘耶聱聿肀肄育肴胤胭胰腋腌腧腰腴膺臃臆臾舀舁舆舒舣艳艺艾芋芩芫芸芽苑苡英茔茚茵荑荥荧荫药荼莜莠莸莹莺菀菸萤营萦萸蓣蓥蔚蔫蕴蕹薏虞蚁蚓蚜蚰蚴蛇蛘蛹蛾蜍蜒蜕蜮蜴蝇蝓蝣蝤螈蠖衍衙衣衤袁袂裔裕要覃觎言誉讠议讶译诒诣语诱说谀谊谒谕谚谣谳谷豫贻赝赢越趼跃踊轧轶轺辕迂迎运迓远迤迭逞逸逾遇遗遥邀邑邕邪邮邺郁郓郢郧郾鄞鄢酉酏酝酽釉野钇钥钰钺铀铅铕铘铟铫铱银镒镛镱闫阅阈阉阎阏阮阳阴阽院陨陶隅隐隶雁雅雉雍雨雩霪靥鞅韫音韵页预颍颐颖颜食餍饔饫饮饴馀驭驿验鬻魇鱼鱿鳐鳙鸢鸦鸭鸯鸳鹆鹞鹦鹬鹰黝黟鼋鼬鼹龈龉龠";
18 | inline std::wstring pinyin_range_gb2312 = L"[一-龠]";
19 |
20 | #define _T(x) L##x
21 | #include "dynamic_charset.h.user" // private data
22 | //#define DYNAMIC_CHARSET_Y L"源页议游育娱乐汽语言元一么于音友有影"
23 | //#define DYNAMIC_CHARSET_YY_1 L"娱语"
24 | //#define DYNAMIC_CHARSET_YY_2 L"乐言"
--------------------------------------------------------------------------------
/test/main.cpp:
--------------------------------------------------------------------------------
1 | #define BOOST_TEST_MODULE test
2 | #include
--------------------------------------------------------------------------------
/test/match.cpp:
--------------------------------------------------------------------------------
1 | #include "common.hpp"
2 |
3 | #include "../EverythingExt/match.cpp"
4 | #include "../EverythingExt/helper.cpp"
5 |
6 | BOOST_AUTO_TEST_SUITE(Match)
7 | BOOST_AUTO_TEST_CASE(Match) {
8 | pinyin::init(pinyin::PinyinFlag::All);
9 | std::vector flags = { pinyin::PinyinFlag::PinyinAsciiDigit, pinyin::PinyinFlag::PinyinAscii, pinyin::PinyinFlag::InitialLetter, pinyin::PinyinFlag::DoublePinyinMicrosoft };
10 | int pmatch[20];
11 | auto test = [&flags, &pmatch](const char8_t* pat, const char8_t* subject) {
12 | Pattern* pattern = compile(pat, {}, &flags);
13 | int result = exec(pattern, subject, strlen((const char*)subject), std::size(pmatch) / 2, pmatch, {});
14 | HeapFree(GetProcessHeap(), 0, pattern);
15 | return result;
16 | };
17 |
18 | // plain
19 | BOOST_CHECK(test(u8"pinyin", u8"pinyin") == 1 && pmatch[0] == 0 && pmatch[1] == 6);
20 | BOOST_CHECK(test(u8"pinyin", u8"PinYin") == 1 && pmatch[0] == 0 && pmatch[1] == 6);
21 |
22 | // pinyin
23 | BOOST_CHECK(test(u8"py", u8"拼音") == 1 && pmatch[0] == 0 && pmatch[1] == 6);
24 | BOOST_CHECK(test(u8"pinyin", u8"拼音") == 1 && pmatch[0] == 0 && pmatch[1] == 6);
25 | BOOST_CHECK(test(u8"pin1yin1", u8"拼音") == 1 && pmatch[0] == 0 && pmatch[1] == 6);
26 | // DoublePinyinMicrosoft
27 | BOOST_CHECK(test(u8"pn", u8"拼音") == 1 && pmatch[0] == 0 && pmatch[1] == 3);
28 |
29 | // global
30 | BOOST_CHECK(test(u8"pinyin", u8"0123pinyin") == 1 && pmatch[0] == 4 && pmatch[1] == 10);
31 | BOOST_CHECK(test(u8"pinyin", u8"0123拼音") == 1 && pmatch[0] == 4 && pmatch[1] == 10);
32 |
33 | // multiple
34 | //BOOST_CHECK(test(u8"pinyin", u8"01拼音23拼音") == 1 && pmatch[0] == 2 && pmatch[1] == 8);
35 |
36 | // mix
37 | BOOST_CHECK(test(u8"pinyin", u8"拼yin") == 1 && pmatch[0] == 0 && pmatch[1] == 6);
38 | BOOST_CHECK(test(u8"sous", u8"拼音搜索Everything") == 1 && pmatch[0] == 6 && pmatch[1] == 12);
39 |
40 | pinyin::destroy();
41 | }
42 |
43 | BOOST_AUTO_TEST_SUITE_END()
--------------------------------------------------------------------------------
/test/pcre.cpp:
--------------------------------------------------------------------------------
1 | #include "common.hpp"
2 | #include
3 | #define PCRE2_CODE_UNIT_WIDTH 8
4 | #include
5 |
6 | #undef _T
7 | #define _T(x) u8##x
8 |
9 | BOOST_AUTO_TEST_SUITE(PCRE_Match)
10 |
11 | uint32_t get_pinyin(char32_t c) {
12 | return 0x400;
13 | }
14 |
15 | BOOST_AUTO_TEST_CASE(Match) {
16 | auto match = [](std::string_view pattern, std::string_view subject) -> uint32_t {
17 | for (uint32_t i = 0; i < subject.size(); i++) {
18 | uint32_t j = 0, i_ = i;
19 | for (; j < pattern.size() && i_ < subject.size(); j++, i_++) {
20 | if (subject[i_] == pattern[j] || subject[i_] > 'z' && get_pinyin(subject[i_]) & 1 << (pattern[j] - 'a'))
21 | continue;
22 | break;
23 | }
24 | if (j == pattern.size())
25 | return i;
26 | }
27 | return (uint32_t)-1;
28 | };
29 | BOOST_CHECK(match("kk", "abcdefgkk.txt") == 7);
30 | BOOST_CHECK(match("kk", "abcdefg~~.txt") == 7);
31 |
32 | char pattern[] = "yy", subject[] = "abcdefg满天都是小星星.txt";
33 | DWORD t = timeGetTime();
34 | for (size_t i = 0; i < 1'000'000; i++) {
35 | if (__rdtsc() == 0) {
36 | pattern[0] = subject[0] = '\0';
37 | }
38 | match(pattern, subject);
39 | }
40 | t = timeGetTime() - t;
41 | BOOST_TEST_MESSAGE(t << "ms");
42 | // 10ms
43 | }
44 |
45 | BOOST_AUTO_TEST_SUITE_END()
46 |
47 |
48 | BOOST_AUTO_TEST_SUITE(PCRE)
49 |
50 | BOOST_AUTO_TEST_CASE(Compile) {
51 | DWORD t = timeGetTime();
52 | std::u8string_view pattern = u8"[y" DYNAMIC_CHARSET_YY_1 u8"][y" DYNAMIC_CHARSET_YY_2 u8"]";
53 | int errorcode, erroroffset;
54 | const char* error;
55 | pcre* re = pcre_compile2((const char*)pattern.data(), PCRE_UCP | PCRE_UTF8 | PCRE_CASELESS, &errorcode, &error, &erroroffset, nullptr);
56 |
57 | int offsets[30], result;
58 |
59 | result = pcre_exec(re, nullptr, (const char*)u8"测试语言.txt", 16, 0, 0, offsets, std::size(offsets));
60 | t = timeGetTime() - t;
61 | BOOST_REQUIRE(result > 0 && offsets[0] == 6);
62 | BOOST_TEST_MESSAGE(t << "ms");
63 | // 0ms
64 |
65 | std::u8string_view subject(u8"abcdefg满天都是小星星.txt");
66 | t = timeGetTime();
67 | for (size_t i = 0; i < 1'000'000; i++) {
68 | result = pcre_exec(re, nullptr, (const char*)subject.data(), subject.size(), 0, 0, offsets, std::size(offsets));
69 | }
70 | t = timeGetTime() - t;
71 | BOOST_CHECK(result == -1);
72 |
73 | pcre_free(re);
74 |
75 | BOOST_TEST_MESSAGE(t << "ms");
76 | // 4800~5200ms
77 | }
78 |
79 | void JIT_common(std::u8string_view pattern, std::u8string_view test_subject, std::u8string_view subject, int subject_result = -1) {
80 | int errorcode, erroroffset;
81 | const char* error;
82 | DWORD t = timeGetTime();
83 | pcre* re = pcre_compile2((const char*)pattern.data(), PCRE_UCP | PCRE_UTF8 | PCRE_CASELESS, &errorcode, &error, &erroroffset, nullptr);
84 |
85 | pcre_extra* extra = pcre_study(re, PCRE_STUDY_JIT_COMPILE, &error);
86 | pcre_jit_stack* jit_stack = pcre_jit_stack_alloc(32 * 1024, 512 * 1024);
87 | pcre_assign_jit_stack(extra, nullptr, jit_stack);
88 |
89 | int offsets[30], result;
90 |
91 | result = pcre_exec(re, extra, (const char*)test_subject.data(), test_subject.size(), 0, 0, offsets, std::size(offsets));
92 | BOOST_REQUIRE(result > 0 && offsets[0] == 6);
93 | t = timeGetTime() - t;
94 | BOOST_TEST_MESSAGE(t << "ms");
95 | // 0ms
96 |
97 | t = timeGetTime();
98 | for (size_t i = 0; i < 1'000'000; i++) {
99 | result = pcre_exec(re, extra, (const char*)subject.data(), subject.size(), 0, 0, offsets, std::size(offsets));
100 | }
101 | t = timeGetTime() - t;
102 | BOOST_CHECK(result == subject_result);
103 |
104 | pcre_free(re);
105 | pcre_free_study(extra);
106 | pcre_jit_stack_free(jit_stack);
107 |
108 | BOOST_TEST_MESSAGE(t << "ms");
109 | }
110 |
111 | void JIT_common32(std::u32string_view pattern, std::u32string_view test_subject, std::u32string_view subject, int subject_result = -1) {
112 | int errorcode, erroroffset;
113 | const char* error;
114 | DWORD t = timeGetTime();
115 | pcre32* re = pcre32_compile2((PCRE_SPTR32)pattern.data(), PCRE_UCP | PCRE_UTF8 | PCRE_CASELESS, &errorcode, &error, &erroroffset, nullptr);
116 |
117 | pcre32_extra* extra = pcre32_study(re, PCRE_STUDY_JIT_COMPILE, &error);
118 | pcre32_jit_stack* jit_stack = pcre32_jit_stack_alloc(32 * 1024, 512 * 1024);
119 | pcre32_assign_jit_stack(extra, nullptr, jit_stack);
120 |
121 | int offsets[30], result;
122 |
123 | result = pcre32_exec(re, extra, (PCRE_SPTR32)test_subject.data(), test_subject.size(), 0, 0, offsets, std::size(offsets));
124 | BOOST_REQUIRE(result > 0 && offsets[0] == 2);
125 | t = timeGetTime() - t;
126 | BOOST_TEST_MESSAGE(t << "ms");
127 | // 0ms
128 |
129 | t = timeGetTime();
130 | for (size_t i = 0; i < 1'000'000; i++) {
131 | result = pcre32_exec(re, extra, (PCRE_SPTR32)subject.data(), subject.size(), 0, 0, offsets, std::size(offsets));
132 | }
133 | t = timeGetTime() - t;
134 | BOOST_CHECK(result == subject_result);
135 |
136 | pcre32_free(re);
137 | pcre32_free_study(extra);
138 | pcre32_jit_stack_free(jit_stack);
139 |
140 | BOOST_TEST_MESSAGE(t << "ms");
141 | }
142 |
143 | #undef _T
144 | #define _T(x) U##x
145 |
146 | BOOST_AUTO_TEST_CASE(JIT32) {
147 | JIT_common32(
148 | U"[y" DYNAMIC_CHARSET_YY_1 U"][y" DYNAMIC_CHARSET_YY_2 U"]",
149 | U"测试语言.txt",
150 | U"abcdefg满天都是小星星.txt"
151 | );
152 | // 600~800ms
153 | JIT_common32(
154 | U"[y" DYNAMIC_CHARSET_YY_1 U"][y" DYNAMIC_CHARSET_YY_2 U"]",
155 | U"测试语言.txt",
156 | U"abcdefghijklmnopqrstuvwxyzab.txt"
157 | );
158 | // 100~150ms
159 | }
160 |
161 | #undef _T
162 | #define _T(x) u8##x
163 |
164 | BOOST_AUTO_TEST_CASE(JIT) {
165 | JIT_common(
166 | u8"[y" DYNAMIC_CHARSET_YY_1 u8"][y" DYNAMIC_CHARSET_YY_2 u8"]",
167 | u8"测试语言.txt",
168 | u8"abcdefg满天都是小星星.txt"
169 | );
170 | // 930~960ms
171 | JIT_common(
172 | u8"[y" DYNAMIC_CHARSET_YY_1 u8"][y" DYNAMIC_CHARSET_YY_2 u8"]",
173 | u8"测试语言.txt",
174 | u8"abcdefghijklmnopqrstuvwxyzab.txt"
175 | );
176 | // 150~200ms
177 | }
178 |
179 | BOOST_AUTO_TEST_CASE(JIT_Lookaround) {
180 | JIT_common(
181 | u8"(?>y|(?=[〇-龥])[" DYNAMIC_CHARSET_YY_1 u8"])(?>y|(?=[〇-龥])[" DYNAMIC_CHARSET_YY_2 u8"])",
182 | u8"测试语言.txt",
183 | u8"abcdefg满天都是小星星.txt"
184 | );
185 | // 700~900ms
186 | JIT_common(
187 | u8"(?>y|(?=[〇-龥])[" DYNAMIC_CHARSET_YY_1 u8"])(?>y|(?=[〇-龥])[" DYNAMIC_CHARSET_YY_2 u8"])",
188 | u8"测试语言.txt",
189 | u8"abcdefghijklmnopqrstuvwxyzab.txt"
190 | );
191 | // 120~150ms
192 | }
193 |
194 | BOOST_AUTO_TEST_CASE(JIT_CharacterClass) {
195 | JIT_common(
196 | u8"[[:alpha:]][[:alpha:]]",
197 | u8"000111yy.txt",
198 | u8"0123456满天都是小星星.txt",
199 | 1
200 | );
201 | // 150~200ms
202 | JIT_common(
203 | u8"[[:alpha:]][[:alpha:]]",
204 | u8"000111yy.txt",
205 | u8"0123456789!@#$%^&.....0123456789"
206 | );
207 | // 270~350ms
208 | }
209 |
210 | BOOST_AUTO_TEST_CASE(JIT_PlainOrHanzi) {
211 | JIT_common(
212 | u8"(?>yy|[y〇-龥]{2})",
213 | u8"000111语言.txt",
214 | u8"abcdefg满天都是小星星.txt",
215 | 1
216 | );
217 | // 120~150ms
218 | JIT_common(
219 | u8"(?>yy|[y〇-龥]{2})",
220 | u8"000111语言.txt",
221 | u8"abcdefghijklmnopqrstuvwxyzab.txt"
222 | );
223 | // 130~160ms
224 | }
225 |
226 | BOOST_AUTO_TEST_CASE(JIT_PlainXorHanzi) {
227 | JIT_common(
228 | u8"(?>yy|[〇-龥]{2})",
229 | u8"000111语言.txt",
230 | u8"abcdefg满天都是小星星.txt",
231 | 1
232 | );
233 | // 120~150ms
234 | }
235 |
236 | BOOST_AUTO_TEST_CASE(JIT_Plain) {
237 | JIT_common(
238 | u8"yy",
239 | u8"测试yy.txt",
240 | u8"abcdefg满天都是小星星.txt"
241 | );
242 | // 70~90ms
243 | }
244 |
245 | BOOST_AUTO_TEST_CASE(DFA) {
246 | std::u8string_view pattern = u8"[y" DYNAMIC_CHARSET_YY_1 u8"][y" DYNAMIC_CHARSET_YY_2 u8"]";
247 | int errorcode, erroroffset;
248 | const char* error;
249 | pcre* re = pcre_compile2((const char*)pattern.data(), PCRE_UCP | PCRE_UTF8 | PCRE_CASELESS, &errorcode, &error, &erroroffset, nullptr);
250 |
251 | int offsets[30], result;
252 | int workspace[4096];
253 |
254 | result = pcre_dfa_exec(re, nullptr, (const char*)u8"测试语言.txt", 16, 0, 0, offsets, std::size(offsets), workspace, std::size(workspace));
255 | BOOST_REQUIRE(result > 0 && offsets[0] == 6);
256 |
257 | std::u8string_view subject(u8"abcdefg满天都是小星星.txt");
258 | DWORD t = timeGetTime();
259 | for (size_t i = 0; i < 1'000'000; i++) {
260 | result = pcre_dfa_exec(re, nullptr, (const char*)subject.data(), subject.size(), 0, 0, offsets, std::size(offsets), workspace, std::size(workspace));
261 | }
262 | t = timeGetTime() - t;
263 | BOOST_CHECK(result == -1);
264 |
265 | pcre_free(re);
266 |
267 | BOOST_TEST_MESSAGE(t << "ms");
268 | // 4900~5600ms
269 | }
270 |
271 | BOOST_AUTO_TEST_SUITE_END()
272 |
273 |
274 | BOOST_AUTO_TEST_SUITE(PCRE2)
275 |
276 | BOOST_AUTO_TEST_CASE(Compile) {
277 | std::u8string_view pattern = u8"[y" DYNAMIC_CHARSET_YY_1 u8"][y" DYNAMIC_CHARSET_YY_2 u8"]";
278 | int errorcode;
279 | PCRE2_SIZE erroroffset;
280 | pcre2_code* re = pcre2_compile((PCRE2_SPTR)pattern.data(), pattern.size(), PCRE2_UCP | PCRE2_UTF | PCRE2_CASELESS, &errorcode, &erroroffset, nullptr);
281 |
282 | pcre2_match_data* match_data = pcre2_match_data_create_from_pattern(re, nullptr);
283 |
284 | int result = pcre2_match(re, (PCRE2_SPTR)u8"测试语言.txt", 16, 0, 0, match_data, nullptr);
285 | BOOST_REQUIRE(result > 0 && pcre2_get_ovector_pointer(match_data)[0] == 6);
286 |
287 | std::u8string_view subject(u8"abcdefg满天都是小星星.txt");
288 | DWORD t = timeGetTime();
289 | for (size_t i = 0; i < 1'000'000; i++) {
290 | result = pcre2_match(re, (PCRE2_SPTR)subject.data(), subject.size(), 0, 0, match_data, nullptr);
291 | }
292 | t = timeGetTime() - t;
293 | BOOST_CHECK(result == -1);
294 |
295 | pcre2_match_data_free(match_data);
296 | pcre2_code_free(re);
297 |
298 | BOOST_TEST_MESSAGE(t << "ms");
299 | // 4700~4900ms
300 | }
301 |
302 | BOOST_AUTO_TEST_CASE(JIT) {
303 | std::u8string_view pattern = u8"[y" DYNAMIC_CHARSET_YY_1 u8"][y" DYNAMIC_CHARSET_YY_2 u8"]";
304 | int errorcode;
305 | PCRE2_SIZE erroroffset;
306 | pcre2_code* re = pcre2_compile((PCRE2_SPTR)pattern.data(), pattern.size(), PCRE2_UCP | PCRE2_UTF | PCRE2_CASELESS, &errorcode, &erroroffset, nullptr);
307 |
308 | pcre2_jit_compile(re, PCRE2_JIT_COMPLETE);
309 | pcre2_match_context* mcontext = pcre2_match_context_create(nullptr);
310 | pcre2_jit_stack* jit_stack = pcre2_jit_stack_create(32 * 1024, 512 * 1024, nullptr);
311 | pcre2_jit_stack_assign(mcontext, nullptr, jit_stack);
312 |
313 | pcre2_match_data* match_data = pcre2_match_data_create_from_pattern(re, nullptr);
314 |
315 | int result = pcre2_match(re, (PCRE2_SPTR)u8"测试语言.txt", 16, 0, 0, match_data, mcontext);
316 | BOOST_REQUIRE(result > 0 && pcre2_get_ovector_pointer(match_data)[0] == 6);
317 |
318 | std::u8string_view subject(u8"abcdefg满天都是小星星.txt");
319 | DWORD t = timeGetTime();
320 | for (size_t i = 0; i < 1'000'000; i++) {
321 | result = pcre2_match(re, (PCRE2_SPTR)subject.data(), subject.size(), 0, 0, match_data, mcontext);
322 | }
323 | t = timeGetTime() - t;
324 | BOOST_CHECK(result == -1);
325 |
326 | pcre2_code_free(re);
327 | pcre2_match_data_free(match_data);
328 | pcre2_match_context_free(mcontext);
329 | pcre2_jit_stack_free(jit_stack);
330 |
331 | BOOST_TEST_MESSAGE(t << "ms");
332 | // 950~1100ms
333 | }
334 |
335 | BOOST_AUTO_TEST_SUITE_END()
--------------------------------------------------------------------------------
/test/test.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | {1dbb8594-6baf-34c0-9998-6aa359588998}
34 |
35 |
36 | {169d9787-0f47-3ee4-9056-c52dfc6e922a}
37 |
38 |
39 | {81a0272a-5ef3-30a8-9154-3a5a8df9aa70}
40 |
41 |
42 |
43 | 16.0
44 | Win32Proj
45 | {80718343-f2b4-4358-8d44-321cbe687f92}
46 | test
47 | 10.0
48 |
49 |
50 |
51 | Application
52 | true
53 | v143
54 | Unicode
55 |
56 |
57 | Application
58 | false
59 | v143
60 | true
61 | Unicode
62 |
63 |
64 | Application
65 | true
66 | v143
67 | Unicode
68 |
69 |
70 | Application
71 | false
72 | v143
73 | true
74 | Unicode
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 | true
96 |
97 |
98 | false
99 |
100 |
101 | true
102 |
103 |
104 | false
105 |
106 |
107 | x64-windows-static-md
108 |
109 |
110 | x64-windows-static-md
111 |
112 |
113 |
114 | Level3
115 | true
116 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
117 | true
118 | $(SolutionDir)external\build\_deps\ibeverything-src\include;$(SolutionDir)external\build\_deps\ibwincpp-src\include;$(SolutionDir)external\build\_deps\ibpinyin-src\include
119 | stdcpplatest
120 |
121 |
122 | Console
123 | true
124 |
125 |
126 |
127 |
128 | Level3
129 | true
130 | true
131 | true
132 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
133 | true
134 | $(SolutionDir)external\build\_deps\ibeverything-src\include;$(SolutionDir)external\build\_deps\ibwincpp-src\include;$(SolutionDir)external\build\_deps\ibpinyin-src\include
135 | stdcpplatest
136 |
137 |
138 | Console
139 | true
140 | true
141 | true
142 | /PDBALTPATH:https://github.com/Chaoses-Ib/IbEverythingExt %(AdditionalOptions)
143 |
144 |
145 |
146 |
147 | Level3
148 | true
149 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
150 | true
151 | $(SolutionDir)external\build\_deps\ibeverything-src\include;$(SolutionDir)external\build\_deps\ibwincpp-src\include;$(SolutionDir)external\build\_deps\ibpinyin-src\include
152 | stdcpplatest
153 |
154 |
155 | Console
156 | true
157 |
158 |
159 |
160 |
161 | Level3
162 | true
163 | true
164 | true
165 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
166 | true
167 | $(SolutionDir)external\build\_deps\ibeverything-src\include;$(SolutionDir)external\build\_deps\ibwincpp-src\include;$(SolutionDir)external\build\_deps\ibpinyin-src\include
168 | stdcpplatest
169 |
170 |
171 | Console
172 | true
173 | true
174 | true
175 | /PDBALTPATH:https://github.com/Chaoses-Ib/IbEverythingExt %(AdditionalOptions)
176 |
177 |
178 |
179 |
180 |
181 |
--------------------------------------------------------------------------------
/test/test.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Header Files
20 |
21 |
22 |
23 |
24 | Source Files
25 |
26 |
27 | Source Files
28 |
29 |
30 | Source Files
31 |
32 |
33 | Source Files
34 |
35 |
36 | Source Files
37 |
38 |
39 |
--------------------------------------------------------------------------------
/test/v1.4.cpp:
--------------------------------------------------------------------------------
1 | #include "common.hpp"
2 |
3 | BOOST_AUTO_TEST_SUITE(v1_4)
4 |
5 | BOOST_FIXTURE_TEST_SUITE(SingleCharQueryPerformance, Everythings::Everything)
6 | void test_query(Everythings::Everything& ev, std::wstring_view query) {
7 | using namespace Everythings;
8 |
9 | DWORD t = timeGetTime();
10 | ev.query_send(query, 0, Request::FileName);
11 | QueryResults results = ev.query_get();
12 | t = timeGetTime() - t;
13 |
14 | BOOST_CHECK(results.found_num);
15 | BOOST_TEST_MESSAGE(t << "ms");
16 | Sleep(2000);
17 | }
18 |
19 | BOOST_AUTO_TEST_SUITE(Char)
20 |
21 | BOOST_AUTO_TEST_CASE(Char) {
22 | test_query(*this, L"y");
23 | }
24 |
25 | BOOST_AUTO_TEST_CASE(Regex) {
26 | test_query(*this, L"regex:y");
27 | }
28 |
29 | BOOST_AUTO_TEST_CASE(RegexSet) {
30 | test_query(*this, L"regex:[y]");
31 | }
32 |
33 | BOOST_AUTO_TEST_SUITE_END()
34 |
35 |
36 | BOOST_AUTO_TEST_SUITE(Pinyin)
37 |
38 | BOOST_AUTO_TEST_CASE(Base_v03) {
39 | test_query(*this, L"regex:[y" DYNAMIC_CHARSET_Y L"]");
40 | }
41 |
42 | // very fast
43 | BOOST_AUTO_TEST_CASE(LetterBranch) {
44 | test_query(*this, L"regex:y|[" DYNAMIC_CHARSET_Y L"]");
45 | }
46 |
47 | BOOST_AUTO_TEST_CASE(LetterBranchCase) {
48 | test_query(*this, L"case:regex:y|Y|[" DYNAMIC_CHARSET_Y L"]");
49 | }
50 |
51 | BOOST_AUTO_TEST_CASE(Base_v02) {
52 | test_query(*this, L"case:regex:[yY" DYNAMIC_CHARSET_Y L"]");
53 | }
54 |
55 | // better
56 | BOOST_AUTO_TEST_CASE(Dynamic) {
57 | test_query(*this, L"regex:[y" DYNAMIC_CHARSET_Y L"]");
58 | }
59 |
60 | // better
61 | BOOST_AUTO_TEST_CASE(Gb2312) {
62 | test_query(*this, L"regex:[y" + pinyin_regex_gb2312 + L"]");
63 | }
64 |
65 | // faster but not the same
66 | BOOST_AUTO_TEST_CASE(Count) {
67 | // place count before regex!
68 | test_query(*this, L"count:100 regex:[y" + pinyin_regex + L"]");
69 | }
70 |
71 | // faster but not the same
72 | BOOST_AUTO_TEST_CASE(Boundary) {
73 | test_query(*this, L"regex:\\b[y" + pinyin_regex + L"]");
74 | }
75 |
76 | // better
77 | BOOST_AUTO_TEST_CASE(Case) {
78 | test_query(*this, L"case:regex:[yY" + pinyin_regex + L"]");
79 | }
80 |
81 | BOOST_AUTO_TEST_CASE(Base_v01) {
82 | test_query(*this, L"regex:[y" + pinyin_regex + L"]");
83 | }
84 |
85 | /*
86 | // cpu killer
87 | BOOST_AUTO_TEST_CASE(Branch) {
88 | test_query(*this, L"regex:y|" + pinyin_branch);
89 | }
90 | */
91 |
92 | // worse
93 | BOOST_AUTO_TEST_CASE(Lookaround1) {
94 | test_query(*this, L"regex:");
95 | }
96 |
97 | BOOST_AUTO_TEST_CASE(Lookaround2_1) {
98 | // regex:"(?>y|(?=[一-龠])一)"
99 | test_query(*this, L"regex:\"(?>y|(?=[" + pinyin_range + L"])[" + pinyin_regex + L"])\"");
100 | }
101 |
102 | // worse than 1
103 | BOOST_AUTO_TEST_CASE(Lookaround2) {
104 | // regex:"(y|(?=[一-龠])一)"
105 | test_query(*this, L"regex:\"(y|(?=[" + pinyin_range + L"])[" + pinyin_regex + L"])\"");
106 | }
107 |
108 | // worse than 2
109 | BOOST_AUTO_TEST_CASE(Lookaround3) {
110 | // regex:"(y|(?![\x00-\xff])一)"
111 | test_query(*this, L"regex:\"(y|(?![\\x00-\\xff])[" + pinyin_regex + L"])\"");
112 | }
113 |
114 | // worse than 3
115 | BOOST_AUTO_TEST_CASE(Lookaround4) {
116 | // regex:"(y|(?![一-龠])(?!)|一)"
117 | test_query(*this, L"regex:\"(y|(?![" + pinyin_range + L"])(?!)|[" + pinyin_regex + L"])\"");
118 | }
119 | BOOST_AUTO_TEST_SUITE_END()
120 |
121 | BOOST_AUTO_TEST_SUITE_END()
122 |
123 |
124 | BOOST_FIXTURE_TEST_SUITE(MultiCharsQueryPerformance, Everythings::Everything)
125 | void test_query(Everythings::Everything& ev, std::wstring_view query) {
126 | using namespace Everythings;
127 |
128 | DWORD t = timeGetTime();
129 | ev.query_send(query, 0, Request::FileName);
130 | QueryResults results = ev.query_get();
131 | t = timeGetTime() - t;
132 |
133 | BOOST_CHECK(results.found_num);
134 | BOOST_TEST_MESSAGE(t << "ms");
135 | Sleep(2000);
136 | }
137 |
138 | BOOST_AUTO_TEST_SUITE(Char)
139 |
140 | BOOST_AUTO_TEST_CASE(Branch) {
141 | test_query(*this, L"x|y");
142 | }
143 |
144 | // faster than set?
145 | BOOST_AUTO_TEST_CASE(RegexBranch) {
146 | test_query(*this, L"regex:x|y");
147 | }
148 |
149 | BOOST_AUTO_TEST_CASE(RegexSet) {
150 | test_query(*this, L"regex:[xy]");
151 | }
152 |
153 | BOOST_AUTO_TEST_SUITE_END()
154 |
155 |
156 | BOOST_AUTO_TEST_SUITE(Char100)
157 |
158 | BOOST_AUTO_TEST_CASE(RegexSet) {
159 | test_query(*this, L"regex:[一与业严丫丿么义乐乙也予于亏云亚亦亿仡以仪仰伊众优伛伢但佑佗余佚佣佯佻佾侑依侥俑俞俣俨俺倚偃允元兖养冤冶刈刖剡劓勇匀医卣印厂压厌原厣又友台右叶叹吁吆吖吟听吲吾呀呓员呦咏咦咬咽咿哑哕哟哩哽唁唷喁喑喝喻嗌]");
160 | }
161 |
162 | // very slow
163 | BOOST_AUTO_TEST_CASE(RegexBranch) {
164 | test_query(*this, L"regex:一|与|业|严|丫|丿|么|义|乐|乙|也|予|于|亏|云|亚|亦|亿|仡|以|仪|仰|伊|众|优|伛|伢|但|佑|佗|余|佚|佣|佯|佻|佾|侑|依|侥|俑|俞|俣|俨|俺|倚|偃|允|元|兖|养|冤|冶|刈|刖|剡|劓|勇|匀|医|卣|印|厂|压|厌|原|厣|又|友|台|右|叶|叹|吁|吆|吖|吟|听|吲|吾|呀|呓|员|呦|咏|咦|咬|咽|咿|哑|哕|哟|哩|哽|唁|唷|喁|喑|喝|喻|嗌");
165 | }
166 |
167 | // very slow
168 | BOOST_AUTO_TEST_CASE(Branch) {
169 | test_query(*this, L"一|与|业|严|丫|丿|么|义|乐|乙|也|予|于|亏|云|亚|亦|亿|仡|以|仪|仰|伊|众|优|伛|伢|但|佑|佗|余|佚|佣|佯|佻|佾|侑|依|侥|俑|俞|俣|俨|俺|倚|偃|允|元|兖|养|冤|冶|刈|刖|剡|劓|勇|匀|医|卣|印|厂|压|厌|原|厣|又|友|台|右|叶|叹|吁|吆|吖|吟|听|吲|吾|呀|呓|员|呦|咏|咦|咬|咽|咿|哑|哕|哟|哩|哽|唁|唷|喁|喑|喝|喻|嗌");
170 | }
171 |
172 | BOOST_AUTO_TEST_SUITE_END()
173 |
174 |
175 | BOOST_AUTO_TEST_SUITE(Pinyin)
176 |
177 | BOOST_AUTO_TEST_CASE(Base_v03) {
178 | test_query(*this, L"regex:[y" DYNAMIC_CHARSET_YY_1 L"][y" DYNAMIC_CHARSET_YY_2 L"]");
179 | }
180 |
181 | // slower than Base_v02
182 | BOOST_AUTO_TEST_CASE(LetterBranch) {
183 | // regex:"(y|[英])(y|[语])"
184 | test_query(*this, L"regex:\"(y|[" DYNAMIC_CHARSET_YY_1 L"])(y|[" DYNAMIC_CHARSET_YY_2 L"])\"");
185 | }
186 |
187 | BOOST_AUTO_TEST_CASE(LetterBranch_1) {
188 | // regex:"(?:y|[英])(?:y|[语])"
189 | test_query(*this, L"regex:\"(?:y|[" DYNAMIC_CHARSET_YY_1 L"])(?:y|[" DYNAMIC_CHARSET_YY_2 L"])\"");
190 | }
191 |
192 | BOOST_AUTO_TEST_CASE(LetterBranch_2) {
193 | // regex:"(?>y|[英])(?>y|[语])"
194 | test_query(*this, L"regex:\"(?>y|[" DYNAMIC_CHARSET_YY_1 L"])(?>y|[" DYNAMIC_CHARSET_YY_2 L"])\"");
195 | }
196 |
197 | BOOST_AUTO_TEST_CASE(Base_v02) {
198 | test_query(*this, L"case:regex:[yY" DYNAMIC_CHARSET_YY_1 L"][yY" DYNAMIC_CHARSET_YY_2 L"]");
199 | }
200 |
201 | BOOST_AUTO_TEST_CASE(DynamicPair) {
202 | test_query(*this, L"regex:[y" DYNAMIC_CHARSET_YY_1 L"][y" DYNAMIC_CHARSET_YY_2 L"]");
203 | }
204 |
205 | BOOST_AUTO_TEST_CASE(Dynamic) {
206 | test_query(*this, L"regex:[y" DYNAMIC_CHARSET_Y L"]{2}");
207 | }
208 |
209 | BOOST_AUTO_TEST_CASE(Base_v01) {
210 | test_query(*this, L"regex:[y" + pinyin_regex + L"]{2}");
211 | }
212 |
213 | BOOST_AUTO_TEST_CASE(Quantifier) {
214 | test_query(*this, L"regex:[y" + pinyin_regex + L"]{2}");
215 | }
216 |
217 | BOOST_AUTO_TEST_CASE(Repeat) {
218 | test_query(*this, L"regex:[y" + pinyin_regex + L"][y" + pinyin_regex + L"]");
219 | }
220 |
221 | BOOST_AUTO_TEST_SUITE_END()
222 |
223 | BOOST_AUTO_TEST_SUITE_END()
224 |
225 |
226 | BOOST_FIXTURE_TEST_SUITE(DynamicCharset, Everythings::Everything)
227 | void test_query(Everythings::Everything& ev, std::wstring_view query) {
228 | using namespace Everythings;
229 |
230 | DWORD t = timeGetTime();
231 | ev.query_send(query, Search::MatchCase, Request::FileName);
232 | QueryResults results = ev.query_get();
233 | t = timeGetTime() - t;
234 |
235 | BOOST_TEST_MESSAGE(results.available_num << ", " << t << "ms");
236 | Sleep(2000);
237 | }
238 |
239 | BOOST_AUTO_TEST_CASE(GenerateQuery) {
240 | test_query(*this, L"regex:[〇-𰻞]");
241 | }
242 |
243 | BOOST_AUTO_TEST_CASE(UpdateQuery) {
244 | test_query(*this, L"rc:");
245 | }
246 |
247 | BOOST_AUTO_TEST_CASE(UpdateQueryRegex) {
248 | test_query(*this, L"rc: regex:[〇-𰻞]");
249 | }
250 |
251 | BOOST_AUTO_TEST_SUITE_END()
252 |
253 | BOOST_AUTO_TEST_SUITE_END()
--------------------------------------------------------------------------------
/test/v1.5a.cpp:
--------------------------------------------------------------------------------
1 | #include "common.hpp"
2 |
3 | BOOST_AUTO_TEST_SUITE(v1_5a)
4 |
5 | BOOST_FIXTURE_TEST_SUITE(SingleCharQueryPerformance, Everythings::Everything)
6 | void test_query(std::wstring_view query) {
7 | using namespace Everythings;
8 |
9 | Everything ev(L"1.5a");
10 | DWORD t = timeGetTime();
11 | ev.query_send(query, 0, Request::FileName);
12 | QueryResults results = ev.query_get();
13 | t = timeGetTime() - t;
14 |
15 | BOOST_CHECK(results.found_num);
16 | BOOST_TEST_MESSAGE(t << "ms");
17 | Sleep(2000);
18 | }
19 |
20 | BOOST_AUTO_TEST_SUITE(Char)
21 |
22 | BOOST_AUTO_TEST_CASE(Char) {
23 | test_query(L"y");
24 | }
25 |
26 | BOOST_AUTO_TEST_CASE(Regex) {
27 | test_query(L"regex:y");
28 | }
29 |
30 | BOOST_AUTO_TEST_CASE(RegexSet) {
31 | test_query(L"regex:[y]");
32 | }
33 |
34 | BOOST_AUTO_TEST_SUITE_END()
35 |
36 |
37 | BOOST_AUTO_TEST_SUITE(Pinyin)
38 |
39 | BOOST_AUTO_TEST_CASE(Base_v03) {
40 | test_query(L"regex:[y" DYNAMIC_CHARSET_Y L"]");
41 | }
42 |
43 | BOOST_AUTO_TEST_CASE(LetterBranch) {
44 | test_query(L"regex:y|[" DYNAMIC_CHARSET_Y L"]");
45 | }
46 |
47 | BOOST_AUTO_TEST_CASE(LetterBranchCase) {
48 | test_query(L"case:regex:y|Y|[" DYNAMIC_CHARSET_Y L"]");
49 | }
50 |
51 | BOOST_AUTO_TEST_CASE(Base_v02) {
52 | test_query(L"case:regex:[yY" DYNAMIC_CHARSET_Y L"]");
53 | }
54 |
55 | // better
56 | BOOST_AUTO_TEST_CASE(Dynamic) {
57 | test_query(L"regex:[y" DYNAMIC_CHARSET_Y L"]");
58 | }
59 |
60 | // better
61 | BOOST_AUTO_TEST_CASE(Gb2312) {
62 | test_query(L"regex:[y" + pinyin_regex_gb2312 + L"]");
63 | }
64 |
65 | // faster but not the same
66 | BOOST_AUTO_TEST_CASE(Count) {
67 | // place count before regex!
68 | test_query(L"count:100 regex:[y" + pinyin_regex + L"]");
69 | }
70 |
71 | // faster but not the same
72 | BOOST_AUTO_TEST_CASE(Boundary) {
73 | test_query(L"regex:\\b[y" + pinyin_regex + L"]");
74 | }
75 |
76 | // better
77 | BOOST_AUTO_TEST_CASE(Case) {
78 | test_query(L"case:regex:[yY" + pinyin_regex + L"]");
79 | }
80 |
81 | BOOST_AUTO_TEST_CASE(Base_v01) {
82 | test_query(L"regex:[y" + pinyin_regex + L"]");
83 | }
84 |
85 | /*
86 | // cpu killer
87 | BOOST_AUTO_TEST_CASE(Branch) {
88 | test_query(L"regex:y|" + pinyin_branch);
89 | }
90 | */
91 |
92 | // worse
93 | BOOST_AUTO_TEST_CASE(Lookaround1) {
94 | test_query(L"regex:");
95 | }
96 |
97 | BOOST_AUTO_TEST_CASE(Lookaround2_1) {
98 | // regex:(?>y|(?=[一-龠])一)
99 | test_query(L"regex:(?>y|(?=[" + pinyin_range + L"])[" + pinyin_regex + L"])");
100 | }
101 |
102 | // worse than 1
103 | BOOST_AUTO_TEST_CASE(Lookaround2) {
104 | // regex:(y|(?=[一-龠])一)
105 | test_query(L"regex:(y|(?=[" + pinyin_range + L"])[" + pinyin_regex + L"])");
106 | }
107 |
108 | // worse than 2
109 | BOOST_AUTO_TEST_CASE(Lookaround3) {
110 | // regex:(y|(?![\x00-\xff])一)
111 | test_query(L"regex:(y|(?![\\x00-\\xff])[" + pinyin_regex + L"])");
112 | }
113 |
114 | // worse than 3
115 | BOOST_AUTO_TEST_CASE(Lookaround4) {
116 | // regex:(y|(?![一-龠])(?!)|一)
117 | test_query(L"regex:(y|(?![" + pinyin_range + L"])(?!)|[" + pinyin_regex + L"])");
118 | }
119 | BOOST_AUTO_TEST_SUITE_END()
120 |
121 | BOOST_AUTO_TEST_SUITE_END()
122 |
123 |
124 | BOOST_AUTO_TEST_SUITE(MultiCharsQueryPerformance)
125 | void test_query(std::wstring_view query) {
126 | using namespace Everythings;
127 |
128 | Everything ev(L"1.5a");
129 | DWORD t = timeGetTime();
130 | ev.query_send(query, 0, Request::FileName);
131 | QueryResults results = ev.query_get();
132 | t = timeGetTime() - t;
133 |
134 | BOOST_CHECK(results.found_num);
135 | BOOST_TEST_MESSAGE(t << "ms");
136 | Sleep(2000);
137 | }
138 |
139 | BOOST_AUTO_TEST_SUITE(Char)
140 |
141 | BOOST_AUTO_TEST_CASE(Branch) {
142 | test_query(L"x|y");
143 | }
144 |
145 | BOOST_AUTO_TEST_CASE(WildcardsSet) {
146 | test_query(L"wildcards:*[xy]*");
147 | }
148 |
149 | // faster than set?
150 | BOOST_AUTO_TEST_CASE(RegexBranch) {
151 | test_query(L"regex:x|y");
152 | }
153 |
154 | BOOST_AUTO_TEST_CASE(RegexSet) {
155 | test_query(L"regex:[xy]");
156 | }
157 |
158 | BOOST_AUTO_TEST_SUITE_END()
159 |
160 |
161 | BOOST_AUTO_TEST_SUITE(Char100)
162 |
163 | BOOST_AUTO_TEST_CASE(RegexSet) {
164 | test_query(L"regex:[一与业严丫丿么义乐乙也予于亏云亚亦亿仡以仪仰伊众优伛伢但佑佗余佚佣佯佻佾侑依侥俑俞俣俨俺倚偃允元兖养冤冶刈刖剡劓勇匀医卣印厂压厌原厣又友台右叶叹吁吆吖吟听吲吾呀呓员呦咏咦咬咽咿哑哕哟哩哽唁唷喁喑喝喻嗌]");
165 | }
166 |
167 | // slow
168 | BOOST_AUTO_TEST_CASE(WildcardsSet) {
169 | test_query(L"wildcards:*[一与业严丫丿么义乐乙也予于亏云亚亦亿仡以仪仰伊众优伛伢但佑佗余佚佣佯佻佾侑依侥俑俞俣俨俺倚偃允元兖养冤冶刈刖剡劓勇匀医卣印厂压厌原厣又友台右叶叹吁吆吖吟听吲吾呀呓员呦咏咦咬咽咿哑哕哟哩哽唁唷喁喑喝喻嗌]*");
170 | }
171 |
172 | // very slow
173 | BOOST_AUTO_TEST_CASE(RegexBranch) {
174 | test_query(L"regex:一|与|业|严|丫|丿|么|义|乐|乙|也|予|于|亏|云|亚|亦|亿|仡|以|仪|仰|伊|众|优|伛|伢|但|佑|佗|余|佚|佣|佯|佻|佾|侑|依|侥|俑|俞|俣|俨|俺|倚|偃|允|元|兖|养|冤|冶|刈|刖|剡|劓|勇|匀|医|卣|印|厂|压|厌|原|厣|又|友|台|右|叶|叹|吁|吆|吖|吟|听|吲|吾|呀|呓|员|呦|咏|咦|咬|咽|咿|哑|哕|哟|哩|哽|唁|唷|喁|喑|喝|喻|嗌");
175 | }
176 |
177 | // very slow
178 | BOOST_AUTO_TEST_CASE(Branch) {
179 | test_query(L"一|与|业|严|丫|丿|么|义|乐|乙|也|予|于|亏|云|亚|亦|亿|仡|以|仪|仰|伊|众|优|伛|伢|但|佑|佗|余|佚|佣|佯|佻|佾|侑|依|侥|俑|俞|俣|俨|俺|倚|偃|允|元|兖|养|冤|冶|刈|刖|剡|劓|勇|匀|医|卣|印|厂|压|厌|原|厣|又|友|台|右|叶|叹|吁|吆|吖|吟|听|吲|吾|呀|呓|员|呦|咏|咦|咬|咽|咿|哑|哕|哟|哩|哽|唁|唷|喁|喑|喝|喻|嗌");
180 | }
181 |
182 | BOOST_AUTO_TEST_SUITE_END()
183 |
184 |
185 | BOOST_AUTO_TEST_SUITE(Pinyin)
186 |
187 | BOOST_AUTO_TEST_CASE(Base_v03) {
188 | test_query(L"regex:[y" DYNAMIC_CHARSET_YY_1 L"][y" DYNAMIC_CHARSET_YY_2 L"]");
189 | }
190 |
191 | // slower than Base_v02
192 | BOOST_AUTO_TEST_CASE(LetterBranch) {
193 | // regex:(y|[英])(y|[语])
194 | test_query(L"regex:(y|[" DYNAMIC_CHARSET_YY_1 L"])(y|[" DYNAMIC_CHARSET_YY_2 L"])");
195 | }
196 |
197 | BOOST_AUTO_TEST_CASE(LetterBranch_1) {
198 | // regex:(?:y|[英])(?:y|[语])
199 | test_query(L"regex:(?:y|[" DYNAMIC_CHARSET_YY_1 L"])(?:y|[" DYNAMIC_CHARSET_YY_2 L"])");
200 | }
201 |
202 | BOOST_AUTO_TEST_CASE(LetterBranch_2) {
203 | // regex:(?>y|[英])(?>y|[语])
204 | test_query(L"regex:(?>y|[" DYNAMIC_CHARSET_YY_1 L"])(?>y|[" DYNAMIC_CHARSET_YY_2 L"])");
205 | }
206 |
207 | BOOST_AUTO_TEST_CASE(Base_v02) {
208 | test_query(L"case:regex:[yY" DYNAMIC_CHARSET_YY_1 L"][yY" DYNAMIC_CHARSET_YY_2 L"]");
209 | }
210 |
211 | BOOST_AUTO_TEST_CASE(DynamicPair) {
212 | test_query(L"regex:[y" DYNAMIC_CHARSET_YY_1 L"][y" DYNAMIC_CHARSET_YY_2 L"]");
213 | }
214 |
215 | BOOST_AUTO_TEST_CASE(Dynamic) {
216 | test_query(L"regex:[y" DYNAMIC_CHARSET_Y L"]{2}");
217 | }
218 |
219 | BOOST_AUTO_TEST_CASE(Base_v01) {
220 | test_query(L"regex:[y" + pinyin_regex + L"]{2}");
221 | }
222 |
223 | BOOST_AUTO_TEST_CASE(Quantifier) {
224 | test_query(L"regex:[y" + pinyin_regex + L"]{2}");
225 | }
226 |
227 | BOOST_AUTO_TEST_CASE(Repeat) {
228 | test_query(L"regex:[y" + pinyin_regex + L"][y" + pinyin_regex + L"]");
229 | }
230 |
231 | BOOST_AUTO_TEST_SUITE_END()
232 |
233 | BOOST_AUTO_TEST_SUITE_END()
234 |
235 |
236 | BOOST_FIXTURE_TEST_SUITE(DynamicCharset, Everythings::Everything)
237 | void test_query(std::wstring_view query) {
238 | using namespace Everythings;
239 |
240 | Everything ev(L"1.5a");
241 | DWORD t = timeGetTime();
242 | ev.query_send(query, Search::MatchCase, Request::FileName);
243 | QueryResults results = ev.query_get();
244 | t = timeGetTime() - t;
245 |
246 | BOOST_TEST_MESSAGE(results.available_num << ", " << t << "ms");
247 | Sleep(2000);
248 | }
249 |
250 | BOOST_AUTO_TEST_CASE(GenerateQuery) {
251 | test_query(L"regex:[〇-𰻞]");
252 | }
253 |
254 | BOOST_AUTO_TEST_CASE(UpdateQuery) {
255 | test_query(L"rc:");
256 | }
257 |
258 | BOOST_AUTO_TEST_CASE(UpdateQueryRegex) {
259 | test_query(L"rc: regex:[〇-𰻞]");
260 | }
261 |
262 | BOOST_AUTO_TEST_SUITE_END()
263 |
264 | BOOST_AUTO_TEST_SUITE_END()
--------------------------------------------------------------------------------