]> uap-core.de Git - note.git/commitdiff
apply styles from previous char when inserting text main
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Sat, 7 Feb 2026 10:32:45 +0000 (11:32 +0100)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Sat, 7 Feb 2026 10:32:45 +0000 (11:32 +0100)
application/editor.h
application/gtk-text.c
application/gtk-text.h

index c2aba27cf06238b0b8bd65859bfb7cef8e46b9b3..c8fca31ca33c6e7421fd303604d1e76c9b0aa6d0 100644 (file)
@@ -49,10 +49,10 @@ extern "C" {
 #define EDITOR_STYLE_CODE_BLOCK "code_block"
 #define EDITOR_STYLE_LIST0      "ul0"
 #define EDITOR_STYLE_ORDLIST0   "ol0"
-#define EDITOR_STYLE_EMPHASIS   "emphasis"
-#define EDITOR_STYLE_STRONG     "strong"
-#define EDITOR_STYLE_CODE       "code"
-#define EDITOR_STYLE_LINK       "link"
+#define EDITOR_STYLE_EMPHASIS   "_emphasis"
+#define EDITOR_STYLE_STRONG     "_strong"
+#define EDITOR_STYLE_CODE       "_code"
+#define EDITOR_STYLE_LINK       "_link"
 
 #define MDDocStyleSection_IMAGE -1
 #define MDDocStyleSection_LIST  -2
index 266d334ef4a3fdb222bf17cacb656961ec22138f..caa68ec36464b9ac2a5567ab5bc6f5e9d919d15c 100644 (file)
@@ -73,6 +73,13 @@ static void editor_delete_range_cb(
         const GtkTextIter *end,
         NoteEditor *editor);
 
+static void edit_insert_text_cb(
+        GtkTextBuffer *buffer,
+        const GtkTextIter *location,
+        gchar *text,
+        gint len,
+        NoteEditor *editor);
+
 #if GTK_CHECK_VERSION(4, 0, 0)
 static void editor_button_released_cb(
         GtkGestureClick *gesture,
@@ -180,6 +187,13 @@ void editor_init_textview(UiObject *obj, UIWIDGET textview) {
     
 }
 
+static void editor_reset_tmp_styles(NoteEditor *editor) {
+    editor->disable_bold = FALSE;
+    editor->disable_underline = FALSE;
+    editor->disable_italic = FALSE;
+    editor->disable_code = FALSE;
+}
+
 static void editor_resize(NoteEditor *editor) {
     editor_update_width(editor);
 }
@@ -198,6 +212,7 @@ static void update_cursor_paragraph_style(NoteEditor *editor, GtkTextBuffer *buf
     } else {
         GtkTextMark *mark = gtk_text_buffer_get_insert(buffer);
         gtk_text_buffer_get_iter_at_mark(buffer, &pos, mark);
+        gtk_text_iter_backward_char(&pos);
     }
     
     MDActiveStyles styles = { 0 };
@@ -210,11 +225,14 @@ static void update_cursor_paragraph_style(NoteEditor *editor, GtkTextBuffer *buf
         }
         tags = tags->next;
     }
+    g_slist_free(tags);
     
     NoteModel *note = notemodel_current(editor->obj);
     if(note) {
         note_update_current_style(note, &styles);
     }
+    
+    editor_reset_tmp_styles(editor);
 }
 
 
@@ -256,6 +274,7 @@ static void editor_set_buffer_cb(
     }
     
     editor_update_width(editor);
