4 * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
24 //#include <Ecore_X.h>
25 #include <utils_i18n.h>
26 #include <system_settings.h>
29 #include "indicator.h"
31 #include "indicator_gui.h"
38 #define SYSTEM_RESUME "system_wakeup"
40 #define TIME_FONT_SIZE_24 ELM_SCALE_SIZE(30)
41 #define TIME_FONT_SIZE_12 ELM_SCALE_SIZE(30)
42 #define AMPM_FONT_SIZE ELM_SCALE_SIZE(29)
44 #define TIME_FONT_COLOR 200, 200, 200, 255
45 #define AMPM_FONT_COLOR 200, 200, 200, 255
46 #define LABEL_STRING "<font_size=%d>%s" \
48 #define LABEL_STRING_FONT "%s</font>"
50 #define BATTERY_TIMER_INTERVAL 3
51 #define BATTERY_TIMER_INTERVAL_CHARGING 30
53 #define CLOCK_STR_LEN 128
56 INDICATOR_CLOCK_MODE_12H = 0,
57 INDICATOR_CLOCK_MODE_24H,
58 INDICATOR_CLOCK_MODE_MAX
61 int clock_mode = INDICATOR_CLOCK_MODE_12H;
63 static const char *colon = ":";
64 static const char *ratio = "∶";
66 static int apm_length = 0;
67 static int apm_position = 0;
68 extern Ecore_Timer *clock_timer;
70 static i18n_udatepg_h _last_generator;
71 static char *_last_locale = NULL;
72 static int battery_charging = 0;
74 static int register_clock_module(void *data);
75 static int unregister_clock_module(void);
76 static int language_changed_cb(void *data);
77 static int region_changed_cb(void *data);
78 static int wake_up_cb(void *data);
79 #ifdef _SUPPORT_SCREEN_READER
80 static int register_clock_tts(void *data,int win_type);
83 #define ICON_PRIORITY INDICATOR_PRIORITY_FIXED8
84 #define MODULE_NAME "clock"
86 static void indicator_get_apm_by_region(char* output, void* data);
87 static void indicator_get_time_by_region(char* output, void* data);
89 #ifdef _SUPPORT_SCREEN_READER
90 static void ICU_set_timezone(const char *timezone);
94 .type = INDICATOR_TXT_ICON,
96 .priority = ICON_PRIORITY,
97 .always_top = EINA_FALSE,
99 .obj_exist = EINA_FALSE,
100 .exist_in_view = EINA_FALSE,
101 .init = register_clock_module,
102 .fini = unregister_clock_module,
103 .region_changed = region_changed_cb,
104 .lang_changed = language_changed_cb,
105 .wake_up = wake_up_cb,
110 void cal_delete_last_generator(void)
116 if (_last_generator) {
117 i18n_udatepg_destroy(_last_generator);
118 _last_generator = NULL;
124 static i18n_udatepg_h __cal_get_pattern_generator(const char *locale, int *status)
126 if (!_last_generator || !_last_locale || strcmp(locale, _last_locale)) {
128 cal_delete_last_generator();
130 _last_locale = strdup(locale);
132 int ret = i18n_udatepg_create(locale, &_last_generator);
133 if (ret != I18N_ERROR_NONE) {
134 _E("i18n_udatepg_create failed %d", ret);
135 _last_generator = NULL;
138 return _last_generator;
143 static void set_app_state(void* data)
150 static void indicator_clock_changed_cb(void *data)
152 char time_str[CLOCK_STR_LEN] = {0,};
153 char time_buf[CLOCK_STR_LEN] = {0,};
154 char ampm_buf[CLOCK_STR_LEN] = {0,};
155 char ampm_str[CLOCK_STR_LEN] = {0,};
156 char buf[CLOCK_STR_LEN] = {0,};
157 char result[CLOCK_STR_LEN] = {0,};
158 char icu_apm[CLOCK_STR_LEN] = {0,};
160 struct tm *ts = NULL;
162 struct appdata *ad = NULL;
165 int ampm_size = AMPM_FONT_SIZE;
169 ad = (struct appdata *)data;
171 if (icon_get_update_flag() == 0) return;
175 ts = localtime(&ctime);
177 _E("Fail to get localtime !");
181 if (clock_timer != NULL) {
182 ecore_timer_del(clock_timer);
186 memset(time_str, 0x00, sizeof(time_str));
187 memset(ampm_str, 0x00, sizeof(ampm_str));
188 memset(time_buf, 0x00, sizeof(time_buf));
189 memset(ampm_buf, 0x00, sizeof(ampm_buf));
190 memset(buf, 0x00, sizeof(buf));
192 clock_timer = ecore_timer_add(60 - ts->tm_sec, (void *)indicator_clock_changed_cb, data);
194 _E("Fail to add timer !");
197 indicator_get_apm_by_region(icu_apm,data);
198 indicator_get_time_by_region(time_buf,data);
201 if (clock_mode == INDICATOR_CLOCK_MODE_12H) {
202 char bf1[32] = { 0, };
204 static int pre_hour = 0;
205 const char *region = NULL;
207 int bRegioncheck = 0;
208 char *lang1 = "it_IT";
210 region = vconf_get_str(VCONFKEY_REGIONFORMAT);
213 if (strncmp(region,lang1,strlen(lang1)) == 0) bRegioncheck = 1;
215 if (apm_length>=4 || bRegioncheck==1) {
216 if (ts->tm_hour >= 0 && ts->tm_hour < 12) {
217 snprintf(ampm_buf, sizeof(ampm_buf),"%s","AM");
219 snprintf(ampm_buf, sizeof(ampm_buf),"%s","PM");
222 snprintf(ampm_buf, sizeof(ampm_buf),"%s",icu_apm);
225 strftime(bf1, sizeof(bf1), "%l", ts);
227 strftime(bf1, sizeof(bf1), ":%M", ts);
229 font_size = TIME_FONT_SIZE_12;
232 if ((pre_hour<10 && hour>=10)||(pre_hour>=10 && hour<10)) {
233 box_update_display(&(ad->win));
238 font_size = TIME_FONT_SIZE_24;
241 snprintf(time_str, sizeof(time_str), LABEL_STRING, font_size, time_buf);
242 snprintf(ampm_str, sizeof(ampm_str), LABEL_STRING, ampm_size, ampm_buf);
244 if (clock_mode == INDICATOR_CLOCK_MODE_12H) {
245 if (apm_position == 0) {
246 len = snprintf(buf, sizeof(buf), "%s %s", ampm_str, time_str);
248 len = snprintf(buf, sizeof(buf), "%s %s", time_str, ampm_str);
251 len = snprintf(buf, sizeof(buf), "%s", time_str);
254 snprintf(result, sizeof(result), LABEL_STRING_FONT, buf);
256 _E("Unexpected ERROR!");
260 _D("[CLOCK MODULE] Timer Status : %d Time: %s", clock_timer, result);
261 util_part_text_emit(data, "elm.text.clock", result);
268 static void _clock_format_changed_cb(keynode_t *node, void *data)
270 struct appdata *ad = NULL;
272 i18n_timezone_h timezone;
276 ad = (struct appdata *)data;
278 if (vconf_get_int(VCONFKEY_REGIONFORMAT_TIME1224,&mode_24) < 0)
280 ERR("Error getting VCONFKEY_REGIONFORMAT_TIME1224 value");
284 /* Check Time format. If timeformat have invalid value, Set to 12H */
285 if( mode_24==VCONFKEY_TIME_FORMAT_24)
287 if(clock_mode == INDICATOR_CLOCK_MODE_12H)
289 clock_mode = INDICATOR_CLOCK_MODE_24H;
290 box_update_display(&(ad->win));
295 if(clock_mode==INDICATOR_CLOCK_MODE_24H)
297 clock_mode = INDICATOR_CLOCK_MODE_12H;
298 box_update_display(&(ad->win));
302 char *timezone_str = util_get_timezone_str();
304 int ret = i18n_timezone_create(&timezone, timezone_str);
305 if (ret != I18N_ERROR_NONE) {
306 _E("Unable to create timzone handle for %s: %d", timezone_str, ret);
311 ret = i18n_timezone_set_default(timezone);
312 if (ret != I18N_ERROR_NONE) {
313 _E("Unable to set default timzone: %d", ret);
314 i18n_timezone_destroy(timezone);
319 indicator_clock_changed_cb(data);
320 i18n_timezone_destroy(timezone);
326 static void indicator_clock_charging_now_cb(keynode_t *node, void *data)
330 retif(data == NULL, , "Invalid parameter!");
333 vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, &status);
335 battery_charging = status;
340 static int language_changed_cb(void *data)
342 const char *pa_lang = vconf_get_str(VCONFKEY_LANGSET);
343 DBG("language_changed_cb %s",pa_lang);
344 indicator_clock_changed_cb(data);
350 static int region_changed_cb(void *data)
352 _clock_format_changed_cb(NULL, data);
358 static int wake_up_cb(void *data)
360 indicator_clock_changed_cb(data);
367 /*static void _time_changed(system_settings_key_e key, void *data)
369 DBG("_time_changed");
370 _clock_format_changed_cb(NULL,data);
375 static void regionformat_changed(keynode_t *node, void *data)
377 DBG("regionformat_changed");
378 _clock_format_changed_cb(NULL,data);
383 static void timezone_int_changed(keynode_t *node, void *data)
385 DBG("timezone_int_changed");
386 _clock_format_changed_cb(NULL,data);
391 static void timezone_id_changed(keynode_t *node, void *data)
393 char *szTimezone = NULL;
394 szTimezone = vconf_get_str(VCONFKEY_SETAPPL_TIMEZONE_ID);
396 DBG("timezone_id_changed %s",szTimezone);
397 _clock_format_changed_cb(NULL,data);
402 static int register_clock_module(void *data)
406 retif(data == NULL, FAIL, "Invalid parameter!");
410 /*ret = system_settings_set_changed_cb(SYSTEM_SETTINGS_KEY_TIME_CHANGED, _time_changed, data);
415 ret = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, regionformat_changed, data);
420 ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_TIMEZONE_INT, timezone_int_changed, data);
425 ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_TIMEZONE_ID, timezone_id_changed, data);
430 ret = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, regionformat_changed, data);
434 _clock_format_changed_cb(NULL, data);
435 indicator_clock_charging_now_cb(NULL,data);
442 static int unregister_clock_module(void)
446 //ret = system_settings_unset_changed_cb(SYSTEM_SETTINGS_KEY_TIME_CHANGED);
447 ret = ret | vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, regionformat_changed);
448 ret = ret | vconf_ignore_key_changed(VCONFKEY_SETAPPL_TIMEZONE_INT, timezone_int_changed);
449 ret = ret | vconf_ignore_key_changed(VCONFKEY_SETAPPL_TIMEZONE_ID, timezone_id_changed);
450 ret = ret | vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT, regionformat_changed);
452 if (clock_timer != NULL) {
453 ecore_timer_del(clock_timer);
457 cal_delete_last_generator();
464 static inline char *_extend_heap(char *buffer, int *sz, int incsz)
469 tmp = realloc(buffer, *sz);
480 static char *_string_replacer(const char *src, const char *pattern, const char *replace)
495 if (!src || !pattern)
498 out_sz = strlen(src);
506 for (state = STATE_START, ptr = src; state != STATE_END; ptr++) {
511 } else if (!isblank(*ptr)) {
519 } else if (*ptr == *pattern) {
526 if (out_idx == out_sz) {
527 tmp = _extend_heap(ret, &out_sz, strlen(replace) + 1);
539 * If there is no space for copying the replacement,
540 * Extend size of the return buffer.
542 if (out_sz - out_idx < strlen(replace) + 1) {
543 tmp = _extend_heap(ret, &out_sz, strlen(replace) + 1);
551 strcpy(ret + out_idx, replace);
552 out_idx += strlen(replace);
556 } else if (*ptr != pattern[idx]) {
559 /* Copy the first matched character */
562 if (out_idx == out_sz) {
563 tmp = _extend_heap(ret, &out_sz, strlen(replace) + 1);
588 void indicator_get_apm_by_region(char* output,void *data)
590 retif(data == NULL, , "Data parameter is NULL");
591 retif(output == NULL, , "output parameter is NULL");
593 i18n_uchar u_custom_skeleton[CLOCK_STR_LEN] = { 0, };
594 i18n_uchar u_timezone[64] = {0,};
595 i18n_uchar u_best_pattern[CLOCK_STR_LEN] = { 0, };
596 i18n_uchar u_formatted[CLOCK_STR_LEN] = { 0, };
598 i18n_udate_format_h formatter;
599 int32_t best_pattern_len, formatted_len;
601 char s_best_pattern[CLOCK_STR_LEN] = { 0, };
602 char s_formatted[CLOCK_STR_LEN] = { 0, };
606 i18n_udatepg_h pattern_generator = NULL;
608 char *locale = vconf_get_str(VCONFKEY_REGIONFORMAT);
611 ERR("[Error] get value of fail.");
615 /* Remove ".UTF-8" in locale */
616 char locale_tmp[32] = {0,};
617 strncpy(locale_tmp, locale, sizeof(locale_tmp)-1);
618 char *p = util_safe_str(locale_tmp, ".UTF-8");
624 i18n_ustring_copy_ua_n(u_custom_skeleton, "hhmm", ARRAY_SIZE(u_custom_skeleton));
626 pattern_generator = __cal_get_pattern_generator (locale_tmp, &status);
627 if (pattern_generator == NULL) {
631 int ret = i18n_udatepg_get_best_pattern(pattern_generator, u_custom_skeleton, i18n_ustring_get_length(u_custom_skeleton),
632 u_best_pattern, (int32_t)ARRAY_SIZE(u_best_pattern), &best_pattern_len);
633 if (ret != I18N_ERROR_NONE) {
634 _E("i18n_udatepg_get_best_pattern failed: %d", ret);
638 i18n_ustring_copy_au(s_best_pattern, u_best_pattern);
639 i18n_ustring_copy_ua(u_best_pattern, "a");
641 char *timezone_id = util_get_timezone_str();
642 DBG("TimeZone is %s", timezone_id);
644 if (s_best_pattern[0] == 'a') {
652 ret = i18n_ucalendar_get_now(&date);
653 if (ret != I18N_ERROR_NONE) {
654 ERR("i18n_ucalendar_get_now failed: %d", ret);
659 i18n_ustring_copy_ua_n(u_timezone, timezone_id, ARRAY_SIZE(u_timezone));
662 ret = i18n_udate_create(I18N_UDATE_PATTERN, I18N_UDATE_PATTERN, locale_tmp, timezone_id ? u_timezone : NULL, -1,
663 u_best_pattern, -1, &formatter);
664 if (ret != I18N_ERROR_NONE) {
671 ret = i18n_udate_format_date(formatter, date, u_formatted, ARRAY_SIZE(s_formatted), NULL, &formatted_len);
672 if (ret != I18N_ERROR_NONE) {
673 i18n_udate_destroy(formatter);
677 i18n_udate_destroy(formatter);
679 i18n_ustring_copy_au(s_formatted, u_formatted);
680 apm_length = i18n_ustring_get_length(u_formatted);
682 if (strlen(s_formatted) < CLOCK_STR_LEN) {
683 strncpy(output, s_formatted, strlen(s_formatted));
686 strncpy(output, s_formatted, CLOCK_STR_LEN - 1);
694 void indicator_get_time_by_region(char* output,void *data)
696 retif(data == NULL, , "Data parameter is NULL");
697 retif(output == NULL, , "output parameter is NULL");
699 i18n_uchar u_custom_skeleton[CLOCK_STR_LEN] = { 0, };
700 i18n_uchar u_timezone[64] = {0,};
701 i18n_uchar u_best_pattern[CLOCK_STR_LEN] = { 0, };
702 i18n_uchar u_formatted[CLOCK_STR_LEN] = { 0, };
705 i18n_udate_format_h formatter = NULL;
707 char s_best_pattern[CLOCK_STR_LEN] = { 0, };
708 char s_formatted[CLOCK_STR_LEN] = { 0, };
709 char *s_convert_formatted = NULL;
711 char s_time_skeleton[20] = {0,};
712 i18n_udatepg_h pattern_generator = NULL;
714 int32_t best_pattern_len, formatted_len;
716 if (clock_mode == INDICATOR_CLOCK_MODE_12H) {
717 strcpy(s_time_skeleton, "hm");
720 strcpy(s_time_skeleton, "Hm");
722 char *locale = vconf_get_str(VCONFKEY_REGIONFORMAT);
723 if (locale == NULL) {
724 ERR("[Error] get value of fail.");
728 /* Remove ".UTF-8" in locale */
729 char locale_tmp[32] = {0,};
730 strncpy(locale_tmp, locale, sizeof(locale_tmp)-1);
731 char *p = util_safe_str(locale_tmp, ".UTF-8");
737 i18n_ustring_copy_ua_n(u_custom_skeleton, s_time_skeleton, ARRAY_SIZE(u_custom_skeleton));
739 pattern_generator = __cal_get_pattern_generator (locale_tmp, &status);
740 if (pattern_generator == NULL) {
744 int ret = i18n_udatepg_get_best_pattern(pattern_generator, u_custom_skeleton, i18n_ustring_get_length(u_custom_skeleton),
745 u_best_pattern, ARRAY_SIZE(u_best_pattern), &best_pattern_len);
746 if (ret != I18N_ERROR_NONE) {
747 _E("i18n_udatepg_get_best_pattern failed: %d", ret);
751 char a_best_pattern[64] = {0,};
752 i18n_ustring_copy_au(a_best_pattern, u_best_pattern);
754 char *a_best_pattern_fixed = strtok(a_best_pattern, "a");
755 a_best_pattern_fixed = strtok(a_best_pattern_fixed, " ");
756 if (a_best_pattern_fixed) {
757 i18n_ustring_copy_ua(u_best_pattern, a_best_pattern_fixed);
760 i18n_ustring_copy_au(s_best_pattern, u_best_pattern);
762 DBG("BestPattern is %s", s_best_pattern);
765 ret = i18n_ucalendar_get_now(&date);
766 if (ret != I18N_ERROR_NONE) {
767 ERR("i18n_ucalendar_get_now failed: %d", ret);
771 char* timezone_id = util_get_timezone_str();
772 DBG("TimeZone is %s", timezone_id);
775 i18n_ustring_copy_ua_n(u_timezone, timezone_id, ARRAY_SIZE(u_timezone));
778 ret = i18n_udate_create(I18N_UDATE_PATTERN, I18N_UDATE_PATTERN, locale_tmp, timezone_id ? u_timezone : NULL, -1,
779 u_best_pattern, -1, &formatter);
780 if (ret != I18N_ERROR_NONE) {
787 ret = i18n_udate_format_date(formatter, date, u_formatted, ARRAY_SIZE(s_formatted), NULL, &formatted_len);
788 if (ret != I18N_ERROR_NONE) {
789 i18n_udate_destroy(formatter);
793 i18n_udate_destroy(formatter);
795 i18n_ustring_copy_au(s_formatted, u_formatted);
796 DBG("DATE & TIME is %s %s %d %s", locale_tmp, s_formatted, i18n_ustring_get_length(u_formatted), s_best_pattern);
798 DBG("24H :: Before change %s", s_formatted);
799 s_convert_formatted = _string_replacer(s_formatted, colon, ratio);
800 DBG("24H :: After change %s", s_convert_formatted);
802 if (!s_convert_formatted) {
803 DBG("_string_replacer return NULL");
807 if (strlen(s_convert_formatted) < CLOCK_STR_LEN) {
808 strncpy(output, s_convert_formatted, strlen(s_convert_formatted));
811 strncpy(output, s_convert_formatted, CLOCK_STR_LEN - 1);
814 free(s_convert_formatted);
820 #ifdef _SUPPORT_SCREEN_READER
821 static void ICU_set_timezone(const char *timezone)
825 if (timezone == NULL) {
826 ERR("TIMEZONE is NULL");
830 int ret = i18n_timezone_create(&tmz, timezone);
831 if (ret != I18N_ERROR_NONE) {
832 ERR("Unable to create timezone handle from %s: %d", timezone, ret);
836 ret = i18n_timezone_set_default(tmz);
837 if (ret != I18N_ERROR_NONE) {
838 ERR("Unable to set default timezone to %s: %d", timezone, ret);
841 i18n_timezone_destroy(tmz);
847 #ifdef _SUPPORT_SCREEN_READER
848 static char *_access_info_cb(void *data, Evas_Object *obj)
850 Evas_Object *item = data;
853 char time_buf[128], ampm_buf[128];
854 char buf[CLOCK_STR_LEN];
855 char buf1[CLOCK_STR_LEN];
857 int battery_capa = 0;
860 char strHour[128] = { 0, };
861 char strMin[128] = { 0, };
864 struct tm *ts = NULL;
868 retif(data == NULL,NULL, "Invalid parameter!");
869 char *timezone = util_get_timezone_str();
870 ICU_set_timezone(timezone);
876 ts = localtime(&ctime);
880 memset(time_str, 0x00, sizeof(time_str));
881 memset(time_buf, 0x00, sizeof(time_buf));
882 memset(ampm_buf, 0x00, sizeof(ampm_buf));
883 memset(buf, 0x00, sizeof(buf));
884 memset(buf1, 0x00, sizeof(buf1));
886 if (clock_mode == INDICATOR_CLOCK_MODE_12H) {
887 char bf1[32] = { 0, };
889 if (ts->tm_hour >= 0 && ts->tm_hour < 12)
890 strncpy(ampm_buf, _("IDS_IDLE_OPT_AM_ABB"),sizeof(ampm_buf)-1);
892 strncpy(ampm_buf, _("IDS_IDLE_OPT_PM_ABB"),sizeof(ampm_buf)-1);
894 strftime(bf1, sizeof(bf1), "%l", ts);
896 strftime(bf1, sizeof(bf1), "%M", ts);
900 char bf1[32] = { 0, };
902 strftime(bf1, sizeof(bf1), "%H", ts);
904 strftime(bf1, sizeof(bf1), "%M", ts);
910 strncpy(strHour, _("IDS_COM_BODY_1_HOUR"),sizeof(strHour));
914 snprintf(strHour, sizeof(strHour), _("IDS_COM_POP_PD_HOURS"),hour);
919 strncpy(strMin, _("IDS_COM_BODY_1_MINUTE"),sizeof(strMin));
923 snprintf(strMin, sizeof(strMin), _("IDS_COM_BODY_PD_MINUTES"),minute);
926 if(clock_mode == INDICATOR_CLOCK_MODE_12H)
927 snprintf(time_str, sizeof(time_str), "%s, %s, %s", strHour, strMin,ampm_buf);
929 snprintf(time_str, sizeof(time_str), "%s, %s", strHour, strMin);
932 ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY, &battery_capa);
937 if (battery_capa < 0)
942 if (battery_capa > 100)
944 snprintf(buf1, sizeof(buf1), _("IDS_IDLE_BODY_PD_PERCENT_OF_BATTERY_POWER_REMAINING"), battery_capa);
946 snprintf(buf, sizeof(buf), "%s, %s, %s", time_str, buf1, _("IDS_IDLE_BODY_STATUS_BAR_ITEM"));
950 if (!tmp) return NULL;
956 static int register_clock_tts(void *data,int win_type)
960 retif(data == NULL, FAIL, "Invalid parameter!");
962 Evas_Object *to = NULL;
963 Evas_Object *ao = NULL;
964 struct appdata *ad = data;
966 to = (Evas_Object *) edje_object_part_object_get(elm_layout_edje_get(ad->win[win_type].layout), "elm.rect.clock.access");
967 ao = util_access_object_register(to, ad->win[win_type].layout);
968 util_access_object_info_cb_set(ao,ELM_ACCESS_INFO,_access_info_cb,data);