add separate textarea change events for before and after changes (GTK)

Sat, 30 May 2026 20:35:32 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 30 May 2026 20:35:32 +0200
changeset 1153
f15375e0480c
parent 1152
f560b35c8ca1
child 1154
8f44450932d5

add separate textarea change events for before and after changes (GTK)

ui/common/args.c file | annotate | diff | comparison | revisions
ui/common/args.h file | annotate | diff | comparison | revisions
ui/gtk/text.c file | annotate | diff | comparison | revisions
ui/gtk/text.h file | annotate | diff | comparison | revisions
ui/ui/text.h file | annotate | diff | comparison | revisions
--- a/ui/common/args.c	Fri May 29 22:43:47 2026 +0200
+++ b/ui/common/args.c	Sat May 30 20:35:32 2026 +0200
@@ -2227,8 +2227,20 @@
     args->onchangedata = onchangedata;
 }
 
-void ui_textarea_args_set_action(UiTextAreaArgs *args, const char *action) {
-    args->action = strdup(action);
+void ui_textarea_args_set_change_action(UiTextAreaArgs *args, const char *action) {
+    args->onchange_action = strdup(action);
+}
+
+void ui_textarea_args_set_ontextchanged(UiTextAreaArgs *args, ui_callback callback) {
+    args->ontextchanged = callback;
+}
+
+void ui_textarea_args_set_ontextchangeddata(UiTextAreaArgs *args, void *onchangedata) {
+    args->ontextchangeddata = onchangedata;
+}
+
+void ui_textarea_args_set_ontextchanged_action(UiTextAreaArgs *args, const char *action) {
+    args->ontextchanged_action = strdup(action);
 }
 
 void ui_textarea_args_set_varname(UiTextAreaArgs *args, const char *varname) {
@@ -2255,7 +2267,8 @@
     free((void*)args->name);
     free((void*)args->style_class);
     free((void*)args->varname);
-    free((void*)args->action);
+    free((void*)args->onchange_action);
+    free((void*)args->ontextchanged_action);
     free((void*)args->states);
     free((void*)args->visibility_states);
     free(args);
--- a/ui/common/args.h	Fri May 29 22:43:47 2026 +0200
+++ b/ui/common/args.h	Sat May 30 20:35:32 2026 +0200
@@ -520,7 +520,10 @@
 UIEXPORT void ui_textarea_args_set_style_class(UiTextAreaArgs *args, const char *classname);
 UIEXPORT void ui_textarea_args_set_onchange(UiTextAreaArgs *args, ui_callback callback);
 UIEXPORT void ui_textarea_args_set_onchangedata(UiTextAreaArgs *args, void *onchangedata);
-UIEXPORT void ui_textarea_args_set_action(UiTextAreaArgs *args, const char *action);
+UIEXPORT void ui_textarea_args_set_onchange_action(UiTextAreaArgs *args, const char *action);
+UIEXPORT void ui_textarea_args_set_ontextchanged(UiTextAreaArgs *args, ui_callback callback);
+UIEXPORT void ui_textarea_args_set_ontextchangeddata(UiTextAreaArgs *args, void *onchangedata);
+UIEXPORT void ui_textarea_args_set_ontextchanged_action(UiTextAreaArgs *args, const char *action);
 UIEXPORT void ui_textarea_args_set_varname(UiTextAreaArgs *args, const char *varname);
 UIEXPORT void ui_textarea_args_set_value(UiTextAreaArgs *args, UiText *value);
 UIEXPORT void ui_textarea_args_set_states(UiTextAreaArgs *args, int *states, int numstates);
--- a/ui/gtk/text.c	Fri May 29 22:43:47 2026 +0200
+++ b/ui/gtk/text.c	Sat May 30 20:35:32 2026 +0200
@@ -97,23 +97,21 @@
 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);
-        */
         
         g_signal_connect(
                 buf,
                 "insert-text",
-                G_CALLBACK(ui_textbuf_changed_insert),
+                G_CALLBACK(ui_textbuf_change_insert),
                 textarea);
         g_signal_connect(
                 buf,
                 "delete-range",
-                G_CALLBACK(ui_textbuf_changed_delete),
+                G_CALLBACK(ui_textbuf_change_delete),
                 textarea); 
     } else {
         fprintf(stderr, "Error: create_textbuffer: textarea == NULL\n");
@@ -142,7 +140,10 @@
     uitext->last_selection_state = 0;
     uitext->onchange = args->onchange;
     uitext->onchangedata = args->onchangedata;
-    uitext->action = args->action ? strdup(args->action) : NULL;
+    uitext->onchange_action = args->onchange_action ? strdup(args->onchange_action) : NULL;
+    uitext->ontextchanged = args->ontextchanged;
+    uitext->ontextchangeddata = args->ontextchangeddata;
+    uitext->ontextchanged_action = args->ontextchanged_action ? strdup(args->ontextchanged_action) : NULL;
     
     g_object_set_data(G_OBJECT(text_area), "ui_textarea", uitext);
     g_object_set_data(G_OBJECT(text_area), "ui_textarea_widget", text_area);
@@ -226,7 +227,8 @@
     if(textarea->var) {
         ui_destroy_boundvar(textarea->ctx, textarea->var);
     }
-    free(textarea->action);
+    free(textarea->onchange_action);
+    free(textarea->ontextchanged_action);
     free(textarea);
 }
 
@@ -463,47 +465,11 @@
 }
 
 
