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