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