From c6d6e0b4a175b39151fec94daeaf8922a7b27eac Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 26 Dec 2019 20:31:35 +0100 Subject: Cut/copy in text format --- libstorycode/gtk/gtknarrativeview.c | 86 +++++++++++++++++++++++------------- libstorycode/narrative.c | 87 +++++++++++++++++++++++++++++++++++++ libstorycode/narrative.h | 3 ++ 3 files changed, 147 insertions(+), 29 deletions(-) diff --git a/libstorycode/gtk/gtknarrativeview.c b/libstorycode/gtk/gtknarrativeview.c index b26c86b..409b48b 100644 --- a/libstorycode/gtk/gtknarrativeview.c +++ b/libstorycode/gtk/gtknarrativeview.c @@ -409,15 +409,18 @@ void sc_editor_paste(GtkNarrativeView *e) static void clipboard_get(GtkClipboard *cb, GtkSelectionData *seldata, guint info, gpointer data) { - char *t = data; + char **clipboard_data = data; printf("clipboard get\n"); if ( info == 0 ) { - printf("sending SC frame\n"); - gtk_selection_data_set(seldata, - gtk_selection_data_get_target(seldata), - 8, (const guchar *)t, strlen(t)+1); + printf("sending text\n"); + gtk_selection_data_set_text(seldata, clipboard_data[0], -1); + + } else if ( info == 1 ) { + printf("sending SC\n"); + gtk_selection_data_set_text(seldata, clipboard_data[1], -1); + } else { GdkAtom target; gchar *name; @@ -431,35 +434,52 @@ static void clipboard_get(GtkClipboard *cb, GtkSelectionData *seldata, static void clipboard_clear(GtkClipboard *cb, gpointer data) { - free(data); + char **clipboard_data = data; + printf("freeing clipboard data\n"); + free(clipboard_data[0]); + free(clipboard_data[1]); + free(clipboard_data); } static void copy_selection(GtkNarrativeView *e) { -// char *t; -// GtkClipboard *cb; -// GdkAtom atom; -// GtkTargetEntry targets[1]; -// -// atom = gdk_atom_intern("CLIPBOARD", FALSE); -// if ( atom == GDK_NONE ) return; -// -// cb = gtk_clipboard_get(atom); -// -// targets[0].target = "text/x-storycode"; -// targets[0].flags = 0; -// targets[0].info = 0; -// -// printf("copying selection\n"); -// -// bl = block_at_cursor(e->cursor_frame, e->cpos.para, 0); -// if ( bl == NULL ) return; -// -// t = serialise_sc_block(bl); -// -// gtk_clipboard_set_with_data(cb, targets, 1, -// clipboard_get, clipboard_clear, t); + GtkClipboard *cb; + GtkTargetEntry targets[2]; + char **clipboard_data; + size_t start_offs, end_offs; + + clipboard_data = malloc(2*sizeof(char *)); + if ( clipboard_data == NULL ) return; + + cb = gtk_clipboard_get_default(gtk_widget_get_display(GTK_WIDGET(e))); + + start_offs = narrative_pos_trail_to_offset(e->n, e->sel_start.para, + e->sel_start.pos, e->sel_start.trail); + end_offs = narrative_pos_trail_to_offset(e->n, e->sel_end.para, + e->sel_end.pos, e->sel_end.trail); + + targets[0].target = "text/plain"; + targets[0].flags = 0; + targets[0].info = 0; + clipboard_data[0] = narrative_range_as_text(e->n, e->sel_start.para, start_offs, + e->sel_end.para, end_offs); + + targets[1].target = "text/x-storycode"; + targets[1].flags = 0; + targets[1].info = 1; + clipboard_data[1] = narrative_range_as_storycode(e->n, e->sel_start.para, start_offs, + e->sel_end.para, end_offs); + + /* Data is prepared for all the possible MIME types right now, not later + * when the data is represented. This avoids having to convert + * everything to a new, intermediate format, or saving a copy of the + * entire GtkNarrativeView's state (which might change before the data + * gets requested. + * Perhaps I missed something and there is an easier way. + */ + gtk_clipboard_set_with_data(cb, targets, 2, clipboard_get, clipboard_clear, + clipboard_data); } @@ -1120,6 +1140,14 @@ static gboolean gtknv_key_press_sig(GtkWidget *da, GdkEventKey *event, } break; + case GDK_KEY_X : + case GDK_KEY_x : + if ( event->state == GDK_CONTROL_MASK ) { + copy_selection(e); + gtknv_do_backspace(e, 0); + } + break; + case GDK_KEY_V : case GDK_KEY_v : if ( event->state == GDK_CONTROL_MASK ) { diff --git a/libstorycode/narrative.c b/libstorycode/narrative.c index 67fe9e9..5dc3f7f 100644 --- a/libstorycode/narrative.c +++ b/libstorycode/narrative.c @@ -589,6 +589,92 @@ Slide *narrative_get_slide_by_number(Narrative *n, int pos) } +/* Return the text between item p1/offset o1 and p2/o2 */ +char *narrative_range_as_storycode(Narrative *n, int p1, size_t o1, int p2, size_t o2) +{ + return strdup(": Text"); +} + + +/* Return the text between item p1/offset o1 and p2/o2 */ +char *narrative_range_as_text(Narrative *n, int p1, size_t o1, int p2, size_t o2) +{ + int i; + char *t; + int r1, r2; + size_t r1offs, r2offs; + size_t len = 0; + size_t size = 256; + + t = malloc(size); + if ( t == NULL ) return NULL; + t[0] = '\0'; + + r1 = narrative_which_run(&n->items[p1], o1, &r1offs); + r2 = narrative_which_run(&n->items[p2], o2, &r2offs); + + for ( i=p1; i<=p2; i++ ) { + + int r; + + /* Skip non-text runs straight away */ + if ( !narrative_item_is_text(n, i) ) continue; + + for ( r=0; ritems[i].n_runs; r++ ) { + + size_t run_text_len, len_to_add, start_run_offs; + + /* Is this run within the range? */ + if ( (i==p1) && (rr2) ) continue; + + run_text_len = strlen(n->items[i].runs[r].text); + + if ( (p1==p2) && (r1==r2) && (r==r1) ) { + start_run_offs = r1offs; + len_to_add = r2offs - r1offs; + } else if ( (i==p1) && (r==r1) ) { + start_run_offs = r1offs; + len_to_add = run_text_len - r1offs; + } else if ( (i==p2) && (r==r2) ) { + start_run_offs = 0; + len_to_add = r2offs; + } else { + start_run_offs = 0; + len_to_add = run_text_len; + } + + if ( len_to_add == 0 ) continue; + + /* Ensure space */ + if ( len + len_to_add + 2 > size ) { + char *nt; + size += 256 + len_to_add; + nt = realloc(t, size); + if ( nt == NULL ) { + fprintf(stderr, "Failed to allocate\n"); + return NULL; + } + t = nt; + } + + memcpy(&t[len], n->items[i].runs[r].text+start_run_offs, + len_to_add); + len += len_to_add; + t[len] = '\0'; + } + + if ( i < p2 ) { + t[len++] = '\n'; + t[len] = '\0'; + } + + } + + return t; +} + + static void debug_runs(struct narrative_item *item) { int j; @@ -597,6 +683,7 @@ static void debug_runs(struct narrative_item *item) } } + void narrative_debug(Narrative *n) { int i; diff --git a/libstorycode/narrative.h b/libstorycode/narrative.h index c5cb6f3..599318e 100644 --- a/libstorycode/narrative.h +++ b/libstorycode/narrative.h @@ -73,6 +73,9 @@ extern Slide *narrative_get_slide_by_number(Narrative *n, int pos); extern int narrative_get_slide_number_for_para(Narrative *n, int para); extern int narrative_get_slide_number_for_slide(Narrative *n, Slide *s); +extern char *narrative_range_as_text(Narrative *n, int p1, size_t o1, int p2, size_t o2); +extern char *narrative_range_as_storycode(Narrative *n, int p1, size_t o1, int p2, size_t o2); + extern void narrative_debug(Narrative *n); #endif /* NARRATIVE_H */ -- cgit v1.2.3