46 Widget parent = ct->prepare(ct, args, &n, TRUE); |
46 Widget parent = ct->prepare(ct, args, &n, TRUE); |
47 Widget text_area = XmCreateScrolledText(parent, "text_area", args, n); |
47 Widget text_area = XmCreateScrolledText(parent, "text_area", args, n); |
48 ct->add(ct, XtParent(text_area)); |
48 ct->add(ct, XtParent(text_area)); |
49 XtManageChild(text_area); |
49 XtManageChild(text_area); |
50 |
50 |
51 UiTextArea *uitext = ucx_mempool_malloc( |
51 UiTextArea *uitext = cxMalloc( |
52 obj->ctx->mempool, |
52 obj->ctx->allocator, |
53 sizeof(UiTextArea)); |
53 sizeof(UiTextArea)); |
54 uitext->ctx = obj->ctx; |
54 uitext->ctx = obj->ctx; |
55 uitext->last_selection_state = 0; |
55 uitext->last_selection_state = 0; |
56 XtAddCallback( |
56 XtAddCallback( |
57 text_area, |
57 text_area, |
190 |
190 |
191 |
191 |
192 UiUndoMgr* ui_create_undomgr() { |
192 UiUndoMgr* ui_create_undomgr() { |
193 UiUndoMgr *mgr = malloc(sizeof(UiUndoMgr)); |
193 UiUndoMgr *mgr = malloc(sizeof(UiUndoMgr)); |
194 mgr->begin = NULL; |
194 mgr->begin = NULL; |
|
195 mgr->end = NULL; |
195 mgr->cur = NULL; |
196 mgr->cur = NULL; |
196 mgr->length = 0; |
197 mgr->length = 0; |
197 mgr->event = 1; |
198 mgr->event = 1; |
198 return mgr; |
199 return mgr; |
|
200 } |
|
201 |
|
202 void ui_destroy_undomgr(UiUndoMgr *mgr) { |
|
203 UiTextBufOp *op = mgr->begin; |
|
204 while(op) { |
|
205 UiTextBufOp *nextOp = op->next; |
|
206 if(op->text) { |
|
207 free(op->text); |
|
208 } |
|
209 free(op); |
|
210 op = nextOp; |
|
211 } |
|
212 free(mgr); |
199 } |
213 } |
200 |
214 |
201 void ui_text_selection_callback( |
215 void ui_text_selection_callback( |
202 Widget widget, |
216 Widget widget, |
203 UiTextArea *textarea, |
217 UiTextArea *textarea, |
236 |
250 |
237 char *text = txv->text->ptr; |
251 char *text = txv->text->ptr; |
238 int length = txv->text->length; |
252 int length = txv->text->length; |
239 |
253 |
240 if(mgr->cur) { |
254 if(mgr->cur) { |
241 UcxList *elm = mgr->cur->next; |
255 UiTextBufOp *elm = mgr->cur->next; |
242 if(elm) { |
256 if(elm) { |
243 mgr->cur->next = NULL; |
257 mgr->cur->next = NULL; |
|
258 mgr->end = mgr->cur; |
244 while(elm) { |
259 while(elm) { |
245 elm->prev = NULL; |
260 elm->prev = NULL; |
246 UcxList *next = elm->next; |
261 UiTextBufOp *next = elm->next; |
247 ui_free_textbuf_op(elm->data); |
262 ui_free_textbuf_op(elm); |
248 free(elm); |
|
249 elm = next; |
263 elm = next; |
250 } |
264 } |
251 } |
265 } |
252 |
266 |
253 if(type == UI_TEXTBUF_INSERT) { |
267 UiTextBufOp *last_op = mgr->cur; |
254 UiTextBufOp *last_op = mgr->cur->data; |
268 if( |
255 if( |
269 last_op->type == UI_TEXTBUF_INSERT && |
256 last_op->type == UI_TEXTBUF_INSERT && |
270 ui_check_insertstr(last_op->text, last_op->len, text, length) == 0) |
257 ui_check_insertstr(last_op->text, last_op->len, text, length) == 0) |
271 { |
258 { |
272 // append text to last op |
259 // append text to last op |
273 int ln = last_op->len; |
260 int ln = last_op->len; |
274 char *newtext = malloc(ln + length + 1); |
261 char *newtext = malloc(ln + length + 1); |
275 memcpy(newtext, last_op->text, ln); |
262 memcpy(newtext, last_op->text, ln); |
276 memcpy(newtext+ln, text, length); |
263 memcpy(newtext+ln, text, length); |
277 newtext[ln+length] = '\0'; |
264 newtext[ln+length] = '\0'; |
278 |
265 |
279 last_op->text = newtext; |
266 last_op->text = newtext; |
280 last_op->len = ln + length; |
267 last_op->len = ln + length; |
281 last_op->end += length; |
268 last_op->end += length; |
282 |
269 |
283 return; |
270 return; |
|
271 } |
|
272 } |
284 } |
273 } |
285 } |
274 |
286 |
275 char *str; |
287 char *str; |
276 if(type == UI_TEXTBUF_INSERT) { |
288 if(type == UI_TEXTBUF_INSERT) { |
282 str = malloc(length + 1); |
294 str = malloc(length + 1); |
283 XmTextGetSubstring(value->obj, txv->startPos, length, length+1, str); |
295 XmTextGetSubstring(value->obj, txv->startPos, length, length+1, str); |
284 } |
296 } |
285 |
297 |
286 UiTextBufOp *op = malloc(sizeof(UiTextBufOp)); |
298 UiTextBufOp *op = malloc(sizeof(UiTextBufOp)); |
|
299 op->prev = NULL; |
|
300 op->next = NULL; |
287 op->type = type; |
301 op->type = type; |
288 op->start = txv->startPos; |
302 op->start = txv->startPos; |
289 op->end = txv->endPos + 1; |
303 op->end = txv->endPos + 1; |
290 op->len = length; |
304 op->len = length; |
291 op->text = str; |
305 op->text = str; |
292 |
306 |
293 UcxList *elm = ucx_list_append(NULL, op); |
307 cx_linked_list_add( |
294 mgr->cur = elm; |
308 (void**)&mgr->begin, |
295 mgr->begin = ucx_list_concat(mgr->begin, elm); |
309 (void**)&mgr->end, |
|
310 offsetof(UiTextBufOp, prev), |
|
311 offsetof(UiTextBufOp, next), |
|
312 op); |
|
313 |
|
314 mgr->cur = op; |
296 } |
315 } |
297 |
316 |
298 int ui_check_insertstr(char *oldstr, int oldlen, char *newstr, int newlen) { |
317 int ui_check_insertstr(char *oldstr, int oldlen, char *newstr, int newlen) { |
299 // return 1 if oldstr + newstr are one word |
318 // return 1 if oldstr + newstr are one word |
300 |
319 |
325 |
344 |
326 void ui_text_undo(UiText *value) { |
345 void ui_text_undo(UiText *value) { |
327 UiUndoMgr *mgr = value->undomgr; |
346 UiUndoMgr *mgr = value->undomgr; |
328 |
347 |
329 if(mgr->cur) { |
348 if(mgr->cur) { |
330 UiTextBufOp *op = mgr->cur->data; |
349 UiTextBufOp *op = mgr->cur; |
331 mgr->event = 0; |
350 mgr->event = 0; |
332 switch(op->type) { |
351 switch(op->type) { |
333 case UI_TEXTBUF_INSERT: { |
352 case UI_TEXTBUF_INSERT: { |
334 XmTextReplace(value->obj, op->start, op->end, ""); |
353 XmTextReplace(value->obj, op->start, op->end, ""); |
335 break; |
354 break; |
345 } |
364 } |
346 |
365 |
347 void ui_text_redo(UiText *value) { |
366 void ui_text_redo(UiText *value) { |
348 UiUndoMgr *mgr = value->undomgr; |
367 UiUndoMgr *mgr = value->undomgr; |
349 |
368 |
350 UcxList *elm = NULL; |
369 UiTextBufOp *elm = NULL; |
351 if(mgr->cur) { |
370 if(mgr->cur) { |
352 if(mgr->cur->next) { |
371 if(mgr->cur->next) { |
353 elm = mgr->cur->next; |
372 elm = mgr->cur->next; |
354 } |
373 } |
355 } else if(mgr->begin) { |
374 } else if(mgr->begin) { |
356 elm = mgr->begin; |
375 elm = mgr->begin; |
357 } |
376 } |
358 |
377 |
359 if(elm) { |
378 if(elm) { |
360 UiTextBufOp *op = elm->data; |
379 UiTextBufOp *op = elm; |
361 mgr->event = 0; |
380 mgr->event = 0; |
362 switch(op->type) { |
381 switch(op->type) { |
363 case UI_TEXTBUF_INSERT: { |
382 case UI_TEXTBUF_INSERT: { |
364 XmTextInsert(value->obj, op->start, op->text); |
383 XmTextInsert(value->obj, op->start, op->text); |
365 break; |
384 break; |