aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.org.uk>2016-09-21 14:33:50 +0200
committerThomas White <taw@bitwiz.org.uk>2016-09-21 14:33:50 +0200
commit6c5b9480352251c2d221eb7997fdd6dd358d7366 (patch)
treee380032f80e5696d320b9ea6196dfe08a38946bf
parent8ebf692bcd8ef5f949afb01e777e58ee607533c4 (diff)
Fix abuse of cursor_trail
cursor_pos is a byte offset, but cursor_trail is a number of characters. Therefore, adding them together is always wrong. This fixes problems when inserting multi-byte characters.
-rw-r--r--src/frame.c19
-rw-r--r--src/frame.h2
-rw-r--r--src/sc_editor.c43
3 files changed, 51 insertions, 13 deletions
diff --git a/src/frame.c b/src/frame.c
index 11c6d8f..5c20437 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -764,6 +764,25 @@ static int which_run(Paragraph *para, size_t offs)
}
+size_t pos_trail_to_offset(Paragraph *para, size_t offs, int trail)
+{
+ glong char_offs;
+ const char *run_text;
+ struct text_run *run;
+ int nrun;
+ char *ptr;
+
+ nrun = which_run(para, offs);
+ run= &para->runs[nrun];
+ run_text = sc_block_contents(run->scblock) + run->scblock_offs_bytes;
+ char_offs = g_utf8_pointer_to_offset(run_text, run_text+offs);
+ char_offs += trail;
+
+ ptr = g_utf8_offset_to_pointer(run_text, char_offs);
+ return ptr - run_text;
+}
+
+
void insert_text_in_paragraph(Paragraph *para, size_t offs, const char *t)
{
int nrun;
diff --git a/src/frame.h b/src/frame.h
index bf09e52..7f9c920 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -156,6 +156,8 @@ extern void cursor_movev(struct frame *fr, int *cpara, size_t *cpos, int *ctrail
extern void check_callback_click(struct frame *fr, int para);
+extern size_t pos_trail_to_offset(Paragraph *para, size_t offs, int trail);
+
extern void insert_text_in_paragraph(Paragraph *para, size_t offs,
const char *t);
diff --git a/src/sc_editor.c b/src/sc_editor.c
index 4b4a601..5aeb003 100644
--- a/src/sc_editor.c
+++ b/src/sc_editor.c
@@ -593,17 +593,24 @@ static gboolean draw_sig(GtkWidget *da, cairo_t *cr, SCEditor *e)
SCBlock *split_paragraph_at_cursor(SCEditor *e)
{
- return split_paragraph(e->cursor_frame, e->cursor_para,
- e->cursor_pos+e->cursor_trail, e->pc);
+ size_t offs;
+ Paragraph *para;
+
+ para = e->cursor_frame->paras[e->cursor_para];
+ offs = pos_trail_to_offset(para, e->cursor_pos, e->cursor_trail);
+ return split_paragraph(e->cursor_frame, e->cursor_para, offs, e->pc);
}
static void check_cursor_visible(SCEditor *e)
{
double x, y, h;
+ size_t offs;
+ Paragraph *para;
- get_cursor_pos(e->cursor_frame, e->cursor_para,
- e->cursor_pos+e->cursor_trail, &x, &y, &h);
+ para = e->cursor_frame->paras[e->cursor_para];
+ offs = pos_trail_to_offset(para, e->cursor_pos, e->cursor_trail);
+ get_cursor_pos(e->cursor_frame, e->cursor_para, offs, &x, &y, &h);
/* Off the bottom? */
if ( y - e->scroll_pos + h > e->visible_height ) {
@@ -637,14 +644,16 @@ static void insert_text(char *t, SCEditor *e)
/* Is this paragraph even a text one? */
if ( para_type(para) == PARA_TYPE_TEXT ) {
+ size_t off;
/* Yes. The "easy" case */
- insert_text_in_paragraph(para, e->cursor_pos+e->cursor_trail,
- t);
+ off = pos_trail_to_offset(para, e->cursor_pos, e->cursor_trail);
+ insert_text_in_paragraph(para, off, t);
wrap_paragraph(para, NULL,
e->cursor_frame->w - e->cursor_frame->pad_l
- e->cursor_frame->pad_r);
if ( e->flow ) update_size(e);
+
cursor_moveh(e->cursor_frame, &e->cursor_para,
&e->cursor_pos, &e->cursor_trail, +1);
@@ -702,9 +711,15 @@ static void do_backspace(struct frame *fr, SCEditor *e)
wrap_paragraph(e->cursor_frame->paras[new_para], NULL, wrapw);
} else {
- delete_text_in_paragraph(para, e->cursor_pos+e->cursor_trail,
- old_pos+old_trail);
+ size_t offs_new, offs_old;
+
+ offs_new = pos_trail_to_offset(para, e->cursor_pos,
+ e->cursor_trail);
+ offs_old = pos_trail_to_offset(para, old_pos, old_trail);
+
+ delete_text_in_paragraph(para, offs_new, offs_old);
wrap_paragraph(para, NULL, wrapw);
+
}
@@ -1213,8 +1228,7 @@ static void copy_selection(SCEditor *e)
char *storycode;
SCBlock *bl;
- bl = block_at_cursor(e->cursor_frame, e->cursor_para,
- e->cursor_pos+e->cursor_trail);
+ bl = block_at_cursor(e->cursor_frame, e->cursor_para, 0);
if ( bl == NULL ) return;
storycode = serialise_sc_block(bl);
@@ -1231,10 +1245,13 @@ static void paste_callback(GtkClipboard *cb, const gchar *text, void *vp)
SCBlock *bl = sc_parse(text);
SCBlock *cur_bl;
size_t cur_sc_pos;
+ size_t offs;
+ Paragraph *para;
+
+ para = e->cursor_frame->paras[e->cursor_para];
+ offs = pos_trail_to_offset(para, e->cursor_pos, e->cursor_trail);
- get_sc_pos(e->cursor_frame, e->cursor_para,
- e->cursor_pos+e->cursor_trail,
- &cur_bl, &cur_sc_pos);
+ get_sc_pos(e->cursor_frame, e->cursor_para, offs, &cur_bl, &cur_sc_pos);
sc_insert_block(cur_bl, cur_sc_pos, bl);
full_rerender(e);
}