GtkTextIter begin = *location;
GtkTextIter end = begin;
+ int insert_offset = gtk_text_iter_get_offset(location) - len;
+
if(!gtk_text_iter_backward_chars(&begin, len)) {
return; // should not happen
}
+ cxstring ins_text = cx_strn(text, len);
+
+ cxstring lines[64];
+ size_t nlines = cx_strsplit(ins_text, "\n", 64, lines);
+
+ int list_depth = 0;
+ int list_style = 0;
+ int list_num = 0;
+ if(nlines > 1) {
+ // Inserted text contains at least one linebreak
+ // Check if the current line contains a list
+ GtkTextIter prev_line = begin;
+ if(gtk_text_iter_backward_line(&prev_line)) {
+ GtkTextChildAnchor *anchor = NULL;
+ GtkTextChildAnchor *prevAnchor = NULL;
+ int end_offset = gtk_text_iter_get_offset(&begin);
+ // iterate over chars in line and check for anchors
+ while(gtk_text_iter_get_offset(&prev_line) < end_offset) {
+ if(!gtk_text_iter_forward_to_tag_toggle(&prev_line, NULL)) {
+ prev_line = begin;
+ }
+
+ anchor = gtk_text_iter_get_child_anchor(&prev_line);
+ if(anchor && anchor != prevAnchor) {
+ EmbeddedWidget *em = g_object_get_data(G_OBJECT(anchor), "em");
+ if(em) {
+ if(em->type == EMBEDDED_WIDGET_LIST) {
+ list_style = em->intdata1;
+ list_num = em->intdata2;
+ list_depth++;
+ } else if(em->type == EMBEDDED_WIDGET_LIST_INDENT) {
+ list_depth++;
+ } // else: other type of embedded widget (image, ...)
+ }
+ }
+ prevAnchor = anchor;
+ }
+ }
+ }
+
GtkTextIter prev = begin;
if(gtk_text_iter_backward_char(&prev)) {
// a previous position exists, apply tags from it
}
g_slist_free(tags);
}
+
+ if(list_depth > 0) {
+ // Insert list elements for all inserted lines
+ // The first line is skipped, because the text will be part of the current list line
+ const char *style_name = list_style == 1 ? EDITOR_STYLE_LIST0 : EDITOR_STYLE_ORDLIST0;
+ for(int i=nlines-1;i>0;i--) {
+ intptr_t line_off = (intptr_t)(lines[i].ptr - text);
+ GtkTextIter iter;
+ gtk_text_buffer_get_iter_at_offset(buffer, &iter, insert_offset + line_off);
+ editor_insert_list_element(editor, &iter, style_name, list_num+i+1);
+ }
+ }
}
static gboolean path_is_image_file(cxstring path) {
gtk_widget_show_all(image);
#endif
+ em->type = EMBEDDED_WIDGET_IMAGE;
em->widget = image;
em->anchor = anchor;
em->data1 = attachment;
int height = pango_font_metrics_get_height(metrics) / PANGO_SCALE;
ListElmWidget *elm = malloc(sizeof(ListElmWidget));
+ int liststyle = 0;
if(!strcmp(style, EDITOR_STYLE_LIST0)) {
elm->str = strdup("•");
+ liststyle = 1;
+ num = 0;
} else {
char buf[32];
snprintf(buf, 32, "%d.", num+1);
#if GTK_MAJOR_VERSION < 4
gtk_widget_show_all(widget);
#endif
+ em->type = EMBEDDED_WIDGET_LIST;
em->widget = widget;
em->anchor = anchor;
em->serialize = md_serialize_list;
+ em->intdata1 = liststyle;
+ em->intdata2 = num;
g_object_ref(widget);
g_object_ref(anchor);
CxList *objects;
} BufferEmbeddedObjects;
+enum EmbeddedWidgetType {
+ EMBEDDED_WIDGET_IMAGE = 0,
+ EMBEDDED_WIDGET_LIST,
+ EMBEDDED_WIDGET_LIST_INDENT
+};
+
+typedef enum EmbeddedWidgetType EmbeddedWidgetType;
+
typedef struct EmbeddedWidget EmbeddedWidget;
struct EmbeddedWidget {
GtkWidget *widget;
GtkTextChildAnchor *anchor;
+ EmbeddedWidgetType type;
int width;
int height;
void (*adjust_size)(EmbeddedWidget *em, int max_width);
void *wdata1; // wdata1/wdata2 filled by widget constructor
void *wdata2; // and used by adjust_size
void (*serialize)(EmbeddedWidget *e, CxBuffer *out);
+ int intdata1;
+ int intdata2;
};
typedef struct ListElmWidget {