108 |
112 |
109 void ui_textarea_realize_event(GtkWidget *widget, gpointer data) { |
113 void ui_textarea_realize_event(GtkWidget *widget, gpointer data) { |
110 gtk_widget_grab_focus(widget); |
114 gtk_widget_grab_focus(widget); |
111 } |
115 } |
112 |
116 |
|
117 |
|
118 // undo manager functions |
|
119 |
113 void ui_textbuf_insert( |
120 void ui_textbuf_insert( |
114 GtkTextBuffer *textbuffer, |
121 GtkTextBuffer *textbuffer, |
115 GtkTextIter *location, |
122 GtkTextIter *location, |
116 char *text, |
123 char *text, |
117 int len, |
124 int length, |
118 void *data) |
125 void *data) |
119 { |
126 { |
120 //TODO |
127 UiText *value = data; |
|
128 UiUndoMgr *mgr = value->undomgr; |
|
129 if(!mgr->event) { |
|
130 return; |
|
131 } |
|
132 |
|
133 printf("insert\n"); |
|
134 if(mgr->cur) { |
|
135 UcxList *elm = mgr->cur->next; |
|
136 while(elm) { |
|
137 ui_free_textbuf_op(elm->data); |
|
138 UcxList *next = elm->next; |
|
139 ucx_list_remove(mgr->begin, elm); |
|
140 elm = next; |
|
141 } |
|
142 |
|
143 UiTextBufOp *last_op = mgr->cur->data; |
|
144 if(ui_check_insertstr(last_op->text, last_op->len, text, length) == 0) { |
|
145 // append text to last op |
|
146 int ln = last_op->len; |
|
147 char *newtext = malloc(ln + length + 1); |
|
148 memcpy(newtext, last_op->text, ln); |
|
149 memcpy(newtext+ln, text, length); |
|
150 newtext[ln+length] = '\0'; |
|
151 |
|
152 last_op->text = newtext; |
|
153 last_op->len = ln + length; |
|
154 last_op->end += length; |
|
155 |
|
156 return; |
|
157 } |
|
158 } |
|
159 |
|
160 char *dpstr = malloc(length + 1); |
|
161 memcpy(dpstr, text, length); |
|
162 dpstr[length] = 0; |
|
163 |
|
164 UiTextBufOp *op = malloc(sizeof(UiTextBufOp)); |
|
165 op->type = UI_TEXTBUF_INSERT; |
|
166 op->start = gtk_text_iter_get_offset(location); |
|
167 op->end = op->start+length; |
|
168 op->len = length; |
|
169 op->text = dpstr; |
|
170 |
|
171 UcxList *elm = ucx_list_append(NULL, op); |
|
172 mgr->cur = elm; |
|
173 mgr->begin = ucx_list_concat(mgr->begin, elm); |
121 } |
174 } |
122 |
175 |
123 void ui_textbuf_delete( |
176 void ui_textbuf_delete( |
124 GtkTextBuffer *textbuffer, |
177 GtkTextBuffer *textbuffer, |
125 GtkTextIter *start, |
178 GtkTextIter *start, |
126 GtkTextIter *end, |
179 GtkTextIter *end, |
127 void *data) |
180 void *data) |
128 { |
181 { |
129 //TODO |
182 UiText *value = data; |
130 } |
183 UiUndoMgr *mgr = value->undomgr; |
|
184 if(!mgr->event) { |
|
185 return; |
|
186 } |
|
187 |
|
188 printf("delete\n"); |
|
189 if(mgr->cur) { |
|
190 UcxList *elm = mgr->cur->next; |
|
191 while(elm) { |
|
192 ui_free_textbuf_op(elm->data); |
|
193 UcxList *next = elm->next; |
|
194 ucx_list_remove(mgr->begin, elm); |
|
195 elm = next; |
|
196 } |
|
197 } |
|
198 |
|
199 char *text = gtk_text_buffer_get_text(value->obj, start, end, FALSE); |
|
200 |
|
201 UiTextBufOp *op = malloc(sizeof(UiTextBufOp)); |
|
202 op->type = UI_TEXTBUF_DELETE; |
|
203 op->start = gtk_text_iter_get_offset(start); |
|
204 op->end = gtk_text_iter_get_offset(end); |
|
205 op->len = op->end - op->start; |
|
206 |
|
207 char *dpstr = malloc(op->len + 1); |
|
208 memcpy(dpstr, text, op->len); |
|
209 dpstr[op->len] = 0; |
|
210 op->text = dpstr; |
|
211 |
|
212 UcxList *elm = ucx_list_append(NULL, op); |
|
213 mgr->cur = elm; |
|
214 mgr->begin = ucx_list_concat(mgr->begin, elm); |
|
215 } |
|
216 |
|
217 UiUndoMgr* ui_create_undomgr() { |
|
218 UiUndoMgr *mgr = malloc(sizeof(UiUndoMgr)); |
|
219 mgr->begin = NULL; |
|
220 mgr->cur = NULL; |
|
221 mgr->length = 0; |
|
222 mgr->event = 1; |
|
223 return mgr; |
|
224 } |
|
225 |
|
226 void ui_free_textbuf_op(UiTextBufOp *op) { |
|
227 if(op->text) { |
|
228 g_free(op->text); |
|
229 } |
|
230 free(op); |
|
231 } |
|
232 |
|
233 int ui_check_insertstr(char *oldstr, int oldlen, char *newstr, int newlen) { |
|
234 // return 1 if oldstr + newstr are one word |
|
235 |
|
236 int has_space = 0; |
|
237 for(int i=0;i<oldlen;i++) { |
|
238 if(oldstr[i] < 33) { |
|
239 has_space = 1; |
|
240 break; |
|
241 } |
|
242 } |
|
243 |
|
244 for(int i=0;i<newlen;i++) { |
|
245 if(has_space && newstr[i] > 32) { |
|
246 return 1; |
|
247 } |
|
248 } |
|
249 |
|
250 return 0; |
|
251 } |
|
252 |
|
253 void ui_text_undo(UiText *value) { |
|
254 UiUndoMgr *mgr = value->undomgr; |
|
255 |
|
256 if(mgr->cur) { |
|
257 UiTextBufOp *op = mgr->cur->data; |
|
258 mgr->event = 0; |
|
259 switch(op->type) { |
|
260 case UI_TEXTBUF_INSERT: { |
|
261 GtkTextIter begin; |
|
262 GtkTextIter end; |
|
263 gtk_text_buffer_get_iter_at_offset(value->obj, &begin, op->start); |
|
264 gtk_text_buffer_get_iter_at_offset(value->obj, &end, op->end); |
|
265 gtk_text_buffer_delete(value->obj, &begin, &end); |
|
266 break; |
|
267 } |
|
268 case UI_TEXTBUF_DELETE: { |
|
269 GtkTextIter begin; |
|
270 GtkTextIter end; |
|
271 gtk_text_buffer_get_iter_at_offset(value->obj, &begin, op->start); |
|
272 gtk_text_buffer_get_iter_at_offset(value->obj, &end, op->end); |
|
273 gtk_text_buffer_insert(value->obj, &begin, op->text, op->len); |
|
274 break; |
|
275 } |
|
276 } |
|
277 mgr->event = 1; |
|
278 mgr->cur = mgr->cur->prev; |
|
279 } |
|
280 } |
|
281 |
|
282 void ui_text_redo(UiText *value) { |
|
283 |
|
284 } |