├── src ├── urlPlugin │ ├── urlPlugin.rc │ ├── res │ │ └── Icon_url.ico │ ├── AboutDlg.h │ ├── SettingsDlg.h │ ├── ShortcutCommand.h │ ├── external │ │ └── npp │ │ │ ├── Sci_Position.h │ │ │ ├── PluginInterface.h │ │ │ ├── URLCtrl.h │ │ │ ├── StaticDialog.h │ │ │ ├── ControlsTab.h │ │ │ ├── ControlsTab.cpp │ │ │ ├── Window.h │ │ │ ├── URLCtrl.cpp │ │ │ ├── StaticDialog.cpp │ │ │ ├── TabBar.h │ │ │ └── TabBar.cpp │ ├── ShortcutCommand.cpp │ ├── Profile.h │ ├── ScintillaEditor.h │ ├── resource.h │ ├── dllmain.cpp │ ├── PluginHelper.h │ ├── Define.h │ ├── AboutDlg.cpp │ ├── urlPlugin.vcxproj.filters │ ├── ScintillaEditor.cpp │ ├── Profile.cpp │ ├── SettingsDlg.cpp │ ├── URL.h │ ├── PluginHelper.cpp │ └── urlPlugin.vcxproj ├── utilityLib │ ├── framework.h │ ├── pch.cpp │ ├── Execute.h │ ├── pch.h │ ├── StringHelper.h │ ├── Execute.cpp │ ├── Utility.h │ ├── utilityLib.vcxproj.filters │ ├── StringHelper.cpp │ ├── Utility.cpp │ └── utilityLib.vcxproj └── nppURLPlugin.sln ├── README.md ├── .gitignore ├── .gitatttributes ├── appveyor.yml └── LICENSE /src/urlPlugin/urlPlugin.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SinghRajenM/nppURLPlugin/HEAD/src/urlPlugin/urlPlugin.rc -------------------------------------------------------------------------------- /src/urlPlugin/res/Icon_url.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SinghRajenM/nppURLPlugin/HEAD/src/urlPlugin/res/Icon_url.ico -------------------------------------------------------------------------------- /src/utilityLib/framework.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 4 | 5 | #include 6 | -------------------------------------------------------------------------------- /src/utilityLib/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: source file corresponding to the pre-compiled header 2 | 3 | #include "pch.h" 4 | 5 | // When you are using pre-compiled headers, this source file is necessary for compilation to succeed. 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nppURLPlugin: A URL encode/decode plugin for Notepad++ 2 | [![GitHub release](https://img.shields.io/github/release/SinghRajenM/nppURLPlugin.svg)](../../releases/latest) 3 |     [![Build status](https://ci.appveyor.com/api/projects/status/tmvwjtyn5sb36knj?svg=true)](https://ci.appveyor.com/project/SinghRajenM/nppurlplugin) 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/urlPlugin/AboutDlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "URLCtrl.h" 3 | #include "StaticDialog.h" 4 | 5 | class AboutDlg : public StaticDialog 6 | { 7 | public: 8 | AboutDlg(HINSTANCE hIntance, HWND hParent, int nCmdId); 9 | ~AboutDlg() = default; 10 | 11 | bool ShowDlg(bool bShow); 12 | 13 | protected: 14 | virtual INT_PTR CALLBACK run_dlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) override; 15 | 16 | void SetVersion(HWND hWnd); 17 | 18 | private: 19 | int m_nCmdId = -1; 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /src/utilityLib/Execute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | class Execute 8 | { 9 | public: 10 | Execute(const TCHAR* cmd, const TCHAR* args, const TCHAR* cDir, bool show = false); 11 | 12 | bool Run(bool isElevationRequired = false); 13 | DWORD RunSync(bool isElevationRequired = false); 14 | 15 | private: 16 | std::wstring m_Command; 17 | std::wstring m_Args; 18 | std::wstring m_CurDir; 19 | bool m_bShow = false; 20 | SHELLEXECUTEINFO m_ShExecInfo = {}; 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /src/utilityLib/pch.h: -------------------------------------------------------------------------------- 1 | // pch.h: This is a precompiled header file. 2 | // Files listed below are compiled only once, improving build performance for future builds. 3 | // This also affects IntelliSense performance, including code completion and many code browsing features. 4 | // However, files listed here are ALL re-compiled if any one of them is updated between builds. 5 | // Do not add files here that you will be updating frequently as this negates the performance advantage. 6 | 7 | #ifndef PCH_H 8 | #define PCH_H 9 | 10 | // add headers that you want to pre-compile here 11 | #include "framework.h" 12 | 13 | #endif //PCH_H 14 | -------------------------------------------------------------------------------- /src/utilityLib/StringHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class StringHelper 6 | { 7 | public: 8 | StringHelper() = default; 9 | ~StringHelper() = default; 10 | 11 | static std::string ReplaceAll(const std::string& str, const std::string& search, const std::string& replace); 12 | static std::wstring ReplaceAll(const std::wstring& wstr, const std::wstring& search, const std::wstring& replace); 13 | 14 | static std::wstring ToWstring(const std::string& str, UINT codePage = CP_THREAD_ACP); 15 | static std::string ToString(const std::wstring& wstr, UINT codePage = CP_THREAD_ACP); 16 | 17 | static std::vector Split(const std::string& input, const std::string& delim); 18 | static std::vector Split(const std::wstring& input, const std::wstring& delim); 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------- 2 | # VisualStudio 3 | 4 | #-- User-specific files 5 | *.suo 6 | *.user 7 | *.vcxproj.user 8 | *.sln.docstates 9 | 10 | 11 | #-- Build results 12 | [Dd]ebug/ 13 | [Rr]elease/ 14 | x64/ 15 | x86/ 16 | #[Bb]in/ 17 | [Oo]bj/ 18 | *.pdb 19 | 20 | #-- Visual C++ cache files 21 | .vs/ 22 | ipch/ 23 | *.aps 24 | *.ncb 25 | *.opensdf 26 | *.sdf 27 | *.cachefile 28 | 29 | # Prerequisites 30 | *.d 31 | 32 | # Compiled Object files 33 | *.slo 34 | *.lo 35 | *.o 36 | *.obj 37 | 38 | # Precompiled Headers 39 | *.gch 40 | *.pch 41 | 42 | # Compiled Dynamic libraries 43 | *.so 44 | *.dylib 45 | *.dll 46 | 47 | # Fortran module files 48 | *.mod 49 | *.smod 50 | 51 | # Compiled Static libraries 52 | *.lai 53 | *.la 54 | *.a 55 | *.lib 56 | 57 | # Executables 58 | *.exe 59 | *.out 60 | *.app 61 | -------------------------------------------------------------------------------- /src/urlPlugin/SettingsDlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "StaticDialog.h" 3 | #include "ControlsTab.h" 4 | #include "Define.h" 5 | #include 6 | 7 | class SettingsDlg : public StaticDialog 8 | { 9 | public: 10 | SettingsDlg(HINSTANCE hIntance, HWND hParent, int nCmdId, const std::wstring& configPath); 11 | ~SettingsDlg() = default; 12 | 13 | bool ShowDlg(bool bShow); 14 | 15 | protected: 16 | virtual INT_PTR CALLBACK run_dlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) override; 17 | 18 | private: 19 | bool Apply(); 20 | void destroy() override; 21 | bool ReadINI(); 22 | bool WriteINI(); 23 | void InitDlg(); 24 | 25 | void EnableDelimter(bool enable); 26 | 27 | void FillExclusionSet(); 28 | void DisplayExclusionSet(); 29 | 30 | private: 31 | int m_nCmdId = -1; 32 | std::wstring m_configPath; 33 | EncodeInfo m_EncodeInfo; 34 | DecodeInfo m_DecodeInfo; 35 | }; 36 | -------------------------------------------------------------------------------- /src/urlPlugin/ShortcutCommand.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Define.h" 3 | #include 4 | 5 | enum class CallBackID :int { SHOW_SETTING = 0, ENCODE_URL, DECODE_URL, SEP_1, ABOUT }; 6 | 7 | class ShortcutCommand 8 | { 9 | public: 10 | ShortcutCommand(int nCommandCount); 11 | ~ShortcutCommand() = default; 12 | 13 | auto GetCommandID(CallBackID id) const->int { return m_pFuncItem[At(id)]._cmdID; } 14 | auto GetFuncItem() const->FuncItem* { return m_pFuncItem.get(); } 15 | 16 | bool SetCommand(CallBackID id, const TCHAR* cmdName, const PFUNCPLUGINCMD pFunc, bool checkOnInit); 17 | bool SetShortCut(CallBackID id, const ShortcutKey& scKey); 18 | 19 | private: 20 | int At(CallBackID id) const { return static_cast(id); } 21 | 22 | private: 23 | std::unique_ptr m_pFuncItem = nullptr; 24 | std::unique_ptr m_pShortcutKeys = nullptr; 25 | int m_nCmdCount = 0; 26 | }; 27 | 28 | -------------------------------------------------------------------------------- /src/urlPlugin/external/npp/Sci_Position.h: -------------------------------------------------------------------------------- 1 | // Scintilla source code edit control 2 | /** @file Sci_Position.h 3 | ** Define the Sci_Position type used in Scintilla's external interfaces. 4 | ** These need to be available to clients written in C so are not in a C++ namespace. 5 | **/ 6 | // Copyright 2015 by Neil Hodgson 7 | // The License.txt file describes the conditions under which this software may be distributed. 8 | 9 | #ifndef SCI_POSITION_H 10 | #define SCI_POSITION_H 11 | 12 | #include 13 | 14 | // Basic signed type used throughout interface 15 | typedef ptrdiff_t Sci_Position; 16 | 17 | // Unsigned variant used for ILexer::Lex and ILexer::Fold 18 | // Definitions of common types 19 | typedef size_t Sci_PositionU; 20 | 21 | 22 | // For Sci_CharacterRange which is defined as long to be compatible with Win32 CHARRANGE 23 | typedef intptr_t Sci_PositionCR; 24 | 25 | #ifdef _WIN32 26 | #define SCI_METHOD __stdcall 27 | #else 28 | #define SCI_METHOD 29 | #endif 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/urlPlugin/ShortcutCommand.cpp: -------------------------------------------------------------------------------- 1 | #include "ShortcutCommand.h" 2 | #include 3 | 4 | ShortcutCommand::ShortcutCommand(int nCommandCount) : 5 | m_nCmdCount(nCommandCount), 6 | m_pFuncItem(std::make_unique(nCommandCount)), 7 | m_pShortcutKeys(std::make_unique(nCommandCount)) 8 | { 9 | } 10 | 11 | bool ShortcutCommand::SetCommand(CallBackID id, const TCHAR* cmdName, const PFUNCPLUGINCMD pFunc, bool checkOnInit) 12 | { 13 | int nIndex = static_cast(id); 14 | 15 | if (m_nCmdCount <= nIndex || !pFunc) 16 | return false; 17 | 18 | _tcscpy_s(m_pFuncItem[nIndex]._itemName, cmdName); 19 | m_pFuncItem[nIndex]._pFunc = pFunc; 20 | m_pFuncItem[nIndex]._init2Check = checkOnInit; 21 | m_pFuncItem[nIndex]._pShKey = &m_pShortcutKeys[nIndex]; 22 | 23 | return true; 24 | } 25 | 26 | bool ShortcutCommand::SetShortCut(CallBackID id, const ShortcutKey& scKey) 27 | { 28 | int nIndex = static_cast(id); 29 | 30 | if (m_nCmdCount <= nIndex) 31 | return false; 32 | 33 | m_pShortcutKeys[At(id)] = scKey; 34 | 35 | return true; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /src/urlPlugin/Profile.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Define.h" 4 | 5 | class Profile 6 | { 7 | std::wstring m_ProfileFilePath; 8 | 9 | public: 10 | Profile(const std::wstring &path); 11 | virtual ~Profile() = default; 12 | 13 | protected: 14 | bool ReadValue(const std::wstring& section, const std::wstring& key, std::wstring& retVal, const std::wstring& defaultVal = {}) const; 15 | bool WriteValue(const std::wstring& section, const std::wstring& key, const std::wstring& value) const; 16 | 17 | private: 18 | void Init(); 19 | }; 20 | 21 | 22 | class ProfileEncode : public Profile 23 | { 24 | public: 25 | ProfileEncode(const std::wstring& path) : Profile(path) {} 26 | ~ProfileEncode() = default; 27 | 28 | bool GetInfo(EncodeInfo& info) const; 29 | bool SetInfo(const EncodeInfo& info) const; 30 | }; 31 | 32 | 33 | class ProfileDecode : public Profile 34 | { 35 | public: 36 | ProfileDecode(const std::wstring& path) : Profile(path) {} 37 | ~ProfileDecode() = default; 38 | 39 | bool GetInfo(DecodeInfo & info) const; 40 | bool SetInfo(const DecodeInfo& info) const; 41 | }; -------------------------------------------------------------------------------- /src/urlPlugin/ScintillaEditor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Define.h" 3 | #include 4 | #include 5 | 6 | class ScintillaEditor 7 | { 8 | public: 9 | ScintillaEditor(const NppData& nppData); 10 | ~ScintillaEditor() = default; 11 | 12 | auto GetSelectedText() const->std::string; 13 | bool ReplaceSelectedText(const std::string& replaceText) const; 14 | bool PasteSelectedOnNewFile(const std::string& text) const; 15 | 16 | auto GetFullFilePath() const->std::wstring; 17 | bool OpenFile(const std::wstring& filePath) const; 18 | 19 | private: 20 | LRESULT Execute(UINT Msg, WPARAM wParam = 0, LPARAM lParam = 0) const; 21 | auto GetSelection() const->Sci_CharacterRange; 22 | auto GetSelectedText(char* txt, int size, bool expand = true) const->char*; 23 | bool ExpandWordSelection() const; 24 | auto GetWordRange() const->std::pair; 25 | auto GetWordFromRange(char* txt, size_t size, size_t pos1, size_t pos2) const->char*; 26 | void GetText(char* dest, size_t start, size_t end) const; 27 | 28 | private: 29 | NppData m_NppData = {}; 30 | HWND m_hScintilla = nullptr; 31 | }; 32 | 33 | -------------------------------------------------------------------------------- /.gitatttributes: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------- 2 | # VisualStudio 3 | 4 | #-- User-specific files 5 | *.suo 6 | *.user 7 | *.vcxproj.user 8 | *.sln.docstates 9 | 10 | 11 | #-- Build results 12 | [Dd]ebug/ 13 | [Rr]elease/ 14 | x64/ 15 | x86/ 16 | #[Bb]in/ 17 | [Oo]bj/ 18 | *.pdb 19 | 20 | #-- Visual C++ cache files 21 | .vs/ 22 | ipch/ 23 | *.aps 24 | *.ncb 25 | *.opensdf 26 | *.sdf 27 | *.cachefile 28 | 29 | # Prerequisites 30 | *.d 31 | 32 | # Compiled Object files 33 | *.slo 34 | *.lo 35 | *.o 36 | *.obj 37 | 38 | # Precompiled Headers 39 | *.gch 40 | *.pch 41 | 42 | # Compiled Dynamic libraries 43 | *.so 44 | *.dylib 45 | *.dll 46 | 47 | # Fortran module files 48 | *.mod 49 | *.smod 50 | 51 | # Compiled Static libraries 52 | *.lai 53 | *.la 54 | *.a 55 | *.lib 56 | 57 | # Executables 58 | *.exe 59 | *.out 60 | *.app 61 | 62 | #default settings 63 | * text=auto 64 | *.txt text 65 | *.vcproj text eol=crlf 66 | *.sh text eol=lf 67 | *.jpg -text 68 | 69 | # Make UTF-16 files diff-able (looks a bit ugly, but nice to have) 70 | *.rc diff=set diff 71 | resource.h diff=set diff -------------------------------------------------------------------------------- /src/urlPlugin/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by urlPlugin.rc 4 | // 5 | #define IDD_DLG_ABOUT 101 6 | #define IDD_DLG_SETTING 102 7 | #define IDI_ICON_TOOLBAR 103 8 | #define IDC_WEB_SOURCE 1001 9 | #define IDC_WEB_ISSUE 1002 10 | #define IDC_GB_TITLE 1003 11 | #define IDC_SYSLINK_EMAIL 1004 12 | #define IDC_CHK_SAME_FILE 1006 13 | #define IDC_CHK_MULTILINE 1007 14 | #define IDC_EDT_DELIMITER 1008 15 | #define IDC_HOR_BAR_TOP 1009 16 | #define IDC_HOR_BAR_BOTTOM 1010 17 | #define IDC_CHK_RETAIN_LINE_FEED 1011 18 | #define IDC_CHK_CONTEXT_MENU 1012 19 | #define IDC_STC_DELIMETER 1013 20 | 21 | // Next default values for new objects 22 | // 23 | #ifdef APSTUDIO_INVOKED 24 | #ifndef APSTUDIO_READONLY_SYMBOLS 25 | #define _APS_NEXT_RESOURCE_VALUE 104 26 | #define _APS_NEXT_COMMAND_VALUE 40001 27 | #define _APS_NEXT_CONTROL_VALUE 1014 28 | #define _APS_NEXT_SYMED_VALUE 101 29 | #endif 30 | #endif 31 | -------------------------------------------------------------------------------- /src/utilityLib/Execute.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Execute.h" 3 | 4 | 5 | Execute::Execute(const TCHAR* cmd, const TCHAR* args, const TCHAR* cDir, bool show) : 6 | m_Command(cmd), m_Args(args), m_CurDir(cDir), m_bShow(show) 7 | { 8 | m_ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); 9 | m_ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; 10 | m_ShExecInfo.hwnd = NULL; 11 | m_ShExecInfo.lpFile = m_Command.c_str(); 12 | m_ShExecInfo.lpParameters = m_Args.c_str(); 13 | m_ShExecInfo.lpDirectory = m_CurDir.c_str(); 14 | m_ShExecInfo.nShow = show ? SW_SHOWNORMAL : SW_HIDE; 15 | m_ShExecInfo.hInstApp = NULL; 16 | } 17 | 18 | bool Execute::Run(bool isElevationRequired) 19 | { 20 | m_ShExecInfo.lpVerb = isElevationRequired ? TEXT("runas") : TEXT("open"); 21 | 22 | auto shellExecRes = ::ShellExecuteEx(&m_ShExecInfo); 23 | return shellExecRes ? false : true; 24 | } 25 | 26 | DWORD Execute::RunSync(bool isElevationRequired) 27 | { 28 | m_ShExecInfo.lpVerb = isElevationRequired ? TEXT("runas") : TEXT("open"); 29 | 30 | ShellExecuteEx(&m_ShExecInfo); 31 | WaitForSingleObject(m_ShExecInfo.hProcess, INFINITE); 32 | 33 | DWORD exitCode = 0; 34 | if (::GetExitCodeProcess(m_ShExecInfo.hProcess, &exitCode) == FALSE) 35 | { 36 | exitCode = GetLastError(); 37 | } 38 | 39 | return exitCode; 40 | } 41 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.2.0.{build} 2 | image: Visual Studio 2022 3 | 4 | 5 | environment: 6 | matrix: 7 | - PlatformToolset: v143 8 | 9 | platform: 10 | - x86 11 | - x64 12 | - arm64 13 | 14 | configuration: 15 | - Release 16 | - Debug 17 | 18 | install: 19 | - if "%platform%"=="x86" set platform_input=x86 20 | - if "%platform%"=="x64" set platform_input=x64 21 | - if "%platform%"=="arm64" set platform_input=arm64 22 | 23 | build: 24 | parallel: true # enable MSBuild parallel builds 25 | verbosity: minimal 26 | 27 | build_script: 28 | - cd "%APPVEYOR_BUILD_FOLDER%" 29 | - cd src 30 | - git submodule update --init --recursive 31 | - msbuild nppURLPlugin.sln /m /p:configuration="%configuration%" /p:platform="%platform_input%" /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" 32 | - cd .. 33 | - echo %CD% 34 | 35 | artifacts: 36 | - path: src\Build\Bin\Debug\Win32\urlPlugin.dll 37 | name: Debug-x86 38 | - path: \src\Build\Bin\Release\Win32\urlPlugin.dll 39 | name: Release-x86 40 | - path: src\Build\Bin\Debug\x64\urlPlugin.dll 41 | name: Debug-x64 42 | - path: src\Build\Bin\Release\x64\urlPlugin.dll 43 | name: Release-x64 44 | - path: src\Build\Bin\Debug\ARM64\urlPlugin.dll 45 | name: Debug-ARM64 46 | - path: \src\Build\Bin\Release\ARM64\urlPlugin.dll 47 | name: Release-ARM64 48 | -------------------------------------------------------------------------------- /src/utilityLib/Utility.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class CUtility 7 | { 8 | public: 9 | CUtility() = default; 10 | ~CUtility() = default; 11 | 12 | static std::wstring GetVersion(const std::wstring& filePath); 13 | 14 | static HWND CreateToolTip(HWND hWnd, int nCtrlID, const std::wstring& tooltipText, HINSTANCE hInst = nullptr); 15 | 16 | static float GetDesktopScale(HWND hWnd); 17 | 18 | static auto GetEditCtrlText(HWND hWnd)->std::wstring; 19 | static void SetEditCtrlText(HWND hWnd, const std::wstring& txt); 20 | 21 | static bool GetCheckboxStatus(HWND hWnd); 22 | static void SetCheckboxStatus(HWND hWnd, bool bCheck); 23 | 24 | static bool DirExist(const std::wstring& dirPath); 25 | static bool FileExist(const std::wstring& filePath); 26 | 27 | static long FileSize(const std::wstring& filePath); 28 | 29 | static bool CreateDir(const std::wstring& dirPath); 30 | static bool DeleteDir(const std::wstring& dirPath); 31 | 32 | static bool Copy(const std::wstring& srcFile, const std::wstring& dstFile); 33 | static bool Move(const std::wstring& srcFile, const std::wstring& dstFile); 34 | 35 | static auto GetFileName(const std::wstring& fullPath, bool withExtension = true)->std::wstring; 36 | static auto GetFileExtension(const std::wstring& fileName)->std::wstring; 37 | 38 | static auto GetTempFilePath()->std::wstring; 39 | static auto GetSpecialFolderLocation(int folderKind)->std::wstring; 40 | 41 | static bool OpenFileDlg(std::wstring& filePath, const std::wstring& dlgTitle, const std::vector& dlgFilter, DWORD flags = 0); 42 | 43 | }; 44 | 45 | -------------------------------------------------------------------------------- /src/utilityLib/utilityLib.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/urlPlugin/dllmain.cpp: -------------------------------------------------------------------------------- 1 | // dllmain.cpp : Defines the entry point for the DLL application. 2 | #include "PluginHelper.h" 3 | 4 | PluginHelper g_PluginHelper; 5 | BOOL APIENTRY DllMain( HMODULE hModule, 6 | DWORD ul_reason_for_call, 7 | LPVOID /*lpReserved*/ 8 | ) 9 | { 10 | switch (ul_reason_for_call) 11 | { 12 | case DLL_PROCESS_ATTACH: 13 | g_PluginHelper.PluginInit(hModule); 14 | break; 15 | 16 | case DLL_PROCESS_DETACH: 17 | g_PluginHelper.PluginCleanup(); 18 | break; 19 | 20 | case DLL_THREAD_ATTACH: 21 | case DLL_THREAD_DETACH: 22 | break; 23 | } 24 | return TRUE; 25 | } 26 | 27 | // Below are the mandatory function to be implemented as Notepad++ requires them 28 | 29 | extern "C" __declspec(dllexport) void setInfo(NppData notpadPlusData) 30 | { 31 | g_PluginHelper.SetInfo(notpadPlusData); 32 | } 33 | 34 | extern "C" __declspec(dllexport) const TCHAR * getName() 35 | { 36 | return g_PluginHelper.GetPluginName(); 37 | } 38 | 39 | extern "C" __declspec(dllexport) FuncItem * getFuncsArray(int* nbF) 40 | { 41 | return g_PluginHelper.GetFuncsArray(nbF); 42 | } 43 | 44 | extern "C" __declspec(dllexport) void beNotified(SCNotification * notifyCode) 45 | { 46 | g_PluginHelper.ProcessNotification(notifyCode); 47 | } 48 | 49 | // Here you can process the Npp Messages 50 | // I will make the messages accessible little by little, according to the need of plugin development. 51 | // Please let me know if you need to access to some messages : 52 | // http://sourceforge.net/forum/forum.php?forum_id=482781 53 | // 54 | extern "C" __declspec(dllexport) LRESULT messageProc(UINT msg, WPARAM wParam, LPARAM lParam) 55 | { 56 | return g_PluginHelper.MessageProc(msg, wParam, lParam); 57 | } 58 | 59 | #ifdef UNICODE 60 | extern "C" __declspec(dllexport) BOOL isUnicode() 61 | { 62 | return g_PluginHelper.IsUnicode(); 63 | } 64 | #endif //UNICODE -------------------------------------------------------------------------------- /src/urlPlugin/external/npp/PluginInterface.h: -------------------------------------------------------------------------------- 1 | // This file is part of Notepad++ project 2 | // Copyright (C)2021 Don HO 3 | 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // at your option any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #pragma once 19 | 20 | #include "Scintilla.h" 21 | #include "Notepad_plus_msgs.h" 22 | 23 | const int nbChar = 64; 24 | 25 | typedef const TCHAR * (__cdecl * PFUNCGETNAME)(); 26 | 27 | struct NppData 28 | { 29 | HWND _nppHandle = nullptr; 30 | HWND _scintillaMainHandle = nullptr; 31 | HWND _scintillaSecondHandle = nullptr; 32 | }; 33 | 34 | typedef void (__cdecl * PFUNCSETINFO)(NppData); 35 | typedef void (__cdecl * PFUNCPLUGINCMD)(); 36 | typedef void (__cdecl * PBENOTIFIED)(SCNotification *); 37 | typedef LRESULT (__cdecl * PMESSAGEPROC)(UINT Message, WPARAM wParam, LPARAM lParam); 38 | 39 | 40 | struct ShortcutKey 41 | { 42 | bool _isCtrl = false; 43 | bool _isAlt = false; 44 | bool _isShift = false; 45 | UCHAR _key = 0; 46 | }; 47 | 48 | struct FuncItem 49 | { 50 | TCHAR _itemName[nbChar] = { '\0' }; 51 | PFUNCPLUGINCMD _pFunc = nullptr; 52 | int _cmdID = 0; 53 | bool _init2Check = false; 54 | ShortcutKey *_pShKey = nullptr; 55 | }; 56 | 57 | typedef FuncItem * (__cdecl * PFUNCGETFUNCSARRAY)(int *); 58 | 59 | // You should implement (or define an empty function body) those functions which are called by Notepad++ plugin manager 60 | extern "C" __declspec(dllexport) void setInfo(NppData); 61 | extern "C" __declspec(dllexport) const TCHAR * getName(); 62 | extern "C" __declspec(dllexport) FuncItem * getFuncsArray(int *); 63 | extern "C" __declspec(dllexport) void beNotified(SCNotification *); 64 | extern "C" __declspec(dllexport) LRESULT messageProc(UINT Message, WPARAM wParam, LPARAM lParam); 65 | 66 | // This API return always true now, since Notepad++ isn't compiled in ANSI mode anymore 67 | extern "C" __declspec(dllexport) BOOL isUnicode(); 68 | 69 | -------------------------------------------------------------------------------- /src/urlPlugin/PluginHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "Define.h" 7 | #include "Notepad_plus_msgs.h" 8 | #include "ShortcutCommand.h" 9 | #include "AboutDlg.h" 10 | #include "SettingsDlg.h" 11 | #include "ScintillaEditor.h" 12 | 13 | 14 | class PluginHelper 15 | { 16 | public: 17 | PluginHelper(); 18 | ~PluginHelper() = default; 19 | 20 | void PluginInit(HMODULE hModule); 21 | void PluginCleanup(); 22 | 23 | // Notepad++ APIs to be implemented 24 | void SetInfo(const NppData& notpadPlusData); 25 | 26 | const TCHAR* GetPluginName() const; 27 | 28 | FuncItem* GetFuncsArray(int* nbF); 29 | 30 | void ProcessNotification(const SCNotification* notifyCode); 31 | 32 | LRESULT MessageProc(UINT msg, WPARAM wParam, LPARAM lParam); 33 | 34 | BOOL IsUnicode(); 35 | 36 | private: 37 | class Callback 38 | { 39 | friend class PluginHelper; 40 | static PluginHelper* m_pPluginHelper; 41 | public: 42 | Callback() = default; 43 | ~Callback() = default; 44 | 45 | static void ShowSettingDlg() { m_pPluginHelper->ShowSettingDlg(); } 46 | static void ShowAboutDlg() { m_pPluginHelper->ShowAboutDlg(); } 47 | static void EncodeURL() { m_pPluginHelper->EncodeURL(); } 48 | static void DecodeURL() { m_pPluginHelper->DecodeURL(); } 49 | }; 50 | 51 | void SetMenuIcon(); 52 | void SetMenuIcon(toolbarIconsWithDarkMode& tbIcons, CallBackID callbackID); 53 | void InitCommandMenu(); 54 | void InitToolbarIcon(); 55 | void InitToolbarIcon(toolbarIconsWithDarkMode& tbIcons, DWORD iconID); 56 | void InitConfigPath(); 57 | 58 | void ToggleMenuItemState(int nCmdId, bool bVisible); 59 | 60 | void ShowSettingDlg(); 61 | void ShowAboutDlg(); 62 | void EncodeURL(); 63 | void DecodeURL(); 64 | 65 | auto PreOperation()->std::optional; 66 | void PostOperation(const std::string& orgTxt, const std::string& converted, void* convertInfo, bool bEncode); 67 | 68 | bool InitScintilla(); 69 | void ShowError(ErrorCode err); 70 | 71 | const std::vector w2a(const std::vector& vec); 72 | 73 | private: 74 | HMODULE m_hModule = nullptr; 75 | toolbarIconsWithDarkMode m_hMenuIcon = {}; 76 | ShortcutCommand m_shortcutCommands; 77 | NppData m_NppData = {}; 78 | std::unique_ptr m_pSettingsDlg = nullptr; 79 | std::unique_ptr m_pAboutDlg = nullptr; 80 | std::unique_ptr m_pScintillaEditor = nullptr; 81 | std::wstring m_configPath; 82 | }; 83 | -------------------------------------------------------------------------------- /src/urlPlugin/external/npp/URLCtrl.h: -------------------------------------------------------------------------------- 1 | // This file is part of Notepad++ project 2 | // Copyright (C)2003 Don HO 3 | // 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either 7 | // version 2 of the License, or (at your option) any later version. 8 | // 9 | // Note that the GPL places important restrictions on "derived works", yet 10 | // it does not provide a detailed definition of that term. To avoid 11 | // misunderstandings, we consider an application to constitute a 12 | // "derivative work" for the purpose of this license if it does any of the 13 | // following: 14 | // 1. Integrates source code from Notepad++. 15 | // 2. Integrates/includes/aggregates Notepad++ into a proprietary executable 16 | // installer, such as those produced by InstallShield. 17 | // 3. Links to a library or executes a program that does any of the above. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU General Public License 25 | // along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | 28 | 29 | #pragma once 30 | 31 | #include "Window.h" 32 | #include 33 | 34 | class URLCtrl : public Window 35 | { 36 | public: 37 | URLCtrl() = default; 38 | 39 | void create(HWND itemHandle, const TCHAR* link, COLORREF linkColor = RGB(0, 0, 255)); 40 | void create(HWND itemHandle, int cmd, HWND msgDest = NULL); 41 | void destroy(); 42 | 43 | private: 44 | void action(); 45 | COLORREF getCtrlBgColor(HWND hWnd); 46 | 47 | protected: 48 | std::wstring _URL = TEXT(""); 49 | HFONT _hfUnderlined = nullptr; 50 | HCURSOR _hCursor = nullptr; 51 | HWND _msgDest = nullptr; 52 | unsigned long _cmdID = 0; 53 | 54 | WNDPROC _oldproc = nullptr; 55 | COLORREF _linkColor; 56 | COLORREF _visitedColor; 57 | bool _clicking = false; 58 | 59 | static LRESULT CALLBACK URLCtrlProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) 60 | { 61 | return (reinterpret_cast(::GetWindowLongPtr(hwnd, GWLP_USERDATA)))->runProc(hwnd, Message, wParam, lParam); 62 | } 63 | 64 | LRESULT runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam); 65 | }; 66 | 67 | -------------------------------------------------------------------------------- /src/urlPlugin/Define.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "PluginInterface.h" 3 | #include 4 | #include 5 | 6 | // Define the number of plugin commands here 7 | constexpr int nTotalCommandCount = 5; 8 | 9 | // Define plugin name here 10 | constexpr TCHAR PLUGIN_NAME[] = TEXT("URL Plugin"); 11 | 12 | // Text which can be considered for localization 13 | constexpr TCHAR TITLE_TOOLS_SETTING[] = TEXT("URL Plugin Settings"); 14 | 15 | constexpr TCHAR MENU_TOOLS_SETTING[] = TEXT("URL Plugin &Settings"); 16 | constexpr TCHAR MENU_ENCODE[] = TEXT("&Encode URL"); 17 | constexpr TCHAR MENU_DECODE[] = TEXT("&Decode URL"); 18 | constexpr TCHAR MENU_ABOUT[] = TEXT("&About"); 19 | constexpr TCHAR MENU_SEPERATOR[] = TEXT("-SEPARATOR-"); 20 | 21 | constexpr TCHAR URL_SOURCE_CODE[] = TEXT("https://github.com/SinghRajenM/nppURLPlugin"); 22 | constexpr TCHAR URL_REPORT_ISSUE[] = TEXT("https://github.com/SinghRajenM/nppURLPlugin/issues"); 23 | 24 | constexpr TCHAR STR_VERSION[] = TEXT("Version: "); 25 | 26 | constexpr TCHAR STR_PROFILE_NAME[] = TEXT("URLPlugin.ini"); 27 | constexpr TCHAR STR_PROFILE_PATH[] = TEXT("\\Notepad++\\plugins\\URLPlugin\\"); 28 | 29 | constexpr TCHAR STR_CONVERSION_SEPARATOR[] = TEXT(";"); 30 | 31 | constexpr TCHAR STR_INI_ENCODE_SEC[] = TEXT("ENCODE"); 32 | constexpr TCHAR STR_INI_ENCODE_SAMEFILE[] = TEXT("REPLACE_IN_SAME_FILE"); 33 | constexpr TCHAR STR_INI_ENCODE_CONTEXT[] = TEXT("ENABLE_CONTEXT"); 34 | constexpr TCHAR STR_INI_ENCODE_RETAIN_FEED[] = TEXT("RETAIN_FEED"); 35 | constexpr TCHAR STR_INI_ENCODE_EXCLUDE_TEXT[] = TEXT("EXCLUDE_TEXT"); 36 | 37 | constexpr TCHAR STR_INI_DECODE_SEC[] = TEXT("DECODE"); 38 | constexpr TCHAR STR_INI_DECODE_SAMEFILE[] = TEXT("REPLACE_IN_SAME_FILE"); 39 | constexpr TCHAR STR_INI_DECODE_CONTEXT[] = TEXT("ENABLE_CONTEXT"); 40 | constexpr TCHAR STR_INI_DECODE_BREAKLINE[] = TEXT("BREAKLINES"); 41 | constexpr TCHAR STR_INI_DECODE_BREAK_DELIMITER[] = TEXT("LINE_BREAK_DELIMITER"); 42 | constexpr TCHAR STR_INI_DECODE_EXCLUDE_TEXT[] = TEXT("EXCLUDE_TEXT"); 43 | 44 | struct CommonInfo 45 | { 46 | bool bCopyInSameFile = false; 47 | bool bEnableContextMenu = false; 48 | }; 49 | 50 | struct EncodeInfo :CommonInfo 51 | { 52 | bool bRetainLineFeed = false; 53 | std::vector exclusionSet; 54 | }; 55 | 56 | struct DecodeInfo :CommonInfo 57 | { 58 | bool bBreakLine = false; 59 | std::wstring strLineBreakDelimiter; 60 | std::vector exclusionSet; 61 | }; 62 | 63 | enum class ErrorCode { 64 | SCINTILLA_INIT, 65 | SCINTILLA_COPY, 66 | SCINTILLA_PASTE, 67 | SCINTILLA_NEW_FILE, 68 | 69 | CONVERT_ENCODE_UNKNOWN, 70 | CONVERT_DECODE_UNKNOWN, 71 | 72 | CONVERT_ENCODE_SAME, 73 | CONVERT_DECODE_SAME, 74 | }; 75 | -------------------------------------------------------------------------------- /src/urlPlugin/external/npp/StaticDialog.h: -------------------------------------------------------------------------------- 1 | // This file is part of Notepad++ project 2 | // Copyright (C)2003 Don HO 3 | // 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either 7 | // version 2 of the License, or (at your option) any later version. 8 | // 9 | // Note that the GPL places important restrictions on "derived works", yet 10 | // it does not provide a detailed definition of that term. To avoid 11 | // misunderstandings, we consider an application to constitute a 12 | // "derivative work" for the purpose of this license if it does any of the 13 | // following: 14 | // 1. Integrates source code from Notepad++. 15 | // 2. Integrates/includes/aggregates Notepad++ into a proprietary executable 16 | // installer, such as those produced by InstallShield. 17 | // 3. Links to a library or executes a program that does any of the above. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU General Public License 25 | // along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | #pragma once 28 | 29 | #include "Window.h" 30 | 31 | typedef HRESULT(WINAPI* ETDTProc) (HWND, DWORD); 32 | 33 | enum class PosAlign { left, right, top, bottom }; 34 | 35 | struct DLGTEMPLATEEX 36 | { 37 | WORD dlgVer; 38 | WORD signature; 39 | DWORD helpID; 40 | DWORD exStyle; 41 | DWORD style; 42 | WORD cDlgItems; 43 | short x; 44 | short y; 45 | short cx; 46 | short cy; 47 | // The structure has more fields but are variable length 48 | }; 49 | 50 | class StaticDialog : public Window 51 | { 52 | public: 53 | virtual ~StaticDialog(); 54 | 55 | virtual void create(int dialogID, bool isRTL = false, bool msgDestParent = true); 56 | 57 | virtual bool isCreated() const { return (_hSelf != NULL); } 58 | 59 | void goToCenter(); 60 | 61 | void display(bool toShow = true) const; 62 | 63 | POINT getTopPoint(HWND hwnd, bool isLeft = true) const; 64 | 65 | bool isCheckedOrNot(int checkControlID) const 66 | { 67 | return (BST_CHECKED == ::SendMessage(::GetDlgItem(_hSelf, checkControlID), BM_GETCHECK, 0, 0)); 68 | } 69 | 70 | virtual void destroy() override; 71 | 72 | protected: 73 | RECT _rc = {}; 74 | static INT_PTR CALLBACK dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 75 | virtual INT_PTR CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) = 0; 76 | 77 | void alignWith(HWND handle, HWND handle2Align, PosAlign pos, POINT & point); 78 | HGLOBAL makeRTLResource(int dialogID, DLGTEMPLATE **ppMyDlgTemplate); 79 | }; 80 | -------------------------------------------------------------------------------- /src/urlPlugin/external/npp/ControlsTab.h: -------------------------------------------------------------------------------- 1 | // This file is part of Notepad++ project 2 | // Copyright (C)2003 Don HO 3 | // 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either 7 | // version 2 of the License, or (at your option) any later version. 8 | // 9 | // Note that the GPL places important restrictions on "derived works", yet 10 | // it does not provide a detailed definition of that term. To avoid 11 | // misunderstandings, we consider an application to constitute a 12 | // "derivative work" for the purpose of this license if it does any of the 13 | // following: 14 | // 1. Integrates source code from Notepad++. 15 | // 2. Integrates/includes/aggregates Notepad++ into a proprietary executable 16 | // installer, such as those produced by InstallShield. 17 | // 3. Links to a library or executes a program that does any of the above. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU General Public License 25 | // along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | 28 | #ifndef CONTROLS_TAB_H 29 | #define CONTROLS_TAB_H 30 | 31 | #include 32 | #include 33 | 34 | #ifndef TAB_BAR_H 35 | #include "TabBar.h" 36 | #endif //TAB_BAR_H 37 | 38 | typedef std::basic_string generic_string; 39 | struct DlgInfo { 40 | Window *_dlg; 41 | generic_string _name; 42 | generic_string _internalName; 43 | 44 | DlgInfo(Window *dlg, const wchar_t *name, const wchar_t *internalName = NULL): _dlg(dlg), _name(name), _internalName(internalName?internalName:TEXT("")) {}; 45 | }; 46 | 47 | typedef std::vector WindowVector; 48 | 49 | class ControlsTab : public TabBar 50 | { 51 | public : 52 | ControlsTab() : TabBar(), _pWinVector(NULL), _current(0){}; 53 | ~ControlsTab(){}; 54 | 55 | void initTabBar(HINSTANCE hInst, HWND hwnd, bool isVertical = false, bool isTraditional = false, bool isMultiLine = false) override { 56 | _isVertical = isVertical; 57 | TabBar::initTabBar(hInst, hwnd, false, isTraditional, isMultiLine); 58 | }; 59 | void createTabs(WindowVector & winVector); 60 | 61 | void destroy() override { 62 | TabBar::destroy(); 63 | }; 64 | 65 | void reSizeTo(RECT & rc) override; 66 | void activateWindowAt(int index); 67 | 68 | void clickedUpdate() 69 | { 70 | int indexClicked = int(::SendMessage(_hSelf, TCM_GETCURSEL, 0, 0)); 71 | activateWindowAt(indexClicked); 72 | }; 73 | void renameTab(int index, const wchar_t *newName); 74 | bool renameTab(const wchar_t *internalName, const wchar_t *newName); 75 | 76 | private : 77 | WindowVector *_pWinVector; 78 | int _current; 79 | }; 80 | 81 | #endif //CONTROLS_TAB_H 82 | -------------------------------------------------------------------------------- /src/nppURLPlugin.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.1.32319.34 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "urlPlugin", "urlPlugin\urlPlugin.vcxproj", "{159FACFB-40AE-4D9F-B76A-325389E84EA3}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {8085352B-BABD-4447-95CC-57457EF895D1} = {8085352B-BABD-4447-95CC-57457EF895D1} 9 | EndProjectSection 10 | EndProject 11 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utilityLib", "utilityLib\utilityLib.vcxproj", "{8085352B-BABD-4447-95CC-57457EF895D1}" 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|ARM64 = Debug|ARM64 16 | Debug|x64 = Debug|x64 17 | Debug|x86 = Debug|x86 18 | Release|ARM64 = Release|ARM64 19 | Release|x64 = Release|x64 20 | Release|x86 = Release|x86 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {159FACFB-40AE-4D9F-B76A-325389E84EA3}.Debug|ARM64.ActiveCfg = Debug|ARM64 24 | {159FACFB-40AE-4D9F-B76A-325389E84EA3}.Debug|ARM64.Build.0 = Debug|ARM64 25 | {159FACFB-40AE-4D9F-B76A-325389E84EA3}.Debug|x64.ActiveCfg = Debug|x64 26 | {159FACFB-40AE-4D9F-B76A-325389E84EA3}.Debug|x64.Build.0 = Debug|x64 27 | {159FACFB-40AE-4D9F-B76A-325389E84EA3}.Debug|x86.ActiveCfg = Debug|Win32 28 | {159FACFB-40AE-4D9F-B76A-325389E84EA3}.Debug|x86.Build.0 = Debug|Win32 29 | {159FACFB-40AE-4D9F-B76A-325389E84EA3}.Release|ARM64.ActiveCfg = Release|ARM64 30 | {159FACFB-40AE-4D9F-B76A-325389E84EA3}.Release|ARM64.Build.0 = Release|ARM64 31 | {159FACFB-40AE-4D9F-B76A-325389E84EA3}.Release|x64.ActiveCfg = Release|x64 32 | {159FACFB-40AE-4D9F-B76A-325389E84EA3}.Release|x64.Build.0 = Release|x64 33 | {159FACFB-40AE-4D9F-B76A-325389E84EA3}.Release|x86.ActiveCfg = Release|Win32 34 | {159FACFB-40AE-4D9F-B76A-325389E84EA3}.Release|x86.Build.0 = Release|Win32 35 | {8085352B-BABD-4447-95CC-57457EF895D1}.Debug|ARM64.ActiveCfg = Debug|ARM64 36 | {8085352B-BABD-4447-95CC-57457EF895D1}.Debug|ARM64.Build.0 = Debug|ARM64 37 | {8085352B-BABD-4447-95CC-57457EF895D1}.Debug|x64.ActiveCfg = Debug|x64 38 | {8085352B-BABD-4447-95CC-57457EF895D1}.Debug|x64.Build.0 = Debug|x64 39 | {8085352B-BABD-4447-95CC-57457EF895D1}.Debug|x86.ActiveCfg = Debug|Win32 40 | {8085352B-BABD-4447-95CC-57457EF895D1}.Debug|x86.Build.0 = Debug|Win32 41 | {8085352B-BABD-4447-95CC-57457EF895D1}.Release|ARM64.ActiveCfg = Release|ARM64 42 | {8085352B-BABD-4447-95CC-57457EF895D1}.Release|ARM64.Build.0 = Release|ARM64 43 | {8085352B-BABD-4447-95CC-57457EF895D1}.Release|x64.ActiveCfg = Release|x64 44 | {8085352B-BABD-4447-95CC-57457EF895D1}.Release|x64.Build.0 = Release|x64 45 | {8085352B-BABD-4447-95CC-57457EF895D1}.Release|x86.ActiveCfg = Release|Win32 46 | {8085352B-BABD-4447-95CC-57457EF895D1}.Release|x86.Build.0 = Release|Win32 47 | EndGlobalSection 48 | GlobalSection(SolutionProperties) = preSolution 49 | HideSolutionNode = FALSE 50 | EndGlobalSection 51 | GlobalSection(ExtensibilityGlobals) = postSolution 52 | SolutionGuid = {73E75058-ED83-4CC0-BA95-2E9072D0AC3F} 53 | EndGlobalSection 54 | EndGlobal 55 | -------------------------------------------------------------------------------- /src/urlPlugin/external/npp/ControlsTab.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of Notepad++ project 2 | // Copyright (C)2003 Don HO 3 | // 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either 7 | // version 2 of the License, or (at your option) any later version. 8 | // 9 | // Note that the GPL places important restrictions on "derived works", yet 10 | // it does not provide a detailed definition of that term. To avoid 11 | // misunderstandings, we consider an application to constitute a 12 | // "derivative work" for the purpose of this license if it does any of the 13 | // following: 14 | // 1. Integrates source code from Notepad++. 15 | // 2. Integrates/includes/aggregates Notepad++ into a proprietary executable 16 | // installer, such as those produced by InstallShield. 17 | // 3. Links to a library or executes a program that does any of the above. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU General Public License 25 | // along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | 28 | #include "ControlsTab.h" 29 | #include 30 | 31 | void ControlsTab::createTabs(WindowVector & winVector) 32 | { 33 | _pWinVector = &winVector; 34 | 35 | for (int i = 0 ; i < int(winVector.size()) ; i++) 36 | TabBar::insertAtEnd(winVector[i]._name.c_str()); 37 | 38 | TabBar::activateAt(0); 39 | activateWindowAt(0); 40 | } 41 | 42 | void ControlsTab::activateWindowAt(int index) 43 | { 44 | if (index == _current) return; 45 | (*_pWinVector)[_current]._dlg->display(false); 46 | (*_pWinVector)[index]._dlg->display(true); 47 | _current = index; 48 | } 49 | 50 | void ControlsTab::reSizeTo(RECT & rc) 51 | { 52 | TabBar::reSizeTo(rc); 53 | rc.left += margeValue; 54 | rc.top += margeValue; 55 | 56 | //-- We do those dirty things 57 | //-- because it's a "vertical" tab control 58 | if (_isVertical) 59 | { 60 | rc.right -= 3; 61 | rc.bottom -= 20; 62 | if (getRowCount() == 2) 63 | { 64 | rc.right -= 20; 65 | } 66 | } 67 | //-- end of dirty things 68 | rc.bottom -= 45; 69 | rc.right -= 10; 70 | 71 | (*_pWinVector)[_current]._dlg->reSizeTo(rc); 72 | (*_pWinVector)[_current]._dlg->redraw(); 73 | } 74 | 75 | bool ControlsTab::renameTab(const wchar_t *internalName, const wchar_t *newName) 76 | { 77 | bool foundIt = false; 78 | int i = 0; 79 | for ( ; i < static_cast (_pWinVector->size()) ; i++) 80 | { 81 | if ((*_pWinVector)[i]._internalName == internalName) 82 | { 83 | foundIt = true; 84 | break; 85 | } 86 | } 87 | if (!foundIt) 88 | return false; 89 | 90 | renameTab(i, newName); 91 | return true; 92 | } 93 | 94 | void ControlsTab::renameTab(int index, const wchar_t *newName) 95 | { 96 | TCITEM tie; 97 | tie.mask = TCIF_TEXT; 98 | tie.pszText = (wchar_t *)newName; 99 | TabCtrl_SetItem(_hSelf, index, &tie); 100 | } -------------------------------------------------------------------------------- /src/urlPlugin/AboutDlg.cpp: -------------------------------------------------------------------------------- 1 | #include "AboutDlg.h" 2 | #include "resource.h" 3 | #include "Utility.h" 4 | #include "StringHelper.h" 5 | #include "Define.h" 6 | #include 7 | #include 8 | 9 | 10 | AboutDlg::AboutDlg(HINSTANCE hIntance, HWND hParent, int nCmdId) : m_nCmdId(nCmdId), StaticDialog() 11 | { 12 | init(hIntance, hParent); 13 | } 14 | 15 | 16 | bool AboutDlg::ShowDlg(bool bShow) 17 | { 18 | bool bShouldShow = bShow && !isVisible(); 19 | if (bShouldShow) 20 | { 21 | if (!isCreated()) 22 | create(IDD_DLG_ABOUT); 23 | 24 | // Adjust the position of AboutBox 25 | goToCenter(); 26 | } 27 | else 28 | { 29 | SendMessage(_hSelf, WM_COMMAND, IDCANCEL, NULL); 30 | } 31 | return bShouldShow; 32 | } 33 | 34 | 35 | INT_PTR AboutDlg::run_dlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) 36 | { 37 | AboutDlg* pSelf = nullptr; 38 | switch (uMsg) 39 | { 40 | case WM_INITDIALOG: 41 | { 42 | ::SetWindowLongPtr(_hSelf, DWLP_USER, lParam); 43 | 44 | pSelf = reinterpret_cast(static_cast (::GetWindowLongPtr(_hSelf, DWLP_USER))); 45 | if (pSelf) 46 | { 47 | pSelf->SetVersion(_hSelf); 48 | } 49 | SetFocus(GetDlgItem(_hSelf, IDOK)); 50 | 51 | // Set links 52 | std::wstring urlIssue(TEXT("__URL__")); 53 | std::wstring urlRepo = urlIssue; 54 | 55 | urlIssue = StringHelper::ReplaceAll(urlIssue, TEXT("__URL__"), URL_REPORT_ISSUE); 56 | urlRepo = StringHelper::ReplaceAll(urlRepo, TEXT("__URL__"), URL_SOURCE_CODE); 57 | 58 | SetWindowText(::GetDlgItem(_hSelf, IDC_WEB_ISSUE), urlIssue.c_str()); 59 | SetWindowText(::GetDlgItem(_hSelf, IDC_WEB_SOURCE), urlRepo.c_str()); 60 | 61 | return TRUE; 62 | } 63 | 64 | case WM_NOTIFY: 65 | { 66 | switch (reinterpret_cast(lParam)->code) 67 | { 68 | case NM_CLICK: 69 | case NM_RETURN: 70 | { 71 | auto nmLink = reinterpret_cast(lParam); 72 | LITEM item = nmLink->item; 73 | 74 | ShellExecute(nullptr, L"open", item.szUrl, nullptr, nullptr, SW_SHOW); 75 | return TRUE; 76 | } 77 | } 78 | return FALSE; 79 | } 80 | 81 | case WM_COMMAND: 82 | { 83 | pSelf = reinterpret_cast(static_cast (::GetWindowLongPtr(_hSelf, DWLP_USER))); 84 | switch (LOWORD(wParam)) 85 | { 86 | case IDCANCEL: // Close this dialog when clicking to close button 87 | case IDOK: 88 | if (pSelf) 89 | ::SendMessage(pSelf->_hParent, NPPM_SETMENUITEMCHECK, static_cast(pSelf->m_nCmdId), false); 90 | EndDialog(_hSelf, wParam); 91 | _hSelf = nullptr; 92 | return TRUE; 93 | } 94 | } 95 | } 96 | return FALSE; 97 | } 98 | 99 | void AboutDlg::SetVersion(HWND hWnd) 100 | { 101 | std::wstring version; 102 | 103 | // Get module path 104 | wchar_t moduleFileName[MAX_PATH + 1] = {}; 105 | ::GetModuleFileName(static_cast(getHinst()), moduleFileName, _MAX_PATH); 106 | 107 | version = CUtility::GetVersion(moduleFileName); 108 | if (!version.empty()) 109 | { 110 | std::wstring text(PLUGIN_NAME); 111 | text += TEXT(" ("); 112 | text += STR_VERSION; 113 | text += version; 114 | text += TEXT(") "); 115 | ::SetWindowText(::GetDlgItem(hWnd, IDC_GB_TITLE), text.c_str()); 116 | } 117 | } 118 | 119 | -------------------------------------------------------------------------------- /src/utilityLib/StringHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "StringHelper.h" 3 | #include 4 | 5 | std::string StringHelper::ReplaceAll(const std::string& str, const std::string& search, const std::string& replace) 6 | { 7 | return std::regex_replace(str, std::regex(search), replace); 8 | } 9 | 10 | std::wstring StringHelper::ReplaceAll(const std::wstring& wstr, const std::wstring& search, const std::wstring& replace) 11 | { 12 | return std::regex_replace(wstr, std::wregex(search), replace); 13 | } 14 | 15 | std::wstring StringHelper::ToWstring(const std::string& str, UINT codePage) 16 | { 17 | std::wstring wstr; 18 | 19 | if (!str.empty()) 20 | { 21 | auto required = ::MultiByteToWideChar(codePage, 0, str.data(), static_cast(str.size()), NULL, 0); 22 | if (0 != required) 23 | { 24 | wstr.resize(required); 25 | 26 | auto converted = ::MultiByteToWideChar(codePage, 0, str.data(), static_cast(str.size()), &wstr[0], static_cast(wstr.capacity())); 27 | if (0 == converted) 28 | { 29 | wstr.clear(); 30 | } 31 | } 32 | } 33 | 34 | return wstr; 35 | } 36 | 37 | std::string StringHelper::ToString(const std::wstring& wstr, UINT codePage) 38 | { 39 | std::string str; 40 | if (!wstr.empty()) 41 | { 42 | auto required = ::WideCharToMultiByte(codePage, 0, wstr.data(), static_cast(wstr.size()), NULL, 0, NULL, NULL); 43 | if (0 != required) 44 | { 45 | str.resize(required); 46 | 47 | auto converted = ::WideCharToMultiByte(codePage, 0, wstr.data(), static_cast(wstr.size()), &str[0], static_cast(str.capacity()), NULL, NULL); 48 | if (0 == converted) 49 | { 50 | str.clear(); 51 | } 52 | } 53 | } 54 | 55 | return str; 56 | } 57 | 58 | std::vector StringHelper::Split(const std::string& input, const std::string& delim) 59 | { 60 | //Vector is created on stack and copied on return 61 | std::vector tokens; 62 | 63 | // Skip delimiters at beginning. 64 | auto lastPos = input.find_first_not_of(delim, 0); 65 | // Find first "non-delimiter". 66 | auto pos = input.find_first_of(delim, lastPos); 67 | 68 | while (pos != std::string::npos || lastPos != std::string::npos) 69 | { 70 | // Found a token, add it to the vector. 71 | tokens.push_back(input.substr(lastPos, pos - lastPos)); 72 | // Skip delimiters. Note the "not_of" 73 | lastPos = input.find_first_not_of(delim, pos); 74 | // Find next "non-delimiter" 75 | pos = input.find_first_of(delim, lastPos); 76 | } 77 | return tokens; 78 | } 79 | 80 | std::vector StringHelper::Split(const std::wstring& input, const std::wstring& delim) 81 | { 82 | //Vector is created on stack and copied on return 83 | std::vector tokens; 84 | 85 | // Skip delimiters at beginning. 86 | auto lastPos = input.find_first_not_of(delim, 0); 87 | // Find first "non-delimiter". 88 | auto pos = input.find_first_of(delim, lastPos); 89 | 90 | while (pos != std::wstring::npos || lastPos != std::wstring::npos) 91 | { 92 | // Found a token, add it to the vector. 93 | tokens.push_back(input.substr(lastPos, pos - lastPos)); 94 | // Skip delimiters. Note the "not_of" 95 | lastPos = input.find_first_not_of(delim, pos); 96 | // Find next "non-delimiter" 97 | pos = input.find_first_of(delim, lastPos); 98 | } 99 | return tokens; 100 | } 101 | -------------------------------------------------------------------------------- /src/urlPlugin/external/npp/Window.h: -------------------------------------------------------------------------------- 1 | // This file is part of Notepad++ project 2 | // Copyright (C)2003 Don HO 3 | // 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either 7 | // version 2 of the License, or (at your option) any later version. 8 | // 9 | // Note that the GPL places important restrictions on "derived works", yet 10 | // it does not provide a detailed definition of that term. To avoid 11 | // misunderstandings, we consider an application to constitute a 12 | // "derivative work" for the purpose of this license if it does any of the 13 | // following: 14 | // 1. Integrates source code from Notepad++. 15 | // 2. Integrates/includes/aggregates Notepad++ into a proprietary executable 16 | // installer, such as those produced by InstallShield. 17 | // 3. Links to a library or executes a program that does any of the above. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU General Public License 25 | // along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | 28 | 29 | #pragma once 30 | #include 31 | 32 | class Window 33 | { 34 | public: 35 | //! \name Constructors & Destructor 36 | //@{ 37 | Window() = default; 38 | Window(const Window&) = delete; 39 | Window& operator = (const Window&) = delete; 40 | virtual ~Window() = default; 41 | //@} 42 | 43 | 44 | virtual void init(HINSTANCE hInst, HWND parent) 45 | { 46 | _hInst = hInst; 47 | _hParent = parent; 48 | } 49 | 50 | virtual void destroy() = 0; 51 | 52 | virtual void display(bool toShow = true) const { ::ShowWindow(_hSelf, toShow ? SW_SHOW : SW_HIDE); } 53 | 54 | 55 | virtual void reSizeTo(RECT & rc) // should NEVER be const !!! 56 | { 57 | ::MoveWindow(_hSelf, rc.left, rc.top, rc.right, rc.bottom, TRUE); 58 | redraw(); 59 | } 60 | 61 | 62 | virtual void reSizeToWH(RECT & rc) // should NEVER be const !!! 63 | { 64 | ::MoveWindow(_hSelf, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE); 65 | redraw(); 66 | } 67 | 68 | 69 | virtual void redraw(bool forceUpdate = false) const 70 | { 71 | ::InvalidateRect(_hSelf, nullptr, TRUE); 72 | if (forceUpdate) 73 | ::UpdateWindow(_hSelf); 74 | } 75 | 76 | 77 | virtual void getClientRect(RECT & rc) const { ::GetClientRect(_hSelf, &rc); } 78 | 79 | virtual void getWindowRect(RECT & rc) const { ::GetWindowRect(_hSelf, &rc); } 80 | 81 | virtual int getWidth() const 82 | { 83 | RECT rc; 84 | ::GetClientRect(_hSelf, &rc); 85 | return (rc.right - rc.left); 86 | } 87 | 88 | virtual int getHeight() const 89 | { 90 | RECT rc; 91 | ::GetClientRect(_hSelf, &rc); 92 | if (::IsWindowVisible(_hSelf) == TRUE) 93 | return (rc.bottom - rc.top); 94 | return 0; 95 | } 96 | 97 | virtual bool isVisible() const { return (::IsWindowVisible(_hSelf) ? true : false); } 98 | 99 | HWND getHSelf() const { return _hSelf; } 100 | 101 | HWND getHParent() const { return _hParent; } 102 | 103 | void getFocus() const { ::SetFocus(_hSelf); } 104 | 105 | HINSTANCE getHinst() const { return _hInst; } 106 | 107 | protected: 108 | HINSTANCE _hInst = NULL; 109 | HWND _hParent = NULL; 110 | HWND _hSelf = NULL; 111 | }; 112 | -------------------------------------------------------------------------------- /src/urlPlugin/urlPlugin.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {5d21a051-e62e-4d9e-adf7-34f5745f9eb3} 18 | 19 | 20 | {d89a15c2-bb36-4bee-9f13-c23be88a3a20} 21 | 22 | 23 | 24 | 25 | ThirdParty\npp 26 | 27 | 28 | ThirdParty\npp 29 | 30 | 31 | ThirdParty\npp 32 | 33 | 34 | ThirdParty\npp 35 | 36 | 37 | ThirdParty\npp 38 | 39 | 40 | ThirdParty\npp 41 | 42 | 43 | ThirdParty\npp 44 | 45 | 46 | ThirdParty\npp 47 | 48 | 49 | ThirdParty\npp 50 | 51 | 52 | Header Files 53 | 54 | 55 | Header Files 56 | 57 | 58 | Header Files 59 | 60 | 61 | Header Files 62 | 63 | 64 | Header Files 65 | 66 | 67 | Header Files 68 | 69 | 70 | Header Files 71 | 72 | 73 | Header Files 74 | 75 | 76 | Header Files 77 | 78 | 79 | 80 | 81 | Source Files 82 | 83 | 84 | ThirdParty\npp 85 | 86 | 87 | ThirdParty\npp 88 | 89 | 90 | ThirdParty\npp 91 | 92 | 93 | ThirdParty\npp 94 | 95 | 96 | Source Files 97 | 98 | 99 | Source Files 100 | 101 | 102 | Source Files 103 | 104 | 105 | Source Files 106 | 107 | 108 | Source Files 109 | 110 | 111 | Source Files 112 | 113 | 114 | 115 | 116 | Resource Files 117 | 118 | 119 | 120 | 121 | Resource Files 122 | 123 | 124 | -------------------------------------------------------------------------------- /src/urlPlugin/ScintillaEditor.cpp: -------------------------------------------------------------------------------- 1 | #include "ScintillaEditor.h" 2 | #include "menuCmdID.h" 3 | #include 4 | #include 5 | 6 | ScintillaEditor::ScintillaEditor(const NppData& nppData) : m_NppData(nppData) 7 | { 8 | int which = -1; 9 | ::SendMessage(m_NppData._nppHandle, NPPM_GETCURRENTSCINTILLA, 0, reinterpret_cast(&which)); 10 | assert(which != -1); 11 | if (which != -1) 12 | m_hScintilla = (which == 0) ? m_NppData._scintillaMainHandle : m_NppData._scintillaSecondHandle; 13 | } 14 | 15 | auto ScintillaEditor::GetSelectedText() const -> std::string 16 | { 17 | if (!m_hScintilla) 18 | return std::string(); 19 | 20 | // Get the required length 21 | auto length = Execute(SCI_GETLENGTH); 22 | 23 | auto pData = std::make_unique(length + 1); 24 | GetSelectedText(pData.get(), static_cast(length + 1), false); 25 | 26 | return pData ? pData.get() : ""; 27 | } 28 | 29 | bool ScintillaEditor::ReplaceSelectedText(const std::string& replaceText) const 30 | { 31 | return Execute(SCI_REPLACESEL, 0, reinterpret_cast(replaceText.c_str())) == 0; 32 | } 33 | 34 | bool ScintillaEditor::PasteSelectedOnNewFile(const std::string& text) const 35 | { 36 | // Open a new document 37 | bool bRetVal = ::SendMessage(m_NppData._nppHandle, NPPM_MENUCOMMAND, 0, IDM_FILE_NEW) ? true : false; 38 | 39 | // Paste the text 40 | auto res = Execute(SCI_SETTEXT, 0, reinterpret_cast(text.c_str())); 41 | bRetVal &= res == 1; 42 | 43 | // Set file's language Javascript 44 | bRetVal &= ::SendMessage(m_NppData._nppHandle, NPPM_MENUCOMMAND, 0, IDM_LANG_JS) ? true : false; 45 | 46 | return bRetVal; 47 | } 48 | 49 | std::wstring ScintillaEditor::GetFullFilePath() const 50 | { 51 | std::wstring retVal; 52 | 53 | auto pFilePath = std::make_unique(MAX_PATH * 2); 54 | ::SendMessage(m_NppData._nppHandle, NPPM_GETFULLCURRENTPATH, 0, reinterpret_cast(pFilePath.get())); 55 | 56 | if (pFilePath) 57 | retVal = pFilePath.get(); 58 | 59 | return retVal; 60 | } 61 | 62 | bool ScintillaEditor::OpenFile(const std::wstring& filePath) const 63 | { 64 | bool retVal; 65 | retVal = ::SendMessage(m_NppData._nppHandle, NPPM_DOOPEN, 0, reinterpret_cast(filePath.data())) ? true : false; 66 | return retVal; 67 | } 68 | 69 | LRESULT ScintillaEditor::Execute(UINT Msg, WPARAM wParam, LPARAM lParam) const 70 | { 71 | if (!m_hScintilla) 72 | return -1; 73 | 74 | try 75 | { 76 | return ::SendMessage(m_hScintilla, Msg, wParam, lParam); 77 | } 78 | catch (...) 79 | { 80 | return -1; 81 | } 82 | } 83 | 84 | Sci_CharacterRange ScintillaEditor::GetSelection() const 85 | { 86 | Sci_CharacterRange crange; 87 | crange.cpMin = static_cast(Execute(SCI_GETSELECTIONSTART)); 88 | crange.cpMax = static_cast(Execute(SCI_GETSELECTIONEND)); 89 | return crange; 90 | } 91 | 92 | char* ScintillaEditor::GetSelectedText(char* txt, int size, bool expand) const 93 | { 94 | if (!size) 95 | return NULL; 96 | Sci_CharacterRange range = GetSelection(); 97 | if (range.cpMax == range.cpMin && expand) 98 | { 99 | ExpandWordSelection(); 100 | range = GetSelection(); 101 | } 102 | if (!(static_cast(size) > (range.cpMax - range.cpMin))) //there must be atleast 1 byte left for zero terminator 103 | { 104 | range.cpMax = range.cpMin + size - 1; //keep room for zero terminator 105 | } 106 | 107 | return GetWordFromRange(txt, size, range.cpMin, range.cpMax); 108 | } 109 | 110 | bool ScintillaEditor::ExpandWordSelection() const 111 | { 112 | std::pair wordRange = GetWordRange(); 113 | if (wordRange.first != wordRange.second) 114 | { 115 | Execute(SCI_SETSELECTIONSTART, wordRange.first); 116 | Execute(SCI_SETSELECTIONEND, wordRange.second); 117 | return true; 118 | } 119 | return false; 120 | } 121 | 122 | auto ScintillaEditor::GetWordRange() const -> std::pair 123 | { 124 | auto caretPos = Execute(SCI_GETCURRENTPOS, 0, 0); 125 | int startPos = static_cast(Execute(SCI_WORDSTARTPOSITION, caretPos, true)); 126 | int endPos = static_cast(Execute(SCI_WORDENDPOSITION, caretPos, true)); 127 | return std::pair(startPos, endPos); 128 | } 129 | 130 | auto ScintillaEditor::GetWordFromRange(char* txt, size_t size, size_t pos1, size_t pos2) const-> char* 131 | { 132 | if (!size) 133 | return NULL; 134 | if (pos1 > pos2) 135 | { 136 | auto tmp = pos1; 137 | pos1 = pos2; 138 | pos2 = tmp; 139 | } 140 | 141 | if (size < pos2 - pos1) 142 | return NULL; 143 | 144 | GetText(txt, pos1, pos2); 145 | return txt; 146 | } 147 | 148 | void ScintillaEditor::GetText(char* dest, size_t start, size_t end) const 149 | { 150 | Sci_TextRange tr; 151 | tr.chrg.cpMin = static_cast(start); 152 | tr.chrg.cpMax = static_cast(end); 153 | tr.lpstrText = dest; 154 | Execute(SCI_GETTEXTRANGE, 0, reinterpret_cast(&tr)); 155 | } 156 | 157 | -------------------------------------------------------------------------------- /src/urlPlugin/Profile.cpp: -------------------------------------------------------------------------------- 1 | #include "Profile.h" 2 | #include "Utility.h" 3 | #include "StringHelper.h" 4 | #include 5 | #include 6 | 7 | Profile::Profile(const std::wstring& path) 8 | : m_ProfileFilePath(path) 9 | { 10 | Init(); 11 | } 12 | 13 | bool Profile::ReadValue(const std::wstring& section, const std::wstring& key, std::wstring& retVal, const std::wstring& defaultVal) const 14 | { 15 | bool bRetVal = false; 16 | 17 | // Try with MAX_PATH 18 | constexpr DWORD nBufSize = MAX_PATH * 2; 19 | auto pData = std::make_unique(nBufSize); 20 | GetPrivateProfileString(section.c_str(), key.c_str(), defaultVal.c_str(), pData.get(), nBufSize, m_ProfileFilePath.c_str()); 21 | 22 | if (pData) 23 | { 24 | bRetVal = true; 25 | retVal = pData.get(); 26 | } 27 | 28 | return bRetVal; 29 | } 30 | 31 | bool Profile::WriteValue(const std::wstring& section, const std::wstring& key, const std::wstring& value) const 32 | { 33 | return WritePrivateProfileString(section.c_str(), key.c_str(), value.c_str(), m_ProfileFilePath.c_str()) ? true : false; 34 | } 35 | 36 | void Profile::Init() 37 | { 38 | // Move exiting config file 39 | // from "%appdata%\\Notepad++\\plugins\\URLPlugin" 40 | // to default plugin folder 41 | 42 | auto oldProfileDir = CUtility::GetSpecialFolderLocation(CSIDL_APPDATA); 43 | if (!oldProfileDir.empty() && !m_ProfileFilePath.empty()) 44 | { 45 | oldProfileDir += STR_PROFILE_PATH; 46 | 47 | auto oldProfilePath = oldProfileDir + STR_PROFILE_NAME; 48 | if (CUtility::FileExist(oldProfilePath)) 49 | { 50 | CUtility::Move(oldProfilePath, m_ProfileFilePath); 51 | } 52 | 53 | CUtility::DeleteDir(oldProfileDir); 54 | } 55 | } 56 | 57 | bool ProfileEncode::GetInfo(EncodeInfo& info) const 58 | { 59 | bool bRetVal = true; 60 | 61 | std::wstring txt; 62 | bRetVal &= ReadValue(STR_INI_ENCODE_SEC, STR_INI_ENCODE_SAMEFILE, txt); 63 | if (bRetVal && txt == L"1") 64 | info.bCopyInSameFile = true; 65 | 66 | bRetVal &= ReadValue(STR_INI_ENCODE_SEC, STR_INI_ENCODE_CONTEXT, txt); 67 | if (bRetVal && txt == L"1") 68 | info.bEnableContextMenu = true; 69 | 70 | txt = L""; 71 | bRetVal &= ReadValue(STR_INI_ENCODE_SEC, STR_INI_ENCODE_RETAIN_FEED, txt); 72 | if (bRetVal && txt == L"1") 73 | info.bRetainLineFeed = true; 74 | 75 | txt = L""; 76 | bRetVal &= ReadValue(STR_INI_ENCODE_SEC, STR_INI_ENCODE_EXCLUDE_TEXT, txt); 77 | if (bRetVal && !txt.empty()) 78 | info.exclusionSet = StringHelper::Split(txt, L";"); 79 | 80 | return bRetVal; 81 | } 82 | 83 | bool ProfileEncode::SetInfo(const EncodeInfo& info) const 84 | { 85 | bool bRetVal = true; 86 | 87 | bRetVal &= WriteValue(STR_INI_ENCODE_SEC, STR_INI_ENCODE_SAMEFILE, info.bCopyInSameFile ? L"1" : L"0"); 88 | bRetVal &= WriteValue(STR_INI_ENCODE_SEC, STR_INI_ENCODE_CONTEXT, info.bEnableContextMenu ? L"1" : L"0"); 89 | bRetVal &= WriteValue(STR_INI_ENCODE_SEC, STR_INI_ENCODE_RETAIN_FEED, info.bRetainLineFeed ? L"1" : L"0"); 90 | 91 | std::wstring txt; 92 | for (const auto& ch : info.exclusionSet) 93 | txt += ch + STR_CONVERSION_SEPARATOR; 94 | bRetVal &= WriteValue(STR_INI_ENCODE_SEC, STR_INI_ENCODE_EXCLUDE_TEXT, txt); 95 | 96 | return bRetVal; 97 | } 98 | 99 | bool ProfileDecode::GetInfo(DecodeInfo& info) const 100 | { 101 | bool bRetVal = true; 102 | 103 | std::wstring txt; 104 | bRetVal &= ReadValue(STR_INI_DECODE_SEC, STR_INI_DECODE_SAMEFILE, txt); 105 | if (bRetVal && txt == L"1") 106 | info.bCopyInSameFile = true; 107 | 108 | bRetVal &= ReadValue(STR_INI_DECODE_SEC, STR_INI_DECODE_CONTEXT, txt); 109 | if (bRetVal && txt == L"1") 110 | info.bEnableContextMenu = true; 111 | 112 | txt = L""; 113 | bRetVal &= ReadValue(STR_INI_DECODE_SEC, STR_INI_DECODE_BREAKLINE, txt); 114 | if (bRetVal && txt == L"1") 115 | info.bBreakLine = true; 116 | 117 | txt = L""; 118 | bRetVal &= ReadValue(STR_INI_DECODE_SEC, STR_INI_DECODE_BREAK_DELIMITER, txt); 119 | if (bRetVal && !txt.empty()) 120 | info.strLineBreakDelimiter = txt; 121 | 122 | txt = L""; 123 | bRetVal &= ReadValue(STR_INI_DECODE_SEC, STR_INI_ENCODE_EXCLUDE_TEXT, txt); 124 | if (bRetVal && !txt.empty()) 125 | info.exclusionSet = StringHelper::Split(txt, L";"); 126 | 127 | return bRetVal; 128 | } 129 | 130 | bool ProfileDecode::SetInfo(const DecodeInfo& info) const 131 | { 132 | bool bRetVal = true; 133 | 134 | bRetVal &= WriteValue(STR_INI_DECODE_SEC, STR_INI_DECODE_SAMEFILE, info.bCopyInSameFile ? L"1" : L"0"); 135 | bRetVal &= WriteValue(STR_INI_DECODE_SEC, STR_INI_DECODE_CONTEXT, info.bEnableContextMenu ? L"1" : L"0"); 136 | bRetVal &= WriteValue(STR_INI_DECODE_SEC, STR_INI_DECODE_BREAKLINE, info.bBreakLine ? L"1" : L"0"); 137 | bRetVal &= WriteValue(STR_INI_DECODE_SEC, STR_INI_DECODE_BREAK_DELIMITER, info.strLineBreakDelimiter); 138 | 139 | std::wstring txt; 140 | for (const auto& ch : info.exclusionSet) 141 | txt += ch + STR_CONVERSION_SEPARATOR; 142 | bRetVal &= WriteValue(STR_INI_DECODE_SEC, STR_INI_DECODE_EXCLUDE_TEXT, txt); 143 | 144 | return bRetVal; 145 | } -------------------------------------------------------------------------------- /src/urlPlugin/SettingsDlg.cpp: -------------------------------------------------------------------------------- 1 | #include "SettingsDlg.h" 2 | #include "resource.h" 3 | #include "Utility.h" 4 | #include "StringHelper.h" 5 | #include "Profile.h" 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | SettingsDlg::SettingsDlg(HINSTANCE hIntance, HWND hParent, int nCmdId, const std::wstring& configPath) 12 | : m_nCmdId(nCmdId) 13 | , m_configPath(configPath) 14 | , StaticDialog() 15 | { 16 | init(hIntance, hParent); 17 | } 18 | 19 | 20 | bool SettingsDlg::ShowDlg(bool bShow) 21 | { 22 | bool bShouldShow = bShow && !isVisible(); 23 | if (bShouldShow) 24 | { 25 | if (!isCreated()) 26 | create(IDD_DLG_SETTING); 27 | 28 | // Adjust the position of AboutBox 29 | goToCenter(); 30 | } 31 | else 32 | { 33 | SendMessage(_hSelf, WM_COMMAND, IDCANCEL, NULL); 34 | } 35 | return bShouldShow; 36 | } 37 | 38 | INT_PTR SettingsDlg::run_dlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) 39 | { 40 | switch (uMsg) 41 | { 42 | case WM_INITDIALOG: 43 | { 44 | ::SetWindowLongPtr(_hSelf, DWLP_USER, lParam); 45 | 46 | auto enable_dlg_theme = reinterpret_cast(::SendMessage(_hParent, NPPM_GETENABLETHEMETEXTUREFUNC, 0, 0)); 47 | if (enable_dlg_theme != nullptr) 48 | enable_dlg_theme(_hSelf, ETDT_ENABLETAB); 49 | 50 | InitDlg(); 51 | 52 | SetFocus(GetDlgItem(_hSelf, IDOK)); 53 | 54 | return TRUE; 55 | } 56 | 57 | case WM_COMMAND: 58 | { 59 | switch (LOWORD(wParam)) 60 | { 61 | case IDOK: 62 | if (Apply()) 63 | { 64 | ::SendMessage(_hParent, NPPM_SETMENUITEMCHECK, static_cast(m_nCmdId), false); 65 | EndDialog(_hSelf, wParam); 66 | } 67 | else 68 | { 69 | ::MessageBox(_hSelf, L"Failed to save the setting. Please try again.", 70 | L"Setting Save Error", MB_OK | MB_ICONERROR); 71 | } 72 | return TRUE; 73 | 74 | case IDCANCEL: // Close this dialog when clicking to close button 75 | ::SendMessage(_hParent, NPPM_SETMENUITEMCHECK, static_cast(m_nCmdId), false); 76 | EndDialog(_hSelf, wParam); 77 | return TRUE; 78 | 79 | case IDC_CHK_MULTILINE: 80 | EnableDelimter(CUtility::GetCheckboxStatus(::GetDlgItem(_hSelf, IDC_CHK_MULTILINE))); 81 | return TRUE; 82 | } 83 | } 84 | } 85 | return FALSE; 86 | } 87 | 88 | bool SettingsDlg::Apply() 89 | { 90 | // Get all the data from the UI 91 | 92 | // Common setting 93 | m_EncodeInfo.bCopyInSameFile = CUtility::GetCheckboxStatus(::GetDlgItem(_hSelf, IDC_CHK_SAME_FILE)); 94 | m_DecodeInfo.bCopyInSameFile = m_EncodeInfo.bCopyInSameFile; 95 | 96 | // Encode setting 97 | m_EncodeInfo.bRetainLineFeed = CUtility::GetCheckboxStatus(::GetDlgItem(_hSelf, IDC_CHK_RETAIN_LINE_FEED)); 98 | 99 | // Decode Setting 100 | m_DecodeInfo.bBreakLine = CUtility::GetCheckboxStatus(::GetDlgItem(_hSelf, IDC_CHK_MULTILINE)); 101 | m_DecodeInfo.strLineBreakDelimiter = CUtility::GetEditCtrlText(::GetDlgItem(_hSelf, IDC_EDT_DELIMITER)); 102 | 103 | // For both 104 | FillExclusionSet(); 105 | 106 | return WriteINI(); 107 | } 108 | 109 | void SettingsDlg::destroy() 110 | { 111 | } 112 | 113 | bool SettingsDlg::ReadINI() 114 | { 115 | return ProfileEncode(m_configPath).GetInfo(m_EncodeInfo) && ProfileDecode(m_configPath).GetInfo(m_DecodeInfo); 116 | } 117 | 118 | bool SettingsDlg::WriteINI() 119 | { 120 | return ProfileEncode(m_configPath).SetInfo(m_EncodeInfo) && ProfileDecode(m_configPath).SetInfo(m_DecodeInfo); 121 | } 122 | 123 | void SettingsDlg::InitDlg() 124 | { 125 | ReadINI(); 126 | 127 | // Common setting goes here 128 | CUtility::SetCheckboxStatus(::GetDlgItem(_hSelf, IDC_CHK_SAME_FILE), m_DecodeInfo.bCopyInSameFile); 129 | 130 | // Encode setting 131 | CUtility::SetCheckboxStatus(::GetDlgItem(_hSelf, IDC_CHK_RETAIN_LINE_FEED), m_EncodeInfo.bRetainLineFeed); 132 | 133 | // Decode Setting 134 | CUtility::SetCheckboxStatus(::GetDlgItem(_hSelf, IDC_CHK_MULTILINE), m_DecodeInfo.bBreakLine); 135 | EnableDelimter(m_DecodeInfo.bBreakLine); 136 | 137 | // For both 138 | DisplayExclusionSet(); 139 | } 140 | 141 | void SettingsDlg::EnableDelimter(bool enable) 142 | { 143 | EnableWindow(::GetDlgItem(_hSelf, IDC_EDT_DELIMITER), enable); 144 | EnableWindow(::GetDlgItem(_hSelf, IDC_STC_DELIMETER), enable); 145 | 146 | CUtility::SetEditCtrlText(::GetDlgItem(_hSelf, IDC_EDT_DELIMITER), enable ? m_DecodeInfo.strLineBreakDelimiter : L""); 147 | } 148 | 149 | void SettingsDlg::FillExclusionSet() 150 | { 151 | auto fill = [&](UINT ctrlID, std::vector& data) { 152 | std::wstring txt = CUtility::GetEditCtrlText(::GetDlgItem(_hSelf, ctrlID)); 153 | data = StringHelper::Split(txt, L"\r\n"); // because of multiline edit control 154 | }; 155 | 156 | //fill(IDC_EDT_EXCLUDE_ENCODE, m_EncodeInfo.exclusionSet); 157 | //fill(IDC_EDT_EXCLUDE_DECODE, m_DecodeInfo.exclusionSet); 158 | } 159 | 160 | void SettingsDlg::DisplayExclusionSet() 161 | { 162 | auto fill = [&](UINT ctrlID, const std::vector& data) { 163 | std::wstring txt; 164 | for (const auto& item : data) 165 | txt += item + L"\r\n"; // because of multiline edit control 166 | 167 | CUtility::SetEditCtrlText(::GetDlgItem(_hSelf, ctrlID), txt); 168 | }; 169 | 170 | //fill(IDC_EDT_EXCLUDE_ENCODE, m_EncodeInfo.exclusionSet); 171 | //fill(IDC_EDT_EXCLUDE_DECODE, m_DecodeInfo.exclusionSet); 172 | } 173 | 174 | -------------------------------------------------------------------------------- /src/urlPlugin/URL.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | class EncodeDecodeBase 10 | { 11 | protected: 12 | std::map _parameters; 13 | std::string _baseUrl; // Eg: http://example.com 14 | std::string _url; // Eg: http://example.com?key1=val1&key2=val2 15 | std::vector _exclusionSet; 16 | 17 | public: 18 | 19 | EncodeDecodeBase() = default; 20 | virtual ~EncodeDecodeBase() = default; 21 | 22 | virtual void setParameter(const std::pair& pair) 23 | { 24 | setParameter(pair.first, pair.second); 25 | } 26 | 27 | virtual void setParameter(const std::string& key, const std::string& val) 28 | { 29 | _parameters[key] = val; 30 | } 31 | 32 | virtual void clear() 33 | { 34 | _baseUrl.clear(); 35 | _parameters.clear(); 36 | _url.clear(); 37 | } 38 | 39 | virtual size_t removeParameter(const std::string& key) 40 | { 41 | return _parameters.erase(key); 42 | } 43 | 44 | virtual void setBaseUrl(const std::string& baseUrl) 45 | { 46 | _baseUrl = baseUrl; 47 | } 48 | 49 | virtual const std::string& getBaseUrl() const 50 | { 51 | return _baseUrl; 52 | } 53 | 54 | virtual void setUrl(const std::string& url) 55 | { 56 | _url = url; 57 | } 58 | 59 | virtual const std::string& getUrl() const 60 | { 61 | return _url; 62 | } 63 | 64 | virtual void setExclusion(const std::vector& exclusion) 65 | { 66 | _exclusionSet = exclusion; 67 | } 68 | 69 | virtual const std::vector& getExclusion() const 70 | { 71 | return _exclusionSet; 72 | } 73 | 74 | virtual const std::map& getParameters() const 75 | { 76 | return _parameters; 77 | } 78 | }; 79 | 80 | 81 | class Encode : public EncodeDecodeBase 82 | { 83 | const std::string& encode(const std::string& aString, bool bRetainLineFeed) 84 | { 85 | std::string aEncodedString = ""; 86 | 87 | // Does starts with https:// or http://, then find base URL till ? 88 | std::string https[] = { "http://", "https://" }; 89 | 90 | for (const auto& h : https) 91 | { 92 | // aString starts with http or https 93 | if (aString.rfind(h) == 0) 94 | { 95 | auto posOfQMark = aString.find_first_of('?'); 96 | if (posOfQMark != std::string::npos) 97 | { 98 | // Everything prior to ? is the baseUrl 99 | _baseUrl = aString.substr(0, posOfQMark); 100 | aEncodedString = aString.substr(0, posOfQMark + 1); 101 | 102 | _url = aString.substr(posOfQMark + 1); 103 | } 104 | break; 105 | } 106 | } 107 | 108 | for (char aChar : aString) 109 | { 110 | // Ignore below whitespaces and retain space which will be converted 111 | /* 112 | '\n' : newline, 113 | '\t' : horizontal tab, 114 | '\v' : vertical tab 115 | '\r' : Carraige return 116 | '\f' : form feed 117 | */ 118 | if (std::isspace(aChar) && aChar != ' ' && bRetainLineFeed == false) 119 | continue; 120 | 121 | char allowedChars[] = { '-', '_', '.','~','&', '=', '+', }; 122 | 123 | if (!std::isalnum(aChar) && !(std::any_of(std::begin(allowedChars), std::end(allowedChars), [aChar](const char c) {return aChar == c; }))) 124 | { 125 | // Hex encode 126 | aEncodedString += "%"; 127 | std::stringstream ss; 128 | ss << std::hex << (int)aChar; 129 | std::string aTempStr = ss.str(); 130 | /* Apparently two overloaded toupper methods exist. 131 | * One in the std namespace and one in the global namespace 132 | * Good going C++, you god damned cryptic esoteric parseltongue 133 | */ 134 | std::transform(aTempStr.begin(), aTempStr.end(), aTempStr.begin(), 135 | [](char c) {return static_cast(std::toupper(c)); }); 136 | aEncodedString += aTempStr; 137 | } 138 | else 139 | { 140 | //Otherwise, keep it as it is 141 | aEncodedString += aChar; 142 | } 143 | } 144 | _url = aEncodedString; 145 | return _url; 146 | } 147 | 148 | public: 149 | 150 | Encode() = default; 151 | ~Encode() = default; 152 | 153 | const std::string& encode(bool bRetainLineFeed) 154 | { 155 | return _url.empty() ? _url : encode(_url, bRetainLineFeed); 156 | } 157 | }; // class Encode 158 | 159 | 160 | class Decode : public EncodeDecodeBase 161 | { 162 | std::vector split(const std::string& str, const char delim) 163 | { 164 | if (str.empty()) 165 | return {}; 166 | 167 | std::vector tokens; 168 | std::istringstream iss(str); 169 | std::string token; 170 | 171 | while (std::getline(iss, token, delim)) 172 | { 173 | tokens.push_back(token); 174 | } 175 | return tokens; 176 | } 177 | 178 | void buildParameters(const std::string& parameters) 179 | { 180 | auto keyValTokens = split(parameters, '&'); 181 | for (const auto& keyValToken : keyValTokens) 182 | { 183 | if (keyValToken.size() < 1) 184 | { 185 | continue; 186 | } 187 | 188 | auto keyValVector = split(keyValToken, '='); 189 | if (keyValVector.size() != 2) 190 | { 191 | continue; 192 | } 193 | _parameters[keyValVector[0]] = keyValVector[1]; 194 | } 195 | } 196 | 197 | const std::string& decode(const std::string encodedUrl) 198 | { 199 | bool baseUrlAvailable = false; 200 | 201 | auto posOfQMark = encodedUrl.find_first_of('?'); 202 | if (posOfQMark != std::string::npos) 203 | { 204 | baseUrlAvailable = true; 205 | 206 | // Everything prior to ? is the baseUrl 207 | _baseUrl = encodedUrl.substr(0, posOfQMark); 208 | } 209 | 210 | //If '?' is at n, we need n+1 characters from the start, i.e including the ?. 211 | _url = encodedUrl.substr(0, baseUrlAvailable ? posOfQMark + 1 : 0); 212 | 213 | std::string parameters; 214 | for (size_t pos = posOfQMark + 1; pos < encodedUrl.size(); ++pos) 215 | { 216 | // Look for %XX 217 | if ('%' == encodedUrl[pos]) 218 | { 219 | if (pos + 2 >= encodedUrl.size()) 220 | { 221 | //We have reached the end of the url. We cannot decode it because there is nothing to decode 222 | break; 223 | } 224 | //Decode next two chars and increase the pos counter accordingly 225 | //Get the next two characters after % and store it in iss 226 | std::istringstream iss(encodedUrl.substr(pos + 1, 2)); 227 | int aIntVal; 228 | iss >> std::hex >> aIntVal; 229 | parameters += static_cast (aIntVal); 230 | //We have processed two extra characters 231 | pos += 2; 232 | } 233 | else 234 | { 235 | //Nothing to do, just copy 236 | parameters += encodedUrl[pos]; 237 | } 238 | } 239 | 240 | buildParameters(parameters); 241 | _url += parameters; 242 | return _url; 243 | } 244 | 245 | public: 246 | 247 | Decode() = default; 248 | ~Decode() = default; 249 | 250 | const std::string& decode() 251 | { 252 | return _url.empty() ? _url : decode(_url); 253 | } 254 | 255 | }; // class Decode 256 | 257 | -------------------------------------------------------------------------------- /src/utilityLib/Utility.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Utility.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #pragma comment(lib, "Version.lib") 13 | #pragma comment(lib, "shlwapi.lib") 14 | #pragma comment(lib, "Comctl32.lib") 15 | 16 | 17 | std::wstring CUtility::GetVersion(const std::wstring& filePath) 18 | { 19 | std::wstring retVer; 20 | 21 | if (!filePath.empty() && ::PathFileExists(filePath.c_str())) 22 | { 23 | DWORD handle = 0; 24 | DWORD bufferSize = ::GetFileVersionInfoSize(filePath.c_str(), &handle); 25 | 26 | if (bufferSize > 0) 27 | { 28 | auto buffer = std::make_unique(bufferSize); 29 | ::GetFileVersionInfo(filePath.c_str(), 0, bufferSize, reinterpret_cast(buffer.get())); 30 | 31 | VS_FIXEDFILEINFO* lpFileInfo = nullptr; 32 | UINT cbFileInfo = 0; 33 | VerQueryValue(buffer.get(), TEXT("\\"), reinterpret_cast(&lpFileInfo), &cbFileInfo); 34 | if (cbFileInfo) 35 | { 36 | std::wostringstream os; 37 | os << ((lpFileInfo->dwFileVersionMS & 0xFFFF0000) >> 16); 38 | os << '.'; 39 | os << (lpFileInfo->dwFileVersionMS & 0x0000FFFF); 40 | os << '.'; 41 | os << ((lpFileInfo->dwFileVersionLS & 0xFFFF0000) >> 16); 42 | os << '.'; 43 | os << (lpFileInfo->dwFileVersionLS & 0x0000FFFF); 44 | 45 | retVer = os.str(); 46 | } 47 | } 48 | } 49 | 50 | return retVer; 51 | } 52 | 53 | HWND CUtility::CreateToolTip(HWND hWnd, int nCtrlID, const std::wstring& tooltipText, HINSTANCE hInst) 54 | { 55 | if (nCtrlID == 0 || hWnd == nullptr || tooltipText.empty()) 56 | { 57 | return nullptr; 58 | } 59 | 60 | // Get the window of the tool. 61 | HWND hControl = GetDlgItem(hWnd, nCtrlID); 62 | 63 | // Create the tooltip. g_hInst is the global instance handle. 64 | HWND hToolTip = CreateWindowEx(NULL, TOOLTIPS_CLASS, nullptr, WS_POPUP | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hWnd, nullptr, hInst, nullptr); 65 | 66 | if (hControl == nullptr || hToolTip == nullptr) 67 | { 68 | return nullptr; 69 | } 70 | 71 | // Associate the tooltip with the control. 72 | TOOLINFO toolInfo = {}; 73 | toolInfo.cbSize = sizeof(toolInfo); 74 | toolInfo.hwnd = hWnd; 75 | toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS; 76 | toolInfo.uId = reinterpret_cast(hControl); 77 | toolInfo.lpszText = const_cast(tooltipText.c_str()); 78 | SendMessage(hToolTip, TTM_ADDTOOL, 0, reinterpret_cast(&toolInfo)); 79 | 80 | return hToolTip; 81 | } 82 | 83 | float CUtility::GetDesktopScale(HWND hWnd) 84 | { 85 | HDC hdc = GetDC(hWnd); 86 | float fScale = GetDeviceCaps(hdc, LOGPIXELSX) / 96.0f; 87 | ReleaseDC(hWnd, hdc); 88 | return fScale; 89 | } 90 | 91 | std::wstring CUtility::GetEditCtrlText(HWND hWnd) 92 | { 93 | auto length = Edit_GetTextLength(hWnd); 94 | std::vector buf(length + 1); 95 | Edit_GetText(hWnd, buf.data(), static_cast(buf.size())); 96 | return buf.data(); 97 | } 98 | 99 | void CUtility::SetEditCtrlText(HWND hWnd, const std::wstring& txt) 100 | { 101 | Edit_SetText(hWnd, txt.data()); 102 | } 103 | 104 | bool CUtility::GetCheckboxStatus(HWND hWnd) 105 | { 106 | return Button_GetCheck(hWnd); 107 | } 108 | 109 | void CUtility::SetCheckboxStatus(HWND hWnd, bool bCheck) 110 | { 111 | Button_SetCheck(hWnd, bCheck); 112 | } 113 | 114 | bool CUtility::DirExist(const std::wstring& dirPath) 115 | { 116 | return std::filesystem::exists(dirPath);; 117 | } 118 | 119 | bool CUtility::FileExist(const std::wstring& filePath) 120 | { 121 | bool r = std::filesystem::exists(filePath); 122 | return r; 123 | } 124 | 125 | long CUtility::FileSize(const std::wstring& filePath) 126 | { 127 | auto r = std::filesystem::file_size(filePath); 128 | return static_cast(r); 129 | } 130 | 131 | bool CUtility::CreateDir(const std::wstring& dirPath) 132 | { 133 | bool r = std::filesystem::create_directories(dirPath); 134 | return r; 135 | } 136 | 137 | bool CUtility::DeleteDir(const std::wstring& dirPath) 138 | { 139 | bool r = std::filesystem::remove(dirPath); 140 | return r; 141 | } 142 | 143 | bool CUtility::Copy(const std::wstring& srcFile, const std::wstring& dstFile) 144 | { 145 | bool r = std::filesystem::copy_file(srcFile, dstFile); 146 | return r; 147 | } 148 | 149 | bool CUtility::Move(const std::wstring& srcFile, const std::wstring& dstFile) 150 | { 151 | bool r = false; 152 | try 153 | { 154 | std::filesystem::rename(srcFile, dstFile); 155 | r = true; 156 | } 157 | catch (std::filesystem::filesystem_error& e) 158 | { 159 | throw e; 160 | } 161 | catch (...) 162 | { 163 | throw "Move file failed."; 164 | } 165 | 166 | return r; 167 | } 168 | 169 | auto CUtility::GetFileName(const std::wstring& fullPath, bool withExtension) -> std::wstring 170 | { 171 | std::filesystem::path pathObj(fullPath); 172 | 173 | // Check if file name is required without extension 174 | if (withExtension == false) 175 | { 176 | // Check if file has stem i.e. filename without extension 177 | if (pathObj.has_stem()) 178 | { 179 | // return the stem (file name without extension) from path object 180 | return pathObj.stem().wstring(); 181 | } 182 | } 183 | 184 | // return the file name with extension from path object 185 | return pathObj.filename().wstring(); 186 | } 187 | 188 | auto CUtility::GetFileExtension(const std::wstring& fileName) -> std::wstring 189 | { 190 | std::wstring retVal; 191 | 192 | std::filesystem::path pathObj(fileName); 193 | 194 | // Check if file has stem i.e. filename without extension 195 | if (pathObj.has_stem()) 196 | { 197 | retVal = pathObj.filename().extension().wstring(); 198 | } 199 | return retVal; 200 | } 201 | 202 | auto CUtility::GetTempFilePath() -> std::wstring 203 | { 204 | TCHAR tmpDir[1024]; 205 | GetTempPath(1024, tmpDir); 206 | return tmpDir; 207 | } 208 | 209 | auto CUtility::GetSpecialFolderLocation(int folderKind) -> std::wstring 210 | { 211 | wchar_t path[MAX_PATH] = {}; 212 | const HRESULT specialLocationResult = SHGetFolderPath(nullptr, folderKind, nullptr, SHGFP_TYPE_CURRENT, path); 213 | 214 | std::wstring result; 215 | if (SUCCEEDED(specialLocationResult)) 216 | { 217 | result = path; 218 | } 219 | return result; 220 | } 221 | 222 | bool CUtility::OpenFileDlg(std::wstring& filePath, const std::wstring& dlgTitle, const std::vector& dlgFilter, DWORD flags) 223 | { 224 | bool bRetVal = false; 225 | 226 | OPENFILENAME ofn; 227 | ::memset(&ofn, 0, sizeof(ofn)); 228 | wchar_t fileName[MAX_PATH] = {}; 229 | ofn.lStructSize = sizeof(ofn); 230 | ofn.lpstrTitle = dlgTitle.c_str(); 231 | ofn.lpstrFilter = dlgFilter.data(); 232 | ofn.nFilterIndex = 1; 233 | ofn.lpstrFile = fileName; 234 | ofn.nMaxFile = MAX_PATH; 235 | ofn.Flags = flags ? flags : OFN_FILEMUSTEXIST; 236 | 237 | if (::GetOpenFileName(&ofn) != FALSE) 238 | { 239 | filePath = ofn.lpstrFile; // will have the full pathand file name. 240 | bRetVal = true; 241 | } 242 | 243 | return bRetVal; 244 | } 245 | -------------------------------------------------------------------------------- /src/urlPlugin/external/npp/URLCtrl.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of Notepad++ project 2 | // Copyright (C)2003 Don HO 3 | // 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either 7 | // version 2 of the License, or (at your option) any later version. 8 | // 9 | // Note that the GPL places important restrictions on "derived works", yet 10 | // it does not provide a detailed definition of that term. To avoid 11 | // misunderstandings, we consider an application to constitute a 12 | // "derivative work" for the purpose of this license if it does any of the 13 | // following: 14 | // 1. Integrates source code from Notepad++. 15 | // 2. Integrates/includes/aggregates Notepad++ into a proprietary executable 16 | // installer, such as those produced by InstallShield. 17 | // 3. Links to a library or executes a program that does any of the above. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU General Public License 25 | // along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | 28 | 29 | #include "URLCtrl.h" 30 | 31 | void URLCtrl::create(HWND itemHandle, const TCHAR* link, COLORREF linkColor) 32 | { 33 | // turn on notify style 34 | ::SetWindowLongPtr(itemHandle, GWL_STYLE, ::GetWindowLongPtr(itemHandle, GWL_STYLE) | SS_NOTIFY); 35 | 36 | // set the URL text (not the display text) 37 | if (link) 38 | _URL = link; 39 | 40 | // set the hyperlink colour 41 | _linkColor = linkColor; 42 | 43 | // set the visited colour 44 | _visitedColor = RGB(128, 0, 128); 45 | 46 | // subclass the static control 47 | _oldproc = reinterpret_cast(::SetWindowLongPtr(itemHandle, GWLP_WNDPROC, reinterpret_cast(URLCtrlProc))); 48 | 49 | // associate the URL structure with the static control 50 | ::SetWindowLongPtr(itemHandle, GWLP_USERDATA, reinterpret_cast(this)); 51 | 52 | // save hwnd 53 | _hSelf = itemHandle; 54 | } 55 | void URLCtrl::create(HWND itemHandle, int cmd, HWND msgDest) 56 | { 57 | // turn on notify style 58 | ::SetWindowLongPtr(itemHandle, GWL_STYLE, ::GetWindowLongPtr(itemHandle, GWL_STYLE) | SS_NOTIFY); 59 | 60 | _cmdID = cmd; 61 | _msgDest = msgDest; 62 | 63 | // set the hyperlink colour 64 | _linkColor = RGB(0, 0, 255); 65 | 66 | // subclass the static control 67 | _oldproc = reinterpret_cast(::SetWindowLongPtr(itemHandle, GWLP_WNDPROC, reinterpret_cast(URLCtrlProc))); 68 | 69 | // associate the URL structure with the static control 70 | ::SetWindowLongPtr(itemHandle, GWLP_USERDATA, reinterpret_cast(this)); 71 | 72 | // save hwnd 73 | _hSelf = itemHandle; 74 | } 75 | 76 | void URLCtrl::destroy() 77 | { 78 | if (_hfUnderlined) 79 | ::DeleteObject(_hfUnderlined); 80 | if (_hCursor) 81 | ::DestroyCursor(_hCursor); 82 | } 83 | 84 | void URLCtrl::action() 85 | { 86 | if (_cmdID) 87 | { 88 | ::SendMessage(_msgDest ? _msgDest : _hParent, WM_COMMAND, _cmdID, 0); 89 | } 90 | else 91 | { 92 | _linkColor = _visitedColor; 93 | 94 | ::InvalidateRect(_hSelf, 0, 0); 95 | ::UpdateWindow(_hSelf); 96 | 97 | // Open a browser 98 | if (_URL != TEXT("")) 99 | { 100 | ::ShellExecute(NULL, TEXT("open"), _URL.c_str(), NULL, NULL, SW_SHOWNORMAL); 101 | } 102 | else 103 | { 104 | TCHAR szWinText[MAX_PATH]; 105 | ::GetWindowText(_hSelf, szWinText, MAX_PATH); 106 | ::ShellExecute(NULL, TEXT("open"), szWinText, NULL, NULL, SW_SHOWNORMAL); 107 | } 108 | } 109 | } 110 | 111 | COLORREF URLCtrl::getCtrlBgColor(HWND hWnd) 112 | { 113 | COLORREF crRet = CLR_INVALID; 114 | if (hWnd && IsWindow(hWnd)) 115 | { 116 | RECT rc; 117 | if (GetClientRect(hWnd, &rc)) 118 | { 119 | HDC hDC = GetDC(hWnd); 120 | if (hDC) 121 | { 122 | HDC hdcMem = CreateCompatibleDC(hDC); 123 | if (hdcMem) 124 | { 125 | HBITMAP hBmp = CreateCompatibleBitmap(hDC, 126 | rc.right, rc.bottom); 127 | if (hBmp) 128 | { 129 | HGDIOBJ hOld = SelectObject(hdcMem, hBmp); 130 | if (hOld) 131 | { 132 | if (SendMessage(hWnd, WM_ERASEBKGND, reinterpret_cast(hdcMem), 0)) 133 | { 134 | crRet = GetPixel(hdcMem, 2, 2); // 0, 0 is usually on the border 135 | } 136 | SelectObject(hdcMem, hOld); 137 | } 138 | DeleteObject(hBmp); 139 | } 140 | DeleteDC(hdcMem); 141 | } 142 | ReleaseDC(hWnd, hDC); 143 | } 144 | } 145 | } 146 | return crRet; 147 | } 148 | 149 | LRESULT URLCtrl::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) 150 | { 151 | switch (Message) 152 | { 153 | // Free up the structure we allocated 154 | case WM_NCDESTROY: 155 | //HeapFree(GetProcessHeap(), 0, url); 156 | break; 157 | 158 | // Paint the static control using our custom 159 | // colours, and with an underline text style 160 | case WM_PAINT: 161 | { 162 | DWORD dwStyle = static_cast(::GetWindowLongPtr(hwnd, GWL_STYLE)); 163 | DWORD dwDTStyle = DT_SINGLELINE; 164 | 165 | //Test if centered horizontally or vertically 166 | if (dwStyle & SS_CENTER) dwDTStyle |= DT_CENTER; 167 | if (dwStyle & SS_RIGHT) dwDTStyle |= DT_RIGHT; 168 | if (dwStyle & SS_CENTERIMAGE) dwDTStyle |= DT_VCENTER; 169 | 170 | RECT rect; 171 | ::GetClientRect(hwnd, &rect); 172 | 173 | PAINTSTRUCT ps; 174 | HDC hdc = ::BeginPaint(hwnd, &ps); 175 | 176 | ::SetTextColor(hdc, _linkColor); 177 | 178 | ::SetBkColor(hdc, getCtrlBgColor(GetParent(hwnd))); ///*::GetSysColor(COLOR_3DFACE)*/); 179 | 180 | // Create an underline font 181 | if (_hfUnderlined == 0) 182 | { 183 | // Get the default GUI font 184 | LOGFONT lf; 185 | HFONT hf = (HFONT)::GetStockObject(DEFAULT_GUI_FONT); 186 | 187 | // Add UNDERLINE attribute 188 | GetObject(hf, sizeof lf, &lf); 189 | lf.lfUnderline = TRUE; 190 | 191 | // Create a new font 192 | _hfUnderlined = ::CreateFontIndirect(&lf); 193 | } 194 | 195 | HANDLE hOld = SelectObject(hdc, _hfUnderlined); 196 | 197 | // Draw the text! 198 | TCHAR szWinText[MAX_PATH]; 199 | ::GetWindowText(hwnd, szWinText, MAX_PATH); 200 | ::DrawText(hdc, szWinText, -1, &rect, dwDTStyle); 201 | 202 | ::SelectObject(hdc, hOld); 203 | 204 | ::EndPaint(hwnd, &ps); 205 | 206 | return 0; 207 | } 208 | 209 | case WM_SETTEXT: 210 | { 211 | LRESULT ret = ::CallWindowProc(_oldproc, hwnd, Message, wParam, lParam); 212 | ::InvalidateRect(hwnd, 0, 0); 213 | return ret; 214 | } 215 | // Provide a hand cursor when the mouse moves over us 216 | case WM_SETCURSOR: 217 | case WM_MOUSEMOVE: 218 | { 219 | if (_hCursor == 0) 220 | _hCursor = LoadCursor(NULL, IDC_HAND); 221 | 222 | SetCursor(_hCursor); 223 | return TRUE; 224 | } 225 | 226 | case WM_LBUTTONDOWN: 227 | _clicking = true; 228 | break; 229 | 230 | case WM_LBUTTONUP: 231 | if (_clicking) 232 | { 233 | _clicking = false; 234 | 235 | action(); 236 | } 237 | 238 | break; 239 | 240 | //Support using space to activate this object 241 | case WM_KEYDOWN: 242 | if (wParam == VK_SPACE) 243 | _clicking = true; 244 | break; 245 | 246 | case WM_KEYUP: 247 | if (wParam == VK_SPACE && _clicking) 248 | { 249 | _clicking = false; 250 | 251 | action(); 252 | } 253 | break; 254 | 255 | // A standard static control returns HTTRANSPARENT here, which 256 | // prevents us from receiving any mouse messages. So, return 257 | // HTCLIENT instead. 258 | case WM_NCHITTEST: 259 | return HTCLIENT; 260 | } 261 | return ::CallWindowProc(_oldproc, hwnd, Message, wParam, lParam); 262 | } 263 | -------------------------------------------------------------------------------- /src/urlPlugin/external/npp/StaticDialog.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of Notepad++ project 2 | // Copyright (C)2003 Don HO 3 | // 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either 7 | // version 2 of the License, or (at your option) any later version. 8 | // 9 | // Note that the GPL places important restrictions on "derived works", yet 10 | // it does not provide a detailed definition of that term. To avoid 11 | // misunderstandings, we consider an application to constitute a 12 | // "derivative work" for the purpose of this license if it does any of the 13 | // following: 14 | // 1. Integrates source code from Notepad++. 15 | // 2. Integrates/includes/aggregates Notepad++ into a proprietary executable 16 | // installer, such as those produced by InstallShield. 17 | // 3. Links to a library or executes a program that does any of the above. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU General Public License 25 | // along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | 28 | #include "StaticDialog.h" 29 | #include "Notepad_plus_msgs.h" 30 | 31 | StaticDialog::~StaticDialog() 32 | { 33 | if (isCreated()) 34 | { 35 | // Prevent run_dlgProc from doing anything, since its virtual 36 | ::SetWindowLongPtr(_hSelf, GWLP_USERDATA, NULL); 37 | destroy(); 38 | } 39 | } 40 | 41 | void StaticDialog::destroy() 42 | { 43 | ::SendMessage(_hParent, NPPM_MODELESSDIALOG, MODELESSDIALOGREMOVE, reinterpret_cast(_hSelf)); 44 | ::DestroyWindow(_hSelf); 45 | } 46 | 47 | POINT StaticDialog::getTopPoint(HWND hwnd, bool isLeft) const 48 | { 49 | RECT rc; 50 | ::GetWindowRect(hwnd, &rc); 51 | 52 | POINT p; 53 | if (isLeft) 54 | p.x = rc.left; 55 | else 56 | p.x = rc.right; 57 | 58 | p.y = rc.top; 59 | ::ScreenToClient(_hSelf, &p); 60 | return p; 61 | } 62 | 63 | void StaticDialog::goToCenter() 64 | { 65 | RECT rc; 66 | ::GetClientRect(_hParent, &rc); 67 | POINT center; 68 | center.x = rc.left + (rc.right - rc.left)/2; 69 | center.y = rc.top + (rc.bottom - rc.top)/2; 70 | ::ClientToScreen(_hParent, ¢er); 71 | 72 | int x = center.x - (_rc.right - _rc.left)/2; 73 | int y = center.y - (_rc.bottom - _rc.top)/2; 74 | 75 | ::SetWindowPos(_hSelf, HWND_TOP, x, y, _rc.right - _rc.left, _rc.bottom - _rc.top, SWP_SHOWWINDOW); 76 | } 77 | 78 | void StaticDialog::display(bool toShow) const 79 | { 80 | if (toShow) 81 | { 82 | // If the user has switched from a dual monitor to a single monitor since we last 83 | // displayed the dialog, then ensure that it's still visible on the single monitor. 84 | RECT workAreaRect = {0}; 85 | RECT rc = {0}; 86 | ::SystemParametersInfo(SPI_GETWORKAREA, 0, &workAreaRect, 0); 87 | ::GetWindowRect(_hSelf, &rc); 88 | int newLeft = rc.left; 89 | int newTop = rc.top; 90 | int margin = ::GetSystemMetrics(SM_CYSMCAPTION); 91 | 92 | if (newLeft > ::GetSystemMetrics(SM_CXVIRTUALSCREEN)-margin) 93 | newLeft -= rc.right - workAreaRect.right; 94 | if (newLeft + (rc.right - rc.left) < ::GetSystemMetrics(SM_XVIRTUALSCREEN)+margin) 95 | newLeft = workAreaRect.left; 96 | if (newTop > ::GetSystemMetrics(SM_CYVIRTUALSCREEN)-margin) 97 | newTop -= rc.bottom - workAreaRect.bottom; 98 | if (newTop + (rc.bottom - rc.top) < ::GetSystemMetrics(SM_YVIRTUALSCREEN)+margin) 99 | newTop = workAreaRect.top; 100 | 101 | if ((newLeft != rc.left) || (newTop != rc.top)) // then the virtual screen size has shrunk 102 | // Remember that MoveWindow wants width/height. 103 | ::MoveWindow(_hSelf, newLeft, newTop, rc.right - rc.left, rc.bottom - rc.top, TRUE); 104 | } 105 | 106 | Window::display(toShow); 107 | } 108 | 109 | HGLOBAL StaticDialog::makeRTLResource(int dialogID, DLGTEMPLATE **ppMyDlgTemplate) 110 | { 111 | if (!ppMyDlgTemplate) 112 | return nullptr; 113 | 114 | // Get Dlg Template resource 115 | HRSRC hDialogRC = ::FindResource(_hInst, MAKEINTRESOURCE(dialogID), RT_DIALOG); 116 | if (!hDialogRC) 117 | return NULL; 118 | 119 | HGLOBAL hDlgTemplate = ::LoadResource(_hInst, hDialogRC); 120 | if (!hDlgTemplate) 121 | return NULL; 122 | 123 | DLGTEMPLATE *pDlgTemplate = static_cast(::LockResource(hDlgTemplate)); 124 | if (!pDlgTemplate) 125 | return NULL; 126 | 127 | // Duplicate Dlg Template resource 128 | unsigned long sizeDlg = ::SizeofResource(_hInst, hDialogRC); 129 | HGLOBAL hMyDlgTemplate = ::GlobalAlloc(GPTR, sizeDlg); 130 | if (hMyDlgTemplate) 131 | { 132 | *ppMyDlgTemplate = static_cast(::GlobalLock(hMyDlgTemplate)); 133 | 134 | ::memcpy(*ppMyDlgTemplate, pDlgTemplate, sizeDlg); 135 | 136 | DLGTEMPLATEEX* pMyDlgTemplateEx = reinterpret_cast(*ppMyDlgTemplate); 137 | if (pMyDlgTemplateEx && pMyDlgTemplateEx->signature == 0xFFFF) 138 | pMyDlgTemplateEx->exStyle |= WS_EX_LAYOUTRTL; 139 | else if(*ppMyDlgTemplate) 140 | (*ppMyDlgTemplate)->dwExtendedStyle |= WS_EX_LAYOUTRTL; 141 | } 142 | 143 | return hMyDlgTemplate; 144 | } 145 | 146 | void StaticDialog::create(int dialogID, bool isRTL, bool msgDestParent) 147 | { 148 | if (isRTL) 149 | { 150 | DLGTEMPLATE *pMyDlgTemplate = NULL; 151 | HGLOBAL hMyDlgTemplate = makeRTLResource(dialogID, &pMyDlgTemplate); 152 | _hSelf = ::CreateDialogIndirectParam(_hInst, pMyDlgTemplate, _hParent, dlgProc, reinterpret_cast(this)); 153 | ::GlobalFree(hMyDlgTemplate); 154 | } 155 | else 156 | _hSelf = ::CreateDialogParam(_hInst, MAKEINTRESOURCE(dialogID), _hParent, dlgProc, reinterpret_cast(this)); 157 | 158 | if (!_hSelf) 159 | { 160 | ::MessageBox(NULL, TEXT("CreateDialogParam() return NULL."), TEXT("In StaticDialog::create()"), MB_OK); 161 | return; 162 | } 163 | 164 | // if the destination of message NPPM_MODELESSDIALOG is not its parent, then it's the grand-parent 165 | ::SendMessage(msgDestParent ? _hParent : (::GetParent(_hParent)), NPPM_MODELESSDIALOG, MODELESSDIALOGADD, reinterpret_cast(_hSelf)); 166 | } 167 | 168 | INT_PTR CALLBACK StaticDialog::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 169 | { 170 | switch (message) 171 | { 172 | case WM_INITDIALOG: 173 | { 174 | StaticDialog *pStaticDlg = reinterpret_cast(lParam); 175 | pStaticDlg->_hSelf = hwnd; 176 | ::SetWindowLongPtr(hwnd, GWLP_USERDATA, static_cast(lParam)); 177 | ::GetWindowRect(hwnd, &(pStaticDlg->_rc)); 178 | pStaticDlg->run_dlgProc(message, wParam, lParam); 179 | 180 | return TRUE; 181 | } 182 | 183 | default: 184 | { 185 | StaticDialog *pStaticDlg = reinterpret_cast(::GetWindowLongPtr(hwnd, GWLP_USERDATA)); 186 | if (!pStaticDlg) 187 | return FALSE; 188 | return pStaticDlg->run_dlgProc(message, wParam, lParam); 189 | } 190 | } 191 | } 192 | 193 | void StaticDialog::alignWith(HWND handle, HWND handle2Align, PosAlign pos, POINT & point) 194 | { 195 | RECT rc, rc2; 196 | ::GetWindowRect(handle, &rc); 197 | 198 | point.x = rc.left; 199 | point.y = rc.top; 200 | 201 | switch (pos) 202 | { 203 | case PosAlign::left: 204 | { 205 | ::GetWindowRect(handle2Align, &rc2); 206 | point.x -= rc2.right - rc2.left; 207 | break; 208 | } 209 | case PosAlign::right: 210 | { 211 | ::GetWindowRect(handle, &rc2); 212 | point.x += rc2.right - rc2.left; 213 | break; 214 | } 215 | case PosAlign::top: 216 | { 217 | ::GetWindowRect(handle2Align, &rc2); 218 | point.y -= rc2.bottom - rc2.top; 219 | break; 220 | } 221 | case PosAlign::bottom: 222 | { 223 | ::GetWindowRect(handle, &rc2); 224 | point.y += rc2.bottom - rc2.top; 225 | break; 226 | } 227 | } 228 | 229 | ::ScreenToClient(_hSelf, &point); 230 | } 231 | -------------------------------------------------------------------------------- /src/urlPlugin/external/npp/TabBar.h: -------------------------------------------------------------------------------- 1 | // This file is part of Notepad++ project 2 | // Copyright (C)2003 Don HO 3 | // 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either 7 | // version 2 of the License, or (at your option) any later version. 8 | // 9 | // Note that the GPL places important restrictions on "derived works", yet 10 | // it does not provide a detailed definition of that term. To avoid 11 | // misunderstandings, we consider an application to constitute a 12 | // "derivative work" for the purpose of this license if it does any of the 13 | // following: 14 | // 1. Integrates source code from Notepad++. 15 | // 2. Integrates/includes/aggregates Notepad++ into a proprietary executable 16 | // installer, such as those produced by InstallShield. 17 | // 3. Links to a library or executes a program that does any of the above. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU General Public License 25 | // along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | 28 | #ifndef TAB_BAR_H 29 | #define TAB_BAR_H 30 | 31 | #ifndef _WIN32_IE 32 | #define _WIN32_IE 0x0600 33 | #endif //_WIN32_IE 34 | 35 | #include 36 | #include 37 | #include "Window.h" 38 | 39 | //Notification message 40 | #define TCN_TABDROPPED (TCN_FIRST - 10) 41 | #define TCN_TABDROPPEDOUTSIDE (TCN_FIRST - 11) 42 | #define TCN_TABDELETE (TCN_FIRST - 12) 43 | 44 | #define WM_TABSETSTYLE (WM_APP + 0x024) 45 | 46 | const int margeValue = 2; 47 | const int nbCtrlMax = 10; 48 | 49 | const wchar_t TABBAR_ACTIVEFOCUSEDINDCATOR[64] = TEXT("Active tab focused indicator"); 50 | const wchar_t TABBAR_ACTIVEUNFOCUSEDINDCATOR[64] = TEXT("Active tab unfocused indicator"); 51 | const wchar_t TABBAR_ACTIVETEXT[64] = TEXT("Active tab text"); 52 | const wchar_t TABBAR_INACTIVETEXT[64] = TEXT("Inactive tabs"); 53 | 54 | struct TBHDR { 55 | NMHDR hdr; 56 | int tabOrigin; 57 | }; 58 | 59 | class TabBar : public Window 60 | { 61 | public: 62 | TabBar() : Window() {}; 63 | virtual ~TabBar() {}; 64 | virtual void destroy(); 65 | virtual void initTabBar(HINSTANCE hInst, HWND hwnd, bool isVertical = false, bool isTraditional = false, bool isMultiLine = false); 66 | virtual void reSizeTo(RECT & rc2Ajust); 67 | int insertAtEnd(const wchar_t *subTabName); 68 | void activateAt(int index) const; 69 | void getCurrentTitle(wchar_t *title, int titleLen); 70 | void setFont(HFONT font); 71 | 72 | auto getCurrentTabIndex() const { 73 | return ::SendMessage(_hSelf, TCM_GETCURSEL, 0, 0); 74 | }; 75 | void deletItemAt(size_t index); 76 | 77 | void deletAllItem() { 78 | ::SendMessage(_hSelf, TCM_DELETEALLITEMS, 0, 0); 79 | _nbItem = 0; 80 | }; 81 | 82 | void setImageList(HIMAGELIST himl) { 83 | _hasImgLst = true; 84 | ::SendMessage(_hSelf, TCM_SETIMAGELIST, 0, (LPARAM)himl); 85 | }; 86 | 87 | auto nbItem() const { 88 | return _nbItem; 89 | }; 90 | 91 | void setFont(const wchar_t* fontName, int fontSize); 92 | 93 | void setVertical(bool b) { 94 | _isVertical = b; 95 | }; 96 | 97 | void setMultiLine(bool b) { 98 | _isMultiLine = b; 99 | }; 100 | 101 | protected: 102 | size_t _nbItem = 0; 103 | bool _hasImgLst = false; 104 | HFONT _hFont = nullptr; 105 | HFONT _hLargeFont = nullptr; 106 | HFONT _hVerticalFont = nullptr; 107 | HFONT _hVerticalLargeFont = nullptr; 108 | 109 | int _ctrlID = -1; 110 | bool _isTraditional = false; 111 | 112 | bool _isVertical = false; 113 | bool _isMultiLine = false; 114 | 115 | long getRowCount() const { 116 | return long(::SendMessage(_hSelf, TCM_GETROWCOUNT, 0, 0)); 117 | }; 118 | }; 119 | 120 | struct CloseButtonZone { 121 | CloseButtonZone(): _width(11), _hight(11), _fromTop(5), _fromRight(3){}; 122 | bool isHit(int x, int y, const RECT & testZone) const; 123 | RECT getButtonRectFrom(const RECT & tabItemRect) const; 124 | 125 | int _width; 126 | int _hight; 127 | int _fromTop; // distance from top in pixzl 128 | int _fromRight; // distance from right in pixzl 129 | }; 130 | 131 | class TabBarPlus : public TabBar 132 | { 133 | public : 134 | 135 | TabBarPlus() : TabBar() {}; 136 | 137 | enum class tabColourIndex { 138 | activeText, activeFocusedTop, activeUnfocusedTop, inactiveText, inactiveBg 139 | }; 140 | 141 | static void doDragNDrop(bool justDoIt) { 142 | _doDragNDrop = justDoIt; 143 | }; 144 | 145 | virtual void initTabBar(HINSTANCE hInst, HWND hwnd, bool isVertical = false, bool isTraditional = false, bool isMultiLine = false); 146 | 147 | static bool doDragNDropOrNot() { 148 | return _doDragNDrop; 149 | }; 150 | 151 | int getSrcTabIndex() const { 152 | return _nSrcTab; 153 | }; 154 | 155 | int getTabDraggedIndex() const { 156 | return _nTabDragged; 157 | }; 158 | 159 | POINT getDraggingPoint() const { 160 | return _draggingPoint; 161 | }; 162 | 163 | void resetDraggingPoint() { 164 | _draggingPoint.x = 0; 165 | _draggingPoint.y = 0; 166 | }; 167 | 168 | static void doOwnerDrawTab(); 169 | static void doVertical(); 170 | static void doMultiLine(); 171 | static bool isOwnerDrawTab() {return true;}; 172 | static bool drawTopBar() {return _drawTopBar;}; 173 | static bool drawInactiveTab() {return _drawInactiveTab;}; 174 | static bool drawTabCloseButton() {return _drawTabCloseButton;}; 175 | static bool isDbClk2Close() {return _isDbClk2Close;}; 176 | static bool isVertical() { return _isCtrlVertical;}; 177 | static bool isMultiLine() { return _isCtrlMultiLine;}; 178 | 179 | static void setDrawTopBar(bool b) { 180 | _drawTopBar = b; 181 | doOwnerDrawTab(); 182 | }; 183 | static void setDrawInactiveTab(bool b) { 184 | _drawInactiveTab = b; 185 | doOwnerDrawTab(); 186 | }; 187 | static void setDrawTabCloseButton(bool b) { 188 | _drawTabCloseButton = b; 189 | doOwnerDrawTab(); 190 | }; 191 | 192 | static void setDbClk2Close(bool b) { 193 | _isDbClk2Close = b; 194 | }; 195 | 196 | static void setVertical(bool b) { 197 | _isCtrlVertical = b; 198 | doVertical(); 199 | }; 200 | 201 | static void setMultiLine(bool b) { 202 | _isCtrlMultiLine = b; 203 | doMultiLine(); 204 | }; 205 | 206 | static void setColour(COLORREF colour2Set, tabColourIndex i); 207 | 208 | protected: 209 | // it's the boss to decide if we do the drag N drop 210 | static bool _doDragNDrop; 211 | // drag N drop members 212 | bool _isDragging = false; 213 | bool _isDraggingInside = false; 214 | int _nSrcTab = 0; 215 | int _nTabDragged = -1; 216 | POINT _draggingPoint = {}; // coordinate of Screen 217 | WNDPROC _tabBarDefaultProc = nullptr; 218 | 219 | RECT _currentHoverTabRect = {}; 220 | int _currentHoverTabItem = -1; 221 | 222 | CloseButtonZone _closeButtonZone; 223 | bool _isCloseHover = false; 224 | int _whichCloseClickDown = -1; 225 | bool _lmbdHit = false; // Left Mouse Button Down Hit 226 | 227 | LRESULT runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam); 228 | 229 | static LRESULT CALLBACK TabBarPlus_Proc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) { 230 | return (((TabBarPlus *)(::GetWindowLongPtr(hwnd, GWLP_USERDATA)))->runProc(hwnd, Message, wParam, lParam)); 231 | }; 232 | void exchangeItemData(POINT point); 233 | 234 | // it's the boss to decide if we do the ownerDraw style tab 235 | static bool _drawInactiveTab; 236 | static bool _drawTopBar; 237 | static bool _drawTabCloseButton; 238 | static bool _isDbClk2Close; 239 | static bool _isCtrlVertical; 240 | static bool _isCtrlMultiLine; 241 | 242 | static COLORREF _activeTextColour; 243 | static COLORREF _activeTopBarFocusedColour; 244 | static COLORREF _activeTopBarUnfocusedColour; 245 | static COLORREF _inactiveTextColour; 246 | static COLORREF _inactiveBgColour; 247 | 248 | static int _nbCtrl; 249 | static HWND _hwndArray[nbCtrlMax]; 250 | 251 | void drawItem(DRAWITEMSTRUCT *pDrawItemStruct); 252 | void draggingCursor(POINT screenPoint); 253 | 254 | int getTabIndexAt(const POINT& p) { 255 | return getTabIndexAt(p.x, p.y); 256 | }; 257 | 258 | int getTabIndexAt(int x, int y) { 259 | TCHITTESTINFO hitInfo; 260 | hitInfo.pt.x = x; 261 | hitInfo.pt.y = y; 262 | return static_cast (::SendMessage(_hSelf, TCM_HITTEST, 0, (LPARAM)&hitInfo)); 263 | }; 264 | 265 | bool isPointInParentZone(POINT screenPoint) const { 266 | RECT parentZone; 267 | ::GetWindowRect(_hParent, &parentZone); 268 | return (((screenPoint.x >= parentZone.left) && (screenPoint.x <= parentZone.right)) && 269 | (screenPoint.y >= parentZone.top) && (screenPoint.y <= parentZone.bottom)); 270 | }; 271 | }; 272 | 273 | #endif // TAB_BAR_H 274 | -------------------------------------------------------------------------------- /src/urlPlugin/PluginHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "PluginHelper.h" 2 | #include "resource.h" 3 | #include "AboutDlg.h" 4 | #include "URL.h" 5 | #include "Profile.h" 6 | #include 7 | #include 8 | 9 | PluginHelper* PluginHelper::Callback::m_pPluginHelper = nullptr; 10 | 11 | PluginHelper::PluginHelper() : m_shortcutCommands(nTotalCommandCount) 12 | { 13 | PluginHelper::Callback::m_pPluginHelper = this; 14 | } 15 | 16 | void PluginHelper::PluginInit(HMODULE hModule) 17 | { 18 | m_hModule = hModule; 19 | } 20 | 21 | void PluginHelper::PluginCleanup() 22 | { 23 | } 24 | 25 | void PluginHelper::SetInfo(const NppData& notpadPlusData) 26 | { 27 | m_NppData = notpadPlusData; 28 | InitCommandMenu(); 29 | InitToolbarIcon(); 30 | InitConfigPath(); 31 | } 32 | 33 | const TCHAR* PluginHelper::GetPluginName() const 34 | { 35 | return PLUGIN_NAME; 36 | } 37 | 38 | FuncItem* PluginHelper::GetFuncsArray(int* nbF) 39 | { 40 | *nbF = nTotalCommandCount; 41 | return m_shortcutCommands.GetFuncItem(); 42 | } 43 | 44 | void PluginHelper::ProcessNotification(const SCNotification* notifyCode) 45 | { 46 | switch (notifyCode->nmhdr.code) 47 | { 48 | case NPPN_TBMODIFICATION: 49 | { 50 | SetMenuIcon(); 51 | break; 52 | } 53 | 54 | case NPPN_SHUTDOWN: 55 | { 56 | PluginCleanup(); 57 | break; 58 | } 59 | 60 | default: 61 | return; 62 | } 63 | } 64 | 65 | LRESULT PluginHelper::MessageProc(UINT /*msg*/, WPARAM /*wParam*/, LPARAM /*lParam*/) 66 | { 67 | return TRUE; 68 | } 69 | 70 | BOOL PluginHelper::IsUnicode() 71 | { 72 | #ifdef _UNICODE 73 | return TRUE; 74 | #else 75 | return FALSE; 76 | #endif // _UNICODE 77 | } 78 | 79 | void PluginHelper::SetMenuIcon() 80 | { 81 | // For Decode URL Toolbar Icon 82 | SetMenuIcon(m_hMenuIcon, CallBackID::DECODE_URL); 83 | } 84 | 85 | void PluginHelper::SetMenuIcon(toolbarIconsWithDarkMode& tbIcons, CallBackID callbackID) 86 | { 87 | if (tbIcons.hToolbarIcon || tbIcons.hToolbarBmp) 88 | { 89 | auto nCommandId = m_shortcutCommands.GetCommandID(callbackID); 90 | ::SendMessage(m_NppData._nppHandle, NPPM_ADDTOOLBARICON_FORDARKMODE, reinterpret_cast(nCommandId), reinterpret_cast(&tbIcons)); 91 | } 92 | } 93 | 94 | void PluginHelper::InitCommandMenu() 95 | { 96 | m_shortcutCommands.SetShortCut(CallBackID::SHOW_SETTING, { true, true, true, 'S' }); 97 | m_shortcutCommands.SetCommand(CallBackID::SHOW_SETTING, MENU_TOOLS_SETTING, Callback::ShowSettingDlg, false); 98 | 99 | m_shortcutCommands.SetShortCut(CallBackID::ENCODE_URL, { true, true, true, 'E' }); 100 | m_shortcutCommands.SetCommand(CallBackID::ENCODE_URL, MENU_ENCODE, Callback::EncodeURL, false); 101 | 102 | m_shortcutCommands.SetShortCut(CallBackID::DECODE_URL, { true, true, true, 'D' }); 103 | m_shortcutCommands.SetCommand(CallBackID::DECODE_URL, MENU_DECODE, Callback::DecodeURL, false); 104 | 105 | m_shortcutCommands.SetCommand(CallBackID::SEP_1, MENU_SEPERATOR, NULL, true); 106 | 107 | m_shortcutCommands.SetCommand(CallBackID::ABOUT, MENU_ABOUT, Callback::ShowAboutDlg, false); 108 | } 109 | 110 | void PluginHelper::InitToolbarIcon() 111 | { 112 | // For Seeting Toolbar Icon 113 | InitToolbarIcon(m_hMenuIcon, IDI_ICON_TOOLBAR); 114 | } 115 | 116 | void PluginHelper::InitToolbarIcon(toolbarIconsWithDarkMode& tbIcons, DWORD iconID) 117 | { 118 | auto dpi = GetDeviceCaps(GetWindowDC(m_NppData._nppHandle), LOGPIXELSX); 119 | int size = 16 * dpi / 96; 120 | 121 | tbIcons.hToolbarIcon = reinterpret_cast(::LoadImage(static_cast(m_hModule), MAKEINTRESOURCE(iconID), IMAGE_ICON, size, size, 0)); 122 | tbIcons.hToolbarIconDarkMode = reinterpret_cast(::LoadImage(static_cast(m_hModule), MAKEINTRESOURCE(iconID), IMAGE_ICON, size, size, 0)); // handle later for dark mode 123 | 124 | ICONINFO iconinfo; 125 | GetIconInfo(tbIcons.hToolbarIcon, &iconinfo); 126 | tbIcons.hToolbarBmp = iconinfo.hbmColor; 127 | } 128 | 129 | void PluginHelper::InitConfigPath() 130 | { 131 | // Get config dir path 132 | WCHAR szPath[_MAX_PATH]{}; 133 | SendMessage(m_NppData._nppHandle, NPPM_GETPLUGINSCONFIGDIR, MAX_PATH, reinterpret_cast(&szPath)); 134 | m_configPath = std::wstring(szPath) + TEXT("\\") + STR_PROFILE_NAME; 135 | } 136 | 137 | void PluginHelper::ToggleMenuItemState(int nCmdId, bool bVisible) 138 | { 139 | ::SendMessage(m_NppData._nppHandle, NPPM_SETMENUITEMCHECK, static_cast(nCmdId), bVisible); 140 | } 141 | 142 | void PluginHelper::ShowSettingDlg() 143 | { 144 | auto nCmdId = m_shortcutCommands.GetCommandID(CallBackID::SHOW_SETTING); 145 | 146 | if (!m_pSettingsDlg) 147 | { 148 | m_pSettingsDlg = std::make_unique(reinterpret_cast(m_hModule), m_NppData._nppHandle, nCmdId, m_configPath); 149 | } 150 | 151 | if (m_pSettingsDlg) // Hope it is constructed by now. 152 | { 153 | bool bVisible = !m_pSettingsDlg->isVisible(); 154 | m_pSettingsDlg->ShowDlg(bVisible); 155 | ToggleMenuItemState(nCmdId, bVisible); 156 | } 157 | } 158 | 159 | void PluginHelper::ShowAboutDlg() 160 | { 161 | auto nCmdId = m_shortcutCommands.GetCommandID(CallBackID::ABOUT); 162 | 163 | if (!m_pAboutDlg) 164 | m_pAboutDlg = std::make_unique(reinterpret_cast(m_hModule), m_NppData._nppHandle, nCmdId); 165 | bool isShown = m_pAboutDlg->ShowDlg(true); 166 | 167 | ToggleMenuItemState(nCmdId, isShown); 168 | } 169 | 170 | void PluginHelper::EncodeURL() 171 | { 172 | auto selectedText = PreOperation(); 173 | if (selectedText.has_value() && !selectedText->empty()) 174 | { 175 | EncodeInfo info; 176 | ProfileEncode(m_configPath).GetInfo(info); 177 | 178 | auto pEncode = std::make_unique(); 179 | pEncode->setUrl(selectedText.value()); 180 | pEncode->setExclusion(w2a(info.exclusionSet)); 181 | auto encoded = pEncode->encode(info.bRetainLineFeed); 182 | 183 | PostOperation(selectedText.value(), encoded, &info, true); 184 | } 185 | } 186 | 187 | void PluginHelper::DecodeURL() 188 | { 189 | auto selectedText = PreOperation(); 190 | if (selectedText.has_value() && !selectedText->empty()) 191 | { 192 | DecodeInfo info; 193 | ProfileDecode(m_configPath).GetInfo(info); 194 | 195 | auto pDecoder = std::make_unique(); 196 | pDecoder->setUrl(selectedText.value()); 197 | pDecoder->setExclusion(w2a(info.exclusionSet)); 198 | auto decoded = pDecoder->decode(); 199 | 200 | PostOperation(selectedText.value(), decoded, &info, false); 201 | } 202 | } 203 | 204 | auto PluginHelper::PreOperation() -> std::optional 205 | { 206 | std::optional retVal{ std::nullopt }; 207 | 208 | if (InitScintilla()) 209 | { 210 | auto selectedText = m_pScintillaEditor->GetSelectedText(); 211 | if (selectedText.empty()) 212 | ShowError(ErrorCode::SCINTILLA_COPY); 213 | else 214 | retVal = selectedText; 215 | } 216 | 217 | return retVal; 218 | } 219 | 220 | void PluginHelper::PostOperation(const std::string& orgTxt, const std::string& converted, void* convertInfo, bool bEncode) 221 | { 222 | if (converted.empty()) 223 | { 224 | ShowError(bEncode ? ErrorCode::CONVERT_ENCODE_UNKNOWN : ErrorCode::CONVERT_DECODE_UNKNOWN); 225 | return; 226 | } 227 | 228 | std::string finalConvertedText = converted; 229 | bool bCopyInSameFile = false; 230 | 231 | if (bEncode) 232 | { 233 | EncodeInfo& info = *reinterpret_cast(convertInfo); 234 | bCopyInSameFile = info.bCopyInSameFile; 235 | } 236 | else 237 | { 238 | DecodeInfo& info = *reinterpret_cast(convertInfo); 239 | bCopyInSameFile = info.bCopyInSameFile; 240 | 241 | if (info.bBreakLine && !info.strLineBreakDelimiter.empty()) 242 | { 243 | finalConvertedText.clear(); 244 | finalConvertedText.reserve(converted.length()); 245 | 246 | auto delimeter = StringHelper::ToString(info.strLineBreakDelimiter); 247 | auto allText = StringHelper::Split(converted, delimeter); 248 | 249 | auto len = allText.size(); 250 | for (const auto& eachline : allText) 251 | { 252 | --len; 253 | if (len) 254 | finalConvertedText += eachline + "\r\n" + delimeter; 255 | else 256 | finalConvertedText += eachline; 257 | } 258 | } 259 | } 260 | 261 | 262 | if (orgTxt == finalConvertedText) 263 | { 264 | ShowError(bEncode ? ErrorCode::CONVERT_ENCODE_SAME : ErrorCode::CONVERT_DECODE_SAME); 265 | return; 266 | } 267 | 268 | auto res = bCopyInSameFile ? 269 | m_pScintillaEditor->ReplaceSelectedText(finalConvertedText) : 270 | m_pScintillaEditor->PasteSelectedOnNewFile(finalConvertedText); 271 | 272 | if (!res) 273 | { 274 | ShowError(bCopyInSameFile ? ErrorCode::SCINTILLA_PASTE : ErrorCode::SCINTILLA_NEW_FILE); 275 | return; 276 | } 277 | } 278 | 279 | bool PluginHelper::InitScintilla() 280 | { 281 | if (!m_pScintillaEditor) 282 | { 283 | m_pScintillaEditor = std::make_unique(m_NppData); 284 | 285 | if (!m_pScintillaEditor) 286 | ShowError(ErrorCode::SCINTILLA_INIT); 287 | } 288 | 289 | return m_pScintillaEditor ? true : false; 290 | } 291 | 292 | void PluginHelper::ShowError(ErrorCode err) 293 | { 294 | UINT uType = MB_OK; 295 | std::wstring title = L"Error"; 296 | std::wstring msg = L"An error occured."; 297 | std::wstring msgSuffix = L"Please contact developer if error continues."; 298 | 299 | switch (err) 300 | { 301 | case ErrorCode::SCINTILLA_INIT: 302 | title = L"Internal Error"; 303 | msg = L"Failed to intialize scintilla. " + msgSuffix; 304 | break; 305 | case ErrorCode::SCINTILLA_COPY: 306 | title = L"Internal Error"; 307 | msg = L"Scintilla error: Failed to copy the text selected txt. \nPlease insure that you've selected the required text and try agian.\n\n" + msgSuffix; 308 | break; 309 | case ErrorCode::SCINTILLA_PASTE: 310 | title = L"Internal Error"; 311 | msg = L"Scintilla error: Failed to paste the text. " + msgSuffix; 312 | break; 313 | case ErrorCode::SCINTILLA_NEW_FILE: 314 | title = L"Internal Error"; 315 | msg = L"Scintilla error: Failed to create new file. " + msgSuffix; 316 | break; 317 | case ErrorCode::CONVERT_ENCODE_UNKNOWN: 318 | title = L"Internal Error"; 319 | msg = L"Failed to encode URL in the selected text. Please try again. " + msgSuffix; 320 | break; 321 | case ErrorCode::CONVERT_DECODE_UNKNOWN: 322 | title = L"Internal Error"; 323 | msg = L"Failed to decode the URL in the selected text. Please try again. " + msgSuffix; 324 | break; 325 | case ErrorCode::CONVERT_ENCODE_SAME: 326 | title = L"Nothing to Convert"; 327 | msg = L"There is nothing to encode for selected URL text or selected text appears to be already encoded."; 328 | break; 329 | case ErrorCode::CONVERT_DECODE_SAME: 330 | title = L"Nothing to Convert"; 331 | msg = L"There is nothing to decode from the selected URL text or selected text appears to be already decoded."; 332 | break; 333 | default: 334 | break; 335 | } 336 | 337 | ::MessageBox(m_NppData._nppHandle, msg.c_str(), title.c_str(), uType); 338 | } 339 | 340 | const std::vector PluginHelper::w2a(const std::vector& vec) 341 | { 342 | std::vector ret; 343 | 344 | if (vec.size()) 345 | { 346 | ret.resize(vec.size()); 347 | 348 | for (const auto& item : vec) 349 | ret.push_back(StringHelper::ToString(item)); 350 | } 351 | 352 | return ret; 353 | } 354 | -------------------------------------------------------------------------------- /src/utilityLib/utilityLib.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | ARM64 7 | 8 | 9 | Debug 10 | Win32 11 | 12 | 13 | Release 14 | ARM64 15 | 16 | 17 | Release 18 | Win32 19 | 20 | 21 | Debug 22 | x64 23 | 24 | 25 | Release 26 | x64 27 | 28 | 29 | 30 | 16.0 31 | Win32Proj 32 | {8085352b-babd-4447-95cc-57457ef895d1} 33 | utilityLib 34 | 10.0 35 | 36 | 37 | 38 | StaticLibrary 39 | Unicode 40 | v143 41 | 42 | 43 | true 44 | 45 | 46 | false 47 | true 48 | 49 | 50 | true 51 | 52 | 53 | true 54 | 55 | 56 | false 57 | true 58 | 59 | 60 | false 61 | true 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | true 89 | $(SolutionDir)Build\Bin\$(Configuration)\$(Platform)\ 90 | $(SolutionDir)Build\Intermediate\$(ProjectName)\$(Configuration)\$(Platform)\ 91 | 92 | 93 | false 94 | $(SolutionDir)Build\Bin\$(Configuration)\$(Platform)\ 95 | $(SolutionDir)Build\Intermediate\$(ProjectName)\$(Configuration)\$(Platform)\ 96 | 97 | 98 | true 99 | $(SolutionDir)Build\Bin\$(Configuration)\$(Platform)\ 100 | $(SolutionDir)Build\Intermediate\$(ProjectName)\$(Configuration)\$(Platform)\ 101 | 102 | 103 | true 104 | $(SolutionDir)Build\Bin\$(Configuration)\$(Platform)\ 105 | $(SolutionDir)Build\Intermediate\$(ProjectName)\$(Configuration)\$(Platform)\ 106 | 107 | 108 | false 109 | $(SolutionDir)Build\Bin\$(Configuration)\$(Platform)\ 110 | $(SolutionDir)Build\Intermediate\$(ProjectName)\$(Configuration)\$(Platform)\ 111 | 112 | 113 | false 114 | $(SolutionDir)Build\Bin\$(Configuration)\$(Platform)\ 115 | $(SolutionDir)Build\Intermediate\$(ProjectName)\$(Configuration)\$(Platform)\ 116 | 117 | 118 | 119 | Level4 120 | true 121 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 122 | true 123 | Use 124 | pch.h 125 | stdcpplatest 126 | true 127 | true 128 | MultiThreadedDebug 129 | 130 | 131 | 132 | 133 | true 134 | 135 | 136 | 137 | 138 | Level4 139 | true 140 | true 141 | true 142 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) 143 | true 144 | Use 145 | pch.h 146 | stdcpplatest 147 | true 148 | true 149 | MultiThreaded 150 | 151 | 152 | 153 | 154 | true 155 | true 156 | true 157 | 158 | 159 | 160 | 161 | Level4 162 | true 163 | _DEBUG;_LIB;%(PreprocessorDefinitions) 164 | true 165 | Use 166 | pch.h 167 | stdcpplatest 168 | true 169 | true 170 | MultiThreadedDebug 171 | 172 | 173 | 174 | 175 | true 176 | 177 | 178 | 179 | 180 | Level4 181 | true 182 | _DEBUG;_LIB;%(PreprocessorDefinitions) 183 | true 184 | Use 185 | pch.h 186 | stdcpplatest 187 | true 188 | true 189 | MultiThreadedDebug 190 | 191 | 192 | 193 | 194 | true 195 | 196 | 197 | 198 | 199 | Level4 200 | true 201 | true 202 | true 203 | NDEBUG;_LIB;%(PreprocessorDefinitions) 204 | true 205 | Use 206 | pch.h 207 | stdcpplatest 208 | true 209 | true 210 | MultiThreaded 211 | 212 | 213 | 214 | 215 | true 216 | true 217 | true 218 | 219 | 220 | 221 | 222 | Level4 223 | true 224 | true 225 | true 226 | NDEBUG;_LIB;%(PreprocessorDefinitions) 227 | true 228 | Use 229 | pch.h 230 | stdcpplatest 231 | true 232 | true 233 | MultiThreaded 234 | 235 | 236 | 237 | 238 | true 239 | true 240 | true 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | Create 254 | Create 255 | Create 256 | Create 257 | Create 258 | Create 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | -------------------------------------------------------------------------------- /src/urlPlugin/urlPlugin.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | ARM64 7 | 8 | 9 | Debug 10 | Win32 11 | 12 | 13 | Release 14 | ARM64 15 | 16 | 17 | Release 18 | Win32 19 | 20 | 21 | Debug 22 | x64 23 | 24 | 25 | Release 26 | x64 27 | 28 | 29 | 30 | 16.0 31 | Win32Proj 32 | {159facfb-40ae-4d9f-b76a-325389e84ea3} 33 | urlPlugin 34 | 10.0 35 | 36 | 37 | 38 | DynamicLibrary 39 | Unicode 40 | v143 41 | 42 | 43 | true 44 | 45 | 46 | false 47 | true 48 | 49 | 50 | true 51 | 52 | 53 | true 54 | 55 | 56 | false 57 | true 58 | 59 | 60 | false 61 | true 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | true 89 | $(SolutionDir)Build\Bin\$(Configuration)\$(Platform)\ 90 | $(SolutionDir)Build\Intermediate\$(ProjectName)\$(Configuration)\$(Platform)\ 91 | .\external\npp\;..\utilityLib\;$(IncludePath) 92 | 93 | 94 | false 95 | $(SolutionDir)Build\Bin\$(Configuration)\$(Platform)\ 96 | $(SolutionDir)Build\Intermediate\$(ProjectName)\$(Configuration)\$(Platform)\ 97 | .\external\npp\;..\utilityLib\;$(IncludePath) 98 | 99 | 100 | true 101 | $(SolutionDir)Build\Bin\$(Configuration)\$(Platform)\ 102 | $(SolutionDir)Build\Intermediate\$(ProjectName)\$(Configuration)\$(Platform)\ 103 | .\external\npp\;..\utilityLib\;$(IncludePath) 104 | 105 | 106 | true 107 | $(SolutionDir)Build\Bin\$(Configuration)\$(Platform)\ 108 | $(SolutionDir)Build\Intermediate\$(ProjectName)\$(Configuration)\$(Platform)\ 109 | .\external\npp\;..\utilityLib\;$(IncludePath) 110 | 111 | 112 | false 113 | $(SolutionDir)Build\Bin\$(Configuration)\$(Platform)\ 114 | $(SolutionDir)Build\Intermediate\$(ProjectName)\$(Configuration)\$(Platform)\ 115 | .\external\npp\;..\utilityLib\;$(IncludePath) 116 | 117 | 118 | false 119 | $(SolutionDir)Build\Bin\$(Configuration)\$(Platform)\ 120 | $(SolutionDir)Build\Intermediate\$(ProjectName)\$(Configuration)\$(Platform)\ 121 | .\external\npp\;..\utilityLib\;$(IncludePath) 122 | 123 | 124 | 125 | Level4 126 | true 127 | WIN32;_DEBUG;URLPLUGIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 128 | true 129 | true 130 | stdcpplatest 131 | true 132 | MultiThreadedDebug 133 | 134 | 135 | Windows 136 | true 137 | false 138 | 139 | 140 | 141 | 142 | Level4 143 | true 144 | true 145 | true 146 | WIN32;NDEBUG;URLPLUGIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 147 | true 148 | true 149 | stdcpplatest 150 | true 151 | MultiThreaded 152 | 153 | 154 | Windows 155 | true 156 | true 157 | true 158 | false 159 | 160 | 161 | 162 | 163 | Level4 164 | true 165 | _DEBUG;URLPLUGIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 166 | true 167 | true 168 | stdcpplatest 169 | true 170 | MultiThreadedDebug 171 | 172 | 173 | Windows 174 | true 175 | false 176 | 177 | 178 | 179 | 180 | Level4 181 | true 182 | _DEBUG;URLPLUGIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 183 | true 184 | true 185 | stdcpplatest 186 | true 187 | MultiThreadedDebug 188 | 189 | 190 | Windows 191 | true 192 | false 193 | 194 | 195 | 196 | 197 | Level4 198 | true 199 | true 200 | true 201 | NDEBUG;URLPLUGIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 202 | true 203 | true 204 | stdcpplatest 205 | true 206 | MultiThreaded 207 | 208 | 209 | Windows 210 | true 211 | true 212 | true 213 | false 214 | 215 | 216 | 217 | 218 | Level4 219 | true 220 | true 221 | true 222 | NDEBUG;URLPLUGIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 223 | true 224 | true 225 | stdcpplatest 226 | true 227 | MultiThreaded 228 | 229 | 230 | Windows 231 | true 232 | true 233 | true 234 | false 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | {8085352b-babd-4447-95cc-57457ef895d1} 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /src/urlPlugin/external/npp/TabBar.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of Notepad++ project 2 | // Copyright (C)2003 Don HO 3 | // 4 | // This program is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU General Public License 6 | // as published by the Free Software Foundation; either 7 | // version 2 of the License, or (at your option) any later version. 8 | // 9 | // Note that the GPL places important restrictions on "derived works", yet 10 | // it does not provide a detailed definition of that term. To avoid 11 | // misunderstandings, we consider an application to constitute a 12 | // "derivative work" for the purpose of this license if it does any of the 13 | // following: 14 | // 1. Integrates source code from Notepad++. 15 | // 2. Integrates/includes/aggregates Notepad++ into a proprietary executable 16 | // installer, such as those produced by InstallShield. 17 | // 3. Links to a library or executes a program that does any of the above. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU General Public License 25 | // along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | 28 | #include "TabBar.h" 29 | #include 30 | #include 31 | #include "menuCmdID.h" 32 | 33 | const COLORREF grey = RGB(128, 128, 128); 34 | 35 | #define IDC_DRAG_TAB 1404 36 | #define IDC_DRAG_INTERDIT_TAB 1405 37 | #define IDC_DRAG_PLUS_TAB 1406 38 | #define IDC_DRAG_OUT_TAB 1407 39 | 40 | bool TabBarPlus::_doDragNDrop = false; 41 | 42 | bool TabBarPlus::_drawTopBar = true; 43 | bool TabBarPlus::_drawInactiveTab = true; 44 | bool TabBarPlus::_drawTabCloseButton = false; 45 | bool TabBarPlus::_isDbClk2Close = false; 46 | bool TabBarPlus::_isCtrlVertical = false; 47 | bool TabBarPlus::_isCtrlMultiLine = false; 48 | 49 | COLORREF TabBarPlus::_activeTextColour = ::GetSysColor(COLOR_BTNTEXT); 50 | COLORREF TabBarPlus::_activeTopBarFocusedColour = RGB(250, 170, 60); 51 | COLORREF TabBarPlus::_activeTopBarUnfocusedColour = RGB(250, 210, 150); 52 | COLORREF TabBarPlus::_inactiveTextColour = grey; 53 | COLORREF TabBarPlus::_inactiveBgColour = RGB(192, 192, 192); 54 | 55 | HWND TabBarPlus::_hwndArray[nbCtrlMax] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; 56 | int TabBarPlus::_nbCtrl = 0; 57 | 58 | void TabBar::initTabBar(HINSTANCE hInst, HWND parent, bool isVertical, bool isTraditional, bool isMultiLine) 59 | { 60 | Window::init(hInst, parent); 61 | int vertical = isVertical?(TCS_VERTICAL | TCS_MULTILINE | TCS_RIGHTJUSTIFY):0; 62 | _isTraditional = isTraditional; 63 | _isVertical = isVertical; 64 | _isMultiLine = isMultiLine; 65 | 66 | INITCOMMONCONTROLSEX icce; 67 | icce.dwSize = sizeof(icce); 68 | icce.dwICC = ICC_TAB_CLASSES; 69 | InitCommonControlsEx(&icce); 70 | int multiLine = isMultiLine?(_isTraditional?TCS_MULTILINE:0):0; 71 | 72 | int style = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE |\ 73 | TCS_FOCUSNEVER | TCS_TABS | WS_TABSTOP | vertical | multiLine; 74 | 75 | _hSelf = ::CreateWindowEx( 76 | 0, 77 | WC_TABCONTROL, 78 | TEXT("Tab"), 79 | style, 80 | 0, 0, 0, 0, 81 | _hParent, 82 | NULL, 83 | _hInst, 84 | 0); 85 | 86 | if (!_hSelf) 87 | { 88 | throw std::runtime_error("TabBar::initTabBar : CreateWindowEx() function return null"); 89 | } 90 | } 91 | 92 | void TabBar::destroy() 93 | { 94 | if (_hFont) 95 | DeleteObject(_hFont); 96 | 97 | if (_hLargeFont) 98 | DeleteObject(_hLargeFont); 99 | 100 | if (_hVerticalFont) 101 | DeleteObject(_hVerticalFont); 102 | 103 | if (_hVerticalLargeFont) 104 | DeleteObject(_hVerticalLargeFont); 105 | 106 | ::DestroyWindow(_hSelf); 107 | _hSelf = NULL; 108 | } 109 | 110 | int TabBar::insertAtEnd(const wchar_t *subTabName) 111 | { 112 | TCITEM tie; 113 | tie.mask = TCIF_TEXT | TCIF_IMAGE; 114 | int index = -1; 115 | 116 | if (_hasImgLst) 117 | index = 0; 118 | tie.iImage = index; 119 | tie.pszText = (wchar_t *)subTabName; 120 | return int(::SendMessage(_hSelf, TCM_INSERTITEM, _nbItem++, reinterpret_cast(&tie))); 121 | } 122 | 123 | void TabBar::getCurrentTitle(wchar_t *title, int titleLen) 124 | { 125 | TCITEM tci; 126 | tci.mask = TCIF_TEXT; 127 | tci.pszText = title; 128 | tci.cchTextMax = titleLen-1; 129 | ::SendMessage(_hSelf, TCM_GETITEM, getCurrentTabIndex(), reinterpret_cast(&tci)); 130 | } 131 | 132 | void TabBar::setFont (HFONT font) 133 | { 134 | ::SendMessage(_hSelf, WM_SETFONT, reinterpret_cast(font), 0); 135 | } 136 | 137 | void TabBar::setFont(const wchar_t* fontName, int fontSize) 138 | { 139 | if (_hFont) 140 | ::DeleteObject(_hFont); 141 | 142 | _hFont = ::CreateFont( fontSize, 0, 143 | (_isVertical) ? 900:0, 144 | (_isVertical) ? 900:0, 145 | FW_NORMAL, 146 | 0, 0, 0, 0, 147 | 0, 0, 0, 0, 148 | fontName); 149 | if (_hFont) 150 | ::SendMessage(_hSelf, WM_SETFONT, reinterpret_cast(_hFont), 0); 151 | } 152 | 153 | void TabBar::activateAt(int index) const 154 | { 155 | if (getCurrentTabIndex() != index) 156 | { 157 | ::SendMessage(_hSelf, TCM_SETCURSEL, index, 0); 158 | } 159 | TBHDR nmhdr; 160 | nmhdr.hdr.hwndFrom = _hSelf; 161 | nmhdr.hdr.code = TCN_SELCHANGE; 162 | nmhdr.hdr.idFrom = reinterpret_cast(this); 163 | nmhdr.tabOrigin = index; 164 | } 165 | 166 | void TabBar::deletItemAt(size_t index) 167 | { 168 | if (index == _nbItem-1) 169 | { 170 | //prevent invisible tabs. If last visible tab is removed, other tabs are put in view but not redrawn 171 | //Therefore, scroll one tab to the left if only one tab visible 172 | if (_nbItem > 1) 173 | { 174 | RECT itemRect; 175 | ::SendMessage(_hSelf, TCM_GETITEMRECT, (WPARAM)index, (LPARAM)&itemRect); 176 | if (itemRect.left < 5) //if last visible tab, scroll left once (no more than 5px away should be safe, usually 2px depending on the drawing) 177 | { 178 | //To scroll the tab control to the left, use the WM_HSCROLL notification 179 | //Doesn't really seem to be documented anywhere, but the values do match the message parameters 180 | //The up/down control really is just some sort of scrollbar 181 | //There seems to be no negative effect on any internal state of the tab control or the up/down control 182 | int wParam = MAKEWPARAM(SB_THUMBPOSITION, index - 1); 183 | ::SendMessage(_hSelf, WM_HSCROLL, wParam, 0); 184 | 185 | wParam = MAKEWPARAM(SB_ENDSCROLL, index - 1); 186 | ::SendMessage(_hSelf, WM_HSCROLL, wParam, 0); 187 | } 188 | } 189 | } 190 | ::SendMessage(_hSelf, TCM_DELETEITEM, index, 0); 191 | _nbItem--; 192 | } 193 | 194 | void TabBar::reSizeTo(RECT & rc2Ajust) 195 | { 196 | RECT RowRect; 197 | int RowCount, TabsLength; 198 | 199 | // Important to do that! 200 | // Otherwise, the window(s) it contains will take all the resouce of CPU 201 | // We don't need to resize the contained windows if they are even invisible anyway 202 | display(rc2Ajust.right > 10); 203 | RECT rc = rc2Ajust; 204 | Window::reSizeTo(rc); 205 | 206 | // Do our own calculations because TabCtrl_AdjustRect doesn't work 207 | // on vertical or multi-lined tab controls 208 | 209 | RowCount = TabCtrl_GetRowCount(_hSelf); 210 | TabCtrl_GetItemRect(_hSelf, 0, &RowRect); 211 | if (_isTraditional) 212 | { 213 | TabCtrl_AdjustRect(_hSelf, false, &rc2Ajust); 214 | } 215 | else if (_isVertical) 216 | { 217 | TabsLength = RowCount * (RowRect.right - RowRect.left); 218 | TabsLength += GetSystemMetrics(SM_CXEDGE); 219 | 220 | rc2Ajust.left += TabsLength; 221 | rc2Ajust.right -= TabsLength; 222 | } 223 | else 224 | { 225 | TabsLength = RowCount * (RowRect.bottom - RowRect.top); 226 | TabsLength += GetSystemMetrics(SM_CYEDGE); 227 | 228 | rc2Ajust.top += TabsLength; 229 | rc2Ajust.bottom -= TabsLength; 230 | } 231 | } 232 | 233 | void TabBarPlus::initTabBar(HINSTANCE hInst, HWND parent, bool isVertical, bool isTraditional, bool isMultiLine) 234 | { 235 | Window::init(hInst, parent); 236 | int vertical = isVertical?(TCS_VERTICAL | TCS_MULTILINE | TCS_RIGHTJUSTIFY):0; 237 | _isTraditional = isTraditional; 238 | _isVertical = isVertical; 239 | _isMultiLine = isMultiLine; 240 | 241 | INITCOMMONCONTROLSEX icce; 242 | icce.dwSize = sizeof(icce); 243 | icce.dwICC = ICC_TAB_CLASSES; 244 | InitCommonControlsEx(&icce); 245 | int multiLine = isMultiLine?(_isTraditional?TCS_MULTILINE:0):0; 246 | 247 | int style = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE |\ 248 | TCS_TOOLTIPS | TCS_FOCUSNEVER | TCS_TABS | vertical | multiLine; 249 | 250 | style |= TCS_OWNERDRAWFIXED; 251 | 252 | _hSelf = ::CreateWindowEx( 253 | 0, 254 | WC_TABCONTROL, 255 | TEXT("Tab"), 256 | style, 257 | 0, 0, 0, 0, 258 | _hParent, 259 | NULL, 260 | _hInst, 261 | 0); 262 | 263 | if (!_hSelf) 264 | { 265 | throw std::runtime_error("TabBarPlus::initTabBar : CreateWindowEx() function return null"); 266 | } 267 | if (!_isTraditional) 268 | { 269 | if (!_hwndArray[_nbCtrl]) 270 | { 271 | _hwndArray[_nbCtrl] = _hSelf; 272 | _ctrlID = _nbCtrl; 273 | } 274 | else 275 | { 276 | int i = 0; 277 | bool found = false; 278 | for ( ; i < nbCtrlMax && !found ; i++) 279 | if (!_hwndArray[i]) 280 | found = true; 281 | if (!found) 282 | { 283 | _ctrlID = -1; 284 | destroy(); 285 | throw std::runtime_error("TabBarPlus::initTabBar : Tab Control error - Tab Control # is over its limit"); 286 | } 287 | _hwndArray[i] = _hSelf; 288 | _ctrlID = i; 289 | } 290 | _nbCtrl++; 291 | 292 | ::SetWindowLongPtr(_hSelf, GWLP_USERDATA, (LONG_PTR)this); 293 | _tabBarDefaultProc = reinterpret_cast(::SetWindowLongPtr(_hSelf, GWLP_USERDATA, (LONG_PTR)TabBarPlus_Proc)); 294 | } 295 | 296 | LOGFONT LogFont; 297 | 298 | _hFont = (HFONT)::SendMessage(_hSelf, WM_GETFONT, 0, 0); 299 | 300 | if (_hFont == NULL) 301 | _hFont = (HFONT)::GetStockObject(DEFAULT_GUI_FONT); 302 | 303 | if (_hLargeFont == NULL) 304 | _hLargeFont = (HFONT)::GetStockObject(SYSTEM_FONT); 305 | 306 | if (::GetObject(_hFont, sizeof(LOGFONT), &LogFont) != 0) 307 | { 308 | LogFont.lfEscapement = 900; 309 | LogFont.lfOrientation = 900; 310 | _hVerticalFont = CreateFontIndirect(&LogFont); 311 | 312 | LogFont.lfWeight = 900; 313 | _hVerticalLargeFont = CreateFontIndirect(&LogFont); 314 | } 315 | } 316 | 317 | void TabBarPlus::doOwnerDrawTab() 318 | { 319 | ::SendMessage(_hwndArray[0], TCM_SETPADDING, 0, MAKELPARAM(6, 0)); 320 | for (int i = 0 ; i < _nbCtrl ; i++) 321 | { 322 | if (_hwndArray[i]) 323 | { 324 | auto style = ::GetWindowLongPtr(_hwndArray[i], GWL_STYLE); 325 | if (isOwnerDrawTab()) 326 | style |= TCS_OWNERDRAWFIXED; 327 | else 328 | style &= ~TCS_OWNERDRAWFIXED; 329 | 330 | ::SetWindowLongPtr(_hwndArray[i], GWL_STYLE, style); 331 | ::InvalidateRect(_hwndArray[i], NULL, true); 332 | 333 | const int base = 6; 334 | ::SendMessage(_hwndArray[i], TCM_SETPADDING, 0, MAKELPARAM(_drawTabCloseButton?base+3:base, 0)); 335 | } 336 | } 337 | } 338 | 339 | void TabBarPlus::setColour(COLORREF colour2Set, tabColourIndex i) 340 | { 341 | using enum tabColourIndex; 342 | switch (i) 343 | { 344 | case activeText: 345 | _activeTextColour = colour2Set; 346 | break; 347 | case activeFocusedTop: 348 | _activeTopBarFocusedColour = colour2Set; 349 | break; 350 | case activeUnfocusedTop: 351 | _activeTopBarUnfocusedColour = colour2Set; 352 | break; 353 | case inactiveText: 354 | _inactiveTextColour = colour2Set; 355 | break; 356 | case inactiveBg : 357 | _inactiveBgColour = colour2Set; 358 | break; 359 | default : 360 | return; 361 | } 362 | doOwnerDrawTab(); 363 | } 364 | 365 | void TabBarPlus::doVertical() 366 | { 367 | for (int i = 0 ; i < _nbCtrl ; i++) 368 | { 369 | if (_hwndArray[i]) 370 | SendMessage(_hwndArray[i], WM_TABSETSTYLE, isVertical(), TCS_VERTICAL); 371 | } 372 | } 373 | 374 | void TabBarPlus::doMultiLine() 375 | { 376 | for (int i = 0 ; i < _nbCtrl ; i++) 377 | { 378 | if (_hwndArray[i]) 379 | SendMessage(_hwndArray[i], WM_TABSETSTYLE, isMultiLine(), TCS_MULTILINE); 380 | } 381 | } 382 | 383 | LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) 384 | { 385 | switch (Message) 386 | { 387 | // Custom window message to change tab control style on the fly 388 | case WM_TABSETSTYLE: 389 | { 390 | //::SendMessage(upDownWnd, UDM_SETBUDDY, NULL, 0); 391 | auto style = ::GetWindowLongPtr(hwnd, GWL_STYLE); 392 | 393 | if (wParam > 0) 394 | style |= lParam; 395 | else 396 | style &= ~lParam; 397 | 398 | _isVertical = ((style & TCS_VERTICAL) != 0); 399 | _isMultiLine = ((style & TCS_MULTILINE) != 0); 400 | 401 | ::SetWindowLongPtr(hwnd, GWL_STYLE, style); 402 | ::InvalidateRect(hwnd, NULL, true); 403 | 404 | return true; 405 | } 406 | 407 | case WM_LBUTTONDOWN : 408 | { 409 | if (_drawTabCloseButton) 410 | { 411 | int xPos = LOWORD(lParam); 412 | int yPos = HIWORD(lParam); 413 | 414 | if (_closeButtonZone.isHit(xPos, yPos, _currentHoverTabRect)) 415 | { 416 | _whichCloseClickDown = getTabIndexAt(xPos, yPos); 417 | ::SendMessage(_hParent, WM_COMMAND, IDM_VIEW_REFRESHTABAR, 0); 418 | return true; 419 | } 420 | } 421 | 422 | ::CallWindowProc(_tabBarDefaultProc, hwnd, Message, wParam, lParam); 423 | int currentTabOn = static_cast (::SendMessage(_hSelf, TCM_GETCURSEL, 0, 0)); 424 | 425 | if (wParam == 2) 426 | return true; 427 | 428 | if (_doDragNDrop) 429 | { 430 | _nSrcTab = _nTabDragged = currentTabOn; 431 | 432 | POINT point; 433 | point.x = LOWORD(lParam); 434 | point.y = HIWORD(lParam); 435 | ::ClientToScreen(hwnd, &point); 436 | if(::DragDetect(hwnd, point)) 437 | { 438 | // Yes, we're beginning to drag, so capture the mouse... 439 | _isDragging = true; 440 | ::SetCapture(hwnd); 441 | } 442 | } 443 | 444 | TBHDR nmhdr; 445 | nmhdr.hdr.hwndFrom = _hSelf; 446 | nmhdr.hdr.code = NM_CLICK; 447 | nmhdr.hdr.idFrom = reinterpret_cast(this); 448 | nmhdr.tabOrigin = currentTabOn; 449 | 450 | ::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast(&nmhdr)); 451 | 452 | return true; 453 | } 454 | case WM_RBUTTONDOWN : //rightclick selects tab aswell 455 | { 456 | ::CallWindowProc(_tabBarDefaultProc, hwnd, WM_LBUTTONDOWN, wParam, lParam); 457 | return true; 458 | } 459 | //#define NPPM_INTERNAL_ISDRAGGING 40926 460 | case WM_MOUSEMOVE : 461 | { 462 | if (_isDragging) 463 | { 464 | POINT p; 465 | p.x = LOWORD(lParam); 466 | p.y = HIWORD(lParam); 467 | exchangeItemData(p); 468 | 469 | // Get cursor position of "Screen" 470 | // For using the function "WindowFromPoint" afterward!!! 471 | ::GetCursorPos(&_draggingPoint); 472 | /* 473 | HWND h = ::WindowFromPoint(_draggingPoint); 474 | ::SetFocus(h); 475 | */ 476 | 477 | draggingCursor(_draggingPoint); 478 | //::SendMessage(h, NPPM_INTERNAL_ISDRAGGING, 0, 0); 479 | return true; 480 | } 481 | 482 | if (_drawTabCloseButton) 483 | { 484 | int xPos = LOWORD(lParam); 485 | int yPos = HIWORD(lParam); 486 | 487 | int index = getTabIndexAt(xPos, yPos); 488 | 489 | if (index != -1) 490 | { 491 | // Reduce flicker by only redrawing needed tabs 492 | 493 | bool oldVal = _isCloseHover; 494 | int oldIndex = _currentHoverTabItem; 495 | RECT oldRect; 496 | 497 | ::SendMessage(_hSelf, TCM_GETITEMRECT, index, (LPARAM)&_currentHoverTabRect); 498 | ::SendMessage(_hSelf, TCM_GETITEMRECT, oldIndex, (LPARAM)&oldRect); 499 | _currentHoverTabItem = index; 500 | _isCloseHover = _closeButtonZone.isHit(xPos, yPos, _currentHoverTabRect); 501 | 502 | if (oldVal != _isCloseHover) 503 | { 504 | InvalidateRect(hwnd, &oldRect, false); 505 | InvalidateRect(hwnd, &_currentHoverTabRect, false); 506 | } 507 | } 508 | } 509 | break; 510 | } 511 | 512 | case WM_LBUTTONUP : 513 | { 514 | int xPos = LOWORD(lParam); 515 | int yPos = HIWORD(lParam); 516 | int currentTabOn = getTabIndexAt(xPos, yPos); 517 | if (_isDragging) 518 | { 519 | if(::GetCapture() == _hSelf) 520 | ::ReleaseCapture(); 521 | 522 | // Send a notification message to the parent with wParam = 0, lParam = 0 523 | // nmhdr.idFrom = this 524 | // destIndex = this->_nSrcTab 525 | // scrIndex = this->_nTabDragged 526 | TBHDR nmhdr; 527 | nmhdr.hdr.hwndFrom = _hSelf; 528 | nmhdr.hdr.code = _isDraggingInside?TCN_TABDROPPED:TCN_TABDROPPEDOUTSIDE; 529 | nmhdr.hdr.idFrom = reinterpret_cast(this); 530 | nmhdr.tabOrigin = currentTabOn; 531 | 532 | ::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast(&nmhdr)); 533 | return true; 534 | } 535 | 536 | if (_drawTabCloseButton) 537 | { 538 | if ((_whichCloseClickDown == currentTabOn) && _closeButtonZone.isHit(xPos, yPos, _currentHoverTabRect)) 539 | { 540 | TBHDR nmhdr; 541 | nmhdr.hdr.hwndFrom = _hSelf; 542 | nmhdr.hdr.code = TCN_TABDELETE; 543 | nmhdr.hdr.idFrom = reinterpret_cast(this); 544 | nmhdr.tabOrigin = currentTabOn; 545 | 546 | ::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast(&nmhdr)); 547 | 548 | _whichCloseClickDown = -1; 549 | return true; 550 | } 551 | _whichCloseClickDown = -1; 552 | } 553 | 554 | break; 555 | } 556 | 557 | case WM_CAPTURECHANGED : 558 | { 559 | if (_isDragging) 560 | { 561 | _isDragging = false; 562 | return true; 563 | } 564 | break; 565 | } 566 | 567 | case WM_DRAWITEM : 568 | { 569 | drawItem((DRAWITEMSTRUCT *)lParam); 570 | return true; 571 | } 572 | 573 | case WM_KEYDOWN : 574 | { 575 | if (wParam == VK_LCONTROL) 576 | ::SetCursor(::LoadCursor(_hInst, MAKEINTRESOURCE(IDC_DRAG_PLUS_TAB))); 577 | return true; 578 | } 579 | 580 | case WM_MBUTTONUP: 581 | { 582 | int xPos = LOWORD(lParam); 583 | int yPos = HIWORD(lParam); 584 | int currentTabOn = getTabIndexAt(xPos, yPos); 585 | TBHDR nmhdr; 586 | nmhdr.hdr.hwndFrom = _hSelf; 587 | nmhdr.hdr.code = TCN_TABDELETE; 588 | nmhdr.hdr.idFrom = reinterpret_cast(this); 589 | nmhdr.tabOrigin = currentTabOn; 590 | 591 | ::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast(&nmhdr)); 592 | return true; 593 | } 594 | 595 | case WM_LBUTTONDBLCLK : 596 | { 597 | if (_isDbClk2Close) 598 | { 599 | int xPos = LOWORD(lParam); 600 | int yPos = HIWORD(lParam); 601 | int currentTabOn = getTabIndexAt(xPos, yPos); 602 | TBHDR nmhdr; 603 | nmhdr.hdr.hwndFrom = _hSelf; 604 | nmhdr.hdr.code = TCN_TABDELETE; 605 | nmhdr.hdr.idFrom = reinterpret_cast(this); 606 | nmhdr.tabOrigin = currentTabOn; 607 | 608 | ::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast(&nmhdr)); 609 | } 610 | return true; 611 | } 612 | } 613 | return ::CallWindowProc(_tabBarDefaultProc, hwnd, Message, wParam, lParam); 614 | } 615 | 616 | void TabBarPlus::drawItem(DRAWITEMSTRUCT *pDrawItemStruct) 617 | { 618 | RECT rect = pDrawItemStruct->rcItem; 619 | 620 | int nTab = pDrawItemStruct->itemID; 621 | if (nTab < 0) 622 | { 623 | ::MessageBox(NULL, TEXT("nTab < 0"), TEXT(""), MB_OK); 624 | //return ::CallWindowProc(_tabBarDefaultProc, hwnd, Message, wParam, lParam); 625 | } 626 | bool isSelected = (nTab == ::SendMessage(_hSelf, TCM_GETCURSEL, 0, 0)); 627 | 628 | wchar_t label[MAX_PATH] = {}; 629 | TCITEM tci; 630 | tci.mask = TCIF_TEXT|TCIF_IMAGE; 631 | tci.pszText = label; 632 | tci.cchTextMax = MAX_PATH-1; 633 | 634 | if (!::SendMessage(_hSelf, TCM_GETITEM, nTab, reinterpret_cast(&tci))) 635 | { 636 | ::MessageBox(NULL, TEXT("! TCM_GETITEM"), TEXT(""), MB_OK); 637 | //return ::CallWindowProc(_tabBarDefaultProc, hwnd, Message, wParam, lParam); 638 | } 639 | HDC hDC = pDrawItemStruct->hDC; 640 | 641 | int nSavedDC = ::SaveDC(hDC); 642 | 643 | ::SetBkMode(hDC, TRANSPARENT); 644 | HBRUSH hBrush = ::CreateSolidBrush(::GetSysColor(COLOR_BTNFACE)); 645 | ::FillRect(hDC, &rect, hBrush); 646 | ::DeleteObject((HGDIOBJ)hBrush); 647 | 648 | if (isSelected) 649 | { 650 | if (_drawTopBar) 651 | { 652 | RECT barRect = rect; 653 | 654 | if (_isVertical) 655 | { 656 | barRect.right = barRect.left + 6; 657 | rect.left += 2; 658 | } 659 | else 660 | { 661 | barRect.bottom = barRect.top + 6; 662 | rect.top += 2; 663 | } 664 | 665 | hBrush = ::CreateSolidBrush(_activeTopBarFocusedColour); 666 | ::FillRect(hDC, &barRect, hBrush); 667 | ::DeleteObject((HGDIOBJ)hBrush); 668 | } 669 | } 670 | else 671 | { 672 | if (_drawInactiveTab) 673 | { 674 | RECT barRect = rect; 675 | 676 | hBrush = ::CreateSolidBrush(_inactiveBgColour); 677 | ::FillRect(hDC, &barRect, hBrush); 678 | ::DeleteObject((HGDIOBJ)hBrush); 679 | } 680 | } 681 | 682 | if (_drawTabCloseButton) 683 | { 684 | RECT closeButtonRect = _closeButtonZone.getButtonRectFrom(rect); 685 | if (isSelected) 686 | { 687 | if (!_isVertical) 688 | { 689 | //closeButtonRect.top += 2; 690 | closeButtonRect.left -= 2; 691 | } 692 | } 693 | else 694 | { 695 | if (_isVertical) 696 | closeButtonRect.left += 2; 697 | } 698 | 699 | HDC hdcMemory; 700 | hdcMemory = ::CreateCompatibleDC(hDC); 701 | 702 | ::DeleteDC(hdcMemory); 703 | } 704 | 705 | // Draw image 706 | HIMAGELIST hImgLst = (HIMAGELIST)::SendMessage(_hSelf, TCM_GETIMAGELIST, 0, 0); 707 | 708 | SIZE charPixel; 709 | ::GetTextExtentPoint(hDC, TEXT(" "), 1, &charPixel); 710 | int spaceUnit = charPixel.cx; 711 | 712 | if (hImgLst && tci.iImage >= 0) 713 | { 714 | IMAGEINFO info; 715 | int yPos = 0, xPos = 0; 716 | int marge = 0; 717 | 718 | ImageList_GetImageInfo(hImgLst, tci.iImage, &info); 719 | 720 | RECT & imageRect = info.rcImage; 721 | 722 | if (_isVertical) 723 | xPos = (rect.left + (rect.right - rect.left)/2 + 2) - (imageRect.right - imageRect.left)/2; 724 | else 725 | yPos = (rect.top + (rect.bottom - rect.top)/2 + (isSelected?0:2)) - (imageRect.bottom - imageRect.top)/2; 726 | 727 | if (isSelected) 728 | marge = spaceUnit*2; 729 | else 730 | marge = spaceUnit; 731 | 732 | if (_isVertical) 733 | { 734 | rect.bottom -= imageRect.bottom - imageRect.top; 735 | ImageList_Draw(hImgLst, tci.iImage, hDC, xPos, rect.bottom - marge, isSelected?ILD_TRANSPARENT:ILD_SELECTED); 736 | rect.bottom += marge; 737 | } 738 | else 739 | { 740 | rect.left += marge; 741 | ImageList_Draw(hImgLst, tci.iImage, hDC, rect.left, yPos, isSelected?ILD_TRANSPARENT:ILD_SELECTED); 742 | rect.left += imageRect.right - imageRect.left; 743 | } 744 | } 745 | 746 | if (_isVertical) 747 | SelectObject(hDC, _hVerticalFont); 748 | else 749 | SelectObject(hDC, _hFont); 750 | 751 | int Flags = DT_SINGLELINE; 752 | 753 | if (_drawTabCloseButton) 754 | { 755 | Flags |= DT_LEFT; 756 | } 757 | else 758 | { 759 | if (!_isVertical) 760 | Flags |= DT_CENTER; 761 | } 762 | 763 | // the following uses pixel values the fix alignments issues with DrawText 764 | // and font's that are rotated 90 degrees 765 | if (isSelected) 766 | { 767 | //COLORREF selectedColor = RGB(0, 0, 255); 768 | ::SetTextColor(hDC, _activeTextColour); 769 | 770 | if (_isVertical) 771 | { 772 | rect.bottom -= 2; 773 | rect.left += ::GetSystemMetrics(SM_CXEDGE) + 4; 774 | rect.top += (_drawTabCloseButton)?spaceUnit:0; 775 | 776 | Flags |= DT_BOTTOM; 777 | } 778 | else 779 | { 780 | rect.top -= ::GetSystemMetrics(SM_CYEDGE); 781 | rect.top += 3; 782 | rect.left += _drawTabCloseButton?spaceUnit:0; 783 | 784 | Flags |= DT_VCENTER; 785 | } 786 | } 787 | else 788 | { 789 | ::SetTextColor(hDC, _inactiveTextColour); 790 | if (_isVertical) 791 | { 792 | rect.top += 2; 793 | rect.bottom += 4; 794 | rect.left += ::GetSystemMetrics(SM_CXEDGE) + 2; 795 | } 796 | else 797 | { 798 | rect.left += (_drawTabCloseButton)?spaceUnit:0; 799 | } 800 | 801 | Flags |= DT_BOTTOM; 802 | } 803 | ::DrawText(hDC, label, lstrlen(label), &rect, Flags); 804 | ::RestoreDC(hDC, nSavedDC); 805 | } 806 | 807 | void TabBarPlus::draggingCursor(POINT screenPoint) 808 | { 809 | HWND hWin = ::WindowFromPoint(screenPoint); 810 | if (_hSelf == hWin) 811 | ::SetCursor(::LoadCursor(NULL, IDC_ARROW)); 812 | else 813 | { 814 | wchar_t className[256]; 815 | ::GetClassName(hWin, className, 256); 816 | if ((!lstrcmp(className, TEXT("Scintilla"))) || (!lstrcmp(className, WC_TABCONTROL))) 817 | { 818 | if (::GetKeyState(VK_LCONTROL) & 0x80000000) 819 | ::SetCursor(::LoadCursor(_hInst, MAKEINTRESOURCE(IDC_DRAG_PLUS_TAB))); 820 | else 821 | ::SetCursor(::LoadCursor(_hInst, MAKEINTRESOURCE(IDC_DRAG_TAB))); 822 | } 823 | else if (isPointInParentZone(screenPoint)) 824 | ::SetCursor(::LoadCursor(_hInst, MAKEINTRESOURCE(IDC_DRAG_INTERDIT_TAB))); 825 | else // drag out of application 826 | ::SetCursor(::LoadCursor(_hInst, MAKEINTRESOURCE(IDC_DRAG_OUT_TAB))); 827 | } 828 | } 829 | 830 | void TabBarPlus::exchangeItemData(POINT point) 831 | { 832 | // Find the destination tab... 833 | int nTab = getTabIndexAt(point); 834 | 835 | // The position is over a tab. 836 | //if (hitinfo.flags != TCHT_NOWHERE) 837 | if (nTab != -1) 838 | { 839 | _isDraggingInside = true; 840 | 841 | if (nTab != _nTabDragged) 842 | { 843 | //1. set to focus 844 | ::SendMessage(_hSelf, TCM_SETCURSEL, nTab, 0); 845 | 846 | //2. shift their data, and insert the source 847 | TCITEM itemData_nDraggedTab, itemData_shift; 848 | itemData_nDraggedTab.mask = itemData_shift.mask = TCIF_IMAGE | TCIF_TEXT | TCIF_PARAM; 849 | const int stringSize = 256; 850 | wchar_t str1[stringSize]; 851 | wchar_t str2[stringSize]; 852 | 853 | itemData_nDraggedTab.pszText = str1; 854 | itemData_nDraggedTab.cchTextMax = (stringSize); 855 | 856 | itemData_shift.pszText = str2; 857 | itemData_shift.cchTextMax = (stringSize); 858 | 859 | ::SendMessage(_hSelf, TCM_GETITEM, _nTabDragged, reinterpret_cast(&itemData_nDraggedTab)); 860 | 861 | if (_nTabDragged > nTab) 862 | { 863 | for (int i = _nTabDragged ; i > nTab ; i--) 864 | { 865 | ::SendMessage(_hSelf, TCM_GETITEM, i-1, reinterpret_cast(&itemData_shift)); 866 | ::SendMessage(_hSelf, TCM_SETITEM, i, reinterpret_cast(&itemData_shift)); 867 | } 868 | } 869 | else 870 | { 871 | for (int i = _nTabDragged ; i < nTab ; i++) 872 | { 873 | ::SendMessage(_hSelf, TCM_GETITEM, i+1, reinterpret_cast(&itemData_shift)); 874 | ::SendMessage(_hSelf, TCM_SETITEM, i, reinterpret_cast(&itemData_shift)); 875 | } 876 | } 877 | ::SendMessage(_hSelf, TCM_SETITEM, nTab, reinterpret_cast(&itemData_nDraggedTab)); 878 | 879 | //3. update the current index 880 | _nTabDragged = nTab; 881 | } 882 | } 883 | else 884 | { 885 | //::SetCursor(::LoadCursor(_hInst, MAKEINTRESOURCE(IDC_DRAG_TAB))); 886 | _isDraggingInside = false; 887 | } 888 | } 889 | bool CloseButtonZone::isHit(int x, int y, const RECT & testZone) const 890 | { 891 | if (((x + _width + _fromRight) < testZone.right) || (x > (testZone.right - _fromRight))) 892 | return false; 893 | 894 | if (((y - _hight - _fromTop) > testZone.top) || (y < (testZone.top + _fromTop))) 895 | return false; 896 | 897 | return true; 898 | } 899 | 900 | RECT CloseButtonZone::getButtonRectFrom(const RECT & tabItemRect) const 901 | { 902 | RECT rect; 903 | rect.right = tabItemRect.right - _fromRight; 904 | rect.left = rect.right - _width; 905 | rect.top = tabItemRect.top + _fromTop; 906 | rect.bottom = rect.top + _hight; 907 | 908 | return rect; 909 | } --------------------------------------------------------------------------------