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