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 "core/components_ng/pattern/text/span/mutable_span_string.h"
17
18 #include <algorithm>
19 #include <iterator>
20 #include <vector>
21
22 #include "base/memory/referenced.h"
23 #include "base/utils/string_utils.h"
24 #include "core/components_ng/pattern/text/span/span_object.h"
25 #include "core/components_ng/pattern/text/span/span_string.h"
26 #include "core/components_ng/pattern/text/span_node.h"
27 #include "core/text/text_emoji_processor.h"
28
29 namespace OHOS::Ace {
30 namespace {
GetWStringLength(const std::string & str)31 int32_t GetWStringLength(const std::string& str)
32 {
33 return static_cast<int32_t>(StringUtils::ToWstring(str).length());
34 }
35 } // namespace
36
37 const std::vector<SpanType> specailTypes = { SpanType::Image, SpanType::CustomSpan };
38
SplitSpansByNewLine()39 void MutableSpanString::SplitSpansByNewLine()
40 {
41 for (auto it = spans_.begin(); it != spans_.end();) {
42 it = SplitSpansAndForward(it);
43 }
44 }
45
RemoveSpans(int32_t start,int32_t length,bool removeSpecialSpan)46 void MutableSpanString::RemoveSpans(int32_t start, int32_t length, bool removeSpecialSpan)
47 {
48 if (!CheckRange(start, length)) {
49 return;
50 }
51 auto end = start + length;
52 ChangeStartAndEndToCorrectNum(start, end);
53 length = end - start;
54 std::list<SpanType> typeList;
55 auto iter = typeList.begin();
56 for (auto& it : spansMap_) {
57 auto spanKey = it.first;
58 if (spanKey != SpanType::CustomSpan && spanKey != SpanType::Image) {
59 iter = typeList.insert(iter, spanKey);
60 }
61 }
62 for (const auto& spanKey : typeList) {
63 if (spanKey != SpanType::CustomSpan && spanKey != SpanType::Image) {
64 RemoveSpan(start, length, spanKey);
65 }
66 }
67 if (removeSpecialSpan) {
68 RemoveSpecialSpans(start, length);
69 }
70 }
71
RemoveSpecialSpans(int32_t start,int32_t length)72 void MutableSpanString::RemoveSpecialSpans(int32_t start, int32_t length)
73 {
74 if (!CheckRange(start, length)) {
75 return;
76 }
77 auto end = start + length;
78 ChangeStartAndEndToCorrectNum(start, end);
79 length = end - start;
80 std::list<RefPtr<SpanBase>> spanBaseList;
81 auto iter = spanBaseList.begin();
82 for (const auto& type : specailTypes) {
83 auto spans = spansMap_[type];
84 for (const auto& span : spans) {
85 auto spanIndex = span->GetStartIndex();
86 if (start <= spanIndex && spanIndex < end) {
87 iter = spanBaseList.insert(iter, span);
88 }
89 }
90 }
91 spanBaseList.sort(
92 [](const RefPtr<SpanBase>& a, const RefPtr<SpanBase>& b) { return a->GetStartIndex() < b->GetStartIndex(); });
93 for (const auto& span : spanBaseList) {
94 auto index = span->GetStartIndex();
95 RemoveSpan(index, 1, span->GetSpanType());
96 }
97 }
98
ReplaceSpan(int32_t start,int32_t length,const RefPtr<SpanBase> & span)99 void MutableSpanString::ReplaceSpan(int32_t start, int32_t length, const RefPtr<SpanBase>& span)
100 {
101 if (!CheckRange(start, length)) {
102 return;
103 }
104 auto end = start + length;
105 ChangeStartAndEndToCorrectNum(start, end);
106 length = end - start;
107 if (IsSpecialNode(span)) {
108 RemoveSpans(start, length);
109 AddSpan(span->GetSubSpan(start, start + length));
110 return;
111 }
112 std::list<std::pair<int32_t, int32_t>> indexList;
113 GetNormalTypesVector(indexList, start, length);
114 std::list<int32_t> specialList;
115 GetSpecialTypesVector(specialList, start, length);
116 for (const auto& pair : indexList) {
117 auto startIndex = pair.first;
118 auto secondIndex = pair.second;
119 RemoveSpans(startIndex, secondIndex);
120 AddSpan(span->GetSubSpan(startIndex, startIndex + secondIndex));
121 }
122 for (const auto& index : specialList) {
123 RemoveSpans(index, 1, false);
124 AddSpan(span->GetSubSpan(index, index + 1));
125 }
126 }
127
ApplyReplaceStringToSpans(int32_t start,int32_t length,const std::string & other,SpanStringOperation op)128 void MutableSpanString::ApplyReplaceStringToSpans(
129 int32_t start, int32_t length, const std::string& other, SpanStringOperation op)
130 {
131 int32_t end = start + length;
132 for (auto it = spans_.begin(); it != spans_.end();) {
133 auto intersection = (*it)->GetIntersectionInterval({ start, end });
134 if (!intersection) {
135 ++it;
136 continue;
137 }
138 it = HandleSpanOperation(it, start, length, other, op, intersection.value());
139 }
140 }
141
HandleSpanOperation(std::list<RefPtr<NG::SpanItem>>::iterator it,int32_t start,int32_t length,const std::string & other,SpanStringOperation op,const std::pair<int32_t,int32_t> & intersection)142 std::list<RefPtr<NG::SpanItem>>::iterator MutableSpanString::HandleSpanOperation(
143 std::list<RefPtr<NG::SpanItem>>::iterator it, int32_t start, int32_t length,
144 const std::string& other, SpanStringOperation op, const std::pair<int32_t, int32_t>& intersection)
145 {
146 auto end = start + length;
147 auto spanItemStart = (*it)->interval.first;
148 auto spanItemEnd = (*it)->interval.second;
149 auto wContent = StringUtils::ToWstring((*it)->content);
150 auto wOther = StringUtils::ToWstring(other);
151
152 if (spanItemStart == start && op == SpanStringOperation::REPLACE) {
153 if ((*it)->spanItemType == NG::SpanItemType::IMAGE || (*it)->spanItemType == NG::SpanItemType::CustomSpan) {
154 auto newSpan = MakeRefPtr<NG::SpanItem>();
155 newSpan->content = other;
156 newSpan->interval.first = spanItemStart;
157 newSpan->interval.second = GetWStringLength(newSpan->content) + spanItemStart;
158 it = spans_.erase(it);
159 it = spans_.insert(it, newSpan);
160 } else {
161 (*it)->content = StringUtils::ToString(wOther + GetWideStringSubstr(wContent, length));
162 (*it)->interval.second = GetWStringLength((*it)->content) + spanItemStart;
163 }
164 ++it;
165 return it;
166 }
167
168 if (spanItemStart == intersection.first && spanItemEnd == intersection.second) {
169 return spans_.erase(it);
170 }
171
172 if (spanItemStart < intersection.first && intersection.second < spanItemEnd && op == SpanStringOperation::REMOVE) {
173 auto newSpan = (*it)->GetSameStyleSpanItem();
174 (*it)->interval = { spanItemStart, start };
175 (*it)->content = StringUtils::ToString(wContent.substr(0, start - spanItemStart));
176 newSpan->interval = { end, spanItemEnd };
177 newSpan->content = StringUtils::ToString(wContent.substr(end - spanItemStart, spanItemEnd - end));
178 ++it;
179 spans_.insert(it, newSpan);
180 return it;
181 }
182
183 if (intersection.first > spanItemStart) {
184 if (op == SpanStringOperation::REMOVE) {
185 (*it)->content = StringUtils::ToString(wContent.substr(0, start - spanItemStart));
186 (*it)->interval.second = start;
187 } else {
188 (*it)->content = StringUtils::ToString(GetWideStringSubstr(wContent, 0, start - spanItemStart) + wOther +
189 GetWideStringSubstr(wContent, end - spanItemStart));
190 (*it)->interval.second = std::max(end, spanItemEnd);
191 }
192 } else {
193 (*it)->content = StringUtils::ToString(GetWideStringSubstr(wContent, end - spanItemStart));
194 (*it)->interval.first = end;
195 }
196 return ++it;
197 }
198
ApplyReplaceStringToSpanBase(int32_t start,int32_t length,const std::string & other,SpanStringOperation op)199 void MutableSpanString::ApplyReplaceStringToSpanBase(
200 int32_t start, int32_t length, const std::string& other, SpanStringOperation op)
201 {
202 int32_t end = start + length;
203 for (auto& iter : spansMap_) {
204 if (spansMap_.find(iter.first) == spansMap_.end()) {
205 spansMap_[iter.first] = {};
206 }
207 auto spans = spansMap_[iter.first];
208 ProcessSpanBaseList(spans, start, end, other, op, iter.first);
209 spansMap_[iter.first] = spans;
210 }
211 }
212
ProcessSpanBaseList(std::list<RefPtr<SpanBase>> & spans,int32_t start,int32_t end,const std::string & other,SpanStringOperation op,SpanType spanType)213 void MutableSpanString::ProcessSpanBaseList(std::list<RefPtr<SpanBase>>& spans, int32_t start,
214 int32_t end, const std::string& other, SpanStringOperation op, SpanType spanType)
215 {
216 for (auto it = spans.begin(); it != spans.end();) {
217 auto spanStart = (*it)->GetStartIndex();
218 auto spanEnd = (*it)->GetEndIndex();
219 auto intersection = (*it)->GetIntersectionInterval({ start, end });
220 if (!intersection) {
221 ++it;
222 continue;
223 }
224 if (spanStart == start && op == SpanStringOperation::REPLACE) {
225 if (spanType == SpanType::Image || spanType == SpanType::CustomSpan) {
226 it = spans.erase(it);
227 continue;
228 }
229 auto wOther = StringUtils::ToWstring(other);
230 auto newLength = wOther.length();
231 if (end < spanEnd) {
232 newLength += static_cast<size_t>(spanEnd - end);
233 }
234 (*it)->UpdateEndIndex(newLength + spanStart);
235 ++it;
236 continue;
237 }
238 if (intersection->first == spanStart && intersection->second == spanEnd) {
239 it = spans.erase(it);
240 continue;
241 }
242 if (spanStart < intersection->first && intersection->second < spanEnd &&
243 op == SpanStringOperation::REMOVE) {
244 auto newSpan = (*it)->GetSubSpan(end, spanEnd);
245 (*it)->UpdateEndIndex(start);
246 ++it;
247 spans.insert(it, newSpan);
248 continue;
249 }
250 auto newEnd = (op != SpanStringOperation::REMOVE) ? std::max(end, spanEnd) : start;
251 if (intersection->first > spanStart) {
252 (*it)->UpdateEndIndex(newEnd);
253 } else {
254 (*it)->UpdateStartIndex(intersection->second);
255 }
256 ++it;
257 }
258 }
259
ReplaceString(int32_t start,int32_t length,const std::string & other)260 void MutableSpanString::ReplaceString(int32_t start, int32_t length, const std::string& other)
261 {
262 if (!CheckRange(start, length)) {
263 return;
264 }
265 auto end = start + length;
266 ChangeStartAndEndToCorrectNum(start, end);
267 length = end - start;
268 SpanStringOperation op = SpanStringOperation::REPLACE;
269 auto wOther = StringUtils::ToWstring(other);
270 auto otherLength = wOther.length();
271 if (otherLength == 0) {
272 op = SpanStringOperation::REMOVE;
273 }
274 auto text = GetWideString();
275 SetString(StringUtils::ToString(text.substr(0, start) + wOther + text.substr(end)));
276 ApplyReplaceStringToSpans(start, length, other, op);
277 ApplyReplaceStringToSpanBase(start, length, other, op);
278 UpdateSpansWithOffset(start, otherLength - length);
279 UpdateSpanMapWithOffset(start, otherLength - length);
280 SplitSpansByNewLine();
281 KeepSpansOrder();
282 }
283
UpdateSpansAndSpanMapWithOffsetAfterInsert(int32_t start,int32_t offset,bool useFrontStyle)284 void MutableSpanString::UpdateSpansAndSpanMapWithOffsetAfterInsert(int32_t start, int32_t offset, bool useFrontStyle)
285 {
286 for (auto& span : spans_) {
287 if (span->interval.first > start || (span->interval.first == start && useFrontStyle)) {
288 span->interval.first += offset;
289 }
290 if (span->interval.second > start || (span->interval.second == start && useFrontStyle)) {
291 span->interval.second += offset;
292 }
293 }
294 for (auto& iter : spansMap_) {
295 if (spansMap_.find(iter.first) == spansMap_.end()) {
296 continue;
297 }
298 auto spans = spansMap_[iter.first];
299 for (auto& span : spans) {
300 if (span->GetStartIndex() > start || (span->GetStartIndex() == start && useFrontStyle)) {
301 span->UpdateStartIndex(span->GetStartIndex() + offset);
302 }
303 if (span->GetEndIndex() > start || (span->GetEndIndex() == start && useFrontStyle)) {
304 span->UpdateEndIndex(span->GetEndIndex() + offset);
305 }
306 }
307 spansMap_[iter.first] = spans;
308 }
309 }
310
InsertUseFrontStyle(int32_t start)311 bool MutableSpanString::InsertUseFrontStyle(int32_t start)
312 {
313 if (start == GetLength()) {
314 return true;
315 }
316 for (auto& iter : spansMap_) {
317 if (spansMap_.find(iter.first) == spansMap_.end()) {
318 continue;
319 }
320 auto spans = spansMap_[iter.first];
321 for (auto& span : spans) {
322 if (span->GetStartIndex() <= start - 1 && span->GetEndIndex() > start - 1) {
323 return true;
324 }
325 }
326 }
327 return false;
328 }
329
InsertString(int32_t start,const std::string & other)330 void MutableSpanString::InsertString(int32_t start, const std::string& other)
331 {
332 auto len = GetLength();
333 if (other.length() == 0 || start > len) {
334 return;
335 }
336 ChangeStartToCorrectNum(start);
337 auto isAround = IsInsertAroundSpecialNode(start);
338 if (isAround != AroundSpecialNode::NONE) {
339 InsertStringAroundSpecialNode(start, other, isAround);
340 NotifySpanWatcher();
341 return;
342 }
343 bool useFrontStyle = InsertUseFrontStyle(start);
344 auto wOther = StringUtils::ToWstring(other);
345 auto text = GetWideString();
346 text = GetWideStringSubstr(text, 0, start) + wOther + GetWideStringSubstr(text, start);
347 SetString(StringUtils::ToString(text));
348 auto otherLength = wOther.length();
349 if (len == 0) {
350 spans_.clear();
351 auto spanItem = MakeRefPtr<NG::SpanItem>();
352 spanItem->content = other;
353 spanItem->interval = { 0, otherLength };
354 spans_.emplace_back(spanItem);
355 NotifySpanWatcher();
356 return;
357 }
358 for (auto& span : spans_) {
359 auto spanItemStart = span->interval.first;
360 auto spanItemEnd = span->interval.second;
361 if (start == 0 && spanItemStart == 0) {
362 span->content = other + span->content;
363 break;
364 }
365 auto wContent = StringUtils::ToWstring(span->content);
366 if (start - 1 >= spanItemStart && start - 1 < spanItemEnd && useFrontStyle) {
367 span->content = StringUtils::ToString(GetWideStringSubstr(wContent, 0, start - spanItemStart) + wOther +
368 GetWideStringSubstr(wContent, start - spanItemStart));
369 break;
370 }
371 if (start >= spanItemStart && start < spanItemEnd) {
372 span->content = StringUtils::ToString(GetWideStringSubstr(wContent, 0, start - spanItemStart) + wOther +
373 GetWideStringSubstr(wContent, start - spanItemStart));
374 break;
375 }
376 }
377 UpdateSpansAndSpanMapWithOffsetAfterInsert(start, otherLength, useFrontStyle);
378 SplitSpansByNewLine();
379 KeepSpansOrder();
380 NotifySpanWatcher();
381 }
382
RemoveString(int32_t start,int32_t length)383 void MutableSpanString::RemoveString(int32_t start, int32_t length)
384 {
385 auto end = start + length;
386 ChangeStartAndEndToCorrectNum(start, end);
387 ReplaceString(start, end - start, "");
388 NotifySpanWatcher();
389 }
390
RemoveSpecialpanText()391 void MutableSpanString::RemoveSpecialpanText()
392 {
393 std::list<int32_t> indexList;
394 GetSpecialTypesVector(indexList, 0, GetLength());
395 int32_t count = 0;
396 for (const auto& index : indexList) {
397 auto wStr = GetWideString();
398 wStr.erase(index - count, 1);
399 text_ = StringUtils::ToString(wStr);
400 ++count;
401 }
402 }
403
ClearAllSpans()404 void MutableSpanString::ClearAllSpans()
405 {
406 RemoveSpecialpanText();
407 spansMap_.clear();
408 spans_.clear();
409 spans_.emplace_back(GetDefaultSpanItem(text_));
410 SplitSpansByNewLine();
411 }
412
KeepSpansOrder()413 void MutableSpanString::KeepSpansOrder()
414 {
415 for (auto& it : spansMap_) {
416 auto spans = spansMap_[it.first];
417 SortSpans(spans);
418 MergeIntervals(spans);
419 spansMap_[it.first] = spans;
420 }
421 }
422
ReplaceSpanString(int32_t start,int32_t length,const RefPtr<SpanString> & spanString)423 void MutableSpanString::ReplaceSpanString(int32_t start, int32_t length, const RefPtr<SpanString>& spanString)
424 {
425 if (length < 0 || start + length > GetLength()) {
426 return;
427 }
428 auto end = start + length;
429 ChangeStartAndEndToCorrectNum(start, end);
430 length = end - start;
431 if (length != 0) {
432 RemoveString(start, length);
433 }
434 InsertSpanString(start, spanString);
435 }
436
UpdateSpanAndSpanMapAfterInsertSpanString(int32_t start,int32_t offset)437 void MutableSpanString::UpdateSpanAndSpanMapAfterInsertSpanString(int32_t start, int32_t offset)
438 {
439 for (auto& span : spans_) {
440 if (span->interval.first >= start) {
441 span->interval.first += offset;
442 }
443 if (span->interval.second > start) {
444 span->interval.second += offset;
445 }
446 }
447 }
448
ApplyInsertSpanStringToSpans(int32_t start,const RefPtr<SpanString> & spanString)449 void MutableSpanString::ApplyInsertSpanStringToSpans(int32_t start, const RefPtr<SpanString>& spanString)
450 {
451 auto offset = spanString->GetLength();
452 for (auto it = spans_.begin(); it != spans_.end(); ++it) {
453 auto spanItemStart = (*it)->interval.first;
454 auto spanItemEnd = (*it)->interval.second;
455 if (spanItemEnd < start || spanItemStart > start) {
456 continue;
457 }
458 if (spanItemEnd != start) {
459 auto newSpanItem = (*it)->GetSameStyleSpanItem();
460 newSpanItem->interval.first = start + offset;
461 newSpanItem->interval.second = spanItemEnd;
462 auto wStr = StringUtils::ToWstring((*it)->content);
463 newSpanItem->content = StringUtils::ToString(GetWideStringSubstr(wStr, start - spanItemStart));
464 (*it)->interval.second = start;
465 (*it)->content = StringUtils::ToString(GetWideStringSubstr(wStr, 0, start - spanItemStart));
466 ++it;
467 it = spans_.insert(it, newSpanItem);
468 } else {
469 ++it;
470 }
471 auto otherSpans = spanString->GetSpanItems();
472 for (auto rit = otherSpans.rbegin(); rit != otherSpans.rend(); ++rit) {
473 auto newSpanItem = (*rit)->GetSameStyleSpanItem();
474 newSpanItem->interval.first = (*rit)->interval.first + start;
475 newSpanItem->interval.second = (*rit)->interval.second + start;
476 newSpanItem->content = (*rit)->content;
477 it = spans_.insert(it, newSpanItem);
478 }
479 break;
480 }
481 }
482
ApplyInsertSpanStringToSpanBase(int32_t start,const RefPtr<SpanString> & spanString)483 void MutableSpanString::ApplyInsertSpanStringToSpanBase(int32_t start, const RefPtr<SpanString>& spanString)
484 {
485 auto offset = spanString->GetLength();
486 auto otherSpansMap = spanString->GetSpansMap();
487 for (auto& iter : spansMap_) {
488 auto spans = spansMap_[iter.first];
489 for (auto it = spans.begin(); it != spans.end(); ++it) {
490 auto spanItemStart = (*it)->GetStartIndex();
491 auto spanItemEnd = (*it)->GetEndIndex();
492 if (spanItemStart >= start) {
493 (*it)->UpdateStartIndex(spanItemStart + offset);
494 (*it)->UpdateEndIndex(spanItemEnd + offset);
495 } else if (spanItemStart < start && start < spanItemEnd) {
496 auto newSpanItem = (*it)->GetSubSpan(start + offset, spanItemEnd + offset);
497 (*it)->UpdateEndIndex(start);
498 ++it;
499 it = spans.insert(it, newSpanItem);
500 }
501 }
502 spansMap_[iter.first] = spans;
503 }
504
505 for (auto& iter : otherSpansMap) {
506 auto spans = spansMap_[iter.first];
507 auto otherSpans = otherSpansMap[iter.first];
508 for (auto& spanBase : otherSpans) {
509 auto newSpanItem = spanBase->GetSubSpan(spanBase->GetStartIndex() + start, spanBase->GetEndIndex() + start);
510 spans.emplace_back(newSpanItem);
511 }
512 spansMap_[iter.first] = spans;
513 }
514 }
515
InsertSpanString(int32_t start,const RefPtr<SpanString> & spanString)516 void MutableSpanString::InsertSpanString(int32_t start, const RefPtr<SpanString>& spanString)
517 {
518 auto len = GetLength();
519 if (start > len || spanString->GetLength() == 0) {
520 return;
521 }
522 ChangeStartToCorrectNum(start);
523 auto offset = spanString->GetLength();
524 auto wContent = GetWideString();
525 SetString(StringUtils::ToString(
526 GetWideStringSubstr(wContent, 0, start) + spanString->GetWideString() + GetWideStringSubstr(wContent, start)));
527 UpdateSpanAndSpanMapAfterInsertSpanString(start, offset);
528 if (start == 0 || start == len) {
529 if (len == 0) {
530 spans_.clear();
531 }
532 auto it = start == 0 ? spans_.begin() : spans_.end();
533 auto otherSpans = spanString->GetSpanItems();
534 for (auto rit = otherSpans.rbegin(); rit != otherSpans.rend(); ++rit) {
535 auto newSpanItem = (*rit)->GetSameStyleSpanItem();
536 newSpanItem->interval.first = (*rit)->interval.first + start;
537 newSpanItem->interval.second = (*rit)->interval.second + start;
538 newSpanItem->content = (*rit)->content;
539 it = spans_.insert(it, newSpanItem);
540 }
541 } else {
542 ApplyInsertSpanStringToSpans(start, spanString);
543 }
544 ApplyInsertSpanStringToSpanBase(start, spanString);
545 KeepSpansOrder();
546 NotifySpanWatcher();
547 }
548
AppendSpanString(const RefPtr<SpanString> & spanString)549 void MutableSpanString::AppendSpanString(const RefPtr<SpanString>& spanString)
550 {
551 InsertSpanString(GetLength(), spanString);
552 }
553
IsInsertAroundSpecialNode(int32_t start)554 AroundSpecialNode MutableSpanString::IsInsertAroundSpecialNode(int32_t start)
555 {
556 AroundSpecialNode res = AroundSpecialNode::NONE;
557 if (spansMap_.find(SpanType::Image) == spansMap_.end() && spansMap_.find(SpanType::CustomSpan) == spansMap_.end()) {
558 return res;
559 }
560
561 for (const auto& type : specailTypes) {
562 auto specialSpans = spansMap_[type];
563 for (const auto& span : specialSpans) {
564 if (span->GetEndIndex() == start) {
565 res = (res == AroundSpecialNode::NONE || res == AroundSpecialNode::AFTER) ? AroundSpecialNode::AFTER
566 : AroundSpecialNode::BETWEEN;
567 }
568 if (span->GetStartIndex() == start) {
569 res = (res == AroundSpecialNode::NONE || res == AroundSpecialNode::BEFORE) ? AroundSpecialNode::BEFORE
570 : AroundSpecialNode::BETWEEN;
571 }
572 }
573 }
574 return res;
575 }
576
InsertStringAroundSpecialNode(int32_t start,const std::string & str,AroundSpecialNode aroundMode)577 void MutableSpanString::InsertStringAroundSpecialNode(
578 int32_t start, const std::string& str, AroundSpecialNode aroundMode)
579 {
580 auto iter = spans_.begin();
581 auto step = GetStepsByPosition(start);
582 RefPtr<NG::SpanItem> spanItem = MakeRefPtr<NG::SpanItem>();
583 std::advance(iter, step);
584 if (aroundMode == AroundSpecialNode::BEFORE && step >= 1) {
585 auto iter2 = spans_.begin();
586 std::advance(iter2, step - 1);
587 spanItem = (*iter2)->GetSameStyleSpanItem();
588 } else if (aroundMode == AroundSpecialNode::AFTER && iter != spans_.end()) {
589 spanItem = (*iter)->GetSameStyleSpanItem();
590 }
591 int32_t length = static_cast<int32_t>(StringUtils::ToWstring(str).length());
592 spanItem->content = str;
593 spanItem->interval.first = start;
594 spanItem->interval.second = start + length;
595 auto beforeStr = GetWideStringSubstr(GetWideString(), 0, start);
596 auto centerStr = StringUtils::ToWstring(str);
597 auto afterStr = GetWideStringSubstr(GetWideString(), start);
598 SetString(StringUtils::ToString(beforeStr + centerStr + afterStr));
599 iter = spans_.insert(iter, spanItem);
600 ++iter;
601 for (; iter != spans_.end(); ++iter) {
602 (*iter)->interval.first += length;
603 (*iter)->interval.second += length;
604 }
605
606 SplitSpansByNewLine();
607
608 for (auto& mapIter : spansMap_) {
609 if (spansMap_.find(mapIter.first) == spansMap_.end()) {
610 continue;
611 }
612 auto spans = spansMap_[mapIter.first];
613 for (auto& span : spans) {
614 if (span->GetStartIndex() > start ||
615 (span->GetStartIndex() == start && aroundMode != AroundSpecialNode::AFTER)) {
616 span->UpdateStartIndex(span->GetStartIndex() + length);
617 span->UpdateEndIndex(span->GetEndIndex() + length);
618 }
619 }
620 spansMap_[mapIter.first] = spans;
621 }
622 }
623
IsSpeicalNode(int32_t location,SpanType speicalType)624 bool MutableSpanString::IsSpeicalNode(int32_t location, SpanType speicalType)
625 {
626 if (spansMap_.find(speicalType) == spansMap_.end()) {
627 return false;
628 }
629 auto speicalList = spansMap_[speicalType];
630 for (const auto& speicalNode : speicalList) {
631 if (speicalNode->GetStartIndex() == location) {
632 return true;
633 }
634
635 if (speicalNode->GetStartIndex() > location) {
636 return false;
637 }
638 }
639 return false;
640 }
641
SetSpanWatcher(const WeakPtr<SpanWatcher> & watcher)642 void MutableSpanString::SetSpanWatcher(const WeakPtr<SpanWatcher>& watcher)
643 {
644 watcher_ = watcher;
645 }
646
NotifySpanWatcher()647 void MutableSpanString::NotifySpanWatcher()
648 {
649 if (spans_.empty()) {
650 spans_.emplace_back(GetDefaultSpanItem(""));
651 }
652 auto watcher = watcher_.Upgrade();
653 if (watcher) {
654 watcher->UpdateSpanItems(spans_);
655 }
656 }
657 } // namespace OHOS::Ace