diff --git a/Deploy/NAppUpdate/FeedBuilder.config b/Deploy/NAppUpdate/FeedBuilder.config deleted file mode 100644 index f06954dd2..000000000 --- a/Deploy/NAppUpdate/FeedBuilder.config +++ /dev/null @@ -1,18 +0,0 @@ - - - - True - False - True - True - <?xml version="1.0" encoding="utf-16"?> -<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" /> - True - True - E:\github\Wox\Output\Debug - True - False - E:\github\Wox\Output\Update\Update.xml - - http://127.0.0.1:8888 - diff --git a/Deploy/NAppUpdate/FeedBuilder.exe b/Deploy/NAppUpdate/FeedBuilder.exe deleted file mode 100644 index fae212831..000000000 Binary files a/Deploy/NAppUpdate/FeedBuilder.exe and /dev/null differ diff --git a/Deploy/NAppUpdate/FeedBuilder.exe.config b/Deploy/NAppUpdate/FeedBuilder.exe.config deleted file mode 100644 index ae5879084..000000000 --- a/Deploy/NAppUpdate/FeedBuilder.exe.config +++ /dev/null @@ -1,54 +0,0 @@ - - - - -
- - - - - - - - - True - - - False - - - True - - - False - - - True - - - True - - - - - - True - - - - - *.pdb - *.config - - - - - True - - - - - - - \ No newline at end of file diff --git a/Deploy/NAppUpdate/build.bat b/Deploy/NAppUpdate/build.bat deleted file mode 100644 index 4cf777575..000000000 --- a/Deploy/NAppUpdate/build.bat +++ /dev/null @@ -1 +0,0 @@ -FeedBuilder.exe "FeedBuilder.config" -Build diff --git a/Deploy/NAppUpdate/gui.bat b/Deploy/NAppUpdate/gui.bat deleted file mode 100644 index 6c8eaf13e..000000000 --- a/Deploy/NAppUpdate/gui.bat +++ /dev/null @@ -1 +0,0 @@ -FeedBuilder.exe "FeedBuilder.config" -ShowGUI diff --git a/Deploy/NAppUpdate/NAppUpdate.Framework.dll b/Deploy/UpdateGenerator/NAppUpdate.Framework.dll similarity index 50% rename from Deploy/NAppUpdate/NAppUpdate.Framework.dll rename to Deploy/UpdateGenerator/NAppUpdate.Framework.dll index 60fac8ffc..398d46b81 100644 Binary files a/Deploy/NAppUpdate/NAppUpdate.Framework.dll and b/Deploy/UpdateGenerator/NAppUpdate.Framework.dll differ diff --git a/Deploy/UpdateGenerator/Newtonsoft.Json.dll b/Deploy/UpdateGenerator/Newtonsoft.Json.dll new file mode 100644 index 000000000..0a61735d2 Binary files /dev/null and b/Deploy/UpdateGenerator/Newtonsoft.Json.dll differ diff --git a/Deploy/UpdateGenerator/Wox.Infrastructure.dll b/Deploy/UpdateGenerator/Wox.Infrastructure.dll new file mode 100644 index 000000000..ba780a7d2 Binary files /dev/null and b/Deploy/UpdateGenerator/Wox.Infrastructure.dll differ diff --git a/Deploy/UpdateGenerator/Wox.Plugin.dll b/Deploy/UpdateGenerator/Wox.Plugin.dll new file mode 100644 index 000000000..92111aea8 Binary files /dev/null and b/Deploy/UpdateGenerator/Wox.Plugin.dll differ diff --git a/Deploy/UpdateGenerator/Wox.UpdateFeedGenerator.exe b/Deploy/UpdateGenerator/Wox.UpdateFeedGenerator.exe new file mode 100644 index 000000000..88284908a Binary files /dev/null and b/Deploy/UpdateGenerator/Wox.UpdateFeedGenerator.exe differ diff --git a/Deploy/UpdateGenerator/build.bat b/Deploy/UpdateGenerator/build.bat new file mode 100644 index 000000000..f51873e12 --- /dev/null +++ b/Deploy/UpdateGenerator/build.bat @@ -0,0 +1,2 @@ +cd /d %~dp0 +%~dp0Wox.UpdateFeedGenerator.exe diff --git a/Deploy/UpdateGenerator/config.json b/Deploy/UpdateGenerator/config.json new file mode 100644 index 000000000..0e0afce15 --- /dev/null +++ b/Deploy/UpdateGenerator/config.json @@ -0,0 +1,10 @@ +{ + "OutputDirectory": "..\\..\\Output\\Update", + "SourceDirectory": "..\\..\\Output\\Release", + "BaseURL": "http://127.0.0.1:8888", + "FeedXMLName": "update.xml", + "CheckVersion": false, + "CheckSize": false, + "CheckDate": false, + "CheckHash": true +} diff --git a/Plugins/Wox.Plugin.CMD/CMD.cs b/Plugins/Wox.Plugin.CMD/CMD.cs index cde0bb6f8..bb0a21272 100644 --- a/Plugins/Wox.Plugin.CMD/CMD.cs +++ b/Plugins/Wox.Plugin.CMD/CMD.cs @@ -6,12 +6,13 @@ using System.Reflection; using System.Windows.Forms; using WindowsInput; using WindowsInput.Native; +using Wox.Infrastructure; using Wox.Infrastructure.Hotkey; using Control = System.Windows.Controls.Control; namespace Wox.Plugin.CMD { - public class CMD : IPlugin, ISettingProvider, IPluginI18n + public class CMD : IPlugin, ISettingProvider, IPluginI18n, IInstantSearch { private PluginInitContext context; private bool WinRStroked; @@ -21,14 +22,14 @@ namespace Wox.Plugin.CMD { List results = new List(); List pushedResults = new List(); - if (query.RawQuery == ">") + if (query.Search == ">") { return GetAllHistoryCmds(); } - if (query.RawQuery.StartsWith(">") && query.RawQuery.Length > 1) + if (query.Search.StartsWith(">") && query.Search.Length > 1) { - string cmd = query.RawQuery.Substring(1); + string cmd = query.Search.Substring(1); var queryCmd = GetCurrentCmd(cmd); context.API.PushResults(query, context.CurrentPluginMetadata, new List() { queryCmd }); pushedResults.Add(queryCmd); @@ -37,6 +38,7 @@ namespace Wox.Plugin.CMD context.API.PushResults(query, context.CurrentPluginMetadata, history); pushedResults.AddRange(history); + try { string basedir = null; @@ -72,6 +74,7 @@ namespace Wox.Plugin.CMD } } catch (Exception) { } + } return results; } @@ -207,5 +210,11 @@ namespace Wox.Plugin.CMD { return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Languages"); } + + public bool IsInstantSearch(string query) + { + if (query.StartsWith(">")) return true; + return false; + } } -} +} \ No newline at end of file diff --git a/Plugins/Wox.Plugin.CMD/Wox.Plugin.CMD.csproj b/Plugins/Wox.Plugin.CMD/Wox.Plugin.CMD.csproj index 81bea53e1..b64f79fc2 100644 --- a/Plugins/Wox.Plugin.CMD/Wox.Plugin.CMD.csproj +++ b/Plugins/Wox.Plugin.CMD/Wox.Plugin.CMD.csproj @@ -50,9 +50,8 @@ - - False - ..\..\packages\WindowsInput.0.2.0.0\lib\net20\WindowsInput.dll + + ..\..\packages\InputSimulator.1.0.4.0\lib\net20\WindowsInput.dll diff --git a/Plugins/Wox.Plugin.CMD/packages.config b/Plugins/Wox.Plugin.CMD/packages.config index 5e64150e7..4687456d1 100644 --- a/Plugins/Wox.Plugin.CMD/packages.config +++ b/Plugins/Wox.Plugin.CMD/packages.config @@ -1,5 +1,5 @@  + - \ No newline at end of file diff --git a/Plugins/Wox.Plugin.Caculator/Calculator.cs b/Plugins/Wox.Plugin.Caculator/Calculator.cs index 55ddbc8a6..da5e580a7 100644 --- a/Plugins/Wox.Plugin.Caculator/Calculator.cs +++ b/Plugins/Wox.Plugin.Caculator/Calculator.cs @@ -28,13 +28,13 @@ namespace Wox.Plugin.Caculator public List Query(Query query) { - if (query.RawQuery.Length <= 2 // don't affect when user only input "e" or "i" keyword - || !regValidExpressChar.IsMatch(query.RawQuery) - || !IsBracketComplete(query.RawQuery)) return new List(); + if (query.Search.Length <= 2 // don't affect when user only input "e" or "i" keyword + || !regValidExpressChar.IsMatch(query.Search) + || !IsBracketComplete(query.Search)) return new List(); try { - var result = yampContext.Run(query.RawQuery); + var result = yampContext.Run(query.Search); if (result.Output != null && !string.IsNullOrEmpty(result.Result)) { return new List() { new Result() { diff --git a/Plugins/Wox.Plugin.Caculator/Wox.Plugin.Caculator.csproj b/Plugins/Wox.Plugin.Caculator/Wox.Plugin.Caculator.csproj index 88dd34d16..0a3f8ef91 100644 --- a/Plugins/Wox.Plugin.Caculator/Wox.Plugin.Caculator.csproj +++ b/Plugins/Wox.Plugin.Caculator/Wox.Plugin.Caculator.csproj @@ -81,6 +81,10 @@ + + + + + \ No newline at end of file diff --git a/Plugins/Wox.Plugin.Everything/Wox.Plugin.Everything.sln b/Plugins/Wox.Plugin.Everything/Wox.Plugin.Everything.sln new file mode 100644 index 000000000..f4fdc6d15 --- /dev/null +++ b/Plugins/Wox.Plugin.Everything/Wox.Plugin.Everything.sln @@ -0,0 +1,29 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Plugin.Everything", "Wox.Plugin.Everything.csproj", "{230AE83F-E92E-4E69-8355-426B305DA9C0}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{9BEA8C30-8CC3-48FE-87FD-8D7E65898C1A}" + ProjectSection(SolutionItems) = preProject + .nuget\NuGet.Config = .nuget\NuGet.Config + .nuget\NuGet.exe = .nuget\NuGet.exe + .nuget\NuGet.targets = .nuget\NuGet.targets + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {230AE83F-E92E-4E69-8355-426B305DA9C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {230AE83F-E92E-4E69-8355-426B305DA9C0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {230AE83F-E92E-4E69-8355-426B305DA9C0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {230AE83F-E92E-4E69-8355-426B305DA9C0}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Plugins/Wox.Plugin.Everything/nativesrc/Everything.c b/Plugins/Wox.Plugin.Everything/nativesrc/Everything.c new file mode 100644 index 000000000..fa7400233 --- /dev/null +++ b/Plugins/Wox.Plugin.Everything/nativesrc/Everything.c @@ -0,0 +1,1801 @@ + +// disable warnings +#pragma warning(disable : 4996) // deprecation + +#define EVERYTHINGUSERAPI __declspec(dllexport) + +// include +#include "Everything.h" +#include "Everything_IPC.h" + +// return copydata code +#define _EVERYTHING_COPYDATA_QUERYCOMPLETEA 0 +#define _EVERYTHING_COPYDATA_QUERYCOMPLETEW 1 + +// internal state +static BOOL _Everything_MatchPath = FALSE; +static BOOL _Everything_MatchCase = FALSE; +static BOOL _Everything_MatchWholeWord = FALSE; +static BOOL _Everything_Regex = FALSE; +static DWORD _Everything_LastError = FALSE; +static DWORD _Everything_Max = EVERYTHING_IPC_ALLRESULTS; +static DWORD _Everything_Offset = 0; +static BOOL _Everything_IsUnicodeQuery = FALSE; +static BOOL _Everything_IsUnicodeSearch = FALSE; +static LPVOID _Everything_Search = NULL; // wchar or char +static LPVOID _Everything_List = NULL; // EVERYTHING_IPC_LISTW or EVERYTHING_IPC_LISTA +static volatile BOOL _Everything_Initialized = FALSE; +static volatile LONG _Everything_InterlockedCount = 0; +static CRITICAL_SECTION _Everything_cs; +static HWND _Everything_ReplyWindow = 0; +static DWORD _Everything_ReplyID = 0; + +static VOID _Everything_Initialize(VOID) +{ + if (!_Everything_Initialized) + { + if (InterlockedIncrement(&_Everything_InterlockedCount) == 1) + { + // do the initialization.. + InitializeCriticalSection(&_Everything_cs); + + _Everything_Initialized = 1; + } + else + { + // wait for initialization.. + while (!_Everything_Initialized) Sleep(0); + } + } +} + +static VOID _Everything_Lock(VOID) +{ + _Everything_Initialize(); + + EnterCriticalSection(&_Everything_cs); +} + +static VOID _Everything_Unlock(VOID) +{ + LeaveCriticalSection(&_Everything_cs); +} + +// aVOID other libs +static int _Everything_StringLengthA(LPCSTR start) +{ + register LPCSTR s; + + s = start; + + while(*s) + { + s++; + } + + return (int)(s-start); +} + +static int _Everything_StringLengthW(LPCWSTR start) +{ + register LPCWSTR s; + + s = start; + + while(*s) + { + s++; + } + + return (int)(s-start); +} + +VOID EVERYTHINGAPI Everything_SetSearchW(LPCWSTR lpString) +{ + int len; + + _Everything_Lock(); + + if (_Everything_Search) HeapFree(GetProcessHeap(),0,_Everything_Search); + + len = _Everything_StringLengthW(lpString) + 1; + + _Everything_Search = HeapAlloc(GetProcessHeap(),0,len*sizeof(wchar_t)); + if (_Everything_Search) + { + CopyMemory(_Everything_Search,lpString,len*sizeof(wchar_t)); + } + else + { + _Everything_LastError = EVERYTHING_ERROR_MEMORY; + } + + _Everything_IsUnicodeSearch = 1; + + _Everything_Unlock(); +} + +VOID EVERYTHINGAPI Everything_SetSearchA(LPCSTR lpString) +{ + int size; + + _Everything_Lock(); + + if (_Everything_Search) HeapFree(GetProcessHeap(),0,_Everything_Search); + + size = _Everything_StringLengthA(lpString) + 1; + + _Everything_Search = (LPWSTR )HeapAlloc(GetProcessHeap(),0,size); + if (_Everything_Search) + { + CopyMemory(_Everything_Search,lpString,size); + } + else + { + _Everything_LastError = EVERYTHING_ERROR_MEMORY; + } + + _Everything_IsUnicodeSearch = 0; + + _Everything_Unlock(); +} + +LPCSTR EVERYTHINGAPI Everything_GetSearchA(VOID) +{ + LPCSTR ret; + + _Everything_Lock(); + + if (_Everything_Search) + { + if (_Everything_IsUnicodeSearch) + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDCALL; + + ret = NULL; + } + else + { + ret = (LPCSTR)_Everything_Search; + } + } + else + { + ret = ""; + } + + _Everything_Unlock(); + + return ret; +} + +LPCWSTR EVERYTHINGAPI Everything_GetSearchW(VOID) +{ + LPCWSTR ret; + + _Everything_Lock(); + + if (_Everything_Search) + { + if (!_Everything_IsUnicodeSearch) + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDCALL; + + ret = NULL; + } + else + { + ret = (LPCWSTR)_Everything_Search; + } + } + else + { + ret = L""; + } + + _Everything_Unlock(); + + return ret; +} + +VOID EVERYTHINGAPI Everything_SetMatchPath(BOOL bEnable) +{ + _Everything_Lock(); + + _Everything_MatchPath = bEnable; + + _Everything_Unlock(); +} + +VOID EVERYTHINGAPI Everything_SetMatchCase(BOOL bEnable) +{ + _Everything_Lock(); + + _Everything_MatchCase = bEnable; + + _Everything_Unlock(); +} + +VOID EVERYTHINGAPI Everything_SetMatchWholeWord(BOOL bEnable) +{ + _Everything_Lock(); + + _Everything_MatchWholeWord = bEnable; + + _Everything_Unlock(); +} + +VOID EVERYTHINGAPI Everything_SetRegex(BOOL bEnable) +{ + _Everything_Lock(); + + _Everything_Regex = bEnable; + + _Everything_Unlock(); +} + +VOID EVERYTHINGAPI Everything_SetMax(DWORD dwMax) +{ + _Everything_Lock(); + + _Everything_Max = dwMax; + + _Everything_Unlock(); +} + +VOID EVERYTHINGAPI Everything_SetOffset(DWORD dwOffset) +{ + _Everything_Lock(); + + _Everything_Offset = dwOffset; + + _Everything_Unlock(); +} + +VOID EVERYTHINGAPI Everything_SetReplyWindow(HWND hWnd) +{ + _Everything_Lock(); + + _Everything_ReplyWindow = hWnd; + + _Everything_Unlock(); +} + +VOID EVERYTHINGAPI Everything_SetReplyID(DWORD nId) +{ + _Everything_Lock(); + + _Everything_ReplyID = nId; + + _Everything_Unlock(); +} + +BOOL EVERYTHINGAPI Everything_GetMatchPath(VOID) +{ + BOOL ret; + + _Everything_Lock(); + + ret = _Everything_MatchPath; + + _Everything_Unlock(); + + return ret; +} + +BOOL EVERYTHINGAPI Everything_GetMatchCase(VOID) +{ + BOOL ret; + + _Everything_Lock(); + + ret = _Everything_MatchCase; + + _Everything_Unlock(); + + return ret; +} + +BOOL EVERYTHINGAPI Everything_GetMatchWholeWord(VOID) +{ + BOOL ret; + + _Everything_Lock(); + + ret = _Everything_MatchWholeWord; + + _Everything_Unlock(); + + return ret; +} + +BOOL EVERYTHINGAPI Everything_GetRegex(VOID) +{ + BOOL ret; + + _Everything_Lock(); + + ret = _Everything_Regex; + + _Everything_Unlock(); + + return ret; +} + +DWORD EVERYTHINGAPI Everything_GetMax(VOID) +{ + BOOL ret; + + _Everything_Lock(); + + ret = _Everything_Max; + + _Everything_Unlock(); + + return ret; +} + +DWORD EVERYTHINGAPI Everything_GetOffset(VOID) +{ + BOOL ret; + + _Everything_Lock(); + + ret = _Everything_Offset; + + _Everything_Unlock(); + + return ret; +} + +HWND EVERYTHINGAPI Everything_GetReplyWindow(VOID) +{ + HWND ret; + + _Everything_Lock(); + + ret = _Everything_ReplyWindow; + + _Everything_Unlock(); + + return ret; +} + +DWORD EVERYTHINGAPI Everything_GetReplyID(VOID) +{ + DWORD ret; + + _Everything_Lock(); + + ret = _Everything_ReplyID; + + _Everything_Unlock(); + + return ret; +} + +// custom window proc +static LRESULT EVERYTHINGAPI _Everything_window_proc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) +{ + switch(msg) + { + case WM_COPYDATA: + { + COPYDATASTRUCT *cds = (COPYDATASTRUCT *)lParam; + + switch(cds->dwData) + { + case _EVERYTHING_COPYDATA_QUERYCOMPLETEA: + + if (!_Everything_IsUnicodeQuery) + { + if (_Everything_List) HeapFree(GetProcessHeap(),0,_Everything_List); + + _Everything_List = (EVERYTHING_IPC_LISTW *)HeapAlloc(GetProcessHeap(),0,cds->cbData); + + if (_Everything_List) + { + CopyMemory(_Everything_List,cds->lpData,cds->cbData); + } + else + { + _Everything_LastError = EVERYTHING_ERROR_MEMORY; + } + + PostQuitMessage(0); + + return TRUE; + } + + break; + + case _EVERYTHING_COPYDATA_QUERYCOMPLETEW: + + if (_Everything_IsUnicodeQuery) + { + if (_Everything_List) HeapFree(GetProcessHeap(),0,_Everything_List); + + _Everything_List = (EVERYTHING_IPC_LISTW *)HeapAlloc(GetProcessHeap(),0,cds->cbData); + + if (_Everything_List) + { + CopyMemory(_Everything_List,cds->lpData,cds->cbData); + } + else + { + _Everything_LastError = EVERYTHING_ERROR_MEMORY; + } + + PostQuitMessage(0); + + return TRUE; + } + + break; + } + + break; + } + } + + return DefWindowProc(hwnd,msg,wParam,lParam); +} + +// get the search length +static int _Everything_GetSearchLengthW(VOID) +{ + if (_Everything_Search) + { + if (_Everything_IsUnicodeSearch) + { + return _Everything_StringLengthW((LPCWSTR )_Everything_Search); + } + else + { + return MultiByteToWideChar(CP_ACP,0,(LPCSTR )_Everything_Search,-1,0,0); + } + } + + return 0; +} + +// get the search length +static int _Everything_GetSearchLengthA(VOID) +{ + if (_Everything_Search) + { + if (_Everything_IsUnicodeSearch) + { + return WideCharToMultiByte(CP_ACP,0,(LPCWSTR )_Everything_Search,-1,0,0,0,0); + } + else + { + return _Everything_StringLengthA((LPCSTR )_Everything_Search); + } + } + + return 0; +} + +// get the search length +static VOID _Everything_GetSearchTextW(LPWSTR wbuf) +{ + int wlen; + + if (_Everything_Search) + { + wlen = _Everything_GetSearchLengthW(); + + if (_Everything_IsUnicodeSearch) + { + CopyMemory(wbuf,_Everything_Search,(wlen+1) * sizeof(wchar_t)); + + return; + } + else + { + MultiByteToWideChar(CP_ACP,0,(LPCSTR )_Everything_Search,-1,wbuf,wlen+1); + + return; + } + } + + *wbuf = 0; +} + +// get the search length +static VOID _Everything_GetSearchTextA(LPSTR buf) +{ + int len; + + if (_Everything_Search) + { + len = _Everything_GetSearchLengthW(); + + if (_Everything_IsUnicodeSearch) + { + WideCharToMultiByte(CP_ACP,0,(LPCWSTR )_Everything_Search,-1,buf,len+1,0,0); + + return; + } + else + { + CopyMemory(buf,_Everything_Search,len+1); + + return; + } + } + + *buf = 0; +} + +static DWORD EVERYTHINGAPI _Everything_thread_proc(VOID *param) +{ + HWND everything_hwnd; + COPYDATASTRUCT cds; + WNDCLASSEX wcex; + HWND hwnd; + MSG msg; + int ret; + int len; + int size; + union + { + EVERYTHING_IPC_QUERYA *queryA; + EVERYTHING_IPC_QUERYW *queryW; + VOID *query; + }q; + + ZeroMemory(&wcex,sizeof(wcex)); + wcex.cbSize = sizeof(wcex); + + if (!GetClassInfoEx(GetModuleHandle(0),TEXT("EVERYTHING_DLL"),&wcex)) + { + ZeroMemory(&wcex,sizeof(wcex)); + wcex.cbSize = sizeof(wcex); + wcex.hInstance = GetModuleHandle(0); + wcex.lpfnWndProc = _Everything_window_proc; + wcex.lpszClassName = TEXT("EVERYTHING_DLL"); + + if (!RegisterClassEx(&wcex)) + { + _Everything_LastError = EVERYTHING_ERROR_REGISTERCLASSEX; + + return 0; + } + } + + hwnd = CreateWindow( + TEXT("EVERYTHING_DLL"), + TEXT(""), + 0, + 0,0,0,0, + 0,0,GetModuleHandle(0),0); + + if (hwnd) + { + everything_hwnd = FindWindow(EVERYTHING_IPC_WNDCLASS,0); + if (everything_hwnd) + { + LPVOID a; + + if (param) + { + // unicode + len = _Everything_GetSearchLengthW(); + + size = sizeof(EVERYTHING_IPC_QUERYW) - sizeof(wchar_t) + len*sizeof(wchar_t) + sizeof(wchar_t); + } + else + { + // ansi + len = _Everything_GetSearchLengthA(); + + size = sizeof(EVERYTHING_IPC_QUERYA) - sizeof(char) + (len*sizeof(char)) + sizeof(char); + } + + // alloc + a = HeapAlloc(GetProcessHeap(),0,size); + q.query = (EVERYTHING_IPC_QUERYW *)a; + + if (q.query) + { + if (param) + { + q.queryW->max_results = _Everything_Max; + q.queryW->offset = _Everything_Offset; + q.queryW->reply_copydata_message = _EVERYTHING_COPYDATA_QUERYCOMPLETEW; + q.queryW->search_flags = (_Everything_Regex?EVERYTHING_IPC_REGEX:0) | (_Everything_MatchCase?EVERYTHING_IPC_MATCHCASE:0) | (_Everything_MatchWholeWord?EVERYTHING_IPC_MATCHWHOLEWORD:0) | (_Everything_MatchPath?EVERYTHING_IPC_MATCHPATH:0); + q.queryW->reply_hwnd = (INT32) hwnd; + + _Everything_GetSearchTextW((LPWSTR) q.queryW->search_string); + } + else + { + q.queryA->max_results = _Everything_Max; + q.queryA->offset = _Everything_Offset; + q.queryA->reply_copydata_message = _EVERYTHING_COPYDATA_QUERYCOMPLETEA; + q.queryA->search_flags = (_Everything_Regex?EVERYTHING_IPC_REGEX:0) | (_Everything_MatchCase?EVERYTHING_IPC_MATCHCASE:0) | (_Everything_MatchWholeWord?EVERYTHING_IPC_MATCHWHOLEWORD:0) | (_Everything_MatchPath?EVERYTHING_IPC_MATCHPATH:0); + q.queryA->reply_hwnd = (INT32)hwnd; + + _Everything_GetSearchTextA((LPSTR) q.queryA->search_string); + } + + cds.cbData = size; + cds.dwData = param?EVERYTHING_IPC_COPYDATAQUERYW:EVERYTHING_IPC_COPYDATAQUERYA; + cds.lpData = q.query; + + if (SendMessage(everything_hwnd,WM_COPYDATA,(WPARAM)hwnd,(LPARAM)&cds) == TRUE) + { + // message pump + loop: + + WaitMessage(); + + // update windows + while(PeekMessage(&msg,NULL,0,0,0)) + { + ret = (int)GetMessage(&msg,0,0,0); + if (ret == -1) goto exit; + if (!ret) goto exit; + + // let windows handle it. + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + goto loop; + + exit: + + // get result from window. + DestroyWindow(hwnd); + } + else + { + _Everything_LastError = EVERYTHING_ERROR_IPC; + } + + // get result from window. + HeapFree(GetProcessHeap(),0,q.query); + } + else + { + _Everything_LastError = EVERYTHING_ERROR_MEMORY; + } + } + else + { + // the everything window was not found. + // we can optionally RegisterWindowMessage("EVERYTHING_IPC_CREATED") and + // wait for Everything to post this message to all top level windows when its up and running. + _Everything_LastError = EVERYTHING_ERROR_IPC; + } + } + else + { + _Everything_LastError = EVERYTHING_ERROR_CREATEWINDOW; + } + + return 0; +} + +static BOOL EVERYTHINGAPI _Everything_Query(BOOL bUnicode) +{ + HANDLE hthread; + DWORD threadid; + VOID *param; + + // reset the error flag. + _Everything_LastError = 0; + + if (bUnicode) + { + param = (VOID *)1; + } + else + { + param = 0; + } + + _Everything_IsUnicodeQuery = bUnicode; + + hthread = CreateThread(0,0,_Everything_thread_proc,param,0,&threadid); + + if (hthread) + { + WaitForSingleObject(hthread,INFINITE); + + CloseHandle(hthread); + } + else + { + _Everything_LastError = EVERYTHING_ERROR_CREATETHREAD; + } + + return (_Everything_LastError == 0)?TRUE:FALSE; +} + + +BOOL _Everything_SendIPCQuery(BOOL bUnicode) +{ + HWND everything_hwnd; + COPYDATASTRUCT cds; + int ret; + int len; + int size; + union + { + EVERYTHING_IPC_QUERYA *queryA; + EVERYTHING_IPC_QUERYW *queryW; + VOID *query; + }q; + + _Everything_IsUnicodeQuery = bUnicode; + + // find the everything ipc window. + everything_hwnd = FindWindow(EVERYTHING_IPC_WNDCLASS,0); + if (everything_hwnd) + { + if (bUnicode) + { + // unicode + len = _Everything_GetSearchLengthW(); + + size = sizeof(EVERYTHING_IPC_QUERYW) - sizeof(wchar_t) + len*sizeof(wchar_t) + sizeof(wchar_t); + } + else + { + // ansi + len = _Everything_GetSearchLengthA(); + + size = sizeof(EVERYTHING_IPC_QUERYA) - sizeof(char) + (len*sizeof(char)) + sizeof(char); + } + + // alloc + q.query = (EVERYTHING_IPC_QUERYW *)HeapAlloc(GetProcessHeap(),0,size); + + if (q.query) + { + if (bUnicode) + { + q.queryW->max_results = _Everything_Max; + q.queryW->offset = _Everything_Offset; + q.queryW->reply_copydata_message = _Everything_ReplyID; + q.queryW->search_flags = (_Everything_Regex?EVERYTHING_IPC_REGEX:0) | (_Everything_MatchCase?EVERYTHING_IPC_MATCHCASE:0) | (_Everything_MatchWholeWord?EVERYTHING_IPC_MATCHWHOLEWORD:0) | (_Everything_MatchPath?EVERYTHING_IPC_MATCHPATH:0); + q.queryW->reply_hwnd = (INT32) _Everything_ReplyWindow; + + _Everything_GetSearchTextW((LPWSTR) q.queryW->search_string); + } + else + { + q.queryA->max_results = _Everything_Max; + q.queryA->offset = _Everything_Offset; + q.queryA->reply_copydata_message = _Everything_ReplyID; + q.queryA->search_flags = (_Everything_Regex?EVERYTHING_IPC_REGEX:0) | (_Everything_MatchCase?EVERYTHING_IPC_MATCHCASE:0) | (_Everything_MatchWholeWord?EVERYTHING_IPC_MATCHWHOLEWORD:0) | (_Everything_MatchPath?EVERYTHING_IPC_MATCHPATH:0); + q.queryA->reply_hwnd = (INT32) _Everything_ReplyWindow; + + _Everything_GetSearchTextA((LPSTR) q.queryA->search_string); + } + + cds.cbData = size; + cds.dwData = bUnicode?EVERYTHING_IPC_COPYDATAQUERYW:EVERYTHING_IPC_COPYDATAQUERYA; + cds.lpData = q.query; + + if (SendMessage(everything_hwnd,WM_COPYDATA,(WPARAM)_Everything_ReplyWindow,(LPARAM)&cds)) + { + // sucessful. + ret = TRUE; + } + else + { + // no ipc + _Everything_LastError = EVERYTHING_ERROR_IPC; + + ret = FALSE; + } + + // get result from window. + HeapFree(GetProcessHeap(),0,q.query); + } + else + { + _Everything_LastError = EVERYTHING_ERROR_MEMORY; + + ret = FALSE; + } + } + else + { + _Everything_LastError = EVERYTHING_ERROR_IPC; + + ret = FALSE; + } + + return ret; +} + +BOOL EVERYTHINGAPI Everything_QueryA(BOOL bWait) +{ + BOOL ret; + + _Everything_Lock(); + + if (bWait) + { + ret = _Everything_Query(FALSE); + } + else + { + ret = _Everything_SendIPCQuery(FALSE); + } + + _Everything_Unlock(); + + return ret; +} + +BOOL EVERYTHINGAPI Everything_QueryW(BOOL bWait) +{ + BOOL ret; + + _Everything_Lock(); + + if (bWait) + { + ret = _Everything_Query(TRUE); + } + else + { + ret = _Everything_SendIPCQuery(TRUE); + } + + _Everything_Unlock(); + + return ret; +} + +static int _Everything_CompareA(const VOID *a,const VOID *b) +{ + int i; + + i = stricmp(EVERYTHING_IPC_ITEMPATH(_Everything_List,a),EVERYTHING_IPC_ITEMPATH(_Everything_List,b)); + + if (!i) + { + return stricmp(EVERYTHING_IPC_ITEMFILENAMEA(_Everything_List,a),EVERYTHING_IPC_ITEMFILENAMEA(_Everything_List,b)); + } + else + if (i > 0) + { + return 1; + } + else + { + return -1; + } +} + +static int _Everything_CompareW(const VOID *a,const VOID *b) +{ + int i; + + i = stricmp(EVERYTHING_IPC_ITEMPATH(_Everything_List,a),EVERYTHING_IPC_ITEMPATH(_Everything_List,b)); + + if (!i) + { + return wcsicmp(EVERYTHING_IPC_ITEMFILENAMEW(_Everything_List,a),EVERYTHING_IPC_ITEMFILENAMEW(_Everything_List,b)); + } + else + if (i > 0) + { + return 1; + } + else + { + return -1; + } +} + +VOID EVERYTHINGAPI Everything_SortResultsByPath(VOID) +{ + _Everything_Lock(); + + if (_Everything_List) + { + if (_Everything_IsUnicodeQuery) + { + qsort(((EVERYTHING_IPC_LISTW *)_Everything_List)->items,((EVERYTHING_IPC_LISTW *)_Everything_List)->numitems,sizeof(EVERYTHING_IPC_ITEMW),_Everything_CompareW); + } + else + { + qsort(((EVERYTHING_IPC_LISTA *)_Everything_List)->items,((EVERYTHING_IPC_LISTA *)_Everything_List)->numitems,sizeof(EVERYTHING_IPC_ITEMA),_Everything_CompareA); + } + } + else + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDCALL; + } + + _Everything_Unlock(); +} + +DWORD EVERYTHINGAPI Everything_GetLastError(VOID) +{ + DWORD ret; + + _Everything_Lock(); + + ret = _Everything_LastError; + + _Everything_Unlock(); + + return ret; +} + +int EVERYTHINGAPI Everything_GetNumFileResults(VOID) +{ + int ret; + + _Everything_Lock(); + + if (_Everything_List) + { + if (_Everything_IsUnicodeQuery) + { + ret = ((EVERYTHING_IPC_LISTW *)_Everything_List)->numfiles; + } + else + { + ret = ((EVERYTHING_IPC_LISTA *)_Everything_List)->numfiles; + } + } + else + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDCALL; + + ret = 0; + } + + _Everything_Unlock(); + + return ret; +} + +int EVERYTHINGAPI Everything_GetNumFolderResults(VOID) +{ + int ret; + + _Everything_Lock(); + + if (_Everything_List) + { + if (_Everything_IsUnicodeQuery) + { + ret = ((EVERYTHING_IPC_LISTW *)_Everything_List)->numfolders; + } + else + { + ret = ((EVERYTHING_IPC_LISTA *)_Everything_List)->numfolders; + } + } + else + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDCALL; + + ret = 0; + } + + _Everything_Unlock(); + + return ret; +} + +int EVERYTHINGAPI Everything_GetNumResults(VOID) +{ + int ret; + + _Everything_Lock(); + + if (_Everything_List) + { + if (_Everything_IsUnicodeQuery) + { + ret = ((EVERYTHING_IPC_LISTW *)_Everything_List)->numitems; + } + else + { + ret = ((EVERYTHING_IPC_LISTA *)_Everything_List)->numitems; + } + } + else + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDCALL; + + ret = 0; + } + + _Everything_Unlock(); + + return ret; +} + +int EVERYTHINGAPI Everything_GetTotFileResults(VOID) +{ + int ret; + + _Everything_Lock(); + + if (_Everything_List) + { + if (_Everything_IsUnicodeQuery) + { + ret = ((EVERYTHING_IPC_LISTW *)_Everything_List)->totfiles; + } + else + { + ret = ((EVERYTHING_IPC_LISTA *)_Everything_List)->totfiles; + } + } + else + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDCALL; + + ret = 0; + } + + _Everything_Unlock(); + + return ret; +} + +int EVERYTHINGAPI Everything_GetTotFolderResults(VOID) +{ + int ret; + + _Everything_Lock(); + + if (_Everything_List) + { + if (_Everything_IsUnicodeQuery) + { + ret = ((EVERYTHING_IPC_LISTW *)_Everything_List)->totfolders; + } + else + { + ret = ((EVERYTHING_IPC_LISTA *)_Everything_List)->totfolders; + } + } + else + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDCALL; + + ret = 0; + } + + _Everything_Unlock(); + + return ret; +} + +int EVERYTHINGAPI Everything_GetTotResults(VOID) +{ + int ret; + + _Everything_Lock(); + + if (_Everything_List) + { + if (_Everything_IsUnicodeQuery) + { + ret = ((EVERYTHING_IPC_LISTW *)_Everything_List)->totitems; + } + else + { + ret = ((EVERYTHING_IPC_LISTA *)_Everything_List)->totitems; + } + } + else + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDCALL; + + ret = 0; + } + + _Everything_Unlock(); + + return ret; +} + +BOOL EVERYTHINGAPI Everything_IsVolumeResult(int nIndex) +{ + BOOL ret; + + _Everything_Lock(); + + if (_Everything_List) + { + if (nIndex < 0) + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDINDEX; + + ret = FALSE; + + goto exit; + } + + if (nIndex >= Everything_GetNumResults()) + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDINDEX; + + ret = FALSE; + + goto exit; + } + + if (_Everything_IsUnicodeQuery) + { + ret = ((EVERYTHING_IPC_LISTW *)_Everything_List)->items[nIndex].flags & EVERYTHING_IPC_DRIVE; + } + else + { + ret = ((EVERYTHING_IPC_LISTA *)_Everything_List)->items[nIndex].flags & EVERYTHING_IPC_DRIVE; + } + } + else + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDCALL; + + ret = FALSE; + } + +exit: + + _Everything_Unlock(); + + return ret; +} + +BOOL EVERYTHINGAPI Everything_IsFolderResult(int nIndex) +{ + BOOL ret; + + _Everything_Lock(); + + if (_Everything_List) + { + if (nIndex < 0) + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDINDEX; + + ret = FALSE; + + goto exit; + } + + if (nIndex >= Everything_GetNumResults()) + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDINDEX; + + ret = FALSE; + + goto exit; + } + + if (_Everything_IsUnicodeQuery) + { + ret = ((EVERYTHING_IPC_LISTW *)_Everything_List)->items[nIndex].flags & (EVERYTHING_IPC_DRIVE|EVERYTHING_IPC_FOLDER); + } + else + { + ret = ((EVERYTHING_IPC_LISTA *)_Everything_List)->items[nIndex].flags & (EVERYTHING_IPC_DRIVE|EVERYTHING_IPC_FOLDER); + } + } + else + { + ret = FALSE; + } + +exit: + + _Everything_Unlock(); + + return ret; +} + +BOOL EVERYTHINGAPI Everything_IsFileResult(int nIndex) +{ + BOOL ret; + + _Everything_Lock(); + + if (_Everything_List) + { + if (nIndex < 0) + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDINDEX; + + ret = FALSE; + + goto exit; + } + + if (nIndex >= Everything_GetNumResults()) + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDINDEX; + + ret = FALSE; + + goto exit; + } + + if (_Everything_IsUnicodeQuery) + { + ret = !(((EVERYTHING_IPC_LISTW *)_Everything_List)->items[nIndex].flags & (EVERYTHING_IPC_DRIVE|EVERYTHING_IPC_FOLDER)); + } + else + { + ret = !(((EVERYTHING_IPC_LISTA *)_Everything_List)->items[nIndex].flags & (EVERYTHING_IPC_DRIVE|EVERYTHING_IPC_FOLDER)); + } + } + else + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDCALL; + + ret = FALSE; + } + +exit: + + _Everything_Unlock(); + + return ret; +} + +LPCWSTR EVERYTHINGAPI Everything_GetResultFileNameW(int nIndex) +{ + LPCWSTR ret; + + _Everything_Lock(); + + if ((_Everything_List) && (_Everything_IsUnicodeQuery)) + { + if (nIndex < 0) + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDINDEX; + + ret = NULL; + + goto exit; + } + + if (nIndex >= (int)((EVERYTHING_IPC_LISTW *)_Everything_List)->numitems) + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDINDEX; + + ret = NULL; + + goto exit; + } + + ret = EVERYTHING_IPC_ITEMFILENAMEW(_Everything_List,&((EVERYTHING_IPC_LISTW *)_Everything_List)->items[nIndex]); + } + else + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDCALL; + + ret = NULL; + } + +exit: + + _Everything_Unlock(); + + return ret; +} + +LPCSTR EVERYTHINGAPI Everything_GetResultFileNameA(int nIndex) +{ + LPCSTR ret; + + _Everything_Lock(); + + if ((_Everything_List) && (!_Everything_IsUnicodeQuery)) + { + if (nIndex < 0) + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDINDEX; + + ret = NULL; + + goto exit; + } + + if (nIndex >= (int)((EVERYTHING_IPC_LISTA *)_Everything_List)->numitems) + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDINDEX; + + ret = NULL; + + goto exit; + } + + ret = EVERYTHING_IPC_ITEMFILENAMEA(_Everything_List,&((EVERYTHING_IPC_LISTA *)_Everything_List)->items[nIndex]); + } + else + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDCALL; + + ret = NULL; + } + +exit: + + _Everything_Unlock(); + + return ret; +} + +LPCWSTR EVERYTHINGAPI Everything_GetResultPathW(int nIndex) +{ + LPCWSTR ret; + + _Everything_Lock(); + + if ((_Everything_List) && (_Everything_IsUnicodeQuery)) + { + if (nIndex < 0) + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDINDEX; + + ret = NULL; + + goto exit; + } + + if (nIndex >= (int)((EVERYTHING_IPC_LISTW *)_Everything_List)->numitems) + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDINDEX; + + ret = NULL; + + goto exit; + } + + ret = EVERYTHING_IPC_ITEMPATHW(_Everything_List,&((EVERYTHING_IPC_LISTW *)_Everything_List)->items[nIndex]); + } + else + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDCALL; + + ret = NULL; + } + +exit: + + _Everything_Unlock(); + + return ret; +} + +LPCSTR EVERYTHINGAPI Everything_GetResultPathA(int nIndex) +{ + LPCSTR ret; + + _Everything_Lock(); + + if (_Everything_List) + { + if (nIndex < 0) + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDINDEX; + + ret = NULL; + + goto exit; + } + + if (nIndex >= (int)((EVERYTHING_IPC_LISTA *)_Everything_List)->numitems) + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDINDEX; + + ret = NULL; + + goto exit; + } + + ret = EVERYTHING_IPC_ITEMPATHA(_Everything_List,&((EVERYTHING_IPC_LISTA *)_Everything_List)->items[nIndex]); + } + else + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDCALL; + + ret = NULL; + } + +exit: + + _Everything_Unlock(); + + return ret; +} + +// max is in chars +static int _Everything_CopyW(LPWSTR buf,int bufmax,int catlen,LPCWSTR s) +{ + int wlen; + + if (buf) + { + buf += catlen; + bufmax -= catlen; + } + + wlen = _Everything_StringLengthW(s); + if (!wlen) + { + if (buf) + { + buf[wlen] = 0; + } + + return catlen; + } + + // terminate + if (wlen > bufmax-1) wlen = bufmax-1; + + if (buf) + { + CopyMemory(buf,s,wlen*sizeof(wchar_t)); + + buf[wlen] = 0; + } + + return wlen + catlen; +} + +static int _Everything_CopyA(LPSTR buf,int max,int catlen,LPCSTR s) +{ + int len; + + if (buf) + { + buf += catlen; + max -= catlen; + } + + len = _Everything_StringLengthA(s); + if (!len) + { + if (buf) + { + buf[len] = 0; + } + + return catlen; + } + + // terminate + if (len > max-1) len = max-1; + + if (buf) + { + CopyMemory(buf,s,len*sizeof(char)); + + buf[len] = 0; + } + + return len + catlen; + +} + +// max is in chars +static int _Everything_CopyWFromA(LPWSTR buf,int bufmax,int catlen,LPCSTR s) +{ + int wlen; + + if (buf) + { + buf += catlen; + bufmax -= catlen; + } + + wlen = MultiByteToWideChar(CP_ACP,0,s,_Everything_StringLengthA(s),0,0); + if (!wlen) + { + if (buf) + { + buf[wlen] = 0; + } + + return catlen; + } + + // terminate + if (wlen > bufmax-1) wlen = bufmax-1; + + if (buf) + { + MultiByteToWideChar(CP_ACP,0,s,_Everything_StringLengthA(s),buf,wlen); + + buf[wlen] = 0; + } + + return wlen + catlen; +} + +static int _Everything_CopyAFromW(LPSTR buf,int max,int catlen,LPCWSTR s) +{ + int len; + + if (buf) + { + buf += catlen; + max -= catlen; + } + + len = WideCharToMultiByte(CP_ACP,0,s,_Everything_StringLengthW(s),0,0,0,0); + if (!len) + { + if (buf) + { + buf[len] = 0; + } + + return catlen; + } + + // terminate + if (len > max-1) len = max-1; + + if (buf) + { + WideCharToMultiByte(CP_ACP,0,s,_Everything_StringLengthW(s),buf,len,0,0); + + buf[len] = 0; + } + + return len + catlen; + +} + +int EVERYTHINGUSERAPI Everything_GetResultFullPathNameW(int nIndex,LPWSTR wbuf,int wbuf_size_in_wchars) +{ + int len; + + _Everything_Lock(); + + if (_Everything_List) + { + if (nIndex < 0) + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDINDEX; + + len = _Everything_CopyW(wbuf,wbuf_size_in_wchars,0,L""); + + goto exit; + } + + if (nIndex >= (int)((EVERYTHING_IPC_LISTW *)_Everything_List)->numitems) + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDINDEX; + + len = _Everything_CopyW(wbuf,wbuf_size_in_wchars,0,L""); + + goto exit; + } + + len = 0; + + if (_Everything_IsUnicodeQuery) + { + len = _Everything_CopyW(wbuf,wbuf_size_in_wchars,len,EVERYTHING_IPC_ITEMPATHW(_Everything_List,&((EVERYTHING_IPC_LISTW *)_Everything_List)->items[nIndex])); + } + else + { + len = _Everything_CopyWFromA(wbuf,wbuf_size_in_wchars,len,EVERYTHING_IPC_ITEMPATHA(_Everything_List,&((EVERYTHING_IPC_LISTA *)_Everything_List)->items[nIndex])); + } + + if (len) + { + len = _Everything_CopyW(wbuf,wbuf_size_in_wchars,len,L"\\"); + } + + if (_Everything_IsUnicodeQuery) + { + len = _Everything_CopyW(wbuf,wbuf_size_in_wchars,len,EVERYTHING_IPC_ITEMFILENAMEW(_Everything_List,&((EVERYTHING_IPC_LISTW *)_Everything_List)->items[nIndex])); + } + else + { + len = _Everything_CopyWFromA(wbuf,wbuf_size_in_wchars,len,EVERYTHING_IPC_ITEMFILENAMEA(_Everything_List,&((EVERYTHING_IPC_LISTA *)_Everything_List)->items[nIndex])); + } + } + else + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDCALL; + + len = _Everything_CopyW(wbuf,wbuf_size_in_wchars,0,L""); + } + +exit: + + _Everything_Unlock(); + + return len; +} + +int EVERYTHINGUSERAPI Everything_GetResultFullPathNameA(int nIndex,LPSTR buf,int bufsize) +{ + int len; + + _Everything_Lock(); + + if (_Everything_List) + { + if (nIndex < 0) + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDINDEX; + + len = _Everything_CopyA(buf,bufsize,0,""); + + goto exit; + } + + if (nIndex >= (int)((EVERYTHING_IPC_LISTW *)_Everything_List)->numitems) + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDINDEX; + + len = _Everything_CopyA(buf,bufsize,0,""); + + goto exit; + } + + len = 0; + + if (_Everything_IsUnicodeQuery) + { + len = _Everything_CopyAFromW(buf,bufsize,len,EVERYTHING_IPC_ITEMPATHW(_Everything_List,&((EVERYTHING_IPC_LISTW *)_Everything_List)->items[nIndex])); + } + else + { + len = _Everything_CopyA(buf,bufsize,len,EVERYTHING_IPC_ITEMPATHA(_Everything_List,&((EVERYTHING_IPC_LISTA *)_Everything_List)->items[nIndex])); + } + + if (len) + { + len = _Everything_CopyA(buf,bufsize,len,"\\"); + } + + if (_Everything_IsUnicodeQuery) + { + len = _Everything_CopyAFromW(buf,bufsize,len,EVERYTHING_IPC_ITEMFILENAMEW(_Everything_List,&((EVERYTHING_IPC_LISTW *)_Everything_List)->items[nIndex])); + } + else + { + len = _Everything_CopyA(buf,bufsize,len,EVERYTHING_IPC_ITEMFILENAMEA(_Everything_List,&((EVERYTHING_IPC_LISTA *)_Everything_List)->items[nIndex])); + } + } + else + { + _Everything_LastError = EVERYTHING_ERROR_INVALIDCALL; + + len = _Everything_CopyA(buf,bufsize,0,""); + } + +exit: + + _Everything_Unlock(); + + return len; +} + +BOOL EVERYTHINGAPI Everything_IsQueryReply(UINT message,WPARAM wParam,LPARAM lParam,DWORD nId) +{ + if (message == WM_COPYDATA) + { + COPYDATASTRUCT *cds = (COPYDATASTRUCT *)lParam; + + if (cds) + { + if (cds->dwData == _Everything_ReplyID) + { + if (_Everything_IsUnicodeQuery) + { + if (_Everything_List) HeapFree(GetProcessHeap(),0,_Everything_List); + + _Everything_List = (EVERYTHING_IPC_LISTW *)HeapAlloc(GetProcessHeap(),0,cds->cbData); + + if (_Everything_List) + { + CopyMemory(_Everything_List,cds->lpData,cds->cbData); + } + else + { + _Everything_LastError = EVERYTHING_ERROR_MEMORY; + } + + return TRUE; + } + else + { + if (_Everything_List) HeapFree(GetProcessHeap(),0,_Everything_List); + + _Everything_List = (EVERYTHING_IPC_LISTW *)HeapAlloc(GetProcessHeap(),0,cds->cbData); + + if (_Everything_List) + { + CopyMemory(_Everything_List,cds->lpData,cds->cbData); + } + else + { + _Everything_LastError = EVERYTHING_ERROR_MEMORY; + } + + return TRUE; + } + } + } + } + + return FALSE; +} + +VOID EVERYTHINGUSERAPI Everything_Reset(VOID) +{ + _Everything_Lock(); + + if (_Everything_Search) + { + HeapFree(GetProcessHeap(),0,_Everything_Search); + + _Everything_Search = 0; + } + + if (_Everything_List) + { + HeapFree(GetProcessHeap(),0,_Everything_List); + + _Everything_List = 0; + } + + // reset state + _Everything_MatchPath = FALSE; + _Everything_MatchCase = FALSE; + _Everything_MatchWholeWord = FALSE; + _Everything_Regex = FALSE; + _Everything_LastError = FALSE; + _Everything_Max = EVERYTHING_IPC_ALLRESULTS; + _Everything_Offset = 0; + _Everything_IsUnicodeQuery = FALSE; + _Everything_IsUnicodeSearch = FALSE; + + _Everything_Unlock(); +} + +//VOID DestroyResultArray(VOID *) + +// testing +/* +int main(int argc,char **argv) +{ + char buf[MAX_PATH]; + wchar_t wbuf[MAX_PATH]; + + // set search +// Everything_SetSearchA("sonic"); + Everything_SetSearchW(L"sonic"); + +// Everything_QueryA(); + Everything_QueryW(TRUE); + +// Everything_GetResultFullPathNameA(0,buf,sizeof(buf)); + Everything_GetResultFullPathNameW(0,wbuf,sizeof(wbuf)/sizeof(wchar_t)); + +// MessageBoxA(0,buf,"result 1",MB_OK); + MessageBoxW(0,wbuf,L"result 1",MB_OK); + +// MessageBoxA(0,resultA.cFileName,"result 1",MB_OK); +// MessageBoxW(0,resultW.cFileName,L"result 1",MB_OK); +} +*/ \ No newline at end of file diff --git a/Plugins/Wox.Plugin.Everything/nativesrc/Everything.def b/Plugins/Wox.Plugin.Everything/nativesrc/Everything.def new file mode 100644 index 000000000..389f86885 --- /dev/null +++ b/Plugins/Wox.Plugin.Everything/nativesrc/Everything.def @@ -0,0 +1,51 @@ +LIBRARY Everything + +EXPORTS + + Everything_GetLastError + + Everything_SetSearchA + Everything_SetSearchW + Everything_SetMatchPath + Everything_SetMatchCase + Everything_SetMatchWholeWord + Everything_SetRegex + Everything_SetMax + Everything_SetOffset + + Everything_GetSearchA + Everything_GetSearchW + Everything_GetMatchPath + Everything_GetMatchCase + Everything_GetMatchWholeWord + Everything_GetRegex + Everything_GetMax + Everything_GetOffset + + Everything_QueryA + Everything_QueryW + + Everything_IsQueryReply + + Everything_SortResultsByPath + + Everything_GetNumFileResults + Everything_GetNumFolderResults + Everything_GetNumResults + Everything_GetTotFileResults + Everything_GetTotFolderResults + Everything_GetTotResults + + Everything_IsVolumeResult + Everything_IsFolderResult + Everything_IsFileResult + + Everything_GetResultFileNameA + Everything_GetResultFileNameW + Everything_GetResultPathA + Everything_GetResultPathW + Everything_GetResultFullPathNameA + Everything_GetResultFullPathNameW + + Everything_Reset + \ No newline at end of file diff --git a/Plugins/Wox.Plugin.Everything/nativesrc/Everything.h b/Plugins/Wox.Plugin.Everything/nativesrc/Everything.h new file mode 100644 index 000000000..1a1770ba5 --- /dev/null +++ b/Plugins/Wox.Plugin.Everything/nativesrc/Everything.h @@ -0,0 +1,95 @@ + +#ifndef _EVERYTHING_DLL_ +#define _EVERYTHING_DLL_ + +#ifndef _INC_WINDOWS +#include +#endif + +#define EVERYTHING_OK 0 +#define EVERYTHING_ERROR_MEMORY 1 +#define EVERYTHING_ERROR_IPC 2 +#define EVERYTHING_ERROR_REGISTERCLASSEX 3 +#define EVERYTHING_ERROR_CREATEWINDOW 4 +#define EVERYTHING_ERROR_CREATETHREAD 5 +#define EVERYTHING_ERROR_INVALIDINDEX 6 +#define EVERYTHING_ERROR_INVALIDCALL 7 + +#ifndef EVERYTHINGAPI +#define EVERYTHINGAPI __stdcall +#endif + +#ifndef EVERYTHINGUSERAPI +#define EVERYTHINGUSERAPI __declspec(dllimport) +#endif + +// write search state +EVERYTHINGUSERAPI VOID EVERYTHINGAPI Everything_SetSearchW(LPCWSTR lpString); +EVERYTHINGUSERAPI VOID EVERYTHINGAPI Everything_SetSearchA(LPCSTR lpString); +EVERYTHINGUSERAPI VOID EVERYTHINGAPI Everything_SetMatchPath(BOOL bEnable); +EVERYTHINGUSERAPI VOID EVERYTHINGAPI Everything_SetMatchCase(BOOL bEnable); +EVERYTHINGUSERAPI VOID EVERYTHINGAPI Everything_SetMatchWholeWord(BOOL bEnable); +EVERYTHINGUSERAPI VOID EVERYTHINGAPI Everything_SetRegex(BOOL bEnable); +EVERYTHINGUSERAPI VOID EVERYTHINGAPI Everything_SetMax(DWORD dwMax); +EVERYTHINGUSERAPI VOID EVERYTHINGAPI Everything_SetOffset(DWORD dwOffset); +EVERYTHINGUSERAPI VOID EVERYTHINGAPI Everything_SetReplyWindow(HWND hWnd); +EVERYTHINGUSERAPI VOID EVERYTHINGAPI Everything_SetReplyID(DWORD nId); + +// read search state +EVERYTHINGUSERAPI BOOL EVERYTHINGAPI Everything_GetMatchPath(VOID); +EVERYTHINGUSERAPI BOOL EVERYTHINGAPI Everything_GetMatchCase(VOID); +EVERYTHINGUSERAPI BOOL EVERYTHINGAPI Everything_GetMatchWholeWord(VOID); +EVERYTHINGUSERAPI BOOL EVERYTHINGAPI Everything_GetRegex(VOID); +EVERYTHINGUSERAPI DWORD EVERYTHINGAPI Everything_GetMax(VOID); +EVERYTHINGUSERAPI DWORD EVERYTHINGAPI Everything_GetOffset(VOID); +EVERYTHINGUSERAPI LPCSTR EVERYTHINGAPI Everything_GetSearchA(VOID); +EVERYTHINGUSERAPI LPCWSTR EVERYTHINGAPI Everything_GetSearchW(VOID); +EVERYTHINGUSERAPI DWORD EVERYTHINGAPI Everything_GetLastError(VOID); +EVERYTHINGUSERAPI HWND EVERYTHINGAPI Everything_GetReplyWindow(VOID); +EVERYTHINGUSERAPI DWORD EVERYTHINGAPI Everything_GetReplyID(VOID); + +// execute query +EVERYTHINGUSERAPI BOOL EVERYTHINGAPI Everything_QueryA(BOOL bWait); +EVERYTHINGUSERAPI BOOL EVERYTHINGAPI Everything_QueryW(BOOL bWait); + +// query reply +BOOL EVERYTHINGAPI Everything_IsQueryReply(UINT message,WPARAM wParam,LPARAM lParam,DWORD nId); + +// write result state +EVERYTHINGUSERAPI VOID EVERYTHINGAPI Everything_SortResultsByPath(VOID); + +// read result state +EVERYTHINGUSERAPI int EVERYTHINGAPI Everything_GetNumFileResults(VOID); +EVERYTHINGUSERAPI int EVERYTHINGAPI Everything_GetNumFolderResults(VOID); +EVERYTHINGUSERAPI int EVERYTHINGAPI Everything_GetNumResults(VOID); +EVERYTHINGUSERAPI int EVERYTHINGAPI Everything_GetTotFileResults(VOID); +EVERYTHINGUSERAPI int EVERYTHINGAPI Everything_GetTotFolderResults(VOID); +EVERYTHINGUSERAPI int EVERYTHINGAPI Everything_GetTotResults(VOID); +EVERYTHINGUSERAPI BOOL EVERYTHINGAPI Everything_IsVolumeResult(int nIndex); +EVERYTHINGUSERAPI BOOL EVERYTHINGAPI Everything_IsFolderResult(int nIndex); +EVERYTHINGUSERAPI BOOL EVERYTHINGAPI Everything_IsFileResult(int nIndex); +EVERYTHINGUSERAPI LPCWSTR EVERYTHINGAPI Everything_GetResultFileNameW(int nIndex); +EVERYTHINGUSERAPI LPCSTR EVERYTHINGAPI Everything_GetResultFileNameA(int nIndex); +EVERYTHINGUSERAPI LPCWSTR EVERYTHINGAPI Everything_GetResultPathW(int nIndex); +EVERYTHINGUSERAPI LPCSTR EVERYTHINGAPI Everything_GetResultPathA(int nIndex); +EVERYTHINGUSERAPI int Everything_GetResultFullPathNameW(int nIndex,LPWSTR wbuf,int wbuf_size_in_wchars); +EVERYTHINGUSERAPI int Everything_GetResultFullPathNameA(int nIndex,LPSTR buf,int bufsize); +EVERYTHINGUSERAPI VOID Everything_Reset(VOID); + +#ifdef UNICODE +#define Everything_SetSearch Everything_SetSearchW +#define Everything_GetSearch Everything_GetSearchW +#define Everything_Query Everything_QueryW +#define Everything_GetResultFileName Everything_GetResultFileNameW +#define Everything_GetResultPath Everything_GetResultPathW +#else +#define Everything_SetSearch Everything_SetSearchA +#define Everything_GetSearch Everything_GetSearchA +#define Everything_Query Everything_QueryA +#define Everything_GetResultFileName Everything_GetResultFileNameA +#define Everything_GetResultPath Everything_GetResultPathA +#endif + + +#endif + diff --git a/Plugins/Wox.Plugin.Everything/nativesrc/Everything_IPC.h b/Plugins/Wox.Plugin.Everything/nativesrc/Everything_IPC.h new file mode 100644 index 000000000..3c2af015e --- /dev/null +++ b/Plugins/Wox.Plugin.Everything/nativesrc/Everything_IPC.h @@ -0,0 +1,287 @@ + +// Everything IPC + +#ifndef _EVERYTHING_IPC_H_ +#define _EVERYTHING_IPC_H_ + +// C +#ifdef __cplusplus +extern "C" { +#endif + +// 1 byte packing for our varible sized structs +#pragma pack(push, 1) + +// WM_USER (send to the taskbar notification window) +// SendMessage(FindWindow(EVERYTHING_IPC_WNDCLASS,0),WM_USER,EVERYTHING_IPC_*,lParam) +// version format: major.minor.revision.build +// example: 1.1.4.309 +#define EVERYTHING_IPC_GET_MAJOR_VERSION 0 // int major_version = (int)SendMessage(hwnd,WM_USER,EVERYTHING_IPC_GET_MAJOR_VERSION,0); +#define EVERYTHING_IPC_GET_MINOR_VERSION 1 // int minor_version = (int)SendMessage(hwnd,WM_USER,EVERYTHING_IPC_GET_MINOR_VERSION,0); +#define EVERYTHING_IPC_GET_REVISION 2 // int revision = (int)SendMessage(hwnd,WM_USER,EVERYTHING_IPC_GET_REVISION,0); +#define EVERYTHING_IPC_GET_BUILD_NUMBER 3 // int build = (int)SendMessage(hwnd,WM_USER,EVERYTHING_IPC_GET_BUILD,0); + +// uninstall options +#define EVERYTHING_IPC_DELETE_START_MENU_SHORTCUTS 100 // SendMessage(hwnd,WM_USER,EVERYTHING_IPC_DELETE_START_MENU_SHORTCUTS,0); +#define EVERYTHING_IPC_DELETE_QUICK_LAUNCH_SHORTCUT 101 // SendMessage(hwnd,WM_USER,EVERYTHING_IPC_DELETE_QUICK_LAUNCH_SHORTCUT,0); +#define EVERYTHING_IPC_DELETE_DESKTOP_SHORTCUT 102 // SendMessage(hwnd,WM_USER,EVERYTHING_IPC_DELETE_DESKTOP_SHORTCUT,0); +#define EVERYTHING_IPC_DELETE_FOLDER_CONTEXT_MENU 103 // SendMessage(hwnd,WM_USER,EVERYTHING_IPC_DELETE_FOLDER_CONTEXT_MENU,0); +#define EVERYTHING_IPC_DELETE_RUN_ON_SYSTEM_STARTUP 104 // SendMessage(hwnd,WM_USER,EVERYTHING_IPC_DELETE_RUN_ON_SYSTEM_STARTUP,0); + +// install options +#define EVERYTHING_IPC_CREATE_START_MENU_SHORTCUTS 200 // SendMessage(hwnd,WM_USER,EVERYTHING_IPC_CREATE_START_MENU_SHORTCUTS,0); +#define EVERYTHING_IPC_CREATE_QUICK_LAUNCH_SHORTCUT 201 // SendMessage(hwnd,WM_USER,EVERYTHING_IPC_CREATE_QUICK_LAUNCH_SHORTCUT,0); +#define EVERYTHING_IPC_CREATE_DESKTOP_SHORTCUT 202 // SendMessage(hwnd,WM_USER,EVERYTHING_IPC_CREATE_DESKTOP_SHORTCUT,0); +#define EVERYTHING_IPC_CREATE_FOLDER_CONTEXT_MENU 203 // SendMessage(hwnd,WM_USER,EVERYTHING_IPC_CREATE_FOLDER_CONTEXT_MENU,0); +#define EVERYTHING_IPC_CREATE_RUN_ON_SYSTEM_STARTUP 204 // SendMessage(hwnd,WM_USER,EVERYTHING_IPC_CREATE_RUN_ON_SYSTEM_STARTUP,0); + +// get option status; 0 = no, 1 = yes, 2 = indeterminate (partially installed) +#define EVERYTHING_IPC_IS_START_MENU_SHORTCUTS 300 // int ret = (int)SendMessage(hwnd,WM_USER,EVERYTHING_IPC_IS_START_MENU_SHORTCUTS,0); +#define EVERYTHING_IPC_IS_QUICK_LAUNCH_SHORTCUT 301 // int ret = (int)SendMessage(hwnd,WM_USER,EVERYTHING_IPC_IS_QUICK_LAUNCH_SHORTCUT,0); +#define EVERYTHING_IPC_IS_DESKTOP_SHORTCUT 302 // int ret = (int)SendMessage(hwnd,WM_USER,EVERYTHING_IPC_IS_DESKTOP_SHORTCUT,0); +#define EVERYTHING_IPC_IS_FOLDER_CONTEXT_MENU 303 // int ret = (int)SendMessage(hwnd,WM_USER,EVERYTHING_IPC_IS_FOLDER_CONTEXT_MENU,0); +#define EVERYTHING_IPC_IS_RUN_ON_SYSTEM_STARTUP 304 // int ret = (int)SendMessage(hwnd,WM_USER,EVERYTHING_IPC_IS_RUN_ON_SYSTEM_STARTUP,0); + +// find the everything window +#define EVERYTHING_IPC_WNDCLASS TEXT("EVERYTHING_TASKBAR_NOTIFICATION") + +// find a everything search window +#define EVERYTHING_IPC_SEARCH_WNDCLASS TEXT("EVERYTHING") + +// this global window message is sent to all top level windows when everything starts. +#define EVERYTHING_IPC_CREATED TEXT("EVERYTHING_IPC_CREATED") + +// search flags for querys +#define EVERYTHING_IPC_MATCHCASE 0x00000001 // match case +#define EVERYTHING_IPC_MATCHWHOLEWORD 0x00000002 // match whole word +#define EVERYTHING_IPC_MATCHPATH 0x00000004 // include paths in search +#define EVERYTHING_IPC_REGEX 0x00000008 // enable regex + +// item flags +#define EVERYTHING_IPC_FOLDER 0x00000001 // The item is a folder. (its a file if not set) +#define EVERYTHING_IPC_DRIVE 0x00000002 // The folder is a drive. Path will be an empty string. + // (will also have the folder bit set) + +// the WM_COPYDATA message for a query. +#define EVERYTHING_IPC_COPYDATAQUERYA 1 +#define EVERYTHING_IPC_COPYDATAQUERYW 2 + +// all results +#define EVERYTHING_IPC_ALLRESULTS 0xFFFFFFFF // all results + +// macro to get the filename of an item +#define EVERYTHING_IPC_ITEMFILENAMEA(list,item) (CHAR *)((CHAR *)(list) + ((EVERYTHING_IPC_ITEMA *)(item))->filename_offset) +#define EVERYTHING_IPC_ITEMFILENAMEW(list,item) (WCHAR *)((CHAR *)(list) + ((EVERYTHING_IPC_ITEMW *)(item))->filename_offset) + +// macro to get the path of an item +#define EVERYTHING_IPC_ITEMPATHA(list,item) (CHAR *)((CHAR *)(list) + ((EVERYTHING_IPC_ITEMW *)(item))->path_offset) +#define EVERYTHING_IPC_ITEMPATHW(list,item) (WCHAR *)((CHAR *)(list) + ((EVERYTHING_IPC_ITEMW *)(item))->path_offset) + +// +// Varible sized query struct sent to everything. +// +// sent in the form of a WM_COPYDAYA message with EVERYTHING_IPC_COPYDATAQUERY as the +// dwData member in the COPYDATASTRUCT struct. +// set the lpData member of the COPYDATASTRUCT struct to point to your EVERYTHING_IPC_QUERY struct. +// set the cbData member of the COPYDATASTRUCT struct to the size of the +// EVERYTHING_IPC_QUERY struct minus the size of a CHAR plus the length of the search string in bytes plus +// one CHAR for the null terminator. +// +// NOTE: to determine the size of this structure use +// ASCII: sizeof(EVERYTHING_IPC_QUERYA) - sizeof(CHAR) + strlen(search_string)*sizeof(CHAR) + sizeof(CHAR) +// UNICODE: sizeof(EVERYTHING_IPC_QUERYW) - sizeof(WCHAR) + unicode_length_in_wchars(search_string)*sizeof(WCHAR) + sizeof(WCHAR) +// +// NOTE: Everything will only do one query per window. +// Sending another query when a query has not completed +// will cancel the old query and start the new one. +// +// Everything will send the results to the reply_hwnd in the form of a +// WM_COPYDAYA message with the dwData value you specify. +// +// Everything will return TRUE if successful. +// returns FALSE if not supported. +// +// If you query with EVERYTHING_IPC_COPYDATAQUERYW, the results sent from Everything will be Unicode. +// + +typedef struct EVERYTHING_IPC_QUERYW +{ + // the window that will receive the new results. + INT32 reply_hwnd; + + // the value to set the dwData member in the COPYDATASTRUCT struct + // sent by Everything when the query is complete. + INT32 reply_copydata_message; + + // search flags (see EVERYTHING_MATCHCASE | EVERYTHING_MATCHWHOLEWORD | EVERYTHING_MATCHPATH) + INT32 search_flags; + + // only return results after 'offset' results (0 to return the first result) + // useful for scrollable lists + INT32 offset; + + // the number of results to return + // zero to return no results + // EVERYTHING_IPC_ALLRESULTS to return ALL results + INT32 max_results; + + // null terminated string. arbitrary sized search_string buffer. + INT32 search_string[1]; + +}EVERYTHING_IPC_QUERYW; + +// ASCII version +typedef struct EVERYTHING_IPC_QUERYA +{ + // the window that will receive the new results. + INT32 reply_hwnd; + + // the value to set the dwData member in the COPYDATASTRUCT struct + // sent by Everything when the query is complete. + INT32 reply_copydata_message; + + // search flags (see EVERYTHING_MATCHCASE | EVERYTHING_MATCHWHOLEWORD | EVERYTHING_MATCHPATH) + INT32 search_flags; + + // only return results after 'offset' results (0 to return the first result) + // useful for scrollable lists + INT32 offset; + + // the number of results to return + // zero to return no results + // EVERYTHING_IPC_ALLRESULTS to return ALL results + INT32 max_results; + + // null terminated string. arbitrary sized search_string buffer. + INT32 search_string[1]; + +}EVERYTHING_IPC_QUERYA; + +// +// Varible sized result list struct received from Everything. +// +// Sent in the form of a WM_COPYDATA message to the hwnd specifed in the +// EVERYTHING_IPC_QUERY struct. +// the dwData member of the COPYDATASTRUCT struct will match the sent +// reply_copydata_message member in the EVERYTHING_IPC_QUERY struct. +// +// make a copy of the data before returning. +// +// return TRUE if you processed the WM_COPYDATA message. +// + +typedef struct EVERYTHING_IPC_ITEMW +{ + // item flags + DWORD flags; + + // The offset of the filename from the beginning of the list structure. + // (wchar_t *)((char *)everything_list + everythinglist->name_offset) + DWORD filename_offset; + + // The offset of the filename from the beginning of the list structure. + // (wchar_t *)((char *)everything_list + everythinglist->path_offset) + DWORD path_offset; + +}EVERYTHING_IPC_ITEMW; + +typedef struct EVERYTHING_IPC_ITEMA +{ + // item flags + DWORD flags; + + // The offset of the filename from the beginning of the list structure. + // (char *)((char *)everything_list + everythinglist->name_offset) + DWORD filename_offset; + + // The offset of the filename from the beginning of the list structure. + // (char *)((char *)everything_list + everythinglist->path_offset) + DWORD path_offset; + +}EVERYTHING_IPC_ITEMA; + +typedef struct EVERYTHING_IPC_LISTW +{ + // the total number of folders found. + DWORD totfolders; + + // the total number of files found. + DWORD totfiles; + + // totfolders + totfiles + DWORD totitems; + + // the number of folders available. + DWORD numfolders; + + // the number of files available. + DWORD numfiles; + + // the number of items available. + DWORD numitems; + + // index offset of the first result in the item list. + DWORD offset; + + // arbitrary sized item list. + // use numitems to determine the actual number of items available. + EVERYTHING_IPC_ITEMW items[1]; + +}EVERYTHING_IPC_LISTW; + +typedef struct EVERYTHING_IPC_LISTA +{ + // the total number of folders found. + DWORD totfolders; + + // the total number of files found. + DWORD totfiles; + + // totfolders + totfiles + DWORD totitems; + + // the number of folders available. + DWORD numfolders; + + // the number of files available. + DWORD numfiles; + + // the number of items available. + DWORD numitems; + + // index offset of the first result in the item list. + DWORD offset; + + // arbitrary sized item list. + // use numitems to determine the actual number of items available. + EVERYTHING_IPC_ITEMA items[1]; + +}EVERYTHING_IPC_LISTA; + +#ifdef UNICODE +#define EVERYTHING_IPC_COPYDATAQUERY EVERYTHING_IPC_COPYDATAQUERYW +#define EVERYTHING_IPC_ITEMFILENAME EVERYTHING_IPC_ITEMFILENAMEW +#define EVERYTHING_IPC_ITEMPATH EVERYTHING_IPC_ITEMPATHW +#define EVERYTHING_IPC_QUERY EVERYTHING_IPC_QUERYW +#define EVERYTHING_IPC_ITEM EVERYTHING_IPC_ITEMW +#define EVERYTHING_IPC_LIST EVERYTHING_IPC_LISTW +#else +#define EVERYTHING_IPC_COPYDATAQUERY EVERYTHING_IPC_COPYDATAQUERYA +#define EVERYTHING_IPC_ITEMFILENAME EVERYTHING_IPC_ITEMFILENAMEA +#define EVERYTHING_IPC_ITEMPATH EVERYTHING_IPC_ITEMPATHA +#define EVERYTHING_IPC_QUERY EVERYTHING_IPC_QUERYA +#define EVERYTHING_IPC_ITEM EVERYTHING_IPC_ITEMA +#define EVERYTHING_IPC_LIST EVERYTHING_IPC_LISTA +#endif + + +// restore packing +#pragma pack(pop) + +// end extern C +#ifdef __cplusplus +} +#endif + +#endif // _EVERYTHING_H_ + diff --git a/Plugins/Wox.Plugin.Everything/nativesrc/dll.sln b/Plugins/Wox.Plugin.Everything/nativesrc/dll.sln new file mode 100644 index 000000000..5f394cb79 --- /dev/null +++ b/Plugins/Wox.Plugin.Everything/nativesrc/dll.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dll", "dll.vcxproj", "{7C90030E-6EDB-445E-A61B-5540B7355C59}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7C90030E-6EDB-445E-A61B-5540B7355C59}.Debug|Win32.ActiveCfg = Debug|x64 + {7C90030E-6EDB-445E-A61B-5540B7355C59}.Debug|Win32.Build.0 = Debug|x64 + {7C90030E-6EDB-445E-A61B-5540B7355C59}.Debug|x64.ActiveCfg = Debug|x64 + {7C90030E-6EDB-445E-A61B-5540B7355C59}.Debug|x64.Build.0 = Debug|x64 + {7C90030E-6EDB-445E-A61B-5540B7355C59}.Release|Win32.ActiveCfg = Release|Win32 + {7C90030E-6EDB-445E-A61B-5540B7355C59}.Release|Win32.Build.0 = Release|Win32 + {7C90030E-6EDB-445E-A61B-5540B7355C59}.Release|x64.ActiveCfg = Release|x64 + {7C90030E-6EDB-445E-A61B-5540B7355C59}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Plugins/Wox.Plugin.Everything/nativesrc/dll.vcxproj b/Plugins/Wox.Plugin.Everything/nativesrc/dll.vcxproj new file mode 100644 index 000000000..ebc74b25e --- /dev/null +++ b/Plugins/Wox.Plugin.Everything/nativesrc/dll.vcxproj @@ -0,0 +1,291 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {7C90030E-6EDB-445E-A61B-5540B7355C59} + dll + Win32Proj + + + + DynamicLibrary + false + MultiByte + v90 + + + DynamicLibrary + MultiByte + v90 + + + DynamicLibrary + false + MultiByte + v90 + + + DynamicLibrary + MultiByte + v90 + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + Debug\ + Debug\ + true + $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + Release\ + Release\ + false + false + $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + %(AdditionalIncludeDirectories) + BZ_NO_STDIO;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + + Level3 + EditAndContinue + + + $(OutDir)Everything.dll + + + true + true + Console + 0 + true + true + false + + + MachineX86 + + + %(AdditionalManifestFiles) + + + + + X64 + + + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + + Level3 + ProgramDatabase + CompileAsC + + + ComCtl32.lib;UxTheme.lib;Ws2_32.lib;shlwapi.lib;ole32.lib;htmlhelp.lib;%(AdditionalDependencies) + $(OutDir)Everything.dll + true + $(OutDir)dll.pdb + Console + false + + + MachineX64 + + + %(AdditionalManifestFiles) + + + + + + + + + MaxSpeed + AnySuitable + true + Speed + false + false + %(AdditionalIncludeDirectories) + BZ_NO_STDIO;%(PreprocessorDefinitions) + true + Sync + Default + MultiThreaded + true + Fast + + + Level3 + + + Cdecl + CompileAsC + + + + + + + true + + + NotSet + $(OutDir)Everything.dll + %(AdditionalManifestDependencies) + false + everything.def + false + true + Windows + 0 + true + true + + + false + + + MachineX86 + + + %(AdditionalManifestFiles) + false + false + + + + + + + + + X64 + + + MaxSpeed + AnySuitable + true + Speed + false + false + %(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Default + MultiThreaded + true + Fast + + + Level3 + + + CompileAsC + + + true + + + comctl32.lib;UxTheme.lib;Ws2_32.lib;HTMLHelp.lib;msimg32.lib;%(AdditionalDependencies) + NotSet + $(OutDir)Everything.dll + %(AdditionalManifestDependencies) + false + true + Windows + true + true + + + false + + + MachineX64 + + + %(AdditionalManifestFiles) + false + false + + + + + + + + + + + + + + + + diff --git a/Plugins/Wox.Plugin.Everything/nativesrc/dll.vcxproj.filters b/Plugins/Wox.Plugin.Everything/nativesrc/dll.vcxproj.filters new file mode 100644 index 000000000..93496a8d7 --- /dev/null +++ b/Plugins/Wox.Plugin.Everything/nativesrc/dll.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {072e536f-0b4e-4b52-bbf4-45486ca2a90b} + cpp;c;cxx;def;odl;idl;hpj;bat;asm + + + + + src + + + + + src + + + + + src + + + src + + + \ No newline at end of file diff --git a/Plugins/Wox.Plugin.Everything/packages.config b/Plugins/Wox.Plugin.Everything/packages.config new file mode 100644 index 000000000..7a13476a5 --- /dev/null +++ b/Plugins/Wox.Plugin.Everything/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Plugins/Wox.Plugin.Everything/plugin.json b/Plugins/Wox.Plugin.Everything/plugin.json new file mode 100644 index 000000000..0f7418f95 --- /dev/null +++ b/Plugins/Wox.Plugin.Everything/plugin.json @@ -0,0 +1,12 @@ +{ + "ID":"D2D2C23B084D411DB66FE0C79D6C2A6E", + "ActionKeyword":"f", + "Name":"Everything", + "Description":"Search Everything", + "Author":"qianlifeng,orzfly", + "Version":"1.1.0", + "Language":"csharp", + "Website":"http://www.getwox.com", + "IcoPath":"Images\\find.png", + "ExecuteFileName":"Wox.Plugin.Everything.dll" +} diff --git a/Plugins/Wox.Plugin.Everything/x64/Everything.dll b/Plugins/Wox.Plugin.Everything/x64/Everything.dll new file mode 100644 index 000000000..2b7abd03c Binary files /dev/null and b/Plugins/Wox.Plugin.Everything/x64/Everything.dll differ diff --git a/Plugins/Wox.Plugin.Everything/x86/Everything.dll b/Plugins/Wox.Plugin.Everything/x86/Everything.dll new file mode 100644 index 000000000..c0c1fe792 Binary files /dev/null and b/Plugins/Wox.Plugin.Everything/x86/Everything.dll differ diff --git a/Plugins/Wox.Plugin.Folder/FolderPlugin.cs b/Plugins/Wox.Plugin.Folder/FolderPlugin.cs index 32b41578f..ed9127509 100644 --- a/Plugins/Wox.Plugin.Folder/FolderPlugin.cs +++ b/Plugins/Wox.Plugin.Folder/FolderPlugin.cs @@ -53,8 +53,7 @@ namespace Wox.Plugin.Folder public List Query(Query query) { - if(string.IsNullOrEmpty(query.RawQuery)) return new List(); - string input = query.RawQuery.ToLower(); + string input = query.Search.ToLower(); List userFolderLinks = FolderStorage.Instance.FolderLinks.Where( x => x.Nickname.StartsWith(input, StringComparison.OrdinalIgnoreCase)).ToList(); diff --git a/Plugins/Wox.Plugin.PluginIndicator/PluginIndicator.cs b/Plugins/Wox.Plugin.PluginIndicator/PluginIndicator.cs index 124ef2666..645401339 100644 --- a/Plugins/Wox.Plugin.PluginIndicator/PluginIndicator.cs +++ b/Plugins/Wox.Plugin.PluginIndicator/PluginIndicator.cs @@ -13,8 +13,6 @@ namespace Wox.Plugin.PluginIndicator public List Query(Query query) { List results = new List(); - if (string.IsNullOrEmpty(query.RawQuery)) return results; - if (allPlugins.Count == 0) { allPlugins = context.API.GetAllPlugins().Where(o => !PluginManager.IsSystemPlugin(o.Metadata)).ToList(); @@ -22,7 +20,7 @@ namespace Wox.Plugin.PluginIndicator foreach (PluginMetadata metadata in allPlugins.Select(o => o.Metadata)) { - if (metadata.ActionKeyword.StartsWith(query.RawQuery)) + if (metadata.ActionKeyword.StartsWith(query.Search)) { PluginMetadata metadataCopy = metadata; var customizedPluginConfig = UserSettingStorage.Instance.CustomizedPluginConfigs.FirstOrDefault(o => o.ID == metadataCopy.ID); @@ -47,18 +45,18 @@ namespace Wox.Plugin.PluginIndicator } } - results.AddRange(UserSettingStorage.Instance.WebSearches.Where(o => o.ActionWord.StartsWith(query.RawQuery) && o.Enabled).Select(n => new Result() - { - Title = n.ActionWord, - SubTitle = string.Format("Activate {0} web search", n.ActionWord), - Score = 100, - IcoPath = "Images/work.png", - Action = (c) => - { - context.API.ChangeQuery(n.ActionWord + " "); - return false; - } - })); + //results.AddRange(UserSettingStorage.Instance.WebSearches.Where(o => o.ActionWord.StartsWith(query.Search) && o.Enabled).Select(n => new Result() + //{ + // Title = n.ActionWord, + // SubTitle = string.Format("Activate {0} web search", n.ActionWord), + // Score = 100, + // IcoPath = "Images/work.png", + // Action = (c) => + // { + // context.API.ChangeQuery(n.ActionWord + " "); + // return false; + // } + //})); return results; } diff --git a/Plugins/Wox.Plugin.PluginManagement/Main.cs b/Plugins/Wox.Plugin.PluginManagement/Main.cs index a2153610d..48e47a7a6 100644 --- a/Plugins/Wox.Plugin.PluginManagement/Main.cs +++ b/Plugins/Wox.Plugin.PluginManagement/Main.cs @@ -10,59 +10,37 @@ using Newtonsoft.Json; namespace Wox.Plugin.PluginManagement { - public class WoxPluginResult - { - public string plugin_file; - public string description; - public int liked_count; - public string name; - public string version; - } - public class Main : IPlugin { private static string APIBASE = "https://api.getwox.com"; - private static string PluginPath = AppDomain.CurrentDomain.BaseDirectory + "Plugins"; private static string PluginConfigName = "plugin.json"; - private static string pluginSearchUrl = APIBASE +"/plugin/search/"; + private static string pluginSearchUrl = APIBASE + "/plugin/search/"; private PluginInitContext context; public List Query(Query query) { List results = new List(); - if (query.ActionParameters.Count == 0) + if (string.IsNullOrEmpty(query.Search)) { - results.Add(new Result("wpm install ", "Images\\plugin.png", "search and install wox plugins") + results.Add(new Result("install ", "Images\\plugin.png", "search and install wox plugins") { - Action = e => - { - context.API.ChangeQuery("wpm install "); - return false; - } + Action = e => ChangeToInstallCommand() }); - results.Add(new Result("wpm uninstall ", "Images\\plugin.png", "uninstall plugin") + results.Add(new Result("uninstall ", "Images\\plugin.png", "uninstall plugin") { - Action = e => - { - context.API.ChangeQuery("wpm uninstall "); - return false; - } + Action = e => ChangeToUninstallCommand() }); - results.Add(new Result("wpm list", "Images\\plugin.png", "list plugins installed") + results.Add(new Result("list", "Images\\plugin.png", "list plugins installed") { - Action = e => - { - context.API.ChangeQuery("wpm list"); - return false; - } + Action = e => ChangeToListCommand() }); return results; } - if (query.ActionParameters.Count > 0) + if (!string.IsNullOrEmpty(query.FirstSearch)) { bool hit = false; - switch (query.ActionParameters[0].ToLower()) + switch (query.FirstSearch.ToLower()) { case "list": hit = true; @@ -71,51 +49,39 @@ namespace Wox.Plugin.PluginManagement case "uninstall": hit = true; - results = ListUnInstalledPlugins(query); + results = UnInstallPlugins(query); break; case "install": hit = true; - if (query.ActionParameters.Count > 1) + if (!string.IsNullOrEmpty(query.SecondSearch)) { - results = InstallPlugin(query); + results = InstallPlugin(query.SecondSearch); } break; } if (!hit) { - if ("install".Contains(query.ActionParameters[0].ToLower())) + if ("install".Contains(query.FirstSearch.ToLower())) { - results.Add(new Result("wpm install ", "Images\\plugin.png", "search and install wox plugins") + results.Add(new Result("install ", "Images\\plugin.png", "search and install wox plugins") { - Action = e => - { - context.API.ChangeQuery("wpm install "); - return false; - } + Action = e => ChangeToInstallCommand() }); } - if ("uninstall".Contains(query.ActionParameters[0].ToLower())) + if ("uninstall".Contains(query.FirstSearch.ToLower())) { - results.Add(new Result("wpm uninstall ", "Images\\plugin.png", "uninstall plugin") + results.Add(new Result("uninstall ", "Images\\plugin.png", "uninstall plugin") { - Action = e => - { - context.API.ChangeQuery("wpm uninstall "); - return false; - } + Action = e => ChangeToUninstallCommand() }); } - if ("list".Contains(query.ActionParameters[0].ToLower())) + if ("list".Contains(query.FirstSearch.ToLower())) { - results.Add(new Result("wpm list", "Images\\plugin.png", "list plugins installed") + results.Add(new Result("list", "Images\\plugin.png", "list plugins installed") { - Action = e => - { - context.API.ChangeQuery("wpm list"); - return false; - } + Action = e => ChangeToListCommand() }); } } @@ -124,10 +90,49 @@ namespace Wox.Plugin.PluginManagement return results; } - private List InstallPlugin(Query query) + private bool ChangeToListCommand() + { + if (context.CurrentPluginMetadata.ActionKeyword == "*") + { + context.API.ChangeQuery("list "); + } + else + { + context.API.ChangeQuery(string.Format("{0} list ", context.CurrentPluginMetadata.ActionKeyword)); + } + return false; + } + + private bool ChangeToUninstallCommand() + { + if (context.CurrentPluginMetadata.ActionKeyword == "*") + { + context.API.ChangeQuery("uninstall "); + } + else + { + context.API.ChangeQuery(string.Format("{0} uninstall ", context.CurrentPluginMetadata.ActionKeyword)); + } + return false; + } + + private bool ChangeToInstallCommand() + { + if (context.CurrentPluginMetadata.ActionKeyword == "*") + { + context.API.ChangeQuery("install "); + } + else + { + context.API.ChangeQuery(string.Format("{0} install ", context.CurrentPluginMetadata.ActionKeyword)); + } + return false; + } + + private List InstallPlugin(string queryPluginName) { List results = new List(); - HttpWebResponse response = HttpRequest.CreateGetHttpResponse(pluginSearchUrl + query.ActionParameters[1], context.Proxy); + HttpWebResponse response = HttpRequest.CreateGetHttpResponse(pluginSearchUrl + queryPluginName, context.Proxy); Stream s = response.GetResponseStream(); if (s != null) { @@ -140,7 +145,7 @@ namespace Wox.Plugin.PluginManagement } catch { - context.API.ShowMsg("Coundn't parse api search results", "Please update your Wox!",string.Empty); + context.API.ShowMsg("Coundn't parse api search results", "Please update your Wox!", string.Empty); return results; } @@ -194,19 +199,19 @@ namespace Wox.Plugin.PluginManagement return results; } - private List ListUnInstalledPlugins(Query query) + private List UnInstallPlugins(Query query) { List results = new List(); - List allInstalledPlugins = ParseUserPlugins(); - if (query.ActionParameters.Count > 1) + List allInstalledPlugins = context.API.GetAllPlugins().Select(o => o.Metadata).ToList(); + if (!string.IsNullOrEmpty(query.SecondSearch)) { - string pluginName = query.ActionParameters[1]; allInstalledPlugins = - allInstalledPlugins.Where(o => o.Name.ToLower().Contains(pluginName.ToLower())).ToList(); + allInstalledPlugins.Where(o => o.Name.ToLower().Contains(query.SecondSearch.ToLower())).ToList(); } foreach (PluginMetadata plugin in allInstalledPlugins) { + var plugin1 = plugin; results.Add(new Result() { Title = plugin.Name, @@ -214,7 +219,7 @@ namespace Wox.Plugin.PluginManagement IcoPath = plugin.FullIcoPath, Action = e => { - UnInstalledPlugins(plugin); + UnInstallPlugin(plugin1); return false; } }); @@ -222,7 +227,7 @@ namespace Wox.Plugin.PluginManagement return results; } - private void UnInstalledPlugins(PluginMetadata plugin) + private void UnInstallPlugin(PluginMetadata plugin) { string content = string.Format("Do you want to uninstall following plugin?\r\n\r\nName: {0}\r\nVersion: {1}\r\nAuthor: {2}", plugin.Name, plugin.Version, plugin.Author); if (MessageBox.Show(content, "Wox", MessageBoxButtons.YesNo) == DialogResult.Yes) @@ -235,7 +240,7 @@ namespace Wox.Plugin.PluginManagement private List ListInstalledPlugins() { List results = new List(); - foreach (PluginMetadata plugin in ParseUserPlugins()) + foreach (PluginMetadata plugin in context.API.GetAllPlugins().Select(o => o.Metadata)) { results.Add(new Result() { @@ -247,61 +252,6 @@ namespace Wox.Plugin.PluginManagement return results; } - private static List ParseUserPlugins() - { - List pluginMetadatas = new List(); - if (!Directory.Exists(PluginPath)) - Directory.CreateDirectory(PluginPath); - - string[] directories = Directory.GetDirectories(PluginPath); - foreach (string directory in directories) - { - PluginMetadata metadata = GetMetadataFromJson(directory); - if (metadata != null) pluginMetadatas.Add(metadata); - } - - return pluginMetadatas; - } - - private static PluginMetadata GetMetadataFromJson(string pluginDirectory) - { - string configPath = Path.Combine(pluginDirectory, PluginConfigName); - PluginMetadata metadata; - - if (!File.Exists(configPath)) - { - return null; - } - - try - { - metadata = JsonConvert.DeserializeObject(File.ReadAllText(configPath)); - metadata.PluginType = PluginType.User; - metadata.PluginDirectory = pluginDirectory; - } - catch (Exception) - { - string error = string.Format("Parse plugin config {0} failed: json format is not valid", configPath); - return null; - } - - - if (!AllowedLanguage.IsAllowed(metadata.Language)) - { - string error = string.Format("Parse plugin config {0} failed: invalid language {1}", configPath, - metadata.Language); - return null; - } - if (!File.Exists(metadata.ExecuteFilePath)) - { - string error = string.Format("Parse plugin config {0} failed: ExecuteFile {1} didn't exist", configPath, - metadata.ExecuteFilePath); - return null; - } - - return metadata; - } - public void Init(PluginInitContext context) { this.context = context; diff --git a/Plugins/Wox.Plugin.PluginManagement/Wox.Plugin.PluginManagement.csproj b/Plugins/Wox.Plugin.PluginManagement/Wox.Plugin.PluginManagement.csproj index b7e35ad14..d19ddc345 100644 --- a/Plugins/Wox.Plugin.PluginManagement/Wox.Plugin.PluginManagement.csproj +++ b/Plugins/Wox.Plugin.PluginManagement/Wox.Plugin.PluginManagement.csproj @@ -51,6 +51,7 @@ + diff --git a/Plugins/Wox.Plugin.PluginManagement/WoxPluginResult.cs b/Plugins/Wox.Plugin.PluginManagement/WoxPluginResult.cs new file mode 100644 index 000000000..a7fcd513e --- /dev/null +++ b/Plugins/Wox.Plugin.PluginManagement/WoxPluginResult.cs @@ -0,0 +1,11 @@ +namespace Wox.Plugin.PluginManagement +{ + public class WoxPluginResult + { + public string plugin_file; + public string description; + public int liked_count; + public string name; + public string version; + } +} \ No newline at end of file diff --git a/Plugins/Wox.Plugin.Program/Programs.cs b/Plugins/Wox.Plugin.Program/Programs.cs index 9c4d2d423..7028848b8 100644 --- a/Plugins/Wox.Plugin.Program/Programs.cs +++ b/Plugins/Wox.Plugin.Program/Programs.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Windows; using Wox.Infrastructure; using Wox.Plugin.Program.ProgramSources; +using IWshRuntimeLibrary; namespace Wox.Plugin.Program { @@ -26,9 +27,7 @@ namespace Wox.Plugin.Program public List Query(Query query) { - if (query.RawQuery.Trim().Length <= 1) return new List(); - - var fuzzyMather = FuzzyMatcher.Create(query.RawQuery); + var fuzzyMather = FuzzyMatcher.Create(query.Search); List returnList = programs.Where(o => MatchProgram(o, fuzzyMather)).ToList(); returnList.ForEach(ScoreFilter); returnList = returnList.OrderByDescending(o => o.Score).ToList(); @@ -57,11 +56,40 @@ namespace Wox.Plugin.Program return true; }, IcoPath = "Images/cmd.png" + }, + new Result() + { + Title = "Open Containing Folder", + Action = _ => + { + context.API.HideApp(); + String Path=c.ExecutePath; + //check if shortcut + if (Path.EndsWith(".lnk")) + { + //get location of shortcut + Path = ResolveShortcut(Path); + } + //get parent folder + Path=System.IO.Directory.GetParent(Path).FullName; + //open the folder + context.API.ShellRun("explorer.exe "+Path,false); + return true; + }, + IcoPath = "Images/folder.png" } } }).ToList(); } + static string ResolveShortcut(string filePath) + { + // IWshRuntimeLibrary is in the COM library "Windows Script Host Object Model" + IWshRuntimeLibrary.WshShell shell = new IWshRuntimeLibrary.WshShell(); + IWshRuntimeLibrary.IWshShortcut shortcut = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(filePath); + return shortcut.TargetPath; + } + private bool MatchProgram(Program program, FuzzyMatcher matcher) { if ((program.Score = matcher.Evaluate(program.Title).Score) > 0) return true; diff --git a/Plugins/Wox.Plugin.Program/Wox.Plugin.Program.csproj b/Plugins/Wox.Plugin.Program/Wox.Plugin.Program.csproj index 324b0fb10..a517e1407 100644 --- a/Plugins/Wox.Plugin.Program/Wox.Plugin.Program.csproj +++ b/Plugins/Wox.Plugin.Program/Wox.Plugin.Program.csproj @@ -121,7 +121,17 @@ Wox.Plugin - + + + {F935DC20-1CF0-11D0-ADB9-00C04FD58A0B} + 1 + 0 + 0 + tlbimp + False + True + + diff --git a/Plugins/Wox.Plugin.QueryHistory/QueryHistory.cs b/Plugins/Wox.Plugin.QueryHistory/QueryHistory.cs index 6a77964e1..7f74a9e0b 100644 --- a/Plugins/Wox.Plugin.QueryHistory/QueryHistory.cs +++ b/Plugins/Wox.Plugin.QueryHistory/QueryHistory.cs @@ -13,7 +13,7 @@ namespace Wox.Plugin.QueryHistory public List Query(Query query) { var histories = QueryHistoryStorage.Instance.GetHistory(); - string filter = query.GetAllRemainingParameter(); + string filter = query.Search; if (!string.IsNullOrEmpty(filter)) { histories = histories.Where(o => o.Query.Contains(filter)).ToList(); diff --git a/Plugins/Wox.Plugin.QueryHistory/Wox.Plugin.QueryHistory.csproj b/Plugins/Wox.Plugin.QueryHistory/Wox.Plugin.QueryHistory.csproj index 9ae22def6..2a1c20e7e 100644 --- a/Plugins/Wox.Plugin.QueryHistory/Wox.Plugin.QueryHistory.csproj +++ b/Plugins/Wox.Plugin.QueryHistory/Wox.Plugin.QueryHistory.csproj @@ -26,7 +26,7 @@ pdbonly true - ..\..\Output\Release\Plugins\Wox.Plugin.Program\ + ..\..\Output\Release\Plugins\Wox.Plugin.QueryHistory\ TRACE prompt 4 diff --git a/Plugins/Wox.Plugin.Sys/Sys.cs b/Plugins/Wox.Plugin.Sys/Sys.cs index 2351f5573..80132b29e 100644 --- a/Plugins/Wox.Plugin.Sys/Sys.cs +++ b/Plugins/Wox.Plugin.Sys/Sys.cs @@ -34,7 +34,6 @@ namespace Wox.Plugin.Sys public List Query(Query query) { - if (query.RawQuery.EndsWith(" ") || query.RawQuery.Length <= 1) return new List(); if (availableResults.Count == 0) { LoadCommands(); @@ -43,7 +42,7 @@ namespace Wox.Plugin.Sys List results = new List(); foreach (Result availableResult in availableResults) { - if (availableResult.Title.ToLower().StartsWith(query.RawQuery.ToLower())) + if (availableResult.Title.ToLower().StartsWith(query.Search.ToLower())) { results.Add(availableResult); } diff --git a/Plugins/Wox.Plugin.Url/UrlPlugin.cs b/Plugins/Wox.Plugin.Url/UrlPlugin.cs index e578e7c25..b769a720b 100644 --- a/Plugins/Wox.Plugin.Url/UrlPlugin.cs +++ b/Plugins/Wox.Plugin.Url/UrlPlugin.cs @@ -45,9 +45,7 @@ namespace Wox.Plugin.Url public List Query(Query query) { - if(string.IsNullOrEmpty(query.RawQuery)) return new List(); - - var raw = query.RawQuery; + var raw = query.Search; if (IsURL(raw)) { return new List diff --git a/Wox.Core/UserSettings/WebSearch.cs b/Plugins/Wox.Plugin.WebSearch/WebSearch.cs similarity index 90% rename from Wox.Core/UserSettings/WebSearch.cs rename to Plugins/Wox.Plugin.WebSearch/WebSearch.cs index aa28a2ff8..b05870cb0 100644 --- a/Wox.Core/UserSettings/WebSearch.cs +++ b/Plugins/Wox.Plugin.WebSearch/WebSearch.cs @@ -1,6 +1,6 @@ using System; -namespace Wox.Core.UserSettings +namespace Wox.Plugin.WebSearch { [Serializable] public class WebSearch diff --git a/Plugins/Wox.Plugin.WebSearch/WebSearchPlugin.cs b/Plugins/Wox.Plugin.WebSearch/WebSearchPlugin.cs index 11989fb32..8a2a43011 100644 --- a/Plugins/Wox.Plugin.WebSearch/WebSearchPlugin.cs +++ b/Plugins/Wox.Plugin.WebSearch/WebSearchPlugin.cs @@ -9,7 +9,7 @@ using Wox.Plugin.WebSearch.SuggestionSources; namespace Wox.Plugin.WebSearch { - public class WebSearchPlugin : IPlugin, ISettingProvider,IPluginI18n + public class WebSearchPlugin : IPlugin, ISettingProvider, IPluginI18n, IInstantSearch { private PluginInitContext context; @@ -17,12 +17,12 @@ namespace Wox.Plugin.WebSearch { List results = new List(); - Core.UserSettings.WebSearch webSearch = - UserSettingStorage.Instance.WebSearches.FirstOrDefault(o => o.ActionWord == query.ActionName && o.Enabled); + WebSearch webSearch = + WebSearchStorage.Instance.WebSearches.FirstOrDefault(o => o.ActionWord == query.FirstSearch.Trim() && o.Enabled); if (webSearch != null) { - string keyword = query.ActionParameters.Count > 0 ? query.GetAllRemainingParameter() : ""; + string keyword = query.SecondToEndSearch; string title = keyword; string subtitle = "Search " + webSearch.Title; if (string.IsNullOrEmpty(keyword)) @@ -44,12 +44,12 @@ namespace Wox.Plugin.WebSearch return true; } } - },true); + }); - if (UserSettingStorage.Instance.EnableWebSearchSuggestion && !string.IsNullOrEmpty(keyword)) + if (WebSearchStorage.Instance.EnableWebSearchSuggestion && !string.IsNullOrEmpty(keyword)) { ISuggestionSource sugg = SuggestionSourceFactory.GetSuggestionSource( - UserSettingStorage.Instance.WebSearchSuggestionSource); + WebSearchStorage.Instance.WebSearchSuggestionSource); if (sugg != null) { var result = sugg.GetSuggestions(keyword); @@ -80,8 +80,8 @@ namespace Wox.Plugin.WebSearch { this.context = context; - if (UserSettingStorage.Instance.WebSearches == null) - UserSettingStorage.Instance.WebSearches = UserSettingStorage.Instance.LoadDefaultWebSearches(); + if (WebSearchStorage.Instance.WebSearches == null) + WebSearchStorage.Instance.WebSearches = WebSearchStorage.Instance.LoadDefaultWebSearches(); } #region ISettingProvider Members @@ -97,5 +97,16 @@ namespace Wox.Plugin.WebSearch { return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Languages"); } + + public bool IsInstantSearch(string query) + { + var strings = query.Split(' '); + if (strings.Length > 1) + { + return WebSearchStorage.Instance.EnableWebSearchSuggestion && + WebSearchStorage.Instance.WebSearches.Exists(o => o.ActionWord == strings[0] && o.Enabled); + } + return false; + } } } diff --git a/Plugins/Wox.Plugin.WebSearch/WebSearchSetting.xaml.cs b/Plugins/Wox.Plugin.WebSearch/WebSearchSetting.xaml.cs index c7e5138d0..f7f09bcf5 100644 --- a/Plugins/Wox.Plugin.WebSearch/WebSearchSetting.xaml.cs +++ b/Plugins/Wox.Plugin.WebSearch/WebSearchSetting.xaml.cs @@ -14,7 +14,7 @@ namespace Wox.Plugin.WebSearch private string defaultWebSearchImageDirectory = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Images\\websearch"); private WebSearchesSetting settingWindow; private bool update; - private Core.UserSettings.WebSearch updateWebSearch; + private WebSearch updateWebSearch; private PluginInitContext context; public WebSearchSetting(WebSearchesSetting settingWidow,PluginInitContext context) @@ -24,9 +24,9 @@ namespace Wox.Plugin.WebSearch InitializeComponent(); } - public void UpdateItem(Core.UserSettings.WebSearch webSearch) + public void UpdateItem(WebSearch webSearch) { - updateWebSearch = UserSettingStorage.Instance.WebSearches.FirstOrDefault(o => o == webSearch); + updateWebSearch = WebSearchStorage.Instance.WebSearches.FirstOrDefault(o => o == webSearch); if (updateWebSearch == null || string.IsNullOrEmpty(updateWebSearch.Url)) { @@ -91,13 +91,13 @@ namespace Wox.Plugin.WebSearch if (!update) { - if (UserSettingStorage.Instance.WebSearches.Exists(o => o.ActionWord == action)) + if (WebSearchStorage.Instance.WebSearches.Exists(o => o.ActionWord == action)) { string warning = context.API.GetTranslation("wox_plugin_websearch_action_keyword_exist"); MessageBox.Show(warning); return; } - UserSettingStorage.Instance.WebSearches.Add(new Core.UserSettings.WebSearch() + WebSearchStorage.Instance.WebSearches.Add(new WebSearch() { ActionWord = action, Enabled = cbEnable.IsChecked ?? false, @@ -110,7 +110,7 @@ namespace Wox.Plugin.WebSearch } else { - if (UserSettingStorage.Instance.WebSearches.Exists(o => o.ActionWord == action && o != updateWebSearch)) + if (WebSearchStorage.Instance.WebSearches.Exists(o => o.ActionWord == action && o != updateWebSearch)) { string warning = context.API.GetTranslation("wox_plugin_websearch_action_keyword_exist"); MessageBox.Show(warning); diff --git a/Plugins/Wox.Plugin.WebSearch/WebSearchStorage.cs b/Plugins/Wox.Plugin.WebSearch/WebSearchStorage.cs new file mode 100644 index 000000000..bcf5ec616 --- /dev/null +++ b/Plugins/Wox.Plugin.WebSearch/WebSearchStorage.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using Newtonsoft.Json; +using Wox.Core.UserSettings; +using Wox.Infrastructure.Storage; + +namespace Wox.Plugin.WebSearch +{ + public class WebSearchStorage :JsonStrorage + { + [JsonProperty] + public List WebSearches { get; set; } + + [JsonProperty] + public bool EnableWebSearchSuggestion { get; set; } + + [JsonProperty] + public string WebSearchSuggestionSource { get; set; } + + protected override string ConfigFolder + { + get { return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); } + } + + protected override string ConfigName + { + get { return "setting"; } + } + + protected override WebSearchStorage LoadDefault() + { + WebSearches = LoadDefaultWebSearches(); + return this; + } + + public List LoadDefaultWebSearches() + { + List webSearches = new List(); + + WebSearch googleWebSearch = new WebSearch() + { + Title = "Google", + ActionWord = "g", + IconPath = @"Images\websearch\google.png", + Url = "https://www.google.com/search?q={q}", + Enabled = true + }; + webSearches.Add(googleWebSearch); + + + WebSearch wikiWebSearch = new WebSearch() + { + Title = "Wikipedia", + ActionWord = "wiki", + IconPath = @"Images\websearch\wiki.png", + Url = "http://en.wikipedia.org/wiki/{q}", + Enabled = true + }; + webSearches.Add(wikiWebSearch); + + WebSearch findIcon = new WebSearch() + { + Title = "FindIcon", + ActionWord = "findicon", + IconPath = @"Images\websearch\pictures.png", + Url = "http://findicons.com/search/{q}", + Enabled = true + }; + webSearches.Add(findIcon); + + return webSearches; + } + } +} diff --git a/Plugins/Wox.Plugin.WebSearch/WebSearchesSetting.xaml.cs b/Plugins/Wox.Plugin.WebSearch/WebSearchesSetting.xaml.cs index 474ada758..1883ce831 100644 --- a/Plugins/Wox.Plugin.WebSearch/WebSearchesSetting.xaml.cs +++ b/Plugins/Wox.Plugin.WebSearch/WebSearchesSetting.xaml.cs @@ -24,9 +24,9 @@ namespace Wox.Plugin.WebSearch private void Setting_Loaded(object sender, RoutedEventArgs e) { - webSearchView.ItemsSource = UserSettingStorage.Instance.WebSearches; - cbEnableWebSearchSuggestion.IsChecked = UserSettingStorage.Instance.EnableWebSearchSuggestion; - comboBoxSuggestionSource.Visibility = UserSettingStorage.Instance.EnableWebSearchSuggestion + webSearchView.ItemsSource = WebSearchStorage.Instance.WebSearches; + cbEnableWebSearchSuggestion.IsChecked = WebSearchStorage.Instance.EnableWebSearchSuggestion; + comboBoxSuggestionSource.Visibility = WebSearchStorage.Instance.EnableWebSearchSuggestion ? Visibility.Visible : Visibility.Collapsed; @@ -35,7 +35,7 @@ namespace Wox.Plugin.WebSearch new ComboBoxItem() {Content = "Google"}, new ComboBoxItem() {Content = "Baidu"}, }; - ComboBoxItem selected = items.FirstOrDefault(o => o.Content.ToString() == UserSettingStorage.Instance.WebSearchSuggestionSource); + ComboBoxItem selected = items.FirstOrDefault(o => o.Content.ToString() == WebSearchStorage.Instance.WebSearchSuggestionSource); if (selected == null) { selected = items[0]; @@ -58,14 +58,14 @@ namespace Wox.Plugin.WebSearch private void btnDeleteWebSearch_OnClick(object sender, RoutedEventArgs e) { - Core.UserSettings.WebSearch selectedWebSearch = webSearchView.SelectedItem as Core.UserSettings.WebSearch; + WebSearch selectedWebSearch = webSearchView.SelectedItem as WebSearch; if (selectedWebSearch != null) { string msg = string.Format(context.API.GetTranslation("wox_plugin_websearch_delete_warning"),selectedWebSearch.Title); if (MessageBox.Show(msg,string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes) { - UserSettingStorage.Instance.WebSearches.Remove(selectedWebSearch); + WebSearchStorage.Instance.WebSearches.Remove(selectedWebSearch); webSearchView.Items.Refresh(); } } @@ -78,7 +78,7 @@ namespace Wox.Plugin.WebSearch private void btnEditWebSearch_OnClick(object sender, RoutedEventArgs e) { - Core.UserSettings.WebSearch selectedWebSearch = webSearchView.SelectedItem as Core.UserSettings.WebSearch; + WebSearch selectedWebSearch = webSearchView.SelectedItem as WebSearch; if (selectedWebSearch != null) { WebSearchSetting webSearch = new WebSearchSetting(this,context); @@ -95,23 +95,22 @@ namespace Wox.Plugin.WebSearch private void CbEnableWebSearchSuggestion_OnChecked(object sender, RoutedEventArgs e) { comboBoxSuggestionSource.Visibility = Visibility.Visible; - UserSettingStorage.Instance.EnableWebSearchSuggestion = true; - UserSettingStorage.Instance.Save(); + WebSearchStorage.Instance.EnableWebSearchSuggestion = true; + WebSearchStorage.Instance.Save(); } private void CbEnableWebSearchSuggestion_OnUnchecked(object sender, RoutedEventArgs e) { comboBoxSuggestionSource.Visibility = Visibility.Collapsed; - UserSettingStorage.Instance.EnableWebSearchSuggestion = false; - UserSettingStorage.Instance.Save(); + WebSearchStorage.Instance.EnableWebSearchSuggestion = false; + WebSearchStorage.Instance.Save(); } private void ComboBoxSuggestionSource_OnSelectionChanged(object sender, SelectionChangedEventArgs e) { if (e.AddedItems.Count > 0) { - UserSettingStorage.Instance.WebSearchSuggestionSource = - ((ComboBoxItem) e.AddedItems[0]).Content.ToString(); + WebSearchStorage.Instance.WebSearchSuggestionSource = ((ComboBoxItem) e.AddedItems[0]).Content.ToString(); UserSettingStorage.Instance.Save(); } } diff --git a/Plugins/Wox.Plugin.WebSearch/Wox.Plugin.WebSearch.csproj b/Plugins/Wox.Plugin.WebSearch/Wox.Plugin.WebSearch.csproj index ef331ba74..8c84b7b91 100644 --- a/Plugins/Wox.Plugin.WebSearch/Wox.Plugin.WebSearch.csproj +++ b/Plugins/Wox.Plugin.WebSearch/Wox.Plugin.WebSearch.csproj @@ -56,6 +56,7 @@ + WebSearchesSetting.xaml @@ -63,6 +64,7 @@ WebSearchSetting.xaml + diff --git a/Wox.Core/Plugin/PluginManager.cs b/Wox.Core/Plugin/PluginManager.cs index dcb455c70..c9d15ec0b 100644 --- a/Wox.Core/Plugin/PluginManager.cs +++ b/Wox.Core/Plugin/PluginManager.cs @@ -19,6 +19,11 @@ namespace Wox.Core.Plugin /// public static class PluginManager { + public const string ActionKeywordWildcardSign = "*"; + private static List pluginMetadatas; + private static List instantSearches = new List(); + + public static String DebuggerMode { get; private set; } public static IPublicAPI API { get; private set; } @@ -29,7 +34,6 @@ namespace Wox.Core.Plugin /// private static List pluginDirectories = new List(); - private static void SetupPluginDirectories() { pluginDirectories.Add(PluginDirectory); @@ -70,7 +74,7 @@ namespace Wox.Core.Plugin API = api; plugins.Clear(); - List pluginMetadatas = PluginConfig.Parse(pluginDirectories); + pluginMetadatas = PluginConfig.Parse(pluginDirectories); plugins.AddRange(new CSharpPluginLoader().LoadPlugin(pluginMetadatas)); plugins.AddRange(new JsonRPCPluginLoader().LoadPlugin(pluginMetadatas)); @@ -93,6 +97,8 @@ namespace Wox.Core.Plugin } }); } + + LoadInstantSearches(); } public static void InstallPlugin(string path) @@ -102,27 +108,35 @@ namespace Wox.Core.Plugin public static void Query(Query query) { - QueryDispatcher.QueryDispatcher.Dispatch(query); + if (!string.IsNullOrEmpty(query.RawQuery.Trim())) + { + QueryDispatcher.QueryDispatcher.Dispatch(query); + } } public static List AllPlugins { get { - return plugins; + return plugins.OrderBy(o => o.Metadata.Name).ToList(); } } public static bool IsUserPluginQuery(Query query) { - if (string.IsNullOrEmpty(query.ActionName)) return false; + if (string.IsNullOrEmpty(query.RawQuery)) return false; + var strings = query.RawQuery.Split(' '); + if(strings.Length == 1) return false; - return plugins.Any(o => o.Metadata.PluginType == PluginType.User && o.Metadata.ActionKeyword == query.ActionName); + var actionKeyword = strings[0].Trim(); + if (string.IsNullOrEmpty(actionKeyword)) return false; + + return plugins.Any(o => o.Metadata.PluginType == PluginType.User && o.Metadata.ActionKeyword == actionKeyword); } public static bool IsSystemPlugin(PluginMetadata metadata) { - return metadata.ActionKeyword == "*"; + return metadata.ActionKeyword == ActionKeywordWildcardSign; } public static void ActivatePluginDebugger(string path) @@ -130,6 +144,46 @@ namespace Wox.Core.Plugin DebuggerMode = path; } + public static bool IsInstantSearch(string query) + { + return LoadInstantSearches().Any(o => o.IsInstantSearch(query)); + } + + private static List LoadInstantSearches() + { + if (instantSearches.Count > 0) return instantSearches; + List CSharpPluginMetadatas = pluginMetadatas.Where(o => o.Language.ToUpper() == AllowedLanguage.CSharp.ToUpper()).ToList(); + + foreach (PluginMetadata metadata in CSharpPluginMetadatas) + { + try + { + Assembly asm = Assembly.Load(AssemblyName.GetAssemblyName(metadata.ExecuteFilePath)); + List types = asm.GetTypes().Where(o => o.IsClass && !o.IsAbstract && o.GetInterfaces().Contains(typeof(IInstantSearch))).ToList(); + if (types.Count == 0) + { + continue; + } + + foreach (Type type in types) + { + instantSearches.Add(Activator.CreateInstance(type) as IInstantSearch); + } + } + catch (System.Exception e) + { + Log.Error(string.Format("Couldn't load plugin {0}: {1}", metadata.Name, e.Message)); +#if (DEBUG) + { + throw; + } +#endif + } + } + + return instantSearches; + } + /// /// get specified plugin, return null if not found /// diff --git a/Wox.Core/Plugin/QueryDispatcher/QueryDispatcher.cs b/Wox.Core/Plugin/QueryDispatcher/QueryDispatcher.cs index 0e0eb62fb..e5f5b76bf 100644 --- a/Wox.Core/Plugin/QueryDispatcher/QueryDispatcher.cs +++ b/Wox.Core/Plugin/QueryDispatcher/QueryDispatcher.cs @@ -3,18 +3,20 @@ namespace Wox.Core.Plugin.QueryDispatcher { internal static class QueryDispatcher { - private static IQueryDispatcher pluginCmd = new UserPluginQueryDispatcher(); - private static IQueryDispatcher systemCmd = new SystemPluginQueryDispatcher(); + private static readonly IQueryDispatcher UserPluginDispatcher = new UserPluginQueryDispatcher(); + private static readonly IQueryDispatcher SystemPluginDispatcher = new SystemPluginQueryDispatcher(); public static void Dispatch(Wox.Plugin.Query query) { if (PluginManager.IsUserPluginQuery(query)) { - pluginCmd.Dispatch(query); + query.Search = query.RawQuery.Substring(query.RawQuery.IndexOf(' ') + 1); + UserPluginDispatcher.Dispatch(query); } else { - systemCmd.Dispatch(query); + query.Search = query.RawQuery; + SystemPluginDispatcher.Dispatch(query); } } } diff --git a/Wox.Core/Plugin/QueryDispatcher/SystemPluginQueryDispatcher.cs b/Wox.Core/Plugin/QueryDispatcher/SystemPluginQueryDispatcher.cs index e8ef1ee4f..5cda7d3e3 100644 --- a/Wox.Core/Plugin/QueryDispatcher/SystemPluginQueryDispatcher.cs +++ b/Wox.Core/Plugin/QueryDispatcher/SystemPluginQueryDispatcher.cs @@ -5,7 +5,6 @@ using Wox.Core.Exception; using Wox.Core.UserSettings; using Wox.Infrastructure.Logger; using Wox.Plugin; -//using Wox.Plugin.SystemPlugins; namespace Wox.Core.Plugin.QueryDispatcher { @@ -24,7 +23,10 @@ namespace Wox.Core.Plugin.QueryDispatcher try { List results = pair1.Plugin.Query(query); - results.ForEach(o => { o.AutoAjustScore = true; }); + results.ForEach(o => + { + o.PluginID = pair1.Metadata.ID; + }); PluginManager.API.PushResults(query, pair1.Metadata, results); } diff --git a/Wox.Core/Plugin/QueryDispatcher/UserPluginQueryDispatcher.cs b/Wox.Core/Plugin/QueryDispatcher/UserPluginQueryDispatcher.cs index 9b4217963..c50344296 100644 --- a/Wox.Core/Plugin/QueryDispatcher/UserPluginQueryDispatcher.cs +++ b/Wox.Core/Plugin/QueryDispatcher/UserPluginQueryDispatcher.cs @@ -13,7 +13,7 @@ namespace Wox.Core.Plugin.QueryDispatcher { public void Dispatch(Query query) { - PluginPair userPlugin = PluginManager.AllPlugins.FirstOrDefault(o => o.Metadata.ActionKeyword == query.ActionName); + PluginPair userPlugin = PluginManager.AllPlugins.FirstOrDefault(o => o.Metadata.ActionKeyword == query.GetActionKeyword()); if (userPlugin != null && !string.IsNullOrEmpty(userPlugin.Metadata.ActionKeyword)) { var customizedPluginConfig = UserSettingStorage.Instance.CustomizedPluginConfigs.FirstOrDefault(o => o.ID == userPlugin.Metadata.ID); @@ -29,7 +29,11 @@ namespace Wox.Core.Plugin.QueryDispatcher try { List results = userPlugin.Plugin.Query(query) ?? new List(); - PluginManager.API.PushResults(query,userPlugin.Metadata,results); + results.ForEach(o => + { + o.PluginID = userPlugin.Metadata.ID; + }); + PluginManager.API.PushResults(query, userPlugin.Metadata, results); } catch (System.Exception e) { diff --git a/Wox.Core/README.md b/Wox.Core/README.md index 337b0a463..b2e9b83de 100644 --- a/Wox.Core/README.md +++ b/Wox.Core/README.md @@ -2,6 +2,8 @@ ===== * Handle Query +* Define Wox exceptions * Manage Plugins (including system plugin and user plugin) * Manage Themes -* Manage i18n \ No newline at end of file +* Manage i18n +* Manage Update and version \ No newline at end of file diff --git a/Wox.Core/Theme/Theme.cs b/Wox.Core/Theme/Theme.cs index 78bea898d..b20e95cdd 100644 --- a/Wox.Core/Theme/Theme.cs +++ b/Wox.Core/Theme/Theme.cs @@ -102,7 +102,7 @@ namespace Wox.Core.Theme .Where(filePath => filePath.EndsWith(".xaml") && !filePath.EndsWith("Base.xaml")) .ToList()); } - return themes; + return themes.OrderBy(o => o).ToList(); } private string GetThemePath(string themeName) diff --git a/Wox.Core/UI/ResourceMerger.cs b/Wox.Core/UI/ResourceMerger.cs index b2167a3cd..6d7a89298 100644 --- a/Wox.Core/UI/ResourceMerger.cs +++ b/Wox.Core/UI/ResourceMerger.cs @@ -39,7 +39,7 @@ namespace Wox.Core.UI foreach (var pluginI18n in pluginI18ns) { - string languageFile = InternationalizationManager.Internationalization.GetLanguageFile( + string languageFile = InternationalizationManager.Instance.GetLanguageFile( ((IPluginI18n)Activator.CreateInstance(pluginI18n)).GetLanguagesFolder()); if (!string.IsNullOrEmpty(languageFile)) { diff --git a/Wox/Update/Release.cs b/Wox.Core/Updater/Release.cs similarity index 70% rename from Wox/Update/Release.cs rename to Wox.Core/Updater/Release.cs index 3664f5f2f..4808ffefb 100644 --- a/Wox/Update/Release.cs +++ b/Wox.Core/Updater/Release.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Wox.Update +namespace Wox.Core.Updater { public class Release { @@ -12,5 +7,10 @@ namespace Wox.Update public string download_link1 { get; set; } public string download_link2 { get; set; } public string description { get; set; } + + public override string ToString() + { + return version; + } } -} +} \ No newline at end of file diff --git a/Wox.Core/Version/SemanticVersion.cs b/Wox.Core/Updater/SemanticVersion.cs similarity index 95% rename from Wox.Core/Version/SemanticVersion.cs rename to Wox.Core/Updater/SemanticVersion.cs index 9ba46238c..693ce73ee 100644 --- a/Wox.Core/Version/SemanticVersion.cs +++ b/Wox.Core/Updater/SemanticVersion.cs @@ -1,11 +1,7 @@ using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; using Wox.Core.Exception; -namespace Wox.Core.Version +namespace Wox.Core.Updater { public class SemanticVersion : IComparable { diff --git a/Wox.Core/Updater/UpdaterManager.cs b/Wox.Core/Updater/UpdaterManager.cs index 7f0717160..258d3c0b6 100644 --- a/Wox.Core/Updater/UpdaterManager.cs +++ b/Wox.Core/Updater/UpdaterManager.cs @@ -1,11 +1,19 @@ - -using System; +using System; +using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Net; +using System.Reflection; using System.Windows.Forms; using System.Windows.Threading; using NAppUpdate.Framework; using NAppUpdate.Framework.Common; using NAppUpdate.Framework.Sources; +using NAppUpdate.Framework.Tasks; +using Newtonsoft.Json; +using Wox.Core.i18n; +using Wox.Core.UserSettings; +using Wox.Infrastructure.Http; using Wox.Infrastructure.Logger; namespace Wox.Core.Updater @@ -13,6 +21,15 @@ namespace Wox.Core.Updater public class UpdaterManager { private static UpdaterManager instance; + private const string VersionCheckURL = "https://api.getwox.com/release/latest/"; + //private const string UpdateFeedURL = "http://upgrade.getwox.com/update.xml"; + private const string UpdateFeedURL = "http://127.0.0.1:8888/update.xml"; + private static SemanticVersion currentVersion; + + public event EventHandler PrepareUpdateReady; + public event EventHandler UpdateError; + + public Release NewRelease { get; set; } public static UpdaterManager Instance { @@ -31,11 +48,61 @@ namespace Wox.Core.Updater UpdateManager.Instance.UpdateSource = GetUpdateSource(); } + public SemanticVersion CurrentVersion + { + get + { + if (currentVersion == null) + { + currentVersion = new SemanticVersion(Assembly.GetExecutingAssembly().GetName().Version); + } + return currentVersion; + } + } + + private bool IsNewerThanCurrent(Release release) + { + if (release == null) return false; + + return new SemanticVersion(release.version) > CurrentVersion; + } + + public List GetAvailableUpdateFiles() + { + List files = new List(); + foreach (var task in UpdateManager.Instance.Tasks) + { + if (task is FileUpdateTask) + { + files.Add(((FileUpdateTask)task).LocalPath); + } + } + return files; + } + public void CheckUpdate() { - // Get a local pointer to the UpdateManager instance - UpdateManager updManager = UpdateManager.Instance; + string json = HttpRequest.Get(VersionCheckURL, HttpProxy.Instance); + if (!string.IsNullOrEmpty(json)) + { + try + { + NewRelease = JsonConvert.DeserializeObject(json); + if (IsNewerThanCurrent(NewRelease) && !UserSettingStorage.Instance.DontPromptUpdateMsg) + { + StartUpdate(); + } + } + catch (System.Exception e) + { + Log.Error(e); + } + } + } + private void StartUpdate() + { + UpdateManager updManager = UpdateManager.Instance; updManager.BeginCheckForUpdates(asyncResult => { if (asyncResult.IsCompleted) @@ -43,9 +110,9 @@ namespace Wox.Core.Updater // still need to check for caught exceptions if any and rethrow try { - ((UpdateProcessAsyncResult) asyncResult).EndInvoke(); + ((UpdateProcessAsyncResult)asyncResult).EndInvoke(); } - catch(System.Exception e) + catch (System.Exception e) { Log.Error(e); updManager.CleanUp(); @@ -55,7 +122,6 @@ namespace Wox.Core.Updater // No updates were found, or an error has occured. We might want to check that... if (updManager.UpdatesAvailable == 0) { - MessageBox.Show("All is up to date!"); return; } } @@ -63,54 +129,52 @@ namespace Wox.Core.Updater updManager.BeginPrepareUpdates(result => { ((UpdateProcessAsyncResult)result).EndInvoke(); - - // ApplyUpdates is a synchronous method by design. Make sure to save all user work before calling - // it as it might restart your application - // get out of the way so the console window isn't obstructed - try - { - updManager.ApplyUpdates(true,false,true); - } - catch - { - // this.WindowState = WindowState.Normal; - MessageBox.Show( - "An error occurred while trying to install software updates"); - } - - updManager.CleanUp(); + OnPrepareUpdateReady(); }, null); }, null); } - public void Reinstall() + public void CleanUp() { - UpdateManager.Instance.ReinstateIfRestarted(); + UpdateManager.Instance.CleanUp(); } - private void OnPrepareUpdatesCompleted(bool obj) + public void ApplyUpdates() { - UpdateManager updManager = UpdateManager.Instance; - - DialogResult dr = MessageBox.Show( - "Updates are ready to install. Do you wish to install them now?", - "Software updates ready", - MessageBoxButtons.YesNo); - - if (dr == DialogResult.Yes) + // ApplyUpdates is a synchronous method by design. Make sure to save all user work before calling + // it as it might restart your application + // get out of the way so the console window isn't obstructed + try { - // This is a synchronous method by design, make sure to save all user work before calling - // it as it might restart your application - updManager.ApplyUpdates(true,true,true); + UpdateManager.Instance.ApplyUpdates(true, UserSettingStorage.Instance.EnableUpdateLog, false); } + catch (System.Exception e) + { + string updateError = InternationalizationManager.Instance.GetTranslation("update_wox_update_error"); + Log.Error(e); + MessageBox.Show(updateError); + OnUpdateError(); + } + + UpdateManager.Instance.CleanUp(); } private IUpdateSource GetUpdateSource() { - // Normally this would be a web based source. - // But for the demo app, we prepare an in-memory source. - var source = new NAppUpdate.Framework.Sources.SimpleWebSource("http://127.0.0.1:8888/Update.xml"); + var source = new WoxUpdateSource(UpdateFeedURL, HttpRequest.GetWebProxy(HttpProxy.Instance)); return source; } + + protected virtual void OnPrepareUpdateReady() + { + var handler = PrepareUpdateReady; + if (handler != null) handler(this, EventArgs.Empty); + } + + protected virtual void OnUpdateError() + { + var handler = UpdateError; + if (handler != null) handler(this, EventArgs.Empty); + } } } diff --git a/Wox.Core/Updater/WoxUpdateSource.cs b/Wox.Core/Updater/WoxUpdateSource.cs new file mode 100644 index 000000000..20b66e2f6 --- /dev/null +++ b/Wox.Core/Updater/WoxUpdateSource.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using NAppUpdate.Framework.Common; +using NAppUpdate.Framework.Sources; +using NAppUpdate.Framework.Utils; + +namespace Wox.Core.Updater +{ + internal class WoxUpdateSource : IUpdateSource + { + public IWebProxy Proxy { get; set; } + + public string FeedUrl { get; set; } + + public WoxUpdateSource(string feedUrl,IWebProxy proxy) + { + this.FeedUrl = feedUrl; + this.Proxy = proxy; + } + + private void TryResolvingHost() + { + Uri uri = new Uri(this.FeedUrl); + try + { + Dns.GetHostEntry(uri.Host); + } + catch (System.Exception ex) + { + throw new WebException(string.Format("Failed to resolve {0}. Check your connectivity.", (object)uri.Host), WebExceptionStatus.ConnectFailure); + } + } + + public string GetUpdatesFeed() + { + this.TryResolvingHost(); + string str = string.Empty; + WebRequest webRequest = WebRequest.Create(this.FeedUrl); + webRequest.Method = "GET"; + webRequest.Proxy = this.Proxy; + using (WebResponse response = webRequest.GetResponse()) + { + Stream responseStream = response.GetResponseStream(); + if (responseStream != null) + { + using (StreamReader streamReader = new StreamReader(responseStream, true)) + str = streamReader.ReadToEnd(); + } + } + return str; + } + + public bool GetData(string url, string baseUrl, Action onProgress, ref string tempLocation) + { + if (!string.IsNullOrEmpty(baseUrl) && !baseUrl.EndsWith("/")) + baseUrl += "/"; + FileDownloader fileDownloader = !Uri.IsWellFormedUriString(url, UriKind.Absolute) ? (!Uri.IsWellFormedUriString(baseUrl, UriKind.Absolute) ? (string.IsNullOrEmpty(baseUrl) ? new FileDownloader(url) : new FileDownloader(new Uri(new Uri(baseUrl), url))) : new FileDownloader(new Uri(new Uri(baseUrl, UriKind.Absolute), url))) : new FileDownloader(url); + fileDownloader.Proxy = this.Proxy; + if (string.IsNullOrEmpty(tempLocation) || !Directory.Exists(Path.GetDirectoryName(tempLocation))) + tempLocation = Path.GetTempFileName(); + return fileDownloader.DownloadToFile(tempLocation, onProgress); + } + } +} diff --git a/Wox.Core/UserSettings/UserSettingStorage.cs b/Wox.Core/UserSettings/UserSettingStorage.cs index 9b1af13a6..436cfaf70 100644 --- a/Wox.Core/UserSettings/UserSettingStorage.cs +++ b/Wox.Core/UserSettings/UserSettingStorage.cs @@ -6,6 +6,7 @@ using Newtonsoft.Json; using Wox.Infrastructure.Storage; using Wox.Plugin; using System.Drawing; +using System.Reflection; namespace Wox.Core.UserSettings { @@ -14,6 +15,13 @@ namespace Wox.Core.UserSettings [JsonProperty] public bool DontPromptUpdateMsg { get; set; } + [JsonProperty] + public int ActivateTimes { get; set; } + + + [JsonProperty] + public bool EnableUpdateLog { get; set; } + [JsonProperty] public string Hotkey { get; set; } @@ -47,9 +55,6 @@ namespace Wox.Core.UserSettings [JsonProperty] public string ResultItemFontStretch { get; set; } - [JsonProperty] - public List WebSearches { get; set; } - [JsonProperty] public double WindowLeft { get; set; } @@ -64,18 +69,14 @@ namespace Wox.Core.UserSettings [JsonProperty] public bool StartWoxOnSystemStartup { get; set; } + [Obsolete] [JsonProperty] public double Opacity { get; set; } + [Obsolete] [JsonProperty] public OpacityMode OpacityMode { get; set; } - [JsonProperty] - public bool EnableWebSearchSuggestion { get; set; } - - [JsonProperty] - public string WebSearchSuggestionSource { get; set; } - [JsonProperty] public bool LeaveCmdOpen { get; set; } @@ -97,55 +98,9 @@ namespace Wox.Core.UserSettings [JsonProperty] public string ProxyPassword { get; set; } - public List LoadDefaultWebSearches() - { - List webSearches = new List(); - - WebSearch googleWebSearch = new WebSearch() - { - Title = "Google", - ActionWord = "g", - IconPath = Path.GetDirectoryName(Application.ExecutablePath) + @"\Images\websearch\google.png", - Url = "https://www.google.com/search?q={q}", - Enabled = true - }; - webSearches.Add(googleWebSearch); - - - WebSearch wikiWebSearch = new WebSearch() - { - Title = "Wikipedia", - ActionWord = "wiki", - IconPath = Path.GetDirectoryName(Application.ExecutablePath) + @"\Images\websearch\wiki.png", - Url = "http://en.wikipedia.org/wiki/{q}", - Enabled = true - }; - webSearches.Add(wikiWebSearch); - - WebSearch findIcon = new WebSearch() - { - Title = "FindIcon", - ActionWord = "findicon", - IconPath = Path.GetDirectoryName(Application.ExecutablePath) + @"\Images\websearch\pictures.png", - Url = "http://findicons.com/search/{q}", - Enabled = true - }; - webSearches.Add(findIcon); - - return webSearches; - } - protected override string ConfigFolder { - get - { - string userProfilePath = Environment.GetEnvironmentVariable("USERPROFILE"); - if (userProfilePath == null) - { - throw new ArgumentException("Environment variable USERPROFILE is empty"); - } - return Path.Combine(Path.Combine(userProfilePath, ".Wox"), "Config"); - } + get { return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Config"); } } protected override string ConfigName @@ -153,12 +108,20 @@ namespace Wox.Core.UserSettings get { return "config"; } } + public void IncreaseActivateTimes() + { + ActivateTimes++; + if (ActivateTimes % 15 == 0) + { + Save(); + } + } + protected override UserSettingStorage LoadDefault() { DontPromptUpdateMsg = false; Theme = "Dark"; Language = "en"; - WebSearches = LoadDefaultWebSearches(); CustomizedPluginConfigs = new List(); Hotkey = "Alt + Space"; QueryBoxFont = FontFamily.GenericSansSerif.Name; diff --git a/Wox.Core/Version/VersionManager.cs b/Wox.Core/Version/VersionManager.cs deleted file mode 100644 index 994e46e16..000000000 --- a/Wox.Core/Version/VersionManager.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; - -namespace Wox.Core.Version -{ - public class VersionManager - { - private static VersionManager versionManager; - private static SemanticVersion currentVersion; - - public static VersionManager Instance - { - get - { - if (versionManager == null) - { - versionManager = new VersionManager(); - } - return versionManager; - } - } - - private VersionManager() { } - - public SemanticVersion CurrentVersion - { - get - { - if (currentVersion == null) - { - currentVersion = new SemanticVersion(Assembly.GetExecutingAssembly().GetName().Version); - } - return currentVersion; - } - } - } -} diff --git a/Wox.Core/Wox.Core.csproj b/Wox.Core/Wox.Core.csproj index b9b40bb80..84940b303 100644 --- a/Wox.Core/Wox.Core.csproj +++ b/Wox.Core/Wox.Core.csproj @@ -69,7 +69,9 @@ + + @@ -99,9 +101,7 @@ - - - + diff --git a/Wox.Core/i18n/InternationalizationManager.cs b/Wox.Core/i18n/InternationalizationManager.cs index a1f0a9049..cfe1ca7fc 100644 --- a/Wox.Core/i18n/InternationalizationManager.cs +++ b/Wox.Core/i18n/InternationalizationManager.cs @@ -14,7 +14,7 @@ namespace Wox.Core.i18n private static Internationalization instance; private static object syncObject = new object(); - public static Internationalization Internationalization + public static Internationalization Instance { get { diff --git a/Wox.CrashReporter/ReportWindow.xaml.cs b/Wox.CrashReporter/ReportWindow.xaml.cs index 55ec0555b..7a6ec983c 100644 --- a/Wox.CrashReporter/ReportWindow.xaml.cs +++ b/Wox.CrashReporter/ReportWindow.xaml.cs @@ -16,8 +16,8 @@ using Wox.Core; using Wox.Core.Exception; using Wox.Core.i18n; using Wox.Core.UI; +using Wox.Core.Updater; using Wox.Core.UserSettings; -using Wox.Core.Version; using Wox.Infrastructure.Http; namespace Wox.CrashReporter @@ -36,7 +36,7 @@ namespace Wox.CrashReporter private void SetException(Exception exception) { tbSummary.AppendText(exception.Message); - tbVersion.Text = VersionManager.Instance.CurrentVersion.ToString(); + tbVersion.Text = UpdaterManager.Instance.CurrentVersion.ToString(); tbDatetime.Text = DateTime.Now.ToString(); tbStackTrace.AppendText(exception.StackTrace); tbSource.Text = exception.Source; @@ -45,7 +45,7 @@ namespace Wox.CrashReporter private void btnSend_Click(object sender, RoutedEventArgs e) { - string sendingMsg = InternationalizationManager.Internationalization.GetTranslation("reportWindow_sending"); + string sendingMsg = InternationalizationManager.Instance.GetTranslation("reportWindow_sending"); tbSendReport.Content = sendingMsg; btnSend.IsEnabled = false; ThreadPool.QueueUserWorkItem(o => SendReport()); @@ -57,11 +57,11 @@ namespace Wox.CrashReporter string response = HttpRequest.Post(APIServer.ErrorReportURL, error, HttpProxy.Instance); if (response.ToLower() == "ok") { - MessageBox.Show(InternationalizationManager.Internationalization.GetTranslation("reportWindow_report_succeed")); + MessageBox.Show(InternationalizationManager.Instance.GetTranslation("reportWindow_report_succeed")); } else { - MessageBox.Show(InternationalizationManager.Internationalization.GetTranslation("reportWindow_report_failed")); + MessageBox.Show(InternationalizationManager.Instance.GetTranslation("reportWindow_report_failed")); } Dispatcher.Invoke(new Action(Close)); } diff --git a/Wox.Infrastructure/Http/HttpRequest.cs b/Wox.Infrastructure/Http/HttpRequest.cs index 5c08377d6..e80501936 100644 --- a/Wox.Infrastructure/Http/HttpRequest.cs +++ b/Wox.Infrastructure/Http/HttpRequest.cs @@ -14,6 +14,24 @@ namespace Wox.Infrastructure.Http return Get(url, encoding, proxy); } + public static WebProxy GetWebProxy(IHttpProxy proxy) + { + if (proxy != null && proxy.Enabled && !string.IsNullOrEmpty(proxy.Server)) + { + if (string.IsNullOrEmpty(proxy.UserName) || string.IsNullOrEmpty(proxy.Password)) + { + return new WebProxy(proxy.Server, proxy.Port); + } + + return new WebProxy(proxy.Server, proxy.Port) + { + Credentials = new NetworkCredential(proxy.UserName, proxy.Password) + }; + } + + return null; + } + private static string Get(string url, string encoding, IHttpProxy proxy) { if (string.IsNullOrEmpty(url)) return string.Empty; @@ -21,20 +39,7 @@ namespace Wox.Infrastructure.Http HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest; request.Method = "GET"; request.Timeout = 10 * 1000; - if (proxy != null && proxy.Enabled && !string.IsNullOrEmpty(proxy.Server)) - { - if (string.IsNullOrEmpty(proxy.UserName) || string.IsNullOrEmpty(proxy.Password)) - { - request.Proxy = new WebProxy(proxy.Server, proxy.Port); - } - else - { - request.Proxy = new WebProxy(proxy.Server, proxy.Port) - { - Credentials = new NetworkCredential(proxy.UserName, proxy.Password) - }; - } - } + request.Proxy = GetWebProxy(proxy); try { diff --git a/Wox.Infrastructure/NLog.config b/Wox.Infrastructure/NLog.config index ec19a8278..9dcf31def 100644 --- a/Wox.Infrastructure/NLog.config +++ b/Wox.Infrastructure/NLog.config @@ -15,11 +15,9 @@ Error - error messages Fatal - very serious errors--> - - + - \ No newline at end of file diff --git a/Wox.Infrastructure/Storage/BinaryStorage.cs b/Wox.Infrastructure/Storage/BinaryStorage.cs index 7561ba114..7651ca770 100644 --- a/Wox.Infrastructure/Storage/BinaryStorage.cs +++ b/Wox.Infrastructure/Storage/BinaryStorage.cs @@ -6,6 +6,7 @@ using System.Reflection; using System.Runtime.Serialization.Formatters; using System.Runtime.Serialization.Formatters.Binary; using System.Text; +using System.Threading; using Wox.Infrastructure.Logger; namespace Wox.Infrastructure.Storage @@ -18,6 +19,7 @@ namespace Wox.Infrastructure.Storage [Serializable] public abstract class BinaryStorage : BaseStorage where T : class, IStorage, new() { + private static object syncObject = new object(); protected override string FileSuffix { get { return ".dat"; } @@ -87,25 +89,31 @@ namespace Wox.Infrastructure.Storage protected override void SaveInternal() { - try + ThreadPool.QueueUserWorkItem(o => { - FileStream fileStream = new FileStream(ConfigPath, FileMode.Create); - BinaryFormatter binaryFormatter = new BinaryFormatter + lock (syncObject) { - AssemblyFormat = FormatterAssemblyStyle.Simple - }; - binaryFormatter.Serialize(fileStream, serializedObject); - fileStream.Close(); - } - catch (Exception e) - { - Log.Error(e.Message); + try + { + FileStream fileStream = new FileStream(ConfigPath, FileMode.Create); + BinaryFormatter binaryFormatter = new BinaryFormatter + { + AssemblyFormat = FormatterAssemblyStyle.Simple + }; + binaryFormatter.Serialize(fileStream, serializedObject); + fileStream.Close(); + } + catch (Exception e) + { + Log.Error(e); #if (DEBUG) - { - throw; - } + { + throw; + } #endif - } + } + } + }); } } } diff --git a/Wox.Infrastructure/Storage/JsonStorage.cs b/Wox.Infrastructure/Storage/JsonStorage.cs index 4a4525bd3..ca6c0fea0 100644 --- a/Wox.Infrastructure/Storage/JsonStorage.cs +++ b/Wox.Infrastructure/Storage/JsonStorage.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; +using System.Threading; using Newtonsoft.Json; namespace Wox.Infrastructure.Storage @@ -12,6 +13,7 @@ namespace Wox.Infrastructure.Storage /// public abstract class JsonStrorage : BaseStorage where T : class, IStorage, new() { + private static object syncObject = new object(); protected override string FileSuffix { get { return ".json"; } @@ -39,8 +41,14 @@ namespace Wox.Infrastructure.Storage protected override void SaveInternal() { - string json = JsonConvert.SerializeObject(serializedObject, Formatting.Indented); - File.WriteAllText(ConfigPath, json); + ThreadPool.QueueUserWorkItem(o => + { + lock (syncObject) + { + string json = JsonConvert.SerializeObject(serializedObject, Formatting.Indented); + File.WriteAllText(ConfigPath, json); + } + }); } } } diff --git a/Wox.Plugin/IInstantSearch.cs b/Wox.Plugin/IInstantSearch.cs new file mode 100644 index 000000000..0799f45f4 --- /dev/null +++ b/Wox.Plugin/IInstantSearch.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Wox.Plugin +{ + public interface IInstantSearch + { + bool IsInstantSearch(string query); + } +} diff --git a/Wox.Plugin/IPublicAPI.cs b/Wox.Plugin/IPublicAPI.cs index 40ce63ef5..972d281f9 100644 --- a/Wox.Plugin/IPublicAPI.cs +++ b/Wox.Plugin/IPublicAPI.cs @@ -15,8 +15,7 @@ namespace Wox.Plugin /// /// /// - /// - void PushResults(Query query,PluginMetadata plugin, List results,bool clearBeforeInsert = false); + void PushResults(Query query,PluginMetadata plugin, List results); /// /// Execute command diff --git a/Wox.Plugin/PluginInitContext.cs b/Wox.Plugin/PluginInitContext.cs index 928b15b78..20fbe79a1 100644 --- a/Wox.Plugin/PluginInitContext.cs +++ b/Wox.Plugin/PluginInitContext.cs @@ -7,7 +7,7 @@ namespace Wox.Plugin { public class PluginInitContext { - public PluginMetadata CurrentPluginMetadata { get; set; } + public PluginMetadata CurrentPluginMetadata { get; internal set; } /// /// Public APIs for plugin invocation @@ -15,75 +15,5 @@ namespace Wox.Plugin public IPublicAPI API { get; set; } public IHttpProxy Proxy { get; set; } - - #region Legacy APIs - - [Obsolete("This method has been obsoleted, use API.ShellRun instead")] - public bool ShellRun(string cmd) - { - return API.ShellRun(cmd); - } - - [Obsolete("This method has been obsoleted, use API.OpenSettingDialog instead")] - public void ChangeQuery(string query, bool requery = false) - { - API.ChangeQuery(query, requery); - } - - [Obsolete("This method has been obsoleted, use API.CloseApp instead")] - public void CloseApp() - { - API.CloseApp(); - } - - [Obsolete("This method has been obsoleted, use API.HideApp instead")] - public void HideApp() - { - API.HideApp(); - } - - [Obsolete("This method has been obsoleted, use API.ShowApp instead")] - public void ShowApp() - { - API.ShowApp(); - } - - [Obsolete("This method has been obsoleted, use API.OpenSettingDialog instead")] - public void ShowMsg(string title, string subTitle, string iconPath) - { - API.ShowMsg(title, subTitle, iconPath); - } - - [Obsolete("This method has been obsoleted, use API.OpenSettingDialog instead")] - public void OpenSettingDialog() - { - API.OpenSettingDialog(); - } - - [Obsolete("This method has been obsoleted, use API.StartLoadingBar instead")] - public void StartLoadingBar() - { - API.StartLoadingBar(); - } - - [Obsolete("This method has been obsoleted, use API.StopLoadingBar instead")] - public void StopLoadingBar() - { - API.StopLoadingBar(); - } - - [Obsolete("This method has been obsoleted, use API.InstallPlugin instead")] - public void InstallPlugin(string path) - { - API.InstallPlugin(path); - } - - [Obsolete("This method has been obsoleted, use API.ReloadPlugins instead")] - public void ReloadPlugins() - { - API.ReloadPlugins(); - } - - #endregion } } diff --git a/Wox.Plugin/PluginMetadata.cs b/Wox.Plugin/PluginMetadata.cs index 2c83eb445..406257f86 100644 --- a/Wox.Plugin/PluginMetadata.cs +++ b/Wox.Plugin/PluginMetadata.cs @@ -9,17 +9,6 @@ namespace Wox.Plugin { public class PluginMetadata { - private int configVersion = 1; - - /// - /// if we need to change the plugin config in the futher, use this to - /// indicate config version - /// - public int ConfigVersion - { - get { return configVersion; } - set { configVersion = value; } - } public string ID { get; set; } public string Name { get; set; } public string Author { get; set; } @@ -37,17 +26,16 @@ namespace Wox.Plugin public string ExecuteFileName { get; set; } public string PluginDirectory { get; set; } - [Obsolete("This property has been obsoleted, use PluginDirectory instead")] - public string PluginDirecotry - { - get { return PluginDirectory; } - } - public string ActionKeyword { get; set; } public PluginType PluginType { get; set; } public string IcoPath { get; set; } + public override string ToString() + { + return Name; + } + public string FullIcoPath { get diff --git a/Wox.Plugin/PluginPair.cs b/Wox.Plugin/PluginPair.cs index 9d09f7d10..b3053c057 100644 --- a/Wox.Plugin/PluginPair.cs +++ b/Wox.Plugin/PluginPair.cs @@ -9,5 +9,10 @@ namespace Wox.Plugin { public IPlugin Plugin { get; set; } public PluginMetadata Metadata { get; set; } + + public override string ToString() + { + return Metadata.Name; + } } } diff --git a/Wox.Plugin/Properties/AssemblyInfo.cs b/Wox.Plugin/Properties/AssemblyInfo.cs index 32d76d415..a7fb46756 100644 --- a/Wox.Plugin/Properties/AssemblyInfo.cs +++ b/Wox.Plugin/Properties/AssemblyInfo.cs @@ -2,9 +2,6 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// 有关程序集的常规信息通过以下 -// 特性集控制。更改这些特性值可修改 -// 与程序集关联的信息。 [assembly: AssemblyTitle("Wox.Plugin")] [assembly: AssemblyDescription("https://github.com/qianlifeng/Wox")] [assembly: AssemblyConfiguration("")] @@ -13,24 +10,11 @@ using System.Runtime.InteropServices; [assembly: AssemblyCopyright("The MIT License (MIT)")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] - -// 将 ComVisible 设置为 false 使此程序集中的类型 -// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型, -// 则将该类型上的 ComVisible 特性设置为 true。 [assembly: ComVisible(false)] - -// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID [assembly: Guid("c22be00d-a6f5-4e45-8ecc-09ebf297c812")] - -// 程序集的版本信息由下面四个值组成: -// -// 主版本 -// 次版本 -// 生成号 -// 修订号 -// -// 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, -// 方法是按如下所示使用“*”: -// [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] + +[assembly: InternalsVisibleTo("Wox")] +[assembly: InternalsVisibleTo("Wox.Core")] +[assembly: InternalsVisibleTo("Wox.Test")] diff --git a/Wox.Plugin/Query.cs b/Wox.Plugin/Query.cs index 1717f014a..4a0119914 100644 --- a/Wox.Plugin/Query.cs +++ b/Wox.Plugin/Query.cs @@ -1,11 +1,112 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace Wox.Plugin { public class Query { - public string RawQuery { get; set; } + /// + /// Raw query, this includes action keyword if it has + /// We didn't recommend use this property directly. You should always use Search property. + /// + public string RawQuery { get; internal set; } + + /// + /// Search part of a query. + /// This will not include action keyword if regular plugin gets it, and if a system plugin gets it, it should be same as RawQuery. + /// Since we allow user to switch a regular plugin to system plugin, so this property will always give you the "real" query part of + /// the query + /// + public string Search { get; internal set; } + + internal string GetActionKeyword() + { + if (!string.IsNullOrEmpty(RawQuery)) + { + var strings = RawQuery.Split(' '); + if (strings.Length > 0) + { + return strings[0]; + } + } + + return string.Empty; + } + + /// + /// Return first search split by space if it has + /// + public string FirstSearch + { + get + { + return SplitSearch(0); + } + } + + /// + /// strings from second search (including) to last search + /// + public string SecondToEndSearch + { + get + { + if (string.IsNullOrEmpty(Search)) return string.Empty; + + var strings = Search.Split(' '); + if (strings.Length > 1) + { + return Search.Substring(Search.IndexOf(' ') + 1); + } + return string.Empty; + } + } + + /// + /// Return second search split by space if it has + /// + public string SecondSearch + { + get + { + return SplitSearch(1); + } + } + + /// + /// Return third search split by space if it has + /// + public string ThirdSearch + { + get + { + return SplitSearch(2); + } + } + + private string SplitSearch(int index) + { + if (string.IsNullOrEmpty(Search)) return string.Empty; + + var strings = Search.Split(' '); + if (strings.Length > index) + { + return strings[index]; + } + + return string.Empty; + } + + public override string ToString() + { + return RawQuery; + } + + [Obsolete("Use Search instead, A plugin developer shouldn't care about action name, as it may changed by users. " + + "this property will be removed in v1.3.0")] public string ActionName { get; private set; } + + [Obsolete("Use Search instead, this property will be removed in v1.3.0")] public List ActionParameters { get; private set; } public Query(string rawQuery) @@ -33,10 +134,11 @@ namespace Wox.Plugin } } + [Obsolete("Use Search instead, this method will be removed in v1.3.0")] public string GetAllRemainingParameter() { - string[] strings = RawQuery.Split(new char[]{ ' ' }, 2, System.StringSplitOptions.None); + string[] strings = RawQuery.Split(new char[] { ' ' }, 2, System.StringSplitOptions.None); if (strings.Length > 1) { return strings[1]; diff --git a/Wox.Plugin/Result.cs b/Wox.Plugin/Result.cs index db0bd309c..6c1938fa4 100644 --- a/Wox.Plugin/Result.cs +++ b/Wox.Plugin/Result.cs @@ -8,7 +8,6 @@ namespace Wox.Plugin public class Result { - public string Title { get; set; } public string SubTitle { get; set; } public string IcoPath { get; set; } @@ -34,21 +33,15 @@ namespace Wox.Plugin public int Score { get; set; } - /// - /// Auto add scores for MRU items - /// - public bool AutoAjustScore { get; set; } - - //todo: this should be controlled by system, not visible to users /// /// Only resulsts that originQuery match with curren query will be displayed in the panel /// - public Query OriginQuery { get; set; } + internal Query OriginQuery { get; set; } /// - /// Don't set this property if you are developing a plugin + /// Plugin directory /// - public string PluginDirectory { get; set; } + public string PluginDirectory { get; internal set; } public new bool Equals(object obj) { @@ -75,6 +68,14 @@ namespace Wox.Plugin this.SubTitle = SubTitle; } - public List ContextMenu { get; set; } + /// + /// Context menus associate with this result + /// + public List ContextMenu { get; set; } + + /// + /// Plugin ID that generate this result + /// + public string PluginID { get; set; } } } \ No newline at end of file diff --git a/Wox.Plugin/Wox.Plugin.csproj b/Wox.Plugin/Wox.Plugin.csproj index 8f7aa5941..424272a20 100644 --- a/Wox.Plugin/Wox.Plugin.csproj +++ b/Wox.Plugin/Wox.Plugin.csproj @@ -46,6 +46,7 @@ + diff --git a/Wox.Test/Plugins/PluginInitTest.cs b/Wox.Test/Plugins/PluginInitTest.cs index 8d4108887..4c3b026c0 100644 --- a/Wox.Test/Plugins/PluginInitTest.cs +++ b/Wox.Test/Plugins/PluginInitTest.cs @@ -14,14 +14,6 @@ namespace Wox.Test.Plugins [TestFixture] public class PluginInitTest { - [Test] - public void CouldNotFindUserProfileTest() - { - var api = new Mock(); - Environment.SetEnvironmentVariable("USERPROFILE", ""); - Assert.Throws(typeof(WoxCritialException), () => PluginManager.Init(api.Object)); - } - [Test] public void PublicAPIIsNullTest() { diff --git a/Wox.Test/QueryTest.cs b/Wox.Test/QueryTest.cs index f1d8d2806..061e7d59f 100644 --- a/Wox.Test/QueryTest.cs +++ b/Wox.Test/QueryTest.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using NUnit.Framework; +using Wox.Core.Plugin; using Wox.Plugin; namespace Wox.Test @@ -10,22 +11,27 @@ namespace Wox.Test public class QueryTest { [Test] - public void QueryActionTest() + public void UserPluginQueryTest() { - Query q = new Query("this"); + Query q = new Query("f file.txt file2 file3"); + q.Search = "file.txt file2 file3"; - q = new Query("ev file.txt"); - Assert.AreEqual(q.ActionName,"ev"); - Assert.AreEqual(q.ActionParameters.Count,1); - Assert.AreEqual(q.ActionParameters[0],"file.txt"); + Assert.AreEqual(q.FirstSearch, "file.txt"); + Assert.AreEqual(q.SecondSearch, "file2"); + Assert.AreEqual(q.ThirdSearch, "file3"); + Assert.AreEqual(q.SecondToEndSearch, "file2 file3"); + } - q = new Query("ev file.txt file2.txt"); - Assert.AreEqual(q.ActionName,"ev"); - Assert.AreEqual(q.ActionParameters.Count,2); - Assert.AreEqual(q.ActionParameters[1],"file2.txt"); + [Test] + public void SystemPluginQueryTest() + { + Query q = new Query("file.txt file2 file3"); + q.Search = q.RawQuery; - q = new Query("ev file.txt file2.tx st"); - Assert.AreEqual(q.GetAllRemainingParameter(), "file.txt file2.tx st"); + Assert.AreEqual(q.FirstSearch, "file.txt"); + Assert.AreEqual(q.SecondSearch, "file2"); + Assert.AreEqual(q.ThirdSearch, "file3"); + Assert.AreEqual(q.SecondToEndSearch, "file2 file3"); } } } diff --git a/Wox.Test/SemanticVersionTest.cs b/Wox.Test/SemanticVersionTest.cs index c4abdcbbd..81e6e5dda 100644 --- a/Wox.Test/SemanticVersionTest.cs +++ b/Wox.Test/SemanticVersionTest.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using NUnit.Framework; -using Wox.Core.Version; +using Wox.Core.Updater; namespace Wox.Test { diff --git a/Wox.UpdateFeedGenerator/ConfigStorage.cs b/Wox.UpdateFeedGenerator/ConfigStorage.cs new file mode 100644 index 000000000..bdc6a30f3 --- /dev/null +++ b/Wox.UpdateFeedGenerator/ConfigStorage.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using Newtonsoft.Json; +using Wox.Infrastructure.Storage; + +namespace Wox.UpdateFeedGenerator +{ + public class ConfigStorage : JsonStrorage + { + [JsonProperty] + public string OutputDirectory { get; set; } + + [JsonProperty] + public string SourceDirectory { get; set; } + + [JsonProperty] + public string BaseURL { get; set; } + + [JsonProperty] + public string FeedXMLName { get; set; } + + [JsonProperty] + public bool CheckVersion { get; set; } + + [JsonProperty] + public bool CheckSize { get; set; } + + [JsonProperty] + public bool CheckDate { get; set; } + + [JsonProperty] + public bool CheckHash { get; set; } + + protected override void OnAfterLoad(ConfigStorage config) + { + if (string.IsNullOrEmpty(config.OutputDirectory)) + { + config.OutputDirectory = @"Update"; + ConfigStorage.Instance.Save(); + } + } + + protected override string ConfigFolder + { + get { return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); } + } + + protected override string ConfigName + { + get { return "config"; } + } + } +} diff --git a/Wox.UpdateFeedGenerator/FileInfoEx.cs b/Wox.UpdateFeedGenerator/FileInfoEx.cs new file mode 100644 index 000000000..ff707162e --- /dev/null +++ b/Wox.UpdateFeedGenerator/FileInfoEx.cs @@ -0,0 +1,38 @@ +using System.Diagnostics; +using System.IO; + +namespace Wox.UpdateFeedGenerator +{ + public class FileInfoEx + { + private readonly FileInfo myFileInfo; + private readonly string myFileVersion; + private readonly string myHash; + + public FileInfo FileInfo + { + get { return myFileInfo; } + } + + public string FileVersion + { + get { return myFileVersion; } + } + + public string Hash + { + get { return myHash; } + } + + public string RelativeName { get; private set; } + + public FileInfoEx(string fileName,int rootDirectoryLength) + { + myFileInfo = new FileInfo(fileName); + myFileVersion = FileVersionInfo.GetVersionInfo(fileName).FileVersion; + if (myFileVersion != null) myFileVersion = myFileVersion.Replace(", ", "."); + myHash = NAppUpdate.Framework.Utils.FileChecksum.GetSHA256Checksum(fileName); + RelativeName = fileName.Substring(rootDirectoryLength + 1); + } + } +} diff --git a/Wox.UpdateFeedGenerator/FileSystemEnumerator.cs b/Wox.UpdateFeedGenerator/FileSystemEnumerator.cs new file mode 100644 index 000000000..e7ef75d5f --- /dev/null +++ b/Wox.UpdateFeedGenerator/FileSystemEnumerator.cs @@ -0,0 +1,248 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.ConstrainedExecution; +using System.Runtime.InteropServices; +using System.Security.Permissions; +using System.Text.RegularExpressions; +using Microsoft.Win32.SafeHandles; +using Wox.UpdateFeedGenerator.Win32; + +namespace Wox.UpdateFeedGenerator +{ + namespace Win32 + { + /// + /// Structure that maps to WIN32_FIND_DATA + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + internal sealed class FindData + { + public int fileAttributes; + public int creationTime_lowDateTime; + public int creationTime_highDateTime; + public int lastAccessTime_lowDateTime; + public int lastAccessTime_highDateTime; + public int lastWriteTime_lowDateTime; + public int lastWriteTime_highDateTime; + public int nFileSizeHigh; + public int nFileSizeLow; + public int dwReserved0; + public int dwReserved1; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public String fileName; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] public String alternateFileName; + } + + /// + /// SafeHandle class for holding find handles + /// + internal sealed class SafeFindHandle : SafeHandleMinusOneIsInvalid + { + /// + /// Constructor + /// + public SafeFindHandle() : base(true) {} + + /// + /// Release the find handle + /// + /// true if the handle was released + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + protected override bool ReleaseHandle() + { + return SafeNativeMethods.FindClose(handle); + } + } + + /// + /// Wrapper for P/Invoke methods used by FileSystemEnumerator + /// + [SecurityPermission(SecurityAction.Assert, UnmanagedCode = true)] + internal static class SafeNativeMethods + { + [DllImport("Kernel32.dll", CharSet = CharSet.Auto)] + public static extern SafeFindHandle FindFirstFile(String fileName, [In, Out] FindData findFileData); + + [DllImport("kernel32", CharSet = CharSet.Auto)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool FindNextFile(SafeFindHandle hFindFile, [In, Out] FindData lpFindFileData); + + [DllImport("kernel32", CharSet = CharSet.Auto)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool FindClose(IntPtr hFindFile); + } + } + + /// + /// File system enumerator. This class provides an easy to use, efficient mechanism for searching a list of + /// directories for files matching a list of file specifications. The search is done incrementally as matches + /// are consumed, so the overhead before processing the first match is always kept to a minimum. + /// + public sealed class FileSystemEnumerator : IDisposable + { + /// + /// Information that's kept in our stack for simulated recursion + /// + private struct SearchInfo + { + /// + /// Find handle returned by FindFirstFile + /// + public readonly SafeFindHandle Handle; + + /// + /// Path that was searched to yield the find handle. + /// + public readonly string Path; + + /// + /// Constructor + /// + /// Find handle returned by FindFirstFile. + /// Path corresponding to find handle. + public SearchInfo(SafeFindHandle h, string p) + { + Handle = h; + Path = p; + } + } + + /// + /// Stack of open scopes. This is a member (instead of a local variable) + /// to allow Dispose to close any open find handles if the object is disposed + /// before the enumeration is completed. + /// + private readonly Stack m_scopes; + + /// + /// Array of paths to be searched. + /// + private readonly string[] m_paths; + + /// + /// Array of regular expressions that will detect matching files. + /// + private readonly List m_fileSpecs; + + /// + /// If true, sub-directories are searched. + /// + private readonly bool m_includeSubDirs; + + #region IDisposable implementation + + /// + /// IDisposable.Dispose + /// + public void Dispose() + { + while (m_scopes.Count > 0) { + SearchInfo si = m_scopes.Pop(); + si.Handle.Close(); + } + } + + #endregion + + /// + /// Constructor. + /// + /// Semicolon- or comma-delimitted list of paths to search. + /// Semicolon- or comma-delimitted list of wildcard filespecs to match. + /// If true, subdirectories are searched. + public FileSystemEnumerator(string pathsToSearch, string fileTypesToMatch, bool includeSubDirs) + { + m_scopes = new Stack(); + + // check for nulls + if (null == pathsToSearch) throw new ArgumentNullException("pathsToSearch"); + if (null == fileTypesToMatch) throw new ArgumentNullException("fileTypesToMatch"); + + // make sure spec doesn't contain invalid characters + if (fileTypesToMatch.IndexOfAny(new[] { ':', '<', '>', '/', '\\' }) >= 0) throw new ArgumentException("invalid cahracters in wildcard pattern", "fileTypesToMatch"); + + m_includeSubDirs = includeSubDirs; + m_paths = pathsToSearch.Split(new[] { ';', ',' }); + + string[] specs = fileTypesToMatch.Split(new[] { ';', ',' }); + m_fileSpecs = new List(specs.Length); + foreach (string spec in specs) { + // trim whitespace off file spec and convert Win32 wildcards to regular expressions + string pattern = spec.Trim().Replace(".", @"\.").Replace("*", @".*").Replace("?", @".?"); + m_fileSpecs.Add(new Regex("^" + pattern + "$", RegexOptions.IgnoreCase)); + } + } + + /// + /// Get an enumerator that returns all of the files that match the wildcards that + /// are in any of the directories to be searched. + /// + /// An IEnumerable that returns all matching files one by one. + /// + /// The enumerator that is returned finds files using a lazy algorithm that + /// searches directories incrementally as matches are consumed. + /// + public IEnumerable Matches() + { + foreach (string rootPath in m_paths) { + string path = rootPath.Trim(); + + // we "recurse" into a new directory by jumping to this spot + top: + + // check security - ensure that caller has rights to read this directory + new FileIOPermission(FileIOPermissionAccess.PathDiscovery, Path.Combine(path, ".")).Demand(); + + // now that security is checked, go read the directory + FindData findData = new FindData(); + SafeFindHandle handle = SafeNativeMethods.FindFirstFile(Path.Combine(path, "*"), findData); + m_scopes.Push(new SearchInfo(handle, path)); + bool restart = false; + + // we "return" from a sub-directory by jumping to this spot + restart: +// ReSharper disable InvertIf + if (!handle.IsInvalid) { +// ReSharper restore InvertIf + do { + // if we restarted the loop (unwound a recursion), fetch the next match + if (restart) { + restart = false; + continue; + } + + // don't match . or .. + if (findData.fileName.Equals(@".") || findData.fileName.Equals(@"..")) continue; + + if ((findData.fileAttributes & (int)FileAttributes.Directory) != 0) { + if (m_includeSubDirs) { + // it's a directory - recurse into it + path = Path.Combine(path, findData.fileName); + goto top; + } + } else { + // it's a file, see if any of the filespecs matches it + foreach (Regex fileSpec in m_fileSpecs) { + // if this spec matches, return this file's info + if (fileSpec.IsMatch(findData.fileName)) yield return new FileInfo(Path.Combine(path, findData.fileName)); + } + } + } while (SafeNativeMethods.FindNextFile(handle, findData)); + + // close this find handle + handle.Close(); + + // unwind the stack - are we still in a recursion? + m_scopes.Pop(); + if (m_scopes.Count > 0) { + SearchInfo si = m_scopes.Peek(); + handle = si.Handle; + path = si.Path; + restart = true; + goto restart; + } + } + } + } + } +} diff --git a/Wox.UpdateFeedGenerator/Generator.cs b/Wox.UpdateFeedGenerator/Generator.cs new file mode 100644 index 000000000..944425489 --- /dev/null +++ b/Wox.UpdateFeedGenerator/Generator.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Threading; +using System.Xml; + +namespace Wox.UpdateFeedGenerator +{ + public class Generator + { + private string OutputDirectory; + private string SourceDirectory; + private string BaseURL = ConfigStorage.Instance.BaseURL; + private string feedXMLPath; + private bool checkVersion = ConfigStorage.Instance.CheckVersion; + private bool checkSize = ConfigStorage.Instance.CheckSize; + private bool checkDate = ConfigStorage.Instance.CheckDate; + private bool checkHash = ConfigStorage.Instance.CheckHash; + + public Generator() + { + OutputDirectory = Path.GetFullPath(ConfigStorage.Instance.OutputDirectory); + SourceDirectory = Path.GetFullPath(ConfigStorage.Instance.SourceDirectory); + feedXMLPath = Path.Combine(ConfigStorage.Instance.OutputDirectory, ConfigStorage.Instance.FeedXMLName); + } + + private List ReadSourceFiles() + { + List files = new List(); + FileSystemEnumerator enumerator = new FileSystemEnumerator(SourceDirectory, "*.*", true); + foreach (FileInfo fi in enumerator.Matches()) + { + string file = fi.FullName; + if ((IsIgnorable(file))) continue; + FileInfoEx thisInfo = new FileInfoEx(file, SourceDirectory.Length); + files.Add(thisInfo); + } + return files; + } + + private bool IsIgnorable(string thisFile) + { + return false; + } + + public void Build() + { + Console.WriteLine("Building Wox update feed"); + if (!Directory.Exists(OutputDirectory)) + { + Directory.CreateDirectory(OutputDirectory); + } + + XmlDocument doc = new XmlDocument(); + XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "utf-8", null); + + doc.AppendChild(dec); + XmlElement feed = doc.CreateElement("Feed"); + feed.SetAttribute("BaseUrl", BaseURL.Trim()); + doc.AppendChild(feed); + + XmlElement tasks = doc.CreateElement("Tasks"); + + foreach (FileInfoEx file in ReadSourceFiles()) + { + Console.WriteLine("adding {0} to feed xml.", file.FileInfo.FullName); + XmlElement task = doc.CreateElement("FileUpdateTask"); + task.SetAttribute("localPath", file.RelativeName); + + // generate FileUpdateTask metadata items + task.SetAttribute("lastModified", file.FileInfo.LastWriteTime.ToFileTime().ToString(CultureInfo.InvariantCulture)); + task.SetAttribute("fileSize", file.FileInfo.Length.ToString(CultureInfo.InvariantCulture)); + if (!string.IsNullOrEmpty(file.FileVersion)) task.SetAttribute("version", file.FileVersion); + + XmlElement conds = doc.CreateElement("Conditions"); + XmlElement cond; + bool hasFirstCondition = false; + + //File Exists + cond = doc.CreateElement("FileExistsCondition"); + cond.SetAttribute("type", "or"); + conds.AppendChild(cond); + + //Version + if (checkVersion && !string.IsNullOrEmpty(file.FileVersion)) + { + cond = doc.CreateElement("FileVersionCondition"); + cond.SetAttribute("what", "below"); + cond.SetAttribute("version", file.FileVersion); + conds.AppendChild(cond); + hasFirstCondition = true; + } + + //Size + if (checkSize) + { + cond = doc.CreateElement("FileSizeCondition"); + cond.SetAttribute("type", hasFirstCondition ? "or-not" : "not"); + cond.SetAttribute("what", "is"); + cond.SetAttribute("size", file.FileInfo.Length.ToString(CultureInfo.InvariantCulture)); + conds.AppendChild(cond); + } + + //Date + if (checkDate) + { + cond = doc.CreateElement("FileDateCondition"); + if (hasFirstCondition) cond.SetAttribute("type", "or"); + cond.SetAttribute("what", "older"); + // local timestamp, not UTC + cond.SetAttribute("timestamp", file.FileInfo.LastWriteTime.ToFileTime().ToString(CultureInfo.InvariantCulture)); + conds.AppendChild(cond); + } + + //Hash + if (checkHash) + { + cond = doc.CreateElement("FileChecksumCondition"); + cond.SetAttribute("type", hasFirstCondition ? "or-not" : "not"); + cond.SetAttribute("checksumType", "sha256"); + cond.SetAttribute("checksum", file.Hash); + conds.AppendChild(cond); + } + + task.AppendChild(conds); + tasks.AppendChild(task); + string destFile = Path.Combine(OutputDirectory, file.RelativeName); + CopyFile(file.FileInfo.FullName, destFile); + } + feed.AppendChild(tasks); + doc.Save(feedXMLPath); + } + + private bool CopyFile(string sourceFile, string destFile) + { + // If the target folder doesn't exist, create the path to it + var fi = new FileInfo(destFile); + var d = Directory.GetParent(fi.FullName); + if (!Directory.Exists(d.FullName)) CreateDirectoryPath(d.FullName); + + // Copy with delayed retry + int retries = 3; + while (retries > 0) + { + try + { + if (File.Exists(destFile)) File.Delete(destFile); + File.Copy(sourceFile, destFile); + retries = 0; // success + return true; + } + catch (IOException) + { + // Failed... let's try sleeping a bit (slow disk maybe) + if (retries-- > 0) Thread.Sleep(200); + } + catch (UnauthorizedAccessException) + { + // same handling as IOException + if (retries-- > 0) Thread.Sleep(200); + } + } + return false; + } + + private void CreateDirectoryPath(string directoryPath) + { + // Create the folder/path if it doesn't exist, with delayed retry + int retries = 3; + while (retries > 0 && !Directory.Exists(directoryPath)) + { + Directory.CreateDirectory(directoryPath); + if (retries-- < 3) Thread.Sleep(200); + } + } + + } +} diff --git a/Wox.UpdateFeedGenerator/Program.cs b/Wox.UpdateFeedGenerator/Program.cs new file mode 100644 index 000000000..62953a2a6 --- /dev/null +++ b/Wox.UpdateFeedGenerator/Program.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Xml; + +namespace Wox.UpdateFeedGenerator +{ + class Program + { + static void Main(string[] args) + { + new Generator().Build(); + } + } +} diff --git a/Wox.UpdateFeedGenerator/Properties/AssemblyInfo.cs b/Wox.UpdateFeedGenerator/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..d0f426828 --- /dev/null +++ b/Wox.UpdateFeedGenerator/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的常规信息通过以下 +// 特性集控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Wox.UpdateFeedGenerator")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Wox.UpdateFeedGenerator")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 使此程序集中的类型 +// 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, +// 则将该类型上的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("2f3420c0-2c21-4f71-a45d-a47b5305fe20")] + +// 程序集的版本信息由下面四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, +// 方法是按如下所示使用“*”: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Wox.UpdateFeedGenerator/README.md b/Wox.UpdateFeedGenerator/README.md new file mode 100644 index 000000000..00741d2ac --- /dev/null +++ b/Wox.UpdateFeedGenerator/README.md @@ -0,0 +1 @@ +NAppUpdate feed generator for Wox. It's something like [FeedBuilder](https://github.com/synhershko/NAppUpdate/tree/master/FeedBuilder) \ No newline at end of file diff --git a/Wox.UpdateFeedGenerator/Wox.UpdateFeedGenerator.csproj b/Wox.UpdateFeedGenerator/Wox.UpdateFeedGenerator.csproj new file mode 100644 index 000000000..2752c0e04 --- /dev/null +++ b/Wox.UpdateFeedGenerator/Wox.UpdateFeedGenerator.csproj @@ -0,0 +1,84 @@ + + + + + Debug + AnyCPU + {D120E62B-EC59-4FB4-8129-EFDD4C446A5F} + Exe + Properties + Wox.UpdateFeedGenerator + Wox.UpdateFeedGenerator + v3.5 + 512 + ..\ + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\References\NAppUpdate.Framework.dll + + + False + ..\packages\Newtonsoft.Json.6.0.8\lib\net35\Newtonsoft.Json.dll + + + + + + + + + + + + + + + + + + + + + + + {4fd29318-a8ab-4d8f-aa47-60bc241b8da3} + Wox.Infrastructure + + + + + + + 这台计算机上缺少此项目引用的 NuGet 程序包。启用“NuGet 程序包还原”可下载这些程序包。有关详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 + + + + + \ No newline at end of file diff --git a/Wox.UpdateFeedGenerator/packages.config b/Wox.UpdateFeedGenerator/packages.config new file mode 100644 index 000000000..7a13476a5 --- /dev/null +++ b/Wox.UpdateFeedGenerator/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Wox.sln b/Wox.sln index cd2007ff8..1759a11e0 100644 --- a/Wox.sln +++ b/Wox.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -VisualStudioVersion = 12.0.30723.0 +VisualStudioVersion = 12.0.21005.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Test", "Wox.Test\Wox.Test.csproj", "{FF742965-9A80-41A5-B042-D6C7D3A21708}" EndProject @@ -41,6 +41,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.CrashReporter", "Wox.Cr EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Plugin.QueryHistory", "Plugins\Wox.Plugin.QueryHistory\Wox.Plugin.QueryHistory.csproj", "{B552DCB6-692E-4B1D-9E0B-9096A2A7E6B0}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.UpdateFeedGenerator", "Wox.UpdateFeedGenerator\Wox.UpdateFeedGenerator.csproj", "{D120E62B-EC59-4FB4-8129-EFDD4C446A5F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Plugin.Everything", "Plugins\Wox.Plugin.Everything\Wox.Plugin.Everything.csproj", "{230AE83F-E92E-4E69-8355-426B305DA9C0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -119,6 +123,14 @@ Global {B552DCB6-692E-4B1D-9E0B-9096A2A7E6B0}.Debug|Any CPU.Build.0 = Debug|Any CPU {B552DCB6-692E-4B1D-9E0B-9096A2A7E6B0}.Release|Any CPU.ActiveCfg = Release|Any CPU {B552DCB6-692E-4B1D-9E0B-9096A2A7E6B0}.Release|Any CPU.Build.0 = Release|Any CPU + {D120E62B-EC59-4FB4-8129-EFDD4C446A5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D120E62B-EC59-4FB4-8129-EFDD4C446A5F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D120E62B-EC59-4FB4-8129-EFDD4C446A5F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D120E62B-EC59-4FB4-8129-EFDD4C446A5F}.Release|Any CPU.Build.0 = Release|Any CPU + {230AE83F-E92E-4E69-8355-426B305DA9C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {230AE83F-E92E-4E69-8355-426B305DA9C0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {230AE83F-E92E-4E69-8355-426B305DA9C0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {230AE83F-E92E-4E69-8355-426B305DA9C0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -136,5 +148,6 @@ Global {A3DCCBCA-ACC1-421D-B16E-210896234C26} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} {F35190AA-4758-4D9E-A193-E3BDF6AD3567} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} {B552DCB6-692E-4B1D-9E0B-9096A2A7E6B0} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} + {230AE83F-E92E-4E69-8355-426B305DA9C0} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} EndGlobalSection EndGlobal diff --git a/Wox/ActionKeyword.xaml b/Wox/ActionKeyword.xaml index 27ed9ad17..bdc7b6000 100644 --- a/Wox/ActionKeyword.xaml +++ b/Wox/ActionKeyword.xaml @@ -6,15 +6,16 @@ ResizeMode="NoResize" Loaded="ActionKeyword_OnLoaded" WindowStartupLocation="CenterScreen" - Height="200" Width="674.766"> + Height="200" Width="600"> + - + @@ -24,8 +25,10 @@ + + - +