xref: /reactos/dll/ime/msctfime/profile.cpp (revision 0c2cdcae)
1 /*
2  * PROJECT:     ReactOS msctfime.ime
3  * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4  * PURPOSE:     Profile of msctfime.ime
5  * COPYRIGHT:   Copyright 2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6  */
7 
8 #include "msctfime.h"
9 
10 WINE_DEFAULT_DEBUG_CHANNEL(msctfime);
11 
12 /// @implemented
13 CicProfile::CicProfile()
14 {
15     m_dwFlags &= 0xFFFFFFF0;
16     m_cRefs = 1;
17     m_pIPProfiles = NULL;
18     m_pActiveLanguageProfileNotifySink = NULL;
19     m_LangID1 = 0;
20     m_nCodePage = CP_ACP;
21     m_LangID2 = 0;
22     m_dwUnknown1 = 0;
23 }
24 
25 /// @implemented
26 CicProfile::~CicProfile()
27 {
28     if (m_pIPProfiles)
29     {
30         if (m_LangID1)
31             m_pIPProfiles->ChangeCurrentLanguage(m_LangID1);
32 
33         m_pIPProfiles->Release();
34         m_pIPProfiles = NULL;
35     }
36 
37     if (m_pActiveLanguageProfileNotifySink)
38     {
39         m_pActiveLanguageProfileNotifySink->_Unadvise();
40         m_pActiveLanguageProfileNotifySink->Release();
41         m_pActiveLanguageProfileNotifySink = NULL;
42     }
43 }
44 
45 /// @implemented
46 STDMETHODIMP CicProfile::QueryInterface(REFIID riid, LPVOID* ppvObj)
47 {
48     *ppvObj = NULL;
49     return E_NOINTERFACE;
50 }
51 
52 /// @implemented
53 STDMETHODIMP_(ULONG) CicProfile::AddRef()
54 {
55     return ::InterlockedIncrement(&m_cRefs);
56 }
57 
58 /// @implemented
59 STDMETHODIMP_(ULONG) CicProfile::Release()
60 {
61     if (::InterlockedDecrement(&m_cRefs) == 0)
62     {
63         delete this;
64         return 0;
65     }
66     return m_cRefs;
67 }
68 
69 /// @implemented
70 INT CALLBACK
71 CicProfile::ActiveLanguageProfileNotifySinkCallback(
72     REFGUID rguid1,
73     REFGUID rguid2,
74     BOOL fActivated,
75     LPVOID pUserData)
76 {
77     CicProfile *pThis = (CicProfile *)pUserData;
78     pThis->m_dwFlags &= ~0xE;
79     return 0;
80 }
81 
82 /// @implemented
83 HRESULT CicProfile::GetCodePageA(_Out_ UINT *puCodePage)
84 {
85     if (!puCodePage)
86         return E_INVALIDARG;
87 
88     if (m_dwFlags & 2)
89     {
90         *puCodePage = m_nCodePage;
91         return S_OK;
92     }
93 
94     *puCodePage = 0;
95 
96     LANGID LangID;
97     HRESULT hr = GetLangId(&LangID);
98     if (FAILED(hr))
99         return E_FAIL;
100 
101     WCHAR szBuff[12];
102     INT cch = ::GetLocaleInfoW(LangID, LOCALE_IDEFAULTANSICODEPAGE, szBuff, _countof(szBuff));
103     if (cch)
104     {
105         szBuff[cch] = 0;
106         m_nCodePage = *puCodePage = wcstoul(szBuff, NULL, 10);
107         m_dwFlags |= 2;
108     }
109 
110     return S_OK;
111 }
112 
113 /// @implemented
114 HRESULT CicProfile::GetLangId(_Out_ LANGID *pLangID)
115 {
116     *pLangID = 0;
117 
118     if (!m_pIPProfiles)
119         return E_FAIL;
120 
121     if (m_dwFlags & 4)
122     {
123         *pLangID = m_LangID2;
124         return S_OK;
125     }
126 
127     HRESULT hr = m_pIPProfiles->GetCurrentLanguage(pLangID);
128     if (SUCCEEDED(hr))
129     {
130         m_dwFlags |= 4;
131         m_LangID2 = *pLangID;
132     }
133 
134     return hr;
135 }
136 
137 /// @implemented
138 HRESULT
139 CicProfile::InitProfileInstance(_Inout_ TLS *pTLS)
140 {
141     HRESULT hr = TF_CreateInputProcessorProfiles(&m_pIPProfiles);
142     if (FAILED(hr))
143         return hr;
144 
145     if (!m_pActiveLanguageProfileNotifySink)
146     {
147         CActiveLanguageProfileNotifySink *pSink =
148             new(cicNoThrow) CActiveLanguageProfileNotifySink(
149                 CicProfile::ActiveLanguageProfileNotifySinkCallback, this);
150         if (!pSink)
151         {
152             m_pIPProfiles->Release();
153             m_pIPProfiles = NULL;
154             return E_FAIL;
155         }
156         m_pActiveLanguageProfileNotifySink = pSink;
157     }
158 
159     if (pTLS->m_pThreadMgr)
160         m_pActiveLanguageProfileNotifySink->_Advise(pTLS->m_pThreadMgr);
161 
162     return hr;
163 }
164 
165 /// @unimplemented
166 HRESULT
167 CicProfile::GetActiveLanguageProfile(
168     _In_ HKL hKL,
169     _In_ REFGUID rguid,
170     _Out_ TF_LANGUAGEPROFILE *pProfile)
171 {
172     return E_NOTIMPL;
173 }
174 
175 /// The return value of CicProfile::IsIME is brain-damaged.
176 /// @unimplemented
177 BOOL CicProfile::IsIME(HKL hKL)
178 {
179     return TRUE;
180 }
181