From c44e95eb6d156978b568c504b08e6093b079ad79 Mon Sep 17 00:00:00 2001 From: Olaf Wintermann Date: Sat, 7 Feb 2026 11:32:45 +0100 Subject: [PATCH] apply styles from previous char when inserting text --- application/editor.h | 8 ++-- application/gtk-text.c | 84 +++++++++++++++++++++++++++++++++++++++++- application/gtk-text.h | 4 ++ 3 files changed, 90 insertions(+), 6 deletions(-) diff --git a/application/editor.h b/application/editor.h index c2aba27..c8fca31 100644 --- a/application/editor.h +++ b/application/editor.h @@ -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 diff --git a/application/gtk-text.c b/application/gtk-text.c index 266d334..caa68ec 100644 --- a/application/gtk-text.c +++ b/application/gtk-text.c @@ -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; } diff --git a/application/gtk-text.h b/application/gtk-text.h index 503c633..c62b8c8 100644 --- a/application/gtk-text.h +++ b/application/gtk-text.h @@ -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 { -- 2.47.3