1*8af74909SZhong Yang // Scintilla source code edit control
2*8af74909SZhong Yang /** @file HanjaDic.cxx
3*8af74909SZhong Yang ** Korean Hanja Dictionary
4*8af74909SZhong Yang ** Convert between Korean Hanja and Hangul by COM interface.
5*8af74909SZhong Yang **/
6*8af74909SZhong Yang // Copyright 2015 by Neil Hodgson <[email protected]>
7*8af74909SZhong Yang // The License.txt file describes the conditions under which this software may be distributed.
8*8af74909SZhong Yang
9*8af74909SZhong Yang #include <string>
10*8af74909SZhong Yang #include <string_view>
11*8af74909SZhong Yang
12*8af74909SZhong Yang #include <windows.h>
13*8af74909SZhong Yang
14*8af74909SZhong Yang #include "UniConversion.h"
15*8af74909SZhong Yang #include "HanjaDic.h"
16*8af74909SZhong Yang
17*8af74909SZhong Yang namespace Scintilla {
18*8af74909SZhong Yang
19*8af74909SZhong Yang namespace HanjaDict {
20*8af74909SZhong Yang
21*8af74909SZhong Yang interface IRadical;
22*8af74909SZhong Yang interface IHanja;
23*8af74909SZhong Yang interface IStrokes;
24*8af74909SZhong Yang
25*8af74909SZhong Yang typedef enum { HANJA_UNKNOWN = 0, HANJA_K0 = 1, HANJA_K1 = 2, HANJA_OTHER = 3 } HANJA_TYPE;
26*8af74909SZhong Yang
27*8af74909SZhong Yang interface IHanjaDic : IUnknown {
28*8af74909SZhong Yang STDMETHOD(OpenMainDic)();
29*8af74909SZhong Yang STDMETHOD(CloseMainDic)();
30*8af74909SZhong Yang STDMETHOD(GetHanjaWords)(BSTR bstrHangul, SAFEARRAY* ppsaHanja, VARIANT_BOOL* pfFound);
31*8af74909SZhong Yang STDMETHOD(GetHanjaChars)(unsigned short wchHangul, BSTR* pbstrHanjaChars, VARIANT_BOOL* pfFound);
32*8af74909SZhong Yang STDMETHOD(HanjaToHangul)(BSTR bstrHanja, BSTR* pbstrHangul);
33*8af74909SZhong Yang STDMETHOD(GetHanjaType)(unsigned short wchHanja, HANJA_TYPE* pHanjaType);
34*8af74909SZhong Yang STDMETHOD(GetHanjaSense)(unsigned short wchHanja, BSTR* pbstrSense);
35*8af74909SZhong Yang STDMETHOD(GetRadicalID)(short SeqNumOfRadical, short* pRadicalID, unsigned short* pwchRadical);
36*8af74909SZhong Yang STDMETHOD(GetRadical)(short nRadicalID, IRadical** ppIRadical);
37*8af74909SZhong Yang STDMETHOD(RadicalIDToHanja)(short nRadicalID, unsigned short* pwchRadical);
38*8af74909SZhong Yang STDMETHOD(GetHanja)(unsigned short wchHanja, IHanja** ppIHanja);
39*8af74909SZhong Yang STDMETHOD(GetStrokes)(short nStrokes, IStrokes** ppIStrokes);
40*8af74909SZhong Yang STDMETHOD(OpenDefaultCustomDic)();
41*8af74909SZhong Yang STDMETHOD(OpenCustomDic)(BSTR bstrPath, long* plUdr);
42*8af74909SZhong Yang STDMETHOD(CloseDefaultCustomDic)();
43*8af74909SZhong Yang STDMETHOD(CloseCustomDic)(long lUdr);
44*8af74909SZhong Yang STDMETHOD(CloseAllCustomDics)();
45*8af74909SZhong Yang STDMETHOD(GetDefaultCustomHanjaWords)(BSTR bstrHangul, SAFEARRAY** ppsaHanja, VARIANT_BOOL* pfFound);
46*8af74909SZhong Yang STDMETHOD(GetCustomHanjaWords)(long lUdr, BSTR bstrHangul, SAFEARRAY** ppsaHanja, VARIANT_BOOL* pfFound);
47*8af74909SZhong Yang STDMETHOD(PutDefaultCustomHanjaWord)(BSTR bstrHangul, BSTR bstrHanja);
48*8af74909SZhong Yang STDMETHOD(PutCustomHanjaWord)(long lUdr, BSTR bstrHangul, BSTR bstrHanja);
49*8af74909SZhong Yang STDMETHOD(MaxNumOfRadicals)(short* pVal);
50*8af74909SZhong Yang STDMETHOD(MaxNumOfStrokes)(short* pVal);
51*8af74909SZhong Yang STDMETHOD(DefaultCustomDic)(long* pVal);
52*8af74909SZhong Yang STDMETHOD(DefaultCustomDic)(long pVal);
53*8af74909SZhong Yang STDMETHOD(MaxHanjaType)(HANJA_TYPE* pHanjaType);
54*8af74909SZhong Yang STDMETHOD(MaxHanjaType)(HANJA_TYPE pHanjaType);
55*8af74909SZhong Yang };
56*8af74909SZhong Yang
57*8af74909SZhong Yang extern "C" const GUID __declspec(selectany) IID_IHanjaDic =
58*8af74909SZhong Yang { 0xad75f3ac, 0x18cd, 0x48c6, { 0xa2, 0x7d, 0xf1, 0xe9, 0xa7, 0xdc, 0xe4, 0x32 } };
59*8af74909SZhong Yang
60*8af74909SZhong Yang class HanjaDic {
61*8af74909SZhong Yang private:
62*8af74909SZhong Yang HRESULT hr;
63*8af74909SZhong Yang CLSID CLSID_HanjaDic;
64*8af74909SZhong Yang
65*8af74909SZhong Yang public:
66*8af74909SZhong Yang IHanjaDic *HJinterface;
67*8af74909SZhong Yang
HanjaDic()68*8af74909SZhong Yang HanjaDic() : HJinterface(nullptr) {
69*8af74909SZhong Yang hr = CLSIDFromProgID(OLESTR("mshjdic.hanjadic"), &CLSID_HanjaDic);
70*8af74909SZhong Yang if (SUCCEEDED(hr)) {
71*8af74909SZhong Yang hr = CoCreateInstance(CLSID_HanjaDic, nullptr,
72*8af74909SZhong Yang CLSCTX_INPROC_SERVER, IID_IHanjaDic,
73*8af74909SZhong Yang (LPVOID *)& HJinterface);
74*8af74909SZhong Yang if (SUCCEEDED(hr)) {
75*8af74909SZhong Yang hr = HJinterface->OpenMainDic();
76*8af74909SZhong Yang }
77*8af74909SZhong Yang }
78*8af74909SZhong Yang }
79*8af74909SZhong Yang
~HanjaDic()80*8af74909SZhong Yang ~HanjaDic() {
81*8af74909SZhong Yang if (SUCCEEDED(hr)) {
82*8af74909SZhong Yang hr = HJinterface->CloseMainDic();
83*8af74909SZhong Yang HJinterface->Release();
84*8af74909SZhong Yang }
85*8af74909SZhong Yang }
86*8af74909SZhong Yang
HJdictAvailable()87*8af74909SZhong Yang bool HJdictAvailable() {
88*8af74909SZhong Yang return SUCCEEDED(hr);
89*8af74909SZhong Yang }
90*8af74909SZhong Yang
IsHanja(int hanja)91*8af74909SZhong Yang bool IsHanja(int hanja) {
92*8af74909SZhong Yang HANJA_TYPE hanjaType;
93*8af74909SZhong Yang hr = HJinterface->GetHanjaType(static_cast<unsigned short>(hanja), &hanjaType);
94*8af74909SZhong Yang if (SUCCEEDED(hr)) {
95*8af74909SZhong Yang return (hanjaType > 0);
96*8af74909SZhong Yang }
97*8af74909SZhong Yang return false;
98*8af74909SZhong Yang }
99*8af74909SZhong Yang };
100*8af74909SZhong Yang
GetHangulOfHanja(wchar_t * inout)101*8af74909SZhong Yang int GetHangulOfHanja(wchar_t *inout) {
102*8af74909SZhong Yang // Convert every hanja to hangul.
103*8af74909SZhong Yang // Return the number of characters converted.
104*8af74909SZhong Yang int changed = 0;
105*8af74909SZhong Yang HanjaDic dict;
106*8af74909SZhong Yang if (dict.HJdictAvailable()) {
107*8af74909SZhong Yang const size_t len = wcslen(inout);
108*8af74909SZhong Yang wchar_t conv[UTF8MaxBytes] = {0};
109*8af74909SZhong Yang BSTR bstrHangul = SysAllocString(conv);
110*8af74909SZhong Yang for (size_t i=0; i<len; i++) {
111*8af74909SZhong Yang if (dict.IsHanja(static_cast<int>(inout[i]))) { // Pass hanja only!
112*8af74909SZhong Yang conv[0] = inout[i];
113*8af74909SZhong Yang BSTR bstrHanja = SysAllocString(conv);
114*8af74909SZhong Yang const HRESULT hr = dict.HJinterface->HanjaToHangul(bstrHanja, &bstrHangul);
115*8af74909SZhong Yang if (SUCCEEDED(hr)) {
116*8af74909SZhong Yang inout[i] = static_cast<wchar_t>(bstrHangul[0]);
117*8af74909SZhong Yang changed += 1;
118*8af74909SZhong Yang }
119*8af74909SZhong Yang SysFreeString(bstrHanja);
120*8af74909SZhong Yang }
121*8af74909SZhong Yang }
122*8af74909SZhong Yang SysFreeString(bstrHangul);
123*8af74909SZhong Yang }
124*8af74909SZhong Yang return changed;
125*8af74909SZhong Yang }
126*8af74909SZhong Yang
127*8af74909SZhong Yang }
128*8af74909SZhong Yang }
129