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