jaehyun pushed a commit to branch master.

http://git.enlightenment.org/tools/enventor.git/commit/?id=02a454990689a5c508a853440174ae5277671058

commit 02a454990689a5c508a853440174ae5277671058
Author: Jaehyun Cho <jae_hyun....@samsung.com>
Date:   Wed Feb 17 22:37:28 2016 +0900

    indent: Apply indentation to newly loaded edc text
    
    When an edc text is newly loaded, the edc text is indendted if its
    indentation is not correct.
    The indented text creation function, indent_text_create(), utilizes
    the logic of indent_text_auto_format().
---
 src/lib/edc_editor.c       |  53 ++++--
 src/lib/enventor_private.h |   2 +
 src/lib/indent.c           | 442 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 484 insertions(+), 13 deletions(-)

diff --git a/src/lib/edc_editor.c b/src/lib/edc_editor.c
index 6199b62..9176c6a 100644
--- a/src/lib/edc_editor.c
+++ b/src/lib/edc_editor.c
@@ -1025,16 +1025,48 @@ edit_edc_load(edit_data *ed, const char *file_path)
    utf8_edit = eina_file_map_all(file, EINA_FILE_POPULATE);
    if (!utf8_edit) goto err;
 
-   //Append line numbers
+   //Check indentation.
+   indent_data *id = syntax_indent_data_get(ed->sh);
+   Eina_Bool indent_correct
+      = indent_text_check(id, (const char *)utf8_edit);
+
+   //Set edc text to entry.
+   if (edit_auto_indent_get(ed) && !indent_correct)
+     //Create indented markup text from utf8 text of EDC file.
+     markup_edit = indent_text_create(id, (const char *)utf8_edit,
+                                      &line_num);
+   else
+     markup_edit = elm_entry_utf8_to_markup(utf8_edit);
+   if (!markup_edit) goto err;
+   elm_entry_entry_set(ed->en_edit, markup_edit);
+   if (edit_auto_indent_get(ed) && !indent_correct)
+     edit_changed_set(ed, EINA_TRUE);
+   free(markup_edit);
+
+   //Append line numbers.
    if (!eina_strbuf_append_char(strbuf_line, '1')) goto err;
-   char *p = utf8_edit;
-   int len = strlen(p);
-   while ((p = strchr(p, '\n')) && p < (utf8_edit + len))
+   if (edit_auto_indent_get(ed) && !indent_correct)
+     {
+        int num = 2;
+        //Use line_num given by indent_text_create().
+        while (num <= line_num)
+          {
+             sprintf(buf, "\n%d", num);
+             if (!eina_strbuf_append(strbuf_line, buf)) goto err;
+             num++;
+          }
+     }
+   else
      {
-        line_num++;
-        ++p;
-        sprintf(buf, "\n%d", line_num);
-        if (!eina_strbuf_append(strbuf_line, buf)) goto err;
+        char *p = utf8_edit;
+        int len = strlen(p);
+        while ((p = strchr(p, '\n')) && p < (utf8_edit + len))
+          {
+             line_num++;
+             ++p;
+             sprintf(buf, "\n%d", line_num);
+             if (!eina_strbuf_append(strbuf_line, buf)) goto err;
+          }
      }
 
    markup_line = elm_entry_utf8_to_markup(eina_strbuf_string_get(strbuf_line));
@@ -1042,11 +1074,6 @@ edit_edc_load(edit_data *ed, const char *file_path)
    elm_entry_entry_append(ed->en_line, markup_line);
    free(markup_line);
 
-   markup_edit = elm_entry_utf8_to_markup(utf8_edit);
-   if (!markup_edit) goto err;
-   elm_entry_entry_set(ed->en_edit, markup_edit);
-   free(markup_edit);
-
    ed->line_max = line_num;
 
    group_name = parser_first_group_name_get(ed->pd, ed->en_edit);
diff --git a/src/lib/enventor_private.h b/src/lib/enventor_private.h
index 73b60ce..8febd4f 100644
--- a/src/lib/enventor_private.h
+++ b/src/lib/enventor_private.h
@@ -160,6 +160,8 @@ 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);
+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);
 
 
 /* build */