+    editor_reset_tmp_styles(editor);
 }
 
 static void em_remove_anchor(BufferEmbeddedObjects *em, GtkTextChildAnchor *anchor) {
@@ -281,6 +300,52 @@ static void editor_delete_range_cb(
     
 }
 
+static void edit_insert_text_cb(
+        GtkTextBuffer *buffer,
+        const GtkTextIter *location,
+        gchar *text,
+        gint len,
+        NoteEditor *editor)
+{
+    GtkTextIter begin = *location;
+    GtkTextIter end = begin;
+    
+    if(!gtk_text_iter_backward_chars(&begin, len)) {
+        return; // should not happen
+    }
+    
+    GtkTextIter prev = begin;
+    if(gtk_text_iter_backward_char(&prev)) {  
+        // a previous position exists, apply tags from it
+        GSList *tags = gtk_text_iter_get_tags(&prev);
+        while(tags) {
+            GtkTextTag *tag = tags->data;
+            GValue name_value = G_VALUE_INIT;
+            g_object_get_property(G_OBJECT(tag), "name", &name_value);
+            const char *name = g_value_get_string(&name_value);
+            //printf("apply tag: %s\n", name);
+            if(name && name[0] == '_') {
+                // non-paragraph styles start with an underscore
+                // we don't need to apply paragraph styles, the inserted
+                // text will already be inside the paragraph bounds
+                
+                // check if the style is temporarily disabled
+                gboolean style_disabled = 
+                        (editor->disable_bold && !strcmp(name, EDITOR_STYLE_STRONG)) ||
+                        (editor->disable_italic && !strcmp(name, EDITOR_STYLE_EMPHASIS)) ||
+                        (editor->disable_code && !strcmp(name, EDITOR_STYLE_CODE));     
+                if(!style_disabled) {
+                    gtk_text_buffer_apply_tag(buffer, tags->data, &begin, &end);
+                }
+            }
+            g_value_unset(&name_value);
+            
+            tags = tags->next;
+        }
+        g_slist_free(tags);
+    }
+}
+
 static gboolean path_is_image_file(cxstring path) {
     if(path.length == 0) {
         return FALSE;
@@ -621,6 +686,7 @@ void editor_try_follow_link(NoteEditor *editor, GtkTextIter *pos) {
         }
         tags = tags->next;
     }
+    g_slist_free(tags);
 }
 
 void editor_update_embedded_widgets(NoteEditor *editor) {
@@ -674,6 +740,7 @@ void editor_init_textbuf(UiText *text) {
     if(editor) {
         g_signal_connect(buf, "mark-set", G_CALLBACK(editor_set_cursor_cb), editor);
         g_signal_connect(buf, "delete-range", G_CALLBACK(editor_delete_range_cb), editor);
+        g_signal_connect_after(buf, "insert-text", G_CALLBACK(edit_insert_text_cb), editor);
     }
     
     BufferEmbeddedObjects *embedded_objects = malloc(sizeof(BufferEmbeddedObjects));
@@ -1073,9 +1140,22 @@ UiBool editor_set_style(UiText *text, const char *style, UiBool enabled) {
         fprintf(stderr, "Error: editor_set_style: no text buffer\n");
         return FALSE;
     }
+    NoteEditor *editor = g_object_get_data(text->obj, "editor");
+    if(!editor) {
+        fprintf(stderr, "Error: editor_set_style: no editor\n");
+        return FALSE;
+    }
     
     if(!gtk_text_buffer_get_has_selection(buffer)) {
-        return FALSE;
+        if(!strcmp(style, EDITOR_STYLE_STRONG)) {
+            editor->disable_bold = !enabled;
+        } else if(!strcmp(style, EDITOR_STYLE_EMPHASIS)) {
+            editor->disable_italic = !enabled;
+        } else if(!strcmp(style, EDITOR_STYLE_CODE)) {
+            editor->disable_code = !enabled;
+        }
+        gtk_widget_grab_focus(editor->textview);
+        return TRUE;
     }
     GtkTextIter begin, end;
     gtk_text_buffer_get_selection_bounds(buffer, &begin, &end);
@@ -1090,7 +1170,7 @@ UiBool editor_set_style(UiText *text, const char *style, UiBool enabled) {
             fprintf(stderr, "Error: tag %s not found\n", style);
         }
     }
-    
+    gtk_widget_grab_focus(editor->textview);
     return TRUE;
 }
 
index 503c633ebd790bab19eecbf517d85199692c3885..c62b8c80d4165c3f320f103d69b44be225c39d3d 100644 (file)
@@ -42,6 +42,10 @@ typedef struct NoteEditor {
     UiObject *obj;
     GtkWidget *textview;
     int width;
+    gboolean disable_bold;
+    gboolean disable_italic;
+    gboolean disable_underline;
+    gboolean disable_code;
 } NoteEditor;
     
 typedef struct MDTag {