apply FSL license
[apps/core/preloaded/call-setting.git] / src / cst-forwarding.c
1 /*
2   * Copyright 2012  Samsung Electronics Co., Ltd
3   *
4   * Licensed under the Flora License, Version 1.0 (the "License");
5   * you may not use this file except in compliance with the License.
6   * You may obtain a copy of the License at
7   *
8   * http://www.tizenopensource.org/license
9   *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16
17 #include <Elementary.h>
18
19 #include "cst-common-string.h"
20 #include "cst-call-setting.h"
21
22 #include "cst-forwarding.h"
23 #include "cst-forwarding-ime.h"
24 #include "cst-widget.h"
25 #include "cst-common.h"
26 #include "cst-tapi-request.h"
27 #include "cst-util.h"
28
29 static void __cst_on_click_cf_onoff(void *data, Evas *evas, Evas_Object *obj, void *event_info);
30 static void __cst_on_click_voice_cf(void *data, Evas *evas, Evas_Object *obj, void *event_info);
31 static void __cst_on_click_video_cf(void *data, Evas *evas, Evas_Object *obj, void *event_info);
32
33 static Elm_Genlist_Item_Class *itc_2text_1icon = NULL;
34 static Elm_Genlist_Item_Class *itc_1text = NULL;
35 static CstGlItemDisplayInfo_t list_call_type[] = {
36         {1, CST_STR_VOICECALL, ELM_GENLIST_ITEM_NONE, CST_GL_ITEM_TEXT, __cst_on_click_voice_cf},
37         {1, CST_STR_VIDEOCALL, ELM_GENLIST_ITEM_NONE, CST_GL_ITEM_TEXT, __cst_on_click_video_cf},
38
39         {1, -1, ELM_GENLIST_ITEM_NONE, CST_GL_ITEM_NONE, NULL},
40 };
41
42 static CstGlItemDisplayInfo_t list_call_forwarding[] = {
43         {1, CST_STR_ALWAYS, ELM_GENLIST_ITEM_NONE, CST_GL_ITEM_2TEXT_ONOFF_PROGRESS, __cst_on_click_cf_onoff},
44         {1, CST_STR_IF_BUSY, ELM_GENLIST_ITEM_NONE, CST_GL_ITEM_2TEXT_ONOFF_PROGRESS, __cst_on_click_cf_onoff},
45         {1, CST_STR_IF_NO_REPLY, ELM_GENLIST_ITEM_NONE, CST_GL_ITEM_2TEXT_ONOFF_PROGRESS, __cst_on_click_cf_onoff},
46         {1, CST_STR_IF_OUT_OF_REACH, ELM_GENLIST_ITEM_NONE, CST_GL_ITEM_2TEXT_ONOFF_PROGRESS, __cst_on_click_cf_onoff},
47
48         {1, -1, ELM_GENLIST_ITEM_NONE, CST_GL_ITEM_NONE, NULL},
49 };
50
51 static void __cst_on_click_cf_back_button(void *data, Evas_Object *obj, void *event_info)
52 {
53         ENTER(__cst_on_click_cf_back_button);
54
55         retm_if(data == NULL, "NULL UgData");
56
57         CstUgData_t *ugd = (CstUgData_t *)data;
58
59         ugd->back_button = _cst_get_navifr_prev_btn(ugd->nf);
60         _cst_cancel_all_ss_request(ugd);
61 }
62
63 static void __cst_update_cf_state(int call_type, int cf_flavour,
64                 Eina_Bool cf_state, char *number,
65                 int error, int req_action, void *data)
66 {
67         ret_if(NULL == data);
68         CstGlItemData_t *item_data = (CstGlItemData_t *)data;
69         CstUgData_t *ugd = item_data->ugd;
70         ret_if((call_type != ugd->call_type && call_type != CST_CALLTYPE_ALL));
71         DBG("call_type=%d (0:voice 1:video)", call_type);
72         DBG("cf_flavour=%d (0:CFU 1:CFB 2:CFNR 3:CFOR)", cf_flavour);
73         DBG("cf_state=%d (1:on 0:off)", cf_state);
74         DBG("number=%s, error=%d", number, error);
75         DBG("req_action=%d(0: Act, 1:Deact, 2:Query)", req_action);
76
77         if (error == CST_ERROR_NONE) {
78                 if (cf_state == EINA_TRUE) {
79                         ugd->cf_state[item_data->index] = CST_SS_STATE_ON;
80                         if (strlen(number) > 0) {
81                                 snprintf(item_data->number, sizeof(item_data->number), "%s", number);
82                         } else {
83                                 snprintf(item_data->number, sizeof(item_data->number), "%s", T_(CST_STR_UNKNOWN));
84                         }
85
86                         if (cf_flavour == CST_SSTYPE_CF_UNCONDITIONAL) {
87                                 int cf_index = 0;
88                                 for (cf_index = CST_SSTYPE_CF_BUSY; cf_index <= CST_SSTYPE_CF_NOT_REACHABLE; cf_index++) {
89                                         if (ugd->cf_state[cf_index] == CST_SS_STATE_ON) {
90                                                 ugd->cf_state[cf_index] = CST_SS_STATE_OFF;
91                                                 elm_genlist_item_update(ugd->cf_gl_item[cf_index]);
92                                         }
93                                 }
94                         } else {
95                                 if (ugd->cf_state[CST_SSTYPE_CF_UNCONDITIONAL] == CST_SS_STATE_ON) {
96                                         ugd->cf_state[CST_SSTYPE_CF_UNCONDITIONAL] = CST_SS_STATE_OFF;
97                                         elm_genlist_item_update(ugd->cf_gl_item[CST_SSTYPE_CF_UNCONDITIONAL]);
98                                 }
99                         }
100                 } else
101                         ugd->cf_state[item_data->index] = CST_SS_STATE_OFF;
102                 elm_genlist_item_update(item_data->gl_item);
103         } else {
104                 if (req_action != CST_ACTION_QUERY) {
105                         if (error != CST_ERROR_SERVICE_UNAVAILABLE &&
106                                 error != CST_ERROR_REJECTED_BY_NETWORK &&
107                                 error != CST_ERROR_UNKNOWN) {
108                                 DBG("User error : %d(Restore previous state)", error);
109                                 if (req_action == CST_ACTION_DEACTIVATE)
110                                         ugd->cf_state[item_data->index] = CST_SS_STATE_ON;
111                                 else
112                                         ugd->cf_state[item_data->index] = CST_SS_STATE_OFF;
113                         } else {
114                                 DBG("Network error : %d", error);
115                                 ugd->cf_state[item_data->index] = CST_SS_STATE_OFF;
116                         }
117
118                         elm_genlist_item_update(item_data->gl_item);
119                         ugd->popup = (Evas_Object *)_cst_create_error_popup(ugd->nf, error);
120                         evas_object_show(ugd->popup);
121                 } else {
122                         ugd->cf_state[item_data->index] = CST_SS_STATE_OFF;
123                         elm_genlist_item_update(item_data->gl_item);
124                 }
125         }
126         return;
127 }
128
129 static void __cst_query_cf_status(CstGlItemData_t *item_data)
130 {
131         ret_if(NULL == item_data);
132         CstUgData_t *ugd = (CstUgData_t *)item_data->ugd;
133         int cf_flavour = -1;
134
135         ugd->original_state = EINA_FALSE;
136         switch (item_data->index) {
137         case 0:
138                 cf_flavour = CST_SSTYPE_CF_UNCONDITIONAL;
139                 DBG("CST_SSTYPE_CF_UNCONDITIONAL");
140                 break;
141         case 1:
142                 cf_flavour = CST_SSTYPE_CF_BUSY;
143                 DBG("CST_SSTYPE_CF_BUSY");
144                 break;
145         case 2:
146                 cf_flavour = CST_SSTYPE_CF_NO_REPLY;
147                 DBG("CST_SSTYPE_CF_NO_REPLY");
148                 break;
149         case 3:
150                 cf_flavour = CST_SSTYPE_CF_NOT_REACHABLE;
151                 DBG("CST_SSTYPE_CF_NOT_REACHABLE");
152                 break;
153         default:
154                 DBG("Error type");
155                 break;
156         }
157         _cst_add_ss_request(&ugd->req_queue, CST_ACTION_QUERY,
158                 ugd->call_type, cf_flavour, NULL,
159                 __cst_update_cf_state, item_data);
160 }
161
162 static void __cst_on_click_cf_ime_done_btn(void *data, Evas_Object *obj, void *event_info)
163 {
164         ENTER(__cst_on_click_cf_ime_done_btn);
165         ret_if(!data);
166
167         CallSettingReq_t *req = (CallSettingReq_t *)data;
168         CstGlItemData_t *item_data = (CstGlItemData_t *)req->data;
169         CstUgData_t *ugd = (CstUgData_t *)item_data->ugd;
170
171         char buffer[CST_MAX_PHONE_NUMBER_LEN];
172         Evas_Object *lo;
173         if (_cst_get_input_number(buffer, ugd) > 0) {
174                 ugd->cf_state[item_data->index] = CST_SS_STATE_PROGRESS;
175                 elm_genlist_item_update(item_data->gl_item);
176                 DBG("activate CF num=%s", buffer);
177                 snprintf(req->number, CST_MAX_PHONE_NUMBER_LEN, "%s", buffer);
178                 _cst_add_ss_request(&ugd->req_queue, req->action,
179                         req->call_type, req->flavour, req->number,
180                         __cst_update_cf_state, item_data);
181                 memset(ugd->c_item, 0, sizeof(ugd->c_item));
182                 elm_naviframe_item_pop(ugd->nf);
183                 ugd->back_button = _cst_get_navifr_prev_btn(ugd->nf);
184         }
185
186         free(req);
187 }
188
189 static void __cst_on_click_cf_ime_cancel_btn(void *data, Evas_Object *obj, void *event_info)
190 {
191         ENTER(__cst_on_click_cf_ime_cancel_btn);
192         ret_if(!data);
193
194         CallSettingReq_t *req = (CallSettingReq_t *)data;
195         CstGlItemData_t *item_data = (CstGlItemData_t *)req->data;
196         CstUgData_t *ugd = item_data->ugd;
197
198         DBG("original state : %d", req->original_state);
199         if (req->original_state == CST_SS_STATE_ON)
200                 ugd->cf_state[item_data->index] = CST_SS_STATE_ON;
201         else
202                 ugd->cf_state[item_data->index] = CST_SS_STATE_OFF;
203         elm_genlist_item_update(item_data->gl_item);
204
205         memset(ugd->c_item, 0, sizeof(ugd->c_item));
206         elm_naviframe_item_pop(ugd->nf);
207         ugd->back_button = _cst_get_navifr_prev_btn(ugd->nf);
208
209         free(req);
210 }
211
212 static char *__cst_gl_label_get_cf(void *data, Evas_Object *obj, const char *part)
213 {
214         retv_if(NULL == data, NULL);
215         CstGlItemData_t *item_data = (CstGlItemData_t *)data;
216         CstUgData_t *ugd = (CstUgData_t *)item_data->ugd;
217
218         if (strcmp(part, "elm.text.1") == 0) {
219                 return strdup(T_(list_call_forwarding[item_data->index].str_id));
220         } else if (strcmp(part, "elm.text.2") == 0) {
221                 switch (ugd->cf_state[item_data->index]) {
222                 case CST_SS_STATE_PROGRESS:
223                 case CST_SS_STATE_OFF:
224                         return strdup(T_(CST_STR_DEACTIVATED));
225                 case CST_SS_STATE_ON:
226                         return strdup(item_data->number);
227                 default:
228                         return NULL;
229                 }
230         }
231         return NULL;
232 }
233
234 static void __cst_gl_del_cf(void *data, Evas_Object *obj)
235 {
236         ret_if(NULL == data);
237         CstGlItemData_t *item_data = (CstGlItemData_t *)data;
238         if (item_data)
239                 free(item_data);
240         return;
241 }
242
243 static void __cst_update_change_cf_req(CstGlItemData_t *item_data, Eina_Bool req_state)
244 {
245         ret_if(NULL == item_data);
246         CstUgData_t *ugd = (CstUgData_t *)item_data->ugd;
247         Evas_Object *eo;
248         Elm_Object_Item *navi_it;
249         Evas_Object *btn;
250
251         CallSettingReq_t *req = NULL;
252         req = (CallSettingReq_t *)calloc(1, sizeof(CallSettingReq_t));
253         ret_if(req == NULL);
254
255         ugd->popup = NULL;
256         req->data = item_data;
257         req->call_type = ugd->call_type;
258         req->flavour = item_data->index;
259         DBG("req->flavour = %d", req->flavour);
260
261         ugd->original_state = !req_state;
262         if (req_state == EINA_TRUE) {
263                 req->action = CST_ACTION_ACTIVATE;
264                 req->original_state = CST_SS_STATE_OFF;
265                 eo = _cst_create_cf_ime(ugd->nf, NULL, ugd);
266
267                 _cst_remove_naviframe(ugd->nf);
268                 navi_it = elm_naviframe_item_push(ugd->nf,
269                         T_(CST_STR_FORWARD_TO), NULL, NULL, eo, "1line");
270
271                 btn = _cst_create_title_btn(ugd->nf, (char *)T_(CST_STR_CANCEL),
272                         __cst_on_click_cf_ime_cancel_btn, (void *)req);
273                 elm_object_item_part_content_set(navi_it, "title_left_btn", btn);
274                 
275                 btn = _cst_create_title_btn(ugd->nf, (char *)T_(CST_STR_DONE),
276                         __cst_on_click_cf_ime_done_btn, (void *)req);
277                 elm_object_item_part_content_set(navi_it, "title_right_btn", btn);
278                 elm_object_disabled_set(btn, EINA_TRUE);
279         } else {
280                 ugd->cf_state[item_data->index] = CST_SS_STATE_PROGRESS;
281                 elm_genlist_item_update(item_data->gl_item);
282                 _cst_add_ss_request(&ugd->req_queue, CST_ACTION_DEACTIVATE,
283                         ugd->call_type, req->flavour, NULL,
284                         __cst_update_cf_state, item_data);
285                 free(req);
286         }
287 }
288
289 static void __cst_on_click_cf_onoff(void *data, Evas *evas, Evas_Object *obj, void *event_info)
290 {
291         ret_if(NULL == data);
292         CstGlItemData_t *item_data = (CstGlItemData_t *)data;
293         CstUgData_t *ugd = item_data->ugd;
294
295         if (ugd->cf_state[item_data->index] == CST_SS_STATE_PROGRESS)
296                 return;
297
298         Eina_Bool check_state = elm_check_state_get(item_data->eo_check);
299
300         __cst_update_change_cf_req(item_data, !check_state);
301 }
302
303 static void __cst_gl_sel_cf(void *data, Evas_Object *obj, void *event_info)
304 {
305         ret_if(data == NULL);
306         CstGlItemData_t *item_data = (CstGlItemData_t *)data;
307         elm_genlist_item_selected_set((Elm_Object_Item *)event_info, EINA_FALSE);
308         if (list_call_forwarding[item_data->index].func)
309                 list_call_forwarding[item_data->index].func((void *)item_data, NULL, obj, event_info);
310         return;
311 }
312
313 static void __cst_on_changed_cf_check(void *data, Evas_Object *obj, void *event_info)
314 {
315         CstGlItemData_t *item_data = (CstGlItemData_t *)data;
316
317         Eina_Bool check_state = elm_check_state_get(obj);
318         if (elm_object_item_disabled_get(item_data->gl_item) == EINA_TRUE) {
319                 elm_check_state_set(obj, !check_state);
320                 return;
321         }
322
323         __cst_update_change_cf_req(item_data, check_state);
324 }
325
326 static Evas_Object *__cst_gl_icon_get_cf(void *data, Evas_Object *obj, const char *part)
327 {
328         retv_if(NULL == data, NULL);
329         Evas_Object *icon = NULL;
330         CstGlItemData_t *item_data = (CstGlItemData_t *)data;
331         CstUgData_t *ugd = (CstUgData_t *)item_data->ugd;
332         Eina_Bool check_state = EINA_FALSE;
333
334         if (!strcmp(part, "elm.icon")) {
335                 switch (ugd->cf_state[item_data->index]) {
336                 case CST_SS_STATE_ON:
337                 case CST_SS_STATE_OFF:
338                         DBG("ugd->cf_state : %d(%d)",
339                                 ugd->cf_state[item_data->index], item_data->index);
340                         if (ugd->cf_state[item_data->index] == CST_SS_STATE_ON)
341                                 check_state = EINA_TRUE;
342                         item_data->eo_check = icon = _cst_create_onoff_button(obj, check_state,
343                                 __cst_on_changed_cf_check, item_data);
344                         break;
345                 case CST_SS_STATE_PROGRESS:
346                         icon = _cst_create_progressbar(obj);
347                         break;
348                 default:
349                         return NULL;
350                 }
351         }
352         return icon;
353 }
354
355 static Evas_Object *__cst_create_genlist_cf(void *data)
356 {
357         ret_if(data == NULL);
358         CstUgData_t *ugd = (CstUgData_t *)data;
359         int index = 0;
360         Evas_Object *genlist;
361         CstGlItemData_t *item_data;
362
363         itc_2text_1icon->item_style = "dialogue/2text.1icon.6";
364         itc_2text_1icon->func.text_get = __cst_gl_label_get_cf;
365         itc_2text_1icon->func.content_get = __cst_gl_icon_get_cf;
366         itc_2text_1icon->func.state_get = NULL;
367         itc_2text_1icon->func.del = __cst_gl_del_cf;
368
369         genlist = elm_genlist_add(ugd->nf);
370
371         _cst_create_genlist_seperator(genlist, EINA_FALSE);
372         for (index = 0; list_call_forwarding[index].style != CST_GL_ITEM_NONE; ++index) {
373                 item_data = (CstGlItemData_t *)calloc(1, sizeof(CstGlItemData_t));
374                 retv_if(item_data == NULL, NULL);
375                 item_data->index = index;
376                 item_data->ugd = ugd;
377                 if (list_call_forwarding[index].style == CST_GL_ITEM_2TEXT_ONOFF_PROGRESS) {
378                         ugd->cf_state[index] = CST_SS_STATE_PROGRESS;
379                         item_data->gl_item = elm_genlist_item_append(genlist, itc_2text_1icon,
380                                 (void *)item_data, NULL, list_call_forwarding[index].flags,
381                                 __cst_gl_sel_cf, item_data);
382                         __cst_query_cf_status(item_data);
383                 } else {
384                         DBG("No style");
385                         free(item_data);
386                         item_data = NULL;
387                         return;
388                 }
389                 ugd->cf_gl_item[index] = item_data->gl_item;
390         }
391
392         return genlist;
393 }
394
395 static void __cst_on_click_voice_cf(void *data, Evas *evas, Evas_Object *obj, void *event_info)
396 {
397         ENTER(__cst_on_click_voice_cf);
398         ret_if(data == NULL);
399         CstUgData_t *ugd = (CstUgData_t *)data;
400         Evas_Event_Mouse_Up *ev = (Evas_Event_Mouse_Up *)event_info;
401         Evas_Object *back_btn = NULL;
402         Elm_Object_Item *navi_it;
403
404         if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) {
405                 return;
406         }
407
408         ugd->call_type = CST_CALLTYPE_VOICE;
409         ugd->popup = NULL;
410
411         Evas_Object *genlist = __cst_create_genlist_cf(ugd);
412
413         back_btn = elm_button_add(ugd->nf);
414         navi_it = elm_naviframe_item_push(ugd->nf, T_(CST_STR_VOICECALL),
415                 NULL, NULL, genlist, NULL);
416         back_btn = elm_object_item_part_content_get(navi_it, "prev_btn");
417         evas_object_smart_callback_add(back_btn, "clicked",
418                 __cst_on_click_cf_back_button, ugd);
419 }
420
421 static void __cst_on_click_video_cf(void *data, Evas *evas, Evas_Object *obj, void *event_info)
422 {
423         ENTER(__cst_on_click_video_cf);
424         ret_if(NULL == data);
425         CstUgData_t *ugd = (CstUgData_t *)data;
426         Evas_Event_Mouse_Up *ev = (Evas_Event_Mouse_Up *)event_info;
427         Evas_Object *back_btn = NULL;
428         Elm_Object_Item *navi_it;
429
430         if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) {
431                 return;
432         }
433
434         ugd->call_type = CST_CALLTYPE_VIDEO;
435         ugd->popup = NULL;
436
437         Evas_Object *genlist = __cst_create_genlist_cf(ugd);
438         navi_it = elm_naviframe_item_push(ugd->nf, T_(CST_STR_VIDEOCALL),
439                 NULL, NULL, genlist, NULL);
440         back_btn = elm_object_item_part_content_get(navi_it, "prev_btn");
441         evas_object_smart_callback_add(back_btn, "clicked",
442                 __cst_on_click_cf_back_button, ugd);
443 }
444
445 static void __cst_gl_sel_call_type(void *data, Evas_Object *obj, void *event_info)
446 {
447         ret_if(data == NULL);
448         CstUgData_t *ugd = (CstUgData_t *)data;
449         Elm_Object_Item *item= (Elm_Object_Item *)event_info;
450         int index = (int)elm_object_item_data_get(item);
451         elm_genlist_item_selected_set(item, EINA_FALSE);
452
453         if (list_call_type[index].func)
454                 list_call_type[index].func((void *)ugd, NULL, obj, event_info);
455         return;
456 }
457
458 static char *__cst_gl_label_get_call_type(void *data, Evas_Object *obj, const char *part)
459 {
460         int index = (int)data;
461
462         if (strcmp(part, "elm.text") == 0)
463                 return strdup(T_(list_call_type[index].str_id));
464         return NULL;
465 }
466
467 static Evas_Object *__cst_create_genlist_call_type(void *data)
468 {
469         ENTER(__cst_create_genlist_call_type);
470         retv_if(NULL == data, NULL);
471         CstUgData_t *ugd = (CstUgData_t *)data;
472         Evas_Object *genlist;
473         Elm_Object_Item *git;
474         int index = 0;
475
476         if (!itc_2text_1icon)
477                 itc_2text_1icon = elm_genlist_item_class_new();
478         if (!itc_1text)
479                 itc_1text = elm_genlist_item_class_new();
480
481         itc_1text->item_style = "dialogue/1text";
482         itc_1text->func.text_get = __cst_gl_label_get_call_type;
483         itc_1text->func.content_get = NULL;
484         itc_1text->func.state_get = NULL;
485         itc_1text->func.del = NULL;
486
487         genlist = elm_genlist_add(ugd->nf);
488
489         _cst_create_genlist_seperator(genlist, EINA_FALSE);
490         for (index = 0; list_call_type[index].style != CST_GL_ITEM_NONE; index++) {
491                 git = elm_genlist_item_append(genlist, itc_1text,
492                         (void *)index, NULL, ELM_GENLIST_ITEM_NONE,
493                         __cst_gl_sel_call_type, (void *)ugd);
494         }
495
496         return genlist;
497 }
498
499 void _cst_on_click_call_forwarding(void *data, Evas *evas, Evas_Object *obj, void *event_info)
500 {
501         ENTER(_cst_on_click_call_forwarding);
502         ret_if(NULL == data);
503         CstUgData_t *ugd = (CstUgData_t *)data;
504         Evas_Event_Mouse_Up *ev = (Evas_Event_Mouse_Up *)event_info;
505         Evas_Object *back_btn = NULL;
506         Elm_Object_Item *navi_it;
507
508         if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) {
509                 return;
510         }
511
512         if (_cst_check_flight_mode()) {
513                 ugd->popup = _cst_create_error_popup(ugd->nf,
514                         CST_ERROR_CHANGE_FLIGHT_MODE);
515                 evas_object_show(ugd->popup);
516                 return;
517         }
518
519         if (!_cst_check_sim_status()) {
520                 ugd->popup = _cst_create_error_popup(ugd->nf,
521                         CST_ERROR_INSERT_SIM_CARD);
522                 evas_object_show(ugd->popup);
523                 return;
524         }
525
526         Evas_Object *genlist = __cst_create_genlist_call_type(ugd);
527
528         navi_it = elm_naviframe_item_push(ugd->nf, T_(CST_STR_CALL_FORWARDING),
529                 NULL, NULL, genlist, NULL);
530         back_btn = elm_object_item_part_content_get(navi_it, "prev_btn");
531         evas_object_smart_callback_add(back_btn, "clicked",
532                 __cst_on_click_cf_back_button, ugd);
533 }
534