• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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