• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "core/common/ime/text_editing_value.h"
17 
18 #include "base/json/json_util.h"
19 #include "base/log/log.h"
20 #include "base/utils/macros.h"
21 #include "base/utils/string_utils.h"
22 
23 namespace OHOS::Ace {
24 namespace {
25 
26 // Negotiated fields with Java
27 const char TEXT[] = "text";
28 const char HINT[] = "hint";
29 const char SELECTION_START[] = "selectionStart";
30 const char SELECTION_END[] = "selectionEnd";
31 
32 } // namespace
33 
ParseFromJson(const JsonValue & json)34 void TextEditingValue::ParseFromJson(const JsonValue& json)
35 {
36     text = json.GetString(TEXT);
37     hint = json.GetString(HINT);
38     selection.baseOffset = json.GetInt(SELECTION_START, -1);
39     selection.extentOffset = json.GetInt(SELECTION_END, -1);
40 }
41 
ToJsonString() const42 std::string TextEditingValue::ToJsonString() const
43 {
44     auto json = JsonUtil::Create(true);
45     json->Put(TEXT, text.c_str());
46     json->Put(HINT, hint.c_str());
47     json->Put(SELECTION_START, selection.baseOffset);
48     json->Put(SELECTION_END, selection.extentOffset);
49     return json->ToString();
50 }
51 
operator ==(const TextEditingValue & other) const52 bool TextEditingValue::operator==(const TextEditingValue& other) const
53 {
54     if (selection != other.selection) {
55         return false;
56     }
57 
58     return text == other.text && hint == other.hint;
59 }
60 
operator !=(const TextEditingValue & other) const61 bool TextEditingValue::operator!=(const TextEditingValue& other) const
62 {
63     return !operator==(other);
64 }
65 
GetWideText() const66 std::wstring TextEditingValue::GetWideText() const
67 {
68     return StringUtils::ToWstring(text);
69 }
70 
MoveLeft()71 void TextEditingValue::MoveLeft()
72 {
73     if (selection.extentOffset <= 1) {
74         selection.Update(0);
75         return;
76     }
77 
78     auto utf16Text = StringUtils::Str8ToStr16(text);
79     int32_t prevCharIndex = std::min(selection.extentOffset - 1, static_cast<int32_t>(utf16Text.length()));
80     selection.Update(StringUtils::NotInUtf16Bmp(utf16Text[prevCharIndex]) ? prevCharIndex - 1 : prevCharIndex);
81 }
82 
MoveRight()83 void TextEditingValue::MoveRight()
84 {
85     auto utf16Text = StringUtils::Str8ToStr16(text);
86     if (utf16Text.length() < 1) {
87         LOGI("utf16Text length = 0");
88         return;
89     }
90     if (static_cast<size_t>(selection.extentOffset) >= utf16Text.length() - 1) {
91         selection.Update(utf16Text.length());
92         return;
93     }
94 
95     int32_t nextCharIndex = selection.extentOffset;
96     selection.Update(StringUtils::NotInUtf16Bmp(utf16Text[nextCharIndex])
97                          ? std::min(static_cast<int32_t>(utf16Text.length()), nextCharIndex + 2)
98                          : nextCharIndex + 1);
99 }
100 
MoveToPosition(int32_t position)101 void TextEditingValue::MoveToPosition(int32_t position)
102 {
103     if (position < 0) {
104         selection.Update(0);
105         return;
106     }
107     auto utf16Text = StringUtils::Str8ToStr16(text);
108     if (static_cast<size_t>(position) >= utf16Text.length()) {
109         selection.Update(utf16Text.length());
110         return;
111     }
112     selection.Update(position);
113 }
114 
UpdateSelection(int32_t both)115 void TextEditingValue::UpdateSelection(int32_t both)
116 {
117     UpdateSelection(both, both);
118 }
119 
UpdateSelection(int32_t start,int32_t end)120 void TextEditingValue::UpdateSelection(int32_t start, int32_t end)
121 {
122     if (start < 0) {
123         start = 0;
124     }
125     if (static_cast<size_t>(end) > GetWideText().length()) {
126         end = static_cast<int32_t>(GetWideText().length());
127     }
128     selection.Update(start, end);
129 }
130 
131 #if defined(IOS_PLATFORM)
UpdateCompose(int32_t start,int32_t end)132 void TextEditingValue::UpdateCompose(int32_t start, int32_t end)
133 {
134     compose.Update(start, end);
135 }
136 #endif
137 
138 
SelectionAwareTextManipulation(const TextManipulation & manipulation)139 void TextEditingValue::SelectionAwareTextManipulation(const TextManipulation& manipulation)
140 {
141     if (!manipulation) {
142         return;
143     }
144 
145     auto wideText = GetWideText();
146     int32_t start = selection.GetStart();
147     int32_t end = selection.GetEnd();
148     if (static_cast<size_t>(end) > wideText.length() || start > end) {
149         LOGD("Illegal selection for manipulate: start %{public}d, end %{public}d", start, end);
150         return;
151     }
152 
153     if ((start <= 0) && (end <= 0)) {
154         manipulation(wideText);
155     } else {
156         std::wstring beforeSelection;
157         if ((start > 0) && (static_cast<size_t>(start) <= wideText.length())) {
158             beforeSelection = wideText.substr(0, start);
159             manipulation(beforeSelection);
160         }
161 
162         std::wstring inSelection;
163         if (start != end) {
164             inSelection = wideText.substr(start, end - start);
165             manipulation(inSelection);
166         }
167 
168         std::wstring afterSelection;
169         size_t lenLeft = wideText.length() - static_cast<size_t>(end);
170         if (lenLeft > 0) {
171             afterSelection = wideText.substr(end, lenLeft);
172             manipulation(afterSelection);
173         }
174 
175         wideText = beforeSelection + inSelection + afterSelection;
176         if (selection.baseOffset > selection.extentOffset) {
177             selection.Update(beforeSelection.length() + inSelection.length(), beforeSelection.length());
178         } else {
179             selection.Update(beforeSelection.length(), beforeSelection.length() + inSelection.length());
180         }
181     }
182 
183     text = StringUtils::ToString(wideText);
184 }
185 
GetBeforeSelection() const186 std::string TextEditingValue::GetBeforeSelection() const
187 {
188     auto wideText = GetWideText();
189     int32_t start = selection.GetStart();
190     if (static_cast<size_t>(start) > wideText.length()) {
191         LOGD("Illegal selection for GetBeforeSelection: start %{public}d", start);
192         return "";
193     }
194 
195     std::string beforeText;
196     if (start > 0) {
197         std::wstring beforeSelection = wideText.substr(0, start);
198         beforeText = StringUtils::ToString(beforeSelection);
199     }
200     return beforeText;
201 }
202 
GetSelectedText() const203 std::string TextEditingValue::GetSelectedText() const
204 {
205     auto wideText = GetWideText();
206     int32_t start = selection.GetStart();
207     int32_t end = selection.GetEnd();
208     if (static_cast<size_t>(end) > wideText.length() || start > end) {
209         LOGD("Illegal selection for GetSelectedText: start %{public}d, end %{public}d", start, end);
210         return "";
211     }
212 
213     std::string selectedText;
214     if (start < 0) {
215         start = 0;
216     }
217     if (end > 0 && start != end) {
218         std::wstring inSelection = wideText.substr(start, end - start);
219         selectedText = StringUtils::ToString(inSelection);
220     }
221     return selectedText;
222 }
223 
GetSelectedText(const TextSelection & textSelection) const224 std::string TextEditingValue::GetSelectedText(const TextSelection& textSelection) const
225 {
226     auto wideText = GetWideText();
227     int32_t start = textSelection.GetStart();
228     int32_t end = textSelection.GetEnd();
229     std::string selectedText;
230     if (start < 0) {
231         start = 0;
232     }
233     if (static_cast<size_t>(end) > wideText.length()) {
234         end = static_cast<int32_t>(wideText.length());
235     }
236 
237     if (end > 0 && start < end) {
238         std::wstring inSelection = wideText.substr(start, end - start);
239         selectedText = StringUtils::ToString(inSelection);
240     }
241     return selectedText;
242 }
243 
GetAfterSelection() const244 std::string TextEditingValue::GetAfterSelection() const
245 {
246     auto wideText = GetWideText();
247     int32_t end = selection.GetEnd();
248     if (static_cast<size_t>(end) > wideText.length()) {
249         LOGD("Illegal selection for GetAfterSelection: start %{public}d", end);
250         return "";
251     }
252 
253     std::string afterText;
254     if (end <= 0) {
255         afterText = StringUtils::ToString(wideText);
256     } else {
257         std::wstring afterSelection = wideText.substr(end);
258         afterText = StringUtils::ToString(afterSelection);
259     }
260     return afterText;
261 }
262 
Delete(int32_t start,int32_t end)263 void TextEditingValue::Delete(int32_t start, int32_t end)
264 {
265     auto wideText = GetWideText();
266     auto length = (int32_t)wideText.length();
267     int32_t startPos = std::max(std::min(start, end), 0);
268     int32_t endPos = std::min(std::max(start, end), length);
269     if (startPos >= endPos) {
270         return;
271     }
272 
273     auto textAfterDelete = wideText.substr(0, startPos) + wideText.substr(endPos);
274     text = StringUtils::ToString(textAfterDelete);
275     selection.Update(startPos);
276 }
277 
Append(const std::string & newText)278 void TextEditingValue::Append(const std::string& newText)
279 {
280     text = text + newText;
281 }
282 
283 } // namespace OHOS::Ace
284