ui/gtk/text.c

changeset 6
05a18c56d9ca
parent 5
19d37cb9c96c
child 8
84a541c6e093
equal deleted inserted replaced
5:19d37cb9c96c 6:05a18c56d9ca
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 #include <stdio.h> 29 #include <stdio.h>
30 #include <stdlib.h> 30 #include <stdlib.h>
31 #include <string.h>
31 32
32 #include "text.h" 33 #include "text.h"
33 #include "container.h" 34 #include "container.h"
34 35
35 UIWIDGET ui_textarea(UiObject *obj, UiText *value) { 36 UIWIDGET ui_textarea(UiObject *obj, UiText *value) {
66 value->get = ui_textarea_get; 67 value->get = ui_textarea_get;
67 value->set = ui_textarea_set; 68 value->set = ui_textarea_set;
68 value->value = NULL; 69 value->value = NULL;
69 GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_area)); 70 GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_area));
70 value->obj = buf; 71 value->obj = buf;
72 if(!value->undomgr) {
73 value->undomgr = ui_create_undomgr();
74 }
71 75
72 // register undo manager 76 // register undo manager
73 g_signal_connect( 77 g_signal_connect(
74 buf, 78 buf,
75 "insert-text", 79 "insert-text",
76 G_CALLBACK(ui_textbuf_insert), 80 G_CALLBACK(ui_textbuf_insert),
77 NULL); 81 value);
78 g_signal_connect( 82 g_signal_connect(
79 buf, 83 buf,
80 "delete-range", 84 "delete-range",
81 G_CALLBACK(ui_textbuf_delete), 85 G_CALLBACK(ui_textbuf_delete),
82 NULL); 86 value);
83 } 87 }
84 88
85 return scroll_area; 89 return scroll_area;
86 } 90 }
87 91
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 }

mercurial