• 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/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             start = std::clamp(start, 0, static_cast<int32_t>(wideText.length()));
166             inSelection = wideText.substr(start, end - start);
167             manipulation(inSelection);
168         }
169 
170         std::wstring afterSelection;
171         size_t lenLeft = wideText.length() - static_cast<size_t>(end);
172         if (lenLeft > 0) {
173             end = std::clamp(end, 0, static_cast<int32_t>(wideText.length()));
174             afterSelection = wideText.substr(end, lenLeft);
175             manipulation(afterSelection);
176         }
177 
178         wideText = beforeSelection + inSelection + afterSelection;
179         if (selection.baseOffset > selection.extentOffset) {
180             selection.Update(beforeSelection.length() + inSelection.length(), beforeSelection.length());
181         } else {
182             selection.Update(beforeSelection.length(), beforeSelection.length() + inSelection.length());
183         }
184     }
185 
186     text = StringUtils::ToString(wideText);
187 }
188 
GetBeforeSelection() const189 std::string TextEditingValue::GetBeforeSelection() const
190 {
191     auto wideText = GetWideText();
192     int32_t start = selection.GetStart();
193     if (static_cast<size_t>(start) > wideText.length()) {
194         return "";
195     }
196 
197     std::string beforeText;
198     if (start > 0) {
199         std::wstring beforeSelection = wideText.substr(0, start);
200         beforeText = StringUtils::ToString(beforeSelection);
201     }
202     return beforeText;
203 }
204 
GetSelectedText() const205 std::string TextEditingValue::GetSelectedText() const
206 {
207     auto wideText = GetWideText();
208     int32_t start = selection.GetStart();
209     int32_t end = selection.GetEnd();
210     if (static_cast<size_t>(end) > wideText.length() || start > end) {
211         return "";
212     }
213 
214     std::string selectedText;
215     if (start < 0) {
216         start = 0;
217     }
218     if (end > 0 && start != end) {
219         start = std::clamp(start, 0, static_cast<int32_t>(wideText.length()));
220         std::wstring inSelection = wideText.substr(start, end - start);
221         selectedText = StringUtils::ToString(inSelection);
222     }
223     return selectedText;
224 }
225 
GetSelectedText(const TextSelection & textSelection) const226 std::string TextEditingValue::GetSelectedText(const TextSelection& textSelection) const
227 {
228     auto wideText = GetWideText();
229     int32_t start = textSelection.GetStart();
230     int32_t end = textSelection.GetEnd();
231     std::string selectedText;
232     if (start < 0) {
233         start = 0;
234     }
235     if (static_cast<size_t>(end) > wideText.length()) {
236         end = static_cast<int32_t>(wideText.length());
237     }
238 
239     if (end > 0 && start < end) {
240         start = std::clamp(start, 0, static_cast<int32_t>(wideText.length()));
241         std::wstring inSelection = wideText.substr(start, end - start);
242         selectedText = StringUtils::ToString(inSelection);
243     }
244     return selectedText;
245 }
246 
GetAfterSelection() const247 std::string TextEditingValue::GetAfterSelection() const
248 {
249     auto wideText = GetWideText();
250     int32_t end = selection.GetEnd();
251     if (static_cast<size_t>(end) > wideText.length()) {
252         return "";
253     }
254 
255     std::string afterText;
256     if (end <= 0) {
257         afterText = StringUtils::ToString(wideText);
258     } else {
259         std::wstring afterSelection = wideText.substr(end);
260         afterText = StringUtils::ToString(afterSelection);
261     }
262     return afterText;
263 }
264 
Delete(int32_t start,int32_t end)265 void TextEditingValue::Delete(int32_t start, int32_t end)
266 {
267     auto wideText = GetWideText();
268     auto length = (int32_t)wideText.length();
269     int32_t startPos = std::max(std::min(start, end), 0);
270     int32_t endPos = std::min(std::max(start, end), length);
271     if (startPos >= endPos) {
272         return;
273     }
274 
275     auto textAfterDelete = wideText.substr(0, startPos) + wideText.substr(endPos);
276     text = StringUtils::ToString(textAfterDelete);
277     selection.Update(startPos);
278 }
279 
Append(const std::string & newText)280 void TextEditingValue::Append(const std::string& newText)
281 {
282     text = text + newText;
283 }
284 
285 } // namespace OHOS::Ace
286