Issues deteced by Static Code Analysis fixed
[platform/core/uifw/eail.git] / eail / eail / eail_label.c
1 /*
2  * Copyright (c) 2013 Samsung Electronics Co., Ltd.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 /**
21  * @file eail_label.c
22  * @brief EailLabel implementation.
23  */
24
25 #include <Elementary.h>
26
27 #include "eail_label.h"
28 #include "eail_utils.h"
29
30 static void atk_text_interface_init(AtkTextIface *iface);
31
32 /**
33  * @brief EailLabel type definition
34  */
35 G_DEFINE_TYPE_WITH_CODE(EailLabel,
36                         eail_label,
37                         EAIL_TYPE_WIDGET,
38                         G_IMPLEMENT_INTERFACE(ATK_TYPE_TEXT,
39                                               atk_text_interface_init));
40
41 /**
42  * @brief EailLabel initializer.
43  *
44  * @param obj EailLabel instance
45  * @param data initialization data
46  */
47 static void
48 eail_label_initialize(AtkObject *obj, gpointer data)
49 {
50    ATK_OBJECT_CLASS(eail_label_parent_class)->initialize(obj, data);
51    obj->role = ATK_ROLE_LABEL;
52 }
53
54 /**
55  * @brief EailLabel interface intializer.
56  *
57  * @param label EailLabel instance
58  */
59 static void
60 eail_label_init(EailLabel *label)
61 {
62 }
63
64 /**
65  * @brief Gets the state set of the accessible.
66  *
67  * The caller must unreference it when it is no longer needed.
68  *
69  * @param accessible AtkObject instance
70  * @return AtkStateSet containing the state set of the accessible
71  */
72 static AtkStateSet*
73 eail_label_ref_state_set(AtkObject *accessible)
74 {
75    AtkStateSet *state_set;
76    Evas_Object *widget;
77
78    state_set =
79        ATK_OBJECT_CLASS(eail_label_parent_class)->ref_state_set(accessible);
80
81    widget = eail_widget_get_widget(EAIL_WIDGET(accessible));
82    if (!widget) return state_set;
83
84    atk_state_set_add_state(state_set, ATK_STATE_MULTI_LINE);
85
86    return state_set;
87 }
88
89 /**
90  * @brief Gets obj's name
91  *
92  * @param obj AtkObject instance
93  * @returns string containing obj's name or its text content if the name is not set
94  */
95 static const gchar*
96 eail_label_get_name(AtkObject *obj)
97 {
98    const gchar *name;
99    Evas_Object *widget;
100
101    name = ATK_OBJECT_CLASS(eail_label_parent_class)->get_name(obj);
102    if (NULL != name)
103      return name;
104
105    widget = eail_widget_get_widget(EAIL_WIDGET(obj));
106    if (!widget) return NULL;
107
108    name = (const gchar*)elm_object_text_get(widget);
109    if (!name) return NULL;
110
111    return name;
112 }
113
114 /**
115  * @brief EailLabel class initializer.
116  *
117  * @param klass EailLabelClass instance
118  */
119 static void
120 eail_label_class_init(EailLabelClass *klass)
121 {
122    AtkObjectClass *atk_class = ATK_OBJECT_CLASS(klass);
123
124    atk_class->initialize = eail_label_initialize;
125    atk_class->ref_state_set = eail_label_ref_state_set;
126    atk_class->get_name = eail_label_get_name;
127 }
128
129 /**
130  * @brief Gets text bounded by start_offset and end_offset
131  *
132  * Use g_free() to free the returned string
133  *
134  * @param text an AtkText
135  * @param start_offset start position
136  * @param end_offset end position, -1 for the end of the string
137  * @return string containing text from start_offset up to, but not including
138  * end_offset
139  */
140 static gchar*
141 eail_label_get_text(AtkText   *text,
142                     gint       start_offset,
143                     gint       end_offset)
144 {
145    gchar *string = NULL;
146    Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(text));
147
148    if (widget)
149      string = (gchar *)elm_object_text_get(widget);
150
151    if (!string)
152      return NULL;
153
154    return eail_get_substring(string, start_offset, end_offset);
155 }
156
157 /**
158  * @brief Gets the character at offset
159  *
160  * @param text AtkText instance
161  * @param offset character offset
162  * @return char located at the given offset
163  */
164 static gunichar
165 eail_label_get_character_at_offset(AtkText    *text,
166                                    gint        offset)
167 {
168    gunichar character = '\0';
169    Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(text));
170
171    if (widget)
172      character = g_utf8_get_char(
173          g_utf8_offset_to_pointer(elm_object_text_get(widget), offset));
174
175    return character;
176 }
177
178 /**
179  * @brief Gets the length of text
180  *
181  * @param text AtkText instance
182  * @return integer representing the length of text
183  */
184 static gint
185 eail_label_get_character_count(AtkText *text)
186 {
187    Evas_Object *widget;
188    const char *str;
189
190    widget = eail_widget_get_widget(EAIL_WIDGET(text));
191    if (!widget)
192      return 0;
193
194    str = elm_object_text_get(widget);
195    if (!str)
196      return 0;
197    return g_utf8_strlen(str, -1);
198 }
199
200 /**
201  * @brief Adds attribute to attribute set
202  *
203  * @param attrib_set AtkAttributeSet to add the attribute to
204  * @param attr AtkTextAttrribute to be added
205  * @param value attribute value
206  *
207  * Creates an AtkAttribute from attr and value, and adds it
208  * to attrib_set.
209  *
210  * @returns AtkAttributeSet containing set with added attribute
211  **/
212 AtkAttributeSet*
213 _eail_label_add_attribute(AtkAttributeSet *attrib_set,
214                           AtkTextAttribute attr,
215                           gchar           *value)
216 {
217    AtkAttributeSet *return_set;
218    AtkAttribute *at = g_malloc (sizeof (AtkAttribute));
219    at->name = g_strdup (atk_text_attribute_get_name (attr));
220    at->value = value;
221    return_set = g_slist_prepend(attrib_set, at);
222    return return_set;
223 }
224
225 /**
226  * @brief Creates an AtkAttributeSet which consists of the default values of
227  * attributes for the text.
228  *
229  * This AtkAttributeSet should be freed by a call to
230  * atk_attribute_set_free()
231  *
232  * @param text AtkText instance
233  *
234  * @returns AtkAttributeSet containing default values of attributes
235  * at offset.
236  */
237 AtkAttributeSet *
238 eail_label_get_default_attributes(AtkText *text)
239 {
240    AtkAttributeSet *at_set = NULL;
241
242    at_set = _eail_label_add_attribute
243        (at_set, ATK_TEXT_ATTR_WRAP_MODE,
244         g_strdup
245         (atk_text_attribute_get_value(ATK_TEXT_ATTR_WRAP_MODE, 0)));
246
247    at_set = _eail_label_add_attribute
248        (at_set, ATK_TEXT_ATTR_EDITABLE,
249         g_strdup
250         (atk_text_attribute_get_value
251          (ATK_TEXT_ATTR_EDITABLE, FALSE)));
252
253    return at_set;
254 }
255
256 /**
257  * @brief Creates an AtkAttributeSet which consists of the attributes
258  * explicitly set at the position offset in the text.
259  *
260  * start_offset and end_offset are set to the start and end of the range around offset
261  * where the attributes are invariant.
262  *
263  * Note that end_offset is the offset of the first character after the range.
264  *
265  * This AtkAttributeSet should be freed by a call to
266  * atk_attribute_set_free()
267  *
268  * @param text AtkText instance
269  * @param offset the offset at which to get the attributes
270  * @param [out] start_offset start offset of the range
271  * @param [out] end_offset end offset of the range
272  *
273  * @returns an AtkAttributeSet which contains the attributes explicitly set at
274  * offset.
275  */
276 AtkAttributeSet *
277 eail_label_get_run_attributes(AtkText *text,
278                               gint offset,
279                               gint *start_offset,
280                               gint *end_offset)
281 {
282    AtkAttributeSet *at_set = NULL;
283    Evas_Object *widget = eail_widget_get_widget(EAIL_WIDGET(text));
284    gint len = eail_label_get_character_count(ATK_TEXT(text));
285
286    if (!widget || offset >= len)
287      {
288         *start_offset = -1;
289         *end_offset = -1;
290
291         return NULL;
292      }
293
294    *start_offset = 0;
295    *end_offset = len;
296
297    /* NOTE: Elm_Wrap_Type value is in 100% compatible with ATK wrap modes, so
298     * no additional conversion is needed*/
299    Elm_Wrap_Type wrap_type = elm_label_line_wrap_get(widget);
300    at_set = _eail_label_add_attribute
301        (at_set, ATK_TEXT_ATTR_WRAP_MODE,
302         g_strdup
303         (atk_text_attribute_get_value
304          (ATK_TEXT_ATTR_WRAP_MODE, wrap_type)));
305
306    at_set = _eail_label_add_attribute
307        (at_set, ATK_TEXT_ATTR_EDITABLE,
308         g_strdup
309         (atk_text_attribute_get_value
310          (ATK_TEXT_ATTR_EDITABLE, FALSE)));
311
312    return at_set;
313 }
314
315 /**
316  * @brief Initializes AtkTextIface interface
317  *
318  * @param iface AtkTextIface instance
319  */
320 static void
321 atk_text_interface_init(AtkTextIface *iface)
322 {
323    iface->get_character_count = eail_label_get_character_count;
324    iface->get_character_at_offset = eail_label_get_character_at_offset;
325    iface->get_text = eail_label_get_text;
326    iface->get_run_attributes = eail_label_get_run_attributes;
327    iface->get_default_attributes = eail_label_get_default_attributes;
328 }
329