aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2019-12-26 20:31:35 +0100
committerThomas White <taw@bitwiz.me.uk>2020-01-04 22:32:14 +0100
commitc6d6e0b4a175b39151fec94daeaf8922a7b27eac (patch)
treeeae4705920a4d2383a38bdd84df3316c2c36afdb
parent718314e8b9301f826f35a05fcd9567572bd62b54 (diff)
Cut/copy in text format
-rw-r--r--libstorycode/gtk/gtknarrativeview.c86
-rw-r--r--libstorycode/narrative.c87
-rw-r--r--libstorycode/narrative.h3
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; r<n->items[i].n_runs; r++ ) {
+
+ size_t run_text_len, len_to_add, start_run_offs;
+
+ /* Is this run within the range? */
+ if ( (i==p1) && (r<r1) ) continue;
+ if ( (i==p2) && (r>r2) ) 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 */