diff options
Diffstat (limited to 'win32/HanjaDic.cxx')
-rw-r--r-- | win32/HanjaDic.cxx | 122 |
1 files changed, 65 insertions, 57 deletions
diff --git a/win32/HanjaDic.cxx b/win32/HanjaDic.cxx index a218b1f18..04df43845 100644 --- a/win32/HanjaDic.cxx +++ b/win32/HanjaDic.cxx @@ -8,23 +8,42 @@ #include <string> #include <string_view> +#include <memory> #define WIN32_LEAN_AND_MEAN 1 #include <windows.h> #include <ole2.h> -#include "UniConversion.h" #include "HanjaDic.h" -namespace Scintilla::Internal { +namespace Scintilla::Internal::HanjaDict { + +struct UnknownReleaser { + // Called by unique_ptr to destroy/free the resource + template <class T> + void operator()(T *pUnknown) noexcept { + // same as ReleaseUnknown() in PlatWin.h + try { + pUnknown->Release(); + } catch (...) { + // IUnknown::Release must not throw, ignore if it does. + } + } +}; + +struct BSTRDeleter { + void operator()(BSTR bstr) const noexcept { + SysFreeString(bstr); + } +}; -namespace HanjaDict { +using UniqueBSTR = std::unique_ptr<OLECHAR[], BSTRDeleter>; interface IRadical; interface IHanja; interface IStrokes; -typedef enum { HANJA_UNKNOWN = 0, HANJA_K0 = 1, HANJA_K1 = 2, HANJA_OTHER = 3 } HANJA_TYPE; +enum HANJA_TYPE { HANJA_UNKNOWN = 0, HANJA_K0 = 1, HANJA_K1 = 2, HANJA_OTHER = 3 }; interface IHanjaDic : IUnknown { STDMETHOD(OpenMainDic)(); @@ -60,82 +79,71 @@ extern "C" const GUID __declspec(selectany) IID_IHanjaDic = { 0xad75f3ac, 0x18cd, 0x48c6, { 0xa2, 0x7d, 0xf1, 0xe9, 0xa7, 0xdc, 0xe4, 0x32 } }; class HanjaDic { -private: - HRESULT hr; - CLSID CLSID_HanjaDic; - -public: - IHanjaDic *HJinterface; + std::unique_ptr<IHanjaDic, UnknownReleaser> HJinterface; - HanjaDic() : HJinterface(nullptr) { - hr = CLSIDFromProgID(OLESTR("mshjdic.hanjadic"), &CLSID_HanjaDic); + bool OpenHanjaDic(LPCOLESTR lpszProgID) noexcept { + CLSID CLSID_HanjaDic; + HRESULT hr = CLSIDFromProgID(lpszProgID, &CLSID_HanjaDic); if (SUCCEEDED(hr)) { + IHanjaDic *instance = nullptr; hr = CoCreateInstance(CLSID_HanjaDic, nullptr, - CLSCTX_INPROC_SERVER, IID_IHanjaDic, - (LPVOID *)& HJinterface); + CLSCTX_INPROC_SERVER, IID_IHanjaDic, + (LPVOID *)&instance); if (SUCCEEDED(hr)) { - hr = HJinterface->OpenMainDic(); + HJinterface.reset(instance); + hr = instance->OpenMainDic(); + return SUCCEEDED(hr); } } + return false; } - // Deleted so HanjaDic objects can not be copied. - HanjaDic(const HanjaDic &) = delete; - HanjaDic(HanjaDic &&) = delete; - HanjaDic &operator=(const HanjaDic &) = delete; - HanjaDic &operator=(HanjaDic &&) = delete; +public: + bool Open() noexcept { + return OpenHanjaDic(OLESTR("imkrhjd.hanjadic")) + || OpenHanjaDic(OLESTR("mshjdic.hanjadic")); + } - ~HanjaDic() { - if (SUCCEEDED(hr)) { - hr = HJinterface->CloseMainDic(); - try { - // This can never fail but IUnknown::Release is not marked noexcept. - HJinterface->Release(); - } catch (...) { - // Ignore any exception - } - } + void Close() const noexcept { + HJinterface->CloseMainDic(); } - bool HJdictAvailable() { - return SUCCEEDED(hr); + bool IsHanja(wchar_t hanja) const noexcept { + HANJA_TYPE hanjaType = HANJA_UNKNOWN; + const HRESULT hr = HJinterface->GetHanjaType(hanja, &hanjaType); + return SUCCEEDED(hr) && hanjaType > HANJA_UNKNOWN; } - bool IsHanja(int hanja) { - HANJA_TYPE hanjaType; - hr = HJinterface->GetHanjaType(static_cast<unsigned short>(hanja), &hanjaType); - if (SUCCEEDED(hr)) { - return (hanjaType > 0); - } - return false; + bool HanjaToHangul(BSTR bstrHanja, UniqueBSTR &bstrHangul) const noexcept { + BSTR result = nullptr; + const HRESULT hr = HJinterface->HanjaToHangul(bstrHanja, &result); + bstrHangul.reset(result); + return SUCCEEDED(hr); } }; -int GetHangulOfHanja(wchar_t *inout) { +bool GetHangulOfHanja(std::wstring &inout) noexcept { // Convert every hanja to hangul. - // Return the number of characters converted. - int changed = 0; + // Return whether any character been converted. + // Hanja linked to different notes in Hangul have different codes, + // so current character based conversion is enough. + // great thanks for BLUEnLIVE. + bool changed = false; HanjaDic dict; - if (dict.HJdictAvailable()) { - const size_t len = wcslen(inout); - wchar_t conv[UTF8MaxBytes] = {0}; - BSTR bstrHangul = SysAllocString(conv); - for (size_t i=0; i<len; i++) { - if (dict.IsHanja(static_cast<int>(inout[i]))) { // Pass hanja only! - conv[0] = inout[i]; - BSTR bstrHanja = SysAllocString(conv); - const HRESULT hr = dict.HJinterface->HanjaToHangul(bstrHanja, &bstrHangul); - if (SUCCEEDED(hr)) { - inout[i] = static_cast<wchar_t>(bstrHangul[0]); - changed += 1; + if (dict.Open()) { + for (wchar_t &character : inout) { + if (dict.IsHanja(character)) { // Pass hanja only! + const UniqueBSTR bstrHanja{SysAllocStringLen(&character, 1)}; + UniqueBSTR bstrHangul; + if (dict.HanjaToHangul(bstrHanja.get(), bstrHangul)) { + changed = true; + character = bstrHangul[0]; } - SysFreeString(bstrHanja); } } - SysFreeString(bstrHangul); + dict.Close(); } return changed; } } -} |