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