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