302 if(!mgr->event) { |
304 if(!mgr->event) { |
303 return; |
305 return; |
304 } |
306 } |
305 |
307 |
306 if(mgr->cur) { |
308 if(mgr->cur) { |
307 UcxList *elm = mgr->cur->next; |
309 UiTextBufOp *elm = mgr->cur->next; |
308 if(elm) { |
310 if(elm) { |
309 mgr->cur->next = NULL; |
311 mgr->cur->next = NULL; |
|
312 mgr->end = mgr->cur; |
310 while(elm) { |
313 while(elm) { |
311 elm->prev = NULL; |
314 elm->prev = NULL; |
312 UcxList *next = elm->next; |
315 UiTextBufOp *next = elm->next; |
313 ui_free_textbuf_op(elm->data); |
316 ui_free_textbuf_op(elm); |
314 free(elm); |
|
315 elm = next; |
317 elm = next; |
316 } |
318 } |
317 } |
319 } |
318 |
320 |
319 UiTextBufOp *last_op = mgr->cur->data; |
321 UiTextBufOp *last_op = mgr->cur; |
320 if( |
322 if( |
321 last_op->type == UI_TEXTBUF_INSERT && |
323 last_op->type == UI_TEXTBUF_INSERT && |
322 ui_check_insertstr(last_op->text, last_op->len, text, length) == 0) |
324 ui_check_insertstr(last_op->text, last_op->len, text, length) == 0) |
323 { |
325 { |
324 // append text to last op |
326 // append text to last op |
339 char *dpstr = malloc(length + 1); |
341 char *dpstr = malloc(length + 1); |
340 memcpy(dpstr, text, length); |
342 memcpy(dpstr, text, length); |
341 dpstr[length] = 0; |
343 dpstr[length] = 0; |
342 |
344 |
343 UiTextBufOp *op = malloc(sizeof(UiTextBufOp)); |
345 UiTextBufOp *op = malloc(sizeof(UiTextBufOp)); |
|
346 op->prev = NULL; |
|
347 op->next = NULL; |
344 op->type = UI_TEXTBUF_INSERT; |
348 op->type = UI_TEXTBUF_INSERT; |
345 op->start = gtk_text_iter_get_offset(location); |
349 op->start = gtk_text_iter_get_offset(location); |
346 op->end = op->start+length; |
350 op->end = op->start+length; |
347 op->len = length; |
351 op->len = length; |
348 op->text = dpstr; |
352 op->text = dpstr; |
349 |
353 |
350 UcxList *elm = ucx_list_append(NULL, op); |
354 cx_linked_list_add( |
351 mgr->cur = elm; |
355 (void**)&mgr->begin, |
352 mgr->begin = ucx_list_concat(mgr->begin, elm); |
356 (void**)&mgr->end, |
|
357 offsetof(UiTextBufOp, prev), |
|
358 offsetof(UiTextBufOp, next), |
|
359 op); |
|
360 |
|
361 mgr->cur = op; |
353 } |
362 } |
354 |
363 |
355 void ui_textbuf_delete( |
364 void ui_textbuf_delete( |
356 GtkTextBuffer *textbuffer, |
365 GtkTextBuffer *textbuffer, |
357 GtkTextIter *start, |
366 GtkTextIter *start, |
367 if(!mgr->event) { |
376 if(!mgr->event) { |
368 return; |
377 return; |
369 } |
378 } |
370 |
379 |
371 if(mgr->cur) { |
380 if(mgr->cur) { |
372 UcxList *elm = mgr->cur->next; |
381 UiTextBufOp *elm = mgr->cur->next; |
373 if(elm) { |
382 if(elm) { |
374 mgr->cur->next = NULL; |
383 mgr->cur->next = NULL; |
|
384 mgr->end = mgr->cur; |
375 while(elm) { |
385 while(elm) { |
376 elm->prev = NULL; |
386 elm->prev = NULL; |
377 UcxList *next = elm->next; |
387 UiTextBufOp *next = elm->next; |
378 ui_free_textbuf_op(elm->data); |
388 ui_free_textbuf_op(elm); |
379 free(elm); |
|
380 elm = next; |
389 elm = next; |
381 } |
390 } |
382 } |
391 } |
383 } |
392 } |
384 |
393 |
385 char *text = gtk_text_buffer_get_text(value->obj, start, end, FALSE); |
394 char *text = gtk_text_buffer_get_text(value->obj, start, end, FALSE); |
386 |
395 |
387 UiTextBufOp *op = malloc(sizeof(UiTextBufOp)); |
396 UiTextBufOp *op = malloc(sizeof(UiTextBufOp)); |
|
397 op->prev = NULL; |
|
398 op->next = NULL; |
388 op->type = UI_TEXTBUF_DELETE; |
399 op->type = UI_TEXTBUF_DELETE; |
389 op->start = gtk_text_iter_get_offset(start); |
400 op->start = gtk_text_iter_get_offset(start); |
390 op->end = gtk_text_iter_get_offset(end); |
401 op->end = gtk_text_iter_get_offset(end); |
391 op->len = op->end - op->start; |
402 op->len = op->end - op->start; |
392 |
403 |
393 char *dpstr = malloc(op->len + 1); |
404 char *dpstr = malloc(op->len + 1); |
394 memcpy(dpstr, text, op->len); |
405 memcpy(dpstr, text, op->len); |
395 dpstr[op->len] = 0; |
406 dpstr[op->len] = 0; |
396 op->text = dpstr; |
407 op->text = dpstr; |
397 |
408 |
398 UcxList *elm = ucx_list_append(NULL, op); |
409 cx_linked_list_add( |
399 mgr->cur = elm; |
410 (void**)&mgr->begin, |
400 mgr->begin = ucx_list_concat(mgr->begin, elm); |
411 (void**)&mgr->end, |
|
412 offsetof(UiTextBufOp, prev), |
|
413 offsetof(UiTextBufOp, next), |
|
414 op); |
|
415 |
|
416 mgr->cur = op; |
401 } |
417 } |
402 |
418 |
403 UiUndoMgr* ui_create_undomgr() { |
419 UiUndoMgr* ui_create_undomgr() { |
404 UiUndoMgr *mgr = malloc(sizeof(UiUndoMgr)); |
420 UiUndoMgr *mgr = malloc(sizeof(UiUndoMgr)); |
405 mgr->begin = NULL; |
421 mgr->begin = NULL; |
|
422 mgr->end = NULL; |
406 mgr->cur = NULL; |
423 mgr->cur = NULL; |
407 mgr->length = 0; |
424 mgr->length = 0; |
408 mgr->event = 1; |
425 mgr->event = 1; |
409 return mgr; |
426 return mgr; |
|
427 } |
|
428 |
|
429 void ui_destroy_undomgr(UiUndoMgr *mgr) { |
|
430 UiTextBufOp *op = mgr->begin; |
|
431 while(op) { |
|
432 UiTextBufOp *nextOp = op->next; |
|
433 if(op->text) { |
|
434 free(op->text); |
|
435 } |
|
436 free(op); |
|
437 op = nextOp; |
|
438 } |
|
439 free(mgr); |
410 } |
440 } |
411 |
441 |
412 void ui_free_textbuf_op(UiTextBufOp *op) { |
442 void ui_free_textbuf_op(UiTextBufOp *op) { |
413 if(op->text) { |
443 if(op->text) { |
414 free(op->text); |
444 free(op->text); |
466 } |
496 } |
467 |
497 |
468 void ui_text_redo(UiText *value) { |
498 void ui_text_redo(UiText *value) { |
469 UiUndoMgr *mgr = value->undomgr; |
499 UiUndoMgr *mgr = value->undomgr; |
470 |
500 |
471 UcxList *elm = NULL; |
501 UiTextBufOp *elm = NULL; |
472 if(mgr->cur) { |
502 if(mgr->cur) { |
473 if(mgr->cur->next) { |
503 if(mgr->cur->next) { |
474 elm = mgr->cur->next; |
504 elm = mgr->cur->next; |
475 } |
505 } |
476 } else if(mgr->begin) { |
506 } else if(mgr->begin) { |
477 elm = mgr->begin; |
507 elm = mgr->begin; |
478 } |
508 } |
479 |
509 |
480 if(elm) { |
510 if(elm) { |
481 UiTextBufOp *op = elm->data; |
511 UiTextBufOp *op = elm; |
482 mgr->event = 0; |
512 mgr->event = 0; |
483 switch(op->type) { |
513 switch(op->type) { |
484 case UI_TEXTBUF_INSERT: { |
514 case UI_TEXTBUF_INSERT: { |
485 GtkTextIter begin; |
515 GtkTextIter begin; |
486 GtkTextIter end; |
516 GtkTextIter end; |
578 return create_textfield_var(obj, width, frameless, password, var); |
608 return create_textfield_var(obj, width, frameless, password, var); |
579 } |
609 } |
580 |
610 |
581 void ui_textfield_destroy(GtkWidget *object, UiTextField *textfield) { |
611 void ui_textfield_destroy(GtkWidget *object, UiTextField *textfield) { |
582 if(textfield->var) { |
612 if(textfield->var) { |
|
613 UiText *text = textfield->var->value; |
|
614 if(text->undomgr) { |
|
615 ui_destroy_undomgr(text->undomgr); |
|
616 } |
583 ui_destroy_boundvar(textfield->ctx, textfield->var); |
617 ui_destroy_boundvar(textfield->ctx, textfield->var); |
584 } |
618 } |
585 free(textfield); |
619 free(textfield); |
586 } |
620 } |
587 |
621 |