jaehyun pushed a commit to branch master. http://git.enlightenment.org/tools/enventor.git/commit/?id=ff7ca0ee79976675b9477256cd132d4374d30ba3
commit ff7ca0ee79976675b9477256cd132d4374d30ba3 Author: Jaehyun Cho <[email protected]> Date: Tue Mar 29 19:21:04 2016 +0900 indent: Refactoring indentation. Fix indentation issues by refactoring indentation logic. --- src/lib/edc_editor.c | 9 +- src/lib/enventor_private.h | 2 +- src/lib/indent.c | 823 +++++++++++++++++++++++---------------------- 3 files changed, 428 insertions(+), 406 deletions(-) diff --git a/src/lib/edc_editor.c b/src/lib/edc_editor.c index 14bae66..7d739a1 100644 --- a/src/lib/edc_editor.c +++ b/src/lib/edc_editor.c @@ -451,16 +451,13 @@ edit_changed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info) } else { - int decrease = parser_line_cnt_get(ed->pd, info->change.del.content); - if (edit_auto_indent_get(ed)) { - if (indent_delete_apply(syntax_indent_data_get(ed->sh), - ed->en_edit, info->change.del.content, - ed->cur_line)) - decrease++; + indent_delete_apply(syntax_indent_data_get(ed->sh), ed->en_edit, + info->change.del.content, ed->cur_line); } + int decrease = parser_line_cnt_get(ed->pd, info->change.del.content); edit_line_decrease(ed, decrease); if (info->change.del.content[0] == ' ') return; } diff --git a/src/lib/enventor_private.h b/src/lib/enventor_private.h index 2054c50..a87b9ae 100644 --- a/src/lib/enventor_private.h +++ b/src/lib/enventor_private.h @@ -161,7 +161,7 @@ indent_data *indent_init(Eina_Strbuf *strbuf); void indent_term(indent_data *id); int indent_space_get(indent_data *id, Evas_Object *entry); int indent_insert_apply(indent_data *id, Evas_Object *entry, const char *insert, int cur_line); -Eina_Bool indent_delete_apply(indent_data *id, Evas_Object *entry, const char *del, int cur_line); +void indent_delete_apply(indent_data *id, Evas_Object *entry, const char *del, int cur_line); Eina_Bool indent_text_check(indent_data *id EINA_UNUSED, const char *utf8); char * indent_text_create(indent_data *id, const char *utf8, int *indented_line_cnt); diff --git a/src/lib/indent.c b/src/lib/indent.c index 1f62bc4..9380f12 100644 --- a/src/lib/indent.c +++ b/src/lib/indent.c @@ -10,6 +10,13 @@ struct indent_s Eina_Strbuf *strbuf; }; +typedef struct indent_line_s +{ + Eina_Stringshare *str; + Eina_Bool indent_apply; + int indent_depth; +} indent_line; + /*****************************************************************************/ /* Internal method implementation */ /*****************************************************************************/ @@ -185,71 +192,75 @@ indent_space_get(indent_data *id, Evas_Object *entry) return space; } -Eina_Bool +void indent_delete_apply(indent_data *id EINA_UNUSED, Evas_Object *entry, const char *del, int cur_line) { - if (del[0] != ' ') return EINA_FALSE; + if (del[0] != ' ') return; Evas_Object *tb = elm_entry_textblock_get(entry); Evas_Textblock_Cursor *cur = evas_object_textblock_cursor_new(tb); evas_textblock_cursor_line_set(cur, cur_line - 1); const char *text = evas_textblock_cursor_paragraph_text_get(cur); char *utf8 = elm_entry_markup_to_utf8(text); + char *last_markup = NULL; Eina_Strbuf* diff = eina_strbuf_new(); + int rd_cur_pos = evas_textblock_cursor_pos_get(cur); redoundo_data *rd = evas_object_data_get(entry, "redoundo"); int len = strlen(utf8); - if (len < 0) return EINA_FALSE; + if (len <= 0) goto end; evas_textblock_cursor_paragraph_char_last(cur); + last_markup = evas_textblock_cursor_content_get(cur); + if (last_markup && !strncmp(last_markup, "<br/>", 5)) + evas_textblock_cursor_char_prev(cur); while (len > 0) { if ((utf8[(len - 1)] == ' ')) { - evas_textblock_cursor_char_prev(cur); eina_strbuf_append(diff, evas_textblock_cursor_content_get(cur)); evas_textblock_cursor_char_delete(cur); + evas_textblock_cursor_char_prev(cur); } else break; len--; } - - if (len == 0) - { - eina_strbuf_append(diff, evas_textblock_cursor_content_get(cur)); - evas_textblock_cursor_char_delete(cur); - } redoundo_text_push(rd, eina_strbuf_string_get(diff), rd_cur_pos, 0, EINA_FALSE); elm_entry_calc_force(entry); + +end: evas_textblock_cursor_free(cur); - free(utf8); + if (utf8) free(utf8); + if (last_markup) free(last_markup); eina_strbuf_free(diff); - if (len == 0) - { - elm_entry_cursor_prev(entry); - return EINA_TRUE; - } - return EINA_FALSE; } static Eina_List * -indent_code_lines_create(indent_data *id EINA_UNUSED, const char *utf8) +indent_code_line_list_create(indent_data *id EINA_UNUSED, const char *utf8) { - Eina_List *code_lines = NULL; + Eina_List *code_line_list = NULL; + indent_line *code_line = NULL; char *utf8_ptr = NULL; char *utf8_end = NULL; char *utf8_lexem = NULL; - char *utf8_append_ptr = NULL; + char *utf8_appended = NULL; - Eina_Bool keep_lexem_start_pos = EINA_FALSE; - Eina_Bool single_comment_found = EINA_FALSE; - Eina_Bool multi_comment_found = EINA_FALSE; - Eina_Bool macro_found = EINA_FALSE; + Eina_Bool keep_lexem = EINA_FALSE; + Eina_Bool single_comment_begin = EINA_FALSE; + Eina_Bool single_comment_middle = EINA_FALSE; + Eina_Bool multi_comment_begin = EINA_FALSE; + Eina_Bool multi_comment_middle = EINA_FALSE; + Eina_Bool multi_comment_end = EINA_FALSE; + Eina_Bool macro_begin = EINA_FALSE; + Eina_Bool macro_middle = EINA_FALSE; + + int cur_indent_depth = 0; + int new_indent_depth = 0; if (!utf8) return NULL; @@ -258,151 +269,172 @@ indent_code_lines_create(indent_data *id EINA_UNUSED, const char *utf8) /* Create a list of code line strings from inserted string. Each code line string is generated based on lexeme. - Here, lexeme starts with nonspace character and ends with the followings. - '{', '}', ';', "//", "*\/" - */ - while (utf8_ptr < utf8_end) + Here, lexeme starts with nonspace character and ends with newline. */ + for ( ; utf8_ptr < utf8_end; utf8_ptr++) { - if (*utf8_ptr != ' ' && *utf8_ptr != '\t' && *utf8_ptr != '\n' && - *utf8_ptr != '\r') + if (*utf8_ptr == '\n') { - //Renew the start position of lexeme. - if (!keep_lexem_start_pos) utf8_lexem = utf8_ptr; + if (!keep_lexem) + utf8_lexem = utf8_ptr; + keep_lexem = EINA_FALSE; + + code_line = (indent_line *)calloc(1, sizeof(indent_line)); - //Check line comment. - if (*utf8_ptr == '/' && utf8_ptr + 1 < utf8_end) + char *append_begin = NULL; + if (!utf8_appended) append_begin = (char *)utf8; + + if (single_comment_begin || multi_comment_begin || + multi_comment_end || macro_begin || macro_middle) { - //Start of single line comment. - if (*(utf8_ptr + 1) == '/') - single_comment_found = EINA_TRUE; - //Start of multi line comment. - else if (*(utf8_ptr + 1) == '*') - multi_comment_found = EINA_TRUE; + if (!append_begin) + append_begin = utf8_appended + 1; - if (single_comment_found || multi_comment_found) - utf8_ptr += 2; + code_line->indent_apply = EINA_FALSE; } - //Check macro. - if (*utf8_ptr == '#') + else { - macro_found = EINA_TRUE; - utf8_ptr++; + if (!append_begin) + append_begin = utf8_lexem; + + //Newline only string does not need indentation. + if (utf8_ptr == append_begin) + code_line->indent_apply = EINA_FALSE; + else + code_line->indent_apply = EINA_TRUE; } + code_line->str + = eina_stringshare_add_length(append_begin, + utf8_ptr - append_begin + 1); + code_line->indent_depth = cur_indent_depth; + cur_indent_depth = new_indent_depth; + + code_line_list = eina_list_append(code_line_list, code_line); + utf8_appended = utf8_ptr; + + if (single_comment_begin) + single_comment_begin = EINA_FALSE; + if (single_comment_middle) + single_comment_middle = EINA_FALSE; + if (multi_comment_middle) + { + multi_comment_middle = EINA_FALSE; + multi_comment_begin = EINA_TRUE; + } + if (multi_comment_end) + multi_comment_end = EINA_FALSE; - while (utf8_ptr < utf8_end) + //Check if macro ends. + if (macro_begin || macro_middle) { - if (*utf8_ptr == '\n') + if (*(utf8_ptr - 1) != '\\') { - //End of single line comment. - if (single_comment_found) - single_comment_found = EINA_FALSE; + macro_begin = EINA_FALSE; + macro_middle = EINA_FALSE; + } + } + } + else if ((*utf8_ptr != ' ') && (*utf8_ptr != '\t') && + (*utf8_ptr != '\r')) + { + if (!keep_lexem) + { + utf8_lexem = utf8_ptr; + keep_lexem = EINA_TRUE; + } - //End of macro. - else if (macro_found) + if (!single_comment_begin && !single_comment_middle && + !multi_comment_begin && !multi_comment_middle && + !multi_comment_end) + { + if ((*utf8_ptr == '/') && (utf8_ptr + 1 < utf8_end)) + { + //Check if single line comment begins. + if (*(utf8_ptr + 1) == '/') { - //Macro ends with "\n" but continues with "\\\n". - if (!(utf8_ptr - 1 >= utf8 && - *(utf8_ptr - 1) == '\\')) - macro_found = EINA_FALSE; + if (utf8_ptr == utf8_lexem) + single_comment_begin = EINA_TRUE; + else + single_comment_middle = EINA_TRUE; } - - code_lines = eina_list_append(code_lines, - eina_stringshare_add_length(utf8_lexem, - utf8_ptr - utf8_lexem)); - utf8_append_ptr = utf8_ptr; - break; - } - else if (multi_comment_found) - { - //End of multi line comment. - if (*utf8_ptr == '/' && utf8_ptr - 1 >= utf8 && - *(utf8_ptr - 1) == '*') + //Check if multi line comment begins. + else if (*(utf8_ptr + 1) == '*') { - if (utf8_ptr + 1 == utf8_end) - code_lines = eina_list_append(code_lines, - eina_stringshare_add(utf8_lexem)); + if (utf8_ptr == utf8_lexem) + multi_comment_begin = EINA_TRUE; else - code_lines = - eina_list_append(code_lines, - eina_stringshare_add_length(utf8_lexem, - utf8_ptr - utf8_lexem + 1)); - utf8_append_ptr = utf8_ptr; - multi_comment_found = EINA_FALSE; - break; + multi_comment_middle = EINA_TRUE; } } - //No line comment and No macro. - else if (!single_comment_found && !macro_found) + else if (*utf8_ptr == '#') { - if (*utf8_ptr == '{' || *utf8_ptr == '}' || - *utf8_ptr == ';') - { - if (*utf8_ptr == '{') - { - char *bracket_right_ptr = utf8_ptr + 1; - while (bracket_right_ptr < utf8_end) - { - if (*bracket_right_ptr != ' ' && - *bracket_right_ptr != '\t') - break; - bracket_right_ptr++; - } - if (bracket_right_ptr < utf8_end) - { - /* To preserve code line until block name, - keep start position of lexeme and - append code line until ';'. */ - Eina_Bool block_name_found = EINA_FALSE; - - if (*bracket_right_ptr == '\"') - block_name_found = EINA_TRUE; - else if (bracket_right_ptr + 4 < utf8_end) - { - if (!strncmp(bracket_right_ptr, - "name:", 5)) - block_name_found = EINA_TRUE; - else if (!strncmp(bracket_right_ptr, - "state:", 5)) - block_name_found = EINA_TRUE; - } - - if (block_name_found) - { - keep_lexem_start_pos = EINA_TRUE; - break; - } - } - } - else if (*utf8_ptr == ';') - keep_lexem_start_pos = EINA_FALSE; + if (utf8_ptr == utf8_lexem) + macro_begin = EINA_TRUE; + else + macro_middle = EINA_TRUE; + } + else if (*utf8_ptr == '{') + new_indent_depth++; + else if (*utf8_ptr == '}') + { + new_indent_depth--; - if (utf8_ptr + 1 == utf8_end) - code_lines = eina_list_append(code_lines, - eina_stringshare_add(utf8_lexem)); - else - //FIXME: Here stringshare occurs memory leak. :( - code_lines = - eina_list_append(code_lines, - eina_stringshare_add_length(utf8_lexem, - utf8_ptr - utf8_lexem + 1)); - utf8_append_ptr = utf8_ptr; - break; - } + /* Indentation depth decreases from the current code line + if string begins with '}'. */ + if (utf8_ptr == utf8_lexem) + cur_indent_depth = new_indent_depth; + } + } + + //Check if multi line comment ends. + if (multi_comment_begin || multi_comment_middle) + { + if ((*utf8_ptr == '*') && (utf8_ptr + 1 < utf8_end) && + (*(utf8_ptr + 1) == '/')) + { + multi_comment_begin = EINA_FALSE; + multi_comment_middle = EINA_FALSE; + multi_comment_end = EINA_TRUE; } - utf8_ptr++; } } - utf8_ptr++; } - //FIXME: Now string is not added to code line and indentation is not applied - // if string does not contain keywords which cause a new line. - // (e.g. string not containing ';') - //Append rest of the input string. - if (utf8_append_ptr && (utf8_lexem > utf8_append_ptr)) - code_lines = eina_list_append(code_lines, - eina_stringshare_add(utf8_lexem)); - - return code_lines; + + /* Append rest of the input string which does not end with newline. */ + if (!utf8_appended || (utf8_appended < utf8_end - 1)) + { + char *append_begin = NULL; + if (!utf8_appended) append_begin = (char *)utf8; + + code_line = (indent_line *)calloc(1, sizeof(indent_line)); + + if (single_comment_begin || multi_comment_begin || macro_begin || + multi_comment_end) + { + if (!append_begin) + append_begin = utf8_appended + 1; + + code_line->indent_apply = EINA_FALSE; + } + else + { + if (!append_begin) + append_begin = utf8_lexem; + + //Newline only string does not need indentation. + if ((*append_begin == '\n') && (append_begin == utf8_end - 1)) + code_line->indent_apply = EINA_FALSE; + else + code_line->indent_apply = EINA_TRUE; + } + code_line->str + = eina_stringshare_add_length(append_begin, + utf8_end - append_begin); + code_line->indent_depth = cur_indent_depth; + + code_line_list = eina_list_append(code_line_list, code_line); + } + + return code_line_list; } static int @@ -421,158 +453,180 @@ indent_text_auto_format(indent_data *id, redoundo_data *rd = evas_object_data_get(entry, "redoundo"); - char *utf8_ptr = utf8; - - Eina_List *code_lines = indent_code_lines_create(id, utf8); + Eina_List *code_line_list = indent_code_line_list_create(id, utf8); + indent_line *code_line = NULL; free(utf8); - if (!code_lines) return line_cnt; + if (!code_line_list) goto end; - tb_cur_pos = evas_textblock_cursor_pos_get(cur_end); - evas_textblock_cursor_pos_set(cur_start, tb_cur_pos - utf8_size); - evas_textblock_cursor_range_delete(cur_start, cur_end); + /* Check if indentation should be applied to the first code line. + Indentation is applied if prior string has only spaces. */ + code_line= eina_list_data_get(code_line_list); + if (code_line->indent_apply) + { + Evas_Textblock_Cursor *check_start + = evas_object_textblock_cursor_new(tb); + Evas_Textblock_Cursor *check_end + = evas_object_textblock_cursor_new(tb); - Eina_List *l = NULL; - Eina_Stringshare *line; - evas_textblock_cursor_line_char_first(cur_start); + tb_cur_pos = evas_textblock_cursor_pos_get(cur_end); + evas_textblock_cursor_pos_set(check_end, tb_cur_pos - utf8_size); + evas_textblock_cursor_pos_set(check_start, tb_cur_pos - utf8_size); + evas_textblock_cursor_line_char_first(check_start); - /* Checking the string from start till cursor position is empty. - * And in case if this range is empty - formatted text will be - * inserted above the current line */ - char *check_range = evas_textblock_cursor_range_text_get(cur_start, - cur_end, EVAS_TEXTBLOCK_TEXT_PLAIN); - Eina_Bool above = EINA_TRUE; - if (check_range) - { - int check_len = strlen(check_range); - int space_cnt = 0; - for (; space_cnt < check_len; space_cnt++) + char *check_range + = evas_textblock_cursor_range_text_get(check_start, check_end, + EVAS_TEXTBLOCK_TEXT_PLAIN); + + evas_textblock_cursor_free(check_start); + evas_textblock_cursor_free(check_end); + + Eina_Bool nonspace_found = EINA_FALSE; + if (check_range) { - if (check_range[space_cnt] != ' ') + int check_len = strlen(check_range); + int index = 0; + for ( ; index < check_len; index++) { - above = EINA_FALSE; - break; + if (check_range[index] != ' ') + { + nonspace_found = EINA_TRUE; + break; + } } + free(check_range); } - } - - if (!above) - evas_textblock_cursor_line_char_last(cur_end); - int space = indent_space_get(id, entry); - - utf8 = evas_textblock_cursor_range_text_get(cur_start, cur_end, - EVAS_TEXTBLOCK_TEXT_PLAIN); - utf8_ptr = utf8 + strlen(utf8); - while (utf8_ptr && (utf8_ptr >= utf8)) - { - if (utf8_ptr[0] != ' ') + if (nonspace_found) { - if ((utf8_ptr[0] == '}') && (space > 0)) - space -= TAB_SPACE; - if (!above && !evas_textblock_cursor_paragraph_next(cur_start)) + code_line->indent_apply = EINA_FALSE; + } + else + { + int str_len = eina_stringshare_strlen(code_line->str); + int index = 0; + for ( ; index < str_len; index++) + { + if ((code_line->str[index] != ' ') && + (code_line->str[index] != '\t') && + (code_line->str[index] != '\r')) + break; + } + if (index < str_len) { - code_lines = eina_list_prepend(code_lines, - eina_stringshare_add("\n")); - evas_textblock_cursor_line_char_last(cur_start); + char *new_str = strdup(&code_line->str[index]); + if (new_str) + { + eina_stringshare_del(code_line->str); + code_line->str = eina_stringshare_add(new_str); + free(new_str); + } } - break; } - utf8_ptr--; } - free(utf8); - Eina_Strbuf *buf = eina_strbuf_new(); - int saved_space = 0; - Eina_Bool single_comment_found = EINA_FALSE; - Eina_Bool multi_comment_found = EINA_FALSE; - Eina_Bool macro_found = EINA_FALSE; - EINA_LIST_FOREACH(code_lines, l, line) + tb_cur_pos = evas_textblock_cursor_pos_get(cur_end); + evas_textblock_cursor_pos_set(cur_start, tb_cur_pos - utf8_size); + evas_textblock_cursor_range_delete(cur_start, cur_end); + + //Cancel last added diff, that was created when text pasted into entry. + redoundo_n_diff_cancel(rd, 1); + + evas_textblock_cursor_line_char_first(cur_start); + + //Move cursor to the position where the inserted string will be prepended. + code_line= eina_list_data_get(code_line_list); + if (code_line->indent_apply) { - if (!single_comment_found && !multi_comment_found && !macro_found) + evas_textblock_cursor_line_char_first(cur_start); + int space_pos_start = evas_textblock_cursor_pos_get(cur_start); + int space_pos_end = evas_textblock_cursor_pos_get(cur_end); + + if (space_pos_start < space_pos_end) { - if (!strncmp(line, "//", 2)) - { - single_comment_found = EINA_TRUE; - saved_space = space; - } - else if (!strncmp(line, "/*", 2)) - { - multi_comment_found = EINA_TRUE; - saved_space = space; - } - else if (line[0] == '#') + //Delete prior spaces. + char *prior_space = + evas_textblock_cursor_range_text_get(cur_start, cur_end, + EVAS_TEXTBLOCK_TEXT_MARKUP); + + if (prior_space) { - macro_found = EINA_TRUE; - saved_space = space; + evas_textblock_cursor_range_delete(cur_start, cur_end); + + tb_cur_pos = evas_textblock_cursor_pos_get(cur_end); + /* Add data about removal of prior spaces into the redoundo + queue. */ + redoundo_text_push(rd, prior_space, tb_cur_pos, 0, + EINA_FALSE); + free(prior_space); } } - if ((line[0] == '}') && (space > 0)) - space -= TAB_SPACE; + } + else + { + tb_cur_pos = evas_textblock_cursor_pos_get(cur_end); + evas_textblock_cursor_pos_set(cur_start, tb_cur_pos); + } - char *p = alloca(space + 1); - memset(p, ' ', space); - p[space] = '\0'; - if (strcmp(line, "\n")) - eina_strbuf_append_printf(buf, "%s%s\n", p, line); - else - eina_strbuf_append(buf, "\n"); - memset(p, 0x0, space); + int space = indent_space_get(id, entry); - /* Based on the code line generation logic, "{" and "}" can exist - multiple times in a line within line comment and macro. */ - char *bracket_ptr = strstr(line, "{"); - while (bracket_ptr) - { - space += TAB_SPACE; - bracket_ptr++; - bracket_ptr = strstr(bracket_ptr, "{"); - } - //Restore space. - if (line[0] == '}') space += TAB_SPACE; - bracket_ptr = strstr(line, "}"); - while (bracket_ptr && space > 0) - { - space -= TAB_SPACE; - bracket_ptr++; - bracket_ptr = strstr(bracket_ptr, "}"); - } + Eina_List *l = NULL; + Eina_Strbuf *buf = eina_strbuf_new(); - if (single_comment_found) - { - single_comment_found = EINA_FALSE; - space = saved_space; - } - else if (multi_comment_found && strstr(line, "*/")) + EINA_LIST_FOREACH(code_line_list, l, code_line) + { + Eina_Stringshare *line_str = code_line->str; + + if (code_line->indent_apply == EINA_FALSE) { - multi_comment_found = EINA_FALSE; - space = saved_space; + eina_strbuf_append_printf(buf, "%s", line_str); } - else if (macro_found && line[strlen(line) - 1] != '\\') + else { - macro_found = EINA_FALSE; - space = saved_space; + int cur_space = space + (code_line->indent_depth * TAB_SPACE); + if (cur_space <= 0) + { + eina_strbuf_append_printf(buf, "%s", line_str); + } + else + { + char *p = alloca(cur_space + 1); + memset(p, ' ', cur_space); + p[cur_space] = '\0'; + eina_strbuf_append_printf(buf, "%s%s", p, line_str); + memset(p, 0x0, cur_space); + } } - - eina_stringshare_del(line); - line_cnt++; + eina_stringshare_del(line_str); + free(code_line); } + eina_list_free(code_line_list); char *utf8_buf = eina_strbuf_string_steal(buf); + char *newline_ptr = utf8_buf; + line_cnt = 1; + if (*newline_ptr == '\n') line_cnt++; + while (newline_ptr = strstr(newline_ptr + 1, "\n")) + line_cnt++; + //FIXME: To improve performance, change logic not to translate text. char *markup_buf = evas_textblock_text_utf8_to_markup(NULL, utf8_buf); eina_strbuf_free(buf); free(utf8_buf); + //Initialize cursor position to the beginning of the pasted string. tb_cur_pos = evas_textblock_cursor_pos_get(cur_start); evas_textblock_cursor_pos_set(cur_end, tb_cur_pos); evas_object_textblock_text_markup_prepend(cur_start, markup_buf); - // Cancel last added diff, that was created when text pasted into entry. - redoundo_n_diff_cancel(rd, 1); //Add data about formatted change into the redoundo queue. redoundo_text_push(rd, markup_buf, tb_cur_pos, 0, EINA_TRUE); - free(markup_buf); + + //Update cursor position to the end of the pasted string. + tb_cur_pos = evas_textblock_cursor_pos_get(cur_start); + evas_textblock_cursor_pos_set(cur_end, tb_cur_pos); + +end: evas_textblock_cursor_free(cur_start); return line_cnt; } @@ -582,7 +636,11 @@ indent_insert_apply(indent_data *id, Evas_Object *entry, const char *insert, int cur_line) { int len = strlen(insert); - if (len == 1) + if (len == 0) + { + return 0; + } + else if (len == 1) { if (insert[0] == '}') indent_insert_bracket_case(id, entry, cur_line); @@ -604,7 +662,11 @@ indent_insert_apply(indent_data *id, Evas_Object *entry, const char *insert, else if (!strcmp(insert, AMP)) return 0; else - return indent_text_auto_format(id, entry, insert); + { + int increase = indent_text_auto_format(id, entry, insert); + if (increase > 0) increase--; + return increase; + } } } @@ -621,8 +683,7 @@ indent_text_check(indent_data *id EINA_UNUSED, const char *utf8) int saved_depth = 0; int space = 0; Eina_Bool nonspace_found = EINA_FALSE; - Eina_Bool single_comment_found = EINA_FALSE; - Eina_Bool multi_comment_found = EINA_FALSE; + Eina_Bool comment_found = EINA_FALSE; Eina_Bool macro_found = EINA_FALSE; if (!utf8) return EINA_TRUE; @@ -631,13 +692,13 @@ indent_text_check(indent_data *id EINA_UNUSED, const char *utf8) utf8_size = strlen(utf8); utf8_end = (char *)utf8 + utf8_size; - /* Check spaces based on depth before nonspace character in each line. - Check a new line after the followings. - '{', '}', ';', "*\/" - Depth is not calculated within line comment. - */ + /* Check indentation spaces of each line. + Indentation spaces are checked within line comment and macro. */ while (utf8_ptr < utf8_end) { + comment_found = EINA_FALSE; + macro_found = EINA_FALSE; + if (*utf8_ptr == '}') { depth--; @@ -654,76 +715,93 @@ indent_text_check(indent_data *id EINA_UNUSED, const char *utf8) } else if (*utf8_ptr == '\n') { - //End of single line comment. - if (single_comment_found) - { - depth = saved_depth; - single_comment_found = EINA_FALSE; - } + //Do not allow space only line. + if (!nonspace_found && (space > 0)) + return EINA_FALSE; - //End of macro. - else if (macro_found) - { - //Macro ends with "\n" but continues with "\\\n". - if (!(utf8_ptr - 1 >= utf8 && *(utf8_ptr - 1) == '\\')) - { - depth = saved_depth; - macro_found = EINA_FALSE; - } - } - if (utf8_ptr >= utf8_end - 1) + //Do not allow newline at the end. + if (utf8_ptr == utf8_end - 1) return EINA_FALSE; + space = 0; nonspace_found = EINA_FALSE; } - else + else if (*utf8_ptr != '\r') { - if (!nonspace_found) - { - if (space != depth * TAB_SPACE) return EINA_FALSE; - nonspace_found = EINA_TRUE; - } + char *comment_end = NULL; - if (multi_comment_found) + //Check line comment + if ((*utf8_ptr == '/') && (utf8_ptr + 1 < utf8_end)) { - //End of multi line comment. - if (*utf8_ptr == '/' && (utf8_ptr - 1) >= utf8 && - *(utf8_ptr - 1) == '*') + //Start of single line comment. + if (*(utf8_ptr + 1) == '/') { - if ((utf8_ptr + 1 < utf8_end) && - (*(utf8_ptr + 1) != '\n')) - return EINA_FALSE; + comment_found = EINA_TRUE; - depth = saved_depth; - multi_comment_found = EINA_FALSE; + comment_end = strstr(utf8_ptr + 2, "\n"); + if (comment_end) comment_end--; + } + //Start of multi line comment. + else if (*(utf8_ptr + 1) == '*') + { + comment_found = EINA_TRUE; + + comment_end = strstr(utf8_ptr + 2, "*/"); + if (comment_end) comment_end++; + } + + if (comment_found) + { + if (comment_end) + utf8_ptr = comment_end; + else + return EINA_TRUE; } } - //No line comment and No macro. - else if (!single_comment_found && !macro_found) + + //Check macro + else if (*utf8_ptr == '#') { - //Check line comment. - if (*utf8_ptr == '/' && utf8_ptr + 1 < utf8_end) + macro_found = EINA_TRUE; + + char *macro_end = utf8_ptr; + while (macro_end) { - //Start of single line comment. - if (*(utf8_ptr + 1) == '/') + char *backslash = strstr(macro_end + 1, "\\"); + macro_end = strstr(macro_end + 1, "\n"); + if (macro_end) { - saved_depth = depth; - single_comment_found = EINA_TRUE; - } - //Start of multi line comment. - else if (*(utf8_ptr + 1) == '*') - { - saved_depth = depth; - multi_comment_found = EINA_TRUE; + if (!backslash || (macro_end < backslash)) + break; } } - //Check macro. - else if (*utf8_ptr == '#') + + if (macro_end) { - saved_depth = depth; - macro_found = EINA_TRUE; + macro_end--; + utf8_ptr = macro_end; } - else if (*utf8_ptr == '}') + else + return EINA_TRUE; + } + + if (comment_found || macro_found) + { + if (!nonspace_found) + nonspace_found = EINA_TRUE; + } + //No line comment and No macro. + else + { + if (!nonspace_found) + { + if (space != depth * TAB_SPACE) + return EINA_FALSE; + + nonspace_found = EINA_TRUE; + } + + if (*utf8_ptr == '}') { if ((utf8_ptr + 1 < utf8_end) && (*(utf8_ptr + 1) != '\n')) @@ -771,7 +849,9 @@ indent_text_check(indent_data *id EINA_UNUSED, const char *utf8) } } - if (*utf8_ptr == '{') depth++; + if (!comment_found && !macro_found && (*utf8_ptr == '{')) + depth++; + utf8_ptr++; } @@ -791,113 +871,58 @@ indent_text_create(indent_data *id, return NULL; } - Eina_List *code_lines = indent_code_lines_create(id, utf8); - if (!code_lines) + Eina_List *code_line_list = indent_code_line_list_create(id, utf8); + if (!code_line_list) { if (indented_line_cnt) *indented_line_cnt = 0; return NULL; } + indent_line *code_line = NULL; Eina_List *l = NULL; - Eina_List *l_last = eina_list_last(code_lines); - Eina_Stringshare *line; Eina_Strbuf *buf = eina_strbuf_new(); - int line_cnt = 1; - int space = 0; - int saved_space = 0; - Eina_Bool single_comment_found = EINA_FALSE; - Eina_Bool multi_comment_found = EINA_FALSE; - Eina_Bool macro_found = EINA_FALSE; - EINA_LIST_FOREACH(code_lines, l, line) + EINA_LIST_FOREACH(code_line_list, l, code_line) { - if (!single_comment_found && !multi_comment_found && !macro_found) + Eina_Stringshare *line_str = code_line->str; + + if (!code_line->indent_apply) { - if (!strncmp(line, "//", 2)) - { - single_comment_found = EINA_TRUE; - saved_space = space; - } - else if (!strncmp(line, "/*", 2)) - { - multi_comment_found = EINA_TRUE; - saved_space = space; - } - else if (line[0] == '#') - { - macro_found = EINA_TRUE; - saved_space = space; - } + eina_strbuf_append_printf(buf, "%s", line_str); } - if ((line[0] == '}') && (space > 0)) - space -= TAB_SPACE; - - char *p = alloca(space + 1); - memset(p, ' ', space); - p[space] = '\0'; - if (strcmp(line, "\n")) + else { - if (l == l_last) - eina_strbuf_append_printf(buf, "%s%s", p, line); + int space = code_line->indent_depth * TAB_SPACE; + if (space <= 0) + { + eina_strbuf_append_printf(buf, "%s", line_str); + } else { - eina_strbuf_append_printf(buf, "%s%s\n", p, line); - line_cnt++; + char *p = alloca(space + 1); + memset(p, ' ', space); + p[space] = '\0'; + eina_strbuf_append_printf(buf, "%s%s", p, line_str); + memset(p, 0x0, space); } } - else - { - eina_strbuf_append(buf, "\n"); - line_cnt++; - } - memset(p, 0x0, space); - - /* Based on the code line generation logic, "{" and "}" can exist - multiple times in a line within line comment and macro. */ - char *bracket_ptr = strstr(line, "{"); - while (bracket_ptr) - { - space += TAB_SPACE; - bracket_ptr++; - bracket_ptr = strstr(bracket_ptr, "{"); - } - //Restore space. - if (line[0] == '}') space += TAB_SPACE; - bracket_ptr = strstr(line, "}"); - while (bracket_ptr && space > 0) - { - space -= TAB_SPACE; - bracket_ptr++; - bracket_ptr = strstr(bracket_ptr, "}"); - } - - if (single_comment_found) - { - single_comment_found = EINA_FALSE; - space = saved_space; - } - else if (multi_comment_found && strstr(line, "*/")) - { - multi_comment_found = EINA_FALSE; - space = saved_space; - } - else if (macro_found && line[strlen(line) - 1] != '\\') - { - macro_found = EINA_FALSE; - space = saved_space; - } - - eina_stringshare_del(line); + eina_stringshare_del(line_str); + free(code_line); } + eina_list_free(code_line_list); char *utf8_buf = eina_strbuf_string_steal(buf); + char *newline_ptr = utf8_buf; + int line_cnt = 1; + if (*newline_ptr == '\n') line_cnt++; + while (newline_ptr = strstr(newline_ptr + 1, "\n")) + line_cnt++; + //FIXME: This translation may cause low performance. char *indented_markup = evas_textblock_text_utf8_to_markup(NULL, utf8_buf); eina_strbuf_free(buf); free(utf8_buf); - eina_list_free(code_lines); - if (indented_line_cnt) *indented_line_cnt = line_cnt; return indented_markup; } --
