]> uap-core.de Git - note.git/commitdiff
add editor_get_markdown for converting a GtkTextBuffer to markdown, implement heading...
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Mon, 10 Mar 2025 21:22:41 +0000 (22:22 +0100)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Mon, 10 Mar 2025 21:22:41 +0000 (22:22 +0100)
application/application.c
application/editor.h
application/gtk-text.c
application/gtk-text.h
application/note.c

index 16e53d65cd8ae0838150cab915e74a624f862611..6e5f4418b115608b1c856b1940f73498b7d93c91 100644 (file)
@@ -31,6 +31,7 @@
 #include "store.h"
 #include "menu.h"
 #include "notebook.h"
+#include "editor.h"
 
 #include <unistd.h>
 #include <limits.h>
@@ -40,6 +41,8 @@
 void application_init() {
     menu_init();
     toolbar_init();
+    
+    editor_global_init();
 }
 
 void application_startup(UiEvent *event, void *data) {
index 246ba1b9205e0af1580cb4ff3b5732342412d593..a026be76d0f74e8071b338e5a002bb7d88d6854a 100644 (file)
@@ -107,9 +107,11 @@ MDDocLinear mddoc_linearization(MDDoc *doc);
     
 // platform specific implementation
 // (gtk-text.c)
+void editor_global_init();
 void editor_init_textview(UIWIDGET textview);
 void editor_init_textbuf(UiText *text);
 void editor_apply_styles(UiText *text, CxList /* MDDocStyleSection */ *styles);
+cxmutstr editor_get_markdown(UiText *text, const CxAllocator *a);
 
 #ifdef __cplusplus
 }
index 9d9aa9daa6b86b3b15a989a48ab2480ef5291b4c..688f14a6e9d02bb5626cd92baae469064b0ae144 100644 (file)
 #include "gtk-text.h"
 #include "editor.h"
 
+#include <cx/buffer.h>
+#include <cx/hash_map.h>
+
+static CxMap *markdown_tags;
+
+void editor_global_init() {
+    markdown_tags = cxHashMapCreateSimple(sizeof(MDTag));
+    
+    cxMapPut(markdown_tags, EDITOR_STYLE_PARAGRAPH, &((MDTag){NULL, NULL}));
+    cxMapPut(markdown_tags, EDITOR_STYLE_HEADING1, &((MDTag){"# ", NULL}));
+    cxMapPut(markdown_tags, EDITOR_STYLE_HEADING2, &((MDTag){"## ", NULL}));
+    cxMapPut(markdown_tags, EDITOR_STYLE_HEADING3, &((MDTag){"### ", NULL}));
+    cxMapPut(markdown_tags, EDITOR_STYLE_HEADING4, &((MDTag){"#### ", NULL}));
+    cxMapPut(markdown_tags, EDITOR_STYLE_HEADING5, &((MDTag){"##### ", NULL}));
+    cxMapPut(markdown_tags, EDITOR_STYLE_HEADING6, &((MDTag){"###### ", NULL}));
+    cxMapPut(markdown_tags, EDITOR_STYLE_STRONG, &((MDTag){"**", "**"}));
+}
+
+
 void editor_init_textview(UIWIDGET textview) {
     gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(textview), GTK_WRAP_WORD_CHAR);
     
@@ -119,3 +138,108 @@ void editor_apply_styles(UiText *text, CxList /* MDDocStyleSection */ *styles) {
         }
     }
 }
