1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4 
5 #include "Elementary.h"
6 
7 #include "elm_code_private.h"
8 
9 EAPI void
elm_code_line_free(Elm_Code_Line * line)10 elm_code_line_free(Elm_Code_Line *line)
11 {
12    if (!line)
13      return;
14 
15    if (line->status_text)
16      free((char *)line->status_text);
17    if (line->modified)
18      free(line->modified);
19 
20    free(line);
21 }
22 
23 static void
_elm_code_line_tokens_split_at(Elm_Code_Line * oldline,Elm_Code_Line * newline,Eina_List * tokens,int position)24 _elm_code_line_tokens_split_at(Elm_Code_Line *oldline, Elm_Code_Line *newline,
25                                Eina_List *tokens, int position)
26 {
27    Eina_List *item, *next;
28    Elm_Code_Token *token, *newtoken;
29 
30    EINA_LIST_FOREACH_SAFE(tokens, item, next, token)
31      {
32         if (!token->continues && token->end < position)
33           {
34              oldline->tokens = eina_list_append(oldline->tokens, token);
35              continue;
36           }
37         if (token->start >= position)
38           {
39              token->start -= position;
40              token->end -= position;
41              newline->tokens = eina_list_append(newline->tokens, token);
42              continue;
43           }
44 
45         if (token->continues)
46           elm_code_line_token_add(newline, 0, token->end, 1, token->type);
47         else
48           {
49              elm_code_line_token_add(newline, 0, token->end - position, 1, token->type);
50              token->end = position - 1;
51           }
52 
53         newtoken = eina_list_data_get(newline->tokens);
54         newtoken->continues = token->continues;
55         token->continues = EINA_TRUE;
56         oldline->tokens = eina_list_append(oldline->tokens, token);
57      }
58 
59    elm_code_callback_fire(oldline->file->parent, &ELM_CODE_EVENT_LINE_LOAD_DONE, oldline);
60    elm_code_callback_fire(newline->file->parent, &ELM_CODE_EVENT_LINE_LOAD_DONE, newline);
61 }
62 
elm_code_line_split_at(Elm_Code_Line * line,unsigned int position)63 EAPI void elm_code_line_split_at(Elm_Code_Line *line, unsigned int position)
64 {
65    Elm_Code_Line *newline;
66    Elm_Code_Token *token EINA_UNUSED;
67    Eina_List *tokens;
68    char *content;
69    unsigned int length;
70 
71    content = (char *) elm_code_line_text_get(line, &length);
72    if (!content) return;
73    content = eina_strndup(content, length);
74    if (!content) return;
75    elm_code_file_line_insert(line->file, line->number + 1, "", 0, NULL);
76    newline = elm_code_file_line_get(line->file, line->number + 1);
77 
78    tokens = line->tokens;
79    line->tokens = NULL;
80    elm_code_line_text_set(newline, content + position, length - position);
81    elm_code_line_text_set(line, content, position);
82    _elm_code_line_tokens_split_at(line, newline, tokens, position);
83 
84    EINA_LIST_FREE(tokens, token) {} // don't free tokens, we re-used them
85    free(content);
86 }
87 
88 static void
_elm_code_line_merge_into(Elm_Code_Line * line1,Elm_Code_Line * line2)89 _elm_code_line_merge_into(Elm_Code_Line *line1, Elm_Code_Line *line2)
90 {
91    Eina_List *tokens1, *tokens2;
92    Elm_Code_Token *token;
93    const char *text1, *text2;
94    char *newtext;
95    unsigned int length1, length2;
96 
97    text1 = elm_code_line_text_get(line1, &length1);
98    text2 = elm_code_line_text_get(line2, &length2);
99 
100    newtext = malloc(sizeof(char) * (length1 + length2 + 1));
101    if (!newtext) return;
102    if (length1 > 0)
103      snprintf(newtext, length1 + 1, "%s", text1);
104    if (length2 > 0)
105      snprintf(newtext + length1, length2 + 1, "%s", text2);
106 
107    tokens1 = line1->tokens;
108    line1->tokens = NULL;
109    tokens2 = line2->tokens;
110    line2->tokens = NULL;
111    elm_code_file_line_remove(line2->file, line2->number);
112    elm_code_line_text_set(line1, newtext, length1 + length2);
113 
114    EINA_LIST_FREE(tokens1, token)
115      {
116         token->continues = EINA_FALSE;
117         line1->tokens = eina_list_append(line1->tokens, token);
118      }
119    EINA_LIST_FREE(tokens2, token)
120      {
121         token->start += length1;
122         token->end += length1;
123 
124         line1->tokens = eina_list_append(line1->tokens, token);
125      }
126 
127    elm_code_callback_fire(line1->file->parent, &ELM_CODE_EVENT_LINE_LOAD_DONE, line1);
128    free(newtext);
129 }
130 
131 EAPI void
elm_code_line_merge_up(Elm_Code_Line * line)132 elm_code_line_merge_up(Elm_Code_Line *line)
133 {
134    Elm_Code_Line *other;
135 
136    other = elm_code_file_line_get(line->file, line->number - 1);
137 
138    if (other)
139      _elm_code_line_merge_into(other, line);
140 }
141 
142 EAPI void
elm_code_line_merge_down(Elm_Code_Line * line)143 elm_code_line_merge_down(Elm_Code_Line *line)
144 {
145    Elm_Code_Line *other;
146 
147    other = elm_code_file_line_get(line->file, line->number + 1);
148 
149    if (other)
150      _elm_code_line_merge_into(line, other);
151 }
152 
elm_code_line_status_set(Elm_Code_Line * line,Elm_Code_Status_Type status)153 EAPI void elm_code_line_status_set(Elm_Code_Line *line, Elm_Code_Status_Type status)
154 {
155    if (!line)
156      return;
157 
158    line->status = status;
159 }
160 
elm_code_line_status_text_set(Elm_Code_Line * line,const char * text)161 EAPI void elm_code_line_status_text_set(Elm_Code_Line *line, const char *text)
162 {
163    if (line->status_text)
164      free(line->status_text);
165 
166    if (text)
167      line->status_text = strdup(text);
168    else
169      line->status_text = NULL;
170 }
171 
elm_code_line_token_add(Elm_Code_Line * line,int start,int end,int lines,Elm_Code_Token_Type type)172 EAPI void elm_code_line_token_add(Elm_Code_Line *line, int start, int end, int lines,
173                                   Elm_Code_Token_Type type)
174 {
175    Elm_Code_Token *tok;
176    Elm_Code_Line *next_line;
177 
178    if (!line)
179      return;
180 
181    tok = calloc(1, sizeof(Elm_Code_Token));
182    if (!tok) return;
183 
184    tok->start = start;
185    tok->end = end;
186    tok->continues = lines > 1;
187    tok->type = type;
188 
189    line->tokens = eina_list_append(line->tokens, tok);
190 
191    if (lines > 1)
192      {
193         next_line = elm_code_file_line_get(line->file, line->number + 1);
194         elm_code_line_token_add(next_line, 0, end, lines - 1, type);
195      }
196 }
197 
elm_code_line_tokens_clear(Elm_Code_Line * line)198 EAPI void elm_code_line_tokens_clear(Elm_Code_Line *line)
199 {
200    Elm_Code_Token *token;
201 
202    if (!line->tokens)
203      return;
204 
205    EINA_LIST_FREE(line->tokens, token)
206      free(token);
207    line->tokens = NULL;
208 }
209 
elm_code_line_status_clear(Elm_Code_Line * line)210 EAPI void elm_code_line_status_clear(Elm_Code_Line *line)
211 {
212    line->status = ELM_CODE_STATUS_TYPE_DEFAULT;
213    if (line->status_text)
214      {
215         free((char *)line->status_text);
216         line->status_text = NULL;
217      }
218 }
219 
220 EAPI Eina_Bool
elm_code_line_contains_widget_cursor(Elm_Code_Line * line)221 elm_code_line_contains_widget_cursor(Elm_Code_Line *line)
222 {
223    Elm_Code *code = line->file->parent;
224    Eina_List *item;
225    Eo *widget;
226    unsigned int col, number;
227 
228    if (!code)
229      return EINA_FALSE;
230 
231    EINA_LIST_FOREACH(code->widgets, item, widget)
232      {
233         elm_code_widget_cursor_position_get(widget, &number, &col);
234 
235         if (number == line->number)
236           return EINA_TRUE;
237      }
238 
239    return EINA_FALSE;
240 }
241