aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.me.uk>2019-03-23 22:44:02 +0100
committerThomas White <taw@bitwiz.me.uk>2019-03-23 22:44:02 +0100
commitf5fd7623a14dd51a59657cbab4d5953b1b2e48ff (patch)
tree6581009219c46a2aefc44bcfa0fe284fe6ecb08b
parent91eeae07bd6a4d4db2ec81c4237819c73d79b0de (diff)
Implement slide text deletion
-rw-r--r--libstorycode/gtk/gtkslideview.c74
-rw-r--r--libstorycode/slide.c64
-rw-r--r--libstorycode/slide.h1
-rw-r--r--libstorycode/slide_render_cairo.h3
4 files changed, 134 insertions, 8 deletions
diff --git a/libstorycode/gtk/gtkslideview.c b/libstorycode/gtk/gtkslideview.c
index f60ccec..f80d1b5 100644
--- a/libstorycode/gtk/gtkslideview.c
+++ b/libstorycode/gtk/gtkslideview.c
@@ -572,7 +572,13 @@ static void unset_selection(GtkSlideView *e)
a = e->sel_end.para;
b = e->sel_start.para;
}
- //rewrap_paragraph_range(e->cursor_frame, a, b, e->sel_start, e->sel_end, 0);
+
+ e->sel_start.para = 0;
+ e->sel_start.pos = 0;
+ e->sel_start.trail = 0;
+ e->sel_end.para = 0;
+ e->sel_end.pos = 0;
+ e->sel_end.trail = 0;
}
@@ -694,9 +700,9 @@ static gboolean button_press_sig(GtkWidget *da, GdkEventButton *event,
} else {
e->drag_status = DRAG_STATUS_COULD_DRAG;
e->drag_reason = DRAG_REASON_TEXTSEL;
- unset_selection(e);
find_cursor(clicked, stylesheet, x-frx, y-fry,
&e->sel_start, slide_w, slide_h);
+ e->sel_end = e->sel_start;
}
}
@@ -882,7 +888,7 @@ static gboolean button_release_sig(GtkWidget *da, GdkEventButton *event,
static size_t end_offset_of_para(SlideItem *item, int pnum)
{
assert(pnum >= 0);
- if ( is_text(item->type) ) return 0;
+ if ( !is_text(item->type) ) return 0;
return strlen(item->paras[pnum].text);
}
@@ -893,6 +899,7 @@ static void cursor_moveh(GtkSlideView *e, struct slide_pos *cp, signed int dir)
if ( !is_text(e->cursor_frame->type) ) return;
if ( e->cursor_frame->paras[e->cpos.para].layout == NULL ) return;
+ unset_selection(e);
pango_layout_move_cursor_visually(e->cursor_frame->paras[e->cpos.para].layout,
1, cp->pos, cp->trail, dir,
@@ -944,6 +951,60 @@ static int slide_positions_equal(struct slide_pos a, struct slide_pos b)
}
+static void sort_slide_positions(struct slide_pos *a, struct slide_pos *b)
+{
+ if ( a->para > b->para ) {
+ size_t tpos;
+ int tpara, ttrail;
+ tpara = b->para; tpos = b->pos; ttrail = b->trail;
+ b->para = a->para; b->pos = a->pos; b->trail = a->trail;
+ a->para = tpara; a->pos = tpos; a->trail = ttrail;
+ }
+
+ if ( (a->para == b->para) && (a->pos > b->pos) )
+ {
+ size_t tpos = b->pos;
+ int ttrail = b->trail;
+ b->pos = a->pos; b->trail = a->trail;
+ a->pos = tpos; a->trail = ttrail;
+ }
+}
+
+
+static void do_backspace(GtkSlideView *e, signed int dir)
+{
+ struct slide_pos p1, p2;
+ size_t o1, o2;
+
+ if ( !slide_positions_equal(e->sel_start, e->sel_end) ) {
+
+ /* Block delete */
+ p1 = e->sel_start;
+ p2 = e->sel_end;
+
+ } else {
+
+ /* Delete one character, as represented visually */
+ p2 = e->cpos;
+ p1 = p2;
+ cursor_moveh(e, &p1, dir);
+ }
+
+ sort_slide_positions(&p1, &p2);
+ o1 = pos_trail_to_offset(e->cursor_frame, p1.para, p1.pos, p1.trail);
+ o2 = pos_trail_to_offset(e->cursor_frame, p2.para, p2.pos, p2.trail);
+ slide_item_delete_text(e->cursor_frame, p1.para, o1, p2.para, o2);
+ e->cpos = p1;
+ unset_selection(e);
+
+ pango_layout_set_text(e->cursor_frame->paras[e->cpos.para].layout,
+ e->cursor_frame->paras[e->cpos.para].text, -1);
+
+ emit_change_sig(e);
+ redraw(e);
+}
+
+
static void insert_text_in_paragraph(SlideItem *item, int para,
size_t offs, char *t)
{
@@ -966,8 +1027,9 @@ static void insert_text(char *t, GtkSlideView *e)
if ( !is_text(e->cursor_frame->type) ) return;
if ( !slide_positions_equal(e->sel_start, e->sel_end) ) {
- //do_backspace(e, 0);
+ do_backspace(e, 0);
}
+ unset_selection(e);
if ( strcmp(t, "\n") == 0 ) {
off = pos_trail_to_offset(e->cursor_frame, e->cpos.para,
@@ -1043,12 +1105,12 @@ static gboolean key_press_sig(GtkWidget *da, GdkEventKey *event,
break;
case GDK_KEY_BackSpace :
- //do_backspace(e, -1);
+ do_backspace(e, -1);
claim = 1;
break;
case GDK_KEY_Delete :
- //do_backspace(e, +1);
+ do_backspace(e, +1);
claim = 1;
break;
diff --git a/libstorycode/slide.c b/libstorycode/slide.c
index cb2a5a1..a3dfcc7 100644
--- a/libstorycode/slide.c
+++ b/libstorycode/slide.c
@@ -28,6 +28,11 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
+#include <assert.h>
+
+#ifdef HAVE_PANGO
+#include <pango/pangocairo.h>
+#endif
#include "slide.h"
#include "slide_priv.h"
@@ -326,3 +331,62 @@ void slide_item_split_text_paragraph(SlideItem *item, int para, size_t off)
item->paras[para+1].layout = NULL;
item->paras[para].text[off] = '\0';
}
+
+
+static void delete_paragraph(SlideItem *item, int del)
+{
+ int i;
+
+#ifdef HAVE_PANGO
+ g_object_unref(item->paras[del].layout);
+#endif
+ free(item->paras[del].text);
+
+ for ( i=del; i<item->n_paras-1; i++ ) {
+ item->paras[i] = item->paras[i+1];
+ }
+ item->n_paras--;
+}
+
+
+void slide_item_delete_text(SlideItem *item, int i1, size_t o1, int i2, size_t o2)
+{
+ int i;
+ int n_del = 0;
+
+ /* Starting item */
+ if ( i1 == i2 ) {
+ memmove(&item->paras[i1].text[o1],
+ &item->paras[i1].text[o2],
+ strlen(item->paras[i1].text)-o2+1);
+ return; /* easy case */
+ } else {
+ item->paras[i1].text[o1] = '\0';
+ }
+
+ /* Middle items */
+ for ( i=i1+1; i<i2; i++ ) {
+ /* Deleting the item moves all the subsequent items up, so the
+ * index to be deleted doesn't change. */
+ delete_paragraph(item, i1+1);
+ n_del++;
+ }
+ i2 -= n_del;
+
+ /* Last item */
+ memmove(&item->paras[i2].text[0],
+ &item->paras[i2].text[o2],
+ strlen(&item->paras[i2].text[o2])+1);
+
+ assert(i1 != i2);
+ char *new_text;
+ size_t len = strlen(item->paras[i1].text);
+ len += strlen(item->paras[i2].text);
+ new_text = malloc(len+1);
+ if ( new_text == NULL ) return;
+ strcpy(new_text, item->paras[i1].text);
+ strcat(new_text, item->paras[i2].text);
+ free(item->paras[i1].text);
+ item->paras[i1].text = new_text;
+ delete_paragraph(item, i2);
+}
diff --git a/libstorycode/slide.h b/libstorycode/slide.h
index ab014d5..9d114fb 100644
--- a/libstorycode/slide.h
+++ b/libstorycode/slide.h
@@ -55,6 +55,7 @@ extern void slide_item_get_padding(SlideItem *item, Stylesheet *ss,
double slide_w, double slide_h);
extern void slide_item_split_text_paragraph(SlideItem *item, int para, size_t off);
+extern void slide_item_delete_text(SlideItem *item, int p1, size_t o1, int p2, size_t o2);
/* For debugging, not really part of API */
extern void describe_slide(Slide *s);
diff --git a/libstorycode/slide_render_cairo.h b/libstorycode/slide_render_cairo.h
index 39c0f59..52bf43f 100644
--- a/libstorycode/slide_render_cairo.h
+++ b/libstorycode/slide_render_cairo.h
@@ -38,7 +38,6 @@ struct slide_pos
};
extern int slide_render_cairo(Slide *s, cairo_t *cr, ImageStore *is, Stylesheet *stylesheet,
- int slide_number, PangoLanguage *lang,
- PangoContext *pc);
+ int slide_number, PangoLanguage *lang, PangoContext *pc);
#endif /* RENDER_H */