aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.me.uk>2019-03-10 10:58:20 +0100
committerThomas White <taw@bitwiz.me.uk>2019-03-10 10:58:20 +0100
commit528d0c29049546e130ab61dcc3f67d0ebc9a38cc (patch)
tree507032021e55ecf0b591a0e7f343233298863897
parent22f935dc19ff670e8168059663676d432bcaeef2 (diff)
Implement paragraph merge and forwards delete
-rw-r--r--libstorycode/gtk/gtknarrativeview.c45
-rw-r--r--libstorycode/narrative.c22
2 files changed, 43 insertions, 24 deletions
diff --git a/libstorycode/gtk/gtknarrativeview.c b/libstorycode/gtk/gtknarrativeview.c
index 47ee43c..bf0d22c 100644
--- a/libstorycode/gtk/gtknarrativeview.c
+++ b/libstorycode/gtk/gtknarrativeview.c
@@ -722,47 +722,39 @@ static void cursor_moveh(Narrative *n, struct edit_pos *cp, signed int dir)
}
-static void do_backspace(GtkNarrativeView *e)
+static void do_backspace(GtkNarrativeView *e, signed int dir)
{
Narrative *n;
+ struct edit_pos p1, p2;
size_t o1, o2;
n = presentation_get_narrative(e->p);
if ( e->sel_active ) {
- /* Delete the selected block */
- sort_positions(&e->sel_start, &e->sel_end);
- o1 = pos_trail_to_offset(&n->items[e->sel_start.para],
- e->sel_start.pos, e->sel_start.trail);
- o2 = pos_trail_to_offset(&n->items[e->sel_end.para],
- e->sel_end.pos, e->sel_end.trail);
- narrative_delete_block(n, e->sel_start.para, o1,
- e->sel_end.para, o2);
-
- /* Cursor goes at start of deletion */
- e->cpos = e->sel_start;
- e->sel_active = 0;
+ /* Block delete */
+ p1 = e->sel_start;
+ p2 = e->sel_end;
} else {
- struct edit_pos p1, p2;
-
/* Delete one character, as represented visually */
p2 = e->cpos;
p1 = p2;
- cursor_moveh(n, &p1, -1);
- o1 = pos_trail_to_offset(&n->items[p1.para], p1.pos, p1.trail);
- o2 = pos_trail_to_offset(&n->items[p2.para], p2.pos, p2.trail);
- narrative_delete_block(n, p1.para, o1, p2.para, o2);
- e->cpos = p1;
-
+ cursor_moveh(n, &p1, dir);
}
+ sort_positions(&p1, &p2);
+ o1 = pos_trail_to_offset(&n->items[p1.para], p1.pos, p1.trail);
+ o2 = pos_trail_to_offset(&n->items[p2.para], p2.pos, p2.trail);
+ narrative_delete_block(n, p1.para, o1, p2.para, o2);
+ e->cpos = p1;
+ e->sel_active = 0;
+
/* The only paragraphs which still exist and might have been
* affected by the deletion are sel_start.para and the one
* immediately afterwards. */
- rewrap_range(e, e->sel_start.para, e->sel_start.para+1);
+ rewrap_range(e, p1.para, p1.para+1);
update_size(e);
emit_change_sig(e);
redraw(e);
@@ -789,7 +781,7 @@ static void insert_text(char *t, GtkNarrativeView *e)
struct narrative_item *item;
if ( e->sel_active ) {
- do_backspace(e);
+ do_backspace(e, 0);
}
item = get_current_item(e, &n);
@@ -967,7 +959,12 @@ static gboolean key_press_sig(GtkWidget *da, GdkEventKey *event,
break;
case GDK_KEY_BackSpace :
- do_backspace(e);
+ do_backspace(e, -1);
+ claim = 1;
+ break;
+
+ case GDK_KEY_Delete :
+ do_backspace(e, +1);
claim = 1;
break;
diff --git a/libstorycode/narrative.c b/libstorycode/narrative.c
index 8cb54c3..f32e8f0 100644
--- a/libstorycode/narrative.c
+++ b/libstorycode/narrative.c
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include <string.h>
+#include <assert.h>
#include "narrative.h"
#include "narrative_priv.h"
@@ -155,12 +156,14 @@ static void delete_item(Narrative *n, int del)
void narrative_delete_block(Narrative *n, int i1, size_t o1, int i2, size_t o2)
{
int i;
+ int merge = 1;
/* Starting item */
if ( n->items[i1].type == NARRATIVE_ITEM_SLIDE ) {
delete_item(n, i1);
i1--;
i2--;
+ merge = 0;
} else {
if ( i1 == i2 ) {
memmove(&n->items[i1].text[o1],
@@ -181,8 +184,27 @@ void narrative_delete_block(Narrative *n, int i1, size_t o1, int i2, size_t o2)
/* Last item */
if ( n->items[i2].type == NARRATIVE_ITEM_SLIDE ) {
delete_item(n, i2);
+ merge = 0;
} else {
memmove(&n->items[i2].text[0],
&n->items[i2].text[o2], o2);
}
+
+ /* If the start and end points are in different paragraphs, and both
+ * of them are text (any kind), merge them. Note that at this point,
+ * we know that i1 and i2 are different because otherwise we would've
+ * returned earlier ("easy case"). */
+ assert(i1 != i2);
+ if ( merge ) {
+ char *new_text;
+ size_t len = strlen(n->items[i1].text);
+ len += strlen(n->items[i2].text);
+ new_text = malloc(len+1);
+ if ( new_text == NULL ) return;
+ strcpy(new_text, n->items[i1].text);
+ strcat(new_text, n->items[i2].text);
+ free(n->items[i1].text);
+ n->items[i1].text = new_text;
+ delete_item(n, i2);
+ }
}