diff --git a/src/lib/indent.c b/src/lib/indent.c
index 0898734..88bae67 100644
--- a/src/lib/indent.c
+++ b/src/lib/indent.c
@@ -563,3 +563,445 @@ indent_insert_apply(indent_data *id, Evas_Object *entry, 
const char *insert,
           return indent_text_auto_format(id, entry, insert);
      }
 }
+
+/* Check if indentation of input text is correct.
+   Return EINA_TRUE if indentation is correct.
+   Return EINA_FALSE if indentation is not correct. */
+Eina_Bool
+indent_text_check(indent_data *id EINA_UNUSED, const char *utf8)
+{
+   char *utf8_ptr = NULL;
+   char *utf8_end = NULL;
+   int utf8_size = 0;
+   int depth = 0;
+   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 macro_found = EINA_FALSE;
+
+   if (!utf8) return EINA_TRUE;
+
+   utf8_ptr = (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.
+    */
+   while (utf8_ptr < utf8_end)
+     {
+        if (*utf8_ptr == '}')
+          {
+             depth--;
+             if (depth < 0) depth = 0;
+          }
+
+        //Tab is not allowed.
+        if (*utf8_ptr == '\t')
+          return EINA_FALSE;
+        else if (*utf8_ptr == ' ')
+          {
+             if (!nonspace_found)
+               space++;
+          }
+        else if (*utf8_ptr == '\n')
+          {
+             //End of single line comment.
+             if (single_comment_found)
+               {
+                  depth = saved_depth;
+                  single_comment_found = 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;
+                    }
+               }
+             space = 0;
+             nonspace_found = EINA_FALSE;
+          }
+        else
+          {
+             if (!nonspace_found)
+               {
+                  if (space != depth * TAB_SPACE) return EINA_FALSE;
+                  nonspace_found = EINA_TRUE;
+               }
+
+             if (multi_comment_found)
+               {
+                  //End of multi line comment.
+                  if (*utf8_ptr == '/' && (utf8_ptr - 1) >= utf8 &&
+                      *(utf8_ptr - 1) == '*')
+                    {
+                       if ((utf8_ptr + 1 < utf8_end) &&
+                           (*(utf8_ptr + 1) != '\n'))
+                         return EINA_FALSE;
+
+                       depth = saved_depth;
+                       multi_comment_found = EINA_FALSE;
+                    }
+               }
+             //No line comment and No macro.
+             else if (!single_comment_found && !macro_found)
+               {
+                  //Check line comment.
+                  if (*utf8_ptr == '/' && utf8_ptr + 1 < utf8_end)
+                    {
+                       //Start of single line comment.
+                       if (*(utf8_ptr + 1) == '/')
+                         {
+                            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;
+                         }
+                    }
+                  //Check macro.
+                  else if (*utf8_ptr == '#')
+                    {
+                       saved_depth = depth;
+                       macro_found = EINA_TRUE;
+                    }
+                  else if (*utf8_ptr == '}')
+                    {
+                       if ((utf8_ptr + 1 < utf8_end) &&
+                           (*(utf8_ptr + 1) != '\n'))
+                         return EINA_FALSE;
+                    }
+                  else if (*utf8_ptr == ';')
+                    {
+                       if (utf8_ptr + 1 < utf8_end &&
+                           *(utf8_ptr + 1) != '\n')
+                         return EINA_FALSE;
+                    }
+
+                  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 &&
+                           *bracket_right_ptr != '\n')
+                         {
+                            //Check block name after '{'.
+                            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)
+                              return EINA_FALSE;
+                         }
+                    }
+               }
+          }
+
+        if (*utf8_ptr == '{') depth++;
+        utf8_ptr++;
+     }
+
+   return EINA_TRUE;
+}
+
+/* Create indented markup text from input utf8 text.
+   Count the number of lines of indented text.
+   Return created indented markup text. */
+char *
+indent_text_create(indent_data *id,
+                   const char *utf8, int *indented_line_cnt)
+{
+   if (!utf8)
+     {
+        if (indented_line_cnt) *indented_line_cnt = 0;
+        return NULL;
+     }
+
+   int utf8_size = strlen(utf8);
+   char *utf8_ptr = (char *)utf8;
+   char *utf8_lexem = NULL;
+   char *utf8_end = (char *)utf8 + utf8_size;
+   char *utf8_append_ptr = NULL;
+   Eina_List *code_lines = NULL;
+   Eina_Strbuf *buf = eina_strbuf_new();
+
+   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;
+
+   /* 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)
+     {
+        if (*utf8_ptr != ' ' && *utf8_ptr != '\t' &&  *utf8_ptr != '\n' )
+          {
+             //Renew the start position of lexeme.
+             if (!keep_lexem_start_pos) utf8_lexem = utf8_ptr;
+
+             //Check line comment.
+             if (*utf8_ptr == '/' && utf8_ptr + 1 < utf8_end)
+               {
+                  //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 (single_comment_found || multi_comment_found)
+                    utf8_ptr += 2;
+               }
+             //Check macro.
+             if (*utf8_ptr == '#')
+               {
+                  macro_found = EINA_TRUE;
+                  utf8_ptr++;
+               }
+
+             while (utf8_ptr < utf8_end)
+               {
+                  if (*utf8_ptr == '\n')
+                    {
+                       //End of single line comment.
+                       if (single_comment_found)
+                         single_comment_found = 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) == '\\'))
+                              macro_found = EINA_FALSE;
+                         }
+
+                       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) == '*')
+                         {
+                            if (utf8_ptr + 1 == utf8_end)
+                              code_lines = eina_list_append(code_lines,
+                                              
eina_stringshare_add(utf8_lexem));
+                            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;
+                         }
+                    }
+                  //No line comment and No macro.
+                  else if (!single_comment_found && !macro_found)
+                    {
+                       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 + 1 == utf8_end)
+                              code_lines = eina_list_append(code_lines,
+                                              
eina_stringshare_add(utf8_lexem));
+                            else
+                              code_lines =
+                                 eina_list_append(code_lines,
+                                    eina_stringshare_add_length(utf8_lexem,
+                                    utf8_ptr - utf8_lexem + 1));
+                            utf8_append_ptr = utf8_ptr;
+                            break;
+                         }
+                    }
+                  utf8_ptr++;
+               }
+          }
+        utf8_ptr++;
+     }
+   //Append rest of the input string.
+   if (utf8_lexem > utf8_append_ptr)
+     code_lines = eina_list_append(code_lines,
+                                   eina_stringshare_add(utf8_lexem));
+
+   if (!code_lines)
+     {
+        if (indented_line_cnt) *indented_line_cnt = 0;
+        return NULL;
+     }
+
+   Eina_List *l = NULL;
+   Eina_List *l_last = eina_list_last(code_lines);
+   Eina_Stringshare *line;
+
+   int line_cnt = 1;
+   int space = 0;
+   int saved_space = 0;
+   single_comment_found = EINA_FALSE;
+   multi_comment_found = EINA_FALSE;
+   macro_found = EINA_FALSE;
+   EINA_LIST_FOREACH(code_lines, l, line)
+     {
+        if (!single_comment_found && !multi_comment_found && !macro_found)
+          {
+             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;
+               }
+          }
+        if ((line[0] == '}') && (space > 0))
+          space -= TAB_SPACE;
+
+        char *p = alloca(space + 1);
+        memset(p, ' ', space);
+        p[space] = '\0';
+        if (strcmp(line, "\n"))
+          {
+             if (l == l_last)
+               eina_strbuf_append_printf(buf, "%s%s", p, line);
+             else
+               {
+                  eina_strbuf_append_printf(buf, "%s%s\n", p, line);
+                  line_cnt++;
+               }
+          }
+        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);
+     }
+
+   char *utf8_buf = eina_strbuf_string_steal(buf);
+   //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);
+
+   if (indented_line_cnt) *indented_line_cnt = line_cnt;
+   return indented_markup;
+}

-- 


Reply via email to