3 * Copyright 2012 Samsung Electronics Co., Ltd
5 * Licensed under the Flora License, Version 1.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.tizenopensource.org/license
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 #include <stdbool.h> /* true/false */
20 #include <Elementary.h>
23 #include "calc-main.h"
24 #include "calculator_parser.h"
25 #include "calc-string.h"
26 #include "calc-expression.h"
27 #include "calc-view.h"
30 #define CALCULATOR_CHAR_IS_OPERATOR(C) ((C == '+')||(C == '-')||(C == 'x')||(C == '/')) /**<judge if a char is a basic operator*/
31 #define CALCULATOR_CHAR_IS_MULTI_DIVIDE_OPERATOR(C) ((C == 'x')||(C == '/')) /**<judge if an operator is "*" or "/"*/
32 #define CALCULATOR_CHAR_IS_PLUS_DEDUCT(C) ((C == '+')||(C == '-'))
33 #define CALCULATOR_CHAR_IS_DIGITAL(C)(C >= '0' && C <= '9')
34 #define CALCULATOR_IS_DIGIT_DOT(ch, decimal) (isdigit(ch) || decimal == (ch))
36 static Elm_Entry_Filter_Limit_Size limit_filter_data;
37 extern void _calc_view_show_newest_histroy(Evas_Object * entry);
38 extern void _calc_view_clear_histroy(Evas_Object * entry);
39 extern gboolean __calculator_search_function(char *op, int* len);
40 static void __calculator_wrong_format_create(char * wrong_string);
42 static struct appdata *ad; /* will be removed */
43 static calculator_state_t calculator_state = CALCULATOR_WAITING_INPUT;
44 static double last_result = 0.0;
45 int calculator_cursor_pos = 0;
46 char calculator_input_str[MAX_EXPRESSION_LENGTH] = { 0 };
47 char calculator_before_paste_str[MAX_EXPRESSION_LENGTH] = { 0 };
48 bool paste_flag = FALSE;
50 struct lconv *locale = NULL;
52 char *separator = NULL;
54 char separator_ch = 0;
56 int cur_fontsize = 70;
57 int small_fontsize = 58;
58 int default_fontsize = 0;
61 int scientific_result_len = 8;
64 static op_item_t calc_op_item[] = {
65 {OP_INVALID, "", NULL},
68 {OP_PARENTHESIS, "()", NULL},
69 {OP_DELETE, "<-", NULL},
70 {OP_CLEAR, "C", NULL},
71 {OP_DIVIDE, "/", NULL},
73 {OP_NUM_7, "7", NULL},
74 {OP_NUM_8, "8", NULL},
75 {OP_NUM_9, "9", NULL},
76 {OP_MULTIPLY, "x", NULL},
78 {OP_NUM_4, "4", NULL},
79 {OP_NUM_5, "5", NULL},
80 {OP_NUM_6, "6", NULL},
81 {OP_MINUS, "-", NULL},
83 {OP_NUM_1, "1", NULL},
84 {OP_NUM_2, "2", NULL},
85 {OP_NUM_3, "3", NULL},
89 {OP_NUM_0, "0", NULL},
90 {OP_PLUS_MINUS, "+/-", NULL},
91 {OP_EQUAL, "=", NULL},
94 {OP_PERCENT, "%", NULL},
95 {OP_ROOT, "sqrt", "sqrt("},
98 {OP_SIN, "sin", "sin("},
99 {OP_COS, "cos", "cos("},
100 {OP_TAN, "tan", "tan("},
102 {OP_LN, "ln", "ln("},
103 {OP_LOG, "log", "log("},
104 {OP_1X, "1/x", "1/x"},
106 {OP_10X, "10^x", "10^("},
107 {OP_X2, "x^2", "^2"},
108 {OP_XY, "x^y", "^("},
110 {OP_ABS, "abs", "abs("},
114 char *error_string[] = {
115 "IDS_CCL_POP_UP_TO_15_DIGITS_AVAILABLE",
116 "IDS_CCL_POP_UP_TO_5_DECIMALS_AVAILABLE",
117 "IDS_CCL_POP_UP_TO_20_OPERATORS_AVAILABLE",
118 "IDS_CCL_POP_UNABLE_TO_DIVIDE_BY_ZERO",
119 "IDS_CCL_POP_NO_NUMBER_ERROR",
121 "IDS_CCL_POP_ENTER_NUMBER_AFTER_OPERATOR",
122 "IDS_CCL_BODY_INVALID_INPUT_FOR_SQUARE_ROOT_FUNCTION",
123 "IDS_CCL_BODY_INVALID_INPUT_FOR_LOG_FUNCTION",
124 "IDS_CCL_BODY_NATURAL_NUMBER_ONLY_FOR_X_E_FUNCTION",
125 "IDS_CCL_BODY_ENTER_NUMBER_BEFORE_INPUTTING_X_E_FUNCTION",
126 "IDS_CCL_BODY_ENTER_NUMBER_BEFORE_INPUTTING_1_X_FUNCTION",
127 "IDS_CCL_BODY_ENTER_NUMBER_BEFORE_INPUTTING_X2_FUNCTION",
128 "IDS_CCL_BODY_ENTER_NUMBER_BEFORE_INPUTTING_XY_FUNCTION",
129 "IDS_CCL_POP_NO_OPERATOR_ERROR",
130 "IDS_CCL_POP_SYNTAX_ERROR",
133 calculator_state_t calculator_get_state()
135 return calculator_state;
138 void _calc_add_tag(char *string, char *format_string)
144 char buf[MAX_EXPRESSION_LENGTH] = { 0 };
145 char tmp[MAX_EXPRESSION_LENGTH] = { 0 };
147 while (string[i] != '\0') {
148 if (CALCULATOR_CHAR_IS_DIGITAL(string[i])
149 || string[i] == separator_ch || string[i] == decimal_ch
150 ||( string[i]=='(' && string[i+1]=='\xe2' &&string[i+2]=='\x88' && string[i+3]=='\x92')) {
151 if ( string[i]=='(' && string[i+1]=='\xe2' &&string[i+2]=='\x88' && string[i+3]=='\x92') {
152 memset(buf, 0, sizeof(buf));
153 snprintf(buf, sizeof(buf),
154 "<align=right><font_size=%d><color=#7A9CC6FF>(<align=right><font_size=%d><color=#FFFFFFFF>-",
155 cur_fontsize, cur_fontsize);
156 strcat(format_string, buf);
161 while (CALCULATOR_CHAR_IS_DIGITAL(string[i])
162 || string[i] == separator_ch
163 || string[i] == decimal_ch) {
167 strncpy(tmp, p, MAX_EXPRESSION_LENGTH - 1);
168 tmp[end - begin + 1] = '\0';
169 memset(buf, 0, sizeof(buf));
170 snprintf(buf, sizeof(buf),
171 "<align=right><font_size=%d><color=#FFFFFFFF>%s",
173 strcat(format_string, buf);
177 while (!CALCULATOR_CHAR_IS_DIGITAL(string[i])
178 && string[i] != separator_ch
179 && string[i] != decimal_ch
180 && string[i] != '\0') {
181 if ( string[i]=='(' && string[i+1]=='\xe2' &&string[i+2]=='\x88' && string[i+3]=='\x92') {
188 strncpy(tmp, p, MAX_EXPRESSION_LENGTH - 1);
189 tmp[end - begin + 1] = '\0';
190 memset(buf, 0, sizeof(buf));
191 snprintf(buf, sizeof(buf),
192 "<align=right><font_size=%d><color=#7A9CC6FF>%s",
194 strcat(format_string, buf);
203 * Change line and font size when it is needed.
204 * Refer to the auto font resizing rules.
205 * @param tag_text The text with tags.
209 void _calc_add_br(char *tag_text)
212 if (tag_text == NULL) {
215 int line_valid_num = 0;
216 int whole_valid_num = 0;
217 int operator_tag = -1;
218 int operator_location = -1;
219 /* record is there an operator in one line? */
220 bool operator_flag = FALSE;
221 /* when change to small font, we should rescan the tag_text */
222 bool rescan_flag = FALSE;
224 char buf[MAX_TAG_EXPRESSION_LENGTH] = { 0 };
225 strcpy(buf, tag_text);
229 for ( ; tag_text[i] != '\0' && calculator_input_str[j] != '\0'; ) {
230 while (tag_text[i] == '<') {
231 while (tag_text[i++] != '>');
233 /* if calculator_input_str[j] is "*" or "/", tag_text[i] would be
234 "\xc3\x97" or "\xc3\xb7" */
235 if (tag_text[i] == calculator_input_str[j] || (tag_text[i] == '\xc3') ||
236 ((tag_text[i] == '\xe2') && (tag_text[i+1] == '\x88') && (tag_text[i+2] == '\x92'))) {
238 if ((CALCULATOR_CHAR_IS_OPERATOR(calculator_input_str[j])) &&
239 (!(calculator_input_str[j] == '-' && calculator_input_str[j-1] == '('))) {
240 if (!operator_flag || rescan_flag) {
241 operator_location = j;
243 operator_flag = TRUE;
250 cur_fontsize = default_fontsize;
253 if ((line_valid_num >= min_len) && (!rescan_flag)) {
255 cur_fontsize = small_fontsize;
256 strcpy(tag_text, buf);
257 /* restore to the original state, then scan from the begin */
262 operator_flag = FALSE;
264 operator_location = -1;
265 cur_len = max_len + 1;
269 if (line_valid_num >= cur_len) {
270 if (operator_flag && operator_tag > 0) {
271 string_insert(tag_text, operator_tag, "<br>");
272 line_valid_num = whole_valid_num-operator_location;
273 operator_flag = FALSE;
275 operator_location = -1;
277 string_insert(tag_text, i, "<br>");
305 static void _calc_entry_text_set(Evas_Object * entry, const char *str)
308 char tmp[MAX_EXPRESSION_LENGTH] = { 0 };
309 char tag_text[MAX_TAG_EXPRESSION_LENGTH] = { 0 };
310 char new_font_str[MAX_EXPRESSION_LENGTH] = { 0 };
311 char old_font_str[MAX_EXPRESSION_LENGTH] = { 0 };
317 if (strlen(str) == 0) {
318 elm_entry_entry_set(entry, "");
319 elm_entry_cursor_end_set(entry);
320 elm_object_focus_set(entry, EINA_TRUE);
324 calc_expr_format_expression(str, tmp);
325 _calc_add_tag(tmp, tag_text);
326 int pre_fontsize = cur_fontsize;
327 _calc_add_br(tag_text);
328 snprintf(old_font_str, sizeof(old_font_str), "=%d", pre_fontsize);
329 snprintf(new_font_str, sizeof(new_font_str), "=%d", cur_fontsize);
330 string_replace(tag_text, old_font_str, new_font_str);
331 elm_entry_entry_set(entry, tag_text);
332 if(calculator_cursor_pos == strlen(calculator_input_str)){
333 elm_entry_cursor_end_set(entry);
334 elm_object_focus_set(entry, EINA_TRUE);
336 calc_view_cursor_set_position(entry, calculator_cursor_pos);
341 void _calc_entry_text_set_rotate(struct appdata *ad)
344 if (calculator_state == CALCULATOR_CALCULATED) {
345 _calc_view_show_newest_histroy(ad->input_entry);
346 elm_entry_cursor_end_set(ad->input_entry);
347 elm_object_focus_set(ad->input_entry, EINA_TRUE);
349 _calc_entry_text_set(ad->input_entry, calculator_input_str);
363 static void _calc_entry_text_insert(Evas_Object * entry, char *str)
366 calc_expr_input_insert(calculator_input_str, &calculator_cursor_pos,
368 _calc_entry_text_set(entry, calculator_input_str);
382 static void _calc_entry_text_remove(Evas_Object * entry, const int from_pos,
386 string_remove_at(calculator_input_str, from_pos,
387 end_pos - from_pos + 1);
388 calculator_cursor_pos = from_pos;
389 _calc_entry_text_set(entry, calculator_input_str);
395 * Set correct cursor position in entry.
401 static void _calc_entry_cursor_set(Evas_Object * entry)
404 calc_view_cursor_set_position(entry, calculator_cursor_pos);
416 static void _calc_entry_backspace(Evas_Object * entry)
419 calc_expr_input_backspace(calculator_input_str, &calculator_cursor_pos);
420 _calc_entry_text_set(entry, calculator_input_str);
432 void _calc_entry_clear(Evas_Object * entry)
435 memset(calculator_input_str, 0, sizeof(calculator_input_str));
436 calculator_cursor_pos = 0;
437 _calc_entry_text_set(entry, "");
438 calc_view_cursor_set_position(entry, calculator_cursor_pos);
442 /* END INPUT ENTRY RELATED */
446 * Get the operand start and end location where the cursor in.
447 * 1.2+6.|43 (cursor is before 4), then return begin=4 end=7
448 * Espcially, cursor is after +, it means the operand which follows
449 * the operator, so it return the same result as before.
450 * This is add by on 2012/5/29
452 * @param[in] text The current calculator input string
453 * @param[out] begin The start location of an operand
454 * @param[out] end The end location of an operand
455 * @return Is cursor in an operand
456 * @retval true The cursor is in the operand
457 * @retval false The cursor is not in the operand
461 __calculator_get_float_num_in_cursor_position(char *text, int cur_pos,
462 int *begin, int *end)
468 int pos = cur_pos - 1;
475 if ('p' == text[pos] || 'e' == text[pos]) {
479 } else if (CALCULATOR_IS_DIGIT_DOT(text[pos], decimal_ch)) {
480 for (_begin = pos - 1;
481 CALCULATOR_IS_DIGIT_DOT(text[_begin], decimal_ch)
482 && _begin >= 0; --_begin) {
486 if (_begin > 1 && '-' == text[_begin - 1]
487 && '(' == text[_begin - 2]) {
491 CALCULATOR_IS_DIGIT_DOT(text[_end], decimal_ch)
492 && _end < strlen(text); ++_end) {
500 } else if (CALCULATOR_CHAR_IS_OPERATOR(text[pos]) || text[pos] == '(') {
502 CALCULATOR_IS_DIGIT_DOT(text[_end], decimal_ch)
503 && _end < strlen(text); ++_end) {
518 * Get the operand start and end location where the cursor in the operand
519 * Actually, it would call "__calculator_get_float_num_in_cursor_position"
520 * function to recognize whether the cursor is in the operand.
522 * @param[in] entry_text The current calcualtor input string
523 * @param[out] str The operand which the cursor in
524 * @param[out] from The operand start location which contain the cursor
525 * @param[out] end The operand end location which contain the cursor
526 * @return Is cursor in an operand
527 * @retval true The cursor is in the operand
528 * @retval false The cursor is not in the operand
532 __calculator_get_cursor_position_float_string(char *entry_text, char *str,
533 int cur_pos, int *from, int *end)
536 if (entry_text == NULL) {
539 int from_pos = cur_pos;
540 int end_pos = cur_pos;
543 __calculator_get_float_num_in_cursor_position(entry_text, cur_pos,
549 /* set from&end position */
557 strncpy(str, entry_text + from_pos, end_pos - from_pos + 1);
558 str[end_pos - from_pos + 1] = '\0';
565 * Get the float number in current cursor
573 __calculator_get_before_cursor_float_string(char *entry_text, char *str)
577 int from_pos = calculator_cursor_pos;
578 int end_pos = calculator_cursor_pos;
581 __calculator_get_float_num_in_cursor_position(entry_text,
582 calculator_cursor_pos,
587 snprintf(str, calculator_cursor_pos - from_pos + 1, "%s",
588 entry_text + from_pos);
595 * Get string before cursor in the Entry.
603 __calculator_get_input_from_begin_to_cursor(char *entry_text, char *str)
607 if (calculator_cursor_pos > 0) {
608 strncpy(str, entry_text, calculator_cursor_pos);
609 str[calculator_cursor_pos] = '\0';
619 * judge the type of current input
625 static last_char_t __calculator_string_get_char_type( char ch_in)
637 if (CALCULATOR_CHAR_IS_MULTI_DIVIDE_OPERATOR(ch_in)) {
638 return CHAR_IS_MULTIPLY_DIVIDE;
641 return CHAR_IS_LEFT_PARENTHESE;
644 return CHAR_IS_RIGHT_PARENTHESE;
646 if (CALCULATOR_CHAR_IS_DIGITAL(ch_in)) {
647 return CHAR_IS_DIGIT;
649 if (CALCULATOR_CHAR_IS_PLUS_DEDUCT(ch_in) ){
650 return CHAR_IS_PLUS_MINUS;
652 if (ch_in == decimal_ch) {
653 return CHAR_IS_POINT;
655 return CHAR_IS_CHARACTER;
659 static bool __calculator_string_digit_in(const char *input)
662 while(input[i]!='\0'){
663 if(IS_DIGITAL(input[i])){/*here ,digit include "p" and "e"*/
673 * search charactor in input string, if have charactor, return True and index of first charactor;
676 static bool __calculator_string_char_search(const char *input, int *index)
679 int len_cp = strlen(input);
684 for(; i < len_cp ; i++){
685 last_char_t cur_char_type = __calculator_string_get_char_type(input[i]);
686 if (CHAR_IS_CHARACTER == cur_char_type) {
696 * search invalid charactor in input string, if have invalid charactor, return True and index of first invalid charactor;
699 static bool __calculator_string_invalid_char_search(char *input, int *index)
703 bool char_in = FALSE;
705 char_in = __calculator_string_char_search(p, &sub_index);
706 if(!char_in){/*no charactor*/
710 /* charactor present*/
713 if(!__calculator_search_function(p, &len)){/*charactor not a function*/
715 }else{/*the first sevaral charactors are function, continue search*/
732 __calculator_control_panel_number_button_clicked(Evas_Object * entry,
737 /* replace special characters */
738 char entry_text[MAX_EXPRESSION_LENGTH] = { 0 };
739 snprintf(entry_text, sizeof(entry_text), "%s", calculator_input_str);
741 //Current state is calculated, clear all
742 if (calculator_state == CALCULATOR_CALCULATED) {
743 edje_object_signal_emit(_EDJ(ad->edje), "show,input", "");
744 _calc_entry_clear(entry);
745 _calc_entry_text_insert(entry, op_item->op_sym);
746 calculator_state = CALCULATOR_OPERAND_INPUT;
750 char str_buf[MAX_EXPRESSION_LENGTH] = { 0 };
751 char before_cursor[MAX_EXPRESSION_LENGTH] = { 0 };
755 __calculator_get_cursor_position_float_string(entry_text, str_buf,
756 calculator_cursor_pos,
758 __calculator_get_input_from_begin_to_cursor(entry_text, before_cursor);
759 before_len = strlen(before_cursor);
760 calculator_get_digits_number(str_buf, &nDigitCnt, &nPointCnt);
762 char str_bufa[MAX_EXPRESSION_LENGTH] = { 0 };
763 __calculator_get_before_cursor_float_string(entry_text, str_bufa);
764 if (strcmp(str_bufa, "0") == 0) {
765 _calc_entry_backspace(entry);
768 if (strlen(str_buf) >= MAX_NUM_LENGTH) {
769 __calculator_wrong_format_create(CALC_MSG_MAX_DIGIT);
771 } else if (nPointCnt >= MAX_DECIMAL_NUM
772 && calculator_cursor_pos > nDigitCnt) {
773 __calculator_wrong_format_create(CALC_MSG_MAX_DEC_DIGIT);
775 } else if (before_len > 0
776 && (__calculator_string_get_char_type(before_cursor[before_len - 1]) ==
778 || __calculator_string_get_char_type(before_cursor[before_len - 1]) ==
780 /* input digital after "e" or "p", the "x" opeartor will be added automatically */
781 _calc_entry_text_insert(entry, "x");
782 _calc_entry_text_insert(entry, op_item->op_sym);
783 calculator_state = CALCULATOR_OPERAND_INPUT;
785 } else if (before_len > 0
786 && ((before_cursor[before_len - 1] == '(')
788 CALCULATOR_CHAR_IS_DIGITAL(before_cursor[before_len - 1])
789 || CALCULATOR_CHAR_IS_OPERATOR(before_cursor[before_len - 1]) || (int)before_cursor[before_len - 1] > 120)) //* or/
791 _calc_entry_text_insert(entry, op_item->op_sym);
792 calculator_state = CALCULATOR_OPERAND_INPUT;
794 } else if (before_len > 0 && (before_cursor[before_len - 1] == ')')) {
795 __calculator_wrong_format_create(CALC_MSG_OP_FIRST);
798 _calc_entry_text_insert(entry, op_item->op_sym);
799 calculator_state = CALCULATOR_OPERAND_INPUT;
807 * Deal the event when dot clicked on the keyboard
809 * @param[in] entry The input entry
813 static void _calc_btn_dot_clicked(Evas_Object *entry)
819 char str_num[CALCULATOR_CONTENT_LEN] = { 0 };
822 char decimal_str[32] = { 0 };
824 /* replace special characters */
825 char entry_text[MAX_EXPRESSION_LENGTH] = { 0 };
826 strncpy(entry_text, calculator_input_str, MAX_EXPRESSION_LENGTH - 1);
828 if (calculator_state == CALCULATOR_CALCULATED) {
829 _calc_entry_clear(entry);
830 memset(entry_text,0x00,sizeof(entry_text));
835 if (!__calculator_get_cursor_position_float_string
836 (entry_text, str_num, calculator_cursor_pos, &from_pos, &end_pos)) {
837 if (calculator_cursor_pos == 0
838 || IS_OPERATOER(calculator_input_str[from_pos - 1])
839 || calculator_input_str[from_pos - 1] == '(') {
840 snprintf(decimal_str, sizeof(decimal_str), "0%c",
842 _calc_entry_text_insert(entry, decimal_str);
843 calculator_state = CALCULATOR_OPERAND_INPUT;
848 if (strcmp(str_num, "p") == 0 || strcmp(str_num, "e") == 0) {
849 __calculator_wrong_format_create(CALC_MSG_NUM_FIRST);
854 str_num_len = strlen(str_num);
855 if (str_num_len > 0 && str_num[str_num_len - 1] == decimal_ch) {
861 calculator_get_digits_number(str_num, &nDigitCnt, &nPointCnt);
863 if (nDigitCnt >= 15) {
864 __calculator_wrong_format_create(CALC_MSG_MAX_DIGIT);
871 if (IS_OPERATOER(calculator_input_str[calculator_cursor_pos-1])
872 || calculator_input_str[calculator_cursor_pos-1] == '(') {
873 snprintf(decimal_str, sizeof(decimal_str), "0%c", decimal_ch);
875 snprintf(decimal_str, sizeof(decimal_str), "%c", decimal_ch);
877 _calc_entry_text_insert(entry, decimal_str);
878 calculator_state = CALCULATOR_OPERAND_INPUT;
891 static void _calc_btn_backspace_clicked(Evas_Object * entry)
895 if (calculator_state == CALCULATOR_CALCULATED) {
896 calculator_state = CALCULATOR_OPERATOR_INPUT;
897 if (calculator_cursor_pos > strlen(calculator_input_str)) {
898 calculator_cursor_pos = strlen(calculator_input_str); /* set last position */
901 _calc_entry_backspace(entry);
905 static int __calculator_delete_long_press(void *data)
908 Evas_Object *entry = (Evas_Object *) data;
909 _calc_btn_backspace_clicked(entry);
916 * Process +.-.*.\ these four buttons clicked.
924 __calculator_control_normal_func_clicked(Evas_Object * entry,
928 char all_input[MAX_EXPRESSION_LENGTH] = { 0 };
929 strncpy(all_input, calculator_input_str, MAX_EXPRESSION_LENGTH - 1);
931 if (calculator_state == CALCULATOR_CALCULATED) {
932 edje_object_signal_emit(_EDJ(ad->edje), "show,input", "");
933 char temp[20] = { 0 };
935 calc_expr_num_format_result(last_result, temp);
936 _calc_entry_clear(entry);
938 if (temp[0] == '-' || strchr(temp, 'E')) //result < 0 or sicience number
940 _calc_entry_text_insert(entry, "(");
941 _calc_entry_text_insert(entry, temp);
942 _calc_entry_text_insert(entry, ")");
944 _calc_entry_text_insert(entry, temp);
947 _calc_entry_text_insert(entry, op_item->op_sym);
948 calculator_state = CALCULATOR_OPERATOR_INPUT;
952 if(!strcmp(op_item->op_sym, "x")||!strcmp(op_item->op_sym, "/")
953 ||!strcmp(op_item->op_sym, "+")){
954 if(!__calculator_string_digit_in(calculator_input_str)){ return; }
956 int nCntOp = calc_expr_get_operator_num(all_input);
957 if (nCntOp >= MAX_OPERATOR_NUM) { /* Can't exceed 20 operators */
958 __calculator_wrong_format_create(CALC_MSG_MAX_OP);
962 char before_cursor[MAX_EXPRESSION_LENGTH] = { 0 };
965 __calculator_get_input_from_begin_to_cursor(all_input, before_cursor);
966 input_len = strlen(before_cursor);
969 if (before_cursor[input_len - 1] == '('
970 && !strcmp(op_item->op_sym, "-")) {
971 _calc_entry_text_insert(entry, op_item->op_sym);
972 calculator_state = CALCULATOR_OPERATOR_INPUT;
973 } else if (((input_len > 1) && (before_cursor[input_len - 1] == '-') && (before_cursor[input_len - 2] == '(')) //(-
974 || /*before_cursor[input_len - 1] == decimal_ch ||*/ before_cursor[input_len - 1] == '(') // . or (
977 __calculator_wrong_format_create(CALC_MSG_NUM_FIRST);
979 } else if (IS_OPERATOER(before_cursor[input_len - 1])) {
980 if ((input_len > 1 || !strcmp(op_item->op_sym, "-"))
982 _calc_entry_backspace(entry);
983 _calc_entry_text_insert(entry, op_item->op_sym);
984 calculator_state = CALCULATOR_OPERATOR_INPUT;
986 __calculator_wrong_format_create(CALC_MSG_NUM_FIRST);
989 } else if (before_cursor[input_len - 1] == ')') //
991 _calc_entry_text_insert(entry, op_item->op_sym);
992 calculator_state = CALCULATOR_OPERATOR_INPUT;
995 if (!IS_DIGITAL(before_cursor[input_len - 1])
996 && (before_cursor[input_len - 1] != decimal_ch)) {
997 __calculator_wrong_format_create(CALC_MSG_NUM_FIRST);
1000 _calc_entry_text_insert(entry, op_item->op_sym);
1001 calculator_state = CALCULATOR_OPERATOR_INPUT;
1005 } else { /* before_cursor si empty */
1007 _calc_entry_text_insert(entry, op_item->op_sym);
1008 calculator_state = CALCULATOR_OPERATOR_INPUT;
1021 static void __calculator_symbol_negative_clicked(Evas_Object * entry)
1025 char result[MAX_RESULT_LENGTH] = { 0 };
1027 if (calculator_state == CALCULATOR_CALCULATED) {
1028 edje_object_signal_emit(_EDJ(ad->edje), "show,input", "");
1030 calc_expr_num_format_result(last_result, result);
1031 if (last_result < 0) {
1032 string_remove_at(result, 0, 1); //remove '-'
1034 string_insert(result, 0, "(-"); // add (-xxx)
1035 string_insert(result, strlen(result), ")");
1038 _calc_entry_clear(entry);
1039 _calc_entry_text_insert(entry, result);
1041 calculator_state = CALCULATOR_OPERAND_INPUT;
1042 //use_last_result = 1;
1047 int cursor = calculator_cursor_pos;
1048 int begin = 0, length = 0;
1049 char expr[MAX_EXPRESSION_LENGTH] = { 0 };
1050 strncpy(expr, calculator_input_str, MAX_EXPRESSION_LENGTH - 1);
1053 if (expr[cursor] == ')') {
1055 flag = 1; /* before current cursor is ')' */
1059 calc_expr_get_current_num_at_cursor(expr, cursor, &begin,
1061 if (expr[begin] == '-') {
1062 if (begin > 0 && expr[begin - 1] == '('
1063 && expr[begin + length] == ')') {
1064 string_remove_at(expr, begin + length, 1); //remove ')'
1065 string_remove_at(expr, begin - 1, 2); // remove '(-'
1066 calculator_cursor_pos -= flag ? 3 : 2;
1068 string_remove_at(expr, begin, 1);
1069 calculator_cursor_pos -= 1;
1073 if (flag == 1) //not '(-xxx)' but has ')'
1075 __calculator_wrong_format_create(CALC_MSG_NUM_FIRST);
1078 string_insert(expr, begin + length, ")");
1079 string_insert(expr, begin, "(-");
1080 calculator_cursor_pos +=
1081 (((begin + length) ==
1082 calculator_cursor_pos) ? 3 : 2);
1085 strncpy(calculator_input_str, expr, MAX_EXPRESSION_LENGTH - 1);
1087 _calc_entry_text_set(entry, calculator_input_str);
1088 _calc_entry_cursor_set(entry);
1090 calculator_state = CALCULATOR_OPERAND_INPUT;
1093 __calculator_wrong_format_create(CALC_MSG_NUM_FIRST);
1098 /* search the previous operator and value */
1099 static char * __calculator_search_prev_input(char *input_str)
1103 int bracket_number = 0;
1104 char *prev_input = NULL;
1105 for(; i< strlen(input_str); i++) {
1106 if ('(' ==(input_str[i]) ){
1109 if( ')' == input_str[i]){
1112 if (CALCULATOR_CHAR_IS_PLUS_DEDUCT(input_str[i])
1113 || CALCULATOR_CHAR_IS_MULTI_DIVIDE_OPERATOR(input_str[i])) {
1114 if ( !bracket_number){
1115 prev_input = &input_str[i];
1126 * Deal the event when "=" clicked on the keyboard
1128 * @param[in] entry The input entry
1132 static void __calculator_op_equal(Evas_Object *entry)
1135 if (entry == NULL) {
1138 if (calculator_state == CALCULATOR_CALCULATED) {
1139 /*duplicate previous input operator and value*/
1140 char *p = __calculator_search_prev_input(calculator_input_str);
1144 char prev_input[32] = { 0 };
1145 int len = g_strlcpy(prev_input, p, sizeof(prev_input));
1146 if (len >= sizeof(prev_input)) {
1149 char temp[32] = { 0 };
1150 calc_expr_num_format_result(last_result, temp);
1151 _calc_entry_clear(entry);
1153 if (temp[0] == '-' || strchr(temp, 'E')) {
1154 _calc_entry_text_insert(entry, "(");
1155 _calc_entry_text_insert(entry, temp);
1156 _calc_entry_text_insert(entry, ")");
1158 _calc_entry_text_insert(entry, temp);
1160 _calc_entry_text_insert(entry, prev_input);
1161 calculator_state = CALCULATOR_OPERATOR_INPUT;
1165 char str_buf[MAX_EXPRESSION_LENGTH] = { 0 };
1166 char result_buf[MAX_RESULT_LENGTH] = { 0 };
1167 char result_format[MAX_RESULT_LENGTH] = { 0 };
1169 char error_msg[MAX_ERROR_MESSAGE_LENGTH] = { 0 };
1170 calc_expr_close_parentheses(calculator_input_str);
1171 _calc_entry_text_set(entry, calculator_input_str);
1172 snprintf(str_buf, sizeof(str_buf), "%s", calculator_input_str);
1173 str_len = strlen(str_buf);
1175 __calculator_wrong_format_create(CALC_MSG_NUM_FIRST);
1179 if (!calculator_calculate(str_buf, &result, error_msg)) {
1180 __calculator_wrong_format_create(error_msg);
1181 calculator_state = CALCULATOR_ERROR_OCCURED;
1184 last_result = result;
1185 memset(result_buf, 0, CALCULATOR_CONTENT_LEN + 1);
1186 calc_expr_num_format_result(result, result_buf);
1189 struct history_item item;
1190 memset(item.expression, 0, sizeof(item.expression));
1191 memset(result_format, 0, sizeof(result_format));
1192 calc_expr_format_expression(calculator_input_str,
1194 item.result = result;
1195 calc_expr_format_expression(result_buf, result_format);
1196 if (result_buf[0] == '-') {
1197 string_replace(result_format, "\xe2\x88\x92", "-");
1200 calc_view_save_history(item);
1203 calculator_state = CALCULATOR_CALCULATED;
1204 calc_view_show_result(result_format, ad);
1218 static void __calculator_parenthesis_clicked(Evas_Object * entry)
1221 char all_input[MAX_EXPRESSION_LENGTH] = { 0 };
1222 snprintf(all_input, sizeof(all_input), "%s", calculator_input_str);
1223 if (calculator_state == CALCULATOR_CALCULATED) {
1224 edje_object_signal_emit(_EDJ(ad->edje), "show,input", "");
1226 char temp[MAX_RESULT_LENGTH] = { 0 };
1228 calc_expr_num_format_result(last_result, temp);
1229 _calc_entry_clear(entry);
1231 if (temp[0] == '-' || strchr(temp, 'E') != NULL) //result < 0 or science number
1233 _calc_entry_text_insert(entry, "((");
1234 _calc_entry_text_insert(entry, temp);
1235 _calc_entry_text_insert(entry, ")");
1237 _calc_entry_text_insert(entry, "(");
1238 _calc_entry_text_insert(entry, temp);
1240 calculator_state = CALCULATOR_OPERATOR_INPUT;
1243 char before_cursor[MAX_EXPRESSION_LENGTH] = { 0 };
1245 __calculator_get_input_from_begin_to_cursor(all_input, before_cursor);
1246 input_len = strlen(before_cursor);
1248 if (input_len == 0) {
1249 _calc_entry_text_insert(entry, "(");
1250 calculator_state = CALCULATOR_OPERATOR_INPUT;
1253 int bracket_num = calculator_get_open_braket(all_input);
1254 if (input_len > 0) {
1255 if (before_cursor[input_len - 1] == decimal_ch) {
1256 __calculator_wrong_format_create(CALC_MSG_NUM_FIRST);
1258 } else if (bracket_num > 0 //'(' is more than ')'
1259 && before_cursor[input_len - 1] != '('
1260 && (before_cursor[input_len - 1] == ')'
1261 || isdigit(before_cursor[input_len - 1])
1263 (__calculator_string_get_char_type
1264 (before_cursor[input_len - 1]) == CHAR_IS_PI
1266 __calculator_string_get_char_type
1267 (before_cursor[input_len - 1]) == CHAR_IS_E))) {
1268 _calc_entry_text_insert(entry, ")");
1270 } else if (bracket_num == 0) {
1271 if (calc_expr_get_left_parentheses_num
1272 (calculator_input_str) < MAX_PARENTHESES_NUM) {
1273 _calc_entry_text_insert(entry, "(");
1276 } else if (before_cursor[input_len - 1] != ')') //'(' is less than ')'!isdigit(before_cursor[input_len-1])&&(
1278 if (calc_expr_get_left_parentheses_num
1279 (calculator_input_str) < MAX_PARENTHESES_NUM) {
1280 _calc_entry_text_insert(entry, "(");
1299 __calculator_control_functions_button_clicked(Evas_Object * entry,
1300 op_item_t * op_item)
1305 function_t function = { 0 };
1307 memset(&function, 0x0, sizeof(function_t));
1308 str = op_item->op_name;
1310 char all_input[MAX_EXPRESSION_LENGTH] = { 0 };
1312 char before_cursor[MAX_EXPRESSION_LENGTH] = { 0 };
1314 last_char_t last_char_type = 0;
1316 snprintf(all_input, sizeof(all_input), "%s", calculator_input_str);
1317 __calculator_get_input_from_begin_to_cursor(all_input, before_cursor);
1318 input_len = strlen(all_input);
1319 before_len = strlen(before_cursor);
1321 last_char_type = __calculator_string_get_char_type(before_cursor[before_len - 1]);
1324 switch (op_item->op_id) {
1326 /* if it is calculated state */
1327 if (calculator_state == CALCULATOR_CALCULATED) {
1328 edje_object_signal_emit(_EDJ(ad->edje), "show,input",
1331 char temp[CALCULATOR_CONTENT_LEN] = { 0 };
1332 double per_result = last_result / 100.0;
1334 calc_expr_num_format_result(per_result, temp);
1335 _calc_entry_clear(entry);
1337 if (strcmp(temp, "0") == 0) {
1338 _calc_entry_text_insert(entry, "0");
1339 } else if (temp[0] == '-') //result < 0
1341 _calc_entry_text_insert(entry, "(");
1342 _calc_entry_text_insert(entry, temp);
1343 _calc_entry_text_insert(entry, ")");
1345 _calc_entry_text_insert(entry, temp);
1347 calculator_state = CALCULATOR_OPERAND_INPUT;
1352 int from_pos, end_pos;
1353 char str_num[CALCULATOR_CONTENT_LEN] = { 0 };
1354 char temp[CALCULATOR_CONTENT_LEN] = { 0 };
1355 double per_result = 0.0;
1358 __calculator_get_cursor_position_float_string
1359 (all_input, str_num, calculator_cursor_pos,
1360 &from_pos, &end_pos)) {
1361 __calculator_wrong_format_create(CALC_MSG_NUM_FIRST);
1366 if (strlen(str_num) == 0) {
1367 __calculator_wrong_format_create(CALC_MSG_NUM_FIRST);
1371 if (strcmp(str_num, "0") == 0) {
1375 per_result = atof(str_num);
1376 per_result /= 100.0;
1378 calc_expr_num_format_result(per_result, temp);
1380 _calc_entry_text_remove(entry, from_pos,
1382 _calc_entry_text_insert(entry, temp);
1384 calculator_state = CALCULATOR_OPERAND_INPUT;
1390 if (calculator_state == CALCULATOR_CALCULATED) {
1391 edje_object_signal_emit(_EDJ(ad->edje), "show,input",
1393 _calc_entry_clear(entry);
1394 _calc_entry_text_insert(entry, op_item->op_name);
1397 if ((before_len != 0) && (!IS_DIGITAL(before_cursor[before_len - 1]))
1398 && (!IS_OPERATOER(before_cursor[before_len - 1]))
1399 && (before_cursor[before_len - 1] != '(')
1400 && (before_cursor[before_len - 1] != 'P')
1401 && before_cursor[before_len - 1] != 'C') {
1402 __calculator_wrong_format_create(CALC_MSG_OP_FIRST);
1405 /* input digital after "p", the "x" opeartor will be added automatically */
1406 if(IS_DIGITAL(before_cursor[before_len - 1])){
1407 _calc_entry_text_insert(entry, "x");
1409 _calc_entry_text_insert(entry, op_item->op_name);
1413 if (calculator_state == CALCULATOR_CALCULATED) {
1414 edje_object_signal_emit(_EDJ(ad->edje), "show,input",
1416 _calc_entry_clear(entry);
1417 _calc_entry_text_insert(entry, op_item->op_name);
1420 if ((before_len != 0) && (!IS_DIGITAL(before_cursor[before_len - 1]))
1421 && (!IS_OPERATOER(before_cursor[before_len - 1]))
1422 && (before_cursor[before_len - 1] != '(')
1423 && (before_cursor[before_len - 1] != 'P')
1424 && before_cursor[before_len - 1] != 'C') {
1425 __calculator_wrong_format_create(CALC_MSG_OP_FIRST);
1428 /* input digital after "e", the "x" opeartor will be added automatically */
1429 if(IS_DIGITAL(before_cursor[before_len - 1])){
1430 _calc_entry_text_insert(entry, "x");
1432 _calc_entry_text_insert(entry, op_item->op_name);
1435 case OP_SIN: //sin()
1436 case OP_COS: //cos()
1437 case OP_TAN: //tan()
1438 case OP_LOG: //log()
1439 case OP_ABS: //abs()
1440 if (calculator_state == CALCULATOR_CALCULATED) {
1441 edje_object_signal_emit(_EDJ(ad->edje), "show,input",
1444 _calc_entry_clear(entry);
1445 _calc_entry_text_insert(entry, op_item->op_name);
1448 if (last_char_type == CHAR_IS_PI || last_char_type == CHAR_IS_E) {
1449 __calculator_wrong_format_create(CALC_MSG_OP_FIRST);
1453 _calc_entry_text_insert(entry, op_item->op_name);
1457 if (calculator_state == CALCULATOR_CALCULATED) {
1458 edje_object_signal_emit(_EDJ(ad->edje), "show,input",
1460 _calc_entry_clear(entry);
1461 _calc_entry_text_insert(entry, op_item->op_name);
1464 if (last_char_type == CHAR_IS_PI) {
1465 __calculator_wrong_format_create(CALC_MSG_OP_FIRST);
1468 if ((before_len != 0) && (before_cursor[before_len - 1] != '+')
1469 && (before_cursor[before_len - 1] != '-')
1470 && (last_char_type != CHAR_IS_MULTIPLY_DIVIDE)
1471 && (before_cursor[before_len - 1] != '^')
1472 && (before_cursor[before_len - 1] != '(')
1473 && (before_cursor[before_len - 1] != 'C')
1474 && (before_cursor[before_len - 1] != 'P')) {
1475 __calculator_wrong_format_create(CALC_MSG_OP_FIRST);
1478 _calc_entry_text_insert(entry, op_item->op_name);
1481 case OP_ROOT: //sqrt()
1482 if (calculator_state == CALCULATOR_CALCULATED) {
1483 edje_object_signal_emit(_EDJ(ad->edje), "show,input",
1486 _calc_entry_clear(entry);
1487 _calc_entry_text_insert(entry, op_item->op_name);
1490 if (last_char_type == CHAR_IS_PI) {
1491 __calculator_wrong_format_create(CALC_MSG_OP_FIRST);
1494 if ((before_len != 0) && (before_cursor[before_len - 1] != '+')
1495 && (before_cursor[before_len - 1] != '-')
1496 && (last_char_type != CHAR_IS_MULTIPLY_DIVIDE)
1497 && (before_cursor[before_len - 1] != '^')
1498 && (before_cursor[before_len - 1] != '(')
1499 && (before_cursor[before_len - 1] != 'C')
1500 && (before_cursor[before_len - 1] != 'P')) {
1501 __calculator_wrong_format_create(CALC_MSG_OP_FIRST);
1504 _calc_entry_text_insert(entry, op_item->op_name);
1508 if (calculator_state == CALCULATOR_CALCULATED) {
1509 edje_object_signal_emit(_EDJ(ad->edje), "show,input",
1511 _calc_entry_clear(entry);
1512 _calc_entry_text_insert(entry, op_item->op_name);
1515 if (last_char_type == CHAR_IS_PI) {
1516 __calculator_wrong_format_create(CALC_MSG_OP_FIRST);
1519 if ((before_len != 0) && (before_cursor[before_len - 1] != '+')
1520 && (before_cursor[before_len - 1] != '-')
1521 && (last_char_type != CHAR_IS_MULTIPLY_DIVIDE)
1522 && (before_cursor[before_len - 1] != '^')
1523 && (before_cursor[before_len - 1] != '(')
1524 && (before_cursor[before_len - 1] != 'C')
1525 && (before_cursor[before_len - 1] != 'P')) {
1526 __calculator_wrong_format_create(CALC_MSG_OP_FIRST);
1529 _calc_entry_text_insert(entry, op_item->op_name);
1533 if (calculator_state == CALCULATOR_CALCULATED) {
1534 edje_object_signal_emit(_EDJ(ad->edje), "show,input",
1537 char temp[CALCULATOR_CONTENT_LEN] = { 0 };
1538 calc_expr_num_format_result(last_result, temp);
1539 _calc_entry_clear(entry);
1541 if (temp[0] == '-' || strchr(temp, 'E')) //result < 0 or science number
1543 _calc_entry_text_insert(entry, "(");
1544 _calc_entry_text_insert(entry, temp);
1545 _calc_entry_text_insert(entry, ")");
1547 _calc_entry_text_insert(entry, temp);
1549 _calc_entry_text_insert(entry, op_item->op_name);
1550 calculator_state = CALCULATOR_OPERAND_INPUT;
1551 //use_last_result = 1;
1555 if (input_len == 0) {
1556 __calculator_wrong_format_create(CALC_MSG_NUM_FIRST_X2);
1559 if (last_char_type == CHAR_IS_PI) {
1560 _calc_entry_text_insert(entry, op_item->op_name);
1561 calculator_state = CALCULATOR_OPERAND_INPUT;
1563 } else if ((before_len > 0)
1564 && (!isdigit(before_cursor[before_len - 1]))
1565 && (before_cursor[before_len - 1] != ')')) {
1566 __calculator_wrong_format_create(CALC_MSG_NUM_FIRST_X2);
1569 _calc_entry_text_insert(entry, op_item->op_name);
1570 calculator_state = CALCULATOR_OPERAND_INPUT;
1573 if (calculator_state == CALCULATOR_CALCULATED) {
1574 edje_object_signal_emit(_EDJ(ad->edje), "show,input",
1577 char temp[CALCULATOR_CONTENT_LEN] = { 0 };
1579 calc_expr_num_format_result(last_result, temp);
1580 _calc_entry_clear(entry);
1582 if (temp[0] == '-' || strchr(temp, 'E')) //result < 0 or science number
1584 _calc_entry_text_insert(entry, "(");
1585 _calc_entry_text_insert(entry, temp);
1586 _calc_entry_text_insert(entry, ")");
1588 _calc_entry_text_insert(entry, temp);
1590 _calc_entry_text_insert(entry, op_item->op_name);
1591 calculator_state = CALCULATOR_OPERATOR_INPUT;
1595 if (input_len == 0) {
1596 __calculator_wrong_format_create(CALC_MSG_NUM_FIRST_XY);
1599 if ((last_char_type == CHAR_IS_PI)
1600 || (last_char_type == CHAR_IS_E)) {
1601 _calc_entry_text_insert(entry, op_item->op_name);
1602 calculator_state = CALCULATOR_OPERATOR_INPUT;
1604 } else if ((before_len > 0)
1605 && !isdigit(before_cursor[before_len - 1])
1606 && (before_cursor[before_len - 1] != ')')) {
1607 __calculator_wrong_format_create(CALC_MSG_NUM_FIRST_XY);
1610 _calc_entry_text_insert(entry, op_item->op_name);
1611 calculator_state = CALCULATOR_OPERATOR_INPUT;
1615 if (calculator_state == CALCULATOR_CALCULATED) {
1616 edje_object_signal_emit(_EDJ(ad->edje), "show,input",
1619 char temp[MAX_RESULT_LENGTH] = { 0 };
1621 calc_expr_num_format_result(last_result, temp);
1623 if (strchr(temp, decimal_ch) != NULL || strchr(temp, '-') != NULL) //revise by bfl
1625 __calculator_wrong_format_create(CALC_MSG_INVALID_FAC);
1626 calculator_state = CALCULATOR_WAITING_INPUT; //revise by bfl
1630 _calc_entry_clear(entry);
1631 _calc_entry_text_insert(entry, "(");
1632 _calc_entry_text_insert(entry, temp);
1633 _calc_entry_text_insert(entry, "!)");
1635 calculator_state = CALCULATOR_OPERATOR_INPUT;
1639 if (input_len == 0) {
1640 __calculator_wrong_format_create(CALC_MSG_NUM_FIRST_FAC);
1643 if ((last_char_type == CHAR_IS_PI)
1644 || (last_char_type == CHAR_IS_E)) {
1645 __calculator_wrong_format_create(CALC_MSG_INVALID_FAC);
1649 /* check if it is natural */
1651 char str_buf[MAX_EXPRESSION_LENGTH] = { 0 };
1652 int from_pos = 0, end_pos = 0;
1655 __calculator_get_cursor_position_float_string
1656 (all_input, str_buf, calculator_cursor_pos,
1657 &from_pos, &end_pos)) {
1658 __calculator_wrong_format_create(CALC_MSG_NUM_FIRST);
1662 if (strchr(str_buf, decimal_ch) != NULL
1663 || str_buf[0] == '-') {
1664 __calculator_wrong_format_create(CALC_MSG_INVALID_FAC);
1668 _calc_entry_text_remove(entry, from_pos, end_pos);
1669 _calc_entry_text_insert(entry, "(");
1670 _calc_entry_text_insert(entry, str_buf);
1671 _calc_entry_text_insert(entry, "!)");
1672 calculator_state = CALCULATOR_OPERATOR_INPUT;
1676 if (calculator_state == CALCULATOR_CALCULATED) {
1677 edje_object_signal_emit(_EDJ(ad->edje), "show,input",
1680 char temp[MAX_RESULT_LENGTH] = { 0 };
1683 calc_expr_num_format_result(last_result, temp);
1684 if (strchr(temp, 'E') != NULL) //science number
1686 temp[strlen(temp)] = ')';
1687 for (i = strlen(temp); i > 0; --i) {
1688 temp[i] = temp[i - 1];
1693 _calc_entry_clear(entry);
1694 if (temp[0] == '-') {
1695 _calc_entry_text_insert(entry, "(-1");
1696 _calc_entry_text_insert(entry, "/");
1698 _calc_entry_text_insert(entry, &temp[1]);
1699 _calc_entry_text_insert(entry, ")");
1701 _calc_entry_text_insert(entry, "(1");
1702 _calc_entry_text_insert(entry, "/");
1704 _calc_entry_text_insert(entry, temp);
1705 _calc_entry_text_insert(entry, ")");
1708 calculator_state = CALCULATOR_OPERATOR_INPUT;
1709 //use_last_result = 1;
1712 if (input_len == 0) {
1713 __calculator_wrong_format_create(CALC_MSG_NUM_FIRST_RECIP);
1717 /* check if it is digit */
1719 char str_buf[MAX_EXPRESSION_LENGTH] = { 0 };
1720 int from_pos = 0, end_pos = 0;
1723 __calculator_get_cursor_position_float_string
1724 (all_input, str_buf, calculator_cursor_pos,
1725 &from_pos, &end_pos)) {
1726 __calculator_wrong_format_create(CALC_MSG_NUM_FIRST_RECIP);
1730 if (strcmp(str_buf, "p") && strcmp(str_buf, "e")
1731 && atof(str_buf) == 0) {
1732 __calculator_wrong_format_create(CALC_MSG_DIVIDE_BY_ZERO);
1736 _calc_entry_text_remove(entry, from_pos, end_pos);
1737 if (str_buf[0] == '-') {
1738 _calc_entry_text_insert(entry, "(-1");
1739 _calc_entry_text_insert(entry, "/");
1741 _calc_entry_text_insert(entry, &str_buf[1]);
1742 _calc_entry_text_insert(entry, ")");
1744 _calc_entry_text_insert(entry, "(1");
1745 _calc_entry_text_insert(entry, "/");
1747 _calc_entry_text_insert(entry, str_buf);
1748 _calc_entry_text_insert(entry, ")");
1751 calculator_state = CALCULATOR_OPERATOR_INPUT;
1758 calculator_state = CALCULATOR_SPECIAL_FUNCTION_INPUT;
1763 /////////////////////////// input text finish ////////////////////////////
1774 static int _calculator_get_input_item(Evas_Object * evas_obj, Evas_Object * obj)
1779 if (evas_obj == edje_object_part_object_get(obj, "item_brack")) {
1780 val = OP_PARENTHESIS;
1781 } else if (evas_obj == edje_object_part_object_get(obj, "item_del")) {
1783 } else if (evas_obj == edje_object_part_object_get(obj, "item_c")) {
1785 } else if (evas_obj == edje_object_part_object_get(obj, "item_div")) {
1787 } else if (evas_obj == edje_object_part_object_get(obj, "item_num7")) {
1789 } else if (evas_obj == edje_object_part_object_get(obj, "item_num8")) {
1791 } else if (evas_obj == edje_object_part_object_get(obj, "item_num9")) {
1793 } else if (evas_obj == edje_object_part_object_get(obj, "item_mul")) {
1795 } else if (evas_obj == edje_object_part_object_get(obj, "item_num4")) {
1797 } else if (evas_obj == edje_object_part_object_get(obj, "item_num5")) {
1799 } else if (evas_obj == edje_object_part_object_get(obj, "item_num6")) {
1801 } else if (evas_obj == edje_object_part_object_get(obj, "item_sub")) {
1803 } else if (evas_obj == edje_object_part_object_get(obj, "item_num1")) {
1805 } else if (evas_obj == edje_object_part_object_get(obj, "item_num2")) {
1807 } else if (evas_obj == edje_object_part_object_get(obj, "item_num3")) {
1809 } else if (evas_obj == edje_object_part_object_get(obj, "item_plus")) {
1811 } else if (evas_obj == edje_object_part_object_get(obj, "item_dot")) {
1813 } else if (evas_obj == edje_object_part_object_get(obj, "item_num0")) {
1815 } else if (evas_obj == edje_object_part_object_get(obj, "item_neg")) {
1816 val = OP_PLUS_MINUS;
1817 } else if (evas_obj == edje_object_part_object_get(obj, "item_eq")) {
1819 } else if (evas_obj == edje_object_part_object_get(obj, "item_per")) {
1821 } else if (evas_obj == edje_object_part_object_get(obj, "item_sqr")) {
1823 } else if (evas_obj == edje_object_part_object_get(obj, "item_fac")) {
1825 } else if (evas_obj == edje_object_part_object_get(obj, "item_sin")) {
1827 } else if (evas_obj == edje_object_part_object_get(obj, "item_cos")) {
1829 } else if (evas_obj == edje_object_part_object_get(obj, "item_tan")) {
1831 } else if (evas_obj == edje_object_part_object_get(obj, "item_ln")) {
1833 } else if (evas_obj == edje_object_part_object_get(obj, "item_log")) {
1835 } else if (evas_obj == edje_object_part_object_get(obj, "item_1x")) {
1837 } else if (evas_obj == edje_object_part_object_get(obj, "item_10x")) {
1839 } else if (evas_obj == edje_object_part_object_get(obj, "item_x2")) {
1841 } else if (evas_obj == edje_object_part_object_get(obj, "item_xy")) {
1843 } else if (evas_obj == edje_object_part_object_get(obj, "item_abs")) {
1845 } else if (evas_obj == edje_object_part_object_get(obj, "item_pi")) {
1847 } else if (evas_obj == edje_object_part_object_get(obj, "item_e")) {
1854 /////////////////////////// input text finish ////////////////////////////
1866 static int _calculator_get_input_item_hd(const char *keyname, Evas_Object * obj)
1870 if (0 == strcmp(keyname, "KP_7")) {
1872 } else if (0 == strcmp(keyname, "KP_8")) {
1874 } else if (0 == strcmp(keyname, "KP_9")) {
1876 } else if (0 == strcmp(keyname, "KP_4")) {
1878 } else if (0 == strcmp(keyname, "KP_5")) {
1880 } else if (0 == strcmp(keyname, "KP_6")) {
1882 } else if (0 == strcmp(keyname, "KP_1")) {
1884 } else if (0 == strcmp(keyname, "KP_2")) {
1886 } else if (0 == strcmp(keyname, "KP_3")) {
1888 } else if (0 == strcmp(keyname, "KP_0")) {
1890 }else if (0 == strcmp(keyname, "KP_Decimal")) {
1892 } else if (0 == strcmp(keyname, "Return")) {
1894 } else if (0 == strcmp(keyname, "KP_Add")) {
1896 } else if (0 == strcmp(keyname, "KP_Subtract")) {
1898 } else if (0 == strcmp(keyname, "minus")) {
1900 } else if (0 == strcmp(keyname, "KP_Multiply")) {
1902 } else if (0 == strcmp(keyname, "slash")) {
1904 } else if (0 == strcmp(keyname, "KP_Divide")) {
1906 }else if (0 == strcmp(keyname, "BackSpace")) {
1916 * Interpret all of our different signals, and do things !
1926 _calculator_interp(void *data, Evas * e, Evas_Object * evas_obj,
1933 Evas_Object *obj = (Evas_Object *) data;
1934 val = _calculator_get_input_item(evas_obj, obj);
1935 if (ad->wrong_timer) {
1936 ecore_timer_del(ad->wrong_timer);
1937 ad->wrong_timer = NULL;
1941 _calc_btn_backspace_clicked(ad->input_entry);
1942 if (ad->calc_timer) {
1943 ecore_timer_del(ad->calc_timer);
1944 ad->calc_timer = NULL;
1947 ecore_timer_add(0.1,
1949 __calculator_delete_long_press,
1953 edje_object_signal_emit(_EDJ(ad->edje), "show,input",
1955 _calc_entry_clear(ad->input_entry);
1956 calculator_state = CALCULATOR_WAITING_INPUT;
1962 __calculator_control_normal_func_clicked(ad->
1968 _calc_btn_dot_clicked(ad->input_entry);
1970 case OP_PARENTHESIS:
1971 __calculator_parenthesis_clicked(ad->input_entry);
1974 __calculator_op_equal(ad->input_entry);
1986 __calculator_control_panel_number_button_clicked(ad->
1992 __calculator_symbol_negative_clicked(ad->input_entry);
1994 case OP_PERCENT...OP_E:
1995 __calculator_control_functions_button_clicked(ad->
2003 if (ad->svi_handle) {
2004 svi_play_sound(ad->svi_handle, SVI_SND_TOUCH_SIP);
2005 svi_play_vib(ad->svi_handle, SVI_VIB_TOUCH_SIP);
2012 static void __calculator_wrong_format_delete(Evas_Object *in_entry)
2014 _calc_entry_text_set(in_entry, calculator_input_str);
2015 if (ad->wrong_timer) {
2016 ecore_timer_del(ad->wrong_timer);
2017 ad->wrong_timer = NULL;
2021 static void __calculator_wrong_text_set(char * wrong_string)
2023 char buf[MAX_EXPRESSION_LENGTH] = { 0 };
2024 memset(buf, 0, sizeof(buf));
2025 snprintf(buf, sizeof(buf),
2026 "<align=right><+ font_size=%d><color=#855B11FF>%s",
2027 cur_fontsize, wrong_string);
2028 elm_entry_entry_set(ad->input_entry, buf);
2029 elm_entry_cursor_end_set(ad->input_entry);
2030 elm_object_focus_set(ad->input_entry, EINA_TRUE);
2031 calc_view_revise_input_scroller(ad);
2042 static void __calculator_wrong_format_create(char * wrong_string)
2044 __calculator_wrong_text_set(wrong_string);
2045 if (ad->wrong_timer) {
2046 ecore_timer_del(ad->wrong_timer);
2047 ad->wrong_timer = NULL;
2052 __calculator_wrong_format_delete,
2056 /* mouse up for delete button. */
2058 __calculator_delelte_up(void *data, Evas * e, Evas_Object * evas_obj,
2062 if (ad->calc_timer) {
2063 ecore_timer_del(ad->calc_timer);
2064 ad->calc_timer = NULL;
2071 * Register clicked callback of the keys on the keypad.
2073 * @param keypad the keypad
2076 void _calc_view_keypad_cb_register(Evas_Object * keypad)
2079 char *key_name[] = {
2080 "item_per", "item_sqr", "item_fac", "item_c", "item_div",
2081 "item_mul", "item_del",
2082 "item_sin", "item_cos", "item_tan", "item_num7", "item_num8",
2083 "item_num9", "item_sub",
2084 "item_ln", "item_log", "item_1x", "item_num4", "item_num5",
2085 "item_num6", "item_plus",
2086 "item_10x", "item_x2", "item_xy", "item_num1", "item_num2",
2087 "item_num3", "item_brack",
2088 "item_abs", "item_pi", "item_e", "item_num0", "item_dot",
2089 "item_neg", "item_eq",
2092 Evas_Object *item = NULL;
2093 int key_num = sizeof(key_name) / sizeof(key_name[0]);
2096 for (i = 0; i < key_num; ++i) {
2098 (Evas_Object *) edje_object_part_object_get(keypad,
2101 evas_object_event_callback_add(item,
2102 EVAS_CALLBACK_MOUSE_DOWN,
2105 if (0 == strcmp(key_name[i], "item_del")) {
2106 evas_object_event_callback_add(item,
2107 EVAS_CALLBACK_MOUSE_UP,
2108 __calculator_delelte_up,
2119 * The callback of input entry when mouse up.
2121 * @param data unused
2123 * @param entry the input entry
2124 * @param event_info unused
2128 _calc_view_input_entry_mouseup_cb(void *data, Evas * e, Evas_Object * entry,
2131 calculator_cursor_pos = calc_view_cursor_get_position(entry); //for softkey input and mouse move
2135 _calc_view_input_entry_to_str(char *entry_str, char *internal_str, int buf_size)
2138 strncpy(internal_str, entry_str, buf_size - 1);
2139 /* remove result that behind '='(include '=') */
2140 char *enter = strchr(internal_str, '=');
2141 if (enter != NULL) {
2145 calc_expr_replace_from_special_char(internal_str);
2146 /* remove all ',' and '\n'*/
2149 while (internal_str[j] != '\0'){
2151 if (internal_str[j] == separator_ch || internal_str[j] == '\n'){
2154 internal_str[i++] = internal_str[j++];
2157 internal_str[i] = '\0';
2163 _calc_view_input_entry_keyup_cb(void *data, Evas * e, Evas_Object * entry,
2167 calculator_cursor_pos = calc_view_cursor_get_position(entry); //for hardkey input
2170 Evas_Object *obj = (Evas_Object *) data;
2171 Evas_Event_Key_Up *evt = (Evas_Event_Key_Up *) event_info;
2172 if (0 == strcmp(evt->key, "Return")) {
2173 //calc_expr_input_backspace(calculator_input_str, &calculator_cursor_pos);
2174 __calculator_op_equal(entry);
2177 val = _calculator_get_input_item_hd(evt->key, obj);
2183 __calculator_control_normal_func_clicked(ad->input_entry, &calc_op_item[val]);
2186 _calc_btn_dot_clicked(ad->input_entry);
2198 __calculator_control_panel_number_button_clicked(ad-> input_entry, &calc_op_item[val]);
2201 calc_expr_input_backspace(calculator_input_str, &calculator_cursor_pos);
2212 _calc_view_input_entry_error_include(char *string)
2215 for(; i < ARRAY_SIZE(error_string); i++)
2217 if(!strcmp(string, _(error_string[i]))){
2226 * The callback of input entry when text changed
2228 * @param[in] data the appdata
2229 * @param[in] obj the input entry
2230 * @param[in] event_info unused
2234 _calc_view_input_entry_changed_cb(void *data, Evas_Object *obj,
2238 if (data == NULL || obj == NULL) {
2241 struct appdata *ad = (struct appdata *)data;
2242 const char *str = (char *)elm_entry_entry_get(obj);
2245 char *entry_tmp = elm_entry_markup_to_utf8(str);
2246 char *entry_expr= elm_entry_markup_to_utf8(entry_tmp);/*because the string format from clipboard is not correct*/
2247 char internal_expr[MAX_EXPRESSION_LENGTH] = { 0 };
2248 char f_number_buf[NUMBER_LENGTH] = { 0 };
2249 char s_number_buf[NUMBER_LENGTH] = { 0 };
2251 _calc_view_input_entry_to_str(entry_expr, internal_expr,
2252 MAX_EXPRESSION_LENGTH);
2254 bool char_in =__calculator_string_invalid_char_search(internal_expr, &index);
2255 __calculator_get_cursor_position_float_string(internal_expr,
2257 calculator_cursor_pos,
2259 int cur_pos = calc_view_cursor_get_position(ad->input_entry);
2260 __calculator_get_cursor_position_float_string(internal_expr,
2264 int nCntOp = calc_expr_get_operator_num(internal_expr);
2266 if ((strlen(f_number_buf) > MAX_NUM_LENGTH)
2267 || (strlen(s_number_buf) > MAX_NUM_LENGTH)) {
2268 __calculator_wrong_format_create(CALC_MSG_MAX_DIGIT);
2269 } else if (nCntOp >= MAX_OPERATOR_NUM) {
2270 __calculator_wrong_format_create(CALC_MSG_MAX_OP);
2273 strncpy(calculator_input_str, internal_expr,
2275 calculator_cursor_pos = index;
2277 strncpy(calculator_input_str, internal_expr,
2278 sizeof(calculator_input_str) - 1);
2279 calculator_cursor_pos = cur_pos;
2281 _calc_entry_text_set(ad->input_entry, calculator_input_str);
2293 char *entry_expr_s = elm_entry_markup_to_utf8(str);
2294 char internal_expr_s[MAX_EXPRESSION_LENGTH] = { 0 };
2295 _calc_view_input_entry_to_str(entry_expr_s, internal_expr_s,
2296 MAX_EXPRESSION_LENGTH);
2297 if(!_calc_view_input_entry_error_include(internal_expr_s)){
2298 /*change calculator_input_str, after cut operation*/
2299 strncpy(calculator_input_str, internal_expr_s,
2300 MAX_EXPRESSION_LENGTH - 1);
2304 entry_expr_s = NULL;
2308 * Prevent pasting images into entry.
2309 * If a image pasted, "<item absize=... href=...>" will be appended into entry.
2311 if (strstr(str, "item") != NULL) {
2313 char buf[MAX_EXPRESSION_LENGTH] = { 0 };
2315 while (elm_entry_cursor_prev(obj)) {
2317 } /* save cursor position */
2318 pos -= 1; /* correct */
2320 strncpy(buf, str, sizeof(buf));
2321 char *begin = strstr(buf, "<item");
2322 char *end = strchr(begin, '>');
2323 string_remove_at(buf, begin - buf, end - begin + 1); /* remove "<item...>" */
2324 elm_entry_entry_set(obj, buf);
2327 elm_entry_cursor_next(obj);
2328 } /* retrieve cursor position */
2330 calc_view_revise_input_scroller(ad);
2336 _calc_view_input_entry_paste_cb(void *data, Evas_Object * obj, void *event_info)
2340 strncpy(calculator_before_paste_str, calculator_input_str,
2341 MAX_EXPRESSION_LENGTH - 1);
2348 * Create an entry for inputing expression.
2350 * @param parent the entry's parent
2351 * @param ad the appdata
2352 * @return Evas_Object* the input entry
2354 static Evas_Object *_calc_view_create_input_entry(Evas_Object * parent,
2358 Evas_Object *entry = elm_entry_add(ad->edje);
2359 elm_entry_single_line_set(entry, EINA_FALSE);
2360 elm_entry_editable_set(entry, EINA_TRUE);
2361 elm_entry_input_panel_enabled_set(entry, EINA_FALSE);
2362 elm_entry_entry_set(entry, "");
2363 elm_entry_cnp_mode_set(entry, ELM_CNP_MODE_NO_IMAGE);
2364 elm_entry_magnifier_disabled_set(entry, EINA_TRUE);
2365 elm_entry_cursor_end_set(entry);
2366 elm_object_focus_set(entry, EINA_TRUE);
2367 elm_object_style_set(entry, "black");
2368 evas_object_size_hint_weight_set(entry, EVAS_HINT_EXPAND,
2370 evas_object_size_hint_align_set(entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
2372 evas_object_event_callback_add(entry, EVAS_CALLBACK_MOUSE_UP,
2373 _calc_view_input_entry_mouseup_cb, ad);
2374 evas_object_smart_callback_add(entry, "changed",
2375 _calc_view_input_entry_changed_cb, ad);
2376 evas_object_smart_callback_add(entry, "selection,paste",
2377 _calc_view_input_entry_paste_cb, ad);
2379 evas_object_event_callback_add(entry, EVAS_CALLBACK_KEY_UP,
2380 _calc_view_input_entry_keyup_cb, ad);
2381 evas_object_smart_callback_del (entry, "changed", _calc_view_input_entry_changed_cb);
2383 evas_object_show(entry);
2384 limit_filter_data.max_char_count = 0;
2385 limit_filter_data.max_byte_count = 419 + 20; //19*21+20//result:20
2386 elm_entry_markup_filter_append(entry, elm_entry_filter_limit_size,
2387 &limit_filter_data);
2388 elm_entry_text_style_user_push(entry, "DEFAULT='right_margin=32'");
2395 * Create a input scrooler which around the input entry.
2396 * It can give a input entry a scroller.
2398 * @param parent the parent of input scroller
2399 * @return Evas_Object* the input scroller
2402 static Evas_Object *_calc_view_create_input_scroller(Evas_Object * parent)
2405 Evas_Object *scroller = elm_scroller_add(parent);
2406 elm_scroller_bounce_set(scroller, EINA_FALSE, EINA_TRUE);
2407 evas_object_size_hint_weight_set(scroller, EVAS_HINT_EXPAND,
2409 evas_object_size_hint_align_set(scroller, EVAS_HINT_FILL,
2412 evas_object_show(scroller);
2419 * Create the background
2421 * @param[in] parent background's parent
2422 * @return when success return background, return NULL oppositely
2423 * @retval layout if success, return the background
2424 * @retval NULL if create failed or parent is null, return null
2427 static Evas_Object *__create_bg(Evas_Object *parent)
2430 if (parent == NULL) {
2433 Evas_Object *bg = elm_bg_add(parent);
2437 evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
2438 elm_win_resize_object_add(parent, bg);
2439 evas_object_show(bg);
2446 * Create the main layout
2448 * @param[in] parent main layout's parent
2449 * @return when success return a layout, return NULL oppositely
2450 * @retval layout if success, return the main layout
2451 * @retval NULL if create failed or parent is null, return null
2454 static Evas_Object *__calc_view_create_layout_main(Evas_Object *parent)
2458 if (parent == NULL) {
2462 Evas_Object *layout = elm_layout_add(parent);
2463 if (layout == NULL) {
2467 const char *profile = elm_config_profile_get();
2468 if (!strcmp(profile, "mobile")) {
2469 elm_layout_theme_set(layout, "layout", "application", "default");
2470 } else if (!strcmp(profile, "desktop")) {
2471 elm_layout_theme_set(layout, "layout", "application", "noindicator");
2474 evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND,
2476 elm_win_resize_object_add(parent, layout);
2478 edje_object_signal_emit(_EDJ(layout), "elm,state,show,indicator",
2480 evas_object_show(layout);
2487 void _btn_clicked_cb(void *data, Evas_Object * obj, void *event_info)
2490 Evas_Object *win_main = (Evas_Object *) data;
2491 elm_win_lower(win_main);
2497 * Callback function of "Clear" Button on naviframe
2499 * @param data the appdata
2506 __calc_view_clear_clicked_cb(void *data, Evas_Object *obj, void *event_info)
2509 struct appdata *ad = (struct appdata *)data;
2510 elm_entry_entry_set(ad->hist_area, "");
2511 elm_entry_entry_set(ad->input_entry, "");
2512 _calc_view_clear_histroy(ad->hist_area);
2518 * Load the Naviframe.
2520 * @param ad the appdata
2521 * @return naviframe object
2524 static Evas_Object *__calc_view_create_navigation_layout(struct appdata *ad)
2527 Evas_Object *nf = elm_naviframe_add(ad->layout);
2528 Evas_Object *back_btn = elm_button_add(nf);
2529 elm_object_style_set(back_btn, "naviframe/end_btn/default");
2530 evas_object_smart_callback_add(back_btn, "clicked", _btn_clicked_cb, ad->win);
2532 elm_naviframe_item_push(nf, NULL, back_btn, NULL, ad->edje, NULL);
2533 elm_naviframe_item_title_visible_set(ad->navi_it, EINA_FALSE);
2534 ad->tool_bar = elm_toolbar_add(nf);
2535 elm_toolbar_shrink_mode_set(ad->tool_bar, ELM_TOOLBAR_SHRINK_EXPAND);
2536 elm_object_item_part_content_set(ad->navi_it, "controlbar", ad->tool_bar);
2537 ad->clear_btn = elm_toolbar_item_append(ad->tool_bar, NULL, "Clear History", __calc_view_clear_clicked_cb, ad);
2538 ad->invalid_btn = elm_toolbar_item_append(ad->tool_bar, NULL, NULL, NULL, ad);
2539 elm_object_item_disabled_set(ad->invalid_btn, EINA_TRUE);
2540 evas_object_show(nf);
2547 * Load the main view of calculator.
2548 * Create the input entry and keypad.
2550 * @param ad the appdata
2553 void calc_view_load(struct appdata *ad)
2556 ad->bg = __create_bg(ad->win);
2557 ad->layout = __calc_view_create_layout_main(ad->win);
2558 ad->edje = load_edj(ad->layout, LAYOUT_EDJ_NAME, GRP_MAIN);
2559 evas_object_show(ad->edje);
2560 evas_object_name_set(ad->edje, "edje");
2562 ad->nf = __calc_view_create_navigation_layout(ad);
2563 elm_object_part_content_set(ad->layout, "elm.swallow.content", ad->nf);
2565 /* inititialize environment variable */
2566 locale = localeconv();
2567 decimal = locale->decimal_point;
2568 separator = locale->thousands_sep;
2569 int len_seq = strlen(separator);
2570 decimal_ch = decimal[0];
2571 separator_ch = separator[0];
2572 if (len_seq == 2 || len_seq == 0) {
2577 svi_init(&ad->svi_handle);
2580 ad->input_entry = _calc_view_create_input_entry(ad->edje, ad);
2581 ad->input_scroller = _calc_view_create_input_scroller(ad->edje);
2582 elm_object_content_set(ad->input_scroller, ad->input_entry);
2583 edje_object_part_swallow(_EDJ(ad->edje), "input/entry",
2584 ad->input_scroller);
2591 * assign global variable , this will be removed
2597 void calc_xxx(struct appdata *ap)