1/*
2 * Copyright (c) 2020-2021 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 "components/text_adapter.h"
17#include <cstdio>
18#include "securec.h"
19
20namespace OHOS {
21bool TextFormatter::Format(int16_t value, char* outText, uint16_t textLen)
22{
23    if (sprintf_s(outText, textLen, "%d", value) < 0) {
24        return false;
25    }
26    return true;
27}
28
29TextAdapter::TextAdapter()
30    : dataMode_(DYNAMIC_TEXT_MODE),
31      fontName_(nullptr),
32      fontSize_(0),
33      width_(0),
34      height_(0),
35      direct_(UITextLanguageDirect::TEXT_DIRECT_LTR),
36      lineBreakMode_(UILabel::LINE_BREAK_ADAPT),
37      integerTextStart_(0),
38      integerTextEnd_(0),
39      clickListener_(nullptr),
40      formatter_(nullptr)
41{
42    style_ = StyleDefault::GetBackgroundTransparentStyle();
43    fontId_ = style_.font_;
44}
45
46TextAdapter::~TextAdapter()
47{
48    ClearDynamicText();
49    if (fontName_ != nullptr) {
50        UIFree(fontName_);
51        fontName_ = nullptr;
52    }
53}
54
55void TextAdapter::SetFont(const char* name, uint8_t size)
56{
57    Text::SetFont(name, size, fontName_, fontSize_);
58}
59
60UIView* TextAdapter::GetView(UIView* inView, int16_t index)
61{
62    UILabel* newView = GetTextView(inView, index);
63    if (newView == nullptr) {
64        return nullptr;
65    }
66    newView->SetLineBreakMode(lineBreakMode_);
67    newView->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
68    if (width_) {
69        newView->SetWidth(width_);
70    }
71    if (height_) {
72        newView->SetHeight(height_);
73    }
74    newView->SetViewIndex(index);
75    newView->UIView::SetStyle(style_);
76    newView->GetHeight();
77    if (clickListener_) {
78        newView->SetOnClickListener(clickListener_);
79        newView->SetTouchable(true);
80    }
81    return newView;
82}
83
84UILabel* TextAdapter::GetTextView(UIView* inView, int16_t index)
85{
86    switch (dataMode_) {
87        case DYNAMIC_TEXT_MODE:
88            return GetDynamicText(inView, index);
89        case CONTINUOUS_INTEGER_MODE:
90            return GetIntegerText(inView, index);
91        default:
92            return nullptr;
93    }
94}
95
96UILabel* TextAdapter::GetDynamicText(UIView* inView, int16_t index)
97{
98    if (dynamicText_.IsEmpty() || (index > dynamicText_.Size() - 1) || (index < 0)) {
99        return nullptr;
100    }
101
102    ListNode<const char*>* node = dynamicText_.Begin();
103    for (int16_t i = 0; i < index; i++) {
104        node = node->next_;
105    }
106    UILabel* newView = CreateUILabel(inView);
107    if (newView != nullptr) {
108        newView->SetText(node->data_);
109        if (fontName_ == nullptr) {
110            newView->SetFontId(fontId_);
111        } else {
112            newView->SetFont(fontName_, fontSize_);
113        }
114        newView->SetDirect(direct_);
115    }
116    return newView;
117}
118
119UILabel* TextAdapter::GetIntegerText(UIView* inView, int16_t index)
120{
121    if ((index < 0) || ((integerTextEnd_ - integerTextStart_) < index)) {
122        return nullptr;
123    }
124    UILabel* newView = CreateUILabel(inView);
125    if (newView != nullptr) {
126        char buf[BUF_LEN] = {0};
127        if (formatter_ != nullptr) {
128            if (!formatter_->Format(integerTextStart_ + index, buf, BUF_LEN)) {
129                if (inView == nullptr) {
130                    delete newView;
131                    newView = nullptr;
132                }
133                return nullptr;
134            }
135        } else {
136            if (sprintf_s(buf, sizeof(buf), "%02d", integerTextStart_ + index) < 0) {
137                if (inView == nullptr) {
138                    delete newView;
139                    newView = nullptr;
140                }
141                return nullptr;
142            }
143        }
144
145        buf[BUF_LEN - 1] = '\0';
146        newView->SetText(buf);
147        if (fontName_ == nullptr) {
148            newView->SetFontId(fontId_);
149        } else {
150            newView->SetFont(fontName_, fontSize_);
151        }
152        newView->SetDirect(direct_);
153    }
154    return newView;
155}
156
157UILabel* TextAdapter::CreateUILabel(UIView* inView)
158{
159    if (inView == nullptr) {
160        return new UILabel();
161    }
162    return static_cast<UILabel*>(inView);
163}
164
165void TextAdapter::ClearDynamicText()
166{
167    ListNode<const char*>* node = dynamicText_.Begin();
168    while (node != dynamicText_.End()) {
169        if (node->data_) {
170            UIFree(reinterpret_cast<void*>(const_cast<char*>(node->data_)));
171            node->data_ = nullptr;
172        }
173        node = node->next_;
174    }
175    dynamicText_.Clear();
176}
177
178void TextAdapter::SetData(List<const char*>* data)
179{
180    if (data == nullptr) {
181        return;
182    }
183    if (!dynamicText_.IsEmpty()) {
184        ClearDynamicText();
185    }
186    ListNode<const char*>* node = data->Begin();
187    while (node != data->End()) {
188        uint32_t len = strlen(node->data_);
189        char* stringData = static_cast<char*>(UIMalloc(len + 1));
190        if (stringData == nullptr) {
191            return;
192        }
193        if (memcpy_s(stringData, len + 1, node->data_, len) != EOK) {
194            UIFree(reinterpret_cast<void*>(stringData));
195            stringData = nullptr;
196            return;
197        }
198        stringData[len] = '\0';
199        dynamicText_.PushBack(stringData);
200        node = node->next_;
201    }
202    dataMode_ = DYNAMIC_TEXT_MODE;
203}
204
205void TextAdapter::SetData(int16_t start, int16_t end)
206{
207    if (start <= end) {
208        integerTextStart_ = start;
209        integerTextEnd_ = end;
210        dataMode_ = CONTINUOUS_INTEGER_MODE;
211    }
212}
213
214uint16_t TextAdapter::GetCount()
215{
216    switch (dataMode_) {
217        case DYNAMIC_TEXT_MODE:
218            return dynamicText_.Size();
219        case CONTINUOUS_INTEGER_MODE:
220            return (integerTextStart_ <= integerTextEnd_) ? (integerTextEnd_ - integerTextStart_ + 1) : 0;
221        default:
222            return 0;
223    }
224}
225} // namespace OHOS
226