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