+
+
+static CxMap* tags2map(GSList *tags) {
+    CxMap *map = cxHashMapCreateSimple(CX_STORE_POINTERS);
+    while(tags) {
+        GtkTextTag *t = tags->data;
+        GValue name_value = G_VALUE_INIT;
+        g_object_get_property(G_OBJECT(t), "name", &name_value);
+        const char *name = g_value_get_string(&name_value);
+        if(name) {
+            cxMapPut(map, name, t);
+        }
+        tags = tags->next;
+    }
+    return map;
+}
+
+static CxMap* map_clone(CxMap *map) {
+    CxMap *newmap = cxHashMapCreateSimple(CX_STORE_POINTERS);
+    CxMapIterator i = cxMapIterator(map);
+    cx_foreach(CxMapEntry *, entry, i) {
+        cxMapPut(newmap, *entry->key, entry->value);
+    }
+    return newmap;
+}
+
+static void map_subtract(CxMap *map, CxMap *sub) {
+    CxMapIterator i = cxMapIterator(sub);
+    cx_foreach(CxMapEntry *, entry, i) {
+        cxMapRemove(map, *entry->key);
+    }
+}
+
+cxmutstr editor_get_markdown(UiText *text, const CxAllocator *a) {
+    char *str = ui_get(text);
+    
+    
+    CxBuffer out;
+    cxBufferInit(&out, NULL, 1024, a, CX_BUFFER_AUTO_EXTEND);
+    
+    GtkTextBuffer *buffer = text->data1;
+    
+    CxMap *prev_tags = cxHashMapCreateSimple(CX_STORE_POINTERS);
+    
+    GtkTextIter start;
+    GtkTextIter iter;
+    gtk_text_buffer_get_iter_at_offset(buffer, &iter, 0);
+    start = iter;
+    while(gtk_text_iter_forward_to_tag_toggle(&iter, NULL)) {
+        gchar *text = gtk_text_buffer_get_text(buffer, &start, &iter, TRUE);
+        
+        GSList *tags = gtk_text_iter_get_tags(&start);
+        CxMap *begin_tags = tags2map(tags);
+        g_slist_free(tags);
+        
+        // subtract prev_tags from begin_tags to get a map of all new tags
+        CxMap *new_tags = map_clone(begin_tags);
+        CxMap *begin_tags2 = map_clone(begin_tags);
+        map_subtract(new_tags, prev_tags);
+        cxMapFree(prev_tags);
+        prev_tags = begin_tags;
+        
+        // check all new tags and add tag prefix code
+        CxMapIterator i = cxMapIterator(new_tags);
+        cx_foreach(CxMapEntry *, entry, i) {
+            MDTag *t = cxMapGet(markdown_tags, *entry->key);
+            if(t && t->begin) {
+                cxBufferPutString(&out, t->begin);
+            }
+        }
+        cxMapFree(new_tags);
+        
+        // add content
+        printf("range: {%s}\n\n", text);
+        cxBufferPutString(&out, text);
+        
+        // get all tags that ended here
+        tags = gtk_text_iter_get_tags(&iter);
+        CxMap *end_tags = tags2map(tags);
+        g_slist_free(tags);
+        
+        // check end tags and add tag suffix
+        map_subtract(begin_tags2, end_tags);
+        i = cxMapIterator(begin_tags2);
+        cx_foreach(CxMapEntry *, entry, i) {
+            MDTag *t = cxMapGet(markdown_tags, *entry->key);
+            if(t && t->end) {
+                cxBufferPutString(&out, t->end);
+            }
+        }
+        cxMapFree(begin_tags2);
+        cxMapFree(end_tags);
+        
+        g_free(text);
+        start = iter;
+    }
+    
+    
+    cxBufferTerminate(&out);
+    
+    printf("new markdown doc: \n\n%s\n\n", out.space);
+    
+    cxmutstr ret = cx_mutstrn(out.space, out.size);
+    return ret;
+}
index 55591b345309e7965d559144bb53df2f65f2c74c..f09d4db0e63faf26438eca9399a791b8882f0474 100644 (file)
 #ifdef __cplusplus
 extern "C" {
 #endif
+    
+typedef struct MDTag {
+    const char *begin;
+    const char *end;
+} MDTag;
 
 void init_textbuf(GtkTextBuffer *buf);
 void init_tagtable(GtkTextTagTable *table);
index e571e30f48c221f4ff481e484ccf73211dca42da..165c77a76b5f5a593ee4e28d6cad694b7acbbf8a 100644 (file)
@@ -93,7 +93,6 @@ void note_save(UiObject *obj, NotebookModel *notebook, Note *note) {
     NoteModel *m = note->model;
     
     char *title = ui_get(m->title);
-    char *content = ui_get(m->text);
     const CxAllocator *a = notebook->current_notes_pool->allocator;
     
     cxFree(a, note->title);
@@ -102,8 +101,9 @@ void note_save(UiObject *obj, NotebookModel *notebook, Note *note) {
     cxFree(a, note->name);
     note->name = cx_strdup_a(a, cx_str(title)).ptr;
     
+    cxmutstr content = editor_get_markdown(m->text, a);
     cxFree(a, note->content.ptr);
-    note->content = cx_strdup_a(a, cx_str(content));
+    note->content = content;
     
     if(note->note_id == 0) {
         // new note