--- a/ui/gtk/text.c Tue Feb 25 21:11:00 2025 +0100 +++ b/ui/gtk/text.c Sat Apr 05 16:46:11 2025 +0200 @@ -62,6 +62,51 @@ } } +static void textarea_set_text_funcs(UiText *value) { + +} + +#if GTK_MAJOR_VERSION == 2 +static void textarea_set_undomgr(GtkWidget *text_area, UiText *value) { + GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_area)); + + if(!value->data2) { + value->data2 = ui_create_undomgr(); + } + + // register undo manager + g_signal_connect( + buf, + "insert-text", + G_CALLBACK(ui_textbuf_insert), + var); + g_signal_connect( + buf, + "delete-range", + G_CALLBACK(ui_textbuf_delete), + var); + g_signal_connect( + buf, + "mark-set", + G_CALLBACK(selection_handler), + uitext); +} +#endif + +static GtkTextBuffer* create_textbuffer(UiTextArea *textarea) { + GtkTextBuffer *buf = gtk_text_buffer_new(NULL); + if(textarea) { + g_signal_connect( + buf, + "changed", + G_CALLBACK(ui_textbuf_changed), + textarea); + } else { + fprintf(stderr, "Error: create_textbuffer: textarea == NULL\n"); + } + return buf; +} + UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs args) { UiObject* current = uic_current_obj(obj); UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_TEXT); @@ -85,6 +130,8 @@ uitext->onchange = args.onchange; uitext->onchangedata = args.onchangedata; + g_object_set_data(G_OBJECT(text_area), "ui_textarea", uitext); + g_signal_connect( text_area, "destroy", @@ -114,13 +161,21 @@ // bind value if(var) { UiText *value = var->value; - GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_area)); - - if(value->value.ptr) { - gtk_text_buffer_set_text(buf, value->value.ptr, -1); - value->value.free(value->value.ptr); + GtkTextBuffer *buf; + if(value->data1 && value->datatype == UI_TEXT_TYPE_BUFFER) { + buf = value->data1; + } else { + buf = create_textbuffer(uitext); + if(value->value.ptr) { + gtk_text_buffer_set_text(buf, value->value.ptr, -1); + value->value.free(value->value.ptr); + } } - + gtk_text_view_set_buffer(GTK_TEXT_VIEW(text_area), buf); + value->obj = text_area; + value->save = ui_textarea_save; + value->restore = ui_textarea_restore; + value->destroy = ui_textarea_text_destroy; value->get = ui_textarea_get; value->set = ui_textarea_set; value->getsubstr = ui_textarea_getsubstr; @@ -130,35 +185,15 @@ value->selection = ui_textarea_selection; value->length = ui_textarea_length; value->remove = ui_textarea_remove; + value->data1 = buf; + value->data2 = NULL; + value->datatype == UI_TEXT_TYPE_BUFFER; value->value.ptr = NULL; value->value.free = NULL; - value->obj = buf; - if(!value->undomgr) { - value->undomgr = ui_create_undomgr(); - } - g_signal_connect( - buf, - "changed", - G_CALLBACK(ui_textbuf_changed), - uitext); - - // register undo manager - g_signal_connect( - buf, - "insert-text", - G_CALLBACK(ui_textbuf_insert), - var); - g_signal_connect( - buf, - "delete-range", - G_CALLBACK(ui_textbuf_delete), - var); - g_signal_connect( - buf, - "mark-set", - G_CALLBACK(selection_handler), - uitext); +#if GTK_MAJOR_VERSION == 2 + textarea_set_undomgr(text_area, value); +#endif } return scroll_area; @@ -175,11 +210,29 @@ return SCROLLEDWINDOW_GET_CHILD(textarea); } +void ui_textarea_save(UiText *text) { + // NOOP +} + +void ui_textarea_restore(UiText *text) { + GtkWidget *textarea = text->obj; + if(!text->data1) { + text->data1 = create_textbuffer(g_object_get_data(G_OBJECT(textarea), "ui_textarea")); + text->datatype = UI_TEXT_TYPE_BUFFER; + } + gtk_text_view_set_buffer(GTK_TEXT_VIEW(textarea), text->data1); +} + +void ui_textarea_text_destroy(UiText *text) { + GtkTextBuffer *buf = text->data1; + g_object_unref(buf); +} + char* ui_textarea_get(UiText *text) { if(text->value.ptr) { text->value.free(text->value.ptr); } - GtkTextBuffer *buf = text->obj; + GtkTextBuffer *buf = text->data1; GtkTextIter start; GtkTextIter end; gtk_text_buffer_get_bounds(buf, &start, &end); @@ -190,7 +243,7 @@ } void ui_textarea_set(UiText *text, const char *str) { - gtk_text_buffer_set_text((GtkTextBuffer*)text->obj, str, -1); + gtk_text_buffer_set_text((GtkTextBuffer*)text->data1, str, -1); if(text->value.ptr) { text->value.free(text->value.ptr); } @@ -202,11 +255,11 @@ if(text->value.ptr) { text->value.free(text->value.ptr); } - GtkTextBuffer *buf = text->obj; + GtkTextBuffer *buf = text->data1; GtkTextIter ib; GtkTextIter ie; - gtk_text_buffer_get_iter_at_offset(text->obj, &ib, begin); - gtk_text_buffer_get_iter_at_offset(text->obj, &ie, end); + gtk_text_buffer_get_iter_at_offset(text->data1, &ib, begin); + gtk_text_buffer_get_iter_at_offset(text->data1, &ie, end); char *str = gtk_text_buffer_get_text(buf, &ib, &ie, FALSE); text->value.ptr = g_strdup(str); text->value.free = (ui_freefunc)g_free; @@ -215,8 +268,8 @@ void ui_textarea_insert(UiText *text, int pos, char *str) { GtkTextIter offset; - gtk_text_buffer_get_iter_at_offset(text->obj, &offset, pos); - gtk_text_buffer_insert(text->obj, &offset, str, -1); + gtk_text_buffer_get_iter_at_offset(text->data1, &offset, pos); + gtk_text_buffer_insert(text->data1, &offset, str, -1); if(text->value.ptr) { text->value.free(text->value.ptr); } @@ -226,14 +279,14 @@ void ui_textarea_setposition(UiText *text, int pos) { GtkTextIter iter; - gtk_text_buffer_get_iter_at_offset(text->obj, &iter, pos); - gtk_text_buffer_place_cursor(text->obj, &iter); + gtk_text_buffer_get_iter_at_offset(text->data1, &iter, pos); + gtk_text_buffer_place_cursor(text->data1, &iter); } int ui_textarea_position(UiText *text) { GtkTextIter begin; GtkTextIter end; - gtk_text_buffer_get_selection_bounds(text->obj, &begin, &end); + gtk_text_buffer_get_selection_bounds(text->data1, &begin, &end); text->pos = gtk_text_iter_get_offset(&begin); return text->pos; } @@ -241,13 +294,13 @@ void ui_textarea_selection(UiText *text, int *begin, int *end) { GtkTextIter b; GtkTextIter e; - gtk_text_buffer_get_selection_bounds(text->obj, &b, &e); + gtk_text_buffer_get_selection_bounds(text->data1, &b, &e); *begin = gtk_text_iter_get_offset(&b); *end = gtk_text_iter_get_offset(&e); } int ui_textarea_length(UiText *text) { - GtkTextBuffer *buf = text->obj; + GtkTextBuffer *buf = text->data1; GtkTextIter start; GtkTextIter end; gtk_text_buffer_get_bounds(buf, &start, &end); @@ -255,7 +308,7 @@ } void ui_textarea_remove(UiText *text, int begin, int end) { - GtkTextBuffer *buf = text->obj; + GtkTextBuffer *buf = text->data1; GtkTextIter ib; GtkTextIter ie; gtk_text_buffer_get_iter_at_offset(buf, &ib, begin); @@ -278,6 +331,7 @@ e.document = textarea->ctx->document; e.eventdata = value; e.intval = 0; + e.set = ui_get_setop(); if(textarea->onchange) { textarea->onchange(&e, textarea->onchangedata); @@ -299,10 +353,10 @@ { UiVar *var = data; UiText *value = var->value; - if(!value->undomgr) { - value->undomgr = ui_create_undomgr(); + if(!value->data2) { + value->data2 = ui_create_undomgr(); } - UiUndoMgr *mgr = value->undomgr; + UiUndoMgr *mgr = value->data2; if(!mgr->event) { return; } @@ -371,10 +425,10 @@ { UiVar *var = data; UiText *value = var->value; - if(!value->undomgr) { - value->undomgr = ui_create_undomgr(); + if(!value->data2) { + value->data2 = ui_create_undomgr(); } - UiUndoMgr *mgr = value->undomgr; + UiUndoMgr *mgr = value->data2; if(!mgr->event) { return; } @@ -469,7 +523,7 @@ } void ui_text_undo(UiText *value) { - UiUndoMgr *mgr = value->undomgr; + UiUndoMgr *mgr = value->data2; if(mgr->cur) { UiTextBufOp *op = mgr->cur; @@ -498,7 +552,7 @@ } void ui_text_redo(UiText *value) { - UiUndoMgr *mgr = value->undomgr; + UiUndoMgr *mgr = value->data2; UiTextBufOp *elm = NULL; if(mgr->cur) { @@ -638,6 +692,7 @@ e.document = textfield->obj->ctx->document; e.eventdata = value; e.intval = 0; + e.set = ui_get_setop(); if(textfield->onchange) { textfield->onchange(&e, textfield->onchangedata); @@ -656,6 +711,7 @@ e.document = textfield->obj->ctx->document; e.eventdata = NULL; e.intval = 0; + e.set = ui_get_setop(); textfield->onactivate(&e, textfield->onactivatedata); } } @@ -752,6 +808,7 @@ evt.document = evt.obj->ctx->document; evt.eventdata = elm->path; evt.intval = event->value0; + evt.set = ui_get_setop(); event->callback(&evt, event->userdata); free(path.ptr); }