-void ui_textbuf_changed_insert(
-        GtkTextBuffer *textbuffer,
-        GtkTextIter *location,
-        char *text,
-        int length,
-        UiTextArea *textarea)
-{
-    UiTextChangeEventData event;
-    event.type = UI_TEXT_INSERT;
-    event.begin = gtk_text_iter_get_offset(location);
-    event.end = event.begin + length;
-    event.text = text;
-    event.length = length;
-    ui_textbuf_changed(textarea, &event);
-}
-
-void ui_textbuf_changed_delete(
-        GtkTextBuffer *self,
-        const GtkTextIter *start,
-        const GtkTextIter *end,
-        UiTextArea *textarea)
-{
-    UiTextChangeEventData event;
-    event.type = UI_TEXT_DELETE;
-    event.begin = gtk_text_iter_get_offset(start);
-    event.end = gtk_text_iter_get_offset(end);
-    event.text = NULL;
-    event.length = 0;
-    ui_textbuf_changed(textarea, &event);
-}
-
-
-// void ui_textbuf_changed(GtkTextBuffer *textbuffer, UiTextArea *textarea)
-
-void ui_textbuf_changed(UiTextArea *textarea, UiTextChangeEventData *data) {
+static void textbuf_change_event(UiTextArea *textarea, UiTextChangeEventData *data) {
     if(!ui_onchange_events_is_enabled()) {
         return;
     }
     
-    UiText *value = textarea->var->value;
-    
     UiEvent e;
     e.obj = textarea->obj;
     e.window = e.obj->window;
@@ -517,13 +483,70 @@
         textarea->onchange(&e, textarea->onchangedata);
     }
     
+    if(textarea->onchange_action) {
+        uic_action_callback(&e, textarea->onchange_action);
+    }
+}
+
+void ui_textbuf_change_insert(
+        GtkTextBuffer *textbuffer,
+        GtkTextIter *location,
+        char *text,
+        int length,
+        UiTextArea *textarea)
+{
+    UiTextChangeEventData event;
+    event.type = UI_TEXT_INSERT;
+    event.begin = gtk_text_iter_get_offset(location);
+    event.end = event.begin + length;
+    event.text = text;
+    event.length = length;
+    textbuf_change_event(textarea, &event);
+}
+
+void ui_textbuf_change_delete(
+        GtkTextBuffer *self,
+        const GtkTextIter *start,
+        const GtkTextIter *end,
+        UiTextArea *textarea)
+{
+    UiTextChangeEventData event;
+    event.type = UI_TEXT_DELETE;
+    event.begin = gtk_text_iter_get_offset(start);
+    event.end = gtk_text_iter_get_offset(end);
+    event.text = NULL;
+    event.length = 0;
+    textbuf_change_event(textarea, &event);
+}
+
+
+void ui_textbuf_changed(GtkTextBuffer *textbuffer, UiTextArea *textarea) {
+    if(!ui_onchange_events_is_enabled()) {
+        return;
+    }
+    
+    UiText *value = textarea->var->value;
+    
+    UiEvent e;
+    e.obj = textarea->obj;
+    e.window = e.obj->window;
+    e.document = textarea->ctx->document;
+    e.eventdata = value;
+    e.eventdatatype = UI_EVENT_DATA_TEXT_VALUE;
+    e.intval = 0;
+    e.set = ui_get_setop();
+    
+    if(textarea->ontextchanged) {
+        textarea->ontextchanged(&e, textarea->ontextchangeddata);
+    }
+    
+    if(textarea->ontextchanged_action) {
+        uic_action_callback(&e, textarea->ontextchanged_action);
+    }
+    
     if(value->observers) {
         ui_notify_evt(value->observers, &e);
     }
-    
-    if(textarea->action) {
-        uic_action_callback(&e, textarea->action);
-    }
 }
 
 // undo manager functions
--- a/ui/gtk/text.h	Fri May 29 22:43:47 2026 +0200
+++ b/ui/gtk/text.h	Sat May 30 20:35:32 2026 +0200
@@ -67,7 +67,10 @@
     int         last_selection_state;
     ui_callback onchange;
     void        *onchangedata;
-    char        *action;
+    char        *onchange_action;
+    ui_callback ontextchanged;
+    void        *ontextchangeddata;
+    char        *ontextchanged_action;
 } UiTextArea;
 
 typedef struct UiTextField {
@@ -132,18 +135,19 @@
 
 void ui_textarea_realize_event(GtkWidget *widget, gpointer data);
 //void ui_textbuf_changed(GtkTextBuffer *textbuffer, UiTextArea *textarea);
-void ui_textbuf_changed_insert(
+void ui_textbuf_change_insert(
         GtkTextBuffer *textbuffer,
         GtkTextIter *location,
         char *text,
         int length,
         UiTextArea *textarea);
-void ui_textbuf_changed_delete(
+void ui_textbuf_change_delete(
         GtkTextBuffer *self,
         const GtkTextIter *start,
         const GtkTextIter *end,
         UiTextArea *textarea);
-void ui_textbuf_changed(UiTextArea *textarea, UiTextChangeEventData *data);
+
+void ui_textbuf_changed(GtkTextBuffer *textbuffer, UiTextArea *textarea);
 
 void ui_textbuf_insert(
         GtkTextBuffer *textbuffer,
--- a/ui/ui/text.h	Fri May 29 22:43:47 2026 +0200
+++ b/ui/ui/text.h	Sat May 30 20:35:32 2026 +0200
@@ -58,7 +58,10 @@
     const char *varname;
     ui_callback onchange;
     void *onchangedata;
-    const char *action;
+    const char *onchange_action;
+    ui_callback ontextchanged;
+    void *ontextchangeddata;
+    const char *ontextchanged_action;
     
     const int *states;
     const int *visibility_states;

mercurial