1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "input_method_ffi.h"
17
18#include "inputmethod_trace.h"
19#include "cj_input_method_controller.h"
20#include "input_method_property.h"
21#include "setting_listeners.h"
22#include "global.h"
23#include "utils.h"
24
25namespace OHOS::MiscServices {
26extern "C" {
27int32_t FfiInputMethodGetDefaultInputMethod(CInputMethodProperty &props)
28{
29    auto ctrl = InputMethodController::GetInstance();
30    if (ctrl == nullptr) {
31        return ERR_NO_MEMORY;
32    }
33    std::shared_ptr<Property> property;
34    int32_t ret = ctrl->GetDefaultInputMethod(property);
35    if (property == nullptr) {
36        IMSA_HILOGE("default input method is nullptr!");
37        return ret;
38    }
39    Utils::InputMethodProperty2C(props, *property);
40    return ret;
41}
42
43int32_t FfiInputMethodGetCurrentInputMethod(CInputMethodProperty &props)
44{
45    auto ctrl = InputMethodController::GetInstance();
46    if (ctrl == nullptr) {
47        return ERR_NO_MEMORY;
48    }
49    std::shared_ptr<Property> property = ctrl->GetCurrentInputMethod();
50    if (property == nullptr) {
51        IMSA_HILOGE("current input method is nullptr!");
52        return ERR_NO_MEMORY;
53    }
54    Utils::InputMethodProperty2C(props, *property);
55    return 0;
56}
57
58int32_t FfiInputMethodSwitchInputMethod(bool &result, CInputMethodProperty props)
59{
60    InputMethodSyncTrace tracer("CJInputMethod_SwitchInputMethod");
61    auto ctrl = InputMethodController::GetInstance();
62    if (ctrl == nullptr) {
63        return ERR_NO_MEMORY;
64    }
65    int32_t errCode =
66        ctrl->SwitchInputMethod(SwitchTrigger::CURRENT_IME, std::string(props.name), std::string(props.id));
67    if (errCode == ErrorCode::NO_ERROR) {
68        result = true;
69    }
70    return errCode;
71}
72
73int32_t FfiInputMethodSwitchCurrentInputMethodSubtype(bool &result, CInputMethodSubtype target)
74{
75    InputMethodSyncTrace tracer("CJInputMethod_SwitchCurrentInputMethodSubtype");
76    auto ctrl = InputMethodController::GetInstance();
77    if (ctrl == nullptr) {
78        return ERR_NO_MEMORY;
79    }
80    int32_t errCode =
81        ctrl->SwitchInputMethod(SwitchTrigger::CURRENT_IME, std::string(target.name), std::string(target.id));
82    if (errCode == ErrorCode::NO_ERROR) {
83        result = true;
84    }
85    return errCode;
86}
87
88int32_t FfiInputMethodGetCurrentInputMethodSubtype(CInputMethodSubtype &props)
89{
90    auto ctrl = InputMethodController::GetInstance();
91    if (ctrl == nullptr) {
92        return ERR_NO_MEMORY;
93    }
94    std::shared_ptr<SubProperty> subProperty = ctrl->GetCurrentInputMethodSubtype();
95    if (subProperty == nullptr) {
96        IMSA_HILOGE("current input method subtype is nullptr!");
97        return ERR_NO_MEMORY;
98    }
99    Utils::InputMethodSubProperty2C(props, *subProperty);
100    return 0;
101}
102
103int32_t FfiInputMethodSwitchCurrentInputMethodAndSubtype(bool &result,
104    CInputMethodProperty target, CInputMethodSubtype subtype)
105{
106    InputMethodSyncTrace tracer("CJInputMethod_SwitchCurrentInputMethodAndSubtype");
107    auto ctrl = InputMethodController::GetInstance();
108    if (ctrl == nullptr) {
109        return ERR_NO_MEMORY;
110    }
111    int32_t errCode = ctrl->SwitchInputMethod(SwitchTrigger::CURRENT_IME,
112        std::string(subtype.name), std::string(subtype.id));
113    if (errCode == ErrorCode::NO_ERROR) {
114        result = true;
115    }
116    return errCode;
117}
118
119int32_t FfiInputMethodGetSystemInputMethodConfigAbility(CElementName &elem)
120{
121    OHOS::AppExecFwk::ElementName inputMethodConfig;
122    auto ctrl = InputMethodController::GetInstance();
123    if (ctrl == nullptr) {
124        return ERR_NO_MEMORY;
125    }
126    int32_t ret = ctrl->GetInputMethodConfig(inputMethodConfig);
127    if (ret == ErrorCode::NO_ERROR) {
128        elem.deviceId = Utils::MallocCString(inputMethodConfig.GetDeviceID());
129        elem.bundleName = Utils::MallocCString(inputMethodConfig.GetBundleName());
130        elem.abilityName = Utils::MallocCString(inputMethodConfig.GetAbilityName());
131        elem.moduleName = Utils::MallocCString(inputMethodConfig.GetModuleName());
132    }
133    return ret;
134}
135
136RetInputMethodSubtype FfiInputMethodSettingListInputMethodSubtype(CInputMethodProperty props)
137{
138    IMSA_HILOGD("run in ListInputMethodSubtype");
139    RetInputMethodSubtype ret{};
140    Property property = Utils::C2InputMethodProperty(props);
141    std::vector<SubProperty> subProps;
142    auto ctrl = InputMethodController::GetInstance();
143    if (ctrl == nullptr) {
144        ret.code = ERR_NO_MEMORY;
145        return ret;
146    }
147    int32_t errCode = ctrl->ListInputMethodSubtype(property, subProps);
148    ret.code = errCode;
149    if (errCode != ErrorCode::NO_ERROR) {
150        return ret;
151    }
152    IMSA_HILOGI("exec ListInputMethodSubtype success");
153    ret.size = static_cast<int64_t>(subProps.size());
154    if (ret.size > 0) {
155        ret.head = static_cast<CInputMethodSubtype *>(malloc(sizeof(CInputMethodSubtype) * ret.size));
156    }
157    if (ret.head == nullptr) {
158        ret.size = 0;
159        return ret;
160    }
161    for (unsigned int i = 0; i < ret.size; i++) {
162        CInputMethodSubtype props;
163        Utils::InputMethodSubProperty2C(props, subProps[i]);
164        ret.head[i] = props;
165    }
166    return ret;
167}
168
169RetInputMethodSubtype FfiInputMethodSettingListCurrentInputMethodSubtype()
170{
171    IMSA_HILOGD("run in ListCurrentInputMethodSubtype");
172    RetInputMethodSubtype ret{};
173    std::vector<SubProperty> subProps;
174    auto ctrl = InputMethodController::GetInstance();
175    if (ctrl == nullptr) {
176        ret.code = ERR_NO_MEMORY;
177        return ret;
178    }
179    int32_t errCode = ctrl->ListCurrentInputMethodSubtype(subProps);
180    ret.code = errCode;
181    if (errCode != ErrorCode::NO_ERROR) {
182        return ret;
183    }
184    IMSA_HILOGI("exec ListCurrentInputMethodSubtype success.");
185    ret.size = static_cast<int64_t>(subProps.size());
186    if (ret.size > 0) {
187        ret.head = static_cast<CInputMethodSubtype *>(malloc(sizeof(CInputMethodSubtype) * ret.size));
188    }
189    if (ret.head == nullptr) {
190        ret.size = 0;
191        return ret;
192    }
193    for (unsigned int i = 0; i < ret.size; i++) {
194        CInputMethodSubtype props;
195        Utils::InputMethodSubProperty2C(props, subProps[i]);
196        ret.head[i] = props;
197    }
198    return ret;
199}
200
201RetInputMethodProperty FfiInputMethodSettingGetInputMethods(bool enable)
202{
203    IMSA_HILOGD("run in");
204    RetInputMethodProperty ret{};
205    std::vector<Property> properties;
206    auto ctrl = InputMethodController::GetInstance();
207    if (ctrl == nullptr) {
208        ret.code = ERR_NO_MEMORY;
209        return ret;
210    }
211    int32_t errCode = ctrl->ListInputMethod(enable, properties);
212    ret.code = errCode;
213    if (errCode != ErrorCode::NO_ERROR) {
214        return ret;
215    }
216    ret.size = static_cast<int64_t>(properties.size());
217    if (ret.size > 0) {
218        ret.head = static_cast<CInputMethodProperty *>(malloc(sizeof(CInputMethodProperty) * ret.size));
219    }
220    if (ret.head == nullptr) {
221        ret.size = 0;
222        return ret;
223    }
224    for (unsigned int i = 0; i < ret.size; i++) {
225        CInputMethodProperty props;
226        Utils::InputMethodProperty2C(props, properties[i]);
227        ret.head[i] = props;
228    }
229    return ret;
230}
231
232RetInputMethodProperty FfiInputMethodSettingGetAllInputMethods()
233{
234    IMSA_HILOGD("run in");
235    RetInputMethodProperty ret{};
236    std::vector<Property> properties;
237    auto ctrl = InputMethodController::GetInstance();
238    if (ctrl == nullptr) {
239        ret.code = ERR_NO_MEMORY;
240        return ret;
241    }
242    int32_t errCode = ctrl->ListInputMethod(properties);
243    ret.code = errCode;
244    if (errCode != ErrorCode::NO_ERROR) {
245        return ret;
246    }
247    ret.size = static_cast<int64_t>(properties.size());
248    if (ret.size > 0) {
249        ret.head = static_cast<CInputMethodProperty *>(malloc(sizeof(CInputMethodProperty) * ret.size));
250    }
251    if (ret.head == nullptr) {
252        ret.size = 0;
253        return ret;
254    }
255    for (unsigned int i = 0; i < ret.size; i++) {
256        CInputMethodProperty props;
257        Utils::InputMethodProperty2C(props, properties[i]);
258        ret.head[i] = props;
259    }
260    return ret;
261}
262
263int32_t FfiInputMethodSettingOn(uint32_t type, void (*func)(CInputMethodProperty, CInputMethodSubtype))
264{
265    auto setting = CJGetInputMethodSetting::GetIMSInstance();
266    if (setting == nullptr) {
267        return ERR_NO_MEMORY;
268    }
269    return setting->Subscribe(type, func);
270}
271
272int32_t FfiInputMethodSettingOff(uint32_t type)
273{
274    auto setting = CJGetInputMethodSetting::GetIMSInstance();
275    if (setting == nullptr) {
276        return ERR_NO_MEMORY;
277    }
278    return setting->UnSubscribe(type);
279}
280
281int32_t FfiInputMethodSettingShowOptionalInputMethods(bool& result)
282{
283    IMSA_HILOGD("start JsGetInputMethodSetting.");
284    auto ctrl = InputMethodController::GetInstance();
285    if (ctrl == nullptr) {
286        return ERR_NO_MEMORY;
287    }
288    int32_t errCode = ctrl->DisplayOptionalInputMethod();
289    if (errCode == ErrorCode::NO_ERROR) {
290        IMSA_HILOGI("exec DisplayOptionalInputMethod success");
291        result = true;
292    }
293    return errCode;
294}
295
296int32_t FfiInputMethodControllerOn(int8_t type, int64_t id)
297{
298    return CjInputMethodController::Subscribe(type, id);
299}
300
301int32_t FfiInputMethodControllerOff(int8_t type)
302{
303    return CjInputMethodController::Unsubscribe(type);
304}
305
306int32_t FfiInputMethodControllerAttach(bool showKeyboard, CTextConfig txtCfg)
307{
308    return CjInputMethodController::Attach(txtCfg, showKeyboard);
309}
310
311int32_t FfiInputMethodControllerDetach()
312{
313    return CjInputMethodController::Detach();
314}
315
316int32_t FfiInputMethodControllerShowTextInput()
317{
318    return CjInputMethodController::ShowTextInput();
319}
320
321int32_t FfiInputMethodControllerHideTextInput()
322{
323    return CjInputMethodController::HideTextInput();
324}
325
326int32_t FfiInputMethodControllerSetCallingWindow(uint32_t windowId)
327{
328    return CjInputMethodController::SetCallingWindow(windowId);
329}
330
331int32_t FfiInputMethodControllerUpdateCursor(CCursorInfo cursor)
332{
333    return CjInputMethodController::UpdateCursor(cursor);
334}
335
336int32_t FfiInputMethodControllerChangeSelection(char *text, int32_t start, int32_t end)
337{
338    return CjInputMethodController::ChangeSelection(std::string(text), start, end);
339}
340
341int32_t FfiInputMethodControllerUpdateAttribute(CInputAttribute inputAttribute)
342{
343    return CjInputMethodController::UpdateAttribute(inputAttribute);
344}
345
346int32_t FfiInputMethodControllerShowSoftKeyboard()
347{
348    return CjInputMethodController::ShowSoftKeyboard();
349}
350
351int32_t FfiInputMethodControllerHideSoftKeyboard()
352{
353    return CjInputMethodController::HideSoftKeyboard();
354}
355
356int32_t FfiInputMethodControllerStopInputSession()
357{
358    return CjInputMethodController::StopInputSession();
359}
360}